简体   繁体   English

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

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

I need to be able to import a module that resides on a remote machine through a C# runspace. 我需要能够通过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. 要清楚我的意思是:我正在创建的服务驻留在服务器A上。它使用下面的方法为服务器B创建一个远程运行空间。 Through the runspace I'm trying to import a module on server B. 通过运行空间,我试图在服务器B上导入一个模块。

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" is set to the Powershell script I want to run. “remoteScript”设置为我想要运行的Powershell脚本。 For example: 例如:

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

The module is not packedged together it's a psd1, psm1, and a bunch of script files that reside in C:\\\\Powershell\\ModuleName on the remote server (server B) and I have tested and made sure that it is calling the ModuleName.psd1 file in the C:\\\\Powershell\\ModuleName directory. 该模块没有打包在一起它是一个psd1,psm1,以及一堆脚本文件,它们位于远程服务器(服务器B)上的C:\\\\ Powershell \\ ModuleName中,我已经测试并确保它正在调用ModuleName。 ps:1文件位于C:\\\\ Powershell \\ ModuleName目录中。

Inside the ModuleName.psd1 file is the line: 在ModuleName.psd1文件中是行:

ModuleToProcess = 'ModuleName.psm1'

However I get a very weird error if I try to run it through the c# runspace. 但是,如果我尝试通过c#runspace运行它,我会收到一个非常奇怪的错误。

If I send in the following as a parameter to "remoteScript": 如果我将以下内容作为参数发送到“remoteScript”:

"Import-Module Modulename"

I get the following error: 我收到以下错误:

System.Management.Automation.RemoteException: The module to process 'ModuleName.psm1', listed in field 'ModuleToProcess' of module manifest 'C:\\Powershell\\ModuleName\\ModuleName.psd1' was not processed because no valid module was found in any module directory. System.Management.Automation.RemoteException:未处理模块清单'C:\\ Powershell \\ ModuleName \\ ModuleName.psd1'的字段'ModuleToProcess'中列出的处理'ModuleName.psm1'的模块,因为没有找到任何有效模块模块目录。

The module does exist in one of the "$env:PSModulePath locations and does show up if you run: 该模块确实存在于“$ env:PSModulePath位置之一中,如果运行则会显示:

get-module -listAvailable

I have also tried putting in the fully qualified path to the ModuleName.psm1 file inside the psd1 file. 我还尝试在psd1文件中输入ModuleName.psm1文件的完全限定路径。 When I do that (or what was suggested by x0n below) I get almost the exact same error: 当我这样做(或下面的x0n建议)我得到几乎完全相同的错误:

The module to process 'C:\\Powershell\\ModuleName\\ModuleName.psm1', listed in field 'ModuleToProcess' of module manifest 'C:\\Powershell\\ModuleName\\ModuleName.psd1' was not processed because no valid module was found in any module directory. 未处理模块清单'C:\\ Powershell \\ ModuleName \\ ModuleName.psd1'字段'ModuleToProcess'中列出的'C:\\ Powershell \\ ModuleName \\ ModuleName.psm1'模块,因为在任何模块中都找不到有效模块目录。

At this point I'm really not sure where to go or even if this is actually possible. 在这一点上,我真的不确定去哪里,即使这实际上是可能的。 I've searched everywhere and found some things that seem related, but were never quite the same and tended to be problems I've already overcome or just haven't (to my knowledge) come up against yet. 我到处搜索,发现了一些似乎相关的东西,但是从来没有完全相同,往往是我已经克服过的问题,或者根本没有(据我所知)尚未遇到的问题。 Any help would be appreciated! 任何帮助,将不胜感激! Thanks! 谢谢!

I suspect you need to do two things: 我怀疑你需要做两件事:

  1. Use the absolute path to the .psd1 file: otherwise only modules found in $env:PSModulePath will be considered (it matters not where the script doing the loading is running). 使用.psd1文件的绝对路径:否则只会考虑在$env:PSModulePath找到的模块(重要的不在于加载脚本运行的位置)。

  2. Ensure you can load the remote script. 确保您可以加载远程脚本。 The default or RemoteSigned execution policies will block remote scripts unless signed. 除非签名,否则默认或RemoteSigned执行策略将阻止远程脚本。

I found that if your module is built on a newer .net runtime(say .net 4.0) and you were trying to load it in powershell 2.0(based on .net 3.5) this can be an issue..to work around this, you need to make sure to load powershell or calling process in .net 4.0 clr. 我发现,如果你的模块是在一个较新的.net运行时(比如.net 4.0)上构建的,并且你试图在powershell 2.0(基于.net 3.5)中加载它,这可能是一个问题..解决这个问题,你需要确保在.net 4.0 clr中加载PowerShell或调用进程。

You can do this by adding an enty for supported runtime in *.exe.config( Create powershell.exe.config if one does not exist already) as applicable. 您可以通过在* .exe.config中添加对支持的运行时的enty(如果不存在,则创建powershell.exe.config)来执行此操作。

I tested this works great for the above issue. 我测试过它对上述问题很有用。

It's been a little bit since I solved this so I apologize for the delay. 自从我解决了这个问题以来,我已经有一点点了,所以我为延迟道歉。 The solution for this actually turned out to be rather easy, though a little weird. 事实证明这个解决方案相当简单,虽然有点奇怪。

To fix this, in ModuleName.psd1 I commented out: 为了解决这个问题,在ModuleName.psd1中我注释掉了:

ModuleToProcess = 'ModuleName.psm1'

And I Added it to NestedModules instead: 我将其添加到NestedModules中:

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

Frankly, I'm not exactly sure why this let the module load successfully, but it worked for me. 坦率地说,我不确定为什么这会让模块成功加载,但它对我有用。

It has been a little while since I solved this so it is possible there is some tiny step I missed here. 我解决了这个问题已经有一段时间了,所以我可能会错过这里的一小步。 If this doesn't work for you, let me know what problem you run in to and then I can let you know if it was something additional I had to do. 如果这对您不起作用,请告诉我您遇到的问题,然后我可以告诉您这是否是我必须做的其他事情。 I am fairly certain this was all though. 我相当肯定这就是全部。

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

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