myara CG blog

CG Design Blog. Thoughts, experiments and experiences.

キーボードをスクリプトで打つ

どこかでこういう記事を見たことがあるような気がするけど、思い出せない・・・。
dejavu?

誰か知っていたら教えて下さい。


夢だったのかな?

最近仕事が忙しくて、夢にもCGが出てくるんですよね・・・。おそろしい。


そういえば、以前ある朝に彼女が「肩が痛い」と言いながら起きてきました。
まだ寝ぼけてた俺は「一回ウェイトを外して、付け直してみれば?」と答えちゃいました。
「寝ぼけてる~!www」、
俺は頑固だから「寝ぼけてない!!」と否定しながら目が冷めました。
「だからウェイトを・・・  あれ?」
ヤバい、CGやりすぎだ・・・と思いました。


すいません、話に戻ります。


昨日はTERAさんのブログでこの記事を読みました:

Softimage Script : Python でショートカット入力

要するに、Windows Script Host を 利用して、WSHのSendKeysコマンドでキーボード操作ということです。
WSHでこんな事も出来るなんて知りませんでした。


まずは簡単な例文です。F1(help)をスクリプトで打ってみましょう:

#Python
import win32com.client
shell = win32com.client.Dispatch("WScript.shell")
shell.SendKeys("{F1}")


//JScript
var wsh = new ActiveXObject("WScript.Shell")
wsh.SendKeys("{F1}")


'VBScript
set wsh = CreateObject("WScript.Shell")
wsh.SendKeys "{F1}"



普通のアルファベットキーは""で書けば良いですが、F1, とか特別なキーは特徴な書き方があります:
http://www.devguru.com/technologies/wsh/quickref/wshshell_SendKeys.html


なので、"{F1}" じゃなくて、"F1" を書いてしまったら、F + 1 と認識されてしまいます。

色々やってみて、なんか上手く行かない場合は多い。

分かってきたことは:

・ マウスのカソルの位置
・ キーのリリースタイミング
・ ウィンドウが出てくるタイムラグ

が邪魔してくるってこと。

マウスのカソルの位置によって、キーが入力されるところが変わってしまいます。
そして、キーのリリースタイミングが悪いと、スクリプトとキーボードの入力が混ざってしまいます。


例えば、スクリプトエディターを開いて、以下のコードを試して見ましょう。

//JScript
var wsh = new ActiveXObject("WScript.Shell");
wsh.SendKeys("7");



これを:
マウスで実行すると「7」がビューポートに入力されて、Render Treeが開きます。
ホットキーの「F5」で実行すると、スクリプトエディターのコードに「7」が打たれます。

そして、俺みたいにRUNを「Ctrl+Enter」のホットキーでやっているなら、
Material Managerが出てしまうことが多い。
これは上手くキーを離さないと、Ctrlがスクリプトと混ざって「Ctrl+7」になってしまうからです。



そして、ターゲットのウィンドウが出るまで待たないと、違うところに入力されてしまいます。

例えば、

//JScript
var wsh = new ActiveXObject("WScript.Shell");
OpenView("Explorer");
wsh.SendKeys("m");



このコードを見ると、Explorerが開かれてMaterialsに変わると思いますよね!
でも現実は違います。

Explorerが出てきますが、出てくる前に「m」が入力されてしまうからMaterialsに切り替わりません。

どうする?

以前書いたこの記事が役に立ちます。
VBScriptのWaitを利用してXSIに時間を与えましょう。

予めに「sleep.vbs」を用意してからコードをこんな感じに編集してみましょう:

//JScript
var wsh = new ActiveXObject("WScript.Shell");
OpenView("Explorer");
wsh.run("D:\\sleep.vbs 0", 2, 1)
wsh.SendKeys("m");



これで、Explorerを開いて、0秒を待って、「m」を入力します。

そうなんです。0秒でも十分みたい。
あなたはまだ386系のPCを使っていたら違うかもしれません。

めでたしめでたし・・・


と思ったら、

また違う問題が出てきました。

既にExplorerが開いている場合は上手く行かないんです。WHY?!
知らんけど、思いついたことは一つだけ。

Explorerが開いていたら、閉じてやろう!

//JScript
var views = Application.Desktop.ActiveLayout.Views
for (var i=0; i< views.count; i++){
if (views(i).name == "Explorer"){
views(i).state = siClosed;
}
}
wsh.run("D:\\Sleep.vbs 0", 2, 1)
OpenView("Explorer")
wsh.run("D:\\Sleep.vbs 0", 2, 1)
wsh.SendKeys("m");


不思議なことに、Explorerを閉じた後にもWaitが必要です。


なんかコードが美しくないですね。
しょうがないかな。

それじゃ、


追記

JScriptでSleepのもう一つの作り方はこの記事に書きました。

そして、もう一つ分かったのは、時間の問題ではないかもしれません。
通にwhile time のスリープを使ったら上手く行きませんでした。WshShellでスリープを呼ばないと上手く行かないです。
ポイントは時間じゃないかもしれません。

まだまだ実験が足りないです。