Conéctese a Microsoft Exchange PowerShell dentro de C #
Estoy tratando de conectarme a Powershell remoto desde la aplicación WinForms de C # .NET. Mi objetivo es crear mi propia versión de Microsoft PowerShell ISE. Por lo tanto, necesito una forma de ejecutar PowerShell Scripts desde mi aplicación en máquinas remotas. Creé un par de métodos y lo probé en una máquina local desde mi aplicación. Si yo no usoWSManConnectionInfo y useutilizando (Runspace remoteRunspace = RunspaceFactory.CreateRunspace ()) Puedo ejecutar scripts localmente como si fuera verdadero PowerShell (pequeños scripts, uso de variables, datos de salida usandopie, Florida, hago muchas otras cosas que suelo hacer con powershell. El problema comienza cuando agregoWSManConnectionInfo y apuntarlo a mi servidor de Exchange en lugar de usar una conexión local. Parece que es capaz de ejecutar cosas básicas como "get-buzón", pero tan pronto como trato de canalizar cosas, uso algunas capacidades de secuencias de comandos como $ variables se rompe diciendo que no es compatible.
Del mismo modo tengo que deshabilitarpowershell.AddCommand ("out-string"); cuando no lo usa localmente.
Se produjo una excepción no controlada del tipo 'System.Management.Automation.RemoteException' en System.Management.Automation.dll.
Información adicional: El término 'Out-String' no se reconoce como el nombre de un cmdlet, función, archivo de script o programa operable. Verifique la ortografía del nombre, o si se incluyó una ruta, verifique que la ruta sea correcta e intente nuevamente.
El mismo error no aparece si no fuerzo la conexión remota, sino que simplemente lo hago localmente. Parece que elSchemaUri hace que sea muy estricto ejecutar solo comandos básicos. Vi otros ejemplos en los que la gente usaba información muy directa como nosotros:
powershell.AddCommand("Get-Users");
powershell.AddParameter("ResultSize", count);
Pero con ese enfoque tendría que definir muchas opciones posibles y no quiero pasar por definir parámetros y otras cosas. Simplemente me gustaría cargar "script" y ejecutarlo como en la ventana de PowerShell. Aquí hay un ejemplo de lo que uso ahora.
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();
}
¿Algún consejo sobre por qué sucede esto y cómo solucionarlo para que se comporte de la misma manera? He visto muchos blogs comoesta pero definir cada comando simple no tiene sentido para mí. También vi una opción para crear una conexión local y luego ejecutarconexión remota dentro de ese pero ese debe ser el último recurso ya que depende de muchos otros factores.