Import a Powershell Module on a Remote Server in a C# Runspace

情到浓时终转凉″ 提交于 2019-12-14 02:38:09

问题


I need to be able to import a module that resides on a remote machine through a C# runspace.

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 import a module on server 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. 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.

Inside the ModuleName.psd1 file is the line:

ModuleToProcess = 'ModuleName.psm1'

However I get a very weird error if I try to run it through the c# runspace.

If I send in the following as a parameter to "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.

The module does exist in one of the "$env:PSModulePath locations and does show up if you run:

get-module -listAvailable

I have also tried putting in the fully qualified path to the ModuleName.psm1 file inside the psd1 file. When I do that (or what was suggested by x0n below) I get almost the exact same error:

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.

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!


回答1:


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).

  2. Ensure you can load the remote script. The default or RemoteSigned execution policies will block remote scripts unless signed.




回答2:


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.

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.

I tested this works great for the above issue.




回答3:


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:

ModuleToProcess = 'ModuleName.psm1'

And I Added it to NestedModules instead:

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.



来源:https://stackoverflow.com/questions/9831617/import-a-powershell-module-on-a-remote-server-in-a-c-sharp-runspace

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!