WSHテクニック集

●ここでは、掲示板で出された質問を中心に、WSHで使える様々なテクニックを紹介していきたいと思います。
●コード例はVBSで書きます。
●Shellオブジェクトを利用したスクリプトは、IE4がシェル統合モードでインストールされているWin95,NT4あるいはWin98,Win2000,ME,XPでないと動作しません。
●WSH2.0がないと動作しないものもあります。
●実はWindowsテクニック集でもある(謎)


アプリケーションの起動

DOS用アプリケーションの起動

Windowsの終了・再起動

コントロールパネルの中身を直接実行

特殊フォルダを開く

ウィンドウの整列

右クリックメニューの実行

スクリプトからオプションを解釈する

スクリプトの暴走を止める


アプリケーションの起動

 スクリプトからアプリケーションを起動するには、次のようにWshShellオブジェクトのRunメソッドを使用します。オプションも普通に指定できます。(ただしVBSで特別な意味を持つ記号を使うときは注意しましょう)

'メモ帳を実行する例
Set WSHShell = WScript.CreateObject("WScript.Shell")
WSHShell.Run "C:\Windows\notepad.exe"

 ファイルを関連づけにしたがって実行することもできます。パスの通ったフォルダにあるファイルなら、フォルダを省略して記述できます。

'テキストファイルを開く例
Set WSHShell = WScript.CreateObject("WScript.Shell")
WSHShell.Run "tips.txt"

 ウィンドウの最大化・最小化などを指定することもできます。また、起動したアプリの終了を待ってから次の動作を実行させることも可能です。詳しくはLessonオブジェクト解説をご覧ください。

 ただし、いずれの場合もスペースが含まれたLFN(ロングファイルネーム)は使えません(ファイルがない、というエラーになる)。LFNを使いたい場合は、次のようにします。

Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run """C:\Program Files\Internet Explorer\IEXPLORE.EXE"""
'ダブルクォーテーションでくくる。一つ目の「"」は文字列を表し、次の「""」は文字列中では「"」と置き換えられる。
'したがって、DOSプロンプトとかでLFNを実行するとき「"」でくくるのと原理は同じ。
Set WshShell = WScript.CreateObject("WScript.Shell")
Set Fs = WScript.CreateObject("Scripting.FileSystemObject")
WshShell.Run Fs.GetFile("C:\Program Files\Internet Explorer\IEXPLORE.EXE").ShortName
'まあ、こんな手もあるというくらいで…。

 Shellオブジェクトを使っても可能です。

Set Win = WScript.CreateObject("Shell.Application")
Const filename="C:\Windows\notepad.exe"
Win.NameSpace(filename).ParentFolder.ParseName(Win.NameSpace(filename).Title).InvokeVerb 'メモ帳を起動

[↑]

DOS用アプリケーションの起動

 DOS用アプリを起動させるには、二通りの方法があります。

1.そのまま実行させる。
WSHShell.Runにそのアプリのパスを指定する。実行させて終了するとDOSプロンプトが自動的に閉じるアプリに有効。

2.command.comを介して実行させる。
実行させて終了させてもDOSプロンプトが閉じないソフトの場合やバッチファイルを実行させるには、/cオプションをつけたcommand.comを利用する。pifファイルのプロパティに「プログラム終了時にウィンドウを閉じる」設定をしておくと、1.の方法でもいい。また、command.com内部コマンド(dirなど)を実行させることも可能。

WSHShell.Run"command.com /c dosapp.com"

[↑]

Windowsの終了・再起動

 Windowsを終了・再起動させるには、rundll.exeを使います。スタンバイにはIE4のシェル統合機能を使います。以下の方法のうちいくつかは、Win95では実行できません。

電源をオフにする(以下のどちらでも良い)

Set WSHSHell=CreateObject("WScript.Shell")
WSHShell.Run "C:\WINDOWS\RUNDLL32.EXE Shell32.dll,SHExitWindowsEx 1"
Set WSHSHell=CreateObject("WScript.Shell")
WSHShell.Run "C:\WINDOWS\RUNDLL.EXE USER.EXE,ExitWindows"

マシンの再起動

Set WSHSHell=CreateObject("WScript.Shell")
WSHShell.Run "C:\WINDOWS\RUNDLL32.EXE Shell32.dll,SHExitWindowsEx 2"

Windowsの再起動

Set WSHSHell=CreateObject("WScript.Shell")
WSHShell.Run "C:\WINDOWS\RUNDLL.EXE USER.EXE,ExitWindowsExec"

ログオフ

Set WSHSHell=CreateObject("WScript.Shell")
WSHShell.Run "C:\WINDOWS\RUNDLL32.EXE Shell32.dll,SHExitWindowsEx 0"

サスペンド(スタンバイ)

Set Win = CreateObject("Shell.Application")
Win.Suspend

これはシャットダウンのダイアログが出るタイプ。スタートメニューから終了するのと同じです。

Set Win =CreateObject("Shell.Application")
Win.ShutdownWindows

[↑]

コントロールパネルの中身を直接実行

 コントロールパネルを実行させるには、次の3つの方法があります。開くタブを選べるので、1がおすすめ。3.は他の方法で開けないものに適用するといいでしょう。

1.control.exeを使う

'「画面のプロパティ」を表示
Set WSHShell = WScript.CreateObject("WScript.Shell")
WSHShell.Run "control.exe desk.cpl"
'「システムのプロパティ」の「デバイスマネージャ」タブを開く。指定する数値はタブの順番-1
Set WSHShell = WScript.CreateObject("WScript.Shell")
WSHShell.Run "control.exe sysdm.cpl ,1"

2.Shellオブジェクトを使う

'「地域のプロパティ」を表示
Set Win = WScript.CreateObject("Shell.Application")
Win.ControlPanelItem "intl.cpl"

3.Shellオブジェクトを使う その2

 この方法だと、cplファイルを指定するだけでは開けないものも開けます。

'「マウスのプロパティ」を表示
Set Win = WScript.CreateObject("Shell.Application")
For Each objItem In Win.NameSpace(3).Items
	If objItem.Name="マウス" Then objItem.InvokeVerb
Next

4.rundll32.exeを使う

'「アプリケーションの追加と削除のプロパティ」を表示
Set WSHShell = WScript.CreateObject("WScript.Shell")
WSHShell.Run "rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl"

 対象が限定されますが、以下のような開き方もあります。

Set Win = WScript.CreateObject("Shell.Application")
Win.SetTime '日付と時刻のプロパティ表示
Win.TrayProperties 'タスクバーのプロパティ表示

[↑]

特殊フォルダを開く

 エクスプローラで特殊フォルダ(マイコンピュータなど)を開くには、以下のような方法があります。

1.Shellオブジェクトを使う

 ShellオブジェクトのOpenメソッド、Exploreメソッドを使います。それぞれのメソッドに指定する引数(フォルダの種類)に関しては、オブジェクトの解説をご覧ください。

Set Win = WScript.CreateObject("Shell.Application")
Win.Open 17 'マイコンピュータを開く
Win.Explore 0 'デスクトップをエクスプローラ形式で開く

 なお、普通のフォルダは、引数にパスを指定すれば普通に開けます。

2.explorer.exeを使う

 WshShellオブジェクトのRunメソッドで、explorer.exeを実行します。

Set WSHShell = WScript.CreateObject("WScript.Shell")
WSHShell.Run "explorer.exe /select,""::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"""
'デスクトップを開く
WSHShell.Run "explorer.exe /e,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"
'コントロールパネルをエクスプローラ形式で開く

 他にも、以下のような特殊フォルダを開くことができます。

ダイヤルアップネットワーク
::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{992CFFA0-F557-101A-88EC-00DD010CCC48}
プリンタ
::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{2227A280-3AEA-1069-A2DE-08002B30309D}
タスク
::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{D6277990-4C6A-11CF-8D87-00AA0060F5BF}

 もちろん普通のフォルダを開くこともできます。

Set WSHShell = WScript.CreateObject("WScript.Shell")
WSHShell.Run "explorer.exe C:\Program Files" 'Program Filesを開く
'WSHShell.Run "C:\Progra~1" 
'フォルダを開くだけならこのようにRunメソッドの引数にパスを書くだけでも良いが、その場合何故かLFNは使えないので注意。

 ところで、マイドキュメントフォルダや、インターネットのキャッシュフォルダなど、設定や環境によって場所が変わるフォルダに関しては、直接パスを指定してもいいですが(C:\My Documents、C:\Windows\Tempor~1 etc)、WshSpecialFoldersオブジェクトやレジストリの値を参照することで、より汎用的なスクリプトにすることができます。その方法についてはLessonを参照してください。

3.shell:スキーマのURI(?)を利用する[Win2000]

 Windows2000限定ですが、shell:という特殊なスキーマ(?)で指定されたURIをRunしてやることでも可能です。

Set WSHShell = WScript.CreateObject("WScript.Shell")
WSHShell.Run "shell:DriveFolder"
'マイコンピュータを開く
WSHShell.Run "shell:Common Administrative Tools"
'「管理ツール」を開く

URI一覧
shell:Common Administrative Tools shell:Administrative Tools shell:SystemX86 shell:My Pictures
shell:Profile shell:CommonProgramFiles shell:ProgramFiles shell:System
shell:Windows shell:History shell:Cookies shell:Local AppData
shell:AppData shell:Common Documents shell:Common Templates shell:Common AppData
shell:Common Favorites shell:Common Desktop shell:Common Menu shell:Common Programs
shell:Common Startup shell:Templates shell:PrintHood shell:NetHood
shell:Favorites shell:Personal shell:SendTo shell:Recent
shell:Menu shell:Programs shell:Startup shell:Desktop
shell:Fonts shell:ConnectionsFolder shell:RecycleBinFolder shell:PrintersFolder
shell:ControlPanelFolder shell:InternetFolder shell:DriveFolder shell:NetworkFolder
shell:DesktopFolder

[↑]

ウィンドウの整列

 ウィンドウの整列をおこなうには、Shellオブジェクトの各メソッドを使います。↓の例は、全ウィンドウを最小化するものです。他の例はコメントアウトしています。

Set Win = WScript.CreateObject("Shell.Application")
Win.MinimizeAll '全ウィンドウを最小化
'Win.UndoMinimizeALL 'ウィンドウ操作を元にもどす
'Win.TileVertically 'ウィンドウを左右に並べて表示
'Win.TileHorizontally 'ウィンドウを上下に並べて表示
'Win.CascadeWindows ' ウィンドウを重ねて表示

 状況に応じて、全ウィンドウを最小化・元に戻すのどちらかを実行させるには、「Windowsエクスプローラコマンド」の「デスクトップを表示」を使います。余談ですが、この「Windowsエクスプローラコマンド」の仕様って公開されているのでしょうか?

Set WSHShell = WScript.CreateObject("WScript.Shell")
WSHShell.Run "C:\WINDOWS\SYSTEM\デスクトップの表示.scf"

[↑]

右クリックメニューの実行

 エクスプローラでファイル・フォルダを右クリックしたときのメニューをWSHから実行させるには、以下の2通りの方法があります。

1.レジストリの値を読む

 右クリックメニューの内容は、レジストリに格納されています。以下は、レジストリの値を読み込み、実行させるSubプロシージャと、その利用例です。結構複雑な処理をしているので、解析してみるのも面白いかもしれません。レジストリで、どのようにファイルタイプが記述されているかを知っていないと無理ですが(^^;

'RunSubMenuサンプルスクリプト

msg=MsgBox ("autoexec.batを最大化にしてメモ帳で開きます。",vbOkCancel,"RunSubMenuのテスト")
If msg=vbOk Then RunSubMenu "C:\autoexec.bat","edit","",3,True
msg=MsgBox ("command.comを実行し、カレントディレクトリをC:\にします。",vbOkCancel,"RunSubMenuのテスト")
If msg=vbOk Then RunSubMenu "C:\command.com","open","/k cd c:\",1,True
msg=MsgBox ("Windowsフォルダのtips.txtを印刷します。",vbOkCancel,"RunSubMenuのテスト")
If msg=vbOk Then RunSubMenu "C:\Windows\tips.txt","print","",1,False


 '*************************************************************************************
 '  Subプロシージャ名:	RunSubMenu
 '	用途:		指定したファイルに対し、指定したアクションを実行する。   
 '	受け取る値:	strFileName:ファイル名もしくはフォルダ名。フルパスで指定。
 '			strAction:アクション名。edit、print、open、playなど。
 '			ファイルタイプによって種類が異なる。
 '			strOption:コマンドラインオプションを指定。
 '			intWindowStyle:1=通常、2=最小化、3=最大化
 '			blnWaitOnReturn:True=実行を待ってから次のステートメントにすすむ
 '					False=実行を待たずに次のステートメントにすすむ			
 '	戻り値:		なし      
 '	注意:		ファイル名が%1、オプションが%*と指定されている場合以外では動作しない。
 '*************************************************************************************
Sub RunSubMenu(strFileName,strAction,strOption,intWindowStyle,blnWaitOnReturn) 
	On Error Resume Next

	Dim WSHShell,Fs,ext,extkey,extdata,extcommand
	Set WSHShell = WScript.CreateObject("WScript.Shell")
	Set Fs=WScript.CreateObject("Scripting.FileSystemObject")
	If Fs.FileExists(strFileName)=True Then
		ext=Fs.GetExtensionName(strFileName)
		extkey="HKCR\." & ext & "\"
		extdata=WSHShell.RegRead (extkey)
	ElseIf 	Fs.FolderExists(strFileName)=True Then
		extdata="Folder"
	Else
		Exit Sub 	
	End If
	extcommand=WSHShell.RegRead ("HKCR\" & extdata & "\Shell\" & strAction & "\command\")
	extcommand=Replace (extcommand,"%1",strFileName)
	extcommand=Replace (extcommand,"%*",strOption)
	WSHShell.Run extcommand,intWindowStyle,blnWaitOnReturn
	Err.Clear
End Sub

2.Shellオブジェクトを使う

 Shellオブジェクトを使うと、なかなかエレガントな仕上がりです。以下は、Windowsフォルダにあるtips.txtを印刷する例です。コメントアウトしてある行は、Program Filesフォルダの検索を実行する例と、ごみ箱を空にする例です。
 InvokeVerbメソッドに指定する引数は、基本的に右クリックメニューで表示されるものと同じですが、たとえば、印刷(P)のようにアクセスキーが指定されているものに関しては、印刷(&P)のようにして、アクセスキーの前に&をつけます。
 ファイルとフォルダでは、実行の仕方が異なるので注意してください。
 このスクリプトも実は結構複雑です。Shellオブジェクト、Folderオブジェクト、FolderItemsコレクション、FolderItemオブジェクトを駆使しています。詳しくは、オブジェクトの解説をご覧ください。

Const filename="C:\Windows\tips.txt"
Set Win = WScript.CreateObject("Shell.Application")
Win.NameSpace(filename).ParentFolder.ParseName(Win.NameSpace(filename).Title).InvokeVerb "印刷(&P)" 'tips.txtを印刷
'Win.NameSpace("c:\progra~1").Items.Item.InvokeVerb "検索(&F)..."
'Const ssfBITBUCKET = 10 'ごみ箱を表す定数。他の特殊フォルダの定数についてはオブジェクトの解説をご覧ください。
'Win.NameSpace(ssfBITBUCKET).Items.Item.InvokeVerb "ごみ箱を空にする(&B)"

[↑]

スクリプトからオプションを解釈する

 スクリプトから、スクリプトに与えられたコマンドラインオプションを解釈するには、WshArgumentsオブジェクトを用います。たとえば、/sオプションがあれば、メッセージボックスを表示しないで処理をするようにするには、以下のようにします。以下のスクリプトを、DOSプロンプトや「ファイル名を指定して実行」で、/sオプションをつけて実行してみてください。

Dim silent
Set WshShell = WScript.CreateObject("WScript.Shell")
Set arg= WScript.Arguments
If arg.Count>0 Then
	If arg.Item(0)="/s" Then
		silent=True
	Else
		silent=False
	End If
End If

'処理.....

If silent=False Then MsgBox "完了"

 WSH2.0だと、ファイル・フォルダをスクリプトファイルにドラッグアンドドロップすることで、そのパスを参照することができます。以下は、複数ファイルをドロップすると、その合計サイズを表示するスクリプトです。このスクリプトは、別にWSH1.0でも実行できますが、ファイル名を指定するのが面倒ですね。

Dim sz,fn,foln
Set WshShell = WScript.CreateObject("WScript.Shell")
Set Fs = WScript.CreateObject("Scripting.FileSystemObject")
Set arg= WScript.Arguments
sz=0 : fn=0 : foln=0
If arg.Count>0 Then
	For Each I In arg
		If Fs.FileExists(I) Then
			sz=sz+Fs.GetFile(I).Size
			fn=fn+1
		ElseIf Fs.FolderExists(I) Then
			sz=sz+Fs.GetFolder(I).Size
			foln=foln+1
		End If
	Next
End If

MsgBox fn & "個のファイル、" & foln & "個のフォルダ、合計は" & sz & "バイト"

 なお、WshArgumentsオブジェクトの詳細は、Lessonをご覧ください。

[↑]

スクリプトの暴走を止める

 下のようなスクリプトを実行させると、無限ループに陥って、永遠に終了しなくなってしまいます。

Do
	a=a+1
Loop
    

意図的にこんなスクリプトは書かないでしょうが、人間誰にでもミスはあります。もしこんな無限ループに陥った場合にはどうすればよいでしょうか。
 一つには、WSHファイルで実行時間を指定しておく方法があります。(WSHファイルについては「WSHを導入するには?」を参照) 実行時間を指定したWSHファイルからスクリプトを立ち上げれば、たとえスクリプトが無限ループしても指定時間にはちゃんと終了してくれます。
 また、WSHファイルを使わなかった場合も無限ループを止める方法があります。それは、Ctrl+Alt+Delで表示される、おなじみ強制終了ダイアログを使う方法です(Win9X系)。ここで無限ループに陥っているスクリプトは「Wscript」のように表示されていると思いますので、ここから強制終了させてやることができます。でもこの方法には一つ問題がありまして、たとえば次のようなスクリプト

Do
	msgbox "こんにちは",,"あいさつ"
Loop

のような無限ループを止めるのが難しいのです。実際にやってみるとわかりますが(でもやらない方がいいですよ)、強制終了ダイアログで、無限に表示されるメッセージボックスのタイトル(上の例なら「あいさつ」)を選択して「終了」を押しても、メッセージボックスは一瞬閉じるだけでまた同じように表示されてしまいます。
 この場合は、まずメッセージボックスを閉じて、その瞬間Ctrl+Alt+Delを押せば、うまくタイミングが合えば強制終了ダイアログにメッセージボックスのタイトルではなく「Wscript」と表示される場合があります。すかさず「Wscript」を選択して「終了」を押せば、強制終了させることができます。このタイミングが難しいのです。
 それに強制終了ダイアログを何度も出したりするのはいやですよね。手が滑ってシャットダウンするかもしれないし…。まあ、実行させる前によくスクリプトを見直せってことになりますかね。
 なお、WinXPや2000では「タスクマネージャ」を使ってwscript.exeもしくはcscript.exeのプロセスを終了させることができます。

[↑]


Home