2016年9月2日金曜日

いつかやるメモ

今やらなければいけないことがあって、他のことは保留にする必要がある状況なのですが、その優先事項を進めるために色々調べる過程で見かけた情報が、今回はちょっと関係無い内容だったけど今後役に立つ事例もありそうだと感じました。
時間ができたらテストしたいので思い出せるようにメモ




IE画面をアクティブにして最大化

起動中のIEをアクティブにするには(中略)APIの出番っぽい。
PowerShellでちょっと作ってみた。
# -----------------------------------------------------------------------
$showWindow          =
  New-PMethod "user32.dll" ([Bool]) "ShowWindow"          @([IntPtr], [Int32])
$setForegroundWindow =
  New-PMethod "user32.dll" ([Bool]) "SetForegroundWindow" @([IntPtr])
# -----------------------------------------------------------------------
$ps = ,(ps iexplore)
$psMain = $ps[0] | ?{$_.MainWindowTitle}
$showWindow.Invoke($psMain.MainWindowHandle, 3)
$setForegroundWindow.Invoke($psMain.MainWindowHandle)
PowerShellでAPIを使えるらしいが、PowerShellは使ったことが無いので上記テキストが何をしているのかイマイチ分からない。でも、これでIEをアクティブ化できるらしい。




function New-PType() {
  [AppDomain]::CurrentDomain.DefineDynamicAssembly(
    (New-Object Reflection.AssemblyName 'PInvokeAssembly'), 'Run'
  ).DefineDynamicModule('PInvokeModule').DefineType('PInvokeType', "Public,BeforeFieldInit")
}
# DLL名, 戻り値の型, メソッド名, 引数の型
function New-PMethod([string]$dll_name, [Type]$return_type, [string]$method_name, [Type[]]$parameter_types){
  $ptype = New-PType
  $ptype.DefineMethod(
    $method_name, 'Public,HideBySig,Static,PinvokeImpl', $return_type, $parameter_types
  ).SetCustomAttribute(
    (New-Object Reflection.Emit.CustomAttributeBuilder ([Runtime.InteropServices.DllImportAttribute].GetConstructor([string])), $dll_name)
  )
  # apiにメンバーを追加
  $invoke  = {
    for($i = 0; $i -lt $this.ParameterTypes.Length; $i++){ $args[$i] = $args[$i] -as $this.ParameterTypes[$i] }
    return $this.InvokeMember($this.MethodName, 'Public,Static,InvokeMethod', $null, $null, $args)
  }
  $api = $ptype.CreateType()
  $api =
  Add-Member -InputObject $api -MemberType NoteProperty -Name MethodName     -Value $method_name -passthru
  Add-Member -InputObject $api -MemberType NoteProperty -Name ParameterTypes -Value $parameter_types
  Add-Member -InputObject $api -MemberType ScriptMethod -Name Invoke         -Value $invoke
  return $api
}

 使い方としては、
$showWindowAsync     = New-PMethod "user32.dll" ([Bool]) "ShowWindowAsync"     @([IntPtr], [Int32])
$setForeGroundWindow = New-PMethod "user32.dll" ([Bool]) "SetForegroundWindow" @([IntPtr])
$isIconic            = New-PMethod "user32.dll" ([Bool]) "IsIconic"            @([IntPtr])
$showWindowAsync.Invoke($hwnd, 4)

PowerShellからAPIを利用できるようにするには上記のような関数を定義しておく必要があるらしい。わりと長い。コマンドラインからワンライナーで実行できたらいいなと思っていたけど無理そう。
スクリプトファイルにして実行するという手段しかなさそう。




powershell -Command "ipconfig | ?{ $_ -match '^ *IPv4'} | Select-Object -first 1 | %{ $_.Split()[-1] }"

実行してみた。





Windows Server 2012 R2 以外の OS では、デフォルトでスクリプトファイルの実行ができないようにポリシーが設定されている。
ポリシーを変更するには、 Set-ExecutionPolicy というコマンドレットを使用する。
RemoteSigned を指定した場合、ローカルで作成されたスクリプトは無条件で実行できるが、ネットワークから入手したスクリプトは署名が無ければ実行できない(Windows Server 2012 R2 はこの設定がデフォルト)。



実行権限を変更すれば、書いたpowershellスクリプトを実行出来るようになるわけだが、勝手に権限を変えて実行出来て欲しいときもある。(中略)powershellスクリプトの中に書いてもpowershellスクリプトが実行出来ないんだからダメなんで、権限の変更はbatにやってもらう。

set TARGETEXECUTIONPOLICY=RemoteSigned
set TARGETSCRIPT=%CD%\test.ps1
REM get origin execution policy
for /f "delims=" %%a in ('powershell -Command Get-ExecutionPolicy') do @set ORIGINEXECUTIONPOLICY=%%a
powershell -Command Get-ExecutionPolicy
REM set target execution policy
powershell -Command Set-ExecutionPolicy %TARGETEXECUTIONPOLICY%
powershell -Command Get-ExecutionPolicy
REM execute powershell script
powershell -File %TARGETSCRIPT%
REM set origin execution policy
powershell -Command Set-ExecutionPolicy %ORIGINEXECUTIONPOLICY%
powershell -Command Get-ExecutionPolicy

現在の実行権限を取得して取っておいて、powershellスクリプトが実行出来る権限に変更、powershellスクリプトを実行して、権限を元に戻す。このbatを管理者権限で(重要・Set-ExecutionPlicyコマンドが管理者権限でないと実行出来ない)実行する。



0 件のコメント:

コメントを投稿