ドライブ割当て作業をVBScriptで自動化する―さらに配布スクリプト作成自体を自動化する―

環境
windows10

#概要
　ある課のパソコン全てで，特定のネットワークフォルダを特定のドライブに割当てる作業があります。
 ちなみに他の課では、別のネットワークフォルダを特定のドライブに割当てる作業があります。

　さほど難しい作業ではないのですが，ユーザーにやってもらおうとすると担当者が変わるたびにメールなどで説明がいりますし，かといって，空き時間を確認してやって回るのも非効率的です。
　そうした作業を自動化する，というテーマです。
　最後は、配布者がスクリプトを作成する作業も自動化してみます。

#配布用スクリプト
　特定のネットワークフォルダを特定のドライブに割当てるスクリプトは，VBScriptでシンプルに書けます。
　下記のスクリプトを任意のドライブ名，ネットワークフォルダ名に変更して配布すれば，ユーザーにダブルクリックしてもらうだけで作業終了です。

```vb:VBScript
Option Explicit
Dim wNet
set wNet =Wscript.Createobject("WScript.Network")
wNet.MapNetworkDrive"Z:","\\○○\○○",True
MsgBox"\\○○フォルダをZドライブに割り当てました。"
```

```vb:割当て部分
wNet.MapNetworkDrive"Z:","\\○○\○○",True
```
　第１引数はドライブ名

　第２引数はネットワークフォルダの指定
　　　\\\から始まり末尾の\は付けない形で入力します。
　　　例）\\\共有ドライブ\共有フォルダ

　第３引数は，パソコンを再起動した後も割当てを継続するかの指定
　　trueにします。
　　falseにすると，シャットダウンするたびに割当てが切断されます。

#スクリプトの自動作成
　基本的には担当者が変わるごとに先ほどのスクリプトを配布すればよいわけです。
　フォルダが変わっても、割当てるドライブが変わっても、スクリプトを修整するだけでよいです。ただ、それは自分なら、ということになります。
　配布担当者が自分以外のVBScriptをやらない人に変わり、さらに、割当てるドライブやネットワークフォルダが変わると使えなくなるかもしれません。

　そこで、今度は，先ほどのスクリプト自体を、VBScriptができない人でも自動で作って配布できるようにします。
　任意のネットワークフォルダを任意のドライブに割当てるスクリプトを自動で作成できるようにしました。

```vb:VBScript

Option Explicit

Dim fso, thisFolderName
Set fso = CreateObject("Scripting.FileSystemObject")
thisFolderName = fso.GetParentFolderName(Wscript.ScriptFullname)
Dim recordFolder
    If Wscript.arguments.Count = 0 Then
        recordFolder = InputBox("　ネットワークドライブの割り当てスクリプトを作成したい共有フォルダを指定してください。" _
        & vbLf & "(\\から始まり末尾の\は付けない形で入力)" _
        & vbLf & vbLf & "　このブラウザを閉じてスクリプトに共有フォルダをドラッグ＆ドロップすることもできます。", _
                "共有フォルダ名の入力", "\\（デフォルトのフォルダ名）")
            If recordFolder = "" Then
                Wscript.Quit
            End If
    Else
        recordFolder = Wscript.arguments(0)
    End If

    If InStr(recordFolder, ".lnk") Then
        Dim wShell
        Set wShell = CreateObject("wscript.shell")
        recordFolder = wShell.CreateShortcut(recordFolder).TargetPath
    End If
    If fso.FolderExists(recordFolder) = False Then
	Dim msgAns
        msgAns = MsgBox(recordFolder & "が見つかりません。このまま続けてよろしいですか？", vbOKCancel + vbInformation)
                If msgAns <> vbOK Then
                    Wscript.Quit
                End If
    End If
Dim driveName
driveName = InputBox("このVBScriptと同じフォルダ内に" & vbLf & recordFolder & _
           vbLf & "にドライブを割り当てるVBScriptを作成します。" & vbLf & vbLf & _
            "割り当て先のドライブ名を半角アルファベットで入力してください", _
            "割り当て先ドライブ名入力", "Z")
    If driveName = "" Then
        Wscript.Quit
    End If
Dim vbsFileName
Dim vbsPath
vbsFileName = Mid(recordFolder, InstrRev(recordFolder, "\") + 1) & "ドライブ割当て"
vbsPath = thisFolderName & "\" & vbsFileName & ".vbs"
Dim vbsFile
Set vbsFile = fso.CreateTextFile(vbsPath, True)
vbsFile.WriteLine ("Option Explicit" _
 & vbLf & "Dim wNet" _
 & vbCrLf & "set wNet =Wscript.Createobject(""WScript.Network"")" _
 & vbCrLf & "wNet.MapNetworkDrive""" & driveName & ":"",""" & recordFolder & """,True" _
 & vbCrLf & "MsgBox""共有フォルダ" & recordFolder & "を" & driveName & "ドライブに割り当てました。""")
vbsFile.Close
```

```vb:ドラッグ＆ドロップを見分ける
If Wscript.arguments.Count = 0 Then
```
　ドラッグ＆ドロップすると、そのアイテムのパスが引数になります。なので、ドラッグ＆ドロップを判断するには，Wscript.arguments.Countが0か否かを確認します。
　Wscript.arguments.Countはスクリプト実行時の引数の数を返します(引数がないときは0)。
　ユーザーはコマンドプロンプトなどから引数を渡して実行なんてしませんよね。
　なので、引数なし(Wscript.arguments.Count = 0 )ならダブルクリック実行時、そうでなければドラッグアンドドロップ実行時として処理を分けることができます。
　今回はネットワークフォルダのパス取得をしたいので、ダブルクリック実行時はインプットボックスで文字列入力、フォルダのドラッグアンドドロップでもパス取得可能、との仕様にしています。
　ドラッグアンドドロップ実行が可能なときは、ダブルクリック時にドラッグアンドドロップ実行できる旨メッセージを出すと親切だと思います。

```vb:ショートカットフォルダのドラッグ＆ドロップも可能にする
If InStr(recordFolder, ".lnk") Then
        Dim wShell
        Set wShell = CreateObject("wscript.shell")
        recordFolder = wShell.CreateShortcut(recordFolder).TargetPath
End If
```
　ドラッグ＆ドロップされたフォルダがショートカットフォルダなら，元フォルダのパスを取得します。

```vb:フォルダの存在確認
If fso.FolderExists(recordFolder) = False Then
	Dim msgAns
        msgAns = MsgBox(recordFolder & "が見つかりません。このまま続けてよろしいですか？", vbOKCancel + vbInformation)
                If msgAns <> vbOK Then
                    Wscript.Quit
                End If
    End If
```

　ネットワークフォルダのパスを扱うときには，ファイルシステムオブジェクトがエラーが少なくおすすめです。

```vb:スクリプトの作成
Dim vbsFileName
Dim vbsPath
vbsFileName = Mid(recordFolder, InstrRev(recordFolder, "\") + 1) & "ドライブ割当て"
vbsPath = thisFolderName & "\" & vbsFileName & ".vbs"
Dim vbsFile
Set vbsFile = fso.CreateTextFile(vbsPath, True)
vbsFile.WriteLine ("Option Explicit" _
 & vbLf & "Dim wNet" _
 & vbCrLf & "set wNet =Wscript.Createobject(""WScript.Network"")" _
 & vbCrLf & "wNet.MapNetworkDrive""" & driveName & ":"",""" & recordFolder & """,True" _
 & vbCrLf & "MsgBox""共有フォルダ" & recordFolder & "を" & driveName & "ドライブに割り当てました。""")
vbsFile.Close
```
　テキストファイルに書き込む際は，"ダブルクオーテーションのエスケープに注意が必要です。
　基本的にダブルクオーテーション2つで渡すとダブルクオーテーション1つで渡せますが、渡す文字列全体をダブルクオーテーションで囲って渡すので、渡す文字列の端にダブルクオーテーションが欲しいときは、ダブルクオーテーションを3つにします。
　このあたりはやってみて調整すると慣れてきます。
#どこまで責任を持つか
　今回は、配布者がVBScriptを覚えなくても引き継げるようにしてみました。
　自分が作ったスクリプトが風化しないようにどこまで頑張るか、責任を持つかというのはきりがなく、線引きも難しいですよね。