Windows7 UACについて #VBS #WSH #Windows7

最近は、Windows XPからWindows7Windows8に乗り換える機会があるかと思います。その際、XPで動いていたスクリプトやアプリケーションが動かない!なんてことが起こります。問題を引き起こしている原因は、Windows Vistaより導入されたUAC(User Access Control)という機能であることが多いです。
UACについては、このあたりを見ると理解ができるかと。

1. アプリケーション開発者向け Microsoft® Windows 7 対応アプリケーションの互換性
http://msdn.microsoft.com/ja-jp/library/windows/desktop/dd883236.aspx
2. Windows Vista,7 & 8のUAC対策について
http://www.trycut.com/uac.htm

UACが機能していると、具体的にどのような点に注意を配らなくてはいけないかといいますと。

A. ファイルやフォルダの保護機能で、システム領域(Windows、Program Filesなど)への実行、更新、書き込みが制限される
B. 管理者権限が与えられているユーザーでログインしても通常ユーザーと同じ権限しか書き込み や更新ができない

(※他にもあるようですが・・・省く!)

もちろんUACを無効にすることで回避はできます。が、UACのおかげでセキュリティ強化され、スパイウェアマルウェアなどに知らぬ間にシステムを侵されにくくはなっているわけなので、無効にするのは得策ではないかと思います。UACが悪いんじゃないんです。むしろいてくれて感謝すべき機能なわけです。

じゃあ。回避策はあるのか?といいますと、上記のサイト2. に書かれているのですが、「管理者権限で起動」すればよいわけです。

で。ネットで落ちてるコードを参考にしつつ、枯れてる技術VBS(WSH)で書いてみた。サンプルコードは次の通り。

RunasExec.vbs

Option Explicit
Function runasCheck()
	Dim objWMI, osInfo, os
	Dim i, args, strArgs, flgUac
	Dim curDir, objShell, execParam
	Const dQ = """" ' Double-Quote
	
	' Check OS version
	Set objWMI = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
	Set osInfo = objWMI.ExecQuery("SELECT Version FROM Win32_OperatingSystem")
	For Each os in osInfo
		If Left(os.Version, 3) <= 6.0 Then Exit Function
	Next
	Set osInfo = Nothing
	Set objWMI = Nothing
	
	' init
	Set args = WScript.Arguments
	strArgs = ""
	flgUac = False
	
	' 引数から管理者権限で実行されているか確認
	If args.Count > 0 Then
		If UCase( args.item(args.Length-1) ) = "/UAC" Then
			flgUac = True
			' 実行しなおす前のディレクトリに移動
			Wscript.CreateObject("WScript.shell").CurrentDirectory = args.item(args.Length-2)
		Else
			For i = 0 to args.Length - 1
				strArgs = strArgs & " " & args.item(i)
			Next
		End If
	End If
	
	If flgUac = False Then
		' カレントディレクリ取得
		curDir = CreateObject("WScript.Shell").CurrentDirectory
		' 引数に「curDir」と「/UAC」を追加し、管理者として実行しなおす
		execParam = dQ & WScript.ScriptFullName & dQ & strArgs & " " & dQ & curDir & dQ & " /UAC"
		Set objShell = CreateObject("Shell.Application")
		objShell.ShellExecute "wscript.exe", execParam, "", "RunAs", 1
		Set objShell = Nothing
		Set args = Nothing
		Wscript.Quit
	End If
End Function

Call runasCheck()

WScript.Quit
Dim objWshShell
Dim runScript

runScript= "C:\setup.exe"
Set objWshShell = WScript.CreateObject("WScript.Shell")
objWshShell.Exec runScript
※2/11 ディレクリと引数の処理を追加

runScriptに実行したいアプリケーションを指定するだけで、スクリプトを管理者権限で実行しなおしてくれます。
もちろん続けて実行アプリケーションを記述すれば管理者で実行されます。
但し、起動時にUAC確認ダイアログが1回だけでてきます。これを省くことはWindowsの仕様上無理。できたら、それはセキュリティホールかと。(sendkeysとか試しましたが、自動化は無理でした。。。)

最後に

・毎回起動時にUAC確認ダイアログが出て面倒な人は、タスクスケジュールに登録しビルインAdministratorで起動(最上位の特権で実行)という荒業もあります。が、手動で個別設定が必要です。

・あと、ビルインAdministratorでログインするというのも手です。ただ、デフォルトだとログインできないので、以下のサイトを参考に設定してみると良いかと。
Win7jp Windows 7 総合情報サイト Win10への移行カウントダウン!

・久しぶりにVBSを書いてみたけど、VBSもまだまだ捨てたもんじゃないね!