2012-06-20 16 views
11

Ich versuche, ein PowerShell-Skript aus einer C# -Anwendung auszuführen. Das Skript muss unter einem speziellen Benutzerkontext ausgeführt werden.Ausführen von PowerShell-Skript aus C# -Anwendung

Ich habe versucht, verschiedene Szenarien einige arbeiten einige nicht:

1. direkten Aufruf von Powershell

Ich habe das Skript direkt von einer ps-Konsole genannt, die unter dem richtigen laufen Benutzerberechtigungen.

C:\Scripts\GroupNewGroup.ps1 1 

Ergebnis: Beende das Skript ausgeführt wird.

2. von einer C# Konsolenanwendung

ich das Skript von einem C# Consoleapplication genannt habe, die unter dem richtigen UserCredentials gestartet wird.

Code:

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

Ergebnis: Kein Erfolg. Und viele "Null-Array" -Ausnahmen.

3. von C# Konsolenanwendung - Code auf dieser Seite Identitätswechsel

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

Ich habe das Skript von C# Consoleapplication genannt, die unter den richtigen UserCredentials gestartet wird und der Code enthält Identitätswechsel .

Code:

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

Ergebnisse:

  • Der Begriff 'Get-Contact' wird nicht als Name eines Cmdlets erkannt, Funktion, Skriptdatei oder ein geschriebenes Programm. Überprüfen Sie die Schreibweise des Namens oder, wenn ein Pfad enthalten war, überprüfen Sie, ob der Pfad korrekt ist, und versuchen Sie es erneut mit .
  • Der Begriff 'C: \ Scripts \ FunctionsObjects.ps1' wird nicht als Name eines Cmdlet, einer Funktion, einer Skriptdatei oder eines ausführbaren Programms erkannt. Überprüfen Sie die Schreibweise des Namens, oder wenn ein Pfad enthalten war, überprüfen Sie, ob der Pfad korrekt ist, und versuchen Sie es erneut.
  • keine Snap-In ist für Windows Powershell Version 2. Microsoft.Office.Server, Version = 14.0.0.0, Culture = neutral, PublicKeyToken = 71e9bce111e9429c
  • System.DirectoryServices.AccountManagement, Version = 4.0 registriert. 0,0, Culture = neutral, PublicKeyToken = b77a5c561934e089
  • Ausnahme calling ".ctor" mit "1" Argument (e):. „die Web-Anwendung bei http://XXXX/websites/Test4/ konnte nicht gefunden werden Stellen Sie sicher, dass Sie die URL korrekt eingegeben haben.Wenn die URL Inhalt bestehende dienen sollte, kann der Systemadministrator brauchen eine neue URL Zuordnung der beabsichtigten Anwendung hinzuzufügen.“
  • Sie keine Methode auf einem Null-wertigen Ausdruck aufrufen können. Kann nicht Index in eine null Array.

bis jetzt gibt es keine Arbeits Antwort

weiß jemand, warum es Unterschiede und wie das Problem zu lösen?

+0

eine endgültige Lösung mit vollständigem Source Code zu arbeiten? – Kiquenet

+0

Vermeiden Sie den Aufruf von [RunSpace.Open() bei der Identitätsübernahme] (http://StackOverflow.com/a/22749094/939250). –

Antwort

6

Have Sie versucht Set-ExecutionPolicy Unrestricted

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

Edit:

dieses kleine Juwel gefunden ... 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

Ja, ich habe die ExecutionPolicy bereits manuell gesetzt. Aber ich habe es jetzt in Code ausprobiert, aber ohne Erfolg: Ich habe es in meinen Fragencode eingefügt. – HW90

0

Several PowerShell cmddlets take a PSCredential object to run using a particular user account. Kann in diesem Artikel einen Blick - http://letitknow.wordpress.com/2011/06/20/run-powershell-script-using-another-account/

Hier ist, wie Sie das Credential-Objekt verwenden, um den Benutzernamen und das Passwort, das Sie wollen enthält erstellen:

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

Sobald Sie das Passwort bereit für den Einsatz in einem Berechtigungsnachweis haben B. Start-Prozess starten, PowerShell.exe starten, den Berechtigungsnachweis im Parameter -Credential angeben oder Invoke-Command, um lokal einen "Remote" -Befehl aufzurufen, specifying the credential in the -Credential parameter, oder Sie können anrufen Start-Job, um die Arbeit als Hintergrundjob zu erledigen, passing the credentials you want into the -Credential parameter.

Siehe here, here & in msdn für more information

4

Ich verbrachte den Tag dieses für mich fixiert.

konnte ich es endlich durch Zugabe von -Scope Prozess funktioniert auf Set-ExecutionPolicy

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

danke, dies löste mein Problem, nachdem ich sah, dass ich "Set-ExecutionPolicy Unrestricted" auf hundert von Websites verwenden musste, hat der Scope Process es für mich getan! – Thousand

Verwandte Themen