[英]Connect to Microsoft Exchange PowerShell within C#
我正在嘗試從C#.NET WinForms應用程序連接到遠程PowerShell。 我的目標是創建自己的Microsoft PowerShell ISE版本。 所以我需要一種從遠程計算機上的應用程序執行PowerShell腳本的方法。 我已經創建了幾種方法,並在我的應用程序中在本地計算機上進行了測試。 如果我不使用WSManConnectionInfo並使用(Runspace remoteRunspace = RunspaceFactory.CreateRunspace())我可以在本地執行腳本,就好像它是真的powershell(小腳本,變量的使用,輸出數據使用ft , fl ,做了很多我通常用powershell做的其他事情。當我添加WSManConnectionInfo並將其指向我的Exchange Server而不是使用本地連接時,問題就出現了。似乎它能夠執行像“get-mailbox”這樣的基本內容但是只要我嘗試管道東西,使用一些腳本功能,如$ variables它打破說它不受支持。
同樣,我必須禁用powershell.AddCommand(“out-string”); 什么時候不在本地使用它。
System.Management.Automation.dll中發生了未處理的“System.Management.Automation.RemoteException”類型異常。
附加信息:術語“Out-String”不被識別為cmdlet,函數,腳本文件或可操作程序的名稱。 檢查名稱的拼寫,或者如果包含路徑,請驗證路徑是否正確,然后重試。
如果我不強制遠程連接但只是在本地執行,則不會出現相同的錯誤。 似乎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();
}
關於為什么會發生這種情況的任何建議,並解決如何讓它以相同的方式運行? 我見過很多像這樣的博客,但定義每個簡單的命令對我來說都沒有意義。 我還看到了創建本地連接然后在其中執行遠程連接的選項,但這必須是最后的手段,因為它依賴於多個其他因素。
Exchange 2010通過PowerShell提供的管理體驗已從Local更改為Remote。 [...]只有交換cmdlet才能在此遠程處理方案中運行, 您將無法運行大多數PowerShell cmdlet 。 [...]是的,這確實意味着您將無法在遠程運行空間中運行Where-Object和.PS1腳本等cmdlet 。
這是一個限制嗎? 我不這么認為。 我們可以通過創建一個新的Session並導入它來輕松解決它 。
所以你需要做這樣的事情 :
PSCredential creds = new PSCredential(userName, securePassword);
System.Uri uri = new Uri("http://Exchange-Server/powershell?serializationLevel=Full");
Runspace runspace = RunspaceFactory.CreateRunspace();
PowerShell powershell = PowerShell.Create();
PSCommand command = new PSCommand();
command.AddCommand("New-PSSession");
command.AddParameter("ConfigurationName", "Microsoft.Exchange");
command.AddParameter("ConnectionUri", uri);
command.AddParameter("Credential", creds);
command.AddParameter("Authentication", "Default");
powershell.Commands = command;
runspace.Open(); powershell.Runspace = runspace;
Collection<PSSession> result = powershell.Invoke<PSSession>();
powershell = PowerShell.Create();
command = new PSCommand();
command.AddCommand("Set-Variable");
command.AddParameter("Name", "ra");
command.AddParameter("Value", result[0]);
powershell.Commands = command;
powershell.Runspace = runspace;
powershell.Invoke();
powershell = PowerShell.Create();
command = new PSCommand();
command.AddScript("Import-PSSession -Session $ra");
powershell.Commands = command;
powershell.Runspace = runspace;
powershell.Invoke();
# now you can use remote PS like it's local one
從Exchange Server 2010開始,您需要使用遠程PowerShell會話,而不是直接添加交換PowerShell管理單元(由於在Exchange 2010中使用RBAC而不是ACL)。 因此,您需要創建新的PowerShell會話(使用New-PSSession),然后導入它(使用Import-PSSession)。 您可以使用這樣的代碼來執行遠程PowerShell命令:
void ExecutePowerShellUsingRemotimg()
{
RunspaceConfiguration runspaceConfig = RunspaceConfiguration.Create();
PSSnapInException snapInException = null;
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfig);
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
string serverFqdn = "FQDN of you server";
pipeline.Commands.AddScript(string.Format("$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://{0}/PowerShell/ -Authentication Kerberos", serverFqdn));
pipeline.Commands.AddScript("Import-PSSession $Session");
pipeline.Commands.AddScript("your PowerShell script text");
pipeline.Commands.Add("Out-String");
Collection<PSObject> results = pipeline.Invoke();
runspace.Close();
StringBuilder sb = new StringBuilder();
if (pipeline.Error != null && pipeline.Error.Count > 0)
{
// Read errors
succeeded = false;
Collection<object> errors = pipeline.Error.ReadToEnd();
foreach (object error in errors)
sb.Append(error.ToString());
}
else
{
// Read output
foreach (PSObject obj in results)
sb.Append(obj.ToString());
}
runspace.Dispose();
pipeline.Dispose();
}
看起來你遇到了雙跳認證問題,我在嘗試這個問題時遇到了同樣的問題。
搞亂之后,我最終在本地安裝了Exchange Powershell插件,並使用它們遠程連接到Exchange服務器。
粗略的例子:
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
PSSnapInInfo info = runspaceConfiguration.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.Admin", out snapInException);
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
using (PowerShell powershell = PowerShell.Create())
{
powershell.Runspace = runspace;
string script = string.Format(@"Get-Mailbox -Server {0} -Identity {1}", serverName, identity);
powershell.AddScript(script);
powershell.Invoke();
// Do something with the output
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.