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