2012-06-20 11 views
11

Próbuję wykonać skrypt PowerShell z aplikacji C#. Skrypt musi zostać wykonany w specjalnym tekście użytkownika.Uruchom PowerShell-Script z aplikacji C#

próbowałem różne scenariusze niektórzy pracują niektóre nie:

1. Bezpośrednie połączenie z PowerShell

Zadzwoniłem skrypt bezpośrednio z ps-konsoli, który jest uruchomiony pod prawidłowa Poświadczenia użytkownika.

C:\Scripts\GroupNewGroup.ps1 1 

Wynik: pomyślnie uruchomiony skrypt.

2. z aplikacji konsoli C#

Mam nazwie skrypt z C# consoleapplication który rozpoczął się pod poprawnych usercredentials.

Kod:

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

Wynik: bez powodzenia. I wiele wyjątków "Null-Array".

3. z aC# konsoli aplikacji - kod strony podszywania

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

Zadzwoniłem skrypt z aC# consoleapplication który rozpoczął się pod poprawnych usercredentials a kod zawiera personifikacji .

Kod:

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

Wyniki:

  • Termin 'Get-Contact' nie jest rozpoznawana jako nazwy apletu polecenia, funkcji, pliku skryptu lub program wykonywalny. Sprawdź pisownię nazwy lub, jeśli ścieżka została dołączona, sprawdź, czy ścieżka jest poprawna i spróbuj ponownie.
  • Termin „C: \ Scripts \ FunctionsObjects.ps1” nie jest uznawane jako nazwy z apletu polecenia, funkcji skryptu lub program wykonywalny. Sprawdź pisownię nazwy lub, jeśli ścieżka została uwzględniona, sprawdź, czy ścieżka jest poprawna i spróbuj ponownie.
  • Brak przystawki zostały zarejestrowane dla Windows PowerShell w wersji 2. Microsoft.Office.Server, Version = 14.0.0.0, Culture = neutral, TokenKluczaPublicznego = 71e9bce111e9429c
  • System.DirectoryServices.AccountManagement, Version = 4,0. 0,0, Culture = neutral, TokenKluczaPublicznego = b77a5c561934e089
  • Wyjątek wywołujący „.ctor” z «1» argumentu (ów):. „Aplikacja internetowa na http://XXXX/websites/Test4/ nie można znaleźć Sprawdź, czy poprawnie wpisany URL.Jeśli adres URL należy obsługujących istniejące zawartości, administrator systemu może być konieczne, aby dodać nowy adres URL żądania mapowanie do zamierzonego zastosowania.”
  • Nie można wywołać metodę na wyrażeniu zerowej wycenione. Nie można Indeks do null tablicą.

do tej pory nie ma odpowiedzi roboczego

+0

każdy ostateczne rozwiązanie z pełnym kodem źródłowym działa? – Kiquenet

+0

Unikaj wywoływania [RunSpace.Open() podczas podszywania się] (http://stackoverflow.com/a/22749094/939250). –

Odpowiedz

6

Have Czy ktoś wie dlaczego istnieją różnice i jak rozwiązać ten problem? Czy próbowałeś Set-ExecutionPolicy Unrestricted

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

EDIT:

znaleźliśmy ten mały klejnot ... 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

Tak Ustawię ExecutionPolicy ręcznie. Ale próbowałem tego teraz w kodzie, ale bez powodzenia: umieściłem go w moim kodzie pytań. – HW90

0

Several PowerShell cmddlets take a PSCredential object to run using a particular user account. Mogą rzucić okiem na ten artykuł - http://letitknow.wordpress.com/2011/06/20/run-powershell-script-using-another-account/

Oto jak można utworzyć Credential obiekt zawierający nazwę użytkownika i hasło, którego chcesz użyć:

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

Gdy masz hasło gotowe do wykorzystania w poświadczeniu obiekt, możesz zrobić wiele rzeczy, takich jak wywołanie procesu Start, aby uruchomić PowerShell.exe, określając poświadczenia w parametrze -Credential, lub Invoke-Command, aby wywołać lokalnie polecenie "remote", specifying the credential in the -Credential parameter, lub możesz zadzwonić Start-Job, aby wykonać pracę jako zadanie w tle, passing the credentials you want into the -Credential parameter.

Zobacz here, here & w msdn dla more information

4

Właśnie spędziłem dzień ustalenia to dla siebie.

I w końcu udało mi się zrobić to działa dodając -Zakres proces Do ustawiania ExecutionPolicy

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

dziękuję, to rozwiązało mój problem po tym, jak zobaczyłem, że musiałem użyć "Set-ExecutionPolicy Unststricted" na setkach stron, proces -Scope zrobił to za mnie! – Thousand