Windows
VBA
WSH

WSHからtsdiscon.exeを実行しようとして実行できなかったので呼び出し元アプリがx86かx64か判別してSysnativeとSystem32を使い分ける

背景

(背景追記)
勤務先の「働き方改革(笑)」でリモートセッションの接続時間を管理されるようになったから,うっかりログインしっぱなしになってると人事から警告がくるようになったので,自動切断したいよ!
で,タイマーでリモートセッションを切断しようとして,タスクスケジューラから cmd /C tsdiscon を素直に呼べばいいものを,他の方法も勉強しようとvbaから呼び出そうとしてハマったのが発端.

問題

C:\Windows\System32\tsdiscon.exeを呼んでるのに,そんなもんないって言われるよ!

結論

(修正)
呼び出し元アプリがx86アプリかx64アプリによって,呼び分けが必要だった.(64bit windowsの場合)

x86アプリから呼ぶ場合は,C:\Windows\Sysnative\tsdiscon.exeを呼ぶのじゃ
x64アプリから呼ぶ場合は,C:\Windows\System32\tsdiscon.exeを呼ぶのじゃ
アーキテクチャは環境変数から取ってくるのじゃ

タスクマネージャやエクスプローラから呼ぶ場合は,64bit windowsの場合はx64アプリのようだ.
vbaの実行エンジンがx86だとかx64で固定されているわけではなさそう.
共通の呼び方,用意しておいてくれんかな…

再現方法

  1. パスを書き分けた2種類のvbsを用意する
  2. エクスプローラ(x64アプリ)から呼び出すとSysnativeのパスを書いた方はエラーを吐く.
  3. 例えばあふw(x86版とx64版がある)などx86アプリから呼び出すと,System32のパスを書いた方はエラーを吐く

参考URL

徒然なるままに x64版Windowsで32ビットアプリケーションから64ビットアプリケーションを呼び出すには%Systmroot%\Sysnativeを指定する

ソース

  • 「いいえ」を押さなければ切断される
  • x86かx64か判別できないと実行されない
discon.vba
Set objShell = WScript.CreateObject("Wscript.Shell")
arch = objShell.Environment("Process").Item("PROCESSOR_ARCHITECTURE")

Select Case arch
    Case "x86", "32bit"
        cExec = "C:\Windows\Sysnative\tsdiscon.exe"
    Case "IA64", "AMD64"
        cExec = "C:\Windows\System32\tsdiscon.exe"
    Case Else
        MsgBox "32bitか64bitか分からないよ!"
        cExec = ""
End Select

If Len(cExec) > 0 Then
    iBtn = objShell.Popup( _
        "セッションを切断したくない場合には「いいえ」を押してください.",_
        10, "セッションを切断しますか?", vbYesNo + vbQuestion)

    Select Case iBtn
        Case vbYes, -1
            objShell.Exec(cExec)
    End Select
End If