Windows 環境で動作するインストーラを作成する場合、VBScript がおすすめです。
VBScript は Windows に標準で搭載されており、様々な環境の違いが想定されるクライアント PC 上で、おおむね問題なく動作することが可能であり、特別な前準備も必要としません。
また同じく実装の候補としてあがるバッチファイルよりも高機能であり、インストールに必要な機能を色々と実装することができます。
本記事では VBScript でインストーラを作成する際に必要になりそうなポイントについて、いくつか実装例をご紹介したいと思います。
前提条件
本記事で紹介するスクリプトは、CScript
での動作を前提としています。
コマンドプロンプト上にインストールの実行ログを出力することを想定しているからです。
なお、ダイアログ型のメッセージ出力は、Msgbox
を利用して実装します。
管理者権限で実行する
例えばProgram Files
フォルダ内の変更やレジストリの編集には管理者権限が必要になります。
したがってスクリプトを管理者権限で実行する必要があるのですが、ダブルクリックの実行では通常管理者権限にはなりませんし、スクリプトファイルを右クリックしても「管理者として実行」のメニューが出てきません。
この問題を解決するには、以下のようにスクリプトの最初で管理者に昇格して再実行する仕組みを組み込みます。
' 管理者権限で実行させる
Dim shApp
Set shApp = WScript.CreateObject("Shell.Application")
Dim args
Set args = WScript.Arguments
If args.Count > 0 And args.item(0) = "startAdmin" Then
' 管理者権限モードで再実行中なら何もしない
Else
' 管理者権限モードで再実行する
Dim strArgs, i
Set strArgs = ""
For i = 0 To args.Count - 1
strArgs = strArgs&" "&args.item(i) ' 配列に格納された引数を文字列に展開
Next
shApp.ShellExecute "CScript.exe", WScript.ScriptFullName&" startAdmin"&strArgs, "", "runas", 1
WScript.Quit
End If
なお、このサンプルプログラムでは、管理者権限で実行の際にコマンドの第1引数に必ず “startAdmin” が入る仕様になりますので、コマンド引数を利用する場合は第2引数から参照するようにしてください。
右クリックの「管理者として実行」を有効にするため、スクリプトを実行するバッチファイルを作成したり、スクリプトファイルを .exe の実行ファイルに変換するなどの方法もありますが、いずれもインストールする側に右クリックを強要することになりますので、VBScript 側で対処する上記の方法が最善かと思います。
参考: VBScript / JScript を素早く・簡単に Exe ファイルにするツール MakeExe
レジストリの読み書きRegRead
、RegWrite
、RegDelete
を使用してレジストリに読み書きします。
WshShell.RegRead
引数に参照するキー名もしくはキー名+エントリー名を指定します。
キー名を指定する場合は最後にバックスラッシュをつけます。
キー名+エントリー名を指定した場合は、エントリーの値が返ります(Function 呼び出し)。
WshShell.RegWrite
引数にキー名+エントリー名、設定する値、値の種類を指定します。
キーが存在しない場合はキーの作成も行われます。
WshShell.RegDelete
引数に削除するキー名もしくはキー名+エントリー名を指定します。
キー名を指定する場合は最後にバックスラッシュをつけます。
キー名を指定するとキーの削除、キー名+エントリー名を指定するとエントリーのみの削除となります。
ルートキーは以下のように省略が可能です。
HKEY_CURRENT_USER → HKCU
HKEY_LOCAL_MACHINE → HKLM
' レジストリの読み書き
Dim shell
Set shell = WScript.CreateObject("WScript.Shell")
' キーの存在を確認
Err.Clear
shell.RegRead "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5\"
If Err.Number = 0 Then
WScript.Echo "キーは存在します。"
Else ' -2147024894
WScript.Echo "キーは存在しません。"
End If
' 値の取得
Dim version
version = shell.RegRead("HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5\Version")
WScript.Echo ".NET Framework 3.5 version="&version
' 値の設定(キーの作成)
shell.RegWrite "HKLM\SOFTWARE\Test\Version", "1.00", "REG_SZ"
' 値の削除、キーの削除
shell.RegDelete "HKLM\SOFTWARE\Test\Version" ' 値の削除
shell.RegDelete "HKLM\SOFTWARE\Test\" ' キーの削除
Windows OS および OS 上で動作するアプリケーションには、32bit 版と 64bit 版の2種類が存在します。
32bit のアプリケーションを 64bit 版 Windows と 32bit 版 Windows にインストールした場合では、レジストリの参照・更新場所が変わります。
32bit 版アプリを 32bit 版 Windows へインストールした場合
\HKEY_LOCAL_MACHINE\SOFTWARE\・・・
32bit 版アプリを 64bit 版 Windows へインストールした場合
\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\・・・
32bit 版のアプリケーションを扱う場合は、以下のように Windows がどちらの版なのかあらかじめ判断しておくと便利でしょう。Wos6432Node
のキーの有無で判定します。
' 64bit / 32bit 判定
Dim os
Err.Clear
shell.RegRead("HKLM\SOFTWARE\WOW6432Node\")
If Err.Number = 0 Then
os = 64 ' 64bit
Else
os = 32 ' 32bit
End If
プログラム・コマンドの実行Run
を使用して外部プログラムや内部コマンドを実行します。
WshShell.Run
引数に起動するコマンド、ウィンドウスタイル、コマンドの終了待ちをするか否かを指定します。
ウィンドウスタイルの設定値は以下の通りです。
値 | 実行コマンドのウィンドウ | ウィンドウフォーカス |
---|---|---|
0 | 非表示 | 変わらない |
1 | 表示 | 実行コマンドのウィンドウ |
4 | 表示 | 変わらない |
7 | 最小化 | 変わらない |
' プログラム・コマンドの実行
Dim cmd
' プログラムの実行
cmd = ".\Setup.exe"
shell.Run cmd, 0, True
' 内部コマンドの実行
cmd = "cmd.exe /c copy /Y src dest"
shell.Run cmd, 0, True
基本的にRun
は外部プログラムの実行を行うものなので、copy
コマンドやdir
コマンドなど Windows の内部コマンドは、サンプルのように、cmd.exe
から実行します。
作業ディレクトリを変更する
デフォルトでは VBScript の作業ディレクトリはシステムディレクトリ(Windows\system32
)になっています。
作業ディレクトリを変更する場合は、WshShell.CurrentDirectory
に当該 ディレクトリ を設定します。
' 作業ディレクトリの取得
Dim crrtDir
crrtDir = shell.CurrentDirectory
WScript.Echo crrtDir
' 自身の場所を取得
Dim fso
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Dim myDir
myDir = fso.getParentFolderName(WScript.ScriptFullName)
WScript.Echo myDir
' 作業ディレクトリの変更
shell.CurrentDirectory = myDir
ファイルの読み書きOpenTextFile
を使用してファイルをオープンします。
FileSystemObject.OpenTextFile
引数にファイル名、I/O モード、ファイル作成の有無、ファイル形式を指定します。
第2引数の I/O モードの設定値は以下の通りです (省略可能、デフォルト:1) 。
値 | I/O モード |
---|---|
1 | 参照モード |
2 | 新規書き込みモード |
8 | 追加書き込みモード |
第3引数にTrueを指定すると、ファイルが存在しない場合にはファイルを作成します (省略可能、デフォルト:False) 。
第4引数の ファイル形式の設定値は以下の通りです(省略可能)。
値 | ファイル形式 |
---|---|
0 | ASCII |
-1 | Unicode |
-2 | システムの規定値 |
' ファイルの読み書き
Dim fso
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
' 書き込み
Dim fp
set fp = fso.OpenTextFile("test.txt", 8, True)
fp.WriteLine("test" & vbCrLf & "test2")
fp.Close
' 読み込み
Dim line
set fp = fso.OpenTextFile("test.txt", 1, True)
Do While fp.AtEndOfStream <> True
line = fp.ReadLine
WScript.Echo line
Loop
fp.Close
インストールログ出力
インストーラが動作するクライアント PC には様々な環境の違いがあり、テストでうまくいったからといって、必ずしも他の PC でうまく動作するとは限りません。
インストーラの実行ログを出力するようにしておきましょう。
このとき、メッセージの出力とログの出力を両方行う共通の Function を作成しておくと便利です。
' インストールログ
Dim fso
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
' ログファイル名の日付文字列生成
Dim dateStr
dateStr = Replace(Replace(Replace(Now(), "/", ""), ":", ""), " ", "")
' ログファイルオープン
Dim logfp
Err.Clear
set logfp = fso.OpenTextFile("install_"&dateStr&".log", 8, True)
If Err.Number <> 0 Then
WScript.Echo "->errno=" & Err.Number & ":" & Err.Description
End If
' テキストメッセージ出力+ログ出力
echoLog "テストメッセージ 1"
echoLog "テストメッセージ 2"
' ポップアップメッセージ出力+ログ出力
popLog "title", "テストメッセージ 3"
popLog "title", "テストメッセージ 4"
logfp.Close
WScript.Quit 0
' テキストメッセージ出力+ログ出力関数
Function echoLog(msg)
WScript.Echo msg
logfp.WriteLine(msg)
End Function
' ポップアップメッセージ出力+ログ出力関数
Function popLog(title, msg)
MsgBox msg,,title
logfp.WriteLine(msg)
End Function
プログラム・コマンド実行共通関数
プログラムの実行やコマンドの実行の際、エラー判定やエラー発生時のメッセージやログの出力などを毎回やるのは大変ですので、これら諸々の処理を行う共通関数を作成しておくと便利です。
' プログラム・コマンド実行
Dim rc
rc = cmdExec("cmd.exe /c dir", "dir コマンドでエラーが発生しました。")
If rc <> 0 Then
WScript.Quit rc
End If
WScript.Quit 0
' プログラム・コマンド実行関数
Function cmdExec(cmd, errMsg)
echoLog cmd
Err.Clear
shell.Run cmd, 0, True
If Err.Number <> 0 Then
echoLog "->errno=" & Err.Number & ":" & Err.Description
popLog errMsg
cmdExec = Err.Number
Exit Function
End If
cmdExec = 0
End Function
サンプルプログラムのダウンロード
本記事で紹介したサンプルのプログラムを下記からダウンロードできます。
コメント