Verbindung mit Microsoft Exchange PowerShell in C #

Ich versuche, eine Verbindung mit der Remote-Powershell über die C # .NET WinForms-App herzustellen. Mein Ziel ist es, eine eigene Version von Microsoft PowerShell ISE zu erstellen. Daher brauche ich eine Möglichkeit, PowerShell-Skripte von meiner App auf Remote-Computern auszuführen. Ich habe einige Methoden erstellt und sie auf einem lokalen Computer mit meiner App getestet. Wenn ich kein @ benut WSManConnectionInfo und benutzeusing (Runspace remoteRunspace = RunspaceFactory.CreateRunspace ()) Ich kann Skripte lokal ausführen, als ob es wahres Powershell wäre (kleine Skripte, Verwendung von Variablen, Ausgabedaten mit ft, fl, mache viele andere Dinge, die ich normalerweise mit Powershell mache. Problem beginnt, wenn ich @ hinzufü WSManConnectionInfo und zeige es auf meinen Exchange Server, anstatt eine lokale Verbindung zu verwenden. Es scheint, dass es in der Lage ist, grundlegende Dinge wie "get-mailbox" auszuführen, aber sobald ich versuche, Dinge zu leiten, benutze ich einige Skriptfunktionen wie $ variables, die kaputt gehen und sagen, dass sie nicht unterstützt werden.

Ähnlich muss ich deaktivieren powershell.AddCommand ("out-string"); wenn es nicht lokal verwendet wird.

In System.Management.Automation.dll ist eine nicht behandelte Ausnahme vom Typ 'System.Management.Automation.RemoteException' aufgetreten.

Zusätzliche Informationen: Der Begriff "Out-String" wird nicht als Name eines Cmdlets, einer Funktion, einer Skriptdatei oder eines ausführbaren Programms erkannt. Überprüfen Sie die Schreibweise des Namens, oder überprüfen Sie, ob der Pfad korrekt ist, und versuchen Sie es erneut.

Der gleiche Fehler tritt nicht auf, wenn ich keine Remote-Verbindung erzwinge, sondern nur lokal. Es scheint wie das SchemaUri macht es sehr streng, nur grundlegende Befehle auszuführen. Ich habe andere Beispiele gesehen, in denen Leute sehr direkte Informationen wie uns verwendeten:

powershell.AddCommand("Get-Users");
powershell.AddParameter("ResultSize", count);

Aber mit diesem Ansatz müsste ich viele mögliche Optionen definieren und ich möchte nicht Parameter und andere Dinge definieren. Ich möchte einfach "script" laden und wie im PowerShell-Fenster ausführen. Hier ist ein Beispiel für das, was ich jetzt verwende.

    public static WSManConnectionInfo PowerShellConnectionInformation(string serverUrl, PSCredential psCredentials)
    {
        var connectionInfo = new WSManConnectionInfo(new Uri(serverUrl), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", psCredentials);
        //var connectionInfo = new WSManConnectionInfo(new Uri(serverUrl), "http://schemas.microsoft.com/powershell", psCredentials);
        connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Basic;
        connectionInfo.SkipCACheck = true;
        connectionInfo.SkipCNCheck = true;
        connectionInfo.SkipRevocationCheck = true;
        connectionInfo.MaximumConnectionRedirectionCount = 5;
        connectionInfo.OperationTimeout = 150000;
        return connectionInfo;
    }
    public static PSCredential SecurePassword(string login, string password)
    {
        SecureString ssLoginPassword = new SecureString();
        foreach (char x in password) { ssLoginPassword.AppendChar(x); }
        return new PSCredential(login, ssLoginPassword);
    }
    public static string RunScriptPs(WSManConnectionInfo connectionInfo, string scriptText)
    {
        StringBuilder stringBuilder = new StringBuilder();
        // Create a remote runspace using the connection information.
        //using (Runspace remoteRunspace = RunspaceFactory.CreateRunspace())
        using (Runspace remoteRunspace = RunspaceFactory.CreateRunspace(connectionInfo))
        {
            // Establish the connection by calling the Open() method to open the runspace. 
            // The OpenTimeout value set previously will be applied while establishing 
            // the connection. Establishing a remote connection involves sending and 
            // receiving some data, so the OperationTimeout will also play a role in this process.
            remoteRunspace.Open();
            // Create a PowerShell object to run commands in the remote runspace.
            using (PowerShell powershell = PowerShell.Create())
            {
                powershell.Runspace = remoteRunspace;
                powershell.AddScript(scriptText);
                //powershell.AddCommand("out-string");
                powershell.Commands.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
                Collection<PSObject> results = powershell.Invoke();

                foreach (PSObject result in results) {
                        stringBuilder.AppendLine(result.ToString());
                }

            }
            // Close the connection. Call the Close() method to close the remote 
            // runspace. The Dispose() method (called by using primitive) will call 
            // the Close() method if it is not already called.
            remoteRunspace.Close();
        }

        // convert the script result into a single string
        return stringBuilder.ToString();
    }

Hier gibt es Ratschläge, warum dies geschieht, und eine Problemumgehung, wie Sie dafür sorgen können, dass es sich genauso verhält? Ich habe viele Blogs wie @ gesehDie aber jedes einfache Kommando zu definieren macht für mich keinen Sinn. Ich sah auch eine Option zum Herstellen einer lokalen Verbindung und Ausführen von Fernverbindung innerhalb dieses aber das muss der letzte Ausweg sein, da es auf mehreren anderen Faktoren beruht.

Antworten auf die Frage(6)

Ihre Antwort auf die Frage