Размещенный PowerShell не может видеть командлеты в той же сборке
Я пытаюсь запустить сценарии PowerShell из моего кода C#, который будет использовать пользовательские командлеты из сборки, которая их запускает. Вот код:
using System;
using System.Management.Automation;
[Cmdlet(VerbsCommon.Get,"Hello")]
public class GetHelloCommand:Cmdlet
{
protected override void EndProcessing()
{
WriteObject("Hello",true);
}
}
class MainClass
{
public static void Main(string[] args)
{
PowerShell powerShell=PowerShell.Create();
powerShell.AddCommand("Get-Hello");
foreach(string str in powerShell.AddCommand("Out-String").Invoke<string>())
Console.WriteLine(str);
}
}
Когда я пытаюсь запустить его, я получаю исключение CommandNotFoundException. Я неправильно написал свой командлет? Что-то, что мне нужно сделать, чтобы зарегистрировать мой командлет в PowerShell или в Runspace или что-то?
3 ответа
Самый простой способ сделать это с помощью текущего фрагмента кода:
using System;
using System.Management.Automation;
[Cmdlet(VerbsCommon.Get,"Hello")]
public class GetHelloCommand:Cmdlet
{
protected override void EndProcessing()
{
WriteObject("Hello",true);
}
}
class MainClass
{
public static void Main(string[] args)
{
PowerShell powerShell=PowerShell.Create();
// import commands from the current executing assembly
powershell.AddCommand("Import-Module")
.AddParameter("Assembly",
System.Reflection.Assembly.GetExecutingAssembly())
powershell.Invoke()
powershell.Commands.Clear()
powershell.AddCommand("Get-Hello");
foreach(string str in powerShell.AddCommand("Out-String").Invoke<string>())
Console.WriteLine(str);
}
}
Предполагается, что PowerShell v2.0 (вы можете проверить свою консоль с помощью $psversiontable или датой авторского права, которая должна быть 2009 г.). Если вы работаете на win7, вы на v2.
Еще один простой способ - зарегистрировать командлеты в конфигурации пространства выполнения, создать пространство выполнения с этой конфигурацией и использовать это пространство выполнения.
using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
[Cmdlet(VerbsCommon.Get, "Hello")]
public class GetHelloCommand : Cmdlet
{
protected override void EndProcessing()
{
WriteObject("Hello", true);
}
}
class MainClass
{
public static void Main(string[] args)
{
PowerShell powerShell = PowerShell.Create();
var configuration = RunspaceConfiguration.Create();
configuration.Cmdlets.Append(new CmdletConfigurationEntry[] { new CmdletConfigurationEntry("Get-Hello", typeof(GetHelloCommand), "") });
powerShell.Runspace = RunspaceFactory.CreateRunspace(configuration);
powerShell.Runspace.Open();
powerShell.AddCommand("Get-Hello");
foreach (string str in powerShell.AddCommand("Out-String").Invoke<string>())
Console.WriteLine(str);
}
}
На всякий случай, при таком подходе классы командлетов не должны быть общедоступными.
Вам необходимо зарегистрировать свой командлет, прежде чем использовать его в сеансе Powershell. Обычно вы делаете это с помощью оснастки Powershell. Вот общий обзор процесса:
- Создание пользовательских командлетов (вы уже сделали эту часть)
- Создайте оснастку Powershell, которая содержит и описывает ваши командлеты
- Установите новую оснастку в вашей системе, используя
Installutil
- Добавьте оснастку к определенному сеансу Powershell, используя
Add-PSSnapin
На MSDN есть пара полезных статей, которые довольно подробно объясняют этот процесс:
Есть также серия из двух частей по ByteBlocks, в которой обсуждается написание пользовательских командлетов. Эта серия может быть вашим лучшим выбором, так как вы, кажется, уже сделали эквивалент части 1. Вы можете просто использовать часть 2 в качестве краткого справочника и быть готовым к работе.