在C#运行空间中的其他远程服务器上运行远程Powershell脚本 [英] Run a Remote Powershell Script on a Different Remote Server in a C# Runspace

查看:157
本文介绍了在C#运行空间中的其他远程服务器上运行远程Powershell脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to be able to execute a PS1 script that resides on a remote machine against another remote machine through a C# runspace.

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

To be clear what I mean by this: The service I'm creating resides on server A. It creates a remote runspace to server B using the method below. Through the runspace I'm trying to call a script residing on server C against server B. If it helps, currently server A IS server C, but it's not guaranteed that will always be the case.

这是我用来进行远程呼叫的方法:

Here's the method I'm using to make the remote call:

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脚本.例如:

"remoteScript" is set to the Powershell script I want to run. For example:

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

如果我要在其上运行脚本的远程计算机上,则可以在Powershell控制台中输入以下命令:

If I'm on the remote machine that I want to run the script on, in the powershell console I can just give the following command:

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

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

However this simply refuses to work for me if I try to run it through the c# runspace.

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

If I send in the following as a parameter to "remoteScript":

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

我收到以下错误:

术语'\ remoteserverC \ PathToScript \ Install.ps1'不被识别为cmdlet,函数,脚本文件或可运行程序的名称.检查名称的拼写,或者是否包含路径,请验证路径是否正确,然后重试.

The term '\remoteserverC\PathToScript\Install.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

我尝试过是否使用'&'并带有和不带有参数.我已经可以将直接驻留在远程计算机上的脚本调用为"c:\ ... \ Install.ps1",而不是"\\ remoteserver \ ... \ Install.ps1",但是能够极大地受益于此.直接调用远程脚本.

I've tried with and without '&' and with and without the parameter. I can already call a script that resides directly on the remote machine "c:\...\Install.ps1" instead of "\\remoteserver\...\Install.ps1", but it would be greatly beneficial to be able to call the remote script directly.

我已经搜索了很多Google网页以及关于stackoverflow的网页,但是我没有找到任何有助于克服此问题的信息.任何帮助,将不胜感激!谢谢!

I've searched many many pages in google and here on stackoverflow, but I haven't been able to find anything that helps to overcome this issue. Any help would be appreciated! Thanks!

推荐答案

我从来没有直接使用它,这似乎是一种安全性功能",您无法在远程工作时使用UNC地址访问第三台计算机. .但是,我能够找到一种对我有用的解决方法.

I never did get this to work directly and seems to be a security "feature" that you can't access a third machine using a UNC address while working remotely. I was however able to find a workaround that worked great for me.

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

Instead of trying to call directly to a \\server\share address, I dynamically map a network drive on the machine I'm trying to run the script against to a share on the machine that has the script. (Running remotely from A, map a drive on B to a share on C). Then I call my scripts through that drive and it works like a charm. This string is what I pass in to the RunRemoteScript method above:

"$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是我传入的在用户配置文件中定义的变量.

RemoteServerC is a variable I pass in that is defined in a user config file.

如果有人需要的话,这里的代码与powershell脚本的代码相同(将RemoteServerC替换为您需要先设置的powershell变量,或者只是硬编码:

Here is the same code as just powershell script if anyone needs it (replacing RemoteServerC with a powershell variable you'd need to set before or just hardcode:

$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"驱动器上.

First I set up the object to be able to map the drive. I then check if there is already an "s" drive mapped on the remote machine. If it hasn't I then map the share to the "s" drive on the remote machine using a name and password we set up in active directory to run this service.

我包括了Get-PSDrive命令,因为它似乎迫使Powershell重新加载可用驱动器列表.这似乎只在您第一次尝试在Powershell会话中运行时才有意义(通过c Sharp,我不知道它是否确实有必要,为了安全起见,我将其包括在内).如果使用MapNetworkDrive,则Powershell显然无法在创建的同一会话中识别出驱动器添加.

I included the Get-PSDrive command because it appears to force powershell to reload the list of available drives. This seems to only matter the very first time you try to run this in a powershell session (and through c sharp I don't know if it is truly necessary or not, I included it to be safe). Apparently powershell does not recognize a drive addition in the same session it was created if you use MapNetworkDrive.

这篇关于在C#运行空间中的其他远程服务器上运行远程Powershell脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆