CreateProcessAsUser la Création de la Fenêtre de Session Active

Je suis en utilisant CreateProcessAsUser partir d'un service windows (veuillez pouvons-nous rester dans le sujet, et supposons que j'ai une très bonne raison pour faire ce). Contrairement à ce que tout le monde se pose la question ici, j'obtiens une fenêtre dans ma session de terminal (session 1) au lieu de la même session que le service (session 0) - ce qui est indésirable.

Je appropriation Scott Allen code; et est venu avec ce qui suit. Changements notables sont les "revenir à soi", le "CREATE_NO_WINDOW" en ligne de commande et les arguments de soutien.

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);
}
}
}
}

Supposons maintenant que le service est en cours d'exécution en vertu de l' "Domaine\MyService et je suis actuellement connecté en tant que" Domaine\Administrateur " - et que je suis le démarrage d'une application console comme un processus de travail. Lorsque j'utilise une application client pour accéder au service (le service n'est pas lancé en mode console c'est à dire qu'il est dans la session 0) et d'exécuter la méthode qui appelle la CreateProcessAsUser le processus de travail s'affiche sur mon bureau.

Maintenant, je pourrait en faire une application windows avec pas de fenêtre, à côté de l'étape de la création de la fenêtre de la console; cependant, à la fin de la journée, c'est encore en cours de création de la session 1.

Des idées pourquoi l'application de la console n'est pas créé dans la même session en tant que service?

On dirait qu'il pourrait avoir quelque chose à faire avec cette magie noire, mais je ne peux pas comprendre comment l'ignorer.
Essayé à l'aide de "Service-0×0-3e7$\Default" comme le bureau - qui provoque un crash de l'application.
Quelle version de Windows? Avez-vous essayé de quitter lpDeskTop à null?
Server 2008 R2. J'ai en effet essayé de réglage lpDeskTop à null (qui a causé un accident dans le processus de travail) - j'ai aussi essayé de réglage pour différentes valeurs codées en dur tel que le construit-dans la session 0 ordinateur de bureau nom.
Si de nombreuses circonstances sont à l'origine des accidents, il est peut-être un regroupement question. Pouvez-vous poster le code de vos structures et externes?

OriginalL'auteur Jonathan Dickinson | 2012-02-01