ばんのしゃーによかばんた さん 2005年 02月 01日 19時 21分 36秒

Vectorにソフトを登録していると、毎月、[Vector] 登録内容確認のお願い
というメールが来ます。
それ("$edit.txt")をCSVファイル("$edit.csv")に加工して、HTAで表示します。
――――――――――――――――――――――――――――――――――――――
Set fso=CreateObject("Scripting.FileSystemObject")
Set re=New RegExp
re.Global=True
re.Pattern=" v ----<ライブラリ作品番号:(PS\d{6})>---\r\n" & _
"\((.)\) (.+) ([\d\.]+)\r\n" & _
"    ([^ ]+) ([\d/]+) (\d+)\r\n" & _
"概要:(.+)\r\n" & _
"通算ダウンロード数 (\d+)\r\n" & _
"(.+)\r\n \r\n"
buf=fso.OpenTextFile("$edit.txt").ReadAll
Set Matches=re.Execute(buf)
WScript.Echo Matches.Count
Set StdOut=fso.CreateTextFile("$edit.csv")
StdOut.WriteLine Join(Array("ライブラリ作品番号","公開","ソフト名称","バージョン","アーカイブファイルの名前","日付:Date","サイズ:Int","概要","通算ダウンロード数:Int","URL"),",")
Dim cols(9)
For Each Match In Matches
 For k=0 To 9
  Select Case k
  Case 2,7 cols(k)=Chr(34) & Replace(Match.Submatches.Item(k),"""","”") & Chr(34)
  Case Else cols(k)=Match.Submatches.Item(k)
  End Select
 Next
 StdOut.WriteLine Join(cols,",")
Next
――――――――――――――――――――――――――――――――――――――
<HTML><HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=x-sjis">
<TITLE>[Vector] 登録内容確認のお願い</TITLE>
<OBJECT ID="Soft" WIDTH=0 HEIGHT=0
CLASSID="CLSID:333C7BC4-460F-11D0-BC04-0080C7055A83">
<PARAM NAME="DataURL" VALUE="./$edit.csv">
<PARAM NAME="UseHeader" VALUE="true">
</OBJECT>
<SCRIPT LANGUAGE="JavaScript">
<!--
function filter1() {
  Soft.Filter = "公開=Y";
  Soft.Reset();
}
function sort1() {
  Soft.Sort= "通算ダウンロード数";
  Soft.Reset();
}
function sort2() {
  Soft.Sort= "日付";
  Soft.Reset();
}
function chRecord(select_record) {
  Soft.recordset.AbsolutePosition = select_record.recordNumber;
  RNum.innerText=Soft.recordset.AbsolutePosition;
}
//-->
</SCRIPT>
</HEAD>
<BODY ONLOAD="TNum.innerText=Soft.recordset.recordCount">
<FORM>
<INPUT TYPE="button" VALUE="先頭" ONCLICK="Soft.recordset.MoveFirst();RNum.innerText=Soft.recordset.AbsolutePosition">
<INPUT TYPE="button" VALUE="前項" ONCLICK="Soft.recordset.MovePrevious();RNum.innerText=Soft.recordset.AbsolutePosition">
<INPUT TYPE="button" VALUE="次項" ONCLICK="Soft.recordset.MoveNext();RNum.innerText=Soft.recordset.AbsolutePosition">
<INPUT TYPE="button" VALUE="最後" ONCLICK="Soft.recordset.MoveLast();RNum.innerText=Soft.recordset.AbsolutePosition">
</FORM>
<TABLE BORDER>
<TR><TD>総数</TD>
<TD><SPAN ID="TNum">0</SPAN></TD></TR>
<TR><TD>番号</TD>
<TD><SPAN ID="RNum">1</SPAN></TD></TR>
<TR><TD>ライブラリ作品番号</TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="ライブラリ作品番号"></SPAN></TD></TR>
<TR><TD>公開</TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="公開"></SPAN></TD></TR>
<TR><TD>ソフト名称</TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="ソフト名称"></SPAN></TD></TR>
<TR><TD>バージョン</TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="バージョン"></SPAN></TD></TR>
<TR><TD>アーカイブファイルの名前</TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="アーカイブファイルの名前"></SPAN></TD></TR>
<TR><TD>日付</TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="日付"></SPAN></TD></TR>
<TR><TD>サイズ</TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="サイズ"></SPAN></TD></TR>
<TR><TD>概要</TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="概要"></SPAN></TD></TR>
<TR><TD>通算ダウンロード数</TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="通算ダウンロード数"></SPAN></TD></TR>
<TR><TD>URL</TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="URL"></SPAN></TD></TR>
</TABLE>
<FORM>
<INPUT TYPE="button" VALUE="公開のみ" ONCLICK="filter1()">
<INPUT TYPE="button" VALUE="日付 昇順" ONCLICK="sort2()">
<INPUT TYPE="button" VALUE="通算ダウンロード数 昇順" ONCLICK="sort1()">
</FORM>
<TABLE DATASRC="#Soft" BORDER>
<THEAD>
<TD>ライブラリ作品番号</TD>
<TD>公開</TD>
<TD>ソフト名称</TD>
<TD>バージョン</TD>
<TD>アーカイブファイルの名前</TD>
<TD>日付</TD>
<TD>サイズ</TD>
<TD>概要</TD>
<TD>通算ダウンロード数</TD>
<TD>URL</TD>
</THEAD>
<TBODY>
<TR STYLE="cursor:hand;" onclick="chRecord(this)">
<TD><SPAN DATASRC="#Soft" DATAFLD="ライブラリ作品番号"></SPAN></TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="公開"></SPAN></TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="ソフト名称"></SPAN></TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="バージョン"></SPAN></TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="アーカイブファイルの名前"></SPAN></TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="日付"></SPAN></TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="サイズ"></SPAN></TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="概要"></SPAN></TD>
<TD><SPAN DATASRC="#Soft" DATAFLD="通算ダウンロード数"></SPAN></TD>
<TD><A DATASRC="#Soft" DATAFLD="URL"><SPAN DATASRC="#Soft" DATAFLD="URL"></SPAN></A></TD>
</TR>
</TBODY>
</TABLE>
</BODY>
</HTML>
――――――――――――――――――――――――――――――――――――――
※本当は、前月と比較して、「通算ダウンロード数」の増分を出したいのですが、
どうすりゃいいものやら。。。
力ずくでテキスト処理するなら、新旧二つのCSVを合わせてソートして、
比較しながら第3のCSVを吐き出す。unixのjoinコマンドなら簡単なのに。
折角だから、recordsetを使ってもっとスマートに出来ないものかしら。。。


ばんのしゃーによかばんた さん 2005年 02月 01日 19時 20分 52秒

ProgressBarもどきにも使えますね。

Set AgentControl= WScript.CreateObject("Agent.Control","AC_")
AgentControl.Connected=True
'AgentControl.Characters.Load "merlin","C:\Windows\msagent\chars\merlin.acs"
AgentControl.Characters.Load "マーリン"
Set chars=AgentControl.Characters("マーリン")
chars.AutoPopUpMenu=False
chars.IdleOn=False
Set Balloon=chars.Balloon
Balloon.Style=Balloon.Style And Not 4
chars.Show
For k=0 To 10
Set Req=chars.Think( "なんとかの処理中。(" & k*10 & "%)" & vbTab & String(k,"■") & String(10-k,"□") )
WScript.Sleep 1000
Next
Balloon.Visible=False
chars.Hide

Sub AC_BalloonHide(Char)
chars.Balloon.Visible=True
End Sub

――――――――――――――――――――――――――――――――――――――
ところで、TTSのSpeechEngineについて。
2000にはSamさん一人が標準で付いていましたが、私のXPには、Samさんが居ません。
代わりに、プレインストール元のToshibaのお兄さんお姉さんたちが居ます。
他のXPではどうでしょうか?誰か標準で付いていますか?


魔界の仮面弁士 さん 2005年 02月 01日 10時 13分 45秒

》 ばんのしゃーによかばんた さん 2005年01月31日 19時25分17秒
>>魔界の仮面弁士 さん 2005年 01月 30日 21時 47分 06秒
>> 「Variant型を参照しているVariant 型」になるようです。

これ、某所でいろいろ検証してみているのですが、どうも先の URL の内容とは、
VBSからの呼び出し動作結果が異なっているような気が……(現在も追試中です)。

なお、VARIANT型の実装については、Dr.GUIの記事を参考に。
http://www.microsoft.com/japan/msdn/library/ja/jpdnguion/htm/drgui032999.asp
http://www.microsoft.com/japan/msdn/library/ja/jpdnguion/htm/drgui042099.asp



>> VBAでいえば、 V = CVar(CStr(〜)) に近い処理でしょうか。
> CStr(〜)とCVar(CStr(〜))の違いが出るのは、どういうときでしょうか?

違いが出るというか、代入先がVariantなら自動的にCVarされる、という認識です。
VBScriptの場合、CVar関数はありませんが、代入先は必ずVariantですよね。


> VBScript側の「障害」ですね。
こうした現象は、VBScriptだけに発生するわけではありませんよ。

今回は VBScript からの呼び出しの場合でしたが、Variant型を受け取るメソッドの
呼び出しで、データ型を強く意識しなければならない場合があるという点では、
VBA でも一緒です。

たとえば、IEの「文字のサイズ」を変更するようなコードの場合、
  ZoomSize = 文字サイズをあらわす0〜4の5段階値
  IE.ExecWB OLECMDID_ZOOM, OLECMDEXECOPT_DODEFAULT, ZoomSize
という風に書くのですが、この場合の ZoomSize というのは、
『内部処理形式 Long の Variant型』を渡す必要があります。(Integerは不可)

そして、この ZoomSize の型を
  Dim ZoomSize As Long
  ZoomSize = 1&
  IE.ExecWB OLECMDID_ZOOM, OLECMDEXECOPT_DODEFAULT, ZoomSize
のようにした場合、文字サイズの変更は行われません。無視されます。

この場合は、今回の InvokeVerbメソッドのケースと同様、
  IE.ExecWB OLECMDID_ZOOM, OLECMDEXECOPT_DODEFAULT, (ZoomSize)
のように括弧をつけて渡すか、もしくは、
  Dim ZoomSize As Variant
  ZoomSize = 1&
  IE.ExecWB OLECMDID_ZOOM, OLECMDEXECOPT_DODEFAULT, ZoomSize
のように、Variant型で渡す必要があります。定数値を渡してもOK。

ばんのしゃーによかばんた さん 2005年 01月 31日 19時 25分 17秒

>魔界の仮面弁士 さん 2005年 01月 30日 21時 47分 06秒
>どうやら、文字列を格納した変数を直接渡すと、(VBScriptでは)
>「内部処理形式String型の Variant 型」ではなく、
>「Variant型を参照しているVariant 型」になるようです。

VBScript側の「障害」ですね。
もし「Variant型を参照しているVariant 型」がありなら、
Variant型を参照しているVariant 型1を参照しているVariant 型2を〜3を〜...N
(N→アレフ0?)もありってことに。

この障害の回避方法は、一般に、括弧で囲む、
Call FolderItem.InvokeVerb((Verb))
ですね。

1年以上、もやもやしていた疑問が解消してすっきりしました。
おおきにありがとうござます。

ところで、
>VBAでいえば、 V = CVar(CStr(〜)) に近い処理でしょうか。
CStr(〜)とCVar(CStr(〜))の違いが出るのは、どういうときでしょうか?


通りすがりの者! さん 2005年 01月 31日 17時 14分 44秒

ある場所にあらかじめ指定したファイルがあれば違うファイルを実行するというようなVBSは作れますか?
作れましたらそのソースを教えて下さい。初心者なんですがよろしくお願いします。

魔界の仮面弁士 さん 2005年 01月 30日 23時 28分 39秒

> > [in, optional] VARIANT vVerb
> これは、VBAで書くと、
> Sub InvokeVerb(Optional ByVal vVerb As Variant)
> でしょうか?

さぁ…。私も インターフェイス定義言語は読めないので、
そこまではわかりません。

で、わからないので実験です。
VB6で、ByRef / ByVal な DLLを作ってみました。

============
Option Explicit
Public Sub ByValMethod(Optional ByVal vVerb As Variant)
End Sub
Public Sub ByRefMethod(Optional ByRef vVerb As Variant)
End Sub
============

これを、OLEVIEW で解析すると、こんな感じになりました。
 void ByValMethod([in, optional] VARIANT vVerb);
 void ByRefMethod([in, out, optional] VARIANT* vVerb);


……これから見ると、VB的には
> Sub InvokeVerb(Optional ByVal vVerb As Variant)
が正解のようですね。


そこで、この結果を元に、改めて先の URL の表と比較。
http://program.station.ez-net.jp/special/vc/atl-com/variant.asp

VBScript が、文字列を渡す所を見てみると、こうなっています。


渡した引数  VARIANT(ByVal)     LPVARIANT(ByRef?)
----------- ---------------------  -----------------
文字型変数  VT_BYREF | VT_VARIANT  VT_BSTR
文字列定数  VT_BSTR         VT_BSTR


ちなみに VBA はこう。ずいぶんと違いますね。

渡した引数  VARIANT(ByVal)     LPVARIANT(ByRef?)
----------- ---------------------  -----------------
文字型変数  VT_BSTR         VT_BYREF | VT_BSTR
文字列定数  VT_BSTR         VT_BSTR



> Sub InvokeVerb(Optional ByVal vVerb As Variant)
> なんだけど、
> > ByRef Variant な引数に変数を渡すと、参照渡し。
> のように扱われていて、
VBScriptの場合の「VT_BYREF」が、まさにこの状態のようです。


> Variant型の内部構造にバリエーションとかはないでしょうか?
古いSDKと比較してみないと、確信はもてませんが、確か、
VARIANT構造体の定義は、昔から大きく変わっていなかったと思います。


> 違っていて、InvokeVerb側はError型と誤認してしまう。
この際、VT_ERROR「内部形式 ErrorのVariant型」の事は忘れましょう。
VBA的に言えば、IsMissing()で判断しているというよりも、
  If VarType(引数) = vbString Then
   引数に応じたVerb呼び出し
  Else
   規定のVerbの呼び出し
  End If
って事じゃないですかね。VT_I2 「内部形式 Integer型のVariant型」を
渡しても、省略時と同じ動作をするみたいですし。
 oFolderItem.InvokeVerb 3

> この括弧は=xxx()やcall xxx()の括弧ではなく、式の括弧だったのですか。
そう。他言語を知っている人には覚えにくいと言われますが、
括弧の扱いに気をつけないといけません。

「Method 引数1」=「Call Method(引数1)」であって、
「Method (引数1)」=「Call Method((引数1))」なのですよ。

ばんのしゃーによかばんた さん 2005年 01月 30日 22時 24分 03秒

ほぼ同じ結論に到達しました。

>魔界の仮面弁士 さん 2005年 01月 29日 20時 21分 06秒
> [in, optional] VARIANT vVerb
同じです。XP SP2ですもん。

これは、VBAで書くと、
Sub InvokeVerb(Optional ByVal vVerb As Variant)
でしょうか?

そうすると、
>ByVal Variant な引数に変数を渡すと、値渡し。
>ByRef Variant な引数に変数を渡すと、参照渡し。
値渡しになって、ちゃんと動くはずですよね。

それが、動かない。

そこで、同様に動かないパターンを見つけて、それに該当する可能性は
ないものかとあれこれ思案、障害/トラブル調査時の仮説検証です。

もし、
Sub InvokeVerb(Optional ByRef vVerb As String)
だったら、動かない。ので、

もしかして、
> [in, optional] VARIANT vVerb
を、VBScript側がなんかしら、
Sub InvokeVerb(Optional ByRef vVerb As String)
のように扱っている、ってことはないかしら、と。

>> ここで、実は、型不一致で、Error型(省略の意味)が渡る。
>あれ、 VT_ERROR な Variantになってますか……?
>ByRef String な引数に変数を渡すと、VBS側で実行時エラー[型が一致しません]。
>という結果になっていました。
>コンポーネント側の定義が ByRef String だと、実行時エラーにこそ
>なっていましたが…… VT_ERROR 相当の値は確認できませんでした。

推測です。:-p
VBS側で実行時エラー[型が一致しません]。にならない、かつ、ちゃんと動かない、
なら、何が渡ってるのかな、と。

と言うことは、なんだろ?
Sub InvokeVerb(Optional ByVal vVerb As Variant)
なんだけど、
>ByRef Variant な引数に変数を渡すと、参照渡し。
のように扱われていて、
参照渡しだと、InvokeVerb側でちゃんと認識できないで、無視してしまう、
でしょうか?

Variant型の内部構造にバリエーションとかはないでしょうか?
VBSで変数宣言したVariant型と、値渡しで、式から生成するVariant型が微妙に
違っていて、InvokeVerb側はError型と誤認してしまう。
例えば、変数宣言したVariant型は何でも格納できる重装備タイプ、
式から生成するVariant型はその型だけの軽装タイプ、とか。
変数から値渡しのときは、そのままコピー。

ところで、
>> FolderItem.InvokeVerb(Verb)---String型に暗黙的に型変換
>これらも、括弧をつけているので「式」扱い。やはり『値渡し』ですね。
!!!
この括弧は=xxx()やcall xxx()の括弧ではなく、式の括弧だったのですか。
xxx 引数...
の構文だったんですね。
xxx (a),(b),(c)
みたいな使い方のひとつのケース。
MsgBox("a"),(1),("b")
MsgBox("a")
これって常識?


魔界の仮面弁士 さん 2005年 01月 30日 21時 47分 06秒

》魔界の仮面弁士 2005年01月29日 20時21分06秒
>
> 》 ばんのしゃーによかばんた さん 2005年01月29日 17時56分06秒
> > FolderItem.InvokeVerb Verb---バリアント型 (内部処理形式がString型)
> > ここで、実は、型不一致で、Error型(省略の意味)が渡る。
> あれ、 VT_ERROR な Variantになってますか……?
>

その後、Error型が渡される可能性を探ってみましたが、今のところ
「パラメータの省略時」と、「(VBAの)CVErr関数を併用した時」ぐらいしか
再現しませんでした。

もしかして、
 FolderItem.InvokeVerb Verb
と書くつもりで、
 FolderItem.InvokeVerb
のようにテストしていた……なんて事はありませんか。


それはさておき、肝心の
》 ばんのしゃーによかばんた さん 2005年01月27日 19時22分35秒
> 文字列を直接指定するとOK。
> Call FolderItem.InvokeVerb("削除(&D)")
> 文字列を変数に代入して変数を指定するとNG。
という件ですが。理由がなんとなく分かりました。


……といっても、私もさっぱり分からないので、COMに詳しい、
社本さん(VC++のMVPの方です)に助けを求めたのですが。


社本さんも、VBScriptの動作についてはご存知無い様でしたが、
今回の動作に関して、
  『大雑把に言うと、VariantChangeType API が
   ちゃんとかかっていないんだと思います。』
との大ヒントを頂きました。

で、この API をキーワードに調べてみると、こんなページを発見!
http://program.station.ez-net.jp/special/vc/atl-com/variant.asp


どうやら、文字列を格納した変数を直接渡すと、(VBScriptでは)
「内部処理形式String型の Variant 型」ではなく、
「Variant型を参照しているVariant 型」になるようです。

状況からして、おそらくはこれが原因なのでしょう。


ここからは私の想像ですが、InvokeVerb() メソッド内部では、
  『引数が VT_BSTR で渡された場合だけ処理する』
  『それ以外のデータ型なら、規定の動作を行う』
といった設計になっているのだと思われます。

そして、変数を直接指定してしまった場合、VT_BSTR としては
渡されないため、メソッドが期待とは異なる動作になる……と、
いう事なのでは無いでしょうか。あくまで予測ですけれどね。

魔界の仮面弁士 さん 2005年 01月 30日 20時 12分 46秒

》 まろん さん 2005年01月28日 19時58分05秒
> 以前、魔界の仮面弁士さんが、WSHでIEを操作し、ファイルのダウンロードの

以前、というのがどの投稿かわかりませんが、それは、
> 【↓以前紹介されていたソース】
の事でしょうか? だとしたら、それは IE の操作ではありませんよ。

XMLHTTPは、HTTP/HTTPSによるデータ通信に特化していますが、
InternetExplorerとは異なるコンポーネントです。


> これを利用しようと頑張っているのですが、うまくいきません。
まず、ブラウザから手動でアップロードする事はできますか?
もしできるなら、「InetSpy」などのツールを使って、Webサーバとブラウザの間で、
どのようなデータが交換されているのかを確認してみてください。

XMLHTTPで処理する場合に、それと同じデータが送信されるようにすれば、
正しくアップロードされるようになるはずです。


> ちなみに、下記のようなフォームがありまして、
あれ……<input type="submit">も、<input type="image">もありませんね。

おそらく、<A HREF="javascript:fncInputCehck();"> によって、JScriptにて
フォームのsubmitメソッドを呼び出しているのだと思いますが、
fncInputCehck() 側で何をしているのか分からないので、具体的な
回答はできそうにないです。m(_ _)m

# それにしても、Check ではなく、Cehck なのがとっても気になる。(^^;



> VBSを使ってファイル名を設定して、アップロードボタンを押したいのです。
ボタンを『押』したい、ということは、IE操作を想定されているのかと思います。

単なるボタン操作なら、IEから documentプロパティを辿り、ボタンオブジェクトの
「click メソッド」を呼び出すだけで OK です。

ただしセキュリティ上、<input type="file"> へのファイル名の指定については、
スクリプトからは制御できないため、ファイルの指定は手動操作になってしまいます。


もし、ファイル名の指定も VBScript から行いたいなら、InternetExplorerを
使うのはあきらめて、XMLHTTP で送信する方法で対処してみてください。


> "Referer"や"Content-Type"、"Submit=%91%97%90M"
> に何を代入すればよいのかわかりません。
Referer が必要かどうかは、サーバ側の設定によりますが、とりあえずは、
そのアップロードページの URL を指定しておけば良いかと思います。

Content-Type は、<form>の enctype属性が "multipart/form-data" なので、
 xmlHttpRequest.setRequestHeader "Content-Type", "multipart/form-data; boundary=" & 境界文字列
といった感じにしてみてください。

なお境界文字列は、たとえば IEの場合には、
『-----------------------------7d51c52850034a』のようなデータが使われています。
IEでは、最後の英数字部分が送信のたびに変化していますが、固定データでもOKです。
(ただし、データ中に含まれない文字列にする必要があります)


なお、sendメソッドの引数には、送信するデータを渡します。
データの作成手順のイメージとしては、
 v = 境界文字列
 v = v & "Content-Disposition: form-data; name=""UpFile0"";"
 v = v & " filename=""" & ファイル名 & """ & vbCrLf
 v = v & "Content-Type: " & データ形式 & vbCrLf & vbCrLf
 v = v & ファイルのバイナリ
 v = v & 境界文字列 & "--"
のようになります。

なお、Content-Type に指定する「データ形式」については、たとえば
テキストファイルなら "text/plain"、exe等なら "application/octet-stream"
などの文字列を指定する事になります。

ばんのしゃーによかばんた さん 2005年 01月 30日 19時 18分 43秒

「ごみ箱」のファイルは、エクスプローラで見える名前と実際のディスク上の
名前が異なるため、普通「元に戻す」してからでないと中身を見ることが出来ません。
それは不便なので、「ごみ箱」のファイルを「元に戻す」さないで、
そのままNotePadで見るVBScriptです。「お気に入り」に入れて使います。
フォルダの場合は、コマンドプロンプトで開きます。

Set Shell=CreateObject("Shell.Application")
Path=Shell.Windows.Item.Document.FocusedItem.Path
If vbOK=MsgBox(Path,vbOkCancel,"View Path ?") Then
 Set fso=CreateObject("Scripting.FileSystemObject")
 Set wShell=CreateObject("WScript.Shell")
 If fso.FileExists(Path) Then
  wShell.Run "NotePad.EXE " & Path
 ElseIf fso.FolderExists(Path) Then
  If InStr(WScript.FullName,"32") Then
   wShell.Run "CMD.EXE /K CD /D " & Path
  ElseIf WScript.Version>5.5 Then
   wShell.CurrentDirectory=Path
   wShell.Run "COMMAND.COM"
  ElseIf UCase(Left(Path,1))=UCase(Left(fso.GetAbsolutePathName(""),1)) Then
   wShell.Run "COMMAND.COM /K CD " & Path
  Else
   wShell.Run "COMMAND.COM /K " & Left(Path,2) & " | CD " & Path
  End If
 End If
End If

※動作環境がないところで、9xでも動くように、なんて考えると面倒ですね。:-<

ばんのしゃーによかばんた さん 2005年 01月 30日 19時 18分 18秒

>初心者 さん 2005年 01月 27日 01時 37分 46秒
>何かコマンドを実行中に常に最前面にポップアップで「実行中」等のメッセージを表示させておきたいのですが、この際、ポップアップを閉じるボタン等は表示させたくありません。ポップアップは、コマンド終了時に閉じるようにしたいのですが可能でしょうか?

そう云えば、ぴったりの機能がありましたね。すっかり忘れてました。
――――――――――――――――――――――――――――――――――――――
Set AgentControl= WScript.CreateObject("Agent.Control","AC_")
AgentControl.Connected=True
'AgentControl.Characters.Load "merlin","C:\Windows\msagent\chars\merlin.acs"
AgentControl.Characters.Load "マーリン"
Set chars=AgentControl.Characters("マーリン")
chars.AutoPopUpMenu=False
chars.IdleOn=False
Set Balloon=chars.Balloon
Balloon.Style=Balloon.Style And Not 4
chars.Show
'chars.TTSModeID="{c5c35d60-da44-11d1-B1F1-0000F803E456}"
Set Req=chars.Speak( "#1処理中です。" )
'Set Req=chars.Think( "#1処理中です。" )
msgbox "#1処理をする。"
Set Req=chars.Think( "#2処理中です。" )
msgbox "#2処理をする。"
Balloon.Visible=False
chars.Hide

Sub AC_BalloonHide(Char)
chars.Balloon.Visible=True
End Sub
――――――――――――――――――――――――――――――――――――――
Merlin.IdleON=Falseで動きが止まります。
Speak/Thinkは吹き出しのスタイルがちょっと違う。
(TTSModeIDを指定すれば喋ります。)
――――――――――――――――――――――――――――――――――――――
以下でシステムにインストールされているModeIDを調べます。
――――――――――――――――――――――――――――――――――――――
Set TTS=CreateObject("TextToSpeech.TextToSpeech.1")
ReDim rows(TTS.CountEngines+1)
rows(0)=Join(Array("#","Speaker","Age","Gender","LanguageID","ModeID"&vbTab&vbTab,"ModeName"),vbTab)
For k=1 To TTS.CountEngines
 rows(k)=Join(Array(k,TTS.Speaker(k),TTS.Age(k),TTS.Gender(k),TTS.LanguageID(k),TTS.ModeID(k),TTS.ModeName(k)),vbTab)
Next
rows(k)=Join(Array("CountEngines",TTS.CountEngines,"CurrentMode",TTS.CurrentMode,"TTSMode",TTS.TTSMode),vbTab)
WScript.Echo Join(rows,vbCrLf)
――――――――――――――――――――――――――――――――――――――
以下でシステムに登録されているキャラを調べます。
――――――――――――――――――――――――――――――――――――――
Set AgentControl= CreateObject("Agent.Control")
AgentControl.Connected = True
AgentControl.ShowDefaultCharacterProperties
MsgBox "表示終了?"
――――――――――――――――――――――――――――――――――――――
以下でシステムに存在するキャラファイルを検索します。
パスを指定してloadすれば使えます。
――――――――――――――――――――――――――――――――――――――
Set fso=CreateObject("Scripting.FileSystemObject")
Call acs(fso.GetSpecialFolder(0).SubFolders("msagent").SubFolders("chars"))
'"C:\Windows\msagent\chars"

Set xl=CreateObject("Excel.Application")
Call acs(fso.GetFolder(xl.Path))
'"C:\Program Files\Microsoft Office\Office"
xl.Quit

Sub acs(Folder)
Dim File
Dim k:k=0
Dim rows():ReDim rows(0)
rows(0)=Folder.Path
For Each File In Folder.Files
 If LCase(fso.GetExtensionName(File))="acs" Then
   k=k+1
   ReDim Preserve rows(k)
   rows(k)=File.Name
 End If
Next
WScript.Echo Join(rows,vbCrLf)
End Sub
――――――――――――――――――――――――――――――――――――――

魔界の仮面弁士 さん 2005年 01月 29日 20時 21分 06秒

》 ばんのしゃーによかばんた さん 2005年 01月 29日 17時 56分 06秒
> VBScriptのヘルプのCStr()の記述、
> 「指定された式をバリアント型 (内部処理形式が文字列型 (String) の Variant) に変換して返します。」
VBAでいえば、 V = CVar(CStr(〜)) に近い処理でしょうか。


> Sub InvokeVerb(Optional ByRef vVerb As String)
あれ?

うちの WinXP Pro SP2 環境(Shell32.dll v6.0.2900.2180) のタイプライブラリでは、
ディスパッチインターフェイス側の引数は、BSTR* ではなく、VARIANT で定義されていましたよ。
  [in, optional] VARIANT vVerb

まさか、バージョンによって定義が異なるのかな……。


> 文字列を直接指定するとOK。
> Call FolderItem.InvokeVerb("削除(&D)")---String型
この場合は、変数ではなく、文字列リテラルという「式」が
渡されているため、データが『値渡し』されますね。

> FolderItem.InvokeVerb(Verb)---String型に暗黙的に型変換
> Call FolderItem.InvokeVerb(CStr(Verb))---String型に明示的に型変換
これらも、括弧をつけているので「式」扱い。やはり『値渡し』ですね。


> 文字列を変数に代入して変数を指定するとNG。
この場合は変数が直接渡されたので、Variant型の『参照渡し』ですね。
もし、定義側が ByRef Variant であったとすれば、ですけど。


> ここで、実は、型不一致で、Error型(省略の意味)が渡る。
あれ、 VT_ERROR な Variantになってますか……?
何かの環境の差なのでしょうか。

実験用にCOMコンポーネントを作成して、VBScriptからの引数の渡り方を
追跡してみましたが、当方の環境では、

ByVal Variant な引数に変数を渡すと、値渡し。
ByRef Variant な引数に変数を渡すと、参照渡し。
ByVal String な引数に変数を渡すと、値渡し。
ByRef String な引数に変数を渡すと、VBS側で実行時エラー[型が一致しません]。

という結果になっていました。

コンポーネント側の定義が ByRef String だと、実行時エラーにこそ
なっていましたが…… VT_ERROR 相当の値は確認できませんでした。


先ほどのタイプライブラリの型も違っているようでしたが、
もしかしたら、環境によって違いがあるのでしょうかね。

# Win98環境を構築して、確認してみようかな。

ばんのしゃーによかばんた さん 2005年 01月 29日 17時 56分 06秒

>魔界の仮面弁士 さん 2005年 01月 28日 18時 30分 31秒
>2番目の String("aaa") 構文は、型変換。
>C#なら (String)"aaa" と書くところですが。

あれ、型変換の構文でしたか。
new String("aaa")との類似にばかり気を取られていました。

VBScriptなどのCStr()みたいなもんですね。こちらは関数ですけど。

JScriptで、
var s=String(1);
WScript.Echo(typeof(s));
var n=Number(1);
WScript.Echo(typeof(n));
が動くのに、JScriptのヘルプにはそれらしい記述がなく、
MSDNライブラリもいろいろ検索したんですが、分からなかった。
改めて「型変換」で検索するとJScript.NETの記述が見つかりました。

JScriptのヘルプにちゃんと書いといてほしいもんです。:-<

!!!
それで、気が付いたのですが、
先の問題は、VBScriptのヘルプがおかしいのでは?

VBScriptのヘルプのCStr()の記述、
「指定された式をバリアント型 (内部処理形式が文字列型 (String) の Variant) に変換して返します。」
は本当でしょうか?

VBAのヘルプのように、単に、
「各関数は式を特定のデータ型に変換します。」
なのではありますまいか。

――――――――――――――――――――――――――――――――――――――
Sub InvokeVerb([vVerb])
は、VBAなどの表記では、
Sub InvokeVerb(Optional ByRef vVerb As String)
であって、(?)

文字列を直接指定するとOK。
Call FolderItem.InvokeVerb("削除(&D)")---String型

文字列を変数に代入して変数を指定するとNG。
ただし、参照渡しのとき。
Verb="削除(&D)"
Call FolderItem.InvokeVerb(Verb)---バリアント型 (内部処理形式がString型)
FolderItem.InvokeVerb Verb---バリアント型 (内部処理形式がString型)
ここで、実は、型不一致で、Error型(省略の意味)が渡る。

でも、値渡しならOK。
FolderItem.InvokeVerb(Verb)---String型に暗黙的に型変換

変数をCStrしてもOK。
Call FolderItem.InvokeVerb(CStr(Verb))---String型に明示的に型変換
――――――――――――――――――――――――――――――――――――――

ばんのしゃーによかばんた さん 2005年 01月 28日 19時 59分 05秒

スクリプトからZIPファイルを自由自在に操作するサンプルアプリケーションです。
オープンな課題は、置換と削除のときにプロンプトが出ること。
回避方法は一旦一時フォルダを作って展開して作り直すことですが。。。
"C:\Windows\Temp\a.zip の一時ディレクトリ 1"というのが残ってたりするので、
Windowsは実際そういうことをしているのではないでしょうか。
――――――――――――――――――――――――――――――――――――――
' ZIP.VBS manipulates ZIP file in command line.
' Usage: CScript.exe ZIP.VBS [-d|-e|-v] ZIPfile [files...]

Option Explicit
Dim arg
Dim optind

If WScript.Arguments.Count<1 Then
 WScript.Echo "Usage: CScript.exe ZIP.VBS [-d|-e|-v] ZIPfile [files...]"
 WScript.Quit
End If
arg=WScript.Arguments(optind)
Select Case LCase(arg)
Case "-a","-c"
 optind=optind+1
 Call MakeZIP()
Case "-d"
 optind=optind+1
 Call DeleteZIP()
Case "-e"
 optind=optind+1
 Call ExtractZIP()
Case "-v","-l"
 optind=optind+1
 Call ListZIP()
Case Else
 If optind=WScript.Arguments.Count-1 Then
  Call ListZIP()
 Else
  Call MakeZIP()
 End If
End Select
WScript.Quit

Sub MakeZIP()
Dim fso
Dim wShell
Dim Shell
Dim n
Dim ie
Dim ZIPfile
Dim ZIPdata:ZIPdata="PK" & Chr(5) & Chr(6) & String(18,0)
Dim file
Dim Folder
Dim FolderItem
Dim dFolder

If WScript.Arguments.Count<optind+2 Then
 WScript.Echo "Arguments Missing."
 WScript.Quit
End If

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

Set Shell=CreateObject("Shell.Application")
For n=0 To 9
 For Each ie In Shell.Windows
  If Not ie.Busy Then
   If ie.ReadyState=4 Then
    If InStr(TypeName(ie.Document),"IShellFolderViewDual")=1 Then
     Exit For
    End If
   End If
  End If
 Next
 If Not IsEmpty(ie) Then Exit For
 If n=0 Then CreateObject("WScript.Shell").Run "explorer.exe",0,True
 WScript.Sleep 100
Next
If IsEmpty(ie) Then
 WScript.Echo "Failed"
 WScript.Quit
End If
Set Shell=ie.Document.Application

ZIPfile=fso.GetAbsolutePathName(WScript.Arguments(optind))
If UCase(fso.GetExtensionName(ZIPfile))<>"ZIP" Then
 WScript.Echo "Invalid Extension Name -",fso.GetExtensionName(ZIPfile)
 WScript.Quit
End If
If Not fso.FileExists(ZIPfile) Then
 fso.CreateTextFile(ZIPfile,False).Write ZIPdata
End If
Set dFolder=Shell.NameSpace(ZIPfile)
For optind=optind+1 To WScript.Arguments.Count-1
 file=fso.GetAbsolutePathName(WScript.Arguments(optind))
 Set Folder=Shell.NameSpace(fso.GetParentFolderName(file))
 Set FolderItem=Folder.ParseName(fso.GetFileName(file))
 If FolderItem Is Nothing Then
  WScript.Echo WScript.Arguments(optind),"- Not Found."
  WScript.Quit
 End If
 dFolder.CopyHere FolderItem
Next
End Sub

Sub ListZIP()
Dim fso
Dim Shell
Dim ZIPfile
Dim Folder
Dim FolderItem
Dim k
Dim COL:COL=8
Dim cols
ReDim cols(COL)
Dim rows
Dim j

If WScript.Arguments.Count<optind+1 Then
 WScript.Echo "Arguments Missing."
 WScript.Quit
End If

Set fso=CreateObject("Scripting.FileSystemObject")
Set Shell=CreateObject("Shell.Application")
ZIPfile=fso.GetAbsolutePathName(WScript.Arguments(optind))
If UCase(fso.GetExtensionName(ZIPfile))<>"ZIP" Then
 WScript.Echo "Invalid Extension Name -",fso.GetExtensionName(ZIPfile)
 WScript.Quit
End If
Set Folder=Shell.NameSpace(ZIPfile)
ReDim rows(Folder.Items.Count)
For k=0 To COL
 cols(k)=Folder.GetDetailsOf(,k)
Next
j=0
rows(j)=Join(cols,vbTab)
For Each FolderItem In Folder.Items
 For k=0 To COL
  Cols(k)=Folder.GetDetailsOf(FolderItem,k)
 Next
 j=j+1
 rows(j)=Join(cols,vbTab)
Next
WScript.Echo Join(rows,vbCRLF)
End Sub

Sub DeleteZIP()
Dim fso
Dim Shell
Dim ZIPfile
Dim Folder
Dim FolderItem

If WScript.Arguments.Count<optind+2 Then
 WScript.Echo "Arguments Missing."
 WScript.Quit
End If

Set fso=CreateObject("Scripting.FileSystemObject")
Set Shell=CreateObject("Shell.Application")
ZIPfile=fso.GetAbsolutePathName(WScript.Arguments(optind))
If UCase(fso.GetExtensionName(ZIPfile))<>"ZIP" Then
 WScript.Echo "Invalid Extension Name -",fso.GetExtensionName(ZIPfile)
 WScript.Quit
End If
Set Folder=Shell.NameSpace(ZIPfile)
For optind=optind+1 To WScript.Arguments.Count-1
 Set FolderItem=Folder.ParseName(WScript.Arguments(optind))
 If FolderItem Is Nothing Then
  WScript.Echo WScript.Arguments(optind),"- Not Found."
  WScript.Quit
 End If
' FolderItem.InvokeVerb("delete")
 FolderItem.InvokeVerb("削除(&D)")
Next
End Sub

Sub ExtractZIP()
Dim fso
Dim Shell
Dim ZIPfile
Dim Folder
Dim FolderItem
Dim dFolder

If WScript.Arguments.Count<optind+1 Then
 WScript.Echo "Arguments Missing."
 WScript.Quit
End If

Set fso=CreateObject("Scripting.FileSystemObject")
Set Shell=CreateObject("Shell.Application")
ZIPfile=fso.GetAbsolutePathName(WScript.Arguments(optind))
If UCase(fso.GetExtensionName(ZIPfile))<>"ZIP" Then
 WScript.Echo "Invalid Extension Name -",fso.GetExtensionName(ZIPfile)
 WScript.Quit
End If
Set Folder=Shell.NameSpace(ZIPfile)
Set dFolder=Shell.NameSpace(fso.GetAbsolutePathName(""))
If WScript.Arguments.Count<optind+2 Then
 dFolder.CopyHere Folder.Items
Else
 For optind=optind+1 To WScript.Arguments.Count-1
  Set FolderItem=Folder.ParseName(WScript.Arguments(optind))
  If FolderItem Is Nothing Then
   WScript.Echo WScript.Arguments(optind),"- Not Found."
   WScript.Quit
  End If
  dFolder.CopyHere FolderItem
 Next
End If
End Sub


ばんのしゃーによかばんた さん 2005年 01月 28日 19時 58分 32秒

MsgBoxの小技。

[甲]
Focusは取れなくても、一応一時的に最前面には出る。

CreateObject("WScript.Shell").AppActivate "メモ帳"
MsgBox "prompt",vbMsgBoxSetForeground
'65536

[乙]
右揃えにする。

MsgBox "prompt" & vbCrLf & "longprompt",vbMsgBoxRight
'524288

[丙]
Xボタンを左に置く。

MsgBox "prompt",vbMsgBoxRTLReading
'1048576


まろん さん 2005年 01月 28日 19時 58分 05秒

はじめまして。
今WSHでファイルをアップロードする方法に悩んでおります。

以前、魔界の仮面弁士さんが、WSHでIEを操作し、ファイルのダウンロードの
制御方法を紹介されていましたが、逆にファイルのアップロードも同じような方法
でできるのでしょうか?
【↓以前紹介されていたソース】
Set xmlHttpRequest = CreateObject("MSXML2.XMLHTTP.4.0")
xmlHttpRequest.Open "POST", "http://www.includez.com/wsh/downloader.php", False
xmlHttpRequest.setRequestHeader "Referer", "http://www.includez.com/wsh/form.htm"
xmlHttpRequest.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
xmlHttpRequest.send "Submit=%91%97%90M"

これを利用しようと頑張っているのですが、うまくいきません。
xmlHttpRequestオブジェクトはできているようです。ただその後、
"Referer"や"Content-Type"、"Submit=%91%97%90M"
に何を代入すればよいのかわかりません。

ちなみに、下記のようなフォームがありまして、
VBSを使ってファイル名を設定して、アップロードボタンを押したいのです。
しかし、input="file"の場合は、アップロードファイルをボックスに入力する
ことができないようなので困っております。

<FORM NAME="FB200" METHOD="post" ENCTYPE="multipart/form-data">
<A HREF="javascript:fncInputCehck();"
onMouseOver="fncChangeImage('Upload','web_icon/button/Upload_Sel.gif')" onMouseOut ="fncChangeImage('Upload','web_icon/button/Upload.gif')" ><IMG SRC=web_icon/button/Upload.gif NAME=Upload BORDER=0 ALT="アップロード"></a>
<INPUT TYPE="file" NAME="UpFile0" MAXLENGTH=2400 SIZE="40" accept="text/comma-separated-values">
</FORM>

おわかりになりましたら、宜しくお願い致します。

ばんのしゃーによかばんた さん 2005年 01月 28日 19時 58分 00秒

>初心者 さん 2005年 01月 27日 01時 37分 46秒
>何かコマンドを実行中に常に最前面にポップアップで「実行中」等のメッセージを表示させておきたいのですが、この際、ポップアップを閉じるボタン等は表示させたくありません。ポップアップは、コマンド終了時に閉じるようにしたいのですが可能でしょうか?

「常に最前面」の件は過去ログに、
>管理人むたぐち さん 2001年 11月 18日 21時 10分 01秒
>To: 土屋 さん
>> メモ帳などの任意のプログラムを常に手前にして起動する技はWSHにはないでしょう。
>> (これは、プログラム側で実装しなければならないことなのでは、、)
>一応、SetWindowPosというAPI関数を指定のウィンドウハンドルを持ったウィンドウに
>送ることで、外部から制御できます。
>WSH+DynaCallでやるなら、以下のようになります。
とありますので、こちらを参考になさってはいかがでしょう。

ところで、この記事の中で、
>'電卓を「常に手前に表示」
>UserWrap2.SetWindowPos UserWrap1.FindWindowA (vbNullString, "電卓"),HWND_TOPMOST,0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE
>ところで、
>Title="電卓"
>UserWrap2.SetWindowPos UserWrap1.FindWindowA (vbNullString, Title),HWND_TOPMOST,0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE
>とやると動作しないのは何故でしょう?
とありますが、牟田口さんは、もう納得的に解決されました?

魔界の仮面弁士 さん 2005年 01月 28日 18時 30分 31秒

》 ばんのしゃーによかばんた さん 2005年 01月 28日 16時 48分 58秒
> JScriptのヘルプでは、String()は、
> newString = new String(["stringLiteral"])
> のような使い方しか出て来ません。

そういえば、私もこのあたりが曖昧です。調べてみました。


exealさんのサイトによると……JScriptにおいて、プリミティブな文字列と、
組み込みのStringオブジェクトは別物なのだそうです。
http://www.interq.or.jp/student/exeal/dss/ref/jscript/basic.html#p_variable
http://www.interq.or.jp/student/exeal/dss/ref/jscript/object/string.html

WScript.Echo(typeof("aaa"));       //"string"
WScript.Echo(typeof(String("aaa")));   //"string"
WScript.Echo(typeof(new String("aaa"))); //"object"

1番目は、プリミティブ文字列ですね。

2番目の String("aaa") 構文は、型変換。
C#なら (String)"aaa" と書くところですが。

3番目が、Stringオブジェクトの作成。
括弧内は、コンストラクタ引数ですね。


ここまで確認したところで、改めて JScript のヘルプを見ると、
『String オブジェクトは、文字列リテラルを使用して自動的に作成できます。』
とあり、こうして作成されるのが「"プリミティブ" 文字列」だと記されています。

つまり、1番目と2番目は同じ種類の物、と言えますね。


では、3番目の構文は? とJScriptのヘルプを見ると、プリミティブ文字列は、
new 演算子で作成された String オブジェクトとは使い方が異なると書かれています。

『プリミティブ文字列では、プロパティの読み取りやメソッドの呼び出しは
 実行できますが、新しいプロパティの作成やメソッドの追加は実行できません。』

試してみると、なるほど動きが違いますね。

var S1 = new String("bbb");
S1.newProp = 123;
WScript.Echo(S1.newProp);  // =123

var S2 = "aaa";
S2.newProp = 123;
WScript.Echo(S2.newProp);  // ≠123


しかし……JScript.NET だと、これに加えて System.String などが
絡んでくるので、さらにややこしい事に。

typeof だと調査しきれないので、.GetType() を使います。

import System;

// 以下3つは、『System.String』。
Console.WriteLine( "aaa".GetType().FullName );
Console.WriteLine( String("aaa").GetType().FullName );
Console.WriteLine( System.String("aaa").GetType().FullName );

// これは、『Microsoft.JScript.StringObject』。
Console.WriteLine( (new String("aaa")).GetType().FullName );


『プリミティブ文字列 = System.String ≠ Stringオブジェクト』ですかね。

かおり さん 2005年 01月 28日 18時 00分 11秒

ばんのしゃーによかばんた さん 2005年 01月 28日 16時 48分 25秒

ばんのしゃーによかばんた様

勉強になりました。
大変ご丁寧なご教授ありがとうございました。

間違って二重書き込みなってしまい、皆様にはご迷惑をお掛けいたします。
申し訳ございません。

かおり さん 2005年 01月 28日 17時 58分 32秒

>ばんのしゃーによかばんた さん 2005年 01月 28日 16時 49分 34秒

勉強になりました。
大変ご丁寧なご教授ありがとうございました。

ばんのしゃーによかばんた さん 2005年 01月 28日 16時 49分 34秒

CABファイル自由自在。:-)
スクリプトでCABファイルを扱うサンプルアプリケーション。
CABファイルを作成/解凍/リストするコマンド。

実は、この中で、
cab.CreateCab CStr(CABfile),False,False,False
がトラブったんですね。:-p
――――――――――――――――――――――――――――――――――――――
' CAB.VBS manipulates CAB file in command line.
' Usage: CScript.exe CAB.VBS [-c|-e|-v] CABfile [files...]

Option Explicit
Dim arg
Dim optind

If WScript.Arguments.Count<1 Then
 WScript.Echo "Usage: CScript.exe CAB.VBS [-c|-e|-v] CABfile [files...]"
 WScript.Quit
End If
arg=WScript.Arguments(optind)
Select Case LCase(arg)
Case "-c"
 optind=optind+1
 Call CreateCAB()
Case "-e"
 optind=optind+1
 Call ExtractCAB()
Case "-v","-l"
 optind=optind+1
 Call ListCAB()
Case Else
 Call ListCAB()
End Select
WScript.Quit

Sub CreateCAB()
Dim fso
Dim cab
Dim CABfile
Dim File

If WScript.Arguments.Count<optind+2 Then
 WScript.Echo "Arguments Missing."
 WScript.Quit
End If

Set fso=CreateObject("Scripting.FileSystemObject")
Set cab=CreateObject("MakeCab.MakeCab.1")
CABfile=fso.GetAbsolutePathName(WScript.Arguments(optind))
If UCase(fso.GetExtensionName(CABfile))<>"CAB" Then
 WScript.Echo "Invalid Extension Name -",fso.GetExtensionName(CABfile)
 WScript.Quit
End If
cab.CreateCab CStr(CABfile),False,False,False
For optind=optind+1 To WScript.Arguments.Count-1
 Set File=fso.GetFile(WScript.Arguments(optind))
 cab.AddFile File.Path,File.Name
Next
cab.CloseCab
End Sub

Sub ListCAB()
Dim fso
Dim Shell
Dim CABfile
Dim Folder
Dim FolderItem
Dim k
Dim COL:COL=4
Dim cols
ReDim cols(COL)
Dim rows
Dim j

If WScript.Arguments.Count<optind+1 Then
 WScript.Echo "Arguments Missing."
 WScript.Quit
End If

Set fso=CreateObject("Scripting.FileSystemObject")
Set Shell=CreateObject("Shell.Application")
CABfile=fso.GetAbsolutePathName(WScript.Arguments(optind))
If UCase(fso.GetExtensionName(CABfile))<>"CAB" Then
 WScript.Echo "Invalid Extension Name -",fso.GetExtensionName(CABfile)
 WScript.Quit
End If
Set Folder=Shell.NameSpace(CABfile)
ReDim rows(Folder.Items.Count)
For k=0 To COL
 cols(k)=Folder.GetDetailsOf(,k)
Next
j=0
rows(j)=Join(cols,vbTab)
For Each FolderItem In Folder.Items
 For k=0 To COL
  cols(k)=Folder.GetDetailsOf(FolderItem,k)
 Next
 j=j+1
 rows(j)=Join(cols,vbTab)
Next
WScript.Echo Join(rows,vbCRLF)
End Sub

Sub ExtractCAB()
Dim fso
Dim Shell
Dim CABfile
Dim Folder
Dim FolderItem
Dim dFolder

If WScript.Arguments.Count<optind+1 Then
 WScript.Echo "Arguments Missing."
 WScript.Quit
End If

Set fso=CreateObject("Scripting.FileSystemObject")
Set Shell=CreateObject("Shell.Application")
CABfile=fso.GetAbsolutePathName(WScript.Arguments(optind))
If UCase(fso.GetExtensionName(CABfile))<>"CAB" Then
 WScript.Echo "Invalid Extension Name -",fso.GetExtensionName(CABfile)
 WScript.Quit
End If
Set Folder=Shell.NameSpace(CABfile)
Set dFolder=Shell.NameSpace(fso.GetAbsolutePathName(""))
If WScript.Arguments.Count<optind+2 Then
 dFolder.CopyHere Folder.Items
Else
 For optind=optind+1 To WScript.Arguments.Count-1
  Set FolderItem=Folder.ParseName(WScript.Arguments(optind))
  If FolderItem Is Nothing Then
   WScript.Echo WScript.Arguments(optind),"- Not Found."
   WScript.Quit
  End If
  dFolder.CopyHere FolderItem
 Next
End If
End Sub


ばんのしゃーによかばんた さん 2005年 01月 28日 16時 48分 58秒

JScriptのヘルプでは、String()は、
newString = new String(["stringLiteral"])
のような使い方しか出て来ません。

一方で、以下はJScript.NETですが、JScriptも同様に、
>ばんのしゃーによかばんた さん 2004年 11月 12日 17時 03分 03秒
>var iData : IDataObject = Clipboard.GetDataObject();
>if(iData.GetDataPresent(DataFormats.Text)) {
>Console.WriteLine(String(iData.GetData(DataFormats.Text)));
>}
のような使い方もあるようです。
これは、どういう意味なんでしょう?
String()しないとエラーになるので、よく分からずに使ってるんです。

一般に、Stringに限らず、Number、RegExp、function...など、なんでも、
zzz=new xxx(yyy)
zzz=xxx(yyy)
という書き方が出来て、xxxオブジェクトとxxx型になる、
ということなんでしょうか?


ばんのしゃーによかばんた さん 2005年 01月 28日 16時 48分 25秒

>かおり さん 2005年 01月 27日 11時 06分 44秒
>エクスプローラなどでファイルをカレントフォルダからのドラッグアンドドロップで移動やコピーをできなくする方法はありますか?

ShellFolderViewのBeginDragが使えそうです。
参考。
Class ShellFolderView  Shell32 のメンバ  Shell Folder View Object
Event BeginDrag()  user started to drag an item (return false to cancel).
Event DefaultVerbInvoked()  the default verb (double click) was invoked on an items in the view (return false to cancel).
Event EnumDone()  The folder has finished enumerating (flashlight is gone).
Event SelectionChanged()  The Selection in the view changed.
Event VerbInvoked()
  A verb was invoked on an items in the view (return false to cancel).

サンプル。そのため冗長です。
Set fv=CreateObject("Shell.FolderView.1")
Call WScript.ConnectObject(fv,"FV_")
Set ie=WScript.CreateObject("InternetExplorer.Application","IE_")
ie.Visible=True
ie.Navigate "c:\vbs"
Do While ie.Busy Or ie.ReadyState<>4
 WScript.Sleep 100
Loop
Do While TypeName(ie)="IWebBrowser2"
 WScript.Sleep 100
Loop
WScript.Quit

Sub IE_DocumentComplete(pdisp,url)
 WScript.Echo "DocumentComplete",url
 Call fv.SetFolderView(ie.document)
End Sub

Function FV_BeginDrag()
 WScript.Echo "BeginDrag"
 FV_BeginDrag=False
End Function

Sub FV_SelectionChanged()
 WScript.Echo "SelectionChanged",ie.document.focuseditem
End Sub

Sub FV_EnumDone()
 WScript.Echo "EnumDone"
End Sub

Sub IE_OnQuit()
 WScript.Echo "OnQuit"
End Sub



魔界の仮面弁士 さん 2005年 01月 28日 10時 59分 35秒

》ばんのしゃーによかばんた さん 2005年 01月 27日 19時 22分 35秒
> 魔界の仮面弁士 さん、お教えください。
えー、指名されちゃいましたが、COM も Scripting も専門外です。
VB なら得意なんですが……。

> でも、これらの違いはどうして起きるんでしょう?
> どういう仕組みなんでしょう?
> 「String型」と「Variant型(内部形式がString型)」の違いとかでしょうか?
InvokeVerb メソッドの内部実装を調べないとわかりませんが、
状況からして「値渡し」でなければ駄目みたいですね。

> こういう振る舞いがあることを知らないと悩みますよねー。:-<
型によって影響を受けるものもありますね。

InternetExplorer.Application.ExceWB()とかは、
「内部形式 Integer の Variant型」と、
「内部形式 Long の Variant型」を区別するので、時々悩みます。

管理人むたぐち さん 2005年 01月 27日 23時 41分 54秒
URL:http://www.roy.hi-ho.ne.jp/mutaguchi/wsh/src/mp3_autofill.zip

「MP3プレイヤーにmp3ファイルをランダムにコピー」するスクリプトを公開しました。

これは、USB Mass Storage Classに対応するMP3プレイヤーに、HDDにあるmp3ファイルをランダムにコピーするスクリプトです。
要するに、iPod Shuffleの「オートフィル機能」もどきです。
容量が少なめのフラッシュメモリタイプのMP3プレイヤーをお使いの方にお勧めです。
このスクリプト、私も愛用しています。

ばんのしゃーによかばんた さん 2005年 01月 27日 19時 22分 35秒

魔界の仮面弁士 さん、お教えください。

文字列を直接指定するとOK。
Call FolderItem.InvokeVerb("削除(&D)")

文字列を変数に代入して変数を指定するとNG。
ただし、参照渡しのとき。
Verb="削除(&D)"
Call FolderItem.InvokeVerb(Verb)
FolderItem.InvokeVerb Verb

でも、値渡しならOK。
FolderItem.InvokeVerb(Verb)

変数をCStrしてもOK。
Call FolderItem.InvokeVerb(CStr(Verb))

こういう振る舞いがあることを知らないと悩みますよねー。:-<

でも、これらの違いはどうして起きるんでしょう?
どういう仕組みなんでしょう?
「String型」と「Variant型(内部形式がString型)」の違いとかでしょうか?


ばんのしゃーによかばんた さん 2005年 01月 27日 17時 46分 23秒

>ばんのしゃーによかばんた さん 2005年 01月 26日 18時 31分 47秒
>Folder.CopyHere sFile,FOF_RENAMEONCOLLISION

これって、GUIで出来ると便利なんですが、どうやるんでしょう?
ExplorerのGUI操作では出来ないんでしょうか?

一応、「お気に入り」に下記CopyHere.VBSを入れて、
コピー元ファイル群をコピーして、コピー先フォルダで「お気に入り」の
CopyHere.VBSに貼り付けると、出来ました。

CopyHere.VBS
――――――――――――――――――――――――――――――――――――――
Const FOF_RENAMEONCOLLISION = &H8
Set Shell=CreateObject("Shell.Application")
Set ie=Shell.Windows.Item
Set Folder=ie.Document.Folder
For Each file In WScript.Arguments
 Folder.CopyHere file,FOF_RENAMEONCOLLISION
Next

BrowseForFolderを付ければ、CopyToAnyFolder....VBSも出来ます。
SendToに入れて使います。
――――――――――――――――――――――――――――――――――――――
Const BIF_RETURNONLYFSDIRS = &H1
Const FOF_RENAMEONCOLLISION = &H8
Set Shell=CreateObject("Shell.Application")
Set Folder=Shell.BrowseForFolder(0,"Select Folder",BIF_RETURNONLYFSDIRS)
If Folder Is Nothing Then WScript.Quit
For Each file In WScript.Arguments
 Folder.CopyHere file,FOF_RENAMEONCOLLISION
Next


かおり さん 2005年 01月 27日 11時 06分 44秒

試したいことなんですが、エクスプローラなどでファイルをカレントフォルダからのドラッグアンドドロップで移動やコピーをできなくする方法はありますか?
南坂 静一 氏製作のフリーソフトで「SouthernCross FileLock Wizard」というものがあり似たものがあるのですが、API関数なのかレジストリなのか、過去ログや他のページを見てもわかりませんでした。ご存知の方がいらっしゃいましたら、ご教授頂ければ幸いです。「RegisterAsDropTarget」もFalseにしたりしていろいろ試して見ましたがダメでした。よろしくお願いいたします。

初心者 さん 2005年 01月 27日 01時 37分 46秒

はじめまして。質問ですが、何かコマンドを実行中に常に最前面にポップアップで「実行中」等のメッセージを表示させておきたいのですが、この際、ポップアップを閉じるボタン等は表示させたくありません。ポップアップは、コマンド終了時に閉じるようにしたいのですが可能でしょうか?
どなたかご存知でしたらご教授お願い致します。


ばんのしゃーによかばんた さん 2005年 01月 26日 18時 31分 47秒

>りん さん 2005年 01月 25日 09時 06分 07秒
>WSHを用いて自動的に作成されるバッチファイルのバックアップ(現在は上書きの状態)
>を取りたいのです。(毎日そのファイルをコピーしてフォルダに落とす方法)
>何か参考になるソースがございましたら教えていただけたらありがたいです

もうひとつ追加。

丁案
Const FOF_RENAMEONCOLLISION = &H8
dFolder="c:\vbs\shell\b\"
sFile="c:\vbs\shell\a\c"
Set Shell=CreateObject("Shell.Application")
Set Folder=Shell.NameSpace(dFolder)
Folder.CopyHere sFile,FOF_RENAMEONCOLLISION

※なぜか、CopyHereの第2引数は第1引数にwildcard文字列を指定すると効きません。
CopyHereの第2引数は第1引数にwildcardでない文字列、FolderItem、FolderItemsを
指定した場合にだけ効くようです。

※XP SP2ではFileSystemへのCopyHereは同期のようです。
2000までは同期。XPで非同期になったように思うのですが、SP2で戻ったのでしょうか。
wildcard文字列もXPで一時使えなくなったみたいだし、よく変わりますね。

ばんのしゃーによかばんた さん 2005年 01月 25日 19時 27分 55秒

WSHとIEの併せ技について紆余曲折。

ie.Navigate "about:blank"はインターネットゾーンになるので、
ie.Navigate "res://mshtml.dll/blank.htm"を使って、マイコンピュータゾーンにして、
後からスクリプトやオブジェクトを組み込むことが出来ましたが、
XP SP2から、これもインターネットゾーンになって、使えなくなりました。
マイコンピュータゾーンにする方法は、ローカルにHTMファイルを作る?

ただ、そのようにしても、以前は、後からスクリプトやオブジェクトを組み込む段階で
ダイアログが表示されて、答えると次に進む、でしたが、XP SP2では、
ダイアログも表示されず、スクリプトが無効になって、オブジェクトがエラーになります。

なので、今度は、ローカルのHTMファイルにスクリプトやオブジェクトを先に組み込んで、
ie.Navigate HTMファイル
Do While ie.Busy Or ie.ReadyState<>4
WScript.Sleep 100
Loop
Set OBJ=ie.Document.ID.object
としても、まだ、XP SP2では、ダイアログも表示されず、スクリプトが無効になって、
オブジェクトがエラーになります。

そこで、
Loop
ie.Refresh
Set OBJ=ie.Document.ID.object
とすると、漸くダイアログが表示されますが、それを有効にする前につっ走って、
また、オブジェクトがエラーになります。

有効になるのを待ち合わせる方法はエラーを拾ってリトライループ?
Do
 WScript.Sleep 1000
 On Error Resume Next
 Set OBJ=ie.Document.ID.object
 On Erro GoTo 0
Loop Until TypeName(OBJ)="xxx"

どうも、WSHとIEの併せ技は、もう使えそうにないですね。

ばんのしゃーによかばんた さん 2005年 01月 25日 19時 27分 19秒

>りん さん 2005年 01月 25日 09時 06分 07秒
>WSHを用いて自動的に作成されるバッチファイルのバックアップ(現在は上書きの状態)
>を取りたいのです。(毎日そのファイルをコピーしてフォルダに落とす方法)
>何か参考になるソースがございましたら教えていただけたらありがたいです。

――――――――――――――――――――――――――――――――――――――
甲案
以下の過去ログを参照。
>ばんのしゃーによかばんた さん 2004年 10月 18日 15時 41分 20秒
>同名ファイルがあっても、エラーやプロンプトや上書きなしに移動する。
>サンプルです。
>同名ファイルがあると、ベース名に2〜999のサフィックスを付けて移動します。
>コピーも同様です。
――――――――――――――――――――――――――――――――――――――
乙案
ファイル更新日付+nn(nn=00〜99)をベース名にします。
リネームだけですので、別途、コピー/移動してください。
システム日付やファイル名の前に日付を付加したりしたいときはコメントアウトを参考。
' Fdate.VBS renames file to yymmddnn.ext with file last modified date
' Usage: CScript Fdate.VBS files...
Option Explicit
Dim fso
Dim arg
Dim fa
Dim ext
Dim fdate
Dim yymmdd
Dim bname
Dim fname
Dim n

Set fso=CreateObject("Scripting.FileSystemObject")
For Each arg In WScript.Arguments
 Set fa=fso.GetFile(arg)
 bname=fa.Name
 ext=UCase(fso.GetExtensionName(fa.ShortName))
 fdate=fa.DateLastModified
' fdate=fa.DateCreated
' fdate=fa.DateLastAccessed
' fdate=now
 yymmdd=Mid(CStr(Year(fdate)*10000+Month(fdate)*100+Day(fdate)),3)
 For n=0 To 99
  fname= yymmdd & Right("0" & n,2) & "." & ext
'  fname= yymmdd & Right("0" & n,2) & " " & bname
  Call Rename(fa,fname)
  If Err=0 Then
   WScript.Echo bname,"->",fa.Name
   Exit For
  ElseIf Err<>58 Then
   WScript.Echo Err.Number,Err.Description
   Exit For
  ElseIf n=99 Then
   WScript.Echo "nn Used Up."
   Exit For
  End If
 Next
Next
WScript.Quit

Sub Rename(fa,name)
 On Error Resume Next
 fa.Name=name
End Sub
――――――――――――――――――――――――――――――――――――――
上の乙案は、以下の記事に対する回答にもなりますね。
>nono さん 2003年 08月 06日 15時 58分 23秒
>毎日ダウンロードするファイルが同じ名前で取り込みますので、
>名前が一緒だと上書きしてしまうのです。
>毎日、AAA.txtというファイルを取り込みます。
>そのファイルを年月日時分秒.txtのようにファイル名変更できないでしょうか?
>システム日付から自動でファイル名の変更ができるようにしたいのです。

ここで、
>プログラムのスキルが全くと言っていいほど無いので、なんとかMS−DOSで
>作ろうかと試みたのですが、日付を持ってきてファイル名にすることは不可能でした。

9xではそうですが、2000やXPならバッチファイルだけでも出来ます。

丙案
ファイル更新日付+nn.ext
@Rem Usage: Fdate file
@Echo Off
If Exist %1 GoTo Exist
 Echo %1 Not Found.
 GoTo End
:Exist
SetLocal
Set d=%~t1
Set yymmdd=%d:~0,2%%d:~3,2%%d:~6,2%
Set n=-1
:Retry
 Set /A n=%n%+1
 If Not %n%==100 GoTo Rename
  Echo NN Used Up.
  GoTo End
 :Rename
 Set nn=0%n%
 Set nn=%nn:~-2%
 Rename %1 %yymmdd%%nn%%~x1 2>Nul
If ErrorLevel 1 GoTo Retry
Echo %1 -^> %yymmdd%%nn%%~x1
:End

システム日付+nn.ext
@Rem Usage: Cdate file
@Echo Off
If Exist %1 GoTo Exist
 Echo %1 Not Found.
 GoTo End
:Exist
SetLocal
Set yymmdd=%date:~-8,2%%date:~-5,2%%date:~-2%
Set n=-1
:Retry
 Set /A n=%n%+1
 If Not %n%==100 GoTo Rename
  Echo NN Used Up.
  GoTo End
 :Rename
 Set nn=0%n%
 Set nn=%nn:~-2%
 Rename %1 %yymmdd%%nn%%~x1 2>Nul
If ErrorLevel 1 GoTo Retry
Echo %1 -^> %yymmdd%%nn%%~x1
:End

みた さん 2005年 01月 25日 18時 00分 39秒

どなたか教えてください?
Excelでreplace関数を活用しているのですが、置き換えはできますが、データを更新すると置き換えた値が消えてしまいます。恒常的に置き換える方法はありますか?

むちゃ さん 2005年 01月 25日 09時 31分 13秒

To: 管理人むたぐち さん

> To: むちゃ さん
>
> http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/methods/createpopup.asp
>
> Parameters
> vArgs Optional. This argument is reserved.
>
> とあるので、現在のところは何を指定しても無視されるはずです。

ありがとうございました。m(_ _)m
やっぱ英語は苦手です。(T-T)

りん さん 2005年 01月 25日 09時 06分 07秒

はじめまして、りんと申します*
わかりやすいページ大変助かっています。ただちょっとお願いなのですが、
WSHを用いて自動的に作成されるバッチファイルのバックアップ(現在は上書きの状態)を取りたいのです。(毎日そのファイルをコピーしてフォルダに落とす方法)
何か参考になるソースがございましたら教えていただけたらありがたいです。
ちなみに、スケジューラは入っております。
よろしくお願いいたします。

管理人むたぐち さん 2005年 01月 25日 01時 34分 46秒
URL:http://www.microsoft.com/japan/msdn/library/ja/jpdx8_c/ds/ref/iface/mswebdvd.asp

↑MSWebDVD.MSWebDVD.1のリファレンスです。

MSWebDVD.MSWebDVD.1、WinXP Pro SP2で動きました。
Microsoft DirectX 8.0のコンポーネントみたいですね。

管理人むたぐち さん 2005年 01月 24日 19時 57分 00秒

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

MSWebDVD.MSWebDVD.1ですが、Win2000SP4には入っていないようです。
WinXPは後で確認してみます。

To: むちゃ さん

http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/methods/createpopup.asp

Parameters
vArgs Optional. This argument is reserved.

とあるので、現在のところは何を指定しても無視されるはずです。

# createPopupメソッドを使うとHTAでポップアップメニューが作れますね。
# IE5.5から使用できるようになったはずです。
# ただ、フィッシング詐欺のサイトで悪用されたため、
# WinXP SP2からはウィンドウ領域外にpopupを表示できなくなったみたいです。
# それじゃdivとあんまし変わらないですねぇ…

むちゃ さん 2005年 01月 24日 16時 24分 23秒

只今、 createPopup() について調べているのですが

window.createPopup([vArgs])

の [vArgs] には何が指定できるのか知っている方いらっしゃいますか??
検索して色々しらべたのですが、何も見つかりませんでした。(T-T;)

ばんのしゃーによかばんた さん 2005年 01月 23日 18時 51分 46秒

CreateObject("MSWebDVD.MSWebDVD.1").Mute=True
は、如何でしょう。試してみたら使えそうです。
.Volume=0(max)から-10000(min)で調節もできるようです。
%SystemRoot%System32\MSWebDVD,DLLがあれば使えます。
詳細はMSDNライブラリを参照。

管理人むたぐち さん 2005年 01月 21日 23時 06分 04秒

To: あにょん さん

Command-line Volume Controller (CVC)(Windows95/98/Me/画像&サウンド)
http://www.vector.co.jp/soft/win95/art/se100704.html

こういうソフトを利用してみてはいかがでしょうか。
WSHからもWshShell.Runなどで呼び出せると思います。

あにょん さん 2005年 01月 20日 20時 06分 50秒

こんばんわ。
音量を下げるコマンドなんてありますか?
ミュートでも構いません。

管理人むたぐち さん 2005年 01月 19日 22時 58分 05秒

Hi-HOに問い合わせたところ、Hi-HOが配布しているこの掲示板の
スクリプトは自由に改変して良い、ということでしたので、
少し改良してみることにします。

さしあたっては、
・タブ,半角スペース→&nbsp;の変換

を実装してみました。

(例)
If aaa = bbb Then
     ccc
End If

既存のログとの整合性、AKiOSさんのHTAの動作保証をすると
あまり極端な改造はできないのですが、まあこれくらいなら問題ないでしょう…。

・http://www.roy.hi-ho.ne.jp/mutaguchi/wsh/ のようにhttp://で始まる文字列を自動リンク
も実装しようとしたんですが、AKiOSさんのHTAでエラーになってしまうので、
何か対策を考えます。

ほんとうに今更ですが、そういうことでよろしくお願いします。

ばんのしゃーによかばんた さん 2005年 01月 19日 17時 42分 07秒

*.CLPファイルは、98の頃、CLIPBRD.EXEに関連付けても開いてくれなかった。
2000/XPでは、開いてくれるようになった。と思ったら、
XP SP2では、また、開いてくれなくなった。ですよね?
CLIPBRD.EXE hoge.clpとすると、ファイルの存在まで確認して、削除するか、
聞いてくるので、実装されてたのをわざわざ潰したみたい。なんで?

*.CLPファイルをCLIPBRD.EXEに関連付けて開く方法はないもんでしょうか?
下記のVBSを噛ませば、一応は可能ですが。どうもねー。
――――――――――――――――――――――――――――――――――――――
Option Explicit

Const OLECMDID_COPY = 12
Const OLECMDID_SELECTALL = 17
Const OLECMDEXECOPT_DODEFAULT = 0

Dim arg
Dim wShell
Dim ie

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.body.innerText=WScript.Arguments(0)
Call ie.ExecWB(OLECMDID_SELECTALL,OLECMDEXECOPT_DODEFAULT)
Call Ie.ExecWB(OLECMDID_COPY,OLECMDEXECOPT_DODEFAULT)
ie.Quit

Set wShell=CreateObject("WScript.Shell")
wShell.Run "CLIPBRD.EXE"
Do While Not wShell.AppActivate("クリップブック - [クリップボード]")
Wscript.Sleep 100
Loop
wShell.SendKeys "%fo",True
wShell.SendKeys "^v{Enter}",True
Do While Not wShell.AppActivate("クリップボードの内容を削除")
Wscript.Sleep 100
Loop
wShell.SendKeys "y",True

管理人むたぐち さん 2005年 01月 18日 23時 43分 19秒

TechNet: スクリプト センター
http://www.microsoft.com/japan/technet/scriptcenter/default.mspx

おなじみスクリプトセンターのサイトがリニューアルされています。
TechNet コラム : Tales From the Scriptの未翻訳だったドキュメントの日本語訳など、
英語(本家)サイトにしかなかった文書がいくつか増えました。

そして、昨日1/17〜/28にかけて、「Script Week II」と銘打って、スクリプト関係の
ドキュメントを一気に300ほど増やす予定みたいです。
http://www.microsoft.com/japan/technet/scriptcenter/whatsnew.mspx

内容じたいは、去年の夏〜冬に、英語サイトの方で連載されていた、「Hey, Scripting Guy!」
の日本語訳です。これは、Q&A形式で、スクリプトに関するワンポイントアドバイスを紹介する
コンテンツです。

なお、「Script Week II」は、英語サイトでは、スクリプトに関する講習のWebCastがされるようです。
こちらは、1/24〜1/28の実施となります。
http://www.microsoft.com/technet/scriptcenter/webcasts/default.mspx
講習を受けると、特製Scripting Guys’Tシャツが貰えるそうですよ。

一応、日本時間での日程表を載せておきます。

2005/01/25
2:30 AM - 4:00 AM TechNet Webcast: Hey, What About ADSI? (Level 200)

2005/01/26
2:30 AM - 4:00 AM TechNet Webcast: The Return of WMI (Level 200)

2005/01/27
7:00 AM - 8:30 AM MSDN Webcast: If You Want Something Done Right, Then Let Microsoft Office Do It For You (Level 300)
Pacific Time
2:30 AM - 4:00 AM TechNet Webcast: An Ounce of Prevention ? An Introduction to WMI Events (Level 200)

2005/01/28
2:30 AM - 4:00 AM TechNet Webcast: Things the Scripting Guys Never Told You (Level 200)
6:00 AM - 7:00 AM MSDN Webcast: Running Scripts Securely While Handling Passwords and Security Contexts Properly (Level 300)
6:00 AM - 7:00 AM MSDN Webcast: Scripting .NET Components (Level 200)

2005/01/29
2:30 AM - 4:00 AM TechNet Webcast: Trading Scripts (Level 200)
4:00 AM - 5:00 AM MSDN Webcast: Consuming Web Services With Style Using Script (Level 300)
5:00 AM - 6:00 AM MSDN Webcast: Up and ADAM: Using Scripts to Manage Active Directory Application Mode (Level 300)

ちゃっぴ さん 2005年 01月 18日 20時 33分 40秒

> リモートマシンがWindows Server 2003ではエラーが出ます

そのServerの環境設定を見直すとか・・・
Port Filtering されてるとか・・・

> WMI関連は、Windows 2000 Server/Proでは動作しないんですよね?

動きます。ただ、Class や Method, Propertyによっては、
対応しているものと対応していないものがあります。

詳しくは、MSDNで調べてください。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/win32_classes.asp

キチンハイター さん 2005年 01月 18日 11時 45分 22秒

はじめまして。

WMI+VBを利用してリモートマシンを遠隔で制御したのですが、
リモートマシンがWindows XP Proでは可能なスクリプトが、
リモートマシンがWindows Server 2003ではエラーが出ます。
(RPCサーバが利用できません。)

遠隔操作の際に、以下のスクリプトを使用してます。
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objSWbemServices = objSWbemLocator.ConnectServer (リモートマシン名, root\cimv2, リモートadminユーザ, パスワード)
以後制御のスクリプト。

リモートマシンはWindows Management Instrumentation、
Remote Procedure Call (RPC)のサービスは、自動:開始状態です。
何方か、原因もしくは回避策をご存知ないでしょうか。
また、WMI関連は、Windows 2000 Server/Proでは動作しないんですよね?

おけら さん 2005年 01月 15日 12時 56分 48秒

魔界の仮面弁士 様
ご指摘の通りでうまく動作しました。
大変勉強になりました。
丁寧なご教授ありがとうございました。

魔界の仮面弁士 さん 2005年 01月 14日 22時 18分 31秒

》おけら さん 2005年 01月 14日 21時 40分 30秒
VBScriptでは、「:=」を使った指定(名前付き引数)は使えません。

この場合、
.Sort Key1:=〜, Order1:=xlAscending
の部分は、
.Sort 〜, xlAscending
としてください。

それから、『xlAscending』はExcelの定数ですので、
VBScriptでは未定義になっています。事前に
Const xlAscending = 1
などの定数定義を行ってください。

それと、もう一つ。

Range("C2") という表記は、Excel VBA上ならば構いませんが、
外部から制御するときには使えません。(どのシートの範囲かが曖昧なので)
ExcelApp.ActiveSheet.Range("C2") などの記述を使いましょう。

# できれば、Active系/Selection系プロパティも、あまり多用しない方が
# 望ましいのですが……それは今後の課題という事で。

おけら さん 2005年 01月 14日 21時 40分 30秒

vbsよりEXCELの制御をしなければならなくなりました。
  Set ExcelApp=GetObject( , "Excel.Application" )
ExcelApp.Cells.Select
ExcelApp.Selection.Sort Key1:=Range("C2"), Order1:=xlAscending
以上のようなスクリプトを実行すると
3行目のソートの命令でエラーになります。どうも引数の与え方が悪いようです。
どのように与えればいいのでしょうか?
なにとぞ皆様のご教授お願い致します。

魔界の仮面弁士 さん 2005年 01月 14日 21時 18分 11秒

>> Dim a()
>> MsgBox UBound(a) 'Error
>> なのがおかしいと思いません?こんなの使えないよー。
> 配列自体の仕様から言えば、納得できる動作ではありますが、

あ。上記の理由を書き忘れてました。

納得してもらえるかどうかは分かりませんが、
  Dim U
  Dim V()
  L = UBound(V) 'エラー
  V = Array()
  L = UBound(V) 'OK
  Erase V
  L = UBound(V) 'エラー
という処理を、SafeArrayGetUBound APIで置き換えてみます。
(VB/VBAネタばかりで済みません……)


後述のコードをVB/VBAで実行すると、以下のような結果になります。

》★初期化されていない配列★
》SAFEARRAY* → 0
》Error!! (5)プロシージャの呼び出し、または引数が不正です。

》★初期化された空の配列★
》SAFEARRAY* → 187167592
》UBound →-1

》★未初期化状態に戻す★
》SAFEARRAY* → 0
》Error!! (5)プロシージャの呼び出し、または引数が不正です。


これはつまり、UBoundが失敗するのは、配列変数が
「NULLポインタを参照している状態だから」と見る事ができます。

ReDim等で定義するまでは、SafeArrayが作成されていないため、
SafeArray系APIが失敗し、それがVB側にも伝わってきているようです。


〈実験コード〉
=================================================
Option Explicit

Private Declare Sub RtlMoveMemory Lib "kernel32" _
  (ByRef Dest As Long, ByRef Src() As Any, ByVal size As Long)

Private Declare Function SafeArrayGetUBound Lib "oleaut32" _
  (ByVal psa As Long, ByVal nDim As Long, ByRef plUbound As Long) As Long

Private Sub Form_Load()
  Dim U As Long
  Dim P As Long
  Dim HRESULT As Long

  On Error Resume Next

  '------------------------------------
  Dim V() As Variant
  Debug.Print "★初期化されていない配列★"

  RtlMoveMemory P, V, 4
  Debug.Print "SAFEARRAY* →"; P
  HRESULT = SafeArrayGetUBound(P, 1, U)
  If HRESULT = 0 Then
    Debug.Print "UBound →"; U
  Else
    Err.Raise HRESULT
    Debug.Print "Error!! ("; Hex(Err.Number); ")"; Err.Description
    Err.Clear
  End If
  '------------------------------------
  V = Array()
  Debug.Print "★初期化された空の配列★"

  RtlMoveMemory P, V, 4
  Debug.Print "SAFEARRAY* →"; P
  HRESULT = SafeArrayGetUBound(P, 1, U)
  If HRESULT = 0 Then
    Debug.Print "UBound →"; U
  Else
    Err.Raise HRESULT
    Debug.Print "Error!! ("; Hex(Err.Number); ")"; Err.Description
    Err.Clear
  End If
  '------------------------------------
  Erase V
  Debug.Print "★未初期化状態に戻す★"

  RtlMoveMemory P, V, 4
  Debug.Print "SAFEARRAY* →"; P
  HRESULT = SafeArrayGetUBound(P, 1, U)
  If HRESULT = 0 Then
    Debug.Print "UBound →"; U
  Else
    Err.Raise HRESULT
    Debug.Print "Error!! ("; Hex(Err.Number); ")"; Err.Description
    Err.Clear
  End If
End Sub

Return