【发布时间】:2016-07-14 05:03:03
【问题描述】:
我正在尝试从 C# .NET WinForms 应用程序连接到远程 powershell。我的目标是创建我自己的 Microsoft PowerShell ISE 版本。所以我需要一种在远程机器上从我的应用程序执行 PowerShell 脚本的方法。我已经创建了几种方法,并从我的应用程序在本地机器上对其进行了测试。如果我不使用 WSManConnectionInfo 并使用 using (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();
}
关于为什么会发生这种情况以及如何解决如何让它以相同方式运行的任何建议?我看过很多像this 这样的博客,但是定义每个简单的命令对我来说没有意义。我还看到了创建本地连接然后执行remote connection within that 的选项,但这必须是最后的手段,因为它依赖于多个其他因素。
【问题讨论】:
-
你的
serverUrl是什么样的?
标签: c# .net powershell exchange-server