>ばんのしゃーによかばんた さん 2005年 03月 11日 16時 29分 32秒
>ie.StatusText="pipe"
>If Left(ie.StatusText,InStr(ie.StatusText,vbNullChar)-1)="pipe" Then Exit For
そうそう、言い忘れました。
これは、IEの「障害」だと思いますが、
ie.StatusText="pipe"
If ie.StatusText="pipe" Then
は決してTrueになりません。
ごみが付きます。長さの設定を間違えているのだと思います。
CMD.EXEのコマンドグルーピング()の「障害」の回避方法です。
>ばんのしゃーによかばんた さん 2005年 03月 09日 19時 20分 36秒
>CScript.EXE //E:VBS - の代替です。
標準入力からスクリプトを渡すとき、一行なら
ECHO スクリプト行 | (仮に) MORE
で済みますが、複数行のときは、グルーピング()を使います。
グルーピング()中の)は^)でエスケープします。
ところが、CMD.EXEには「障害」があって、
グルーピング()中の)が正しく処理されないのです。
(
ECHO Set wShell=CreateObject("WScript.Shell"^)
ECHO wShell.PopUp("HOGE"^)
) | MORE
最初の)が消えて末尾に付きます。
これでは折角の機能が使えません。:-< :-< :-<
)を%%29にエスケープして、UnEscape()して逃げるという手もありますが、
びゅーちふるじゃない。
そこで、前後にREM行を付け加えます。
(
ECHO Rem ^)
ECHO Set wShell=CreateObject("WScript.Shell"^)
ECHO wShell.PopUp("HOGE"^)
ECHO Rem
) | MORE
これでばっちぐーです。お試しあれ。
>管理人むたぐち さん 2005年 03月 10日 18時 08分 40秒
>今日、ばんのしゃーによかばんた さん 2005年 03月 06日 16時 01分 18秒 のスクリプトを動かしたら、DEPが作動せず普通にスクリプトが実行されました。
あれ、それはちょっと残念。
>>データ実行防止機能の動作確認用サンプルとしてご利用ください。:-p
として使えませんね。
>良くわからない機能です…<DEP
そんなご無体な。DEPは悪くありませんから。
単にバッファオーバランでなかっただけです。きっと。
元々、未初期化データを参照し、そのデータに依存してメモリを破壊する
障害があって、長〜い「ファイル名」を指定すると、未初期化データが変化し、
たまたまDEPの監視領域を壊したのでしょう。
なので、もしMS開発者と知り合いの方がお読みなら、お伝えくださいまし。
バッファオーバランに注目してソースを見ても空振りですよ。
MSHTAをPurifyに掛けて未初期化データ参照とメモリ破壊を検出しなさい。
と。
ひよこさん、
> workフォルダには、東部社員売上yymmdd.csvファイルともう一つcsvファイルがあり常に2つ存在します。
スクリプトを実行する日時から yymmdd の部分が計算できるのであ
れば、対象のファイルのパス情報を動的につくりだす方法はいかが
でしょうか。
例えば、対象のファイルは、一日前であることが分かる場合は、こ
のようなスクリプトになるでしょうか。n日前であれば DateAdd
() 関数の第二引数を -n に変更すれば OK です。
Dim fso
Dim directory
Dim yesterday
Dim yymmdd
Dim filename
Dim filepath
Set fso = CreateObject("Scripting.FileSystemObject")
directory = "c:\"
yesterday = DateAdd("d", -1, Now())
yymmdd = Mid(Replace(FormatDateTime(yesterday, vbShortDate), "/", ""), 3)
filename = Replace("東部社員売上%s.csv", "%s", yymmdd)
filepath = directory & filename
If fso.fileExists(filepath) Then
' 本体
End If
メモ帳でスクリプトを修正した後、名前を付けて保存するつもりが、
上書き保存してしまいました。
メモ帳さんには自動でバックアップを取って欲しいものです。
NotePad.VBS
――――――――――――――――――――――――――――――――――――――
Path=WScript.Arguments(0)
Set fso=CreateObject("Scripting.FileSystemObject")
Set wShell=CreateObject("WScript.Shell")
fso.CopyFile Path,Path&".BAK"
Call wShell.Run("NotePad.EXE "&Path,,True)
If fso.GetFile(Path).DateLastModified=fso.GetFile(Path&".BAK").DateLastModified Then
Call fso.DeleteFile(Path&".BAK")
End If
――――――――――――――――――――――――――――――――――――――
>G-Luck さん 2005年 02月 28日 12時 06分 36秒
>現在、Excelを二つ起動していて、二番目に起動したExcelを取得したいのですが、その方法はあるでしょうか?
>現在は、GetObject(,"Excel.Application")で取得しているのですが、最初のものしか取得できません。
>環境 WinXP,Excel2003
GetObject(,"Excel.Application")で操作するには、
Excelを複数起動しないようにすればよいと思います。
具体的には以下のようにします。
関連付け起動だけを使う。
或いは、関連付け起動以外を以下のEXCEL.VBSに置き換える。
EXCEL.VBS
――――――――――――――――――――――――――――――――――――――
Set x2=CreateObject("Excel.Application")
Set xl=GetObject(,"Excel.Application")
If Not xl Is x2 Then x2.Quit
xl.Visible=True
xl.WorkBooks.Add
――――――――――――――――――――――――――――――――――――――
さて、私的に流行のie.PutPropertyを使うと、複数のExcelが操作出来ます。
x1.VBS 初めに
――――――――――――――――――――――――――――――――――――――
Set ie=CreateObject("InternetExplorer.Application")
ie.Visible=True
ie.StatusText="pipe"
Set dic=CreateObject("Scripting.Dictionary")
ie.PutProperty "Excel",dic
Do While TypeName(ie)="IWebBrowser2"
WScript.Sleep 1000
Loop
WScript.Echo "manager end."
――――――――――――――――――――――――――――――――――――――
x2.VBS ×n回
――――――――――――――――――――――――――――――――――――――
Set Shell=CreateObject("Shell.Application")
For Each ie In Shell.Windows
If Left(ie.StatusText,InStr(ie.StatusText,vbNullChar)-1)="pipe" Then Exit For
Next
If IsEmpty(ie) Then
WScript.Echo "pipe not found."
WScript.Quit
End If
Set dic=ie.GetProperty("Excel")
Set xl=CreateObject("Excel.Application")
xl.Visible=True
dic.Add xl,xl
Set xl=Nothing
WScript.Echo "I am number",dic.Count
――――――――――――――――――――――――――――――――――――――
x3.vbs 最後に
――――――――――――――――――――――――――――――――――――――
Set Shell=CreateObject("Shell.Application")
For Each ie In Shell.Windows
If Left(ie.StatusText,InStr(ie.StatusText,vbNullChar)-1)="pipe" Then Exit For
Next
Set dic=ie.GetProperty("Excel")
WScript.Echo dic.Count
For Each key In dic
Set xl=dic.Item(key)
dic.Remove key
xl.Quit
Next
ie.Quit
――――――――――――――――――――――――――――――――――――――
IE=Interprocess object Exchangerですね。
いりやさん、お返事ありがとうございます。
ファイルは処理後、バックアップフォルダへ移動させますので、
workフォルダには蓄積させません。
workフォルダには、東部社員売上yymmdd.csvファイルともう一つcsvファイルがあり常に2つ存在します。
拡張子での識別も無理なんです。。。
他のマシンの共有フォルダからスクリプトを使用して、自分のPCのフォルダにファイルをコピーしたいのですが、ホストマシンであるため、共有フォルダにアクセスしようとすると、ユーザ名とパスワードを求められます。前もって手動でログインしておけば問題ないのですが、これをスクリプトを使用して、ユーザ名とパスワードを設定するような事は可能でしょうか?
ひよこさん、
固定ではないがそのディレクトリにその形式で格納されるファイルは一つなのでしたっけ。それとも日がかわるとどんどん増えてくるのでしょうか。
東部社員売上050311.csv
東部社員売上050312.csv
東部社員売上050313.csv
:
:
ファイルを取得したいのですが、ファイル名が固定でない場合のファイル名の取得方法について教えていただけますでしょうか。
ファイル名のすぐ後ろに6桁の数字(yymmdd)がつきますが、可変なのです。
ファイルを開くときに、ファイル名が固定だと処理が可能ですけど、ここでワイルドカードは使えないんですよね。
このような場合はどのようにしたらよいのか、アドバイスをお願いします。
Set fso = CreateObject("Scripting.FileSystemObject")
Set tmpFile = fso.OpenTextFile("C:\My Documents\Temporary\work\東部社員売上*.csv",1,True)
・ファイルが存在する場所は決まっている
・ファイル名は、「東部社員売上yymmdd.csv」
今日、ばんのしゃーによかばんた さん 2005年 03月 06日 16時 01分 18秒 のスクリプトを動かしたら、DEPが作動せず普通にスクリプトが実行されました。
何の設定も弄ってないのに!
良くわからない機能です…<DEP
unixのwhichのようにベース名/ファイル名からPATH配下のフルパス名を得る方法は?
普通に考えると、環境変数のPATHとPATHEXTをばらして、組み合わせて、存否確認して、
と結構、面倒です。もっと簡単にできないかものかと。
バッチなら、
which.BAT
@ECHO OFF
FOR %%0 IN (%~$PATH:1) DO ECHO.%%0
FOR %%2 IN (%PATHEXT%) DO FOR %%3 IN (%1%%2) DO FOR %%4 IN (%%~$PATH:3) DO ECHO.%%4
VBSなら、
which.VBS
――――――――――――――――――――――――――――――――――――――
Option Explicit
Dim wShell
Dim Link
Dim Path
Set wShell=CreateObject("WScript.Shell")
Set Link=wShell.CreateShortCut(".LNK")
Do
Path=InputBox("Enter File Name or Base Name.",WScript.ScriptName,Path)
If Path="" Then Exit Do
On Error Resume Next
Call GetFullPath(Path)
On Error GoTo 0
Loop
Sub GetFullPath(Path)
Link.TargetPath=Path
Path=Link.TargetPath
End Sub
――――――――――――――――――――――――――――――――――――――
HTAのソースを丸ごとパイプでMSHTAに渡す、方法もあります。
これなら、MSHTAのコマンドラインを、F2.VBSより、もっと短くできます。
また、HTAソースをinsertなんとかで組み上げるよりもずっと簡単です。
H.VBS
――――――――――――――――――――――――――――――――――――――
Set fso=CreateObject("Scripting.FileSystemObject")
Set ie=CreateObject("InternetExplorer.Application")
ie.Visible=True
ie.PutProperty "VBScriptTypeInfo",Me
Set wShell=CreateObject("WScript.Shell")
Set oExec=wShell.Exec("MSHTA ""javascript:new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(0).ReadAll();""")
oExec.StdIn.Write fso.OpenTextFile(Left(WScript.ScriptFullName,InStrRev(WScript.ScriptFullName,"."))&"HTA").ReadAll
oExec.StdIn.Close
Do While IsEmpty(ie.GetProperty("window"))
WScript.Sleep 1000
Loop
Set window=ie.GetProperty("window")
ie.Quit
MsgBox window.document.documentElement.outerHTML
window.alert window.document.Title
Set window.document.body.onunload=GetRef("proc")
window.alert "hoge"
window.close
Do While htaStop=False
WScript.Sleep 1000
Loop
WScript.Quit
Sub proc()
MsgBox "hta onunload"
htaStop=True
End Sub
――――――――――――――――――――――――――――――――――――――
H.HTA 本来はH.VBSに文字列で組み込む。今回はコンセプト検証なのでファイル。
――――――――――――――――――――――――――――――――――――――
<html><head><title>HTA TITLE</title>
<script language="VBScript">
Set Shell=CreateObject("Shell.Application")
For Each ie In Shell.Windows
If Not IsEmpty(ie.GetProperty("VBScriptTypeInfo")) Then Exit For
Next
If IsEmpty(ie) Then
alert "ie not found."
close
End If
Set VBScriptTypeInfo=ie.GetProperty("VBScriptTypeInfo")
VBScriptTypeInfo.WScript.Echo "from hta 1"
VBScriptTypeInfo.WScript.Sleep 2000
VBScriptTypeInfo.WScript.Echo "from hta 2"
ie.PutProperty "window",window
</script>
</head><body></body></html>
――――――――――――――――――――――――――――――――――――――
>管理人むたぐち さん 2005年 03月 08日 23時 20分 14秒
>やっぱりデータ実行防止のエラーが出ます。
「データ実行防止」を設定しましたが、エラーは出ませんでした。
>Execに変えてもダメですね。cmd.exeでMSHTA以下の部分を実行してやっても、
やっぱりデータ実行防止のエラーが出ます。
>MSHTAにあまり長いオプションをつけるとダメってことなのかもしれません。
普通は「ファイル名」なので、こういう長い「ファイル名」のテストはしてない
のでしょうね。きっと。
出来るだけ短くしてみました。これならどうでしょう?
F2.VBS
――――――――――――――――――――――――――――――――――――――
Set ie=CreateObject("InternetExplorer.Application")
ie.Visible=True
'ie.StatusText="pipe"
ie.PutProperty "VBS",Me
Set wShell=CreateObject("WScript.Shell")
wShell.Run "MSHTA ""javascript:var ies=new ActiveXObject('Shell.Application').Windows();for(var k=ies.Count;k>0;k--){var ie=ies.Item(k-1);var VBS=ie.GetProperty('VBS');if(VBS){ie.PutProperty('window',window);break;}}if(!k){alert('ie not found.');close();}"""
Do While IsEmpty(ie.GetProperty("window"))
WScript.Sleep 1000
Loop
Set window=ie.GetProperty("window")
ie.Quit
MsgBox window.document.documentElement.outerHTML
window.VBS.WScript.Echo "hta"
Set window.document.body.onunload=GetRef("proc")
window.alert "hoge"
window.close
Do While htaStop=False
WScript.Sleep 1000
Loop
WScript.Quit
Sub proc()
MsgBox "hta onunload"
htaStop=True
End Sub
――――――――――――――――――――――――――――――――――――――
もっと複雑なHTAは、WSHから、
window.document.body.insertAdjacentHTML "<xxx>..."
などを使って、組み込んでいけばよいのかな。
おぉ。XP SP2のDEPが働くんですか。
MSHTA を DEP から除外設定すれば動くのかな?
私の環境は、Windows CE環境のデバッグが必要な関係で、
データ実行防止機能をOffにしているため、確認できませんでした。
http://support.microsoft.com/kb/891667
CScript.EXE //E:VBS - の代替です。
MORE | MSHTA.EXE vbscript:close(execute(CreateObject("Scripting.FileSystemObject").GetStandardStream(0).ReadAll())) | MORE
CScript.EXE //E:JS - の代替です。
MORE | MSHTA.EXE "javascript:eval(new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(0).ReadAll());close();" | MORE
ただし、WScript.*は使えません。
ばんのしゃーによかばんた様ありがとうございました。HTAのスクラッチ
起動できました。これを公開なさったときに丁度 HTA の windowオブジェクト
取得方法を考えていたので「渡りに船」でした。そーかー VARIANT なら
なにを書いても OK で、マーシャリングも IE が勝手にしてくれるんですね。
色々勉強になりました。
管理人様が動かないと書かれてましたが私も最初は D.VBS & D.HTA , F.VBS
は動きませんでした。Win98 という古めかしい環境のせいかもしれませんが
私の場合は ie.PutProperty('window',window) が出来ませんでした(エラーは
表示せず止まったまま)。F.VBSのほうだけいろいろいじった結果 MSHTA 実行
前に'window'プロパティを null で定義してプロパティの書き込み待ちを
IsNull() でチェックすると行けました。ちなみに C.VBS でなさっていたイベントを使う方法は MSHTA 実行で Me オブジェクトを取得できませんでした。IE の
プロパティの存在意味も?だし なんだかよくわからん世界だ…
今後は私のスクリプトツールの定番方法になるでしょう、しかし確かに
セキュリティには良くない方法ですね。
To: うつ猫 さん
Shell.Applicationを使えば可能です。
Set Fs = WScript.CreateObject("Scripting.FileSystemObject")
Set Shell = WScript.CreateObject("Shell.Application")
For Each sArg In WScript.Arguments
If Fs.FileExists(sArg)Then
dDate=Fs.GetFile(sArg).DateLastModified
'ここにファイルの修正のコード入れる
Call ModifyDate(sArg,dDate)
End If
Next
MsgBox "終了"
Sub ModifyDate(path,date)
Shell.NameSpace(Fs.GetParentFolderName(path)).ParseName(Fs.GetFileName(path)).ModifyDate=date
End Sub
To: ばんのしゃーによかばんた さん 2005年 03月 08日 16時 18分 20秒
> コマンドラインが長すぎて、バッファオーバランしたのでしょうか。
> Runか、MSHTAか、その先か。Execに変えても駄目でしょうか?
Execに変えてもダメですね。cmd.exeでMSHTA以下の部分を実行してやっても、
やっぱりデータ実行防止のエラーが出ます。
MSHTAにあまり長いオプションをつけるとダメってことなのかもしれません。
データ実行防止機能は、「システムのプロパティ」→「詳細設定」→「パフォーマンス」
→「データ実行防止」で設定できます。
デフォルトでは「重要なWindowsのプログラムおよびサービスについてのみ有効にする」
にチェックが入っています。
>うつ猫 さん 2005年 03月 08日 17時 56分 27秒
>ファイルを修正した後、ファイルの更新日時は元のファイルのまましたいです。
>出来ますでしょうか?
FileSystemObjectの、DateLastModified プロパティを保存しておいて、
ファイル修正後に、設定しなおせば良いと思います。
>Ω さん 2005年 03月 05日 14時 02分 54秒
>WSHでwinの環境変数に追加したいと考えています。
WSHのEnvironmentプロパティを使えば、
1) SYSTEM環境変数の登録追加(マイコンピュータプロパティの詳細で設定するのと同じ)
2) USER環境変数の登録追加(同上)
3) いまWSHが動いているプロセスの環境変数の書き換え(子プロセスへも継承)
4) 同上(子プロセスへ継承しない)
ができます。
サンプル:上記3)のケース
Set WshShell = WScript.CreateObject("WScript.Shell")
Set WshEnv = WshShell.Environment("process")
WshEnv("ZZZZZ")="12345"
WshShell.run "CMD"
run "CMD" で開くコマンドプロンプトで echo %ZZZZZ% とすれば 12345 となります。
ファイルを修正した後、ファイルの更新日時は元のファイルのまましたいです。
出来ますでしょうか?
教えてください!お願いします。
もう少し実用性のある1行スクリプトをば。
クリップボードの中身を取り出す。
MSHTA.EXE "javascript:new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write(clipboardData.getData('text'));close();" | MORE
クリップボードにテキストを書き込む。
ECHO aaaaa | MSHTA.EXE "javascript:clipboardData.setData('text',new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(0).ReadAll());close();"
1行の中にテクが凝縮されていて、俳句や短歌みたいですね。:-)
>むちゃ さん 2005年 03月 07日 13時 58分 48秒
>> >後は、HTA(*.hta)でも window.status は生きているようなので >StatusTextChange イベントに接続して、
>> >HTA(*.hta)の自作(擬似)ステータスバーに文字列を表示できるかなぁ・・・>と思っちゃったりもして。
>以前はそれで(正確には setTimeout メソッド)やっていたのですが、
>他の動作があまりにも遅くなったためにやめました。
>(100ms 〜 500ms 間隔で window.stats の値を取得していました)
そんなに遅くなりますか?
ひょっとして、毎回、同じ処理=重い処理をしてませんか?
イベントでもタイマループでも同じですが、
高頻度側の処理を軽くする/短絡する工夫が必須ですよね。
こんな感じ。↓
甲案
status=window.status
If status<>previous Then
previous=status
hogehoge.status=status
End If
乙案
If window.status=previous Then Exit Sub
previous=window.status
hogehoge.status=window.status
>管理人むたぐち さん 2005年 03月 06日 23時 37分 34秒
>このスクリプトを実行すると、htaを実行する段階で
>XP SP2のデータ実行防止機能が働いて途中で止まりました(汗
あれまぁ。未修正のセキュリティホールが見つかったってことでしょうか。
コマンドラインが長すぎて、バッファオーバランしたのでしょうか。
Runか、MSHTAか、その先か。Execに変えても駄目でしょうか?
>初めて見たなぁ、データ実行防止のダイアログ。
データ実行防止機能の動作確認用サンプルとしてご利用ください。:-p
これって、ハードとソフトの二つあるんですよね?
有効にするかどうかの設定もあるんですよね?
デフォルトは無効でしょうか?
私のところでは異常を検出することなく動いています。
これって、悪い意味のフォルトトレラントで動いているってことですよね。
動くと言っても、セキュリティホールを開けたままでは嬉しくないですね。
TO ちゃっぴ さん 2005年 03月 07日 21時 28分 11秒
ちゃっぴ さま
ご返答有難うございます。
> Remote Machineで任意のCodeを実行したいというのであれば、
> Win32_Process Class に Create Methodなるものが存在します。
Win32_Processクラスを利用して、以下のスクリプトを完成する
ことが出来ました。
strCMD = InputBox("リモートで実行するコマンドを入力して下さい。")
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objSWbemServices = objSWbemLocator.ConnectServer (strComputer, _
strNameSpace, strUser, strPass)
Set RemoteCom = objSWbemServices.get("Win32_Process")
rc = RemoteCom.create("cmd.exe /c " & strCMD)
今のところ、リモートマシン上でコマンドが実行されているようです。
有難うございました。またよろしくお願い致します。
To タイガージェットシーン さん 2005年 03月 07日 14時 15分 17秒
> VBS上で前回はVBS上でDOSコマンドを実行する方法を
> 質問させていただきましたが、リモートマシンにDOSコマンド
> を実行する方法はありますでしょうか。
惜しいところまではいってますので・・・
Remote Machineで任意のCodeを実行したいというのであれば、
Win32_Process Class に Create Methodなるものが存在します。
また、Pingを打つのであれば、Win32_PingStatusなるものも
存在します。
以前質問させていただきました者です
(魔界の仮面弁士さま。。その際は有難うございました。)
VBS上で前回はVBS上でDOSコマンドを実行する方法を
質問させていただきましたが、リモートマシンにDOSコマンド
を実行する方法はありますでしょうか。
リモートマシンのホスト名、adminユーザ、Passwdを指定して
行えれば幸いです。
イメージとしては。
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objWMIService = objSWbemLocator.ConnectServer (strComputer, strNameSpace, strUser, strPass)
Set wShell = CreateObject("WScript.Shell")
Set oExec = objWMIService.wShell.Exec("cmd.exe /c ping 192.168.0.1")
上記スクリプトでは、「そんなメソッドはない」とエラーが出ます。
宜しくお願いします。
To: ばんのしゃーによかばんた さん
> >むちゃ さん 2005年 03月 04日 01時 17分 14秒
> >実は、HTA(*.hta)で ExecWB メソッドを使用したいと思いまして・・・
>
> document.execCommand()で代替出来ませんか?
execCommand メソッドではだめなようです。
印刷関連(特に印刷プレビュー)の識別子がないので;;
> >後は、HTA(*.hta)でも window.status は生きているようなので >StatusTextChange イベントに接続して、
> >HTA(*.hta)の自作(擬似)ステータスバーに文字列を表示できるかなぁ・・・>と思っちゃったりもして。
>
> window.setInterval()
> で代替でしょうか。
以前はそれで(正確には setTimeout メソッド)やっていたのですが、
他の動作があまりにも遅くなったためにやめました。
(100ms 〜 500ms 間隔で window.stats の値を取得していました)
管理人により削除
To: ばんのしゃーによかばんた さん
このスクリプトを実行すると、htaを実行する段階で
XP SP2のデータ実行防止機能が働いて途中で止まりました(汗
初めて見たなぁ、データ実行防止のダイアログ。
WSH/IE(HTM)連携では、HTMファイルなしで、VBSファイルだけで
IEの中にスクラッチ(about:blank)からHTMLDocumentが作れました。
しかし、WSH/HTA連携ではそういうことは出来ませんでしたよね。
ところが、驚くなかれ、HTAファイルなし、テンポラリファイルもなしに、
VBSファイルだけでWSH/HTA連携が出来ます。
F.VBS
――――――――――――――――――――――――――――――――――――――
Set ie=CreateObject("InternetExplorer.Application")
ie.Visible=True
ie.StatusText="pipe"
ie.PutProperty "VBScriptTypeInfo",Me
Set wShell=CreateObject("WScript.Shell")
wShell.Run "MSHTA ""javascript:var Shell=new ActiveXObject('Shell.Application');var ies=new Enumerator(Shell.Windows());for (;!ies.atEnd();ies.moveNext()){var ie = ies.item();if(ie.GetProperty('VBScriptTypeInfo')) break;}if(!ie){alert('ie not found.');close();}var VBScriptTypeInfo=ie.GetProperty('VBScriptTypeInfo');VBScriptTypeInfo.WScript.Echo('from hta 1');VBScriptTypeInfo.WScript.Sleep(2000);VBScriptTypeInfo.WScript.Echo('from hta 2');ie.PutProperty('window',window);"""
Do While IsEmpty(ie.GetProperty("window"))
WScript.Sleep 1000
Loop
Set window=ie.GetProperty("window")
ie.Quit
MsgBox window.document.documentElement.outerHTML
window.alert window.document.Title
Set window.document.body.onunload=GetRef("proc")
window.alert "hoge"
window.close
Do While htaStop=False
WScript.Sleep 1000
Loop
WScript.Quit
Sub proc()
MsgBox "hta onunload"
htaStop=True
End Sub
――――――――――――――――――――――――――――――――――――――
これで、HTAはWSHの完全なフロントエンドですね。:-)
WSH/HTM連携なんかよりWSH/HTA連携のほうが遥かにパワフルで、
本命、最強の組合せ、ではありますまいか。
これは、もう魔道かもしれない。:-p
従前のCScript -e:VBS -は使えなくなりましたが、それに代わる、
1行スクリプトのアイデアが閃きました。
コマンドプロンプトで、
MSHTA javascript:alert('hoge');close();
MSHTA javascript:confirm(prompt('hoge','fox'));close();
MSHTA vbscript:close(msgbox("hoge"))
MSHTA vbscript:close(msgbox(inputbox("hoge")))
MSHTA vbscript:execute("msgbox(""hoge""):close")
MSHTA "about:<script>alert('hoge');close();</script>"
MSHTA "about:<input type=file onchange=alert(this.value)>"
IExplore "about:<input type=file onchange=alert(this.value)>"
IExploreはセキュリティレベルの制約があるので、MSHTAがいいですね。
WSHとHTAの間でオブジェクトをIEの何処に入れて受け渡すか?
これまでは、HTMLDocumentのeventプロパティを使ってましたが、
今回は、IEのPutProperty/GetPropertyを使ってみました。
D.VBS
――――――――――――――――――――――――――――――――――――――
Set ie=CreateObject("InternetExplorer.Application")
ie.Visible=True
ie.PutProperty "VBScriptTypeInfo",Me
Set wShell=CreateObject("WScript.Shell")
wShell.Run Left(WScript.ScriptFullName,InStrRev(WScript.ScriptFullName,"."))&"HTA"
Do While IsEmpty(ie.GetProperty("window"))
WScript.Sleep 1000
Loop
Set window=ie.GetProperty("window")
ie.Quit
MsgBox window.document.documentElement.outerHTML
window.alert window.document.Title
Set window.document.body.onunload=GetRef("proc")
window.alert "hoge"
window.close
Do While htaStop=False
WScript.Sleep 1000
Loop
WScript.Quit
Sub proc()
MsgBox "hta onunload"
htaStop=True
End Sub
――――――――――――――――――――――――――――――――――――――
D.HTA
――――――――――――――――――――――――――――――――――――――
<html><head><title>HTA TITLE</title>
<script language="VBscript">
Set Shell=CreateObject("Shell.Application")
For Each ie In Shell.Windows
If Not IsEmpty(ie.GetProperty("VBScriptTypeInfo")) Then Exit For
Next
If IsEmpty(ie) Then
alert "ie not found."
close
End If
Set VBScriptTypeInfo=ie.GetProperty("VBScriptTypeInfo")
VBScriptTypeInfo.WScript.Echo "from hta 1"
VBScriptTypeInfo.WScript.Sleep 2000
VBScriptTypeInfo.WScript.Echo "from hta 2"
ie.PutProperty "window",window
</script>
</head></html>
――――――――――――――――――――――――――――――――――――――
このIEのPutProperty/GetPropertyは、汎用のshared memory用途に
使えそうです。
>門外漢 さん 2005年 02月 26日 21時 35分 52秒
>工夫すればさらに信頼済みサイトゾーンも可能です。
これは、どうも駄目みたいです。XP SP2
>・イントラネットゾーン
これは、可能ですね。
しかし、セキュリティゾーンの偽装を許す危険な仕様ではないでしょうか?
<!-- saved from url=(0017)http://localhost/ -->
を埋め込んだページをインターネットに置いておくと、
ローカルにそのまま取り込んだときに、イントラネットゾーンで動きます。
マイコンピュータゾーンのロックダウンも効きません。
ところで、WEBページをローカルに保存すると、NTFSの場合にはファイルに
ZoneIDが付けられると聞いたのですが、どこにあるのでしょう?
ZoneIDの表示や判別方法はあるのでしょうか?
>むちゃ さん 2005年 03月 04日 01時 17分 14秒
>実は、HTA(*.hta)で ExecWB メソッドを使用したいと思いまして・・・
document.execCommand()で代替出来ませんか?
>後は、HTA(*.hta)でも window.status は生きているようなので >StatusTextChange イベントに接続して、
>HTA(*.hta)の自作(擬似)ステータスバーに文字列を表示できるかなぁ・・・>と思っちゃったりもして。
window.setInterval()
で代替でしょうか。
――――――――――――――――――――――――――――――――――――――
>ちゃっぴ さん 2005年 03月 03日 23時 53分 03秒
>遊んでしたら、こんなのが見つかりました。
あるんですね。こういうものが。
>ばんのしゃーによかばんた さん 2005年 03月 02日 16時 16分 51秒
>以前、WSH/WSF/VBS/JSなどのIconHandlerにSCFのものを使う話をしました。
>>ただ、指定のない大多数のファイルがアイコンなしアイコンになってしまうので、
>という問題がありました。これは、URLのものを使うと、よいようです。
駄目ですね。:-<
レジストリにDefaultIconキーがあるので、効くのか、と思ったら、
固定のアイコンしか表示されません。:-<
そもそも、
良く言えば、リンクを作れば、アイコンが変えられる。
悪く言えば、アイコンを変えるには、リンクを作らなければならない。
というのがおかしいと思いません?
任意のファイルで、プロパティでアイコンが変更できればよいのに。
設定情報は、.WSHのような別ファイルではなく、
\05SummaryInformationのようにStreamに入れる。
こういうIconHandlerとPropertySheetHandlerがあればよいに。
はじめまして。最近WSHを勉強しているものです。
いきなり質問です。
WSHでwinの環境変数に追加したいと考えています。
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Exec("set ZZZ=yyy")
を実行しても環境変数に追加されていません。
どうしてでしょうか?
どうしたらうまくいくのでしょうか?
To: むちゃさん ばんのしゃーによかばんた さん
はじめまして 興味がわきましたので。
pipeのieを生かしておけば、HTAのフロントエンドが常に浮かんだ状態でも
任意起動のスクリプトからドライブできるっていう事でいいんですよね。
すんません ぼけてました
>定数と変数では扱いが異なることからVBSでの実装は
> 文字列定数:VARIANT
> 文字列変数:VARIANTへのポインタ(LPVARIANT) ← VT_BYREFです
>になっているように思います。
1つの書きこみで2つ言うのわルール違反ですが
KOU さん へ
{SPACE}表記はもともとないのでわ?手もとの資料でも記述がないし
スペースは特殊な文字でもないので対応する必要がないような。
ちなみに私もエラーが出ました。(Win98)
ooさん、ありがとうございます。
WshShell.Sendkeys(" ")
↑で出来ました。chr(13) や chr(8)でも試してみようと思います!!
>WshShell.Sendkeys("{SPACE}")
WshShell.Sendkeys(" ") でできますよ。
他の制御文字に付いても、"{ENTER}" や "{BS}" でなく chr(13) や chr(8) のように書いてもいけるようです。
はじめまして。Sendkeysについて、お聞きしたい事がありましたので投稿させて頂きました。
Sendkeysを使って、Spacebarをストロークさせたいのですが,
WshShell.Sendkeys("{SPACE}")
↑のように書いても、エラーが出てしまいます。
ENTERは{ENTER}や~など,キーに対応したコードがあるようですが,Spacebarに対応したコードが見つかりません。Sendkeysでは、Spacebarをストロークさせることはできないのですか?
ちょいと口挟み。以前&hffff問題を解決していただいたものです。
Dynacallのパラメータ挙動でVARIANT型の変換に悩んだものとして
ちょっと前に話題になさっていた InvokeVerb を定数の扱いから
類推してみました。
環境はWIN98ですがこの辺は多分変わらないとふんでます。
これを追試験するのはかなり面倒なので結果だけを書きますと
DynaCallでDLLに文字列引数をLPWSTRとして渡すと
文字列定数:文字列へのポインタそのもの(BSTRのアドレス)
文字列変数:VT_BSTRへのポインタ(=VARIANTへのポインタ)
がDLLに渡されます。
これにかかわる部分をDYNWRAP.CPPで見るとVBSからの引数の
VARIANTに格納してある実体を単純に渡しているだけです。
定数と変数では扱いが異なることからVBSでの実装は
文字列定数:VARIANT
文字列変数:VARIANTへのポインタ(LPVARIANT)
になっているように思います。
またこの予想があっていれば VBSはDispatch I/Fに 現在自分が取り出せる
VARIANTを参照など関係なく渡していると考えられます。
InvokeVerb の引数がおかしいのは VARIANTを引数にすることは本来VBSでは
出来ないことからVBSのための実装になっていないせいだと考えています。
私の当て推量があっていればこの問題はVBSとオートメーションオブジェクトの
どっちに非があるとは言えないような。
ちなみにDynWrapの引数の扱いがわかったのでほとんどのWin32API使えるように
なりました。HTAを使って窓操作が(見かけ上は)簡単に出来るようになって
うれしー。VBSの解析にも結構使えます。苦労した甲斐がありました。
ちょっと興味がありまして・・・
皆さんは、Script を書くときにどういう Editor を使っていますか?
私は、VBA もしくは、VB の Editor で単体Test(出来れば)を行って、
そこからWSHとかに落としてやる("As"を"'As"で置換)な感じで
作成することが多いですが・・・
なんか、効率的な WSHの作成方法、および Debug方法がありましたら
ご教授願います。(*- -)(*_ _)ペコリ
To: ばんのしゃーによかばんた さん
> >むちゃ さん 2005年 03月 02日 15時 38分 40秒
> >起動している HTA(*.hta) の InternetExplorer Object(WebBrowser Object)を取得することはできないでしょうか?
>
> なので、苦労します。:-< 例えば、データの遣り取りは、
>
> 中略・・・
>
> WSHからIE/HTMを自由自在に操作できたように、
> WSHからHTAをフロントエンドとして自由自在に操作できます。
> ブラボー!
ほうほう、IE を中継して操作ですか・・・
これはすごいですね(^-^)
> うーん、だんだんよく分からない世界になって来ましたね。
> ここまで来ると邪道というより極道かも。:-p
そうですね。
読み始めは、「???」とよくわかりませんでしたので、
じっくりと拝見させていただきました。(笑)
> なので、苦労します。:-< 例えば、データの遣り取りは、
やはり、HTA の場合、
Shell.Application の Window コレクションから取得できないことから、
InternetExplorer Object(WebBrowser Object)は取得できないみたいですね。
実は、HTA(*.hta)で ExecWB メソッドを使用したいと思いまして・・・
IE(*.html)では自分の InternetExplorer Object を取得して実行が可能なのですが。
後は、HTA(*.hta)でも window.status は生きているようなので StatusTextChange イベントに接続して、
HTA(*.hta)の自作(擬似)ステータスバーに文字列を表示できるかなぁ・・・と思っちゃったりもして。
ですが、根本的に取得が出来なかったので手をこまねいていたのです。
To ばんのしゃーによかばんた さん 2005年 02月 15日 17時 29分 32秒
WMIを扱う上で便利なTool ScriptOmatic が VersionUp したので
http://www.microsoft.com/downloads/details.aspx?FamilyID=09dfc342-648b-4119-b7eb-783b0f7d1178&DisplayLang=en
遊んでしたら、こんなのが見つかりました。
Dim objWMIService ' As WbemScripting.SWbemServices
Dim colItems ' As WbemScripting.SWbemObjectSet
Dim objItem ' As WbemScripting.SWbemObject
Dim strBuf() ' As String
Dim i ' As Long
Set objWMIService = GetObject( _
"winmgmts:\\.\root\CIMV2\Applications\MicrosoftIE")
Set colItems = objWMIService.ExecQuery( _
"SELECT Zone, Level FROM MicrosoftIE_Security")
ReDim strBuf(colItems.Count)
i = 0
For Each objItem In colItems
With objItem
strBuf(i) = .Zone & vbTab & .Level
End With
i = i + 1
Next
WScript.Echo Join(strBuf, vbLF)
>むちゃ さん 2005年 03月 02日 15時 38分 40秒
>起動している HTA(*.hta) の InternetExplorer Object(WebBrowser Object)を取得することはできないでしょうか?
なので、苦労します。:-< 例えば、データの遣り取りは、
>ばんのしゃーによかばんた さん 2005年 02月 12日 19時 39分 08秒
>一方、WSHとHTAの連携は、と言えば、標準入出力のパイプ以外は難しく、
>それも自由度がないので、あまり使えません。
>そこで、IEをパイプ代わりにして、WSH-(IE)-HTAの連携を試してみました。
今回、更に、WSHとHTA間で、相互に相手の関数を呼び出してみました。:-)
B.VBS
――――――――――――――――――――――――――――――――――――――
Set ie=CreateObject("InternetExplorer.Application")
ie.Visible=True
ie.Navigate "about:blank"
Do While ie.Busy Or ie.ReadyState<>4
WScript.Sleep 100
Loop
ie.Document.Title="pipe"
Set wShell=CreateObject("WScript.Shell")
wShell.Run Left(WScript.ScriptFullName,InStrRev(WScript.ScriptFullName,"."))&"HTA"
ie.Document.body.innerText="MsgBox ie.Document.Title"
Do While ie.Document.body.innerText<>""
WScript.Sleep 1000
Loop
Set ie.Document.body.ondblclick=GetRef("proc")
ie.Document.body.onclick
ie.Document.body.innerText="close"
Do While ie.Document.body.innerText<>""
WScript.Sleep 1000
Loop
ie.Quit
WScript.Quit
Sub proc()
MsgBox "proc from hta"
End Sub
――――――――――――――――――――――――――――――――――――――
B.HTA
――――――――――――――――――――――――――――――――――――――
<script language="VBscript">
Set Shell=CreateObject("Shell.Application")
For Each ie In Shell.Windows
If TypeName(ie.Document)="HTMLDocument" Then
If ie.Document.title="pipe" Then Exit For
End If
Next
If IsEmpty(ie) Then
alert "ie not found."
close
End If
Set ie.Document.body.onclick=GetRef("htaproc")
setInterval "proc",1000
Sub proc()
If ie.Document.body.innerText<>"" Then
Execute ie.Document.body.innerText
ie.Document.body.innerText=""
End If
End Sub
Sub htaproc()
MsgBox "call from wsh"
ie.Document.body.ondblclick
End Sub
</script>
――――――――――――――――――――――――――――――――――――――
※pipeのIEをクリックしてはいけません。:-p
なので、非表示にしておいたほうがいいですね。
更に、更に、WSHとHTA間で、
相互に相手内のオブジェクトを参照/操作できます!
HTAからWSHのWScript.Sleep/Echoを呼び出したり、
WSHの関数をGetRefしてHTAのbody.unload Eventに接続したり。
C.VBS
――――――――――――――――――――――――――――――――――――――
Set ie=CreateObject("InternetExplorer.Application")
ie.Visible=True
ie.Navigate "about:blank"
Do While ie.Busy Or ie.ReadyState<>4
WScript.Sleep 100
Loop
ie.Document.Title="pipe"
Set ie.Document.body.ondblclick=Me
Set wShell=CreateObject("WScript.Shell")
wShell.Run Left(WScript.ScriptFullName,InStrRev(WScript.ScriptFullName,"."))&"HTA"
Do While IsNull(ie.Document.body.onclick)
WScript.Sleep 1000
Loop
Set window=ie.Document.body.onclick
ie.Quit
MsgBox window.document.documentElement.outerHTML
window.alert window.document.Title
Set window.document.body.onunload=GetRef("proc")
window.alert "hoge"
window.close
Do While htaStop=False
WScript.Sleep 1000
Loop
WScript.Quit
Sub proc()
MsgBox "hta onunload"
htaStop=True
End Sub
――――――――――――――――――――――――――――――――――――――
C.HTA
――――――――――――――――――――――――――――――――――――――
<html><head><title>HTA TITLE</title>
<script language="VBscript">
Set Shell=CreateObject("Shell.Application")
For Each ie In Shell.Windows
If TypeName(ie.Document)="HTMLDocument" Then
If ie.Document.title="pipe" Then Exit For
End If
Next
If IsEmpty(ie) Then
alert "ie not found."
close
End If
Set vbglobal=ie.Document.body.ondblclick
vbglobal.WScript.Echo "from hta 1"
vbglobal.WScript.Sleep 2000
vbglobal.WScript.Echo "from hta 2"
Set ie.Document.body.onclick=window
</script>
</head></html>
――――――――――――――――――――――――――――――――――――――
WSHからIE/HTMを自由自在に操作できたように、
WSHからHTAをフロントエンドとして自由自在に操作できます。
ブラボー!
うーん、だんだんよく分からない世界になって来ましたね。
ここまで来ると邪道というより極道かも。:-p
管理人により削除
管理人により削除