2010-11-10 2 views
16

Должен ли я включить интерактивный дескрипт для его работы и что такое правильный код для запуска окна EXE или cmd? Я все еще не могу запустить службу, даже когда я разрешил ей взаимодействовать с рабочим столом.Запустите службу Windows и запустите cmd

Я бы использовал механизм чата, поэтому его проще управлять в качестве службы Windows.

Что случилось с моим кодом?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ServiceProcess; 
using System.Diagnostics; 
using System.ComponentModel; 
using System.Threading; 

namespace MyNewService 
{ 
    class Program : ServiceBase 
    { 
     static void Main(string[] args) 
     { 
     } 

     public Program() 
     { 
      this.ServiceName = "Chatter"; 
     } 

     protected override void OnStart(string[] args) 
     { 
      base.OnStart(args); 

      //TODO: place your start code here 
      ThreadStart starter = new ThreadStart(bw_DoWork); 
      Thread t = new Thread(starter); 
      t.Start(); 

     } 

     private void bw_DoWork() 
     { 
      Process p = new Process(); 
      p.StartInfo = new ProcessStartInfo(@"C:\Windows\system32\cmd.exe"); 
      p.Start(); 
      p.WaitForExit(); 
      base.Stop(); 
     } 

     protected override void OnStop() 
     { 
      base.OnStop(); 

      //TODO: clean up any variables and stop any threads 
     } 
    } 
} 

ответ

30

Я пережил всю эту боль.

В Windows 7/Vista/2008 невозможно загрузить любой интерактивный процесс из службы - без вызова ряда Win API. = BLACK MAGIC

Посмотрите here и here.

ниже код делает трюк, использовать его с своим страхом и риском:

public static class ProcessAsCurrentUser 
{ 

    /// <summary> 
    /// Connection state of a session. 
    /// </summary> 
    public enum ConnectionState 
    { 
     /// <summary> 
     /// A user is logged on to the session. 
     /// </summary> 
     Active, 
     /// <summary> 
     /// A client is connected to the session. 
     /// </summary> 
     Connected, 
     /// <summary> 
     /// The session is in the process of connecting to a client. 
     /// </summary> 
     ConnectQuery, 
     /// <summary> 
     /// This session is shadowing another session. 
     /// </summary> 
     Shadowing, 
     /// <summary> 
     /// The session is active, but the client has disconnected from it. 
     /// </summary> 
     Disconnected, 
     /// <summary> 
     /// The session is waiting for a client to connect. 
     /// </summary> 
     Idle, 
     /// <summary> 
     /// The session is listening for connections. 
     /// </summary> 
     Listening, 
     /// <summary> 
     /// The session is being reset. 
     /// </summary> 
     Reset, 
     /// <summary> 
     /// The session is down due to an error. 
     /// </summary> 
     Down, 
     /// <summary> 
     /// The session is initializing. 
     /// </summary> 
     Initializing 
    } 


    [StructLayout(LayoutKind.Sequential)] 
    class SECURITY_ATTRIBUTES 
    { 
     public int nLength; 
     public IntPtr lpSecurityDescriptor; 
     public int bInheritHandle; 
    } 


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
    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 dwYSize; 
     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)] 
    internal struct PROCESS_INFORMATION 
    { 
     public IntPtr hProcess; 
     public IntPtr hThread; 
     public int dwProcessId; 
     public int dwThreadId; 
    } 

    enum LOGON_TYPE 
    { 
     LOGON32_LOGON_INTERACTIVE = 2, 
     LOGON32_LOGON_NETWORK, 
     LOGON32_LOGON_BATCH, 
     LOGON32_LOGON_SERVICE, 
     LOGON32_LOGON_UNLOCK = 7, 
     LOGON32_LOGON_NETWORK_CLEARTEXT, 
     LOGON32_LOGON_NEW_CREDENTIALS 
    } 

    enum LOGON_PROVIDER 
    { 
     LOGON32_PROVIDER_DEFAULT, 
     LOGON32_PROVIDER_WINNT35, 
     LOGON32_PROVIDER_WINNT40, 
     LOGON32_PROVIDER_WINNT50 
    } 

    [Flags] 
    enum CreateProcessFlags : uint 
    { 
     CREATE_BREAKAWAY_FROM_JOB = 0x01000000, 
     CREATE_DEFAULT_ERROR_MODE = 0x04000000, 
     CREATE_NEW_CONSOLE = 0x00000010, 
     CREATE_NEW_PROCESS_GROUP = 0x00000200, 
     CREATE_NO_WINDOW = 0x08000000, 
     CREATE_PROTECTED_PROCESS = 0x00040000, 
     CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000, 
     CREATE_SEPARATE_WOW_VDM = 0x00000800, 
     CREATE_SHARED_WOW_VDM = 0x00001000, 
     CREATE_SUSPENDED = 0x00000004, 
     CREATE_UNICODE_ENVIRONMENT = 0x00000400, 
     DEBUG_ONLY_THIS_PROCESS = 0x00000002, 
     DEBUG_PROCESS = 0x00000001, 
     DETACHED_PROCESS = 0x00000008, 
     EXTENDED_STARTUPINFO_PRESENT = 0x00080000, 
     INHERIT_PARENT_AFFINITY = 0x00010000 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct WTS_SESSION_INFO 
    { 
     public int SessionID; 
     [MarshalAs(UnmanagedType.LPTStr)] 
     public string WinStationName; 
     public ConnectionState State; 
    } 

    [DllImport("wtsapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    public static extern Int32 WTSEnumerateSessions(IntPtr hServer, int reserved, int version, 
                ref IntPtr sessionInfo, ref int count); 


    [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUserW", SetLastError = true, CharSet = CharSet.Auto)] 
    static extern bool CreateProcessAsUser(
     IntPtr hToken, 
     string lpApplicationName, 
     string lpCommandLine, 
     IntPtr lpProcessAttributes, 
     IntPtr lpThreadAttributes, 
     bool bInheritHandles, 
     UInt32 dwCreationFlags, 
     IntPtr lpEnvironment, 
     string lpCurrentDirectory, 
     ref STARTUPINFO lpStartupInfo, 
     out PROCESS_INFORMATION lpProcessInformation); 

    [DllImport("wtsapi32.dll")] 
    public static extern void WTSFreeMemory(IntPtr memory); 

    [DllImport("kernel32.dll")] 
    private static extern UInt32 WTSGetActiveConsoleSessionId(); 

    [DllImport("wtsapi32.dll", SetLastError = true)] 
    static extern int WTSQueryUserToken(UInt32 sessionId, out IntPtr Token); 

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    public extern static bool DuplicateTokenEx(
     IntPtr hExistingToken, 
     uint dwDesiredAccess, 
     IntPtr lpTokenAttributes, 
     int ImpersonationLevel, 
     int TokenType, 
     out IntPtr phNewToken); 

    private const int TokenImpersonation = 2; 
    private const int SecurityIdentification = 1; 
    private const int MAXIMUM_ALLOWED = 0x2000000; 
    private const int TOKEN_DUPLICATE = 0x2; 
    private const int TOKEN_QUERY = 0x00000008; 

    /// <summary> 
    /// Launches a process for the current logged on user if there are any. 
    /// If none, return false as well as in case of 
    /// 
    /// ##### !!! BEWARE !!! #### ------------------------------------------ 
    /// This code will only work when running in a windows service (where it is really needed) 
    /// so in case you need to test it, it needs to run in the service. Reason 
    /// is a security privileg which only services have (SE_??? something, cant remember)! 
    /// </summary> 
    /// <param name="processExe"></param> 
    /// <returns></returns> 
    public static bool CreateProcessAsCurrentUser(string processExe) 
    { 

     IntPtr duplicate = new IntPtr(); 
     STARTUPINFO info = new STARTUPINFO(); 
     PROCESS_INFORMATION procInfo = new PROCESS_INFORMATION(); 

     Debug.WriteLine(string.Format("CreateProcessAsCurrentUser. processExe: " + processExe)); 

     IntPtr p = GetCurrentUserToken(); 

     bool result = DuplicateTokenEx(p, MAXIMUM_ALLOWED | TOKEN_QUERY | TOKEN_DUPLICATE, IntPtr.Zero, SecurityIdentification, SecurityIdentification, out duplicate); 
     Debug.WriteLine(string.Format("DuplicateTokenEx result: {0}", result)); 
     Debug.WriteLine(string.Format("duplicate: {0}", duplicate)); 


     if (result) 
     { 
      result = CreateProcessAsUser(duplicate, processExe, null, 
       IntPtr.Zero, IntPtr.Zero, false, (UInt32)CreateProcessFlags.CREATE_NEW_CONSOLE, IntPtr.Zero, null, 
       ref info, out procInfo); 
      Debug.WriteLine(string.Format("CreateProcessAsUser result: {0}", result)); 

     } 


     if (p.ToInt32() != 0) 
     { 
      Marshal.Release(p); 
      Debug.WriteLine(string.Format("Released handle p: {0}", p)); 
     } 


     if (duplicate.ToInt32() != 0) 
     { 
      Marshal.Release(duplicate); 
      Debug.WriteLine(string.Format("Released handle duplicate: {0}", duplicate)); 
     } 



     return result; 
    } 

    public static int GetCurrentSessionId() 
    { 
     uint sessionId = WTSGetActiveConsoleSessionId(); 
     Debug.WriteLine(string.Format("sessionId: {0}", sessionId)); 

     if (sessionId == 0xFFFFFFFF) 
      return -1; 
     else 
      return (int)sessionId; 
    } 

    public static bool IsUserLoggedOn() 
    { 
     List<WTS_SESSION_INFO> wtsSessionInfos = ListSessions(); 
     Debug.WriteLine(string.Format("Number of sessions: {0}", wtsSessionInfos.Count)); 
     return wtsSessionInfos.Where(x => x.State == ConnectionState.Active).Count() > 0; 
    } 

    private static IntPtr GetCurrentUserToken() 
    { 
     List<WTS_SESSION_INFO> wtsSessionInfos = ListSessions(); 
     int sessionId = wtsSessionInfos.Where(x => x.State == ConnectionState.Active).FirstOrDefault().SessionID; 
     //int sessionId = GetCurrentSessionId(); 

     Debug.WriteLine(string.Format("sessionId: {0}", sessionId)); 
     if (sessionId == int.MaxValue) 
     { 
      return IntPtr.Zero; 
     } 
     else 
     { 
      IntPtr p = new IntPtr(); 
      int result = WTSQueryUserToken((UInt32)sessionId, out p); 
      Debug.WriteLine(string.Format("WTSQueryUserToken result: {0}", result)); 
      Debug.WriteLine(string.Format("WTSQueryUserToken p: {0}", p)); 

      return p; 
     } 
    } 

    public static List<WTS_SESSION_INFO> ListSessions() 
    { 
     IntPtr server = IntPtr.Zero; 
     List<WTS_SESSION_INFO> ret = new List<WTS_SESSION_INFO>(); 

     try 
     { 
      IntPtr ppSessionInfo = IntPtr.Zero; 

      Int32 count = 0; 
      Int32 retval = WTSEnumerateSessions(IntPtr.Zero, 0, 1, ref ppSessionInfo, ref count); 
      Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO)); 

      Int64 current = (int)ppSessionInfo; 

      if (retval != 0) 
      { 
       for (int i = 0; i < count; i++) 
       { 
        WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO)); 
        current += dataSize; 

        ret.Add(si); 
       } 

       WTSFreeMemory(ppSessionInfo); 
      } 
     } 
     catch (Exception exception) 
     { 
      Debug.WriteLine(exception.ToString()); 
     } 

     return ret; 
    } 

} 
+0

Это сложно программировать. Поэтому я сдался, так как это не стоило усилий. – Proyb2

+0

Я могу выкопать код и отправить его вам. Сделаю это сегодня вечером, когда я вернусь домой. – Aliostad

+0

Я обновил код для вас сейчас. – Aliostad

5

Когда работает как сервис, вы не сможете запускать все, что должно взаимодействовать с рабочим столом или породит это собственные окна.

Как сказал Aliostad, вам необходимо вызвать вызовы Win API для CreateProcessAsUser и эмулировать пользователя, чтобы он работал. Это включает в себя эмуляцию зарегистрированного пользователя и использование их учетных данных для «подъема» вашего процесса в уровень изоляции процесса 1 (который дает вам доступ к системе окон и тому подобным графическим процессорам).

Я делаю это в приложении, которое я написал, и это делает работу, но я согласен с Aliostad есть немного черная магия происходит, и это вообще отстой

Сказав все это, вы можете икру рабочих процессов из в рамках службы, поскольку они не требуют вещей, которые находятся в процессе изоляции уровня 1 (Windowing, GPU и т. д.)

cmd.exe по умолчанию будет пытаться создать окно, поэтому ваш пример не работает , Вы можете установить следующие свойства ProcessStartInfo, чтобы заставить его работать.

CreateNoWindow WindowStyle

+0

«Уровень изоляции процесса 1» не существует. То, что вы хотите сказать, это «интерактивная сессия пользователя». – wj32

2

Я написал службу сторожевого приложений, которые просто перезапускает приложение (в моем случае окно консоли App).

  1. Я нашел очень хороший Hands-On Lab Учебное пособие (в C++), который я пытался на нее работал Session 0 Isolation на: http://msdn.microsoft.com/en-us/Windows7TrainingCourse_Win7Session0Isolation

  2. я преобразовал, что образец C++ в C#. После нескольких тестов это сработало. До тех пор, пока я остаюсь включенным и не выхожу из системы и не войду снова, этот код работает отлично. Я должен сделать немного, чтобы поймать сеанс Logout/Login. Но для простого входа в систему и условий работы в Windows сторожевой таймер работает так, как ожидалось.

  3. Вот что требуется PInvoke код:

    [StructLayout(LayoutKind.Sequential)] 
    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; 
    } 
    
    [StructLayout(LayoutKind.Sequential)] 
    public struct PROCESS_INFORMATION 
    { 
        public IntPtr hProcess; 
        public IntPtr hThread; 
        public uint dwProcessId; 
        public uint dwThreadId; 
    } 
    
    
    public enum TOKEN_TYPE 
    { 
        TokenPrimary = 1, 
        TokenImpersonation 
    } 
    
    public enum SECURITY_IMPERSONATION_LEVEL 
    { 
        SecurityAnonymous, 
        SecurityIdentification, 
        SecurityImpersonation, 
        SecurityDelegation 
    } 
    
    [StructLayout(LayoutKind.Sequential)] 
    public struct SECURITY_ATTRIBUTES 
    { 
        public int nLength; 
        public IntPtr lpSecurityDescriptor; 
        public int bInheritHandle; 
    } 
    
    
    [DllImport("kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] 
    public extern static bool CloseHandle(IntPtr handle); 
    
    [DllImport("kernel32.dll")] 
    public static extern uint WTSGetActiveConsoleSessionId(); 
    
    [DllImport("wtsapi32.dll", SetLastError = true)] 
    public static extern bool WTSQueryUserToken(UInt32 sessionId, out IntPtr Token); 
    
    [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] 
    public extern static bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, 
        ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment, 
        String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); 
    
    
    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    public extern static bool DuplicateTokenEx(
        IntPtr hExistingToken, 
        uint dwDesiredAccess, 
        ref SECURITY_ATTRIBUTES lpTokenAttributes, 
        SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, 
        TOKEN_TYPE TokenType, 
        out IntPtr phNewToken); 
    
  4. Вот инкапсулированный метод:

    private void CreateUserProcess() 
    { 
    
        bool ret; 
        SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES(); 
    
        uint dwSessionID = WTSGetActiveConsoleSessionId(); 
    
    
        this.EventLog.WriteEntry("WTSGetActiveConsoleSessionId: " + dwSessionID, EventLogEntryType.FailureAudit); 
    
    
        IntPtr Token = new IntPtr(); 
        ret = WTSQueryUserToken((UInt32)dwSessionID, out Token); 
    
        if (ret == false) 
        { 
         this.EventLog.WriteEntry("WTSQueryUserToken failed with " + Marshal.GetLastWin32Error(), EventLogEntryType.FailureAudit); 
    
        } 
    
        const uint MAXIMUM_ALLOWED = 0x02000000; 
        IntPtr DupedToken = IntPtr.Zero; 
    
        ret = DuplicateTokenEx(Token, 
         MAXIMUM_ALLOWED, 
         ref sa, 
         SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, 
         TOKEN_TYPE.TokenPrimary, 
         out DupedToken); 
    
        if (ret == false) 
        { 
         this.EventLog.WriteEntry("DuplicateTokenEx failed with " + Marshal.GetLastWin32Error(), EventLogEntryType.FailureAudit); 
    
        } 
        else 
        { 
         this.EventLog.WriteEntry("DuplicateTokenEx SUCCESS", EventLogEntryType.SuccessAudit); 
        } 
    
        STARTUPINFO si = new STARTUPINFO(); 
        si.cb = Marshal.SizeOf(si); 
        //si.lpDesktop = ""; 
    
        string commandLinePath; 
    
        // commandLinePath example: "c:\myapp.exe c:\myconfig.xml" . cmdLineArgs can be ommited 
        commandLinePath = AppPath + " " + CmdLineArgs; 
    
        PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); 
        //CreateProcessAsUser(hDuplicatedToken, NULL, lpszClientPath, NULL, NULL, FALSE, 
        //     0, 
        //     NULL, NULL, &si, &pi) 
        ret = CreateProcessAsUser(DupedToken, null, commandLinePath, ref sa, ref sa, false, 0, (IntPtr)0, null, ref si, out pi); 
    
        if (ret == false) 
        { 
         this.EventLog.WriteEntry("CreateProcessAsUser failed with " + Marshal.GetLastWin32Error(), EventLogEntryType.FailureAudit); 
    
    
        } 
        else 
        { 
         this.EventLog.WriteEntry("CreateProcessAsUser SUCCESS. The child PID is" + pi.dwProcessId, EventLogEntryType.SuccessAudit); 
         CloseHandle(pi.hProcess); 
         CloseHandle(pi.hThread); 
        } 
    
        ret = CloseHandle(DupedToken); 
        if (ret == false) 
        { 
         this.EventLog.WriteEntry("CloseHandle LastError: " + Marshal.GetLastWin32Error(), EventLogEntryType.Error); 
        } 
        else 
        { 
        this.EventLog.WriteEntry("CloseHandle SUCCESS", EventLogEntryType.Information); 
    
        } 
    } 
    

Я надеюсь, что это полезно!

1

Функция ниже запускает исполняемый файл как активный пользователь из службы Windows.

//Function to run a process as active user from windows service 
void ImpersonateActiveUserAndRun(WCHAR* path, WCHAR* args) 
{ 
    DWORD session_id = -1; 
    DWORD session_count = 0; 

    WTS_SESSION_INFOA *pSession = NULL; 


    if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &session_count)) 
    { 
     //log success 
    } 
    else 
    { 
     //log error 
     return; 
    } 

    for (int i = 0; i < session_count; i++) 
    { 
     session_id = pSession[i].SessionId; 

     WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected; 
     WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL; 

     DWORD bytes_returned = 0; 
     if (::WTSQuerySessionInformation(
      WTS_CURRENT_SERVER_HANDLE, 
      session_id, 
      WTSConnectState, 
      reinterpret_cast<LPTSTR*>(&ptr_wts_connect_state), 
      &bytes_returned)) 
     { 
      wts_connect_state = *ptr_wts_connect_state; 
      ::WTSFreeMemory(ptr_wts_connect_state); 
      if (wts_connect_state != WTSActive) continue; 
     } 
     else 
     { 
      //log error 
      continue; 
     } 

     HANDLE hImpersonationToken; 

     if (!WTSQueryUserToken(session_id, &hImpersonationToken)) 
     { 
      //log error 
      continue; 
     } 


     //Get real token from impersonation token 
     DWORD neededSize1 = 0; 
     HANDLE *realToken = new HANDLE; 
     if (GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize1)) 
     { 
      CloseHandle(hImpersonationToken); 
      hImpersonationToken = *realToken; 
     } 
     else 
     { 
      //log error 
      continue; 
     } 


     HANDLE hUserToken; 

     if (!DuplicateTokenEx(hImpersonationToken, 
      //0, 
      //MAXIMUM_ALLOWED, 
      TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | MAXIMUM_ALLOWED, 
      NULL, 
      SecurityImpersonation, 
      TokenPrimary, 
      &hUserToken)) 
     { 
      //log error 
      continue; 
     } 

     // Get user name of this process 
     //LPTSTR pUserName = NULL; 
     WCHAR* pUserName; 
     DWORD user_name_len = 0; 

     if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, WTSUserName, &pUserName, &user_name_len)) 
     { 
      //log username contained in pUserName WCHAR string 
     } 

     //Free memory       
     if (pUserName) WTSFreeMemory(pUserName); 

     ImpersonateLoggedOnUser(hUserToken); 

     STARTUPINFOW StartupInfo; 
     GetStartupInfoW(&StartupInfo); 
     StartupInfo.cb = sizeof(STARTUPINFOW); 
     //StartupInfo.lpDesktop = "winsta0\\default"; 

     PROCESS_INFORMATION processInfo; 

     SECURITY_ATTRIBUTES Security1; 
     Security1.nLength = sizeof SECURITY_ATTRIBUTES; 

     SECURITY_ATTRIBUTES Security2; 
     Security2.nLength = sizeof SECURITY_ATTRIBUTES; 

     void* lpEnvironment = NULL; 

     // Get all necessary environment variables of logged in user 
     // to pass them to the new process 
     BOOL resultEnv = CreateEnvironmentBlock(&lpEnvironment, hUserToken, FALSE); 
     if (!resultEnv) 
     { 
      //log error 
      continue; 
     } 

     WCHAR PP[1024]; //path and parameters 
     ZeroMemory(PP, 1024 * sizeof WCHAR); 
     wcscpy(PP, path); 
     wcscat(PP, L" "); 
     wcscat(PP, args); 

     // Start the process on behalf of the current user 
     BOOL result = CreateProcessAsUserW(hUserToken, 
      NULL, 
      PP, 
      //&Security1, 
      //&Security2, 
      NULL, 
      NULL, 
      FALSE, 
      NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE, 
      //lpEnvironment, 
      NULL, 
      //"C:\\ProgramData\\some_dir", 
      NULL, 
      &StartupInfo, 
      &processInfo); 

     if (!result) 
     { 
      //log error 
     } 
     else 
     { 
      //log success 
     } 

     DestroyEnvironmentBlock(lpEnvironment); 

     CloseHandle(hImpersonationToken); 
     CloseHandle(hUserToken); 
     CloseHandle(realToken); 

     RevertToSelf(); 
    } 

    WTSFreeMemory(pSession); 
} 
+1

Я отдам вверх uptote здесь для усилия, но вопрос для C#, а не C++. – TonyG

+0

Да, ты прав. Чтобы сказать вам правду, когда я столкнулся с вопросом, я не понимал, что это C#, и я просто разместил соответствующий код, который у меня был. Я думаю, это может быть полезно показать, что связано с логикой и низким уровнем вызовов. –

Смежные вопросы