从C#应用程序运行PowerShell脚本

我正在尝试从ac#应用程序执行PowerShell脚本。 该脚本必须在特殊的usercontext下执行。

我尝试过不同的场景,有些人正在努力:

1.来自PowerShell的直接调用

我直接从ps-console调用脚本,该控制台在正确的usercredentials下运行。

C:\Scripts\GroupNewGroup.ps1 1 

结果:成功运行脚本。

2.来自ac#console应用程序

我从ac #consoleapplication调用了脚本,该脚本是在正确的usercredentials下启动的。

码:

  string cmdArg = "C:\\Scripts\\GroupNewGroup.ps1 1" Runspace runspace = RunspaceFactory.CreateRunspace(); runspace.ApartmentState = System.Threading.ApartmentState.STA; runspace.ThreadOptions = PSThreadOptions.UseCurrentThread; runspace.Open(); Pipeline pipeline = runspace.CreatePipeline(); pipeline.Commands.AddScript(cmdArg); pipeline.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output); Collection results = pipeline.Invoke(); var error = pipeline.Error.ReadToEnd(); runspace.Close(); if (error.Count >= 1) { string errors = ""; foreach (var Error in error) { errors = errors + " " + Error.ToString(); } } 

结果:没有成功。 还有很多“Null-Array”例外。

3.来自ac#console应用程序 – 代码端冒充

( http://platinumdogs.me/2008/10/30/net-c-impersonation-with-network-credentials )

我从ac #consoleapplication调用了脚本,该脚本是在正确的usercredentials下启动的,代码包含模拟。

码:

 using (new Impersonator("Administrator2", "domain", "testPW")) { using (RunspaceInvoke invoker = new RunspaceInvoke()) { invoker.Invoke("Set-ExecutionPolicy Unrestricted"); } string cmdArg = "C:\\Scripts\\GroupNewGroup.ps1 1"; Runspace runspace = RunspaceFactory.CreateRunspace(); runspace.ApartmentState = System.Threading.ApartmentState.STA; runspace.ThreadOptions = PSThreadOptions.UseCurrentThread; runspace.Open(); Pipeline pipeline = runspace.CreatePipeline(); pipeline.Commands.AddScript(cmdArg); pipeline.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output); Collection results = pipeline.Invoke(); var error = pipeline.Error.ReadToEnd(); runspace.Close(); if (error.Count >= 1) { string errors = ""; foreach (var Error in error) { errors = errors + " " + Error.ToString(); } } } 

结果:

  • 术语“Get-Contact”不被识别为cmdlet,函数,脚本文件或可操作程序的名称。 检查名称的拼写,或者如果包含路径,请validation路径是否正确,然后重试。
  • 术语“C:\ Scripts \ FunctionsObjects.ps1”未被识别为cmdlet,函数,脚本文件或可操作程序的名称。 检查名称的拼写,或者如果包含路径,请validation路径是否正确,然后重试。
  • 没有为Windows PowerShell版本2注册管理单元.Microsoft.Office.Server,Version = 14.0.0.0,Culture = neutral,PublicKeyToken = 71e9bce111e9429c
  • System.DirectoryServices.AccountManagement,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089
  • 调用带有“1”参数的“.ctor”的exception:“无法找到http://XXXX/websites/Test4/的Web应用程序。validation您是否正确输入了URL。如果URL应该服务在现有内容中,系统管理员可能需要向目标应用程序添加新的请求URL映射。“
  • 您不能在空值表达式上调用方法。 无法索引到空数组。

到目前为止,没有可行的答案

有谁知道为什么存在差异以及如何解决问题?

您是否尝试过Set-ExecutionPolicy Unrestricted

 using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) ) { using (RunspaceInvoke invoker = new RunspaceInvoke()) { invoker.Invoke("Set-ExecutionPolicy Unrestricted"); } } 

编辑:

发现这个小gem…… http://www.codeproject.com/Articles/10090/A-small-C-Class-for-impersonating-a-User

 namespace Tools { #region Using directives. // ---------------------------------------------------------------------- using System; using System.Security.Principal; using System.Runtime.InteropServices; using System.ComponentModel; // ---------------------------------------------------------------------- #endregion ///////////////////////////////////////////////////////////////////////// ///  /// Impersonation of a user. Allows to execute code under another /// user context. /// Please note that the account that instantiates the Impersonator class /// needs to have the 'Act as part of operating system' privilege set. ///  ///  /// This class is based on the information in the Microsoft knowledge base /// article http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306158 /// /// Encapsulate an instance into a using-directive like eg: /// /// ... /// using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) ) /// { /// ... /// [code that executes under the new context] /// ... /// } /// ... /// /// Please contact the author Uwe Keim (mailto:uwe.keim@zeta-software.de) /// for questions regarding this class. ///  public class Impersonator : IDisposable { #region Public methods. // ------------------------------------------------------------------ ///  /// Constructor. Starts the impersonation with the given credentials. /// Please note that the account that instantiates the Impersonator class /// needs to have the 'Act as part of operating system' privilege set. ///  /// The name of the user to act as. /// The domain name of the user to act as. /// The password of the user to act as. public Impersonator( string userName, string domainName, string password ) { ImpersonateValidUser( userName, domainName, password ); } // ------------------------------------------------------------------ #endregion #region IDisposable member. // ------------------------------------------------------------------ public void Dispose() { UndoImpersonation(); } // ------------------------------------------------------------------ #endregion #region P/Invoke. // ------------------------------------------------------------------ [DllImport("advapi32.dll", SetLastError=true)] private static extern int LogonUser( string lpszUserName, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] private static extern int DuplicateToken( IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken); [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] private static extern bool RevertToSelf(); [DllImport("kernel32.dll", CharSet=CharSet.Auto)] private static extern bool CloseHandle( IntPtr handle); private const int LOGON32_LOGON_INTERACTIVE = 2; private const int LOGON32_PROVIDER_DEFAULT = 0; // ------------------------------------------------------------------ #endregion #region Private member. // ------------------------------------------------------------------ ///  /// Does the actual impersonation. ///  /// The name of the user to act as. /// The domain name of the user to act as. /// The password of the user to act as. private void ImpersonateValidUser( string userName, string domain, string password ) { WindowsIdentity tempWindowsIdentity = null; IntPtr token = IntPtr.Zero; IntPtr tokenDuplicate = IntPtr.Zero; try { if ( RevertToSelf() ) { if ( LogonUser( userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token ) != 0 ) { if ( DuplicateToken( token, 2, ref tokenDuplicate ) != 0 ) { tempWindowsIdentity = new WindowsIdentity( tokenDuplicate ); impersonationContext = tempWindowsIdentity.Impersonate(); } else { throw new Win32Exception( Marshal.GetLastWin32Error() ); } } else { throw new Win32Exception( Marshal.GetLastWin32Error() ); } } else { throw new Win32Exception( Marshal.GetLastWin32Error() ); } } finally { if ( token!= IntPtr.Zero ) { CloseHandle( token ); } if ( tokenDuplicate!=IntPtr.Zero ) { CloseHandle( tokenDuplicate ); } } } ///  /// Reverts the impersonation. ///  private void UndoImpersonation() { if ( impersonationContext!=null ) { impersonationContext.Undo(); } } private WindowsImpersonationContext impersonationContext = null; // ------------------------------------------------------------------ #endregion } ///////////////////////////////////////////////////////////////////////// } 

我只是花了一天时间为自己解决这个问题。

我终于通过将-Scope Process添加到Set-ExecutionPolicy来使其工作

 invoker.Invoke("Set-ExecutionPolicy Unrestricted -Scope Process"); 

Several PowerShell cmddlets take a PSCredential object to run using a particular user account 。 可以看看这篇文章 – http://letitknow.wordpress.com/2011/06/20/run-powershell-script-using-another-account/

以下是如何创建包含要使用的用户名和密码的Credential对象:

 $username = 'domain\user' $password = 'something' $cred = New-Object System.Management.Automation.PSCredential -ArgumentList @($username,(ConvertTo-SecureString -String $password -AsPlainText -Force)) 

准备好在凭证对象中使用密码后,您可以执行许多操作,例如调用Start-Process以启动PowerShell.exe,在-Credential参数中指定凭据,或调用Invoke-Command以调用“ remote“命令在本地, specifying the credential in the -Credential parameter ,或者您可以调用Start-Job来作为后台作业, passing the credentials you want into the -Credential parameter

有关更多信息 ,请参见此处 , 此处和msdn