2015/11/14
スクリプトを管理者権限で実行する
既出ですが、まとめておきます。
今回登場する関数は、elevate.ps1という名前で一つにまとめて保存しておくと便利です。
起動中のスクリプトが管理者権限で実行されているかどうかの確認
function Test-Admin { ( [Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]:: GetCurrent() ).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) }
スクリプト中でこのTest-Admin関数を実行してTrueが返れば、スクリプト(もしくはコンソール)は管理者権限で実行されている。
管理者権限で任意のスクリプトを起動
function Start-ScriptAsAdmin { param( [string] $ScriptPath, [object[]] $ArgumentList ) if(!(Test-Admin)) { $list = @($ScriptPath) if($null -ne $ArgumentList) { $list += @($ArgumentList) } Start-Process powershell -ArgumentList $list -Verb RunAs -Wait } }
Start-ScriptAsAdmin "任意のps1ファイルパス" を実行すると、指定のスクリプトが管理者権限で実行される。(実行前にUACダイアログが表示される)
なお、"powershell"の部分を、今起動しているホストの実行ファイルと同じにするには、(Get-Process -Id $pid).Path としても良い。ただ、ISEの場合だと単にスクリプトファイルが開かれた状態になるだけで実行まではしてくれない。
管理者権限がない場合、昇格してスクリプトを再実行する
管理者権限を要する処理の直前で、以下のようにStart-ScriptAsAdmin関数を実行すると、仮に管理者権限がない場合はスクリプトを再起動し、昇格して再実行する。(管理者権限がある場合は再実行せずそのまま継続する。)
. .\elevate.ps1 Start-ScriptAsAdmin -ScriptPath $PSCommandPath if(Test-Admin) { "昇格を要する処理" }
v3未満の場合は、実行中のスクリプトパスを示すシェル変数$PSCommandPath の代わりに &{$MyInvocation.ScriptName}が使える
再起動するまでに実行した処理は再実行しないようにするには、以下のようにスクリプトファイルにパラメータを定義すれば良い。
param([switch]$SkipNormalTask) . .\elevate.ps1 if(!$SkipNormalTask) { "昇格不要な処理1" } Start-ScriptAsAdmin -ScriptPath $PSCommandPath -ArgumentList "-SkipNormalTask" if(Test-Admin) { "昇格を要する処理" } if(!$SkipNormalTask) { "昇格不要な処理2" }
UACダイアログを出さずに管理者権限でスクリプトを実行する
一般的な方法と同様、タスクスケジューラを利用する。
PowerShellからタスクスケジューラにスクリプトを登録するには、PowerShell3.0以上に同梱されているPSScheduledJobモジュールが必要。
function Register-ScriptAsAdmin { param( [string] $ScriptPath, [object[]] $ArgumentList ) $jobArgs=@{ FilePath = $ScriptPath ScheduledJobOption = New-ScheduledJobOption -RunElevated Name = "RunAsAdmin $(Split-Path -Leaf $ScriptPath)" } if($null -ne $ArgumentList){$jobArgs+=@{ArgumentList = $ArgumentList}} Register-ScheduledJob @jobArgs } function Invoke-ScriptAsAdmin { param( [string] $ScriptPath ) $job = Get-ScheduledJob -Name "RunAsAdmin $(Split-Path -Leaf $ScriptPath)" $job.RunAsTask() } function Unregister-ScriptAsAdmin { param( [string] $ScriptPath ) Unregister-ScheduledJob -Name "RunAsAdmin $(Split-Path -Leaf $ScriptPath)" }
まず、管理者権限で実行したいスクリプトをRegister-ScriptAsAdmin "スクリプトのフルパス"としてタスクスケジューラに登録。
この操作には当然ながら管理者権限を要するので、もし登録用スクリプトから登録をするには前述のStart-ScriptAsAdminを併用しても良い。(さすがにUACダイアログを1回も表示させない方法はなさげ…)
登録が済んだら後は、Invoke-ScriptAsAdmin "スクリプトのフルパス"とすれば、UACダイアログを表示させずに管理者権限でスクリプトを実行できる。
スクリプトの登録を解除するには、Unregister-ScriptAsAdmin "スクリプトのフルパス"を実行する。(この操作には管理者権限不要)
管理者権限がない場合はスクリプトを実行しない
逆に、管理者権限がない時は、一切処理を実施させたくない場合。
v4以上の場合は、以下をスクリプトの一行目に定義しておくだけでOK。管理者権限がない場合はエラーになってそのままスクリプトは終了する。
#Requires -RunAsAdministrator
v4未満の場合は、前掲のTest-Admin関数を以下のようにスクリプト先頭で呼び出せば良い。
if(!(Test-Admin)) { throw "管理者権限がありません" }
プライバシーポリシー