windowsXPでネットワークドライブに自動的にログインする方法(wsh)

前回はバッチファイルでネットワークドライブに自動ログインする方法を調べた。今回はwshを使う方法。


wshを使う方法は以下のサイトを参考に。
第15回 WshNetworkオブジェクトを利用する (2/2):基礎解説 演習方式で身につけるチェック式WSH超入門 - @IT
MapNetworkDrive メソッド | Microsoft Docs
wshそのものについては以下を参考に。
第1回 WSHを始めよう (1/3):基礎解説 演習方式で身につけるチェック式WSH超入門 - @IT



ごく基本的には、以下の記述を○○.vbs (○○は適当な名前)で保存してダブルクリックすれば自動的にネットワークドライブに接続できる。保存したファイルをスタートアップに入れておけば、起動時に自動ログインできるようになる。

 Dim objWshNetwork
 Set objWshNetwork = WScript.CreateObject("WScript.Network")
 objWshNetwork.MapNetworkDrive "x:", "\\サーバ名\共有フォルダ名", False, "ユーザ名", "パスワード"

ただ、この方法でもファイルにパスワードを記述しておく必要がある。それが嫌な場合は、InputBoxを使ってユーザー入力を受け取るようにすれば、ファイルに記述しておく必要は無くなる。InputBoxで入力されたパスワードを文字列に保持し、それを先ほどのコマンドに渡してやれば良い。以下のような記述で実現可能。

 Option Explicit
 Dim string
 string = InputBox("パスワードを入力してください。")
 Dim objWshNetwork
 Set objWshNetwork = WScript.CreateObject("WScript.Network")
 objWshNetwork.MapNetworkDrive "x:", "\\サーバ名\共有フォルダ名", False, "ユーザー名", string

接続するネットワークドライブが複数の場合、パスワードがすべて同じであれば、objWshNetwork.MapNetworkDriveを複数記述してやれば、1度のパスワード入力で全ドライブにログインできるようになる。
が、InputBoxでは入力した文字列がまる見えになる。できれば****のように表示して隠して表示したい。

パスワードをマスクする方法

入力したパスワードを****のようにマスクして表示する方法がないか調べてみた。結果、wsh(vbs)ではパスワード入力をマスクする方法がないことが分かった。下記のサイトによると、ScriptPWというオブジェクトを使えば実現できるらしいが、windowsXP HomeだとScriptPWが使えないようだ。
http://www.microsoft.com/japan/technet/scriptcenter/resources/qanda/feb05/hey0204.mspx
先のサイトでは、HTMLで実現する方法が載っているが、パスワード入力のためだけにIEが立ち上がるのもどうかと思うので、別の方法を考えることにする。

パスワード入力方法の方針

結局、visual C++ express edition 2008を使って、パスワード入力用のフォームを表示するだけのプログラムを作成し、wshからそれを呼び出す方法をとることにする。
入力されたパスワードの文字列は、標準出力を使って出力し、wsh側でそれを受け取るようにする。

visual C++でパスワード入力用のフォームを作成

入力されたパスワードをそのまま表示したくないので、MaskedTextBox を使うことにする。MaskedTextBoxを使うと、入力された文字列の代わりに「*」を表示して、パスワードを隠すことが出来る。
使うときはMaskedTextBoxのPasswordCharプロパティに「*」を入力すればいい。その他のプロパティはデフォルトのままでOK。入力された文字列は、普通のTextBoxと同じように参照できる。
フォームにはMaskedTextBoxと、OKボタン、キャンセルボタンのみを配置。パスワード入力後にOKボタンを押すと、入力された文字列を標準出力に出力して、プログラムを終了する。OKボタンを押した後の動作のソースは以下のようになる。

 // OKボタンが押されたときの処理
 private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
     // 標準出力に出力
     Console::Write(maskedTextBox1->Text);
     Application::Exit();
  }
 // キャンセルボタンが押されたときの処理
 private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
    Application::Exit();
 }

ちなみに、フォームを画面の中央に表示するには、フォームのプロパティのStartPositionをCenterScreen としておけばいい。
以下のページを参照のこと。
フォームを画面の真ん中(あるいは、任意の位置)に表示する - .NET Tips (VB.NET,C#...)

wshからパスワード入力フォームを呼び出し&パスワード文字列の取得

先に作成したパスワード入力用フォームを表示するプログラムを、wshから呼び出してパスワード入力を行う。
wshから外部のアプリケーションを呼び出す方法には、WshShellオブジェクトのRunメソッドとExecメソッドがある。詳しい解説は次のサイトを参照。
第12回 WshShellオブジェクトを利用する(1) (1/2):基礎解説 演習方式で身につけるチェック式WSH超入門 - @IT
今回は標準入出力を使いたいので、Execメソッドを使う。詳しい解説は以下のサイトを参照。
第14回 WshShellオブジェクトを利用する(3) (1/4):基礎解説 演習方式で身につけるチェック式WSH超入門 - @IT
外部プログラムを起動するためのオブジェクト変数の宣言とWshShellオブジェクトの作成は以下の通り。

 Dim objWshShell
 Set objWshShell = WScript.CreateObject("WScript.Shell")

上記オブジェクトのExecメソッドで、先ほどのパスワード入力フォーム表示プログラム(passform.exe)を起動するには次のように記述する。パスは適当。

 Dim objExec
 Set objExec = objWshShell.Exec("C:\passform.exe")

なお、パスは絶対パスでも、スクリプトを置いてあるディレクトリからの相対パスでもOK。
標準出力に出力された文字列を取得するには、以下のようにする。

 Dim string
 string = objExec.StdOut.ReadLine

詳しくは以下のサイトを参照。
Office TANAKA - Excel VBA Tips[MS-DOSコマンドの標準出力を取得する]



ここまでできれば、あとは上のほうに記述した方法で、ネットワークドライブの割り当てを行えばいい。
結局、作成したスクリプトは以下のようになった。
ここでは、server1のshareAというフォルダをxドライブ、server2のshareBというフォルダをzドライブ、server3のshareCというフォルダをyドライブとしてネットワークドライブの接続を行っている。ユーザー名はuser_nameとしてある。
また、上記の基本機能に加えて、以下の機能も追加してある。

  • 起動したパスワード入力フォーム表示プログラムの終了を待ってから、以降の処理を実行する
  • パスワード入力フォームでキャンセルボタンを押されたときはスクリプトを終了する
  • すでに接続済みの場合は処理を行わない(接続済みのドライブに接続しようとするとエラーになって、そこでスクリプトが止まる)
  • 接続完了したら、それを通知するポップアップを表示(5秒表示した後、勝手に消える)

ポップアップについての説明は次のサイトを参照。
Popup メソッド | Microsoft Docs

 Option Explicit

 'オブジェクト変数の宣言とWshShellオブジェクトの作成。
 Dim objWshShell
 Set objWshShell = WScript.CreateObject("WScript.Shell")

 ' 標準入出力を使うため、Execメソッドで起動
 Dim objExec
 Set objExec = objWshShell.Exec("passform.exe")

 WScript.Sleep(1000)

 ' 起動したプログラムの終了を待つ
 Do While objExec.Status = 0
  WScript.Sleep(100)
 Loop 

 Dim string
 ' 標準出力から文字列を1行取得
 string = objExec.StdOut.ReadLine

 If(string = "") Then
  MsgBox "キャンセルされました"
  WScript.Quit
 End If


 Dim objWshNetwork
 Set objWshNetwork = WScript.CreateObject("WScript.Network")
 Dim objFSO
 Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
 '接続済みのネットワークドライブを調査し、未接続なら接続する
 If Not objFSO.DriveExists("x:") Then
    objWshNetwork.MapNetworkDrive "x:", "\\server1\shareA", False, "user_name", string
 End If
 If Not objFSO.DriveExists("z:") Then
    objWshNetwork.MapNetworkDrive "z:", "\\server2\shareB", False, "user_name", string
 End If
 If Not objFSO.DriveExists("y:") Then
    objWshNetwork.MapNetworkDrive "y:", "\\server3\shareC", False, "user_name", string
 End If

 ' 完了通知ポップアップの表示
 string = "全ネットワークドライブに接続完了しました"
 objWshShell.Popup string, 5',, vbInformation


 ' オブジェクトの破棄
 Set objWshShell = Nothing
 Set objExec = Nothing
 Set objWshNetwork = Nothing
 Set objFSO = Nothing

まとめ

以上の方法で、windowsXPでネットワークドライブに自動ログインするスクリプトを作成できた。パスワードをスクリプトファイルに直接書いておかなくてもよくなったし、やや手間はかかったがパスワード入力時に入力した文字列をマスクすることも可能となった。スクリプトの記述はどこかおかしい箇所があるかもしれないし、もっとスマートなやり方があるかもしれないが、とりあえずうまく動いているようなので、これでよしとする。
あと、参考にされる方は自己責任でお願いしますね。




WSHクイックリファレンス 第2版
羽山 博
オライリー・ジャパン
売り上げランキング: 13198
おすすめ度の平均: 5.0
5 TIPS本ではなくリファレンス本です