Re[2]: Раунд 2
От: kochetkov.vladimir Россия https://kochetkov.github.io
Дата: 26.06.08 10:25
Оценка: 3 (2)
Здравствуйте, Sheridan, Вы писали:

S>kochetkov.vladimir однажды (25 июня 2008 19:34) писал в rsdn.flame.comp:


S>Монитор выключить сможеш?

S>
S>xset -display :0 dpms force off
S>


Честно говоря, не представляю себе — нахрена это может понадобиться, но — почему нет?

Через WMI (как посоветовал Роман), к сожалению — именно монитор отключить не получится, бо MS до сих пор не реализовала провайдера для метода SetPowerState класса Win32_DesktopMonitor. Но это косяк WMI, а PS. Если реализует, либо если взять провайдера третьих контор, либо если написать своего, то на PS через WMI это выглядело бы так:

(gwmi -Class Win32_DesktopMonitor -ComputerName .)[0].InvokeMethod("SetPowerState", 6)


Но увы и ах — провайдера в общем случае нет. Поэтому пойдем вторым путем, предложенным Романом и воспользуемся WinAPI. Чуть расширим задачу: вызвать произвольную функцию из произвольной DLL, не против?

Потратим немного времени на написание универсального "запускателя" нативных функций из dll'ек:

function Invoke-Win32([string] $dllName, [Type] $returnType, 
   [string] $methodName, [Type[]] $parameterTypes, [Object[]] $parameters)
{
   $domain = [AppDomain]::CurrentDomain
   $name = New-Object Reflection.AssemblyName 'PInvokeAssembly'
   $assembly = $domain.DefineDynamicAssembly($name, 'Run')
   $module = $assembly.DefineDynamicModule('PInvokeModule')
   $type = $module.DefineType('PInvokeType', "Public,BeforeFieldInit")

   $inputParameters = @()
   $refParameters = @()
  
   for($counter = 1; $counter -le $parameterTypes.Length; $counter++)
   {
      if($parameterTypes[$counter - 1] -eq [Ref])
      {
         $refParameters += $counter

         $parameterTypes[$counter - 1] = 
            $parameters[$counter - 1].Value.GetType().MakeByRefType()
         $inputParameters += $parameters[$counter - 1].Value
      }
      else
      {
         $inputParameters += $parameters[$counter - 1]
      }
   }

   $method = $type.DefineMethod($methodName, 'Public,HideBySig,Static,PinvokeImpl', 
      $returnType, $parameterTypes)
   foreach($refParameter in $refParameters)
   {
      $method.DefineParameter($refParameter, "Out", $null)
   }

   $ctor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
   $attr = New-Object Reflection.Emit.CustomAttributeBuilder $ctor, $dllName
   $method.SetCustomAttribute($attr)

   $realType = $type.CreateType()
   $realType.InvokeMember($methodName, 'Public,Static,InvokeMethod', $null, $null, 
      $inputParameters)

   foreach($refParameter in $refParameters)
   {
      $parameters[$refParameter - 1].Value = $inputParameters[$refParameter - 1]
   }
}


Его можно оформить в виде отдельного сценария (либо в виде командлета в PS v2.0) для дальнейшего использования из любых скриптов. Затем: напишем обертку для SendMessage:


function SendMessage([IntPtr] $hWnd, [Int32] $message, [Int32] $wParam, [Int32] $lParam)
{
    $parameterTypes = [IntPtr], [Int32], [Int32], [Int32]
    $parameters = $hWnd, $message, $wParam, $lParam

    Invoke-Win32 "user32.dll" ([Int32]) "SendMessage" $parameterTypes $parameters
}


И воспользуемся ей:

SendMessage ([IntPtr] 0xffff) 274 61808 2 | out-null


Писать пришлось много, таки-да. Зато у нас теперь в распоряжении — полноценный доступ не только к API всей системы, но и всех доступных для использования dll-библиотек из обычных скриптов, не дотягивающих до уровня bash

[Интервью] .NET Security — это просто
Автор: kochetkov.vladimir
Дата: 07.11.17
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.