CreateProcessAsUser-Erstellen-Fenster in der Aktiven Sitzung

Ich bin mit CreateProcessAsUser aus einem windows service (bitte können wir bleiben am Thema und an ich habe einen sehr guten Grund, dies zu tun). Im Gegensatz zu dem, was alle anderen Fragen hier, ich bin immer ein Fenster in meiner aktiven terminal session (Sitzung 1) anstelle der gleichen Sitzung wie der service (session-0) - und das ist unerwünscht.

Angeeignet ich Scott Allen - code; und kam mit der folgenden. Wesentliche änderungen sind der "revert to self", der "CREATE_NO_WINDOW" und Kommandozeilen-Argumente unterstützen.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Security.Principal;
using System.ComponentModel;
using System.IO;

namespace SourceCode.Runtime.ChildProcessService
{
    [SuppressUnmanagedCodeSecurity]
    class NativeMethods
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct STARTUPINFO
        {
            public Int32 cb;
            public string lpReserved;
            public string lpDesktop;
            public string lpTitle;
            public Int32 dwX;
            public Int32 dwY;
            public Int32 dwXSize;
            public Int32 dwXCountChars;
            public Int32 dwYCountChars;
            public Int32 dwFillAttribute;
            public Int32 dwFlags;
            public Int16 wShowWindow;
            public Int16 cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public Int32 dwProcessID;
            public Int32 dwThreadID;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SECURITY_ATTRIBUTES
        {
            public Int32 Length;
            public IntPtr lpSecurityDescriptor;
            public bool bInheritHandle;
        }

        public enum SECURITY_IMPERSONATION_LEVEL
        {
            SecurityAnonymous,
            SecurityIdentification,
            SecurityImpersonation,
            SecurityDelegation
        }

        public enum TOKEN_TYPE
        {
            TokenPrimary = 1,
            TokenImpersonation
        }

        public const int GENERIC_ALL_ACCESS = 0x10000000;
        public const int CREATE_NO_WINDOW = 0x08000000;

        [
           DllImport("kernel32.dll",
              EntryPoint = "CloseHandle", SetLastError = true,
              CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)
        ]
        public static extern bool CloseHandle(IntPtr handle);

        [
           DllImport("advapi32.dll",
              EntryPoint = "CreateProcessAsUser", SetLastError = true,
              CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)
        ]
        public static extern bool
           CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine,
                               ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes,
                               bool bInheritHandle, Int32 dwCreationFlags, IntPtr lpEnvrionment,
                               string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo,
                               ref PROCESS_INFORMATION lpProcessInformation);

        [
           DllImport("advapi32.dll",
              EntryPoint = "DuplicateTokenEx")
        ]
        public static extern bool
           DuplicateTokenEx(IntPtr hExistingToken, Int32 dwDesiredAccess,
                            ref SECURITY_ATTRIBUTES lpThreadAttributes,
                            Int32 ImpersonationLevel, Int32 dwTokenType,
                            ref IntPtr phNewToken);

        public static Process CreateProcessAsUser(string filename, string args)
        {
            var hToken = WindowsIdentity.GetCurrent().Token;
            var hDupedToken = IntPtr.Zero;

            var pi = new PROCESS_INFORMATION();
            var sa = new SECURITY_ATTRIBUTES();
            sa.Length = Marshal.SizeOf(sa);

            try
            {
                if (!DuplicateTokenEx(
                        hToken,
                        GENERIC_ALL_ACCESS,
                        ref sa,
                        (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
                        (int)TOKEN_TYPE.TokenPrimary,
                        ref hDupedToken
                    ))
                    throw new Win32Exception(Marshal.GetLastWin32Error());

                var si = new STARTUPINFO();
                si.cb = Marshal.SizeOf(si);
                si.lpDesktop = "";

                var path = Path.GetFullPath(filename);
                var dir = Path.GetDirectoryName(path);

                //Revert to self to create the entire process; not doing this might
                //require that the currently impersonated user has "Replace a process
                //level token" rights - we only want our service account to need
                //that right.
                using (var ctx = WindowsIdentity.Impersonate(IntPtr.Zero))
                {
                    if (!CreateProcessAsUser(
                                            hDupedToken,
                                            path,
                                            string.Format("\"{0}\" {1}", filename.Replace("\"", "\"\""), args),
                                            ref sa, ref sa,
                                            false, 0, IntPtr.Zero,
                                            dir, ref si, ref pi
                                    ))
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                return Process.GetProcessById(pi.dwProcessID);
            }
            finally
            {
                if (pi.hProcess != IntPtr.Zero)
                    CloseHandle(pi.hProcess);
                if (pi.hThread != IntPtr.Zero)
                    CloseHandle(pi.hThread);
                if (hDupedToken != IntPtr.Zero)
                    CloseHandle(hDupedToken);
            }
        }
    }
}

Nun davon ausgehen, dass der Dienst ausgeführt wird, unter "Domain\MyService', und ich bin derzeit angemeldet als 'Domäne\Administrator' - und ich bin dem Booten eine Konsole-Anwendung, wie ein Arbeitsprozess. Wenn ich eine client-Anwendung zum Zugriff auf den Dienst (der Dienst ist nicht gestartet, im Konsolen-Modus, d.h. es wird in session 0) und führen Sie dann die Methode aufruft, die die CreateProcessAsUser den Arbeitsprozess erscheint auf meinem desktop.

Nun, ich könnte es eine windows Anwendung ohne Fenster zu Seite-Schritt die Erstellung von Konsolen-Fenster; jedoch, am Ende des Tages ist es immer noch in Sitzung 1.

Irgendwelche Ideen, warum die Konsole-Anwendung nicht erstellt wird, in der gleichen Sitzung wie der service?

Es sieht aus wie es könnte etwas zu tun mit schwarze Magie, aber ich kann nicht herausfinden, wie es zu überspringen.
Versucht, mit Hilfe von "Service-0×0-3e7$\Default" als die desktop -, die bewirkt, dass die Anwendung zum Absturz zu bringen.
Welche version von Windows? Haben Sie versucht, zu verlassen ipdesktop bei null?
Server 2008 R2. Ich habe in der Tat versucht, die Einstellung lpDeskTop zu null (was zum Absturz führte, in den Arbeitsprozess) - ich habe auch versucht eine Einstellung von verschiedenen hart-kodierten Werten wie die built-in session 0 desktop-Namen.
Wenn so viele Umstände, die Abstürze verursachen, vielleicht gibt es ein Marshalling Problem. Können Sie nach dem code für Ihre Strukturen und externs?

InformationsquelleAutor Jonathan Dickinson | 2012-02-01

Schreibe einen Kommentar