如何在C#中以其他用户身份执行PowerShell脚本且避免远程连接?
问题:在C#中以其他用户身份本地执行PowerShell脚本(无需远程连接)
我现在需要在C#里以另一个用户的身份执行PowerShell脚本,当前用默认方式执行的代码是可以正常运行的:
using (PowerShell PowerShellInstance = PowerShell.Create()) { PowerShellInstance.AddScript(RemoveUser); PowerShellInstance.AddParameter("GID", GID); try { PowerShellInstance.Invoke(); return true; } catch (Exception e) { Debug.WriteLine(e.StackTrace); } return false; }
我尝试用WSManConnectionInfo传入其他用户凭证时,触发了PSRemotingTransportException,提示连接本地服务器失败,但我不想启用远程连接。如果不使用WSManConnectionInfo直接创建Runspace,代码是可以正常运行的:
using (Runspace runspace = RunspaceFactory.CreateRunspace()) { runspace.Open(); using (PowerShell PowerShellInstance = PowerShell.Create()) { PowerShellInstance.Runspace = runspace; PowerShellInstance.AddScript(RemoveUser); PowerShellInstance.AddParameter("GID", GID); try { PowerShellInstance.Invoke(); return true; } catch (Exception e) { Debug.WriteLine(e.StackTrace); } return false; } }
请问有没有办法只添加其他用户凭证,在不使用远程连接的情况下执行该脚本?
解决方案:通过独立进程以目标用户身份执行
没问题,我来帮你搞定这个!首先得明确:直接在当前进程的Runspace里切换用户是做不到的——Runspace依赖当前进程的安全上下文,没法直接跨用户。而你之前用的WSManConnectionInfo是专门给远程PowerShell会话用的,所以才会要求启用远程连接,完全不适合本地场景。
正确的思路是启动一个全新的PowerShell进程,用目标用户的凭证来运行,这样既不需要远程连接,又能切换身份。下面是具体的实现代码:
using System.Diagnostics; using System.Security; using System.Management.Automation; public bool ExecutePowerShellAsAnotherUser(string removeUserScript, string gid, string targetUsername, SecureString targetPassword) { // 构建PowerShell执行命令:把脚本和参数整合进去 string psCommand = $"-Command \"& {{ {removeUserScript} -GID {gid} }}\""; // 配置进程启动信息 ProcessStartInfo startInfo = new ProcessStartInfo { FileName = "powershell.exe", Arguments = psCommand, UseShellExecute = false, // 必须设为false才能指定凭证,这是关键 Credentials = new System.Net.NetworkCredential(targetUsername, targetPassword), RedirectStandardOutput = true, // 可选:捕获输出用于调试 RedirectStandardError = true, // 可选:捕获错误信息 CreateNoWindow = true // 可选:不弹出PowerShell窗口 }; try { using (Process psProcess = Process.Start(startInfo)) { // 读取输出和错误(如果需要调试的话) string output = psProcess.StandardOutput.ReadToEnd(); string error = psProcess.StandardError.ReadToEnd(); psProcess.WaitForExit(); // 如果有错误输出,记录下来 if (!string.IsNullOrEmpty(error)) { Debug.WriteLine($"PowerShell执行出错: {error}"); return false; } // 进程退出码为0表示执行成功 return psProcess.ExitCode == 0; } } catch (Exception ex) { Debug.WriteLine($"启动PowerShell进程失败: {ex.StackTrace}"); return false; } }
关键说明:
UseShellExecute = false:这个属性必须设为false,否则无法指定Credentials——这是Windows进程启动的规则,shell启动模式下不支持跨用户凭证。- 脚本传递方式:如果你的
RemoveUser是外部脚本文件(不是字符串形式的脚本),可以把-Command换成-File,比如$"-File \"C:\\Scripts\\RemoveUser.ps1\" -GID {gid}"。 - 输出捕获:重定向标准输出和错误可以帮你排查执行过程中的问题,如果你不需要调试,也可以去掉这部分代码。
这种方式完全是本地运行,不需要启用任何PowerShell远程服务,完美符合你的需求!
内容的提问来源于stack exchange,提问作者M. Ozn
相关产品推荐
相关产品推荐

