2012-06-20 89 views
11

Estoy intentando ejecutar un script de PowerShell desde una aplicación C#. La secuencia de comandos se debe ejecutar en un contexto de usuario especial.Ejecutar PowerShell-Script desde la aplicación C#

He intentado diferentes escenarios algunos están trabajando algunos no:

1. llamada directa desde PowerShell

me han llamado la secuencia de comandos directamente desde una consola PS-que se está ejecutando bajo la correcta credenciales de usuario.

C:\Scripts\GroupNewGroup.ps1 1 

Resultado: funcionando con éxito la secuencia de comandos.

2. desde una aplicación de consola de C#

He llamado a la secuencia de comandos de un # ConsoleApplication C que se inicia bajo las UserCredentials correctas.

Código:

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

Resultado: sin éxito. Y muchas excepciones de "Null-Array".

3. procedente del AC# aplicación de consola - lateral código de hacerse pasar por

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

He llamado a la secuencia de comandos de AC# ConsoleApplication que se inició bajo los UserCredentials correctas y el código contiene suplantación .

Código:

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

Resultados:

  • El término 'Get-Contacto' no se reconoce como el nombre de un cmdlet, función, archivo de script o programa ejecutable. Compruebe la ortografía del nombre , o si se incluyó una ruta, verifique que la ruta sea correcta y intente de nuevo.
  • El término 'C: \ Scripts \ FunctionsObjects.ps1' no se reconoce como el nombre de un cmdlet, función, archivo de script o programa operable. Compruebe la ortografía del nombre, o si se incluyó una ruta, verifique que la ruta sea correcta y vuelva a intentarlo.
  • No hay complementos se han registrado para la versión de Windows PowerShell 2. Microsoft.Office.Server, versión = 14.0.0.0, Culture = neutral, PublicKeyToken = 71e9bce111e9429c
  • System.DirectoryServices.AccountManagement, versión = 4.0. 0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089
  • Excepción llamada ".ctor" con el argumento (s) "1": ". la aplicación web en http://XXXX/websites/Test4/ no se puede conocer Compruebe que ha escrito la URL correctamente.Si la dirección URL da servicio existente contenido, el administrador del sistema puede que tenga que añadir una nueva solicitud de URL mapeo para la aplicación prevista."
  • No se puede llamar a un método en una expresión nula de valor. No se puede índice en una nula matriz.

hasta ahora no hay una respuesta de trabajo

¿alguien sabe por qué hay diferencias y la forma de resolver el problema?

+0

cualquier solución final con el código fuente completo de trabajo? – Kiquenet

+0

Evita llamar a [RunSpace.Open() mientras suplantas] (http://stackoverflow.com/a/22749094/939250). –

Respuesta

6

Tienes se trató Set-ExecutionPolicy Unrestricted

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

Editar:

encontrado esta pequeña joya ... 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 

    ///////////////////////////////////////////////////////////////////////// 

    /// <summary> 
    /// 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. 
    /// </summary> 
    /// <remarks> 
    /// 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 e.g.: 
    /// 
    ///  ... 
    ///  using (new Impersonator("myUsername", "myDomainname", "myPassword")) 
    ///  { 
    ///   ... 
    ///   [code that executes under the new context] 
    ///   ... 
    ///  } 
    ///  ... 
    /// 
    /// Please contact the author Uwe Keim (mailto:[email protected]) 
    /// for questions regarding this class. 
    /// </remarks> 
    public class Impersonator : 
     IDisposable 
    { 
     #region Public methods. 
     // ------------------------------------------------------------------ 

     /// <summary> 
     /// 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. 
     /// </summary> 
     /// <param name="userName">The name of the user to act as.</param> 
     /// <param name="domainName">The domain name of the user to act as.</param> 
     /// <param name="password">The password of the user to act as.</param> 
     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. 
     // ------------------------------------------------------------------ 

     /// <summary> 
     /// Does the actual impersonation. 
     /// </summary> 
     /// <param name="userName">The name of the user to act as.</param> 
     /// <param name="domainName">The domain name of the user to act as.</param> 
     /// <param name="password">The password of the user to act as.</param> 
     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); 
       } 
      } 
     } 

     /// <summary> 
     /// Reverts the impersonation. 
     /// </summary> 
     private void UndoImpersonation() 
     { 
      if (impersonationContext!=null) 
      { 
       impersonationContext.Undo(); 
      } 
     } 

     private WindowsImpersonationContext impersonationContext = null; 

     // ------------------------------------------------------------------ 
     #endregion 
    } 

    ///////////////////////////////////////////////////////////////////////// 
} 
+0

Sí, ya configuré la ExecutionPolicy a mano. Pero lo probé ahora en código pero sin éxito: lo puse en mi código de preguntas. – HW90

0

Several PowerShell cmddlets take a PSCredential object to run using a particular user account. Puede echar un vistazo a este artículo - http://letitknow.wordpress.com/2011/06/20/run-powershell-script-using-another-account/

Así es como se puede crear el objeto de credenciales que contiene el nombre de usuario y la contraseña que desea utilizar:

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

Una vez que tenga la contraseña listo para su uso en una credencial objeto, puede hacer varias cosas, como llamar a Start-Process para iniciar PowerShell.exe, especificar la credencial en el parámetro -Credential, o Invoke-Command para invocar localmente un comando "remoto", specifying the credential in the -Credential parameter, o puede llamar Start-Job para hacer el trabajo como trabajo de fondo, passing the credentials you want into the -Credential parameter.

Ver here, here & en msdn para more information

4

Me acabo de pasar el día en la fijación del mismo por mí mismo.

finalmente fue capaz de hacer que funcione mediante la adición de -Ámbito Proceso a Set-ExecutionPolicy

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

gracias, esto resolvió mi problema después de ver que tenía que usar "Set-ExecutionPolicy sin restricciones" en un centenar de sitios, ¡el proceso del microscopio lo hizo por mí! – Thousand

Cuestiones relacionadas