在其他用户的凭据下启动一个进程

我想在另一个用户名的凭据下启动一个进程。 这是我现在所拥有的:

/// <summary> /// Do actions under another username's credentials /// </summary> /// <param name="username">Username to inpersonate</param> /// <param name="domain">Domain/Machine</param> /// <param name="password">Password </param> public static void Action(string username,string domain, string password ) { try { if (LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref hToken)) { if (DuplicateToken(hToken, 2, ref hTokenDuplicate)) { WindowsIdentity windowsIdentity = new WindowsIdentity(hTokenDuplicate); WindowsImpersonationContext impersonationContext = windowsIdentity.Impersonate(); // Check the identity but it could do any other action under given username credentials try { ProcessStartInfo info = new ProcessStartInfo("cmd.exe"); info.UseShellExecute = false; info.RedirectStandardInput = true; info.RedirectStandardError = true; info.RedirectStandardOutput = true; info.UserName = "dummy"; // see the link mentioned at the top // Define the string value to assign to a new secure string. char[] chars = { 'p', 'a', 's', 's','1','2','3','4','/' }; // Instantiate the secure string. SecureString testString = new SecureString(); // Assign the character array to the secure string. foreach (char ch in chars) testString.AppendChar(ch); info.Password = testString; Process.Start(info); } catch (Exception ex) { Console.WriteLine("Exception Occurred :{0},{1}",ex.Message, ex.StackTrace.ToString()); } // Stop impersonating the user impersonationContext.Undo(); } } // Free the tokens if (hToken != IntPtr.Zero) CloseHandle(hToken); if (hTokenDuplicate != IntPtr.Zero) CloseHandle(hTokenDuplicate); }catch(Exception ex) { Console.WriteLine("Exception occurred. " + ex); } 

它似乎不工作,我得到一个“访问被拒绝”。 任何想法如何做到这一点? 如果我们要求证书,我们得到正确的,所以它应该执行任何程序下的凭据。 即:

  if (DuplicateToken(hToken, 2, ref hTokenDuplicate)) { WindowsIdentity windowsIdentity = new WindowsIdentity(hTokenDuplicate); WindowsImpersonationContext impersonationContext = windowsIdentity.Impersonate(); // Check the identity but it could do any other action under given username credentials Console.WriteLine("After impersonation: {0}", WindowsIdentity.GetCurrent().Name); // Stop impersonating the user impersonationContext.Undo(); } 

答案是正确的,我们得到“虚拟”。

我们可以使它更简单:

  public static void Run() { try { const string file = "cmd.exe"; var sspw = new SecureString(); foreach (var c in "pass1234/") sspw.AppendChar(c); var proc = new Process(); proc.StartInfo.UseShellExecute = false; proc.StartInfo.WorkingDirectory = Path.GetDirectoryName(file); proc.StartInfo.FileName = Path.GetFileName(file); proc.StartInfo.Domain = "WIN08"; proc.StartInfo.Arguments = ""; proc.StartInfo.UserName = "dummy"; proc.StartInfo.Password = sspw; proc.StartInfo.LoadUserProfile = false; proc.Start(); }catch(Exception e) { Console.WriteLine(e); } 

不过,我仍然得到例外…

Solutions Collecting From Web of "在其他用户的凭据下启动一个进程"

我不认为你需要登录用户和复制句柄。 您只需在ProcessStartInfo对象中设置用户名,域和密码即可。 如果我记得正确的话,自.NET 3.0起可用。

编辑:

另外对于更多的信息,当你给ProcessStartInfo提供用户名/域名/密码时,确实发生了这种情况: http : //support.microsoft.com/kb/165194 。 拒绝访问的原因可能是您无法访问用户的桌面或windowstation。 只是调用LoginUser是不够的。

对某些人来说可能会很奇怪,我很抱歉,我是Linux开发者…测试过:

  /// <summary> /// Class that deals with another username credentials /// </summary> class Credentials { /// <summary> /// Constructor of SecureString password, to be used by RunAs /// </summary> /// <param name="text">Plain password</param> /// <returns>SecureString password</returns> private static SecureString MakeSecureString(string text) { SecureString secure = new SecureString(); foreach (char c in text) { secure.AppendChar(c); } return secure; } /// <summary> /// Run an application under another user credentials. /// Working directory set to C:\Windows\System32 /// </summary> /// <param name="path">Full path to the executable file</param> /// <param name="username">Username of desired credentials</param> /// <param name="password">Password of desired credentials</param> public static void RunAs(string path, string username, string password) { try { ProcessStartInfo myProcess = new ProcessStartInfo(path); myProcess.UserName = username; myProcess.Password = MakeSecureString(password); myProcess.WorkingDirectory = @"C:\Windows\System32"; myProcess.UseShellExecute = false; Process.Start(myProcess); } catch (Win32Exception w32E) { // The process didn't start. Console.WriteLine(w32E); } } } 

可能是你忘了让只读安全字符串? 我的方法适用于我:

 Process proc = new Process { StartInfo = { CreateNoWindow = true, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardInput = true, FileName = "cmd.exe", UserName = "user", Domain = "myDomain", Password = GetSecureString("Password"), Arguments = "/c ipconfig" } }; proc.Start(); 

GetSecureString()函数:

 public static SecureString GetSecureString(string str) { SecureString secureString = new SecureString(); foreach (char ch in str) { secureString.AppendChar(ch); } secureString.MakeReadOnly(); return secureString; }