Здравствуйте, 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