我需要能够通过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:\\ Powershell \ ModuleName目录中的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'模块,因为未找到有效模块在任何模块目录中。
此时我真的不知道该去哪里,即使这实际上是可行的。我到处搜索,发现了一些似乎相关的东西,但是从来没有完全相同,往往是我已经克服过的问题,或者根本没有(据我所知)尚未遇到的问题。任何帮助,将不胜感激!谢谢!
答案 0 :(得分:1)
我怀疑你需要做两件事:
使用.psd1
文件的绝对路径:否则只会考虑$env:PSModulePath
中找到的模块(重要的不是加载脚本运行的位置)。
确保您可以加载远程脚本。除非签名,否则默认或RemoteSigned
执行策略将阻止远程脚本。
答案 1 :(得分:1)
我发现如果你的模块是在较新的.net运行时(比如.net 4.0)上构建的,并且你试图在powershell 2.0(基于.net 3.5)中加载它,那么这可能是一个问题。这个,您需要确保在.net 4.0 clr。
中加载PowerShell或调用进程您可以通过在* .exe.config中添加enty来支持运行时(如果已经存在,则创建powershell.exe.config)。
我测试过,这对上述问题非常有用。
答案 2 :(得分:1)
自从我解决了这个问题以来,这已经有点了,所以我为延迟道歉。对此的解决方案实际上变得相当容易,虽然有点奇怪。
要解决此问题,请在ModuleName.psd1中注释掉:
ModuleToProcess = 'ModuleName.psm1'
我将其添加到NestedModules中:
NestedModules = Join-Path $psscriptroot 'ModuleName.psm1'
坦率地说,我不确定为什么这会让模块成功加载,但它对我有用。
我解决了这个问题已经有一段时间了,所以有可能我在这里错过了一小步。如果这对您不起作用,请告诉我您遇到的问题,然后我可以告诉您这是否是我必须做的其他事情。我很确定这就是全部。