PowerShell - Как импортировать модуль в пространство выполнения


Я пытаюсь создать командлет на C #. Код выглядит примерно так:

[Cmdlet(VerbsCommon.Get, "HeapSummary")]
public class Get_HeapSummary : Cmdlet
{
    protected override void ProcessRecord()
    {
        RunspaceConfiguration config = RunspaceConfiguration.Create();
        Runspace myRs = RunspaceFactory.CreateRunspace(config);
        myRs.Open();

        RunspaceInvoke scriptInvoker = new RunspaceInvoke(myRs);
        scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted");

        Pipeline pipeline = myRs.CreatePipeline();
        pipeline.Commands.Add(@"Import-Module G:\PowerShell\PowerDbg.psm1");
        //...
        pipeline.Invoke();

        Collection<PSObject> psObjects = pipeline.Invoke();
        foreach (var psObject in psObjects)
        {
            WriteObject(psObject);
        }
    }
}

Но попытка выполнить этот CmdLet в PowerShell дает мне эту ошибку: Термин Import-Module не распознается как имя командлета. Та же команда в PowerShell не дает мне этой ошибки. Если вместо этого я выполню Get-Command, я увижу, что Invoke-Module отображается как CmdLet.

Есть ли способ выполнить «Импорт-модуль» в пространстве выполнения?

Спасибо!


person Absolom    schedule 07.06.2011    source источник


Ответы (2)


Есть два способа программно импортировать модули, но сначала я обращусь к вашему методу. Ваша строка pipeline.Commands.Add("...") должна добавлять только команду, а не команду И параметр. Параметр добавляется отдельно:

# argument is a positional parameter
pipeline.Commands.Add("Import-Module");
var command = pipeline.Commands[0];
command.Parameters.Add("Name", @"G:\PowerShell\PowerDbg.psm1")

Вышеупомянутый конвейерный API немного неудобен в использовании и неофициально считается устаревшим для многих применений, хотя он лежит в основе многих API более высокого уровня. Лучший способ сделать это в PowerShell v2 или выше - использовать System.Management.Automation.PowerShell Type и его свободный API:

# if Create() is invoked, a runspace is created for you
var ps = PowerShell.Create(myRS);
ps.Commands.AddCommand("Import-Module").AddArgument(@"g:\...\PowerDbg.psm1")
ps.Invoke()

Другой способ использования последнего метода - это предварительная загрузка модулей с помощью InitialSessionState, что позволяет избежать необходимости явно заполнять пространство выполнения с помощью Import-Module.

InitialSessionState initial = InitialSessionState.CreateDefault();
    initialSession.ImportPSModule(new[] { modulePathOrModuleName1, ... });
    Runspace runspace = RunspaceFactory.CreateRunspace(initial);
    runspace.Open();
    RunspaceInvoke invoker = new RunspaceInvoke(runspace);
    Collection<PSObject> results = invoker.Invoke("...");

Надеюсь это поможет.

person x0n    schedule 07.06.2011
comment
Спасибо! Но метод Add () возвращает void. Я предполагаю, что вам нужно использовать объект Command, добавить к нему параметр и передать его методу Add. Вы говорите о двух способах сделать это программно, каков второй способ? - person Absolom; 07.06.2011
comment
Я также узнал, что если вы получаете исключение «Ошибка проверки авторизации» при попытке импортировать модуль, убедитесь, что ваш файл .psm1 сохранен в UTF8, а не в ASCII. - person Absolom; 07.06.2011
comment
@ x0n Упс .. Ссылка мертвая (?) - person CB.; 27.11.2012
comment
обновление блога сломало ссылки - вздох. - person x0n; 28.11.2012
comment
Я просто смотрю на это сейчас, я не вижу возможности, чтобы любой из этих фрагментов кода был действительным кодом. Мне не удалось заставить их работать. Add возвращает void, поэтому вызов AddArgument для этого приведет к исключению. -1, этот ответ не имеет смысла - person tnw; 11.06.2013
comment
Думаю, когда я ответил на это, я смешал две модели из v1 и v2 в отношении Command и PSCommand API. Сейчас я обновляю ответ, чтобы он был правильным (извините) и соответствовал версии v2 +. - person x0n; 12.06.2013

Самый простой способ сделать это - использовать метод AddScript(). Ты можешь сделать:

pipeline.AddScript("Import-Module moduleName").Invoke();

Если вы хотите добавить еще один импорт в ту же строку

pipeline.AddScript("Import-Module moduleName \n Import-Module moduleName2").Invoke();

Необязательно .Invoke(). После того, как вы добавите сценарий в конвейер, вы можете добавить дополнительные сценарии и вызвать их позже.

pipeline.AddScript("Import-Module moduleName");
pipeline.AddCommand("pwd");
pipeline.Invoke();

Для получения дополнительной информации посетите Официальный сайт Microsoft

person Venkatesh Dharavath    schedule 19.05.2020