Click here to Skip to main content
13,801,468 members
Click here to Skip to main content
Add your own
alternative version


32 bookmarked
Posted 13 May 2007

Launch your app into session 1 using a service helper application written in C#

, 13 May 2007
Rate this:
Please Sign up or sign in to vote.
Launch your application into session 1 using a service in session 0 (C#) under the local system account


This is the same article which I have written earlier in Native C++ code. (Launch your application from session 0 to session 1 in Vista using a service helper application at VistaSessions.asp)

Luzius Kalt mailed me a C# version of the service which would work well for those who wanted the code on the .NET platform.

Since I got many requests to post the article in .NET, I am posting the code I received from Luzius.

To acknowledge his efforts, I am posting this as a separate article.

Using the code

The heart of the application logic is the service. This is what launches the helper application into session 1.

Hence only the service has been rewritten in C#.

The code rewritten in C# uses PINVOKE to execute native API's.

The application Custom message sender which sends the message to the service to launch the application as well as the code which will access HKCU in the registry (refer to my article VistaSessions.asp) is still in native code.

I will update that too soon.

The following structures and API's from Win32 have been declared in C#

// Structure for the CreateProcessAsuser API
        public struct SECURITY_ATTRIBUTES
            public int Length;
            public IntPtr lpSecurityDescriptor;
            public bool bInheritHandle;
//Structure for the DuplicateTokenEx API
        enum TOKEN_TYPE : int
            TokenPrimary = 1,
            TokenImpersonation = 2
//Structure for the SetTokenInformation API
        public enum TOKEN_INFORMATION_CLASS : int
            TokenUser = 1,
        // MaxTokenInfoClass should always be the last enum
//Structure for CreateProcess API
        public struct STARTUPINFO
            public int cb;
            public String lpReserved;
            public String lpDesktop;
            public String lpTitle;
            public uint dwX;
            public uint dwY;
            public uint dwXSize;
            public uint dwYSize;
            public uint dwXCountChars;
            public uint dwYCountChars;
            public uint dwFillAttribute;
            public uint dwFlags;
            public short wShowWindow;
            public short cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
//Structure for CreateProcess API
        public struct PROCESS_INFORMATION
            public IntPtr hProcess;
            public IntPtr hThread;
            public uint dwProcessId;
            public uint dwThreadId;
//Structure for LookupPriveleges API
        internal struct LUID
            public int LowPart;
            public int HighPart;
        }//end struct
        internal struct LUID_AND_ATRIBUTES
            public LUID Luid;
            public int Attributes;
        }//end struct
//Structure for the AdjustTokenPrivileges API

        internal struct TOKEN_PRIVILEGES
            internal int PrivilegeCount;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
            internal int[] Privileges;

//Defined for Token rights

        public const int READ_CONTROL = 0x00020000;
        public const int STANDARD_RIGHTS_REQUIRED = 0x000F0000;
        public const int STANDARD_RIGHTS_READ = READ_CONTROL;
        public const int STANDARD_RIGHTS_WRITE = READ_CONTROL;
        public const int STANDARD_RIGHTS_EXECUTE = READ_CONTROL;
        public const int STANDARD_RIGHTS_ALL = 0x001F0000;
        public const int SPECIFIC_RIGHTS_ALL = 0x0000FFFF;
        public const int TOKEN_ASSIGN_PRIMARY = 0x0001;
        public const int TOKEN_DUPLICATE = 0x0002;
        public const int TOKEN_IMPERSONATE = 0x0004;
        public const int TOKEN_QUERY = 0x0008;
        public const int TOKEN_QUERY_SOURCE = 0x0010;
        public const int TOKEN_ADJUST_PRIVILEGES = 0x0020;
        public const int TOKEN_ADJUST_GROUPS = 0x0040;
        public const int TOKEN_ADJUST_DEFAULT = 0x0080;
        public const int TOKEN_ADJUST_SESSIONID = 0x0100;
                                      TOKEN_ASSIGN_PRIMARY |
                                      TOKEN_DUPLICATE |
                                      TOKEN_IMPERSONATE |
                                      TOKEN_QUERY |
                                      TOKEN_QUERY_SOURCE |
                                      TOKEN_ADJUST_PRIVILEGES |
                                      TOKEN_ADJUST_GROUPS |
        public const int TOKEN_ALL_ACCESS = TOKEN_ALL_ACCESS_P | 
        public const int TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
                                      TOKEN_ADJUST_PRIVILEGES |
                                      TOKEN_ADJUST_GROUPS |

//Defined for Process Rights
        public const uint MAXIMUM_ALLOWED = 0x2000000;
        public const int CREATE_NEW_PROCESS_GROUP = 0x00000200;
        public const int CREATE_UNICODE_ENVIRONMENT = 0x00000400;
        public const int IDLE_PRIORITY_CLASS = 0x40;
        public const int NORMAL_PRIORITY_CLASS = 0x20;
        public const int HIGH_PRIORITY_CLASS = 0x80;
        public const int REALTIME_PRIORITY_CLASS = 0x100;
        public const int CREATE_NEW_CONSOLE = 0x00000010;
        public const string SE_DEBUG_NAME = "SeDebugPrivilege";
        public const string SE_RESTORE_NAME = "SeRestorePrivilege";
        public const string SE_BACKUP_NAME = "SeBackupPrivilege";
        public const int SE_PRIVILEGE_ENABLED = 0x0002;
        public const int ERROR_NOT_ALL_ASSIGNED = 1300;

//structure for the Process32First API
        private struct PROCESSENTRY32
            public uint dwSize;
            public uint cntUsage;
            public uint th32ProcessID;
            public IntPtr th32DefaultHeapID;
            public uint th32ModuleID;
            public uint cntThreads;
            public uint th32ParentProcessID;
            public int pcPriClassBase;
            public uint dwFlags;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szExeFile;
Rest of the code is straightforward. You can refer to my previous article to understand the core logic. You are free to use the code. You can contact me at for more details. I am in the process of writing my second article about UAC tweaks soon.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Singapore Singapore
I graduated from Nanyang Technological University, Singapore in May 2004.Currently I am working as a Technical Consultant. I am also doing my Masters of Computing in IT project management from NUS, Singapore.My interests include reading technical articles,watching movies and traveling.My main areas of work include Project Management, Software Analysis and Design,Building Enterprise Applications using Microsoft .NET technologies,smart phone application development (Windows Mobile 5.0 and Blackberry) and System Programing on Windows Platform & WinCE

You may also be interested in...


Comments and Discussions

QuestionSome simplifications Pin
X-Tech10-May-12 14:18
memberX-Tech10-May-12 14:18 
GeneralMy vote of 4 Pin
Member 802439017-Jan-12 22:19
memberMember 802439017-Jan-12 22:19 
GeneralMy vote of 4 Pin
mlcc200022-Sep-10 6:18
membermlcc200022-Sep-10 6:18 
GeneralRe: My vote of 4 Pin
Member 802439017-Jan-12 22:00
memberMember 802439017-Jan-12 22:00 
GeneralRequest for code Pin
Member 450769716-Jun-10 18:09
memberMember 450769716-Jun-10 18:09 
GeneralPlease convert to VB Pin
KyferEz23-Feb-09 10:35
memberKyferEz23-Feb-09 10:35 
QuestionBut How do I launch an application under current user as elevated on session 1 ? Pin
Yukoop25-Nov-08 12:22
memberYukoop25-Nov-08 12:22 
GeneralYou are a lifesaver Pin
pkorosi30-Jul-08 0:37
memberpkorosi30-Jul-08 0:37 
GeneralRe: You are a lifesaver Pin
Jaisvar30-Jul-08 3:32
memberJaisvar30-Jul-08 3:32 
Generalthe declaration of SetTokenInformation is not correct Pin
curlfw3-Jun-07 15:31
membercurlfw3-Jun-07 15:31 
GeneralAs is the 1st parameter of CreateEnvironmentBlock Pin
Midi_Mick11-Jul-11 18:31
professionalMidi_Mick11-Jul-11 18:31 
QuestionHow to use? Pin
stevenyoung13-May-07 18:36
memberstevenyoung13-May-07 18:36 
AnswerRe: How to use? Pin
Jaisvar13-May-07 20:30
memberJaisvar13-May-07 20:30 
GeneralRe: How to use? Pin
stevenyoung22-May-07 17:26
memberstevenyoung22-May-07 17:26 
GeneralRe: How to use? Pin
BugByter16-Aug-08 6:56
memberBugByter16-Aug-08 6:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web02 | 2.8.181215.1 | Last Updated 13 May 2007
Article Copyright 2007 by Jaisvar
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid