繁体   English   中英

在C#Runspace中的远程服务器上导入Powershell模块

[英]Import a Powershell Module on a Remote Server in a C# Runspace

我需要能够通过C#运行空间导入驻留在远程计算机上的模块。

要清楚我的意思是:我正在创建的服务驻留在服务器A上。它使用下面的方法为服务器B创建一个远程运行空间。 通过运行空间,我试图在服务器B上导入一个模块。

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

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

"Import-Module Modulename;CustomCommand-FromModule -parameter(s) -ErrorAction stop"

该模块没有打包在一起它是一个psd1,psm1,以及一堆脚本文件,它们位于远程服务器(服务器B)上的C:\\\\ Powershell \\ ModuleName中,我已经测试并确保它正在调用ModuleName。 ps:1文件位于C:\\\\ Powershell \\ ModuleName目录中。

在ModuleName.psd1文件中是行:

ModuleToProcess = 'ModuleName.psm1'

但是,如果我尝试通过c#runspace运行它,我会收到一个非常奇怪的错误。

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

"Import-Module Modulename"

我收到以下错误:

System.Management.Automation.RemoteException:未处理模块清单'C:\\ Powershell \\ ModuleName \\ ModuleName.psd1'的字段'ModuleToProcess'中列出的处理'ModuleName.psm1'的模块,因为没有找到任何有效模块模块目录。

该模块确实存在于“$ env:PSModulePath位置之一中,如果运行则会显示:

get-module -listAvailable

我还尝试在psd1文件中输入ModuleName.psm1文件的完全限定路径。 当我这样做(或下面的x0n建议)我得到几乎完全相同的错误:

未处理模块清单'C:\\ Powershell \\ ModuleName \\ ModuleName.psd1'字段'ModuleToProcess'中列出的'C:\\ Powershell \\ ModuleName \\ ModuleName.psm1'模块,因为在任何模块中都找不到有效模块目录。

在这一点上,我真的不确定去哪里,即使这实际上是可能的。 我到处搜索,发现了一些似乎相关的东西,但是从来没有完全相同,往往是我已经克服过的问题,或者根本没有(据我所知)尚未遇到的问题。 任何帮助,将不胜感激! 谢谢!

我怀疑你需要做两件事:

  1. 使用.psd1文件的绝对路径:否则只会考虑在$env:PSModulePath找到的模块(重要的不在于加载脚本运行的位置)。

  2. 确保您可以加载远程脚本。 除非签名,否则默认或RemoteSigned执行策略将阻止远程脚本。

我发现,如果你的模块是在一个较新的.net运行时(比如.net 4.0)上构建的,并且你试图在powershell 2.0(基于.net 3.5)中加载它,这可能是一个问题..解决这个问题,你需要确保在.net 4.0 clr中加载PowerShell或调用进程。

您可以通过在* .exe.config中添加对支持的运行时的enty(如果不存在,则创建powershell.exe.config)来执行此操作。

我测试过它对上述问题很有用。

自从我解决了这个问题以来,我已经有一点点了,所以我为延迟道歉。 事实证明这个解决方案相当简单,虽然有点奇怪。

为了解决这个问题,在ModuleName.psd1中我注释掉了:

ModuleToProcess = 'ModuleName.psm1'

我将其添加到NestedModules中:

NestedModules = Join-Path $psscriptroot 'ModuleName.psm1'

坦率地说,我不确定为什么这会让模块成功加载,但它对我有用。

我解决了这个问题已经有一段时间了,所以我可能会错过这里的一小步。 如果这对您不起作用,请告诉我您遇到的问题,然后我可以告诉您这是否是我必须做的其他事情。 我相当肯定这就是全部。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM