2010-11-10 50 views
16

Tôi có cần bật bàn làm việc Interactive để nó hoạt động không và mã chính xác để bắt đầu cửa sổ EXE hoặc cmd là gì? Tôi vẫn không thể khởi động dịch vụ ngay cả khi tôi đã cho phép nó tương tác với máy tính để bàn.Bắt đầu một dịch vụ windows và khởi động cmd

Tôi sẽ sử dụng công cụ trò chuyện để quản lý cửa sổ dễ dàng hơn.

Điều gì sai với mã của tôi?

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

Trả lời

30

Tôi đã trải qua mọi nỗi đau khi thực hiện việc này.

Trong cửa sổ 7/Vista/2008, không thể tải bất kỳ quy trình tương tác nào từ dịch vụ - mà không cần gọi một số API Win. = BLACK MAGIC

Có giao diện herehere.

Đoạn code dưới đây không lừa, sử dụng nó với nguy cơ của riêng bạn:

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

Thật khó để lập trình. Vì vậy, tôi đã từ bỏ vì nó không đáng để nỗ lực. – Proyb2

+0

Tôi có thể khai thác mã và gửi mã cho bạn. Sẽ làm điều đó tối nay khi tôi về nhà. – Aliostad

+0

Tôi đã cập nhật mã cho bạn ngay bây giờ. – Aliostad

5

Khi chạy như một dịch vụ, bạn sẽ không thể khởi động bất cứ điều gì mà cần phải tương tác với máy tính để bàn hoặc sẽ đẻ trứng nó cửa sổ riêng.

Như Aliostad đã nói, bạn cần gọi các cuộc gọi Win API đến CreateProcessAsUser và mô phỏng người dùng để nó hoạt động. Điều này liên quan đến việc mô phỏng người dùng đã đăng nhập và sử dụng thông tin đăng nhập của họ để "nâng" quy trình của bạn vào mức cô lập quy trình 1 (cung cấp cho bạn quyền truy cập vào hệ thống cửa sổ và những thứ như GPU).

tôi đang làm điều này trong một ứng dụng tôi đã viết và nó không làm việc nhưng tôi đồng ý với Aliostad có một chút màu đen kỳ diệu đang xảy ra và nó thường hút

Có nói tất cả điều đó, bạn có thể đẻ trứng quá trình lao động từ trong một dịch vụ như họ không yêu cầu những thứ đang ở mức cô lập quá trình 1 (Windowing, GPU, v.v.)

cmd.exe theo mặc định sẽ cố tạo cửa sổ, đây là lý do tại sao ví dụ của bạn bị lỗi . Bạn có thể đặt các thuộc tính ProcessStartInfo sau đây để nó hoạt động.

CreateNoWindow WindowStyle

+0

"Quy trình cách ly cấp 1" không tồn tại. Điều bạn muốn nói là "phiên tương tác của người dùng". – wj32

2

tôi đã viết một dịch vụ cơ quan giám sát ứng dụng mà chỉ đơn giản khởi động lại một ứng dụng (trong trường hợp của tôi một App cửa sổ Console).

  1. Tôi tìm thấy một Hands-On rất tốt Lab Hướng dẫn (trong C++) mà tôi đã cố gắng vào nó làm việc cho Session 0 Isolation tại địa chỉ: http://msdn.microsoft.com/en-us/Windows7TrainingCourse_Win7Session0Isolation

  2. tôi chuyển đổi mà C++ Sample vào C#. Sau một vài thử nghiệm nó hoạt động. Miễn là tôi ở lại đăng nhập và không đăng xuất và đăng nhập lại mã đó hoạt động hoàn hảo. Tôi phải làm một chút để bắt Session Logout/Đăng nhập. Nhưng đối với đăng nhập đơn giản và điều kiện làm việc trong Windows, cơ quan giám sát hoạt động như mong đợi.

  3. Dưới đây là mã PInvoke yêu cầu:

    [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. Dưới đây là phương pháp encapsuled:

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

Tôi hy vọng nó rất hữu ích!

1

Chức năng bên dưới sẽ khởi chạy một tệp thực thi với tư cách người dùng đang hoạt động từ dịch vụ cửa sổ.

//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

Tôi sẽ từ bỏ một upvote ở đây cho các nỗ lực, nhưng câu hỏi là cho C#, không C + +. – TonyG

+0

Vâng, bạn nói đúng. Để cho bạn biết sự thật khi tôi đi qua câu hỏi tôi đã không nhận ra nó đã được C# và tôi chỉ đăng mã có liên quan tôi đã xảy ra để có. Tôi đoán nó vẫn có thể hữu ích trong việc hiển thị những gì liên quan đến logic và các cuộc gọi cấp thấp. –

Các vấn đề liên quan