public int Run()
        {
            STARTUPINFO si = new STARTUPINFO();
            si.lpDesktop = this.Desktop;
            PROCESSINFO pi = new PROCESSINFO();

            int creationFlags = NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT;
            creationFlags |= this.CreateNoWindow ? CREATE_NO_WINDOW : 0;

            // This creates the default environment block for this user. If you need
            // something custom skip te CreateEnvironmentBlock (and DestroyEnvironmentBlock)
            // calls. You need to handle the allocation of the memory and writing to
            // it yourself.
            IntPtr envBlock;
            if (!CreateEnvironmentBlock(out envBlock, this.mSessionTokenHandle, 0))
            {
                throw new System.ComponentModel.Win32Exception();
            }

            try
            {
                CreateProcessAsUser(this.mSessionTokenHandle, this.mApplicationPath, this.CommandLine, IntPtr.Zero, IntPtr.Zero, 0, creationFlags, envBlock, this.WorkingDirectory, si, pi);
                ProcessWaitHandle waitable = new ProcessWaitHandle(pi.hProcess);
                if (waitable.WaitOne())
                {
                    return pi.dwProcessId;
                }
            }
            catch (Win32Exception)
            {
            }
            finally
            {
                DestroyEnvironmentBlock(envBlock);
            }

            return -1;
        }
 private static extern bool CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, int bInheritHandles, int dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, STARTUPINFO lpStartupInfo, [Out]PROCESSINFO lpProcessInformation);