
Привет всем.
Технический писатель Коробко Иван Викторович в своей книге "PowerShell как средство автоматического администрирования" 2012-го года издания еще раз показал нам насколько PowerShell является
универсальным инструментом. Я имею ввиду его главу про "PowerShell и другие языки программирования". Просто передам слово автору.
Довольно часто возникает потребность использовать вставки VB.NET или C# в листинге PowerShell. Это обусловливается невозможностью реализовать тот или иной функционал в PowerShell. Как правило, любую манипуляцию с любым объектом можно выполнить с помощью API-функции, вызываемой на низком уровне. Ярким примером является служба DFS, программное управление которой возможно только с помощью API-функций. Чтобы упростить изложение материала приведем пример вывода обычного окна сообщения – MessageBox(). Реализуем вызов сообщения с помощью вставки листинга программного кода, написанного на VB.NET, в тело сценария на PowerShell и с помощью вызова соответствующей API-функции, описанной в VB.NET.
Компиляция кода на DOT.NET в PowerShell
Интеграция в PowerShell кода компилируемых языков, например C# или VB.NET, осуществляется несколько иным механизмом. Вставка программного кода также компилируется, однако вместо файла записывается в оперативную память. Успешная интеграция программного кода на DOT.NET обеспечивается с помощью двух объектов: с помощью первого объекта – CompilerParameters – осуществляется настройка параметров компиляции указанного кода, идентификация языка программирования. Второй объект изменяется в зависимости от используемого языка программирования в ставке. Для C# – Microsoft.CSharp.CSharp-CodeProvider, а для Visual Basic - Microsoft.VisualBasic.VBCodePro-
vider.
Фрагмент исполняемого кода на DOT.NET представляет собой описание класса с произвольным именем и минимум одной функции, имя которой так же произвольно. Листинг является значением переменной, заключенной, помимо кавычек, в символы @ (листинги П4.1 (C#) и П4.2 (VB.NET). При переносе листинга из Visual Studio в PowerShell необходимо следить за тем, чтобы иерархический путь ко всем методам и функциям был указан целиком, так как импорт пространств имен не поддерживается. Таким образом, вывести окно с помощью MsgBox() невозможно, следует указать полный путь – Microsoft.VisualBasic.Interaction.MsgBox().
Листинг П4.1. Вызов VB.NET-вставки из PowerShell (C#)
$provider = New-Object Microsoft.CSharp.CSharpCodeProvider
$params = New-Object System.CodeDom.Compiler.CompilerParameters
$params.GenerateInMemory = $True
$refs = "System.dll","System.Windows.Forms.dll"
$params.ReferencedAssemblies.AddRange($refs)
$txtCode = @"
Class mBox
Sub Main()
Microsoft.VisualBasic.Interaction.MsgBox ("Тестовое сообщение")
End Sub
End class
“@
$results = $provider.CompileAssemblyFromSource($params, $txtCode)
$mAssembly = $results.CompiledAssembly
$i = $mAssembly.CreateInstance("mBox")
$r = $i.main()
Листинг П4.2. Вызов VB.NET-вставки из PowerShell (VB.NET)
$provider = New-Object Microsoft.VisualBasic.VBCodeProvider
$params = New-Object System.CodeDom.Compiler.CompilerParameters
$params.GenerateInMemory = $True
$refs = "System.dll","Microsoft.VisualBasic.dll"
$params.ReferencedAssemblies.AddRange($refs)
$txtCode = @"
Class mBox
Sub Main()
Microsoft.VisualBasic.Interaction.MsgBox ("Тестовое сообщение")
End Sub
End class
"@
$results = $provider.CompileAssemblyFromSource($params, $txtCode)
$mAssembly = $results.CompiledAssembly
$i = $mAssembly.CreateInstance("mBox")
$r = $i.main()
Компиляция вставки на DOT.NET осуществляется в оперативной памяти. За это отвечает свойство GenerateInMemory. После завершения компиляции осуществляется выполнение скомпилированного кода. Для обращения к нужной функции необходимо указать класс, в котором она находится, а затем и саму функцию.