Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Альтернатива Add-Type (http://forum.oszone.net/showthread.php?t=318407)

jkadaba 02-09-2016 08:56 2665069

Альтернатива Add-Type
 
Доброго времени суток! Собственно интересует сабж. Можно как-то обойтись без этогодурацкого командлета, который к тому же для компиляции кода создаёт временный файл в папке temp? Есть ли более, скажем так, изящные способы вызова WinAPI?

Kazun 02-09-2016 09:11 2665075

Модуль PsReflect - http://www.powershellmagazine.com/20...ons-in-memory/

greg zakharov 02-09-2016 09:50 2665085

Альтернативных способов более, чем достаточно. Начнем с того, что непосредственно Add-Type можно "перегрузить" с помощью прокси-функции, добавив в него поддержку, скажем, Python, который адепты "синего" не жалуют, а между тем с его помощью вызов апишных функций упрощается в разы. Можно посредством рефлексии задействовать сигнатуры апишных функций, определенных в сборках самого фреймворка.
Код:

$ptr = [Runtime.InteropServices.Marshal]::AllocHGlobal(48)

if ([Regex].Assembly.GetType(
  'Microsoft.Win32.NativeMethods'
).GetMethod(
  'NtQuerySystemInformation'
).Invoke($null, @(3, $ptr, 48, 0)) -eq 0) {
  [TimeSpan]::FromMilliseconds(
    [Runtime.InteropServices.Marshal]::ReadInt64($ptr, 8) -
    [Runtime.InteropServices.Marshal]::ReadInt64($ptr)
  )
}

[Runtime.InteropServices.Marshal]::FreeHGlobal($ptr)

Пример выше вычисляет uptime системы.
Шагаем дальше.
Рефлексия в купе с обобщенными делегатами так же позволяет вызывать апишные функции.
Код:

$max, $min, $cur = [Byte[]]@(0, 0, 0, 0), [Byte[]]@(0, 0, 0, 0), [Byte[]]@(0, 0, 0, 0)
if ((New-PSDllObject).def(
  'ntdll', 'NtQueryTimerResolution',
  '[Func[[Byte[]], [Byte[]], [Byte[]], Int32]]'
).Invoke($max, $min, $cur) -eq 0) {
  $max, $min, $cur | ForEach-Object { [BitConverter]::ToInt32($_, 0) / 10000 }
}

New-PSDllObject - это набросок модуля $psdll, совмещающий в себе несколько техник вызова winapi. Что же непосредственно кода выше. Следует иметь в виду, что обобщенные делегаты Action и Func не поддерживают параметры с модификаторами ref/out, но это ограничение в некоторых случаях обходится в виде передачи в качестве параметра вызываемой функции массива байт.
В том же $psdll определен метод pin - эквивалент DllImport в C#.
Код:

$psdll = New-PSDllObject

$e = $psdll.enum('NT_PRODUCT_TYPE', [UInt32], @{
  NtProductWinNt = 1
  NtProductLanManNt = 2
  NtProductServer = 3
})

[UInt32]$product = 0
$p = $psdll.pin('ntdll', 'RtlGetProductType', [Boolean], @([UInt32].MakeByRefType()))
if ($p::RtlGetProductType([ref]$product)) {
  $product -as $e
}

Следует иметь в виду, что $psdll не тестировался всесторонне, хотя и является реинкарнацией другого мого черновика.
Есть и другоие варианты, но перечислять их здесь все слишком утомительно.

jkadaba 02-09-2016 10:11 2665094

Цитата:

Цитата Kazun (Сообщение 2665075)

Отличительная черта всех MVP'шников давать ссылку на собрата, причём благо ссылка была стоящая, а то так, барахло плодящее в домене приложений кучу сборок. Не айс.

Цитата:

Цитата greg zakharov (Сообщение 2665085)
Альтернативных способов более, чем достаточно...

Весьма познавательно, спасибо. $psdll при беглом осмотре оказался неплохой штуковиной, правда несколько надуманно в ней создание перечислений. На счёт структур совсем непонятно, может исправите или объясните более подробно?

greg zakharov 04-09-2016 13:33 2665585

Объясняю. Все это писалось для себя, так как подавляющее большинство использует Add-Type, поэтому вряд ли здесь последует детальное описание. Ко всему прочему вопрос был о WinAPI, а не о сторонних расширениях ;)


Время: 05:58.

Время: 05:58.
© OSzone.net 2001-