管理人むたぐち さん 2004年 11月 14日 22時 43分 17秒

*.vbs→*.vb→*.exe変換を行うEmEditor4のマクロを書いてみました。
とりあえず叩き台ですが、完成には程遠いです。
SubやFunctionやClassはSub Main()の外側に出したり、
関数・メソッド呼び出しには()を付けるとか、
やることはゴマンとあります。

'vbs2vb2exe.vbee
'VBSをVB.NETのコードに変換するスクリプト

Set regEX = New RegExp
regEx.Global = True
regEX.IgnoreCase = True
Set Fs = CreateObject("Scripting.FileSystemObject")
Set WshShell = CreateObject("WScript.Shell")

sVBSPath = Document.FullName
sVBPath = Fs.BuildPath(Fs.GetParentFolderName(sVBSPath),Fs.GetBaseName(sVBSPath) & ".vb")
sEXEPath = Fs.BuildPath(Fs.GetParentFolderName(sVBSPath),Fs.GetBaseName(sVBSPath) & ".exe")

Document.Save sVBSPath 'VBSを保存

sCompilerPath="C:\windows\Microsoft.NET\Framework\v1.1.4322\vbc.exe"

sHead="Imports Microsoft.VisualBasic" & vbCrLf & _
"Module Module1" & vbCrLf & _
"Sub Main()" & vbCrLf

sFoot="End Sub" & vbCrLf & "End Module" & vbCrLf

Set iFile=Fs.OpenTextFile(sVBSPath)
Set oFile=Fs.CreateTextFile(sVBPath)

oFile.Write sHead
Do While Not iFile.AtEndOfStream
sLine=iFile.ReadLine

'Set文
regEx.Pattern="set\s"
sLine=regEx.Replace(sLine,"")

oFile.WriteLine sLine
Loop
oFile.Write sFoot

iFile.Close
oFile.Close

WshShell.Run sCompilerPath & " /t:winexe " & _
"/out:" & """" & sEXEPath & """" & " " & _
"""" & sVBPath & """",,True

WshShell.Run """" & sEXEPath & """"

管理人むたぐち さん 2004年 11月 14日 21時 18分 01秒

参考になりそうなリソース

VBA から Visual Basic .NET へのコードの変換
http://www.microsoft.com/japan/msdn/officedev/vsto2003/VBAConvert.asp
VBのあれやこれや <Mythologie Clair de lune>
http://members.at.infoseek.co.jp/mythe_lune/contents_vb/vb_memo.htm

機械的に変換するのには限界がありそうですが、
ある程度は可能なんじゃないかという気もしないでもないですねー。

管理人むたぐち さん 2004年 11月 14日 21時 08分 17秒

このアプローチで行くなら、
*.vbs→*.vb→*.exe と変換していく方が素直ですよね。

*.vbsを*.vbを変換する際、注意すべきことは何でしょう。
少し考えてみませんか。

今思いついたもの
1.Wend→End While
2.変数は必ずDim〜As〜で宣言(これって必須?)
3.Module Module1 ... End Moduleで構造化
4.Set文を整形
5.WScriptオブジェクトをVB.NETでコーディングする。
 DMonkeyのWScriptオブジェクトのように。

5.がめんどくさそうです。
他にしなきゃならないことってありますかね?

管理人むたぐち さん 2004年 11月 14日 20時 54分 02秒

ついでに出力された*.jsのコンパイルまでやらせてみました。
何となくですが、*.vbs→*.exe化の第一歩を踏み出した気がします。

ところで/t:exeが効かないような気がするのは何故でしょう…?

Option Explicit
Dim fso,WshShell
Dim fo
Dim iFile
Dim oFile
Dim oPath,oExePath
Dim header
header="var SC=new ActiveXObject('ScriptControl');" & vbCRLF & _
"SC.Language='VBScript';" & vbCRLF & _
"SC.AllowUI=true;" & vbCRLF & _
"SC.TimeOut=-1;" & vbCRLF & _
"SC.ExecuteStatement("
Dim trailer
trailer="'');"
Dim line

Set fso=CreateObject("Scripting.FileSystemObject")
Set WshShell=CreateObject("WScript.Shell")

If Wscript.Arguments.Count<>1 Then
WScript.Echo "Usage: vbs2js vbsfile"
WScript.Quit
End If
Set fo=fso.GetFile(WScript.Arguments(0))
oPath=fso.BuildPath(fso.GetParentFolderName(fo.Path),fso.GetBaseName(fo.Name) & ".js")
oExePath=fso.BuildPath(fso.GetParentFolderName(fo.Path),fso.GetBaseName(fo.Name) & ".exe")
Set iFile=fso.OpenTextFile(fo.Path)
Set oFile=fso.CreateTextFile(oPath)
oFile.Write header
Do While Not iFile.AtEndOfStream
line=iFile.ReadLine
line=Replace(line,"\","\\")
line=Replace(line,"'","\'")
oFile.WriteLine "'" & line & "'+'\r\n' +"
Loop
oFile.Write trailer
iFile.Close
oFile.Close
WshShell.Run "C:\windows\Microsoft.NET\Framework\v1.1.4322\jsc.exe " & _
"/t:exe " & _
"/out:" & """" & oExePath & """" & " " & """" & oPath & """"
WScript.Quit

ばんのしゃーによかばんた さん 2004年 11月 14日 20時 18分 56秒

作ってみました。vbs2js.VBS
――――――――――――――――――――――――――――――――――――――
Option Explicit
Dim fso
Dim fo
Dim iFile
Dim oFile
Dim oPath
Dim header
header="var SC=new ActiveXObject('ScriptControl');" & vbCRLF & _
"SC.Language='VBScript';" & vbCRLF & _
"SC.AllowUI=true;" & vbCRLF & _
"SC.TimeOut=-1;" & vbCRLF & _
"SC.ExecuteStatement("
Dim trailer
trailer="'');"
Dim line

Set fso=CreateObject("Scripting.FileSystemObject")

If Wscript.Arguments.Count<>1 Then
WScript.Echo "Usage: vbs2js vbsfile"
WScript.Quit
End If
Set fo=fso.GetFile(WScript.Arguments(0))
oPath=fso.BuildPath(fso.GetParentFolderName(fo.Path),fso.GetBaseName(fo.Name) & ".JS")
Set iFile=fso.OpenTextFile(fo.Path)
Set oFile=fso.CreateTextFile(oPath)
oFile.Write header
Do While Not iFile.AtEndOfStream
line=iFile.ReadLine
line=Replace(line,"\","\\")
line=Replace(line,"'","\'")
oFile.WriteLine "'" & line & "'+'\r\n' +"
Loop
oFile.Write trailer
iFile.Close
oFile.Close
WScript.Quit

管理人むたぐち さん 2004年 11月 14日 19時 30分 41秒

To: cian さん

> WSHで非アクティブ状態の特定ウィンドウにキーボード操作を送りたいと思っております。(具体的にはショートカットキー)

これはWshShell.SendKeysではできなかったような気がします。
APIのkeybd_event関数を使えばできるみたいです。
DynaCallから呼び出して使ってみては。

別のアプリにキーイベントを発生させる
http://homepage1.nifty.com/MADIA/delphi/delphi_bbs/200302_03020042.html


To: ばんのしゃーによかばんた さん

> ※使ってないので知りませんが、過去記事から推測すると、
> EmEditor4のマクロは、ScriptControl経由でVBScriptを使っている?

たぶん、そんな感じです。
なので、「EmEditor4のマクロにはWSHを採用」とかいうキャッチコピーを見ると、
我々からすると少し違和感があるんですよね。
厳密に言えば、WSHではない。

> マクロ内でScriptControlをCreateObjectして、SC.AllowUI=Trueして、
> ans=SC.Eval("InputBox(""..."")")する。というのはどうでしょう?

できました、できました。

'test.vbee
'EmEditor4のマクロでInputBoxを使う
Set SC=CreateObject("ScriptControl")
SC.Language="VBScript"
SC.AllowUI=true
ans=SC.Eval("InputBox(""改行もできますよ。"" & vbCrLf & ""はい、このとおり。"")")
alert ans

> 単に、スクリプトテキストをScriptControlに渡しているだけかな?
> なので、WScript.〜が使えない。
> SC.AllowUI=False にしているので、MsgBoxが駄目、なのでは。
> せめて、スクリプトエンコードとか、圧縮とか、すれば、らしく、なるのに。
> また、ScriptControlを使うより、WScriptをCreateProcessしたほうが、
> WScript.〜が使えて、いいのに。
> 作者に要望を出されてみては。

なんか全部当たってる感じがしますねー。
我々でそれに近いものを作った方が早いかもw

ScriptControlを使ってVBSをJScript.NETでラップするというのは
一つのアイデアだとは思いますが、ちょっと回りくどい気がします。
なんかもうちょっと簡単にコンパイルする方法がある気がするんですがねー。

> さらにWScript.〜擬をJScriptで作って、VBScriptに渡せば完璧です。

StdInとか、Echoとか、環境変数とか、結構いろいろ使ってるんですよね。
CGIスクリプトだけに。
このあたりを簡単にポーティングできればいいんですけど。
そこまでやるなら、JScript.NETで一から書き直した方が早いかな、とか思ったりですね。

なぜそこまで既存資源にこだわるのか、と言われそうですが、
既存のvbs資源を、exe、というか.NETのコードに
変換するというテーマは、わりと追求しがいがあると思ってますので、
いろいろ考えてみましょう。

ばんのしゃーによかばんた さん 2004年 11月 14日 18時 12分 16秒

>オズ さん 2004年 11月 12日 09時 48分 33秒
>MoveFileを使えばいいだろうと思えますが、絶対にロストできない
>ファイルなので大事をとって2段構えとしました。
>(もしかしてMoveFileで移動中にエラーがあってもそんなこと起きないですか?)

同じドライブ内なら、Moveのほうが安全だと思います。Renameと同じですから。
異なるドライブ間の場合、私なら、Copyしたあと、コンペアしてから削除します。
書けるけど読めないとか、媒体障害もありますから。
Copy後、しばらく間を置いてからコンペアしたほうがよいかも。
キャッシュが効いているかもしれないので。

>もしかして非同期な動作なのはDeleteFileだけでなくCopyFileメソッドも
>そうなのでは?と疑問に思いました。

DeleteもCopyも、仕様として非同期、とは考え難いです。
そんな仕様ではとても使えません。障害としてはあるかも。
その場合、版により修正されている可能性もあります。
したがって、動作環境を明示したほうがよいと思います。

オブジェクトを解放して、取り直しておられますが、
ひょっとして、解放時は、遂次化/同期の必要がないと考えて、内部処理を
変えているのかも知れません。
Set file=fso.GetFile()
file.Copy
file.Delete
としてみても、駄目ですか。
もし、これが出来ないようなら、障害だとクレームを付けたほうがいいです。
まさか、それが仕様だと言え張れるほど、****なひとは居ないでしょう。

ばんのしゃーによかばんた さん 2004年 11月 14日 18時 11分 38秒

>あんのうん さん 2004年 11月 12日 12時 32分 11秒
>WMIとか使っても動いたり、かといって、Msgboxを出すだけの
>スクリプトが動かなかったり、いまいち法則性がわかりません。
>少なくとも、Wscript.CreateObject(〜)は、CreateObject(〜)
>に直さないと動かないことはわかりました。
>あと、出来たEXEをテキストエディタで開いてみると、スクリプト
>がまんま埋め込まれてますね。
>確かに面白いですが、いまいちどう使ったらいいやら、、

単に、スクリプトテキストをScriptControlに渡しているだけかな?
なので、WScript.〜が使えない。
SC.AllowUI=False にしているので、MsgBoxが駄目、なのでは。
せめて、スクリプトエンコードとか、圧縮とか、すれば、らしく、なるのに。
また、ScriptControlを使うより、WScriptをCreateProcessしたほうが、
WScript.〜が使えて、いいのに。
作者に要望を出されてみては。

それより、こっち↓が早いかかな。

>管理人むたぐち さん 2004年 11月 12日 22時 28分 35秒
>私がやりたいことは、*.vbsを*.exeにコンパイルして、
>それを*.cgiにリネームして、CGIスクリプトとして使いたいんです。
>AnHTTPDの機能で、ファイルを*.cgiにリネームしておくと、
>実行時に中身を判断し、実行形式(exe)ならばファイルを
>実行してくれる機能があるんですね。その機能を使いたいんです。

なら、こういうのはどうでしょう。

var SC=new ActiveXObject("ScriptControl");
SC.Language="VBScript";
SC.AllowUI=true;
SC.ExecuteStatement('MsgBox InputBox("?")');

のように、
VBScriptを読み込んで、'各行'+\r\n+'各行'にwrapして、
ScriptControlで実行するJScriptを生成し、
JScript.NETでコンパイルしてEXEにします。
さらにWScript.〜擬をJScriptで作って、VBScriptに渡せば完璧です。

ばんのしゃーによかばんた さん 2004年 11月 14日 15時 16分 13秒

IEを使ったBrowseForFolder擬です。

Select Folder and Ok:Minimize Cancel:Close
――――――――――――――――――――――――――――――――――――――
WScript.Echo BrowseForFolder("")
WScript.Quit
Function BrowseForFolder(initFolder)
Dim ie
Dim text
text="Select Folder and Ok:Minimize Cancel:Close - "
Set ie=WScript.CreateObject("InternetExplorer.Application")
ie.Visible=True
ie.ShowBrowserBar "{EFA24E64-B078-11D0-89E4-00C04FC9E26E}",True
If initFolder="" Then initFolder="shell:desktopfolder"
ie.Navigate initFolder
Do While ie.Busy Or ie.ReadyState<>4
: WScript.Sleep 100
Loop
Do While TypeName(ie)<>"Object"
: On Error Resume Next
: If InStr(ie.StatusText,text)=0 Then ie.StatusText=text & ie.StatusText
: If ie.width=160 Then
: : BrowseForFolder=UnEscape(Replace(Mid(ie.LocationURL,9),"/","\"))
: : ie.Quit
: : Exit Function
: End If
: On Error GoTo 0
: WScript.Sleep 100
Loop
End Function

ばんのしゃーによかばんた さん 2004年 11月 14日 15時 15分 39秒

>管理人むたぐち さん 2004年 11月 10日 20時 30分 50秒
>To: ばんのしゃーによかばんた さん
>> ZIPやCABは、昔(98)、ie.Document.Folderが取れなかったのですが、
>> XPでは、このFolderが取れるので、スクリプトからInvokeVerbで操作できそう。:-)
>試したことはないのですが、実際にInvokeVerbはできるんでしょうか。
>シェルの機能だけで書庫を扱えれば、結構有効利用できそうですけど。

リスト
Shell.NameSpace(〜.ZIP)で。

削除
Shell.NameSpace(〜.ZIP)で。
InvokeVerb("削除(&D)")もできますが、プロンプトが出るので、どうかな、ですね。

解凍
Shell.NameSpace(〜.ZIP)では、InvokeVerb("コピー(&C)")が効かない。
Shell.Open(〜.ZIP)で、InvokeVerb("コピー(&C)")して、explorerのフォルダに
SendKeysでメニュー操作して「貼り付け」ればよいようですが、そこまでやるか、ですね。
※このコピーでは、普通のドラッグ&ドロップデータでないものがクリップボードに
入るようです。

全解凍
Shell.Open(〜.ZIP)で、SendKeysでメニュー操作。

追加、置換
解凍の逆。置換はプロンプトが出る。

やっぱり駄目ですね。却下。

ばんのしゃーによかばんた さん 2004年 11月 14日 15時 15分 05秒

>管理人むたぐち さん 2004年 11月 11日 14時 26分 19秒
>他に困っているのは、改行コードの扱いです。
>文書中で使われている改行コードが定まってないとき(とくに文書保存前には
>定まらないことが多い)に、改行コードが何であるかを判別する必要があります。
>そうしないと、改行でsplitしたりするときにうまくいかないので。
>If InStr(sText,vbCrLf)<>0 Then
>: sNewLine=vbCrLf
>ElseIf InStr(sText,vbCr)<>0 Then
>: sNewLine=vbCr
>ElseIf InStr(sText,vbLf)<>0 Then
>: sNewLine=vbLf
>End If
>今はこんな面倒なコードを書いていますが、

※使ってないので知りませんが、過去記事から推測すると、
EmEditor4のマクロは、ScriptControl経由でVBScriptを使っている?

このコードは、ちょっと、むたぐち さんらしくないですね。
むたぐち さん流だと、
Split(Replace(Replace(sText,vbCrLf,vbLf),vbCr,vbLf),vbLf)

>あと、Inputboxが使えないのが何気に不便です。
>promptでもいいんですが、InputBoxみたいに「キャンセル」を押したときの判別が
>できない上に、一行しか文字列を表示できない…。

SC.AllowUI=False
にしているせいだと思うのですが、Trueに出来ない理由があるのかな。
マクロ内でScriptControlをCreateObjectして、SC.AllowUI=Trueして、
ans=SC.Eval("InputBox(""..."")")する。というのはどうでしょう?

※EmEditor4を知らないで言ってますので、外れていたらご容赦。

ばんのしゃーによかばんた さん 2004年 11月 14日 15時 13分 52秒

>管理人むたぐち さん 2004年 11月 04日 16時 53分 35秒
>UTF-8を扱っていて一番困るのが、チルダ" ~ "と"〜"です。
>これらの文字は、同一文字として扱われるようで、他の文字コードに変換したり
>すると、"?"などに化けてしまうのです。
>URLなどで頻出の文字なので、とても困ります。

これは、確認できませんでした。

ASCIIの7Eは,
charset=shift_jisで見ると、チルダが上に張り付いて見えますが、
charset=ISO-8859-1で見ると、真ん中に見えます。
これが、半角/全角共通の〜(&#65374;%uFF5E)に似てはいますが、
別のコードで区別されています。

?に化けるのは、〜(&#65374;%uFF5E)でしょうか。

cian さん 2004年 11月 14日 13時 39分 24秒

はじめまして cianと申します。

WSHで非アクティブ状態の特定ウィンドウにキーボード操作を送りたいと思っております。(具体的にはショートカットキー)

そこで、SendKeysメソッドがあったのですが、この場合ですとウィンドウをアクティブ化してからしかキーボード操作を送れません。
非アクティブ状態でキーボード操作を送れないでしょうか?
ご教示願います。

ちゃっぴ さん 2004年 11月 13日 21時 39分 06秒

> > (もしかしてMoveFileで移動中にエラーがあってもそんなこと起きないですか?)
>
> 何となく、ですが、NTFSだから大丈夫じゃないかな、とか思っています。
> 移動と言っても、実質はコピーしてから削除なわけでしょうから。
> 少なくともファイル移動のミスでファイルを消失させた経験は、
> Win2000,XPを使い始めてからは、ないです。

対象が同一Partitionかどうかが問題でしょうね。

同一Partitionの場合、DirectryEntry部分を入れ替え
(つまり、Pointerの入れ替え)

同一Partitionでない場合には、Copyのあと削除
だったと思います。


>> つまり、CopyFile終了後DeleteFile発行時にはまだCopyFileが対象ファイルを
>> 保持しており、DeleteFileには手が出せない状態なのではないか、と。

どうでしょう?わたしはそのような経験がありませんが・・・
書き込みCacheの問題は可能性的にはありえますね。

管理人むたぐち さん 2004年 11月 12日 22時 28分 35秒

To: あんのうん さん

> あと、出来たEXEをテキストエディタで開いてみると、スクリプト
> がまんま埋め込まれてますね。
> 確かに面白いですが、いまいちどう使ったらいいやら、、

私がやりたいことは、*.vbsを*.exeにコンパイルして、
それを*.cgiにリネームして、CGIスクリプトとして使いたいんです。

AnHTTPDの機能で、ファイルを*.cgiにリネームしておくと、
実行時に中身を判断し、実行形式(exe)ならばファイルを
実行してくれる機能があるんですね。その機能を使いたいんです。

管理人むたぐち さん 2004年 11月 12日 22時 24分 48秒

To: オズ さん

> (もしかしてMoveFileで移動中にエラーがあってもそんなこと起きないですか?)

何となく、ですが、NTFSだから大丈夫じゃないかな、とか思っています。
移動と言っても、実質はコピーしてから削除なわけでしょうから。
少なくともファイル移動のミスでファイルを消失させた経験は、
Win2000,XPを使い始めてからは、ないです。

> つまり、CopyFile終了後DeleteFile発行時にはまだCopyFileが対象ファイルを
> 保持しており、DeleteFileには手が出せない状態なのではないか、と。

可能性はありますね。
CopyFile後にちょっとだけウェイトを入れてみたりするとどうでしょう?


To: 楽々園の秀 さん

> 表示は改善されましたが、掲示板への書込ボタンを押すと特定の記事のみしか
> 右フレームに表示されません。

これらの不具合は再現しませんでした。
一度ログを再取得してみてもらえませんか?


To: あんのうん さん

> 軽く試してみましたがコンパイル済EXEが正しく動くスクリプト
> とエラーが出て動かないスクリプトがあります。

私のところだと、そもそも「コンパイル済みEXE」が生成しないのですよ。
使い方は、vbsファイルをwshscrexp.exeにドロップ、でいいんですよね?
何か間違えているのかなあ。

To: ばんのしゃーによかばんた さん

> 私はまだ遭遇しないですね。
> 少なくとも、エラー番号とエラー記述くらいは、書いてくださらないと。。。

おっと、失礼しました。番号は控えていませんでしたが、エラー内容は、
「書き込みできません」
というものです。

ばんのしゃーによかばんた さん 2004年 11月 12日 18時 07分 33秒

>管理人むたぐち さん 2004年 11月 11日 22時 09分 29秒
>To: オズ さん
>> スケジューラで実行しているスクリプト中でFileSystemObjectを用いてファイルを削除する処理があるのですが、そこでたびたびエラーが出て困っております。
>実は私も困っています。
>この件について、何か良い案をお持ちの方は、フォロー願います。

私はまだ遭遇しないですね。
少なくとも、エラー番号とエラー記述くらいは、書いてくださらないと。。。

基本は、タイミングエラーならリトライ、です。
以前に書いた、On Error Resume Nextのパラダイムを使います。

Sub Delete(path)
For k=1 To 100
: Call subDelete(path)
: Select Case Err.Number
: Case 0 Exit Sub
: Case t1,t2,t3 'Continue if timing error
: Case p1,p2 p3
: : WScript.StdOut.WriteLine Join(path,"not deleted. Permanent Error:",Err.Number,Err.Description)
: : Exit Sub
: Case Else
: End Select
: WScript.Sleep 100
Next
WScript.StdOut.WriteLine Join(path,"not deleted. Retry exceeded.",Err.Number,Err.Description)
End Sub
Sub subDelete(path)
On Error Resume Next
fso.DeleteFile path
End Sub

既知の番号を入れて、順次追加します。
: Case t1,t2,t3
: Case p1,p2 p3

――――――――――――――――――――――――――――――――――――――
>しんたろ〜 さん 2004年 11月 11日 18時 17分 46秒
>現在学校で、ネットワークプリンタを使用しているのですが、
>新規にいれるパソコンに、このネットワークプリンタを
>WSHを使用して自動的にプリンタの追加したいのですが、
>どうすればよいのでしょうか?

以下はどうでしょう。※試してません。

JP189105 - ユーザーによる操作なしで Windows にプリンタを追加する方法
ms-help://MS.MSDNQTR.2003FEB.1041/ja_kbwinxpnetkb/winxpnetkb/JP189105.htm

ばんのしゃーによかばんた さん 2004年 11月 12日 17時 03分 48秒

>初心者みきてぃ さん 2004年 11月 10日 11時 59分 26秒
>質問です。VBScriptで強制終了は出来ないのでしょうか?
>Exit Sub で終了する処理はわかっているのですが、
>そうすると、次の処理に入ってしまいますよね。
>強制的に終了することは、可能なのでしょうか?

もし、質問が「WSHなどのホストで」なく、「VBScriptで」なら、
Err.Raise vbObjectError + n
でしょうか。
ただし、これは、Cのabort(n)のような異常終了になります。
「強制終了」の意味が「エラーで途中終了する」ならぴったりです。

一方、Cのexit(n)のような正常終了は、VBScript自体にはないので、
WScript.Quit(n)のようにホストに頼るしかないでしょう。

もし、ホストに頼ることができない状況なら、以下のパラダイムは如何でしょう。

On Error Resume Next
Call Main()
If Err.Number<vbObjectError Then
WScript.Echo Hex(Err.Number),Err.Number,Err.Source,Err.Description
End If
Sub Main()
...
Err.Raise vbObjectError + n
...
End Sub

ばんのしゃーによかばんた さん 2004年 11月 12日 17時 03分 03秒

>ばんのしゃーによかばんた さん 2004年 11月 08日 16時 30分 46秒
>>管理人むたぐち さん 2004年 11月 06日 17時 10分 34秒
>>> ※検索結果をテキストファイルにするにはどうします?
>>検索結果を全選択して、バッチファイルなりスクリプトなりに「送る」を
>>実行しても、エクスプローラの引数の文字数制限にひっかかったりしますし。
>PowerToyのSend To Clipboard as Nameが使えればよいのでしょうが、

全選択して、「送る」「ドラッグ&ドロップ」のほかに、
「コピー」という手がありますが、その先の「貼り付け」で、
テキストに取り出すことが出来ません。:-(

そこで、
クリップボードのテキストやドラッグ&ドロップデータをテキストに取り出し、
同時にクリップボードのドラッグ&ドロップデータをテキストに変換するJScript.NET。

Visual Studio .NET 2003 コマンド プロンプトで、
jsc ClipOut.JS
してClipOut.exeを実行します。
――――――――――――――――――――――――――――――――――――――
import System
import System.IO
import System.Windows
import System.Windows.Forms
import System.Windows.Forms.Clipboard

var iData : IDataObject = Clipboard.GetDataObject();
if(iData.GetDataPresent(DataFormats.Text)) {
Console.WriteLine(String(iData.GetData(DataFormats.Text)));
}
if(iData.GetDataPresent(DataFormats.FileDrop)) {
var files=iData.GetData(DataFormats.FileDrop)
for(var k=0;k<files.length;k++){
Console.WriteLine(files(k));
}
Clipboard.SetDataObject(files.join('\r\n'),true)
}

※このテーマは昔からやりたかったのですが、VB4やVBAでは、出来なくて、
VB6は持ってなくて、ずっと凹んでいたのですが、
.NETで、こんなに簡単に出来てしまうと、うれしいやら、ちょっと複雑。。。

※ところで、この逆は出来ないものでしょうか。つまり、パス名リストを与えて、
クリップボードにドラッグ&ドロップデータをセットする。

あんのうん さん 2004年 11月 12日 12時 32分 11秒

To: 管理人むたぐち さん

軽く試してみましたがコンパイル済EXEが正しく動くスクリプト
とエラーが出て動かないスクリプトがあります。
WMIとか使っても動いたり、かといって、Msgboxを出すだけの
スクリプトが動かなかったり、いまいち法則性がわかりません。

少なくとも、Wscript.CreateObject(〜)は、CreateObject(〜)
に直さないと動かないことはわかりました。

ちなみに、同じく環境はWindows XP Professional SP2です。

あと、出来たEXEをテキストエディタで開いてみると、スクリプト
がまんま埋め込まれてますね。
確かに面白いですが、いまいちどう使ったらいいやら、、

楽々園の秀 さん 2004年 11月 12日 10時 25分 03秒

どうも早速の対応ありがとうございました。
メールアドレス削除もありがとうございました。

表示は改善されましたが、掲示板への書込ボタンを押すと特定の記事のみしか
右フレームに表示されません。
それは
いりや さん 2003年 12月 23日 19時 48分 55秒
です。

又、右フレームの投稿者名前をクリックしたら 上の記事とその下にクリックした
記事が表示されます。(表示先は登録エディタです)

ではでは。

> To: 楽々園の秀 さん 2004年 11月 11日 15時 44分 39秒
>
> > 掲示板への書込ボタンを押すと下記エラーが発生。
>
> こちらでも再現しました。
> Googleの検索フォームを挿入したのがまずかったようです。
> とりあえず検索フォームを外してみたところ、正常動作するようになったみたいです。


オズ さん 2004年 11月 12日 09時 48分 33秒

いつもお世話になっております。

To: 管理人むたぐち さん

削除できなかった場合の処理は書いてあります。
ただし、削除できないと都合が悪いのでただログを登録して処理を終了させる
だけのものではありますが。


下の方で質問をさせていただいたDeleteFileメソッドのエラーに関してですが、
他のDeleteFileでは殆ど問題が出なかったのにここでだけDeleteFileのエラーが
頻発するのはおかしいと思って先ほどソースを見ていて以下のようなことを
思いました。

共通関数化したDeleteFileメソッドを呼出す直前に対象ファイルを同じく
共通関数化したCopyFileメソッドでコピーしています(要は移動です)。
MoveFileを使えばいいだろうと思えますが、絶対にロストできない
ファイルなので大事をとって2段構えとしました。
(もしかしてMoveFileで移動中にエラーがあってもそんなこと起きないですか?)

もしかして非同期な動作なのはDeleteFileだけでなくCopyFileメソッドも
そうなのでは?と疑問に思いました。
つまり、CopyFile終了後DeleteFile発行時にはまだCopyFileが対象ファイルを
保持しており、DeleteFileには手が出せない状態なのではないか、と。
DeleteFileエラーが起きるのって突発的なものを除いてはここだけです。

ただ、全く同じ処理をASPでもやっている(ブラウザからリアルタイムででやるのと
夜間バッチでやるのとの2通りのやり方を用意しています)のですが、そちらでは
殆ど出ません。そうすると上の推論は的外れなのでしょうか・・・。
考えるとますます分からなくなります。

管理人むたぐち さん 2004年 11月 11日 22時 09分 29秒

To: しんたろ〜 さん

"ネットワークプリンタ WSH" で検索をかけたところ、次のような記事が
ひっかかりました。何かの参考になりますでしょうか。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?forum=8&topic=15924

# UWSCが推奨されていますね。WSHだけでは辛い分野なのかもしれません。


To: オズ さん

> スケジューラで実行しているスクリプト中でFileSystemObjectを用いてファイルを削除する処理があるのですが、そこでたびたびエラーが出て困っております。

実は私も困っています。
WSHではperlのように、ファイルにロックをかけたり、ロックがかかってるかどうかを
調べたりができないので、ファイル処理が上手くいかなかった場合のフォローが
難しいです。

私は、とにかくファイル削除に失敗しても次のステップにすすめるように、
「ファイルが削除できなかった場合」の処理を徹底的に書き下すことで対処しています。

この件について、何か良い案をお持ちの方は、フォロー願います。

管理人むたぐち さん 2004年 11月 11日 22時 02分 27秒

WSH用コンパイラ+(WindowsNT/2000/XP/プログラミング)
http://www.vector.co.jp/soft/winnt/prog/se344839.html

これがぜんぜん動作しないんですけど、うまく動いた方は
いらっしゃいませんか?
環境はWindows XP professional SP2です

管理人むたぐち さん 2004年 11月 11日 21時 44分 04秒

To: 楽々園の秀 さん 2004年 11月 11日 15時 44分 39秒

> 掲示板への書込ボタンを押すと下記エラーが発生。

こちらでも再現しました。
Googleの検索フォームを挿入したのがまずかったようです。
とりあえず検索フォームを外してみたところ、正常動作するようになったみたいです。

しんたろ〜 さん 2004年 11月 11日 18時 17分 46秒

はじめまして。突然失礼します。

WSH初心者な為、初歩的な質問かもしれませんが、
ご回答願えますでしょうか?

現在学校で、ネットワークプリンタを使用しているのですが、
新規にいれるパソコンに、このネットワークプリンタを
WSHを使用して自動的にプリンタの追加したいのですが、
どうすればよいのでしょうか?

教えてください。

楽々園の秀 さん 2004年 11月 11日 17時 57分 44秒

どうもすみません。

下のWSH Lab.掲示板記事検索スクリプト エラーの件で環境を書き忘れました
ので追加します。

Win2000 SP4
IE 6.0.2800.1106

オズ さん 2004年 11月 11日 16時 55分 40秒

いつもお世話になっております。

スケジューラで実行しているスクリプト中でFileSystemObjectを用いてファイルを削除する処理があるのですが、そこでたびたびエラーが出て困っております。
こちらの掲示板の過去ログを見てDeleteFileメソッドは非同期で動作するためタイミングによってはファイルの削除が保証されないということは分かったのですが、ではどうしたらよいのかが自分なりに調べても分かりませんでした。
何か有効な策はあるのでしょうか。
どうかよろしくお願いします。

削除機能は共通関数化してあり、コードは以下の通りです。

Function DeleteFile(ByVal sPath, ByVal bReadOnly)

Dim oFs 'ファイルシステムオブジェクト
Dim oFile 'ファイルオブジェクト

On Error Resume Next

DeleteFile = False

'ファイルシステムオブジェクト作成
Set oFs = CreateObject("Scripting.FileSystemObject")
Set oFile = oFs.GetFile(sPath)

'ファイル削除
'Call oFs.DeleteFile(sPath, bReadOnly)
Call oFile.Delete(bReadOnly)

If Err.Number <> 0 Then
On Error Goto 0
Set oFile = Nothing
Set oFs = Nothing
Exit Function
End If

On Error Goto 0

Set oFile = Nothing
Set oFs = Nothing

DeleteFile = True

End Function

楽々園の秀 さん 2004年 11月 11日 15時 44分 39秒

たびたびすみません。
メールアドレスは 公開だったんですね。
出来れば削除頂け無いでしょうか。m(_ _)m

それと
WSH Lab.掲示板記事検索スクリプト で、不具合が出ています。
掲示板への書込ボタンを押すと下記エラーが発生。
このページのスクリプトでエラーが発生しました。
ライン:1562 文字:2 エラー:'email'はNullまたはオブジェクトではありません
コード:0
URL:file://D:\DOWNLOAD\!Uncompress\WshLab12\WshLab.hta
このページのスクリプトを実行しますか?

対処の仕方を教示下さい。

ではでは。

楽々園の秀 さん 2004年 11月 11日 15時 40分 34秒

どうも始めまして。
ばんのしゃーによかばんた さん が作成されたサンプルを
つぎはぎして、フォルダのファイル名のみをクリップボードに
転送するものを作ってみました。
最初はファイル名取得ループの中で、いきなりクリップボードに
転送するようにしてみようと思いましたが、うまくいかずこの形に
なりました。(IEを同時に2個制御になるのまずいのか良くわかりません)
(その後もしうまくいっても最後の1個のみになると気付きました。^_^;)

最初は原作通りフォルダも含んでいたのですが、出来ればとこちらを
読み返して、Lesson14 の 5 でうまくいきました。感謝、感謝。

右クリックメニューの 送る に登録して使用してますが、さらに欲が
出てきて、右クリックメニューに登録出来ないかと WSHテクニック集
右クリックメニューの実行 に挑戦中です。(ちょっと難しくて難航中)

ではでは。

Option Explicit
Dim fso
DIm tf
Dim wShell
Dim Shell
Dim ie
Dim File
Dim TempName
Dim FolderItem
Dim ReadAllTextFile

Set fso=CreateObject("Scripting.FileSystemObject")
Set wShell=CreateObject("WScript.Shell")
Set Shell=CreateObject("Shell.Application")

Set ie=Shell.Windows.Item
If ie Is Nothing Then
: WScript.Echo "No Explorer Found."
: WScript.Quit
End If
If InStr(TypeName(ie.Document),"IShellFolderView")=0 Then
: WScript.Echo "Explorer is not active."
: WScript.Quit
End If

TempName=fso.BuildPath(fso.GetSpecialFolder(2).Path,fso.GetTempName())
'msgbox TempName
Set File=fso.CreateTextFile(TempName)
For Each FolderItem In ie.Document.Folder.Items
: If fso.FileExists(FolderItem.Path) Then
: File.WriteLine FolderItem.Path
: End If
Next
File.Close
'Call wShell.Run("NotePad.Exe " & TempName,,True)
'Call wShell.Run("""D:\Program Files\Terapad\TeraPad.exe """ & TempName,,True)
'fso.DeleteFile TempName

'SetData相当
Const OLECMDID_COPY = 12
Const OLECMDID_SELECTALL = 17 '(&H11)
Const OLECMDEXECOPT_DODEFAULT = 0
'Dim ie
Set ie=CreateObject("InternetExplorer.Application")
ie.Navigate "about:blank"
Do While ie.Busy Or ie.ReadyState<>4

WScript.Sleep 100

Loop
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Set tf = fso.OpenTextFile(TempName,ForReading)
ReadAllTextFile = tf.ReadAll
'msgbox TempName
tf.Close
fso.DeleteFile TempName

ie.Document.body.innerText=ReadAllTextFile
ie.ExecWB OLECMDID_SELECTALL,OLECMDEXECOPT_DODEFAULT
ie.ExecWB OLECMDID_COPY,OLECMDEXECOPT_DODEFAULT
ie.Quit
'Set ie=Nothing


kuroneko さん 2004年 11月 11日 14時 58分 05秒

いつもお世話になっております。
何度もすみませんが教えてください。お願いします。
ばんのしゃーによかばんた様のレスをいただいてIEのソースをテキストに
保存することが出来ました。有難うございます。
この開いているIEを閉じる方法を教えていただけますでしょうか?
宜しくお願いいたします。

Option Explicit
Dim fso
Dim wShell
Dim Shell
Dim ie
Dim File
Dim TempName

Set fso=CreateObject("Scripting.FileSystemObject")
Set wShell=CreateObject("WScript.Shell")
Set Shell=CreateObject("Shell.Application")

Set ie=Shell.Windows.Item
If ie Is Nothing Then
WScript.Echo "No IE Found."
WScript.Quit
End If
If TypeName(ie.Document)<>"HTMLDocument" Then
WScript.Echo "IE is not active."
WScript.Quit
End If

'TempName=fso.BuildPath(fso.GetSpecialFolder(2).Path,fso.GetTempName())
TempName=fso.BuildPath(fso.GetSpecialFolder(2).Path,fso.GetTempName())
'Set File=fso.CreateTextFile("AAA.txt")
Set File=fso.CreateTextFile("C:\Docume~1\Administrator\デスクトップ\AAA.txt")

File.Write ie.Document.documentElement.outerHTML
File.Close
'Call wShell.Run("NotePad.Exe " & "AAA.txt",,True)
'fso.DeleteFile "AAA.txt"


管理人むたぐち さん 2004年 11月 11日 14時 26分 19秒

To: つちや さん

> できないようです。

やっぱり…。

他に困っているのは、改行コードの扱いです。
文書中で使われている改行コードが定まってないとき(とくに文書保存前には
定まらないことが多い)に、改行コードが何であるかを判別する必要があります。
そうしないと、改行でsplitしたりするときにうまくいかないので。

Set sel=document.selection
sText=sel.Text
If InStr(sText,vbCrLf)<>0 Then
: sNewLine=vbCrLf
ElseIf InStr(sText,vbCr)<>0 Then
: sNewLine=vbCr
ElseIf InStr(sText,vbLf)<>0 Then
: sNewLine=vbLf
End If

今はこんな面倒なコードを書いていますが、
document.NewLineChrとかで取れたり、あるいは定数みたいな感じで
簡単に判別できればいいなあ、と思ったりしています。

あと、Inputboxが使えないのが何気に不便です。
promptでもいいんですが、InputBoxみたいに「キャンセル」を押したときの判別が
できない上に、一行しか文字列を表示できない…。

つちや さん 2004年 11月 11日 13時 47分 56秒

> EmEditor4のマクロは、どうやってExitすればいいかご存知ないですか?

できないようです。
If 〜 EndIfで囲んで対応して下さいと江村さん本人の回答をどこかで読んだ気がします。マクロ部分がなかなかパワーアップしませんよねぇ。

管理人むたぐち さん 2004年 11月 10日 20時 30分 50秒

To: ばんのしゃーによかばんた さん

> LZHは、使わなくなりました。最近は、専らOS標準装備のZIPですね。:-)

昔はオンラインソフトなど、よくLZHで圧縮されていたものですが、
最近は見かけなくなってきましたねー。

> ZIPやCABは、昔(98)、ie.Document.Folderが取れなかったのですが、
> XPでは、このFolderが取れるので、スクリプトからInvokeVerbで操作できそう。:-)

試したことはないのですが、実際にInvokeVerbはできるんでしょうか。
シェルの機能だけで書庫を扱えれば、結構有効利用できそうですけど。

> 同じくOS標準装備のCAB

CAB書庫を作る方法は以前どこかに書いた気がします。
ばんのしゃーによかばんたさんがご存知でないとすれば、2chしかないな、と思って
探してみるとありました。

お前ら、WindowsScripting使ってますか? Part3
http://pc5.2ch.net/test/read.cgi/win/1058829737/

> http://groups.google.com/groups?hl=ja&lr=&ie=UTF-8&inlang=ja&c2coff=1&selm=Oqs%24H3ioCHA.1636%40TK2MSFTNGP09
> cabファイル作成なら、MakeCab.MakeCabというコンポーネントが使えるようです。
> Win2000とXPのみらしいですが。
> また、解凍ができるかどうかは調べてません。
>
> WinXPにはzipファイルを作成する機能がOS標準で存在するので、
> コンポーネントとして登録されているような気がしますがこれも未調査です。
>
> http://groups.google.com/groups?hl=ja&lr=&ie=UTF-8&inlang=ja&c2coff=1&selm=3D7FDE08.CDA30007%40hydro.com
> あまり関係ないですが、WMIを使ってファイルやフォルダに圧縮属性をつける方法が出てます。

Set cab=CreateObject("MakeCab.MakeCab.1")
cab.CreateCab "Test.cab",False,False,False
cab.AddFile "test1.txt","test1.txt"
cab.AddFile "test2.txt","test2.txt"
cab.CloseCab
Set cab=Nothing


To: 魔界の仮面弁士 さん

> 実行ホストによりますが、ASP(サーバサイド)であれば「Response.End」、
> WSHであれば「WScript.Quit」といった所でしょうか。

EmEditor4のマクロは、どうやってExitすればいいかご存知ないですか?
あのマクロは、使い込んでいくと微妙に使いづらいことが判明してきますね…。

ばんのしゃーによかばんた さん 2004年 11月 10日 18時 05分 27秒

>管理人むたぐち さん 2004年 11月 09日 20時 30分 39秒
>To: 魔界の仮面弁士 さん
>> シェルエクステンションに対応したアーカイバとしては、
>> ExpLzh などがありますね。結構便利。
>私はRAR書庫を作ったりするので、Noahを愛用しています。
>あれはちょっとしたスクリプトを書くと、RAR書庫も作れちゃうんですよ。
>RAR書庫を作れるアーカイバは他にあまりないので、重宝しています。
>ExpLzhはシェアウェアなので、ちょっと手を出してません。

LZHは、使わなくなりました。最近は、専らOS標準装備のZIPですね。:-)

SendTo の "圧縮 (zip 形式) フォルダ.ZFSendToTarget"
これも、サイズ0の、拡張子だけ意味のあるファイルです。

ZIPやCABは、昔(98)、ie.Document.Folderが取れなかったのですが、
XPでは、このFolderが取れるので、スクリプトからInvokeVerbで操作できそう。:-)

しかし、ドロップが基本の操作になると、逆に、ZIPの作成、追加をスクリプトから
どうしたものか、困ります。:-(
スクリプトからドロップのシミュレーションが出来ればよいのですが。。。

同じくOS標準装備のCABは、DropHandlerがないので、ちょっと使えない。:-<
これ、WSHのDropHandlerを使って、「関連付け」にスクリプトを挿んで、
なんとかならんでしょうか。。。

>魔界の仮面弁士 さん 2004年 11月 09日 20時 17分 51秒
>》 管理人むたぐち さん
>> 右クリックメニューの「送る」で複数ファイルを渡すようなアプリには、
>> これを実装しておいてもらいたいですね。
>> 特に、アーカイバ系。
>ただ、ActiveX DLLをレジストリ登録する必要があるため、
>軽量系/インストール不要系のアプリケーションでは、
>あえて搭載されないケースが多いようですよ。

ファイルの指定の仕方がアプリのよっていろいろ、というのは困ったもんです。

汎用のDropHandlerで、アプリ起動後にそのウィンドウにドロップする。
なんて、出来ないものか、と昔から考えているのですが。。。

あと、「関連付け」で、アプリ起動後に、メニューの「開く」に引数を入れる。
とかも、あったら便利、と昔から考えているのですが。。。

魔界の仮面弁士 さん 2004年 11月 10日 14時 56分 50秒

》 初心者みきてぃ さん
> 強制的に終了することは、可能なのでしょうか?

実行ホストによりますが、ASP(サーバサイド)であれば「Response.End」、
WSHであれば「WScript.Quit」といった所でしょうか。

ばんのしゃーによかばんた さん 2004年 11月 10日 12時 55分 54秒

>管理人むたぐち さん 2004年 11月 06日 17時 10分 34秒
>> fso.GetStandardStream()は、今まで、単なる内部インタフェースで、特に使い道がない、
>> と思っていましたが、とんでもない。HTA/HTMで標準入出力を使うためには必須の機能です。
>こんなメソッドがあることすら知りませんでした。undocumentedですねー。
>microsoft.public.scripting.wshで何回か話題になっていた程度です。

WSH5.6のヘルプには載ってませんが、MSDN libraryには載ってますね。

応用としては、例えば、Excel VBAでCGIが作れます。:-p

やはり、使い道としては、wShell.Execで起こした、WSH/HTA/HTM/Excelなどの子プロセス
との通信手段でしょうか。

従来、子プロセスとの連携で、StdIn/StdOutで通信しようとすると、
wShell.Execを使うことになって、そうすると、コンソールが表示されて、鬱陶しい。
コンソールを隠すために、wShell.Execを使うと、今度は、通信手段がファイル渡しなどに
なって、面倒臭い。このジレンマの解決になります。

例えば、

>ばんのしゃーによかばんた さん 2004年 09月 15日 16時 28分 00秒
>>ばんのしゃーによかばんた さん 2004年 08月 23日 15時 57分 26秒
>>フォルダ選択処理を、"Scripting.FileSystemObject"でVBSファイルに書き出し、
>>ボタンを押下したとき、"WScript.Shell"でRunする。
>>VBSファイル側は、結果をIEの画面に書き込んで、後の処理をキックする。
>>と言うのはどうでしょう。
>このとき、問題なのは、WSH側から親のIEをどうやって一意に識別するか、です。
>(アクティブとは限らないし、locationの比較も、なんだか心配です。)
>以下、サンプル。
>一意識別のため、VBS一時ファイル名を一時的にTitleにセットして、
>WScript.ScriptFullNameと比較してます。
>簡単のため、ここでは、結果をStatusTextにセットしてます。
>window.execScriptで結果をSubに渡したり、変数に格納したりすればよいでしょう。

と苦労していましたが、

<html> <head> <script language="VBScript">
Sub window_onload()
Set fso=CreateObject("Scripting.FileSystemObject")
filename=fso.BuildPath(fso.GetSpecialFolder(2).Path,fso.GetTempName())
Set file=fso.CreateTextFile(filename)
file.Write "CreateObject(""Scripting.FileSystemObject"").GetStandardStream(1).Write CreateObject(""Shell.Application"").BrowseForFolder(0,""Select Folder"",0,0).Self.Path"
file.Close
Set wShell=CreateObject("WScript.Shell")
Set oExec=wShell.Exec("WScript.exe //E:VBS """ & filename & """")
MsgBox oExec.StdOut.ReadAll()
fso.DeleteFile(filename)
End Sub
</script> </head> <body> </body> </html>

のように簡単に出来ます。

因みに、この処理自体はScriptControlを使えば、もっと簡単に、

<html> <head> <script language="VBScript">
Sub window_onload()
Set sc=CreateObject("ScriptControl")
sc.language="VBScript"
MsgBox sc.eval("CreateObject(""Shell.Application"").BrowseForFolder(0,""Select Folder"",0,0).Self.Path")
End Sub
</script> </head> <body> </body> </html>

で出来ます。

MsgBoxのタイトルの(VBScript: タイトル)の問題も、ScriptControlを使えば解決です。

初心者みきてぃ さん 2004年 11月 10日 11時 59分 26秒


いつもお世話になっております。

質問です。VBScriptで強制終了は出来ないのでしょうか?
Exit Sub で終了する処理はわかっているのですが、
そうすると、次の処理に入ってしまいますよね。
強制的に終了することは、可能なのでしょうか?

フラグを立てて、強制終了処理しようかとも
考えてるのですが、もし、強制的に終了できる処理(仕方)が
あれば、教えてください。

宜しくお願い致します。


YZN さん 2004年 11月 10日 09時 55分 25秒

>bb さん
とりあえず、以下の質問に答えられませんかね?
Q1.記述したサイトにある、サンプルスクリプトは実行してみたでしょうか?
Q2.記述したサイトにある説明の意味はわかりますでしょうか?
Q3.説明の内容(意味)と、サンプルスクリプトの出力結果を見比べて、何が出力されているのか理解できますでしょうか?

>作成頂いたサンプルをvbsファイルとして実行してみましたが
コードの内容がわからないようでは厳しいのですが、
標準出力(StdOut)を使用しています。
cscriptで実行してください。

>WSHは見たことも触ったこともない
>何とか目的を達成したい
とのことですが、あなたの得意な別の方法では、
目的の達成は不可能なのでしょうか?

元記事にある
> *や%で試しました
の具体的内容を教えていただけないでしょうか?

>WSHは見たことも触ったこともない
>お助け頂けないでしょうか?
WSHを知らないままでは、この掲示板で助けることができません・・・。(汗
このWSHLab.のVBS講座の内容をしっかり理解しましょう。
「VBS講座のLessonXXくらいまでの内容なら理解できます」と胸を張って言えるようになりましょう。
ある程度、WSHの内容がわかるように自分で努力しましょう。

bb さん 2004年 11月 10日 08時 57分 50秒

YZN 様
レス感謝致します、しかしここにたどり着くまでWSHは見たことも触ったこともない小生にはほとんど理解できません。
作成頂いたサンプルをvbsファイルとして実行してみましたが
行:5 文字:1 エラー:ハンドルが無効です。 コード:80070006 ソース:(null) のウインドウが出ます。
OSはXP Homeです。
何とか目的を達成したいのですがお助け頂けないでしょうか?

管理人むたぐち さん 2004年 11月 09日 20時 30分 39秒

To: 魔界の仮面弁士 さん

> シェルエクステンションに対応したアーカイバとしては、
> ExpLzh などがありますね。結構便利。

私はRAR書庫を作ったりするので、Noahを愛用しています。
あれはちょっとしたスクリプトを書くと、RAR書庫も作れちゃうんですよ。
RAR書庫を作れるアーカイバは他にあまりないので、重宝しています。
ExpLzhはシェアウェアなので、ちょっと手を出してません。

> ただ、ActiveX DLLをレジストリ登録する必要があるため、

なるほど、Noahとかは、それで搭載してないのかな。

魔界の仮面弁士 さん 2004年 11月 09日 20時 17分 51秒

》 管理人むたぐち さん
> 右クリックメニューの「送る」で複数ファイルを渡すようなアプリには、
> これを実装しておいてもらいたいですね。
> 特に、アーカイバ系。

シェルエクステンションに対応したアーカイバとしては、
ExpLzh などがありますね。結構便利。

ただ、ActiveX DLLをレジストリ登録する必要があるため、
軽量系/インストール不要系のアプリケーションでは、
あえて搭載されないケースが多いようですよ。

管理人むたぐち さん 2004年 11月 09日 18時 57分 56秒

To: 魔界の仮面弁士 さん

> Send To Clipboard は、シェル拡張(Shell Extension)を利用しています。

なるほど、そんな仕掛けがあったんですか。
右クリックメニューの「送る」で複数ファイルを渡すようなアプリには、
これを実装しておいてもらいたいですね。
特に、アーカイバ系。

たまに、引数が長すぎると怒られ、ファイルをウィンドウにドロップしてくれと
言われますが、回避できるものならそのほうがいいですよね。


To: mmm さん

> サブフォルダ内にも適用させるためにはどのような記述が必要となるのでしょうか?

サブフォルダは再帰的に検索するのが、この手のスクリプトの定石です。

たとえば・・

Set Obj = CreateObject("Scripting.fileSystemObject")
Set DocFldr = Obj.GetFolder("C:\Documents and Settings\test\My Documents\")

MoveFolder DocFldr

Sub MoveFolder(objFolder)
: For Each oFile In objFolder.Files
: : oFile.Move "D:\保管フォルダ\"
: Next
: For Each oSubFolder In objFolder.SubFolders
: : MoveFolder oSubFolder
: Next
End Sub

mmm さん 2004年 11月 09日 18時 35分 26秒

質問させてください。
フォルダ内のファイルの更新日を見て、更新が1週間行われていないものを別のフォルダに移動させたいと思っています。
これを実現するためにスクリプトを作成したのですが、そのフォルダ直下のファイルに対しては、うまく動くのですが・・・
そのフォルダの中に、サブフォルダを作成していて、その配下にあるファイルはスクリプトを実行しても、適用されないのです。
サブフォルダ内にも適用させるためにはどのような記述が必要となるのでしょうか?

作成したスクリプトは下記のようなものです。
---------------------
Set Obj = CreateObject("Scripting.fileSystemObject")
Set DocFldr = Obj.GetFolder("C:\Documents and Settings\test\My Documents\")
tr = (Date - 7)
For Each F In DocFldr.Files
if F.DateLastModified < tr Then
F.Move "D:\保管フォルダ\"
End If
Next

Set DocFldr = Obj.GetFolder("C:\Documents and Settings\test\デスクトップ\")
tr = (Date - 7)
For Each F In DocFldr.Files
if F.DateLastModified < tr Then
F.Move "D:\保管フォルダ\"
End If
Next

Set DocFldr = Obj.GetFolder("D:\保管フォルダ\")
tr = (Date - 30)
For Each F In DocFldr.Files
if F.DateLastModified < tr Then
F.delete
End If
Next

YZN さん 2004年 11月 09日 17時 20分 57秒

>bb さん

記述したサイトにある、サンプルスクリプトは実行してみたでしょうか?

たぶんそのままコピーペーストすると、
>Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" &
>strComputer & "\root\default:StdRegProv")
がエラーになると思うので、アンダーバーでつなげてください。
>Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
>strComputer & "\root\default:StdRegProv")

実行できましたでしょうか?
説明の内容(意味)と、出力結果を見比べて、何が出力されているのか理解してください。

>WMI を使用して、HKLM\SYSTEM\CurrentControlSet\Services にあるすべてのレジストリ サブキーを列挙します。
この説明の意味がわからないようでは、
「ワイルドカードのようにしたい」という目的が達成できないのですが・・・。

とりあえず、改良サンプルを記述しておきます。

'=======
sKeys = GetRegKeys
If IsArray(sKeys) Then
For Each sKey In sKeys
WScript.StdOut.WriteLine sKey
Next
End If

Private Function GetRegKeys
Const HKEY_LOCAL_MACHINE = &H80000002
GetRegKeys = ""
strComputer = "."
Set StdOut = WScript.StdOut
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\default:StdRegProv")
strKeyPath = "SYSTEM\ControlSet001\Control\Network"
oReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys1
For Each subkey1 In arrSubKeys1
Rem StdOut.WriteLine strKeyPath & "\" & subkey1
oReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath & "\" & subkey1, arrSubKeys2
If IsArray(arrSubKeys2) And InStr(subkey1,"{") <>0 Then
For Each subkey2 In arrSubKeys2
Rem StdOut.WriteLine strKeyPath & "\" & subkey1 & "\" & subkey2
GetRegKeys = GetRegKeys & strKeyPath & "\" & subkey1 & "\" & subkey2 & vbTab
Next
End If
Next
If GetRegKeys <> "" Then
GetRegKeys = Split(Left(GetRegKeys, Len(GetRegKeys) - 1), vbTab)
End If
End Function

bb さん 2004年 11月 09日 16時 19分 59秒

YZN様
>マイクロソフト スクリプトセンター より
>[サブキーの列挙]

小生には全く理解できませんでした (:_;)

YZN さん 2004年 11月 09日 14時 01分 22秒

>bb さん

マイクロソフト スクリプトセンター より
[サブキーの列挙]
http://www.microsoft.com/japan/technet/scriptcenter/registry/scrreg09.mspx

参考にどうぞ。

bb さん 2004年 11月 09日 13時 09分 26秒

管理人むたぐち様
レスありがとうございます。 小生の説明不足だったようで、再度お伺いします。

書込みしたいのは
[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\{9337EC87-E5C5-46F1-974E-03071375B6E8}\Connection]
"ShowIcon"=dword:00000001
であり、この中の\Network\ の次 {4D36・・・0318} とその次 {9337・・・B6E8}
がPCによって異なるのでこの2箇所をワイルドカードのようにしたいのです。
実際に書き込むのは\Connection の下の"ShowIcon"=dword:00000001 です。
WSHについては初心者なので詳しく教えていただけると幸いです。

魔界の仮面弁士 さん 2004年 11月 09日 11時 02分 18秒

》 管理人むたぐち さん
Send To Clipboard は、シェル拡張(Shell Extension)を利用しています。

COMの実装が必要なので、スクリプト系では実装できませんが、
VB6やVB.NETなどがあれば、独自実装も可能です。

「送る」においては、レジストリに登録された Drop Handler を
経由して、処理が行われる事になります。

大雑把に言えば、IDropTargetインターフェイス、および、
IPersistFileインターフェイスを実装したDLLをレジストリに
登録しておくことで、各インターフェイスのメソッドが
呼び出されようになるので、そこに処理を書いておく事になります。

ドロップされてきたファイルの一覧は、IDropTarget::Dropの
引数として渡されますが、これは文字列ではなく、
IDataObjectインターフェイスによって渡されますので、
コマンドラインの文字列長制限を受けることもありません。

# Send To Clipboard (for XP)では、「*.NameOnClipboard」という
# 拡張子のファイルとして登録されていますね。

管理人むたぐち さん 2004年 11月 08日 23時 41分 59秒

To: ばんのしゃーによかばんた さん

> PowerToyのSend To Clipboard as Nameが使えればよいのでしょうが、
> XPでも動くのでしょうか。試してません。

あ、これがありましたね。私はXPに入れていますが、
特に問題なく使えています。

このSend To Clipboard as Nameを使えば、何故かコマンドラインの
文字数制限にひっかからないんですよね。
どうやってるのかは知らないですけど、「ずるいなぁ」って思います。


To: bb さん

> 1つのregファイルを使って複数のPCに書き込みたいのですが例えば
> [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Network\{xxx}\{yyy}\Connection] で最後の\Connection の下に書込みしたいのですがxxx、yyyはPCによって異なります。
> ここをワイルドカードみたいにできないでしょうか? *や%で試しましたがだめでした。

RegWriteメソッドではワイルドカードは使えませんね。
コード中でやりくりしないと駄目だと思います。

xxx="xxxxx"
yyy="yyyyy"
WshShell.RegWrite "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Network\" & xxx & "\" & yyy & "\Connection","value"

というように、コード中でキーを生成してください。

Return