WSHを使って特定コンピュータのみフォルダリダイレクトの設定 Part1の続きです。
上記記事の最後でごみ箱無効化に関する問題がありましたが、あれを回避する方法です。
まず、WSHを管理者ユーザで動かすためのexeを作成し、ログインスクリプトに指定します。
今回はドメイン内のどの端末でもこのexeが動くことになるため、C++でWindowsAPIを使ってコーディングしました。
この辺に関しては、(C++)別ユーザでプロセスを起動するや(C++)ファイルパスからフォルダパスを取得するを参考に。。
これで、管理者権限で動くWSH側でごみ箱無効のレジストリ設定を書けばいいんですが、レジストリパスに、HKCU(HKEY_CURRENT_USER) を使うとその管理者のレジストリに書き込まれてしまいます。
ここは本来ログインしたユーザのレジストリに設定したいので、SIDを使って HKEY_USERS にアクセスする必要があります。
ということで、WSHを管理者キックするexeで現在のログインユーザ名を取得し、WSHにコマンドライン引数として渡し、WSH側でユーザ名から SID を取得するという方法を取ることとしました。
WSHでユーザ名をSIDにする方法と、コマンドライン引数を取得する方法は(WSH)ユーザ名のSIDを取得を、現在のログインユーザを取得する方法は(C++)現在のログインしてるユーザ名を取得するを参考にしてください。
最終的に、WSH(VBScript)側は下記のような感じとなりました。
Option Explicit
Dim objNet
'コンピュータ名取得 対象コンピュータなら処理する
Set objNet = CreateObject("WScript.Network")
IF StrComp(objNet.ComputerName , "SV1" ,1 ) = 0 OR _
StrComp(objNet.ComputerName , "SV2" ,1 ) = 0 OR _
StrComp(objNet.ComputerName , "SV3" ,1 ) = 0 OR _
StrComp(objNet.ComputerName , "SV4" ,1 ) = 0 Then
'コマンドライン引数取得(1番目にユーザ名が入る)
Dim args
Set args = WScript.Arguments
'ユーザ名からSID取得
'WMIサービスへの接続
Dim Locator , Service
Set Locator = CreateObject("WbemScripting.SWbemLocator")
Set Service = Locator.ConnectServer
'Administrator以外
IF StrComp(args(0) , "administrator" , vbTextCompare ) <> 0 Then
'WMIクエリ生成(引数1番目にユーザ名が入っていることとする)
Dim query , UsrSet , sid , Usr
query = "Select * From Win32_UserAccount WHERE Name = '" _
& args(0) & "'"
'WMIクエリを実行
Set UsrSet = Service.ExecQuery( query )
'クエリから結果取得し文字列生成
For Each Usr In UsrSet
sid = Usr.SID
Next
'リダイレクト設定
Dim strRedirectRegKey
strRedirectRegKey = "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\"
Dim strRecycleRegKey
strRecycleRegKey = "HKEY_USERS\" & sid & "\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoRecycleFiles"
Dim strBasePath
strBasePath = "\\filesv\user\%username%\"
Dim objShell
Set objShell = WScript.CreateObject("WScript.Shell")
'マイドキュメントリダイレクト
objShell.RegWrite strRedirectRegKey & "Personal", strBasePath & "マイドキュメント" , "REG_EXPAND_SZ"
'デスクトップリダイレクト
objShell.RegWrite strRedirectRegKey & "Desktop", strBasePath & "デスクトップ" , "REG_EXPAND_SZ"
'ごみ箱使用しない
objShell.RegWrite strRecycleRegKey , 1 , "REG_DWORD"
'設定がまだなら設定する。
IF Left(nowDesktop,Len(strBasePath)) <> strBasePath OR Left(nowPersonal,Len(strBasePath)) <> strBasePath Then
'マイドキュメントリダイレクト
objShell.RegWrite strRedirectRegKey & "Personal", strBasePath & "SunRayマイドキュメント" , "REG_EXPAND_SZ"
'デスクトップリダイレクト
objShell.RegWrite strRedirectRegKey & "Desktop", strBasePath & "SunRayデスクトップ" , "REG_EXPAND_SZ"
'ごみ箱使用しない
objShell.RegWrite strRecycleRegKey , 1 , "REG_DWORD"
'メッセージを送り一回ログアウトを促す。
objShell.Run("msg " & args(0) & " 個人フォルダの設定を完了するため、ログオフし再度ログインしてください。")
End If
End If
End If
上記のスクリプトをグループポリシーのログオンスクリプトに設定しても、そのあとのログインですぐに適用されないケースもあるようです。(グループポリシーの適用とユーザ環境のロードのタイミングの問題のようですが。。)
それで、設定がまだなら再ログオンを促すメッセージを表示することにしました。(今回の要件はターミナルサーバにログインしたユーザのみが対象なので、 msg コマンドで自身のコンピュータ(ターミナルサーバ)の該当ユーザにメッセージを送ります。)
本当はダイアログボックスを表示してOK押下すればログアウトする仕組みを取りたかったんですが、このスクリプトは管理者権限で動くため、ログアウトスクリプト入れると管理者がログアウトしてしまっていました。
なのでメッセージだけという妥協策になっています。
msg コマンドの使って、他のユーザにメッセージを送信するにはDOS「メッセージ送信」コマンドが参考になります。
あと、上記のスクリプトで運用を開始したところ一つ問題が発生しました。
それはデスクトップをリダイレクト対象にした場合、デスクトップのファイル・フォルダリストが最新の情報にならない時があるということです。
最新の情報にならないのは、アプリケーションからファイルを保存するときにリダイレクトされたデスクトップを指定したときや、リダイレクト先の共有フォルダをエクスプローラで開いてそこでファイル・フォルダオブジェクトを操作したときです。
調べてみると、ファイルを作成、移動、または削除しても、エクスプローラのファイル一覧が更新されないで、レジストリの HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer に NoSimpleNetIDList キーを作成し、DWORD値 1 を指定するといいようです。試してみましたが、ダメでした。
MSサポート:Windows Vista または Windows Server 2008 でオフライン ファイルの削除がエクスプローラ上で反映されないでも同様の現象が仕様としてされています。
ただ、グループポリシー→管理テンプレートのフォルダリダイレクトの機能を使うとデスクトップをリダイレクトしても上記の現象は発生しません。
リダイレクト先を監視する常駐アプリでも作ろうかと思いましたが、そこまでの必要性はないとのことだったのでユーザがF5を押下して手動で更新してもらう運用としました。