Подключитесь к Microsoft Exchange PowerShell в C #
Я пытаюсь подключиться к удаленному PowerShell из приложения C # .NET WinForms. Моя цель - создать собственную версию Microsoft PowerShell ISE. Поэтому мне нужен способ выполнения сценариев PowerShell из моего приложения на удаленных компьютерах. Я создал пару методов и проверил их на локальном компьютере из моего приложения. Если я не используюWSManConnectionInfo и использоватьusing (Runspace remoteRunspace = RunspaceFactory.CreateRunspace ()) я могу выполнять сценарии локально, как если бы это был настоящий PowerShell (небольшие сценарии, использование переменных, вывод данных с использованиемфут, ФлоридаЯ делаю много других вещей, которые я обычно делаю с PowerShell. Проблема начинается, когда я добавляюWSManConnectionInfo и укажите его на моем сервере Exchange вместо использования локального подключения. Кажется, что он способен выполнять такие базовые вещи, как «get-mailbox», но как только я пытаюсь передать данные, используйте некоторые возможности сценариев, такие как $ variable, которые он ломает, говоря, что он не поддерживается.
Точно так же я должен отключитьpowershell.AddCommand ( "из-строка"); когда не используете его локально.
Произошло необработанное исключение типа «System.Management.Automation.RemoteException» в System.Management.Automation.dll.
Дополнительная информация: термин «Out-String» не распознается как имя командлета, функции, файла сценария или работоспособной программы. Проверьте правильность написания имени или, если путь был указан, проверьте правильность пути и повторите попытку.
Та же самая ошибка не появляется, если я не форсирую удаленное соединение, а просто делаю это локально. Кажется, чтоSchemaUri делает очень строгим выполнение только основных команд. Я видел другие примеры, когда люди использовали очень прямую информацию, такую как мы:
powershell.AddCommand("Get-Users");
powershell.AddParameter("ResultSize", count);
Но при таком подходе мне пришлось бы определить множество возможных вариантов, и я не хочу переходить к определению параметров и прочего. Я просто хотел бы загрузить «скрипт» и выполнить его так же, как в окне PowerShell. Вот пример того, что я использую сейчас.
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();
}
Любой совет о том, почему это происходит, и как обойти это так? Я видел много блогов, какэтот но определение каждой простой команды не имеет смысла для меня. Я также видел возможность создать локальное соединение, а затем выполнитьудаленное соединение в этом но это должно быть последним средством, так как оно зависит от множества других факторов.