在C#Runspace中的不同远程服务器上运行远程Powershell脚本

时间:2012-03-22 18:48:28

标签: c# powershell runspace

我需要能够通过C#运行空间执行远程计算机上驻留在另一台远程计算机上的PS1脚本。

要清楚我的意思是:我正在创建的服务驻留在服务器A上。它使用下面的方法为服务器B创建一个远程运行空间。通过运行空间,我试图在服务器C上调用驻留在服务器B上的脚本。如果它有帮助,那么当前服务器是一个IS服务器C,但不能保证始终如此。

以下是我用来拨打远程电话的方法:

internal Collection<PSObject> RunRemoteScript(string remoteScript, string remoteServer, string scriptName, out bool scriptSuccessful)
    {
        bool isLocal = (remoteServer == "localhost" || remoteServer == "127.0.0.1" || remoteServer == Environment.MachineName);

        WSManConnectionInfo connectionInfo = null;

        if (!isLocal)
        {
            connectionInfo = new WSManConnectionInfo(new Uri("http://" + remoteServer + ":5985"));
        }

        PsHostImplementation myHost = new PsHostImplementation(scriptName);

        using (Runspace remoteRunspace = (isLocal ? RunspaceFactory.CreateRunspace(myHost) : RunspaceFactory.CreateRunspace(myHost, connectionInfo)))
        {
            remoteRunspace.Open();
            using (PowerShell powershell = PowerShell.Create())
            {
                powershell.Runspace = remoteRunspace;

                Pipeline pipeline = remoteRunspace.CreatePipeline();

                pipeline.Commands.AddScript(remoteScript);

                Collection<PSObject> results = pipeline.Invoke();

                remoteRunspace.Close();

                scriptSuccessful = myHost.ScriptSuccessful;
                return results;
            }
        }
    }

“remoteScript”设置为我要运行的Powershell脚本。例如:

"& \"\\\\remoteserveraddress\\PathToScript\\Install.ps1\" -Parameter;Import-Module Modulename;CustomCommand-FromModule -parameter(s) -ErrorAction stop"

如果我在远程计算机上运行脚本,请在powershell控制台中给出以下命令:

& "\\remoteserverC\PathToScript\Install.ps1" -Parameter

然而,如果我尝试通过c#运行空间运行它,这对我来说就是拒绝工作。

如果我将以下内容作为参数发送到“remoteScript”:

"& \"\\\\remoteserverC\\PathToScript\\Install.ps1\" -Parameter"

我收到以下错误:

  

术语“\ remoteserverC \ PathToScript \ Install.ps1”未被识别为cmdlet,函数,脚本文件或可操作程序的名称。检查名称的拼写,或者如果包含路径,请验证路径是否正确,然后重试。

我尝试过和没有'&amp;'有和没有参数。我已经可以调用一个直接驻留在远程机器上的脚本“c:\ ... \ Install.ps1”而不是“\\ remoteserver \ ... \ Install.ps1”,但能够做到这一点非常有益直接调用远程脚本。

我在google上搜索了很多页面,在这里搜索了stackoverflow,但是我找不到任何有助于克服这个问题的内容。任何帮助,将不胜感激!谢谢!

1 个答案:

答案 0 :(得分:2)

我从来没有让它直接工作,似乎是一个安全“功能”,你无法在远程工作时使用UNC地址访问第三台机器。然而,我能够找到一种对我有用的解决方法。

我没有尝试直接调用\\ server \ share地址,而是动态地将我正在尝试运行脚本的计算机上的网络驱动器映射到具有该脚本的计算机上的共享。 (从A远程运行,将B上的驱动器映射到C上的共享)。然后我通过该驱动器调用我的脚本,它就像一个魅力。我将这个字符串传递给上面的RunRemoteScript方法:

"$net = new-object -ComObject WScript.Network;" +
"if(!($net.EnumNetworkDrives() -contains \"S:\"))" +
    "{Write-Host \"S: Drive Not Currently Mapped. Mapping to \\\\" + RemoteServerC + "\\Share.\";" +
    "$net.MapNetWorkDrive(\"S:\",\"\\\\" + RemoteServerC + "\\Share\",$false,\"username\",\"password\")};" +
"Get-PSDrive | Write-Verbose;" +
"& \"S:\\PathToScript\\Install.ps1\" -noPrompt;"

RemoteServerC是我传入的变量,在用户配置文件中定义。

以下是与powershell脚本相同的代码,如果有人需要它(用之前需要设置的PowerShell变量替换RemoteServerC或只是硬编码:

$net = new-object -ComObject WScript.Network
if(!($net.EnumNetworkDrives() -contains "S:"))
{  Write-Host "S: Drive Not Currently Mapped. Mapping to \\remoteserverC\Share."
   $net.MapNetWorkDrive("S:","\\remoteserverC\Share",$false,"username","password")
}
Get-PSDrive | Write-Verbose
& "S:\\PathToScript\\Install.ps1\" -noPrompt;"

首先,我设置对象以便能够映射驱动器。然后我检查是否已经在远程计算机上映射了“s”驱动器。如果没有,那么我使用我们在活动目录中设置的名称和密码将共享映射到远程计算机上的“s”驱动器以运行此服务。

我包含了Get-PSDrive命令,因为它似乎强制PowerShell重新加载可用驱动器列表。这似乎只是你第一次尝试在PowerShell会话中运行它时(并且通过c sharp我不知道它是否真的有必要,我把它包括在内是安全的)。显然,如果您使用MapNetworkDrive,PowerShell无法识别它在同一会话中添加的驱动器。