在C#运行空间中的远程服务器上导入Powershell模块

本文关键字:服务器 导入 Powershell 模块 运行 空间 | 更新日期: 2023-09-27 18:28:48

我需要能够通过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中,我已经测试并确保它正在调用C:''''Powelshell''ModuteName目录中的ModuleName.psd1文件。

ModuleName.psd1文件中有一行:

ModuleToProcess = 'ModuleName.psm1'

然而,如果我试图通过c#运行空间运行它,我会遇到一个非常奇怪的错误。

如果我将以下内容作为参数发送到"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",因为在任何模块目录中都找不到有效的模块。

在这一点上,我真的不确定该去哪里,甚至不确定这是否真的可能。我到处寻找,发现了一些看似相关的东西,但从来都不完全一样,而且往往是我已经克服或(据我所知)还没有遇到的问题。任何帮助都将不胜感激!谢谢

在C#运行空间中的远程服务器上导入Powershell模块

我怀疑您需要做两件事:

  1. 使用.psd1文件的绝对路径:否则,将只考虑在$env:PSModulePath中找到的模块(执行加载的脚本在哪里运行并不重要)。

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

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

您可以通过在*.exe.config中为支持的运行时添加一个enty(如果还不存在,请创建powershell.exe.config)来实现这一点。

我测试了这对上述问题的效果。

我解决这个问题已经有一段时间了,所以我对延迟表示歉意。事实证明,解决这个问题相当简单,尽管有点奇怪。

为了解决这个问题,我在ModuleName.psd1中评论道:

ModuleToProcess = 'ModuleName.psm1'

我把它添加到嵌套模块中:

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

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

我已经有一段时间没有解决这个问题了,所以我可能错过了一些小步骤。如果这对你不起作用,让我知道你遇到了什么问题,然后我可以让你知道这是否是我必须做的额外事情。我很确定这就是全部。