Импорт модуля Powershell на удаленный сервер в пространстве выполнения C #

Мне нужно иметь возможность импортировать модуль, который находится на удаленном компьютере, через пространство выполнения 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', не был обработан, поскольку ни в одном из модулей не был найден допустимый модуль каталог.

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


person Arangarx    schedule 22.03.2012    source источник
comment
Попробуйте использовать ModuleToProcess = Join-Path $ psscriptroot 'modulename.psm1' в PSD1.   -  person x0n    schedule 23.03.2012
comment
Спасибо, x0n, но я все равно получаю сообщение об ошибке. Я добавил еще несколько деталей в исходный пост.   -  person Arangarx    schedule 27.03.2012
comment
Можно ли импортировать модуль через удаленное взаимодействие в командной строке?   -  person Adam Driscoll    schedule 19.04.2012
comment
какое-либо окончательное решение по этому поводу с полным исходным кодом? Что такое PsHostImplementation?   -  person Kiquenet    schedule 24.05.2012
comment
@AdamDriscoll Прошу прощения, я честно не могу вспомнить, работал ли импорт через ручной удаленный сеанс или нет. Я думаю, что это сработало, но я больше не уверен. Если вам нужно узнать о проблеме, которую вы пытаетесь решить, я могу попробовать ее протестировать (с тех пор я решил проблему, поэтому мне придется быть осторожным при тестировании).   -  person Arangarx    schedule 24.05.2012
comment
@Kiquenet Да, см. Мое решение ниже. Кроме того, если вам нужно, у меня была аналогичная проблема: stackoverflow.com/questions/9828569/.   -  person Arangarx    schedule 24.05.2012
comment
@Kiquenet Что касается вашего вопроса о PSHostImplementation: этот метод, который я предоставил в этом вопросе, используется для запуска множества различных скриптов, и многие из этих скриптов имеют вызовы функций PowerShell, которые ожидают, что для вывода будет консоль или какой-либо другой пользовательский интерфейс. Мне пришлось создать собственную реализацию PsHostImplementation, чтобы обрабатывать эти выходные вызовы, такие как Write-Host, Write-Progress и т. Д. Если вам нужна моя полная реализация PsHostImplementation, я могу ее предоставить. Если вы планируете запускать только сценарии, не имеющие вывода пользовательского интерфейса, вам, вероятно, не нужно это реализовывать.   -  person Arangarx    schedule 24.05.2012
comment
@Arangarx, спасибо большое. Было бы интересно получить окончательный исходный код RunRemoteScript, и полная реализация PsHostImplementation будет полезна. Я новичок в использовании PS, и теперь я тестирую PS для развертывания   -  person Kiquenet    schedule 29.05.2012


Ответы (3)


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

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

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

person Richard    schedule 25.04.2012
comment
Спасибо за ответ. Оба упомянутых вами шага определенно должны быть выполнены кем-либо (я убедился, что это было сделано в рамках моего устранения неполадок), но ни один из них не стал последней проблемой. Я опубликую свое окончательное решение. - person Arangarx; 24.05.2012

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

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

I tested this works great for the above issue.

person Vinay    schedule 09.05.2012
comment
Я уже решил проблему (я просто еще не успел опубликовать решение, моя проблема), но это звучит как что-то отличное, чтобы просто попробовать, если проблема возникнет снова. Спасибо! - person Arangarx; 24.05.2012

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

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

ModuleToProcess = 'ModuleName.psm1'

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

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

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

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

person Arangarx    schedule 24.05.2012