Pocket

Windowsを使用していて、特定のマシンに対し自動的にリモートデスクトップをしてプログラムを実行してくれるような、そんなプログラムが無いかなぁ…

PowerShellもVBScriptも、リモートデスクトップを起動するまではGUIから操作出来るんだけど、その後のキー入力を認識してくれなかったし…(Send-Keysで送ってもリモートデスクトップ側では認識してくれない。PowerShellではスタートメニューの表示までは出来たんだけど…WASP入れてもダメだった…)

他の手段は無いのかと、ちょっと調べてみたところGUI操作用プログラム「UWSC」なるものが存在していると知った。

UWSC

http://www.uwsc.info/

今まで知らなかったんだけど、かなり昔からあるプログラムのようだ。
GUI操作をマクロ化してくれて、なおかつコードを書いてスクリプトを組めると…

素晴らしい!なんで今まで知らなかったんだろう…

UWSCは有料版と無料版があるようで、有料版は以下の機能が追加されるようだ。

・ EXE化ツールが付属しています。(EXE化後は単体での実行が可能であり、ライセンスフリーにて配布できます)
・ IE(Web)用記録ツールが付属しています。(Web上の動作をUWSCのスクリプトとして記録する事ができます)
・ HTMLを利用した画面関数が使えます。
・ EXCELシート用関数が使えます。(OpenOffice.org/LibreOfficeの表計算(Calc)に対しても可)
・ デバッガが付属しています。

今回の利用方法では無料版で問題なく使用出来そうだ。

Sponsored Links

スクリプト

というわけで、早速スクリプトを書いてみた。

使い方としては、対象となるWindowsマシンのリスト「host.list」を読込み、リストの上から順に全てのマシンに対してユーザ関数「PROCESS」で定義しているテストを実行するというもの。

実行後はリモートデスクトップをログオフするようにしている。

●host.list

#hostname,ip_addr,user,password
Server1,192.168.0.100,Admin,pass
Server2,192.168.0.101,Admin,pass
Server3,192.168.0.102,Admin,pass

左から順にホスト名、IPアドレス、ユーザ名、パスワードとしている。

次にスクリプトファイル。

●Remote_Test.UWS

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// 【リモートデスクトップ一括プログラム実行スクリプト】
// 作成者:Blacknon
// 作成日:2014/02/15
// 
// 備考:
// 「HOST_LIST」に存在するサーバに対し、ユーザ関数「PROCESS」に指定されている
// 処理を実行させるUWSCで動作するスクリプト。
// 使用の際はUWSCを操作端末にダウンロードして実行させること。
// また、実際の使用時においては「// 変数格納」の箇所の書き換えを行う事を推奨。
// 
// UWSC
// http://www.uwsc.info/
// 
// ※UWSCフリーの方で動作することを確認済。
// 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// 変数格納
   FOLDER_PATH    = "C:\Users\Work\Documents\WORK"
   HOST_LIST      = "C:\Users\Work\Documents\WORK\host.list"
   LOG_MODEL_NAME = ".log"
 
 
// ワークフォルダ作成用日時取得
   GETTIME()
   WORK_DATE      = G_TIME_YY4+G_TIME_MM2+G_TIME_DD2
   WORK_TIME      = G_TIME_HH2+G_TIME_NN2+G_TIME_SS2
   WORK_FOLDER    = WORK_DATE+"_"+WORK_TIME+"_WORK"
   WORK_FOLDER    = FOLDER_PATH+"\"+WORK_FOLDER
   NOW_TIME       = G_TIME_YY4+"/"+G_TIME_MM2+"/"+G_TIME_DD2+" "+G_TIME_HH2+":"+G_TIME_NN2+":"+G_TIME_SS2
 
 
// ワークフォルダ作成
   Doscmd("mkdir "+WORK_FOLDER)
 
 
// HOST_LIST読込
   LIST_ID        = FOPEN(HOST_LIST, F_READ) 
   LIST_NUM       = FGET(LIST_ID,F_LINECOUNT)
 
 
// HOST_LISTを元に処理を開始
   FOR i = 2 TO LIST_NUM
        HOSTNAME  = FGET( LIST_ID, i, 1 )
        IPADDR    = FGET( LIST_ID, i, 2 )
        USER      = FGET( LIST_ID, i, 3 )
        PASS      = FGET( LIST_ID, i, 4 )
         
     // ログファイル作成
        LOG_FILE  = WORK_FOLDER+"\"+WORK_DATE+"_"+WORK_TIME+"_"+HOSTNAME+LOG_MODEL_NAME
        LOG_ID    = FOPEN(LOG_FILE, F_WRITE)
         
        FPUT(LOG_ID,"==============================================")
        GETTIME()
        NOW_TIME = G_TIME_YY4+"/"+G_TIME_MM2+"/"+G_TIME_DD2+" "+G_TIME_HH2+":"+G_TIME_NN2+":"+G_TIME_SS2
        FPUT(LOG_ID,NOW_TIME)
        FPUT(LOG_ID," ")
        FPUT(LOG_ID,"HostName :"+HOSTNAME)
        FPUT(LOG_ID,"IPAddress:"+IPADDR)
        FPUT(LOG_ID,"PROCESS START")
        FPUT(LOG_ID," ")
         
        GETTIME()
        NOW_TIME = G_TIME_YY4+"/"+G_TIME_MM2+"/"+G_TIME_DD2+" "+G_TIME_HH2+":"+G_TIME_NN2+":"+G_TIME_SS2
        FPUT(LOG_ID,NOW_TIME)
        FPUT(LOG_ID,"Start Remote Desktop")
        RDP_START(IPADDR,USER,PASS,LOG_ID)
        Sleep(3)
         
        GETTIME()
        NOW_TIME = G_TIME_YY4+"/"+G_TIME_MM2+"/"+G_TIME_DD2+" "+G_TIME_HH2+":"+G_TIME_NN2+":"+G_TIME_SS2
        FPUT(LOG_ID,NOW_TIME)
        FPUT(LOG_ID,"Start Process")
        PROCESS(WORK_FOLDER,HOSTNAME,LOG_ID)
        Sleep(3)
         
        GETTIME()
        NOW_TIME = G_TIME_YY4+"/"+G_TIME_MM2+"/"+G_TIME_DD2+" "+G_TIME_HH2+":"+G_TIME_NN2+":"+G_TIME_SS2
        FPUT(LOG_ID,NOW_TIME)
        FPUT(LOG_ID,"Exit Remote Desktop")
        RDP_END(LOG_ID)
         
        GETTIME()
        NOW_TIME = G_TIME_YY4+"/"+G_TIME_MM2+"/"+G_TIME_DD2+" "+G_TIME_HH2+":"+G_TIME_NN2+":"+G_TIME_SS2
        FPUT(LOG_ID,NOW_TIME)
        FPUT(LOG_ID,"ALL PROCESS END")
        FPUT(LOG_ID," ")
        FPUT(LOG_ID,"==============================================")
        FCLOSE(LOG_ID)
   NEXT
 
 
 
 
// *****************************************************************
// 関数
 
// 処理関数PROCESS
//  この関数内で各マシンで実行する処理を記述する。
//   用途に応じ、適時修正を
Procedure PROCESS(WORK_FOLDER,HOSTNAME,LOG_ID)
   FPUT(LOG_ID,"  リモートデスクトップの画面ID取得")
   ID        = GETID("リモート デスクトップ接続","TscShellContainerClass")
   FPUT(LOG_ID,"  リモートデスクトップ画面のアクティブ化")
   ACW(ID,0,0)
    
   FPUT(LOG_ID,"  スタートメニュー表示")
   SCKEY(ID, VK_ALT, VK_HOME)
   Sleep(1)
    
   FPUT(LOG_ID,"  コマンドプロンプトを実行")
   SENDSTR(0,"cmd")
   SCKEY(ID, VK_CTRL, VK_V)
   Sleep(1)
   KBD(VK_ENTER)
   Sleep(1)
    
   FPUT(LOG_ID,"  マウスの位置をウィンドウの相対位置に設定")
   MOUSEORG(ID)
   MMV(250,250)
    
   FPUT(LOG_ID,"  コマンドプロンプトに右クリックでペーストをし、システムを起動")
   SENDSTR(0,"control.exe /name Microsoft.System")
   BTN(RIGHT,CLICK)
   KBD(VK_P)
   KBD(VK_ENTER)
   Sleep(2)
    
   FPUT(LOG_ID,"  システムのスクリーンショットを保存")
   GETTIME()
   WORK_DATE = G_TIME_YY4+G_TIME_MM2+G_TIME_DD2
   WORK_TIME = G_TIME_HH2+G_TIME_NN2+G_TIME_SS2
   PIC1      = WORK_FOLDER+"\"+WORK_DATE+"_"+WORK_TIME+"_"+HOSTNAME
   SAVEIMG(PIC1,ID)
    
Fend
 
 
 
 
// *****************************************************************
// 以下、書き換え非推奨
 
// リモートデスクトップ接続開始
Procedure RDP_START(Server,User,Password,LOG_ID)
   FPUT(LOG_ID,"  Procedure RDP_START START")
   FPUT(LOG_ID,"  Access Server")
   FPUT(LOG_ID,"    "+Server)
   FPUT(LOG_ID,"  Access User")
   FPUT(LOG_ID,"    "+User)
   FPUT(LOG_ID," ")
    
   FPUT(LOG_ID,"  リモートデスクトップ起動")
   EXEC("mstsc /w:1024 /h:768")
   SLEEP(2)
    
   FPUT(LOG_ID,"  リモートデスクトップの画面ID取得")
   ID = GETID("リモート デスクトップ接続")
   FPUT(LOG_ID,"  リモートデスクトップ画面のアクティブ化")
   ACW(ID,0,0)
    
   FPUT(LOG_ID,"  接続サーバ情報入力")
   SENDSTR(0,Server)
   SCKEY(ID, VK_CTRL, VK_V)
   KBD(VK_ENTER)
   SLEEP(1)
    
   FPUT(LOG_ID,"  リモートデスクトップ ログイン情報入力用の画面ID取得")
   ID = GETID("Windows セキュリティ")
   FPUT(LOG_ID,"  ユーザ名入力ダイアログへ移動")
   KBD(VK_DOWN)
   SLEEP(1)
    
   FPUT(LOG_ID,"  ユーザ名入力")
   SENDSTR(0,User)
   SCKEY(ID, VK_CTRL, VK_V)
   SLEEP(1)
   KBD(VK_DOWN)
    
   FPUT(LOG_ID,"  パスワード入力")
   SENDSTR(0,Password)
   SCKEY(ID, VK_CTRL, VK_V)
   SLEEP(1)
    
   KBD(VK_ENTER)
   Sleep(5)
    
   FPUT(LOG_ID," ")
   FPUT(LOG_ID,"  Procedure RDP_START END")
   FPUT(LOG_ID," ")
   FPUT(LOG_ID," ")
Fend
 
 
Procedure RDP_END(LOG_ID)
   FPUT(LOG_ID," ")
   FPUT(LOG_ID,"  Procedure RDP_END START")
   FPUT(LOG_ID," ")
    
   FPUT(LOG_ID,"  現在接続しているリモートデスクトップ画面を取得")
   ID = GETID("リモート デスクトップ接続")
   FPUT(LOG_ID,"  リモートデスクトップ画面のアクティブ化")
   ACW(ID,0,0)
    
   FPUT(LOG_ID,"  スタート画面表示")
   SCKEY(ID, VK_ALT, VK_HOME)
   SLEEP(1)
    
   FPUT(LOG_ID,"  ログオフコマンド実行")
   SENDSTR(0,"shutdown /l /f")
   SCKEY(ID, VK_CTRL, VK_V)
   SLEEP(1)
   KBD(VK_ENTER)
    
    
   FPUT(LOG_ID," ")
   FPUT(LOG_ID,"  Procedure RDP_END END")
   FPUT(LOG_ID," ")
   FPUT(LOG_ID," ")
Fend

例として、ユーザ関数「PROCESS」の中ではOSのシステム画面表示をさせて、その画面をスクリーンショットとして保存するような動作をさせている。
当然、「PROCESS」を書き換えて違うプログラムを実行させることができる。

例えば、100台近いWindows OSに対してバッチを実行させないといけないのに、PowerShellのリモート操作有効化もPSexecを使用できるような設定もしていない時には、バッチファイルをRDP経由でデスクトップに転送し、そのまま実行させることも可能だ。

注意点として、プログラムを実行するマシン上でセキュリティ警告が出ない設定を行う事と、sleepの秒数で次にプログラムが起動するタイミングを調整している箇所があるため、実際の環境に併せて「sleep」の秒数を設定してあげる事。

参考ページ

このスクリプトを作成する上で、参考になったページを掲載しておく。
書き換えの際にも参考になると思う。

UWSC コバヤシ式

UWSCで,CSVファイルの行・列を読み込んで処理するサンプルコード

+++ 上野メモ帳 +++ テキストファイル読み書き – UWSC

+++ 上野メモ帳 +++ 相対位置を取得 – UWSC

SAVEIMG – UWSC Tech

UWSCで自動ログイン – SGGK偽証券 トップ – FC2

Pocket

Written by blacknon

インフラ系のSE。一時期はプログラマ。 仮想化とオープンソースに興味あり。一日中寝てたい今日このごろ。 スペインとかで働きたいなぁ…(シエスタがあるので)

This article has 1 comments

  1. Pingback: UWSCを使ってみた。 | ESORO system design

Leave a Comment

メールアドレスが公開されることはありません。