“尝试使用模拟在远程计算机上运行PowerShell脚本时,不允许”请求注册表访问“

这是我第一次尝试从C#应用程序执行PowerShell脚本。 我正在使用PowerShell,因为我需要从远程计算机上执行的.exe输出。 我能够使用WMI在远程计算机上运行.exe,但是我无法获得所需的输出。

无论如何,过去一天左右我一直在这里,我已经浏览了网络,并在SO处寻找类似的问题,但似乎无法弄清楚问题。 我正在尝试从远程计算机上的.NET 4.0应用程序运行一个简单的PowerShell命令。 当我以管理员身份运行Visual Studio 2013时,以下代码执行正常:

PowerShell ps = PowerShell.Create(); ps.AddScript(@"Invoke-Command {c:\path\to\file.exe /p} -computername "); results = ps.Invoke(); 

我得到了预期的结果。 但是,当我作为非管理员运行VS时,代码似乎执行正常(没有例外),但我没有得到任何结果。 环顾四周之后,我添加了如下假冒:

 using (var impersonator = new Impersonator("username", "domain", "password")) { PowerShell ps = PowerShell.Create(); ps.AddScript(@"Invoke-Command {c:\path\to\file.exe /p} -computername "); results = ps.Invoke(); } 

但是,ps.Invoke方法开始抛出System.Security.SecurityException – “不允许请求的注册表访问”。 这是堆栈跟踪:

在System.Management的System.Management.Automation.ModuleIntrinsics.GetExpandedEnvironmentVariable(String name,EnvironmentVariableTarget target)的System.Environment.GetEnvironmentVariable(String variable,EnvironmentVariableTarget target)上的Microsoft.Win32.RegistryKey.OpenSubKey(String name,Boolean writable)。 System.Management.Automation.ExecutionContext..ctor上System.Management.Automation.ExecutionContext.InitializeCommon(AutomationEngine engine,PSHost hostInterface)的System.Management.Automation.ModuleIntrinsics..ctor(ExecutionContext context)中的Automation.ModuleIntrinsics.SetModulePath() System.Management.Automation.Automation.Runspaces.LocalRunspace.DoOpenHelper()在System.Management上的System.Management.Automation.AutomationEngine..ctor(PSHost hostInterface,RunspaceConfiguration runspaceConfiguration,InitialSessionState iss)中的(AutomationEngine引擎,PSHost hostInterface,RunspaceConfiguration runspaceConfiguration)。 Automation.Runspaces.LocalRunspace.OpenHelper(布尔同步 所有)System.Management.Automation.Runspaces.RunspaceBase.CoreOpen(Boolean syncCall)at System.Management.Automation.Runspaces.RunspaceBase.Open()at System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse,Boolean isSync) )在System.Management.Automation.PowerShell.CoreInvoke [TInput,TOutput]的System.Management.Automation.PowerShell.CoreInvokeHelper [TInput,TOutput](PSDataCollection 1 input, PSDataCollection 1输出,PSInvocationSettings设置)中(PSDataCollection 1 input, PSDataCollection 1)系统上的System.Management.Automation.PowerShell.Invoke(IEnumerable输入,PSInvocationSettings设置)中的System.Management.Automation.PowerShell.CoreInvoke [TOutput](IEnumerable输入,PSDataCollection`1输出,PSInvocationSettings设置)中的输出,PSInvocationSettings设置)。 Management.Automation.PowerShell.Invoke()

我不知道为什么我在运行的管理员帐户可以访问注册表时获得SecurityException,不仅在我的机器上,而且在整个企业的机器上。 我甚至不确定它在我的机器或远程机器上获得exception的注册表。

在模拟之前为PowerShell对象创建基础RunSpace:

 PowerShell ps = PowerShell.Create(); Runspace runspace = RunspaceFactory.CreateRunspace(); runspace.Open(); powerShell.Runspace = runspace; using (var impersonator = new Impersonator("username", "domain", "password")) { ps.AddScript(@"Invoke-Command {c:\path\to\file.exe /p} -computername "); results = ps.Invoke(); } runspace.Close() 

RunSpace对象封装了OS环境以执行脚本。 被访问的密钥可能是HKCU \ Environment。 这就是我在使用Perfmon时看到的。 RunSpace可能使用HKCU \ Environment来填充$ PATH等变量。

因此,在创建RunSpace时,您希望当前用户可以访问HKCU \ Environment。

拉动模拟块的RunSpace.Open在别处被提到作为避免注册表访问问题的黑客 。 但是,仅创建PowerShell对象并不能保证调用Runspace.Open()。