Conecte-se ao Microsoft Exchange PowerShell em C #
Estou tentando conectar-me ao PowerShell remoto do aplicativo C # .NET WinForms. Meu objetivo é criar minha própria versão do Microsoft PowerShell ISE. Então, eu preciso de uma maneira de executar scripts do PowerShell do meu aplicativo em máquinas remotas. Eu criei alguns métodos e testei na máquina local do meu aplicativo. Se eu não usarWSManConnectionInfo E useusing (Runspace remoteRunspace = RunspaceFactory.CreateRunspace ()) Eu posso executar scripts localmente como se fosse um verdadeiro PowerShell (pequenos scripts, uso de variáveis, saída de dados usandoft, fl, faça muitas outras coisas que costumo fazer com o PowerShell. O problema começa quando adicionoWSManConnectionInfo e aponte para o meu Exchange Server em vez de usar a conexão local. Parece que é capaz de executar coisas básicas como "get-mailbox", mas assim que eu tentar canalizar as coisas, use alguns recursos de script como $ variáveis que ele quebra dizendo que não há suporte.
Da mesma forma eu tenho que desativarpowershell.AddCommand ("cadeia de caracteres"); quando não estiver usando localmente.
Ocorreu uma exceção sem tratamento do tipo 'System.Management.Automation.RemoteException' no System.Management.Automation.dll.
Informações adicionais: O termo 'String de saída' não é reconhecido como o nome de um cmdlet, função, arquivo de script ou programa operável. Verifique a ortografia do nome ou, se um caminho foi incluído, verifique se o caminho está correto e tente novamente.
O mesmo erro não aparece se eu não forçar a conexão remota, mas simplesmente fazê-lo localmente. Parece que oSchemaUri está tornando muito rigoroso executar apenas comandos básicos. Vi outros exemplos em que pessoas que usam informações muito diretas como nós:
powershell.AddCommand("Get-Users");
powershell.AddParameter("ResultSize", count);
Mas com essa abordagem, eu teria que definir muitas opções possíveis e não quero definir parâmetros e outras coisas. Eu simplesmente gostaria de carregar o "script" e executá-lo como na janela do PowerShell. Aqui está um exemplo do que eu uso agora.
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();
}
Algum conselho sobre por que isso está acontecendo e a solução alternativa de como fazê-lo se comportar da mesma maneira? Eu já vi muitos blogs comoesta mas definir cada comando simples não faz sentido para mim. Eu também vi uma opção para criar conexão local e depois executarconexão remota dentro desse mas esse deve ser o último recurso, pois depende de vários outros fatores.