ちなみに、試してないのですが、cscript.exeの//U オプションを使えば、
WScript.StdInにUnicodeが渡るはずなので、
Set StdIn = Fs.GetStandardStream(0,True)
と同じ効果が得られると思います。
私の場合は、既存のほかのスクリプトに影響が出るので、
こちらの方法は止めました。
最初、とおりすがりさんご紹介の方法を使って記述していったのですが、
結局バイナリにしてファイル化するにはBASP21を使用するしかない(?)ので、
それなら、と思い、全部BASP21を使って記述することにしました。
Set Stream1 = CreateObject("ADODB.Stream")
Set Stream2 = CreateObject("ADODB.Stream")
Set StdIn = Fs.GetStandardStream(0,True)
Stream1.Open
Stream1.Type = adTypeText
Stream1.Charset = "unicode"
Stream1.WriteText StdIn.ReadAll
Stream1.Position = 0
Stream1.Type = adTypeBinary
Stream1.Position = 2
Stream2.Open
Stream2.Type = adTypeBinary
Stream1.CopyTo Stream2
Stream2.SaveToFile "C:\test.bin",adSaveCreateOverWrite
barray = bobj.BinaryRead ("C:\test.bin")
Fs.DeleteFile "C:\test.bin"
としておき、後は
bobj.Form(barray,"comment")
などで各フォームのテキストの値は読めました。
が、
bobj.FormSaveAs barray,"file1",sTempFilePath
で出来た画像ファイル、ヘッダはJPEGなんですけど、その後にNULL文字が並び、
ファイルの半分以上が破損していました。
>ばんのしゃーによかばんた さん 2004年 12月 08日 15時 27分 24秒
>WSH5.6のFileSysytemObjectのReadLine/ReadAllには、
>重大障害(データ破壊)があるようです。:-<
>データ中にNUL文字があると、その後がNUL文字に化けます。
これですね、原因は。
なんとタイムリーな。
そこで、
Stream1.WriteText StdIn.ReadAll
を
Stream1.WriteText ReadAll(StdIn)
(ばんのしゃーによかばんた さん 2004年 12月 11日 22時 13分 40秒のReadAll代替関数)
を使って読み込むことで、ようやく成功!
これでWSH + BASP21 + AnHTTPDでファイルアップローダが作れます。
とりあえず自分用(ブログに写真を投稿するとき)に使わせていただきます。
みなさま、ありがとうございました。
>管理人むたぐちさん
>さて、実はここからが分からないんです。
>enctype="multipart/form-data" とあるだけに、multipartなデータなんですが、
>どうやって切り分ければ良いのか…。
ご参考までに、ASPだとこういう手でやります
http://www.kcat.zaq.ne.jp/yumenokunisha/develop/bin2str.htm
オリジナルに近いのはこちら
http://www.asp101.com/articles/jacob/scriptupload.asp
ご参考になれば。
>管理人むたぐち さん 2004年 12月 14日 21時 35分 17秒
'multipart'から連想すると、'CDO'が使えませんか。
以下、無責任モードです。
>ばんのしゃーによかばんた さん 2004年 11月 04日 16時 01分 11秒
>CDOを使って読む方法です。これなら、なんでもごじゃれですね。
>path="ファイル名"
>Set CDOMsg=WScript.CreateObject("CDO.Message")
>Set Stm=CreateObject("ADODB.Stream")
>Stm.Open
>Stm.LoadFromFile path
>CDOMsg.DataSource.OpenObject stm,"_Stream"
この代わりに喰わせる。
>WScript.Echo CDOMsg.Subject
>WScript.Echo CDOMsg.From
>WScript.Echo CDOMsg.TextBody
こん辺のかわりに、BodyPartのコレクションBodyPartsを見る。
私はCDOでメールの添付ファイルを取り出そうとして、頓挫してます。
はじめまして。VBSについてご質問がありまして、ご教授願いたいと思いまして、書き込ませていただきます。
HPを作っているのですが、Windowを閉じる関数などがありましたら教えてください。スクリプトで色々な処理を行って、それらが全て終了した後に強制的にWindowを閉じたいと思っています。Window.close()を使ってみたのですが、そうすると、ブラウザ上に「ウィンドウを閉じます。」のようなダイアログが出てしまいます。そういったものを一切出さずに、強制的に閉じる方法があれば是非ご教授願います。
To: ばんのしゃーによかばんた さん
お答えありがとうございます。
要するに、こういうことですよね?
Set Stream1 = CreateObject("ADODB.Stream")
Set Stream2 = CreateObject("ADODB.Stream")
Set StdIn = Fs.GetStandardStream(0,True)
Stream1.Open
Stream1.Type = adTypeText
Stream1.Charset = "unicode"
Stream1.WriteText StdIn.ReadAll
Stream1.Position = 0
Stream1.Type = adTypeBinary
Stream1.Position = 2
Stream2.Open
Stream2.Type = adTypeBinary
Stream1.CopyTo Stream2
Stream2.SaveToFile "C:\test.bin",adSaveCreateOverWrite
さて、実はここからが分からないんです。
enctype="multipart/form-data" とあるだけに、multipartなデータなんですが、
どうやって切り分ければ良いのか…。
バイナリをあまりまともに扱ったことのないツケが回ってきたかな…。
もうちょっと考えてみます。
>ばんのしゃーによかばんた さん 2004年 11月 14日 15時 15分 39秒
>>管理人むたぐち さん 2004年 11月 10日 20時 30分 50秒
>>シェルの機能だけで書庫を扱えれば、結構有効利用できそうですけど。
>やっぱり駄目ですね。却下。
と諦めていましたが、その後、
>ばんのしゃーによかばんた さん 2004年 12月 01日 17時 34分 24秒
>ファイルを「コピー」して、アプリのアイコンに「貼り付け」られるんですね。
>ドラッグ&ドロップと同じですが、スクリプトで出来るってことですね。
>例えば、ファイルを「選択」して、「コピー」して、SendToClipboardに
>「貼り付け」なんてことが、出来そう。でも使い道が。。。
てなことが出来ることが分かったので、試してみました。
>リスト
>Shell.NameSpace(〜.ZIP)で。
――――――――――――――――――――――――――――――――――――――
'aaa.ZIP
If WScript.Arguments.Count<>1 Then WScript.Quit
Set fso=CreateObject("Scripting.FileSystemObject")
Set Shell=CreateObject("Shell.Application")
Set Folder=shell.NameSpace(fso.GetAbsolutePathName(WScript.Arguments(0)))
For k=0 To 8
WScript.StdOut.Write Folder.GetDetailsOf(,k)
If k<8 Then
WScript.StdOut.Write vbTab
Else
WScript.StdOut.Write vbCRLF
End If
Next
For Each FolderItem In Folder.Items
For k=0 To 8
WScript.StdOut.Write Folder.GetDetailsOf(FolderItem,k)
If k<8 Then
WScript.StdOut.Write vbTab
Else
WScript.StdOut.Write vbCRLF
End If
Next
Next
WScript.Quit
――――――――――――――――――――――――――――――――――――――
>削除
>Shell.NameSpace(〜.ZIP)で。
>InvokeVerb("削除(&D)")もできますが、プロンプトが出るので、どうかな、ですね。
――――――――――――――――――――――――――――――――――――――
'aaa.ZIP\bbb
If WScript.Arguments.Count<>1 Then WScript.Quit
Set fso=CreateObject("Scripting.FileSystemObject")
Set Shell=CreateObject("Shell.Application")
arg=fso.GetAbsolutePathName(WScript.Arguments(0))
Set Folder=shell.NameSpace(fso.GetParentFolderName(arg))
Set FolderItem=Folder.ParseName(fso.GetFileName(arg))
FolderItem.InvokeVerb("delete")
WScript.Quit
――――――――――――――――――――――――――――――――――――――
※同期です。プロンプトが出ます。
>解凍
>Shell.NameSpace(〜.ZIP)では、InvokeVerb("コピー(&C)")が効かない。
>Shell.Open(〜.ZIP)で、InvokeVerb("コピー(&C)")して、explorerのフォルダに
>SendKeysでメニュー操作して「貼り付け」ればよいようですが、そこまでやるか、ですね。
――――――――――――――――――――――――――――――――――――――
'aaa.ZIP\bbb dir
If WScript.Arguments.Count<>2 Then WScript.Quit
Set fso=CreateObject("Scripting.FileSystemObject")
Set Shell=CreateObject("Shell.Application")
arg=fso.GetAbsolutePathName(WScript.Arguments(0))
Set sFolder=shell.NameSpace(fso.GetParentFolderName(arg))
Set sFolderItem=sFolder.ParseName(fso.GetFileName(arg))
Set dFolder=shell.NameSpace(fso.GetAbsolutePathName(WScript.Arguments(1)))
dFolder.CopyHere sFolderItem
WScript.Quit
――――――――――――――――――――――――――――――――――――――
※CopyHereが使えます。同期です。
>全解凍
>Shell.Open(〜.ZIP)で、SendKeysでメニュー操作。
――――――――――――――――――――――――――――――――――――――
'aaa.ZIP dir
If WScript.Arguments.Count<>2 Then WScript.Quit
Set fso=CreateObject("Scripting.FileSystemObject")
Set Shell=CreateObject("Shell.Application")
Set sFolder=shell.NameSpace(fso.GetAbsolutePathName(WScript.Arguments(0)))
Set dFolder=shell.NameSpace(fso.GetAbsolutePathName(WScript.Arguments(1)))
dFolder.CopyHere sFolder.Items
WScript.Quit
――――――――――――――――――――――――――――――――――――――
※CopyHereが使えます。同期です。
>追加、置換
>解凍の逆。置換はプロンプトが出る。
――――――――――――――――――――――――――――――――――――――
'aaa bbb.ZIP
If WScript.Arguments.Count<>2 Then WScript.Quit
Set fso=CreateObject("Scripting.FileSystemObject")
Set wShell=CreateObject("WScript.Shell")
Set Shell=CreateObject("Shell.Application")
wShell.Run "explorer.exe",0,True
For n=0 To 9
For Each ie In Shell.Windows
If ie.Visible=False Then
If ie.Busy Or ie.ReadyState<>4 Then
ElseIf InStr(TypeName(ie.Document),"IShellFolderViewDual")=1 Then
Exit For
End If
End If
ie=Empty
Next
If Not IsEmpty(ie) Then Exit For
WScript.Sleep 100
Next
If IsEmpty(ie) Then
WScript.Echo "Failed"
WScript.Quit
End If
Set Shell=ie.Document.Application
arg=fso.GetAbsolutePathName(WScript.Arguments(0))
Set sFolder=shell.NameSpace(fso.GetParentFolderName(arg))
Set sFolderItem=sFolder.ParseName(fso.GetFileName(arg))
Set dFolder=shell.NameSpace(fso.GetAbsolutePathName(WScript.Arguments(1)))
dFolder.CopyHere sFolderItem
ie.Quit
WScript.Quit
――――――――――――――――――――――――――――――――――――――
※CopyHereが非同期なので、'Hidden Explorer'の技を使います。
作成
――――――――――――――――――――――――――――――――――――――
'aaa
If WScript.Arguments.Count<>1 Then WScript.Quit
Set fso=CreateObject("Scripting.FileSystemObject")
Set wShell=CreateObject("WScript.Shell")
Set Shell=CreateObject("Shell.Application")
arg=fso.GetAbsolutePathName(WScript.Arguments(0))
wShell.Run "explorer.exe",0,True
For n=0 To 9
For Each ie In Shell.Windows
If ie.Visible=False Then
If ie.Busy Or ie.ReadyState<>4 Then
ElseIf InStr(TypeName(ie.Document),"IShellFolderViewDual")=1 Then
Exit For
End If
End If
ie=Empty
Next
If Not IsEmpty(ie) Then Exit For
WScript.Sleep 100
Next
If IsEmpty(ie) Then
WScript.Echo "Failed"
WScript.Quit
End If
ie.Navigate fso.GetParentFolderName(arg)
Do While ie.Busy Or ie.ReadyState<>4
WScript.Sleep 100
Loop
Set Folder=ie.Document.Folder
If Folder.Self.Path<>shell.NameSpace(fso.GetParentFolderName(arg)).Self.Path Then
WScript.Echo Folder.Self.Path
WScript.Quit
End If
Set FolderItem=Folder.ParseName(fso.GetFileName(arg))
FolderItem.InvokeVerb("copy")
ie.Navigate "shell:sendto"
Do While ie.Busy Or ie.ReadyState<>4
WScript.Sleep 100
Loop
If ie.Document.Folder.Title<>"SendTo" Then
WScript.Echo ie.Document.Folder.Title
WScript.Quit
End If
Set dFolder=ie.Document.Folder
dFolder.Items.Item("圧縮 (zip 形式) フォルダ.ZFSendToTarget").InvokeVerb("paste")
ie.Quit
WScript.Quit
――――――――――――――――――――――――――――――――――――――
※shell.NameSpace()からだと、
FolderItem.InvokeVerb("copy")
dFolder.Items.Item("圧縮 (zip 形式) フォルダ.ZFSendToTarget").InvokeVerb("paste")
が使えないので、'Hidden Explorer'の技を使います。
また、非同期でもあります。
>ばんのしゃーによかばんた さん 2004年 12月 12日 18時 08分 28秒
>これだと、先のストリームを使う方法は使えませんね。
いろいろと方法がごじゃりましたが、この件に限っては、
#! C:\Windows\System32\CScript.EXE wshbbs.vbs
が一番簡単確実なのではありますまいか。:-p
――――――――――――――――――――――――――――――――――――――
バイナリの標準入出力について。
awkでは、ファイル名/dev/stdinなどで、標準入出力になりますよね。
Windowsでも、そういうことが汎用に出来ると、とても便利なんですが。
例えば、ADODB.Streamで、LoadFromFile("/dev/stdin")みたいに。
何とかならんものでしょうか。
試しに、
CON
CONIN$
CONOUT$
をfso.OpenTextFileに指定するとコンソールにはなりましたが、
標準入出力にはなってくれません。残念。:-<
原理的には、CreateFile("/dev/stdin")をGetStdHandle()に振り替えるだけ。
これがDOS FunctionならアセンブラでTSRを作ればよさそうなところです。
Windowsは、よく知らないのですが、ポートとかデバイスとかを作るのでしょうか。
こういうのって誰か作ってそうな気もします。
教えてください。
Windows NTについてですが、スクリプトエンジンのない、NTへスクリプトエンジンをインストールしたのですが、vbsファイルが認識されません。
なぜでしょうか。
》 管理人むたぐち さん
> さて、どこに報告すればいいのかな?
現行製品に対する意見/報告であれば、確実なのは、MVPインシデントを
利用する事では無いでしょうか。次期(あるいはその次)のバージョンの
修正項目に盛り込まれる可能性が高くなるのだそうです。
(それが未契約なら、eXConnのMVP WISHフォーラムを使うとか)
> ばんのしゃーによかばんた さん 2004年 12月 12日 18時 07分 43秒
> 実は、ProgIDとCLSIDの相互変換機能が欲しい、
> 参照設定で探すファイル名も欲しい、
> と思って、以下のVBScriptを作っていたら、
WMIのWin32_ProgIDSpecificationクラスとWin32_TypeLibraryActionクラス
を
使用すればできるかなとも思いましたが・・・
> 参照設定で探すファイル名
までは、出てきませんね。やはりRegstryが無難そうですね。
>管理人むたぐち さん 2004年 12月 11日 23時 29分 19秒
>ということは、やはり、#!の後の文字列のプログラムを実行して、
>そこは読み捨て、そこから最後までを標準入力に
>渡しているという実装みたいですね。
「標準入力に」→「一時ファイルにして」
スクリプトファイル名をUsage:〜やエラーメッセージに出しているスクリプトに
とっては、ちょっと意外な実装です。
これだと、先のストリームを使う方法は使えませんね。
#! C:\Windows\System32\CMD.EXE /C ECHO
とすると、一時ファイル名が表示されるはずです。
――――――――――――――――――――――――――――――――――――――
>管理人むたぐち さん 2004年 12月 11日 23時 07分 15秒
>一応試してはみたんですが、得られる標準入力の値は
>BASP21のKconvメソッドで調べたところ、ちゃんと
>Unicodeになっていて、読めているらしいのは間違いないんですが、
>サイズが全然あいません。
>30KB程度のJPEGを読み込んでも、数バイトになってしまいます。
>何らかの理由でデータの欠損が発生していると思われます。
お急ぎのようだったし、
過去に、EUCやSJISバイト列をunicode扱いで読んだり書いたりされているので、
あの説明で十分だろうと、詳しく説明しなかったのですが、
↑ちょっと心配な文章です。
念のため、
一般視聴者向け(?)にも、改めて説明すると、※大雑把です。ちょっと不正確。
fso.GetStandardStream(0,True)
は、unicodeにしてくれるわけではありません。
fso.GetStandardStream(0,False)
はSJISの入力データをUnicodeにしてくれます。
fso.GetStandardStream(0,True)
は、入力データをunicodeだと信じて、そのまま渡してくれます。
したがって、EUCだろうが、バイナリだろうが、読めますが、
Unicodeになるわけではありません。
"abcdefg"というバイト列は、(下位、上位)として、(a,b) (c,d) (e,f)
という3文字になります。この順をリトル・エンディアンと言います。
"g"は端数なので読めません。
読んだデータをファイルに落とすには、unicodeで書き込むと、先頭に
Unicodeのリトル・エンディアンを表すByte Order Mark (FF,FE)が付きます。
そこで、ADODB.Streamに、type=Text/charset=unicodeで、WriteTextします。
positionを0にして、Binaryに変えて、先頭にBOMがあるので、
positionを2から別のBinary Streamにコピーします。
それをSaveToFileします。
原因調査で、どういうデータが読めたかを調べるだけなら、
escape()して、FSOで書き出せば分かります。
直接見るときは、
For k=1 To LenB(xxx)
MidB(k,1)
Next
で、"a","b","c","d","e","f"が取れます。
For k=1 To Len(xxx)
Mid(k,1)
Next
は、ChrW(AscB("a")+AscB("b")*256),,,が取れます。
以前、バッチファイルで、ECHOで改行しない方法はないものか、
と探していたのですが、
@ECHO OFF
SET /P x=abc<NUL
SET /P x=efg<NUL
で出来ます。:-)
ところが、これを何に使おうと思って、探していたのか、が思い出せない。:-<
バッチでProgressBar擬を出そうとでもしていたのかなぁ。
#! C:\Windows\System32\more.com
@echo off
echo Content-Type: text/plain
echo.
echo SERVER_NAME=%SERVER_NAME%
echo REMOTE_HOST=%REMOTE_HOST%
echo REMOTE_ADDR=%REMOTE_ADDR%
というtest.batを実行すると、
@echo off echo Content-Type: text/plain echo. echo SERVER_NAME=%SERVER_NAME% echo REMOTE_HOST=%REMOTE_HOST% echo REMOTE_ADDR=%REMOTE_ADDR%
と表示されます。
ということは、やはり、#!の後の文字列のプログラムを実行して、
そこは読み捨て、そこから最後までを標準入力に
渡しているという実装みたいですね。
となると、VBS on WSHがダメだった理由は、やっぱりWSHに由来する
何らかの問題があるんだと思われます。
さて、どこに報告すればいいのかな?
ごめんなさい、fso.GetStandardStream(0,True)の方は
実は投げてしまいました。
一応試してはみたんですが、得られる標準入力の値は
BASP21のKconvメソッドで調べたところ、ちゃんと
Unicodeになっていて、読めているらしいのは間違いないんですが、
サイズが全然あいません。
30KB程度のJPEGを読み込んでも、数バイトになってしまいます。
何らかの理由でデータの欠損が発生していると思われます。
そこでとりあえず、ローカルのファイルを移動するだけのショボイ実装に
なってしまいましたが、ちょっと急ぎだったもので。
batの方は、また(ぉぃ)忘れていました!
忘れないうちに今ためしてきます。
CScript強制実行の新方式です。
A.CMD
――――――――――――――――――――――――――――――――――――――
CScript %~f0:a.vbs %*
――――――――――――――――――――――――――――――――――――――
A.CMD:A.VBS
――――――――――――――――――――――――――――――――――――――
MsgBox "!"
――――――――――――――――――――――――――――――――――――――
※ストリームを使うところに新規性があるかな。
その応用。アイデア止まり。フィージビリティスタディは未。
[応用-1]
A.EXE
――――――――――――――――――――――――――――――――――――――
"CScript %~f0:a.vbs %*"をCreateProcessする。JScript.NETで作る?
――――――――――――――――――――――――――――――――――――――
[応用-2]
A.CGI
――――――――――――――――――――――――――――――――――――――
#!C:\Windows\System32\CMD.EXE /C @C:\xxx\xxx.CMD
――――――――――――――――――――――――――――――――――――――
C:\xxx\xxx.CMD
――――――――――――――――――――――――――――――――――――――
@C:\Windows\System32\CScript.EXE //NoLogo %1:A.VBS %2 %3 %4 %5 %6 %7 %9
――――――――――――――――――――――――――――――――――――――
※これなら#!を'!に書き換える必要はありません。
そういえば、以下はどうなりましたでしょうか。結果に興味津々です。
――――――――――――――――――――――――――――――――――――――
>ばんのしゃーによかばんた さん 2004年 11月 20日 18時 00分 16秒
>>管理人むたぐち さん 2004年 11月 19日 23時 04分 56秒
>>batなど他の言語でも検討してから、AnHTTPDコミュの方に
>>問い合わせてみます。
>そうですね。例えば、
>#! C:\Windows\System32\MORE.COM
>とかすれば、ちゃんと読めているかどうか、分かりますね。
――――――――――――――――――――――――――――――――――――――
>ばんのしゃーによかばんた さん 2004年 12月 07日 18時 07分 28秒
>>管理人むたぐち さん 2004年 12月 06日 22時 46分 30秒
>>WScript.StdIn、あるいは他の方法で、WSHでバイナリの標準入力を
>>読み込む方法は、ありますでしょうか?
>例の、
>fso.GetStandardStream(0,True)
>で、unicode扱いで読めます。
――――――――――――――――――――――――――――――――――――――
「警告:悪質なスクリプトを検出しました」
はどうやってるのか、と思っていましたら、こうやっていたのですね。
――――――――――――――――――――――――――――――――――――――
[HKEY_CLASSES_ROOT\CLSID\{0D43FE01-F093-11CF-8940-00A0C9054228}\InprocServer32]
@="C:\\Program Files\\Common Files\\Symantec Shared\\Script Blocking\\ScrBlock.dll"
"ThreadingModel"="Both"
"ScriptBlockingInProcServer32"="C:\\WINDOWS\\system32\\scrrun.dll"
――――――――――――――――――――――――――――――――――――――
実は、ProgIDとCLSIDの相互変換機能が欲しい、参照設定で探すファイル名も欲しい、
と思って、以下のVBScriptを作っていたら、
FileSystemObjectのInProcServer32が変なのに気付いたのでした。
(作成途中)
――――――――――――――――――――――――――――――――――――――
Set wShell=CreateObject("WScript.Shell")
Do
ans=InputBox("")
If ans="" Then Exit Do
If Left(ans,1)="{" Then
xCLSID ans
Else
xProgID ans
End If
Loop
Sub xProgID(ProgID)
WScript.Echo RegRead("HKCR\" & ProgID & "\")
CLSID=RegRead("HKCR\" & ProgID & "\CLSID\")
WScript.Echo CLSID
Call xCLSID(CLSID)
End Sub
Sub xCLSID(CLSID)
WScript.Echo RegRead("HKCR\CLSID\" & CLSID & "\")
WScript.Echo RegRead("HKCR\CLSID\" & CLSID & "\InprocServer32\")
WScript.Echo RegRead("HKCR\CLSID\" & CLSID & "\InprocServer32\ScriptBlockingInprocServer32")
WScript.Echo RegRead("HKCR\CLSID\" & CLSID & "\ProgID\")
WScript.Echo RegRead("HKCR\CLSID\" & CLSID & "\VersionIndependentProgID\")
WScript.Echo RegRead("HKCR\CLSID\" & CLSID & "\TypeLib\")
WScript.Echo RegRead("HKCR\CLSID\" & CLSID & "\Version\")
End Sub
Function RegRead(Key)
On Error Resume Next
RegRead=wShell.RegRead(Key)
End Function
――――――――――――――――――――――――――――――――――――――
ReadAllの代替関数
――――――――――――――――――――――――――――――――――――――
Function ReadAll(file)
Dim block
Do While Not file.AtEndOfStream
block=block & file.Read(4096)
Loop
ReadAll=block
End Function
――――――――――――――――――――――――――――――――――――――
先にファイルサイズが分かっているなら、
file.Read(oFile.Size)
でもよいかな。
>ばんのしゃーによかばんた さん 2004年 12月 08日 15時 27分 24秒
>WSH5.6のFileSysytemObjectのReadLine/ReadAllには、
>重大障害(データ破壊)があるようです。:-<
>データ中にNUL文字があると、その後がNUL文字に化けます。
>例えば、(NUL)+260個の'a' を読むと、260個の(NUL)+1個の'a' に化けます。
>※ 260 が 閾値? みたいです。
>Read(4096)などで読めば、性能も低下しないで、安全かも。
>※ なぜか、Read()だと、問題なく読める。
障害原因について、当て推量。
ReadLine/ReadAllの不定長要求では、最初、バッファ長の初期値260バイトで
バッファを取り、足りないと、より大きいバッファを取り直して、データを移す。
このとき、memcpy()を使うべきところを、strcpy()を使ったため、
NUL文字の後ろが消えた。
Readの指定長要求では、バッファを取り直さないので、大丈夫。
障害作り込み原因について、当て推量。
未初期化バッファ対策で、realloc()を使うのをやめて、代替関数を自作。
そこでレベルダウン。
これが共通ルーチンなら、障害は広範囲のコンポに拡散しているかも。
ReadLineの代替関数
――――――――――――――――――――――――――――――――――――――
Function ReadLine(file)
Dim line
Dim char
Do While Not file.AtEndOfStream
char=file.Read(1)
If char=vbLF Then Exit Do
line=line & char
Loop
If Right(line,1)=vbCR Then line=Left(line,Len(line)-1)
ReadLine=line
End Function
――――――――――――――――――――――――――――――――――――――
性能は見ての通りで、よくないと思う。
ブロックreadしようとすると、バッファ管理が必要で、Class化しないと。。。
>管理人むたぐち さん 2004年 12月 09日 17時 49分 57秒
>NULL文字が入っているテキストがまともに読めないのは仕様かと思っていた
>私は一体…。
>本来、テキストデータにはあるべきでない文字なわけですから、
>それをまともに読めないというのは、ある意味当たり前かなーと。
それはないと思います。
いくら、聞きしに勝る○○○○○○○と雖も、これを仕様とは強弁しないでしょう。
そんなことを言ったら、ミッションクリティカルな業務システムに使える。という
看板を自ら外すことになりますもの。
unixに於いては、テキストファイルはNUL文字を含まない、
1行2048(?)文字(?)以下の行からなる。とか、どっかに定義してあったのですが、
忘れました。POSIX 1003.1か、ASNI/ISO/JIS Cか。
これは、gets()がnull terminated stringを返す。という仕様と整合を取るため、
ですね。逆に、puts()はNUL文字の前までしか書き込まず、NUL文字を書き込む
ことはない。と、一貫性があります。こういうのが仕様であって、
WriteLineで書けるものが、ReadLineで読めない、のが仕様だ。なんて言うと、
企業ユーザはみんなunixに行っちゃいます。
Windowsのテキストストリームや言語の文字列型には、NUL文字を特別扱いする話は
なかったと思います。
>むちゃ さん 2004年 12月 07日 10時 07分 26秒
>HTA でステータスバーを表示することはできないでしょうか??
もし、コモンコントロールが使える環境ならば、可能です。
以下でも使ってます。普通の使い方とはちょっと違いますが。
>ばんのしゃーによかばんた さん 2004年 07月 21日 13時 13分 27秒
>ファイル(複数可)を、アイコンでなく、ウィンドウにドロップすると、
>フルパス名のリストをクリップボードに入れるHTAです。
>ToClip.HTA
或いは、ステータスバー擬というのはどうでしょう。試しに作ってみました。
<body>
<div id=bdy >
bbbbbbb...
</div>
<div id=status STYLE="background-color:MENU; position:absolute; left:0; top:expression(document.body.clientHeight-this.offsetHeight); width:expression(document.body.clientWidth); border:thin groove;">
aaaaaaa...
</div>
</body>
NULL文字が入っているテキストがまともに読めないのは仕様かと思っていた
私は一体…。
本来、テキストデータにはあるべきでない文字なわけですから、
それをまともに読めないというのは、ある意味当たり前かなーと。
>ばんのしゃーによかばんた さん 2004年 12月 08日 15時 27分 24秒
>WSH5.6のFileSysytemObjectのReadLine/ReadAllには、
>重大障害(データ破壊)があるようです。:-<
>データ中にNUL文字があると、その後がNUL文字に化けます。
>これでは、安心して使えません。:-<
シチュエーションが限定的なら、まだしも、これは、ごく普通に起きるので、
困ります。例えば、メールやWEBページには、よく、NUL文字が混入しています。
実際、この障害を検出したのも、WEBページからスクリプト類を削除するVBScriptを
通したところ、表示が大きく崩れたので、何でかなぁと、調べたのがきっかけです。
このときは、27KBも0だったので、最初、WEBページがバッファオーバラン狙いの
ウィルスにでも汚染されているのか、と思ったのですが、濡れ衣でした。
少なくとも、よく使うスクリプト類からは、ReadLine/ReadAll をなくさないと、
危なくていけません。影響大です。
もし、ReadLine/ReadAll を業務システムに使用しているなら、
緊急に対処が必要です。
対処案
甲案
ReadLine/ReadAll を Read で代替する。
ReadAllはまだしも、ReadLineは自作するのが、ちょっと面倒です。
乙案
FSO を ADODB.Stream で代替する。
いっそのこと、ADODB.Stream で読んだほうが、簡単かも。
丙案
InStrでNUL文字があるか、チェックして、あれば警告する。
別のツール/スクリプトで、先に、NUL文字を除去する。
速報
WSH5.6のFileSysytemObjectのReadLine/ReadAllには、
重大障害(データ破壊)があるようです。:-<
データ中にNUL文字があると、その後がNUL文字に化けます。
例えば、(NUL)+260個の'a' を読むと、260個の(NUL)+1個の'a' に化けます。
※ 260 が 閾値? みたいです。
これでは、安心して使えません。:-<
Read(1)で読めば大丈夫ですが、今度は性能低下が心配です。
Read(4096)などで読めば、性能も低下しないで、安全かも。
※ なぜか、Read()だと、問題なく読める。
ReadLine/ReadAllは自作しないといけませんね。
>魔界の仮面弁士さん
本当にありがとうございます。
丁寧に教えて頂きまして&時間をたくさん割かせてしまい申し訳ないです><
最初からつまずくと、何も分からない状態になりますが、
最初をサポートして頂いたお陰でスムースに行けそうです。
MSDNを参照しながら頑張っていきます
またつまづいてお世話になるかもしれませんが宜しくお願いします
ありがとうございましたm__m
》 Helpです さん
> WScript.Echo(IE.document.getElementsByName(テキストボックス名))
としたところ
> [Object]
> と表示されました。
getElementsByNameの戻り値は、数値や文字列ではなく、オブジェクトです。
そのため、通常は WScript.Echo では表示できません。
しかし、DHTMLで提供されているオブジェクトの多くは、
省略可能な『ToStringメソッド』を持っています。
そして、これらのオブジェクトの殆どは、ToStringの戻り値として
『[object]』という文字列を返すようになっています。
そのため、
WScript.Echo(IE.document.getElementsByName("q"))
という記述をしてもエラーにはならず、かわりに、
WScript.Echo(IE.document.getElementsByName("q").ToString())
として実行されることになり、結果が [object] になってしまうのです。
> そのテキストボックスはObjectとして作られている為
先の書き方で返される物は、テキストボックスではありません。
一種のコレクションオブジェクトです。
getElementsByName メソッドは、『getElement「s」ByName』と
複数形で記述されている事からも推測できるように、複数のエレメントを
返すようになっています。
たとえば、取得された件数については、
WScript.Echo(IE.document.getElementsByName("q").length)
のように、lengthプロパティで取得できます。
また、lenthプロパティが 1以上の値を返すなら、先頭の要素については、
WScript.Echo(IE.document.getElementsByName("q")(0))
のようにして、目的のテキストボックスを取得できるようになっています。
さて、これで テキストボックスまでは到達できましたが、これもやはり
DHTML のオブジェクトなので、先に書いたようにそのまま WScript.Echo に
渡すと、単に [object] と表示されるだけです。
もし、inputエレメントの値などを取得/設定したいなら、
このinputエレメントの各種プロパティを探ってみてください。
inputエレメントの仕様については、こちらに書いてあります。
http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/input_text.asp
たとえば、具体的にはこのような書き方ができます。
WScript.Echo(IE.document.getElementsByName("q")(0).tagName)
WScript.Echo(IE.document.getElementsByName("q")(0).outerHTML)
WScript.Echo(IE.document.getElementsByName("q")(0).value)
>ばんのしゃーによかばんた さん 2004年 12月 05日 17時 04分 51秒
>「ソースを表示」に再度、挑戦。
以下を「お気に入り」に入れて、
IEでWebページを表示し、「お気に入り」から実行すると、
オリジナルHTMLソースをデスクトップにコピーします。
コピー先などは、カストマイズしてください。
Source.VBS
――――――――――――――――――――――――――――――――――――――
Set fso=CreateObject("Scripting.FileSystemObject")
Set wShell=CreateObject("WScript.Shell")
Set Folder=fso.GetFolder(wShell.SpecialFolders.Item("desktop"))
Set File=Folder.CreateTextFile("NotePad.BAT")
File.WriteLine "ECHO %*"
File.WriteLine "COPY %*"
'File.WriteLine "COPY %* C:\XXX\"
File.WriteLine "PAUSE"
File.Close
wShell.SendKeys "%VC"
WScript.Sleep 1000
Folder.Files("NotePad.BAT").Delete
――――――――――――――――――――――――――――――――――――――
※MSDN Library の Document Explorer の「ソースを表示」には、この手も、
前の手も、なぜか効きません。
>魔界の仮面弁士 さん 2004年 12月 07日 11時 07分 13秒
>当方も同じくXP SP2ですが、この記法が使えています。
>(IEのバージョン情報には、6.0.2900.2180.xpsp_sp2_rtm.040803-2158 とあります)
IEのバージョン情報は、同じですね。
>当方では使えません。
>…うぅむ。この違いは何でしょうね。
>OSやIEの違いではなく、どこかの設定の問題という事なのかな。
かも知れません。
どちらにしろ、環境依存なので、自分の環境外では、使わない、ですね。
>管理人むたぐち さん 2004年 12月 06日 22時 46分 30秒
>WScript.StdIn、あるいは他の方法で、WSHでバイナリの標準入力を
>読み込む方法は、ありますでしょうか?
例の、
fso.GetStandardStream(0,True)
で、unicode扱いで読めます。
問題は、末尾が奇数バイトのとき、読み取れないことくらいです。
WScript.Echo(IE.document.getElementsByName(テキストボックス名))
としたところ
[Object]
と表示されました。
そのテキストボックスはObjectとして作られている為
そのテキストボックスに"検索文字"を入力する事は不可能
という事なのでしょうか?(入力する行になるとエラーが発生します)
質問ばかりですみませんが宜しくお願いします
>魔界の仮面弁士さん
返信、ありがとうございます。
なるほどなるほど、だんだん分かって気ました。
喉にひっかかっていた魚の骨がすっととれた気持ちです。
ありがとうございました。
30体27あお武蔵
》 ばんのしゃーによかばんた さん
>> ie.Navigate2 "javascript:document.write('<html><body><input type=file id=txtFile></body></html>');"
>> のような記述であれば、現在のバージョンでも動作するようです。
> これは、使えなくなった?みたい。(XP SP2)
当方も同じくXP SP2ですが、この記法が使えています。
(IEのバージョン情報には、6.0.2900.2180.xpsp_sp2_rtm.040803-2158 とあります)
>> ie.Navigate "about:<html><body><input type=file id=txtFile></body></html>"
>> の記述が利用できないようです。(IE6SP1からだったかな?)
> こっちは、まだ使えます。(XP SP2)
当方では使えません。
…うぅむ。この違いは何でしょうね。
OSやIEの違いではなく、どこかの設定の問題という事なのかな。
》 Helpです さん
> Formに Name属性が入っていない場合、どのようにその
> テキストボックスを教える事が出来るのでしょうか?
もし、id属性があるなら、getElementByIdメソッドが使えるでしょう。
idも無いなら、document.formsが、formエレメントのコレクションを
返しますので、これを利用できます。たとえば、そのHTML中に
formエレメントが一個しか無いのであれば、document.forms(0) です。
> WScript.Echo(ie.document.elements(5).テキストボックス名)
テキストボックス側にname属性があるなら、
document.getElementsByNameメソッドが使えますよ。
nameすら無いなら、要素名からの検索を行うことも出来ます。
この場合は、document.getElementsByTagNameメソッドですね。
HTA でステータスバーを表示することはできないでしょうか??
window.status でメッセージ等を表示したいのですが・・・
WScript.StdIn、あるいは他の方法で、WSHでバイナリの標準入力を
読み込む方法は、ありますでしょうか?
例の、AnHTTPD + CGI(VBS on WSH)で動作しているWebサーバーに、
WSHで記述したファイルアップローダを作ろうと考えているのですが、
WScript.StdInが返すのがTextStreamであるため、enctype="multipart/form-data"
のバイナリが読めないという問題に突き当たりました。
このバイナリを読み込んでByteArrayにさえ変換できれば、あとはBASP21の
BinaryWriteメソッド等を使えばファイル化できるのですが…。
何か案はありませんでしょうか?
>魔界の仮面弁士 さん 2004年 03月 29日 05時 03分 26秒
>ただし、“javascript Protocol”を使った、
>ie.Navigate2 "javascript:document.write('<html><body><input type=file >id=txtFile></body></html>');"
>のような記述であれば、現在のバージョンでも動作するようです。
これは、使えなくなった?みたい。(XP SP2)
>セキュリティ上の問題からなのか、最近のバージョンでは、
>ie.Navigate "about:<html><body><input type=file id=txtFile></body></html>"
>の記述が利用できないようです。(IE6SP1からだったかな?)
こっちは、まだ使えます。(XP SP2)
一方、アドレスバーについては、
about:<html> は、書けなくなった?ようです。
javascript:document.write は、まだ書けるようです。
使えなくなったり、使えるようになったり、いろいろですね。
>魔界の仮面弁士さん
返信遅れてすみません。
ありがとうございます、出来ました。
恐縮ですがもう一つお聞きしたいのですが、
Formに Name属性が入っていない場合、どのようにその
テキストボックスを教える事が出来るのでしょうか?
例えば http://auctions.yahoo.co.jp/jp/show/searchoptions?catid=0
このページのでは FormにAction属性しか書かれていません。
WScript.Echo(ie.document.elements(5))
ここまではエラーにならないのですが、その後にテキストボックス名を入れると
エラーになります
WScript.Echo(ie.document.elements(5).テキストボックス名)
Nameがないと指定できないのでしょうか
お力添え宜しくお願いします
「ソースを表示」に再度、挑戦。
準備。
あるフォルダ(c:\xxx)に
NotePad.BAT を作ります。
――――――――――――――――――――――――――――――――――――――
echo %*
copy %*
pause
――――――――――――――――――――――――――――――――――――――
「お気に入り」に以下のふたつを登録します。
Change.HTM
――――――――――――――――――――――――――――――――――――――
<script language=vbscript>
Sub window_onload()
Set wShell=CreateObject("WScript.Shell")
wShell.CurrentDirectory="c:\xxx" '※要変更
window.document.body.innerText=wShell.CurrentDirectory
End Sub
</script>
――――――――――――――――――――――――――――――――――――――
Restore.HTM
――――――――――――――――――――――――――――――――――――――
<script language=vbscript>
Sub window_onload()
Set wShell=CreateObject("WScript.Shell")
wShell.CurrentDirectory=wShell.SpecialFolders.Item("desktop")
document.body.innerText=wShell.CurrentDirectory
End Sub
</script>
――――――――――――――――――――――――――――――――――――――
Change.HTMを表示すると、以後そのIEで「ソースを表示」すると、
NotePad.BATが実行されます。
NotePad.BATは、オリジナルのHTMLファイルをカレントディレクトリ(c:\xxx)に
コピーします。
Change.HTMを表示すると、もとに戻ります。
※ところで、View-Source:〜は使えなくなった?
※なんか、ここで、話題になると、使えなくなるような。気のせい?
したがって、スクリプトからだとSendKeys("%VC")で「ソースを表示」する
しか、方法がないようです。
1. 「ファイル選択ダイアログ」を出すのにはどのオブジェクトを使うのでしょうか?
メモ帳などで「ファイル(F)->開く(O)」とすると出てくるやつですが・・・
2. いくつかの選択肢から選択するようなテキストボックスはどんなオブジェクトを使うのでしょうか?
ワードパッドでフォントを選択する時のようなものがやりたいのですが・・・
3. Shell.Applicationの、BrowseForFolder()で、
set F = SA.BrowseForFolder(...)
などとした場合、キャンセルを選択すると、エラーになってしまいます。キャンセルされたことを正しくキャッチするにはどうしたらよいですか?
今日はじめたばかりですが、誰か教えて下さい。
たとえば、下のHelpですさんの例で
魔界の仮面弁士 さんが言っているように
IE.Document.SearchForm(0).keyword.value = "keyword"
とすれば、"keyword"と入力されるのですが、
実際にそのキーワードで検索させることはできるのでしょうか。
それと、
For I=1 To 10 Step 1
IE.Document.SearchForm(0).keyword.value = "I"
Next
では、Iが数値に展開されないのですが、(""でくくられてるからなのでしょうか?)””中でIを数値に置き換えるようにさせることは可能なのでしょうか?
あともうひとつ聞きたいことがあるんです。
http://pya.cc/bt/main.php
に罵声を戦わせるというようなゲーム?があるのですが、
そこで、1秒間に数個の投稿をたえまなくしている人がいて、
そのような動作はWSHを使ってやるとしたらどうやればできるのでしょうか。
誰か教えてくださ〜い(><)
(管理人により削除)
》 Helpです さん
> 3 IE.Navigate("www.hmv.co.jp")
そのサイトは、上部と下部にキーワードの入力個所がありますね。
どちらに入力させたいのでしょうか?
> 10 IE.Document.SearchForm.keyword.value = "keyword"
> 10行目でエラーとなります。
そのサイトでは、『SearchForm』という名前のformが複数ありますので、
配列のように扱われる事になります。
上部のテキストボックスに入力するなら、
IE.Document.SearchForm(0).keyword.value = "keyword"
下部のテキストボックスに入力するなら、
IE.Document.SearchForm(1).keyword.value = "keyword"
などとしてみてください。
こんにちわWSHを最近知った素人です。
WSHを使ってIEを開き-テキストボックスにKeywordを入れたいのです。
いろいろと探したのですが良く分かりません。
下記例でHMVのページを開き検索テキストボックスにKEYWORDと文字を入れたい
のですが・・・
1 Set IE = WScript.CreateObject("InternetExplorer.Application")
2 IE.Visible = true
3 IE.Navigate("www.hmv.co.jp")
4
5 Do While IE.busy
6 Loop
7 Do While IE.Document.readyState <> "complete"
8 Loop
9
10 IE.Document.SearchForm.keyword.value = "keyword"
10行目でエラーとなります。
簡単な質問ですみませんが何卒お助けください。
>ばんのしゃーによかばんた さん 2004年 06月 06日 18時 25分 53秒
>var Shell = WScript.CreateObject("Shell.Application");
>var WindowsShell = Shell.Windows();
>for (var i = 0; i < WindowsShell.Count; i++) {
>; if (WindowsShell.item(i).FullName.match(/iexplore.exe$/i)) {
>; ; var ie = WindowsShell.item(i);
>; ; if(ie.Document.hasFocus()) break;
>; }
>}
>とすればよかったわけですね。
>ただし、上のコードはIEからフォルダを開いているとこけます。
>VBScriptなら、
>Set Shell = CreateObject("Shell.Application")
>For Each ie In Shell.Windows()
>: If TypeName(ie.Document)="HTMLDocument" Then
>: : If ie.Document.hasFocus() Then Exit For
>: End If
>Next
>とすればよいのですが、JScriptは分かりません。悪しからず。:-p
Shell.Windows()のそれぞれが、HTMLDocumentなのか、Folderなのか、
VBScriptならTypeName()で簡単に区別できますが、JScriptは困ります。
ie.FullNameは、IEでフォルダを、ExplorerでHTMLを表示できるので、
判定に使えません。
それぞれに固有なプロパティがあるかどうかで判定するのがよいようです。
var shell=new ActiveXObject("Shell.Application")
var ies=shell.Windows()
for(var k=0;k<ies.Count;k++){
var ie=ies(k);
WScript.Echo(ie.FullName);
WScript.Echo(('body' in ie.Document)?'IE':'Explorer');
WScript.Echo(('Folder' in ie.Document)?'Explorer':'IE');
}
先の件は、
var shell=new ActiveXObject("Shell.Application")
var ies=shell.Windows()
for(var k=0;k<ies.Count;k++){
; var ie=ies(k);
; if('body' in ie.Document){
; ; if(ie.Document.hasFocus()) break;
; }
}
となります。
>ばんのしゃーによかばんた さん 2004年 06月 26日 17時 16分 48秒
>あと、borderあたりに隙間が空いて透けて見えるのはどうすればよいのでしょう。
試行錯誤の末、記述の順番を変えると、隙間がなくなりました。:-)
記述の順序に依存するのって、本当に困ります。:-<
なんかIE関係にはそういうのが多いようなので、ご用心。
IEでも結構いいダイアログが出来ますね。
Enter User-ID and Password
――――――――――――――――――――――――――――――――――――――
Option Explicit
Dim ie
Dim fOK,ID,PW
Set ie=CreateObject("InternetExplorer.Application")
ie.Navigate "about:blank"
Do While ie.Busy Or ie.readyState<>4
WScript.Sleep 100
Loop
ie.Document.body.insertAdjacentHTML "AfterBegin","<table>" & _
"<tr><td>User ID :</td><td><input type='textbox' id='ID'></td></tr>" & _
"<tr><td>Password :</td><td><input type='password' id='PW'></td></tr>" & _
"<tr></tr><tr></tr><tr></tr><tr><td></td><td>" & _
"<input type='button' value=' OK ' id='OK'/>" & _
" " & _
"<input type='button' value=' Cancel ' id='Cancel'/>" & _
"</td></tr></table>"
ie.Menubar=False
ie.Toolbar=False
ie.Statusbar=False
ie.Resizable=False
ie.Document.body.scroll="no"
ie.Document.body.bgColor="MENU"
ie.Document.body.style.border="none"
ie.Document.title ="Enter User-ID and Password"
ie.Width=265
ie.Height=150
ie.Top=(ie.Document.parentWindow.screen.availHeight-ie.Height)/2
ie.Left=(ie.Document.parentWindow.screen.availWidth-ie.Width)/2
Set ie.Document.all.Cancel.onclick=GetRef("Cancel")
Set ie.Document.all.OK.onclick=GetRef("OK")
ie.Visible=True
ie.Document.all.ID.Focus
Do While TypeName(ie)="IWebBrowser2"
WScript.Sleep 100
Loop
If fOK Then
MsgBox ID & vbCRLF & PW
Else
MsgBox "Canceled"
End If
Sub Cancel
ie.Quit
End Sub
Sub OK
ID=ie.Document.all.ID.Value
PW=ie.Document.all.PW.Value
fOK=True
ie.Quit
End Sub
――――――――――――――――――――――――――――――――――――――
Enter Password
――――――――――――――――――――――――――――――――――――――
Option Explicit
Dim ie
Dim PW
Set ie=CreateObject("InternetExplorer.Application")
ie.Navigate "about:blank"
Do While ie.Busy Or ie.ReadyState<>4
: WScript.Sleep 100
Loop
ie.Document.body.insertAdjacentHTML "AfterBegin", _
"<input type=password id=PW> " & _
"<input type=button value=' OK ' id=OK>"
ie.MenuBar=False
ie.ToolBar=False
ie.AddressBar=False
ie.StatusBar=False
ie.Resizable=False
ie.Width=225
ie.Height=80
ie.Top=(ie.Document.parentWindow.screen.availHeight-ie.Height)/2
ie.Left=(ie.Document.parentWindow.screen.availWidth-ie.Width)/2
ie.Document.title="Enter Password ...................................."
ie.Document.body.scroll="no"
ie.Document.body.bgcolor="MENU"
ie.Document.bgcolor="MENU"
ie.Document.body.style.border="none"
Set ie.Document.all.OK.onclick=GetRef("OK")
ie.Visible=True
ie.Document.all.PW.focus
Do While TypeName(ie)="IWebBrowser2"
: WScript.Sleep 100
Loop
MsgBox PW
WScript.Quit
Sub OK()
PW=ie.Document.all.PW.value
ie.Quit
End Sub
――――――――――――――――――――――――――――――――――――――
はじめまして。
よっし〜と申します。
TO:ばんのしゃーによかばんたさん
>検索ダイアログに文字列を入れて、キャンセルボタンを押す。
>次に検索ダイアログを開くと、文字列が入っています。
>このIEを残しておくと、別のHTMLファイルを開いて、検索ダイアログを開いても、
>文字列が入っています。
そうですね。
ところで、IEの検索ダイアログは、JavaScriptで書かれていますので、
ちょこちょこ細工すれば挙動を変えることも可能です。
#お勧めはしませんが。(^^;
ソースはIEで以下のパスを表示すると見えます。
#ExeScopeなどのリソースエディタでも見れます。
WindowsXPなど
res://C:\WINDOWS\System32\shdoclc.dll/find.dlg
res://C:\WINDOWS\System32\shdoclc.dll/findinc.dlg
Windows2000など
res://C:\WINNT\System32\shdoclc.dll/find.dlg
res://C:\WINNT\System32\shdoclc.dll/findinc.dlg
ちなみに、キャンセルボタンを押した時の処理は、
shdoclc.dll/findinc.dlg の、
「function btnCancelClick2()」です。
btnCancelClick2
関数名から、改修のにおいがしますねえ。(^^;
では。
IEで「このページの検索」を使い、別のHTMLファイルを開いて、
同じ検索をしようとすると、また、文字列を入れ直す必要があります。
何とかならぬものかと思っておりましたら、たまに、入れ直す必要がないときがあり、
何でかなぁと思っておりました。そこで、発生条件を少し調べてみました。
検索ダイアログに文字列を入れて、キャンセルボタンを押す。
次に検索ダイアログを開くと、文字列が入っています。
このIEを残しておくと、別のHTMLファイルを開いて、検索ダイアログを開いても、
文字列が入っています。
MSDNライブラリのDocument Explorerも同じです。
検索ダイアログに文字列を入れて、キャンセルボタンを押す。
次に検索ダイアログを開くと、文字列が入っています。
HTAで標準入出力を使うサンプル。
パスワード入力をHTAで作り、WSH/VBScriptから呼び出す。バッチから呼び出す。
Password.HTA
――――――――――――――――――――――――――――――――――――――
<html>
<head>
<script language="vbscript">
W=275
H=80
window.ResizeTo W,H
window.MoveTo (window.screen.availWidth-W)/2,(window.screen.availHeight-H)/2
</script>
<HTA:APPLICATION
applicationName="Password"
version=1.00
maximizeButton=no
border=dialog
innerborder=no
showintaskbar=yes
Scroll=no
>
<title>Enter Password</title>
<script language="vbscript">
Option Explicit
Sub Enter()
CreateObject("Scripting.FileSystemObject").GetStandardStream(1).Write PW.Value
window.close()
End Sub
Sub KeyPress()
If window.event.keyCode=13 Then Call Enter()
End Sub
</script>
</head>
<body bgcolor="MENU" onload="PW.focus">
<input type=password id=PW onkeypress="KeyPress()">
<input type=button id=OK value="OK" onclick="Enter()">
<input type=button id=Cancel value="Cancel" onclick="window.close()">
</body>
</html>
――――――――――――――――――――――――――――――――――――――
WSH/VBScriptから呼び出す。
――――――――――――――――――――――――――――――――――――――
Set wShell=Wscript.CreateObject("Wscript.Shell")
Set oExec=wShell.Exec("MSHTA.EXE c:\vbs\hta\password.HTA")
Do While oExec.Status=0
WScript.Sleep 100
Loop
MsgBox oExec.StdOut.ReadAll()
――――――――――――――――――――――――――――――――――――――
バッチから呼び出す。
――――――――――――――――――――――――――――――――――――――
mshta c:\vbs\hta\PASSWORD.HTA |more
――――――――――――――――――――――――――――――――――――――
※mshta.exeの引数はフルパスで。ファイルがないとダンマリに。用心。
※IEで作るより、何がよいかと言うと、らしくなること。
IEだと、どうしてもIEっぽさが残ります。
たまたま、
RunDLL32.EXE Shell32.DLL,ShellExec_RunDLL ファイル [args...]
というのを見つけましたが、
[,vDirectory] [,vOperation] [,vShow]が指定できれば、まだしも、
指定できそうにないので、特に使い道がなさそう。
――――――――――――――――――――――――――――――――――――――
ファイルを「コピー」して、アプリのアイコンに「貼り付け」られるんですね。
※昔(98)は出来なかったと思いますが、ちょっと確認できません。
ドラッグ&ドロップと同じですが、スクリプトで出来るってことですね。
例えば、ファイルを「選択」して、「コピー」して、SendToClipboardに
「貼り付け」なんてことが、出来そう。でも使い道が。。。