Импорт модуля Powershell на удаленный сервер в пространстве выполнения C # - PullRequest
1 голос
/ 23 марта 2012

Мне нужно иметь возможность импортировать модуль, находящийся на удаленной машине, через пространство выполнения 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 и набор файлов сценариев, которые находятся в C: \\ Powershell \ ModuleName на удаленном сервере (сервер B), и я проверил и убедился, что он вызывает файл ModuleName.psd1 в каталоге C: \\ Powershell \ ModuleName.

Внутри файла ModuleName.psd1 находится строка:

ModuleToProcess = 'ModuleName.psm1'

Однако я получаю очень странную ошибку, если пытаюсь запустить ее через пространство выполнения c #.

Если я отправлю следующее в качестве параметра для «remoteScript»:

"Import-Module Modulename"

Я получаю следующую ошибку:

System.Management.Automation.RemoteException: модуль для обработки 'ModuleName.psm1', указанный в поле 'ModuleToProcess' манифеста модуля 'C: \ Powershell \ ModuleName \ ModuleName.psd1', не был обработан, так как действительный модуль не был находится в любом модульном каталоге.

Модуль существует в одном из местоположений "$ env: PSModulePath" и появляется, если вы запустите:

get-module -listAvailable

Я также попытался ввести полный путь к файлу ModuleName.psm1 внутри файла psd1. Когда я делаю это (или то, что было предложено в x0n ниже), я получаю почти такую ​​же ошибку:

Модуль для обработки 'C: \ Powershell \ ModuleName \ ModuleName.psm1', указанный в поле 'ModuleToProcess' манифеста модуля 'C: \ Powershell \ ModuleName \ ModuleName.psd1', не был обработан, так как не найден действительный модуль в любом каталоге модулей.

На данный момент я действительно не уверен, куда идти или даже если это действительно возможно. Я искал повсюду и нашел некоторые вещи, которые кажутся связанными, но никогда не были совершенно одинаковыми и имели тенденцию быть проблемами, которые я уже преодолел или просто еще (насколько я знаю) не сталкивался. Любая помощь будет оценена! Спасибо!

Ответы [ 3 ]

1 голос
/ 09 мая 2012

Я обнаружил, что если ваш модуль построен на более поздней версии .net (скажем, .net 4.0), и вы пытались загрузить его в powershell 2.0 (на основе .net 3.5), это может быть проблемой .. чтобы обойти этоДля этого вам необходимо убедиться, что загрузка PowerShell или вызывающего процесса загружена в .net 4.0 clr.

. Это можно сделать, добавив запись для поддерживаемой среды выполнения в * .exe.config (создайте powershell.exe.config, еслиодин уже не существует) в зависимости от обстоятельств.

Я проверил это прекрасно работает для вышеуказанной проблемы.

1 голос
/ 24 мая 2012

Прошло немного времени, так как я решил это, поэтому я прошу прощения за задержку. Решение для этого на самом деле оказалось довольно простым, хотя и немного странным.

Чтобы это исправить, в ModuleName.psd1 я закомментировал:

ModuleToProcess = 'ModuleName.psm1'

И вместо этого я добавил его в NestedModules:

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

Честно говоря, я не совсем уверен, почему это позволило модулю успешно загрузиться, но у меня это сработало.

Прошло немного времени с тех пор, как я решил это, так что, возможно, здесь есть какой-то крошечный шаг. Если это не работает для вас, дайте мне знать, с какой проблемой вы столкнулись, и тогда я могу сообщить вам, если это было чем-то дополнительным, что мне пришлось сделать. Я вполне уверен, что это все было.

1 голос
/ 25 апреля 2012

Я подозреваю, что вам нужно сделать две вещи:

  1. Используйте абсолютный путь к файлу .psd1: в противном случае будут рассматриваться только модули, найденные в $env:PSModulePath (не имеет значения, где выполняется скрипт, выполняющий загрузку).

  2. Убедитесь, что вы можете загрузить удаленный скрипт. Политики выполнения по умолчанию или RemoteSigned будут блокировать удаленные сценарии, если они не подписаны.

...