我正在尝试从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提供的管理体验已从本地转移到远程。[...]只有交换cmdlet在此远程处理方案中将起作用,您将无法运行大多数powershell cmdlet。[...]是的,这确实意味着您将无法在Remote Runspace中运行cmdlet(如Where-Object和.PS1脚本)。
有限制吗?我不这么认为。通过创建一个新的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
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句