》ばんのしゃーによかばんた さん 2005年 01月 14日 17時 45分 16秒
> ちょっと脱線。「Dim」はDimensionでしょうか?
ですます。“DIM”が配列宣言用のキーワードだった頃の
古いBASIC時代の名残ですね。
>>ちなみにVB/VBA では、「ReDim X(-1)」の記法は使えませんでした。残念。
> この場合の代替記法は、
> Dim a:a=Array()
> でしょうか。
そうですね。
ちなみに VB/VBAで、Variant以外の配列を初期化する時には、
StringArray = Split("")
ByteArray = ""
Call VarType(ObjectArray)
などが使えます。
それ以外の型も初期化したいなら、SafeArrayAllocDescriptor APIです。
# まぁ、VBScriptにはあまり関係の無い話ですけど。
> Dim a:a=Array()とDim a:ReDim a(-1)は区別が付きません。同じなのかも。
同じですね。
この場合の a は、「内部処理形式がVariant配列なVariant型」になります。
aの中身が配列なのであって、a自体は配列ではありません。
> 一方、Dim a():ReDim a(-1)は自由度が低い。(配列固定でスカラに戻れない)
この場合は、a自体が配列となります。
> ReDim a(-1)
> MsgBox UBound(a) '-1
> なのに、
> Dim a()
> MsgBox UBound(a) 'Error
> なのがおかしいと思いません?こんなの使えないよー。
配列自体の仕様から言えば、納得できる動作ではありますが、
言語仕様側で、未初期化状態の判断機能ぐらいは欲しかったですね。
VB.NETの配列は、「Nothingなら未初期化状態」と判定できますが、
VBScriptでは、エラートラップするしかない……なんだかなぁ。
>管理人むたぐち さん 2005年 01月 11日 21時 49分 10秒
>> ※Shell.OpenにsURLを渡せば、ieが起きます。
>厳密に言うと、httpの関連付けが起きるので、IE以外をデフォルト
>ブラウザに使っている場合は注意が必要です。
あれ、そうなんですか。
――――――――――――――――――――――――――――――――――――――
Sub Explore(vDir) Explore a folder
Sub Open(vDir) Open a folder
――――――――――――――――――――――――――――――――――――――
Shell.Exploreは、explorer.exe /e,〜で
Shell.Openは、explorer.exe 〜だとばかり思っていたら、
Shell.Openてのは、InvokeVerbのopenと同じだったんですね。
じゃ、Shell.Explore sURLはどうなるかと思ったら、エラーでした。
exeも起こせるし、引数が不要なら、ShellExecuteのない98/MEでは、
Shell.ShellExecuteやwShell.Runの代用に使えそう。
因みに、
explorer.exe /e,hoge.txt
explorer.exe hoge.txt
は、テキストファイルをNotePadでなく、
それぞれexplorerとieで表示してくれるんですよね。
なんか得した気分になりません?
何が良いかって?
うーん、例えば、NotePadで開くと、何かキーを触って、誤って更新するとか、
保存しますかってうるさかったりしますが、こっちなら大丈夫。
表示専用に向いています。
ところで、いつの頃にか、
Shell.ToggleDesktop
なんてのが追加されていて、バージョン依存になりますが、
「デスクトップの表示.SCF」を使わなくても済むようになってますね。
>魔界の仮面弁士 さん 2005年 01月 12日 11時 42分 31秒
>「"Re"Dim」という名前からは、「"再"定義」という意味が読み取れるので、
ちょっと脱線。「Dim」はDimensionでしょうか?
配列ならまだしも、配列でなくてもDimensionて変。
>下記はVBAのヘルプの記述ですが、VBSでも同じ事が言えますよね。
>| 同じ名前を持つほかの変数が後で作成されると、その変数の
>| 適用範囲 (スコープ) が広く、Option Explicit ステートメントが
>| 指定されている場合でも、ReDim ステートメントは後で作成された
>| 変数を参照し、コンパイル エラーは発生しません。
このヘルプは例なしではちょっときついのではないでしょうか。
Option Explicit
Sub s()
'Dim a()
ReDim a(-1)
WScript.Echo TypeName(a)
End Sub
s
Dim a
WScript.Echo TypeName(a)
ここで、Dim a()があるかないかで、違う結果(ローカル/グローバル)になる。
結局、動的配列の宣言は、ローカル変数でも使えるように、
Dim a():ReDim a(-1)
あるいは、
Dim a:ReDim a(-1)
と覚えましょう。ってことですね。
>ちなみにVB/VBA では、「ReDim X(-1)」の記法は使えませんでした。残念。
この場合の代替記法は、
Dim a:a=Array()
でしょうか。
Dim a:a=Array()とDim a:ReDim a(-1)は区別が付きません。同じなのかも。
一方、Dim a():ReDim a(-1)は自由度が低い。(配列固定でスカラに戻れない)
オーソドックスですが、こちらを使うメリットは特になさそう。
大体、
ReDim a(-1)
MsgBox UBound(a) '-1
や
Dim a:a=Array()
MsgBox UBound(a) '-1
なのに、
Dim a()
MsgBox UBound(a) 'Error
や
ReDim a(1)
Erase a
MsgBox UBound(a) 'Error
なのがおかしいと思いません?こんなの使えないよー。
本当にアプリはどうやって判定してエラーを迂回してたんでしょう?
てことで、ReDim a(-1)が導入されたんでしょうね。きっと。
そうそう、
こういった仕様上の特異点を作らないことが、仕様設計の観点のひとつです。
>魔界の仮面弁士 さん 2004年 12月 29日 23時 46分 50秒
>>XPにはschtasksコマンドなんてあるんですね。
>当方のProfessional Editionにはありました。
Professional EditionのCDを見ると、schtasks.ex{e|_}は無かったのですが、
sctasks.ex_が有りました。これですね。
ところが、Home Editionには、どちらも有りません。:-<
比べてみると、他にも、
taskkill.exe
tasklist.exe
のような、有用そうなコマンドがProにあって、Homeに無いようです。:-<
また、msg.exeなんてのが共通してあります。なんだろと思って、/?すると、
――――――――――――――――――――――――――――――――――――――
ユーザーにメッセージを送信します。
MSG {ユーザー名 | セッション名 | セッションID | @ファイル名 | *}
[/SERVER:サーバー名] [/TIME:秒] [/V] [/W] [メッセージ]
――――――――――――――――――――――――――――――――――――――
メッセージを標準入力から読み込んだりして、unixのwriteコマンドみたいです。
これは、以下に使えそう。
>たるら さん 2004年 09月 15日 20時 43分 34秒
>あるサーバから、繋がっているクライアントに対して、
>メッセージを通知したいのですが、(WindowsPopupメッセージみたいに)
ところで、
ZIPDLL.DLLとZIPFLDR.DLLを覗いて見ると、どちらも、サードパーティ製のようです。
もし、これらの仕様が公開されていれば、いろいろ使えるのではないかと思い、
どこかにないものかと探してみたのですが、分かりませんでした。残念。
これ?
http://pc5.2ch.net/test/read.cgi/esite/1099390847/
(管理人により削除)
》ばんのしゃーによかばんた さん 2005年 01月 11日 16時 04分 15秒
> 「または」なので、ReDimだけでよく、Dimは必要ありません。
これは、VBA や VB の
| 宣言した変数がモジュール レベルまたはプロシージャ レベルにない場合、
| ReDim ステートメントは宣言ステートメントと同様の働きをします。
という仕様を受け継いでいるのでしょうね。
私は、むたぐちさん同様、ReDim前に変数宣言を明示する派だったりします。
といっても、明確な理由があるわけではありません。単に気分の問題。(^^;
「"Re"Dim」という名前からは、「"再"定義」という意味が読み取れるので、
それを「変数の(最初の)宣言」に使うのが、あまり好きでは無いという、
それだけの理由です。
無理に、他の理由を探すなら…下記の様な場面かな?
下記はVBAのヘルプの記述ですが、VBSでも同じ事が言えますよね。
| 同じ名前を持つほかの変数が後で作成されると、その変数の
| 適用範囲 (スコープ) が広く、Option Explicit ステートメントが
| 指定されている場合でも、ReDim ステートメントは後で作成された
| 変数を参照し、コンパイル エラーは発生しません。
|
| このような名前の競合を避けるには、ReDim ステートメントは
| 宣言ステートメントとして使わず、配列を再定義するためだけに使用します。
# VB.NETではとうとう、事前宣言無しの ReDim が禁止されましたし。
>> ReDim x(-1)は、私もたまたま思いついたんですが、
>> 果たして正式な(?)方法なんでしょうか。
Undocumented であり、正式(?)な手法では無いと思いますが、
とても便利な方法ですね。利用させて頂きます。m(_ _)m
手元の環境で試したところ、特に問題なく利用できるみたいでした。
もっとも、全ての VBSバージョン(VBScript 1.0 環境など)で
試したわけでは無いので、絶対に大丈夫とは言えませんけれども…。
> VBのほうのReDimの説明に、
その説明は、VB.NETの言語仕様の物ですね。これも知りませんでした。
今まで、VB.NETでは「Dim I() As F = New F() {}」と書いていました。(恥)
ちなみにVB/VBA では、「ReDim X(-1)」の記法は使えませんでした。残念。
言語仕様で見ると、VBA と VB では、下限値と上限値を設定する仕組みになっていて、
VBS と VB.NET では、下限値は設定不可(常に0固定)で、上限値のみ設定可能ですね。
一方、VBA や VBS が利用している「COM の SafeArray」に関しては、
上限値を設定するのではなく、「下限値」と「長さ」を設定する仕様です。
これは、VB.NET が利用している「CLR の System.Array」でも同様で、
やはり生成時に 「下限値」と「長さ」を指定する必要があります。
そして上限値は、『上限値 = (下限値 + 長さ - 1)』として処理されています。
おはようございます。
昨日の問い合わせは、下記の方法で回避できました。
ご報告いたします。
Set wmiFileSecSetting = GetObject( _
"winmgmts:Win32_LogicalFileSecuritySetting.path=""" & Replace(fPath,"\","\\") & """")
>ちゃっぴさん
ご指摘のとおり、\は\\に変えないと駄目でした。
シングルクォートはそのままでも大丈夫でした。
ありがとうございます。
なお、最初に記述したソースは、
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/getsecuritydescriptor_method_in_class_win32_logicalfilesecuritysetting.asp
を参考にしておりました。
> XP Home Editionユーザは、Logoff/Shutdownスクリプトの
> 恩恵を受けられないってことですね。:-<
WMIにWin32_ComputerShutdownEvent Classというのがあったので
それがつかえないかな〜と思ってTryしてみたんですけど
Event取得できませんでした・・・
Dim objWMIService 'As WbemScripting.SWbemServices
Dim objEventSource 'As WbemScripting.SWbemEventSource
Dim objEventObject 'As WbemScripting.SWbemObject
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set objEventSource = objWMIService.ExecNotificationQuery( _
"SELECT * FROM __InstanceCreationEvent WITHIN 2" _
& "WHERE TargetInstance ISA 'Win32_ComputerShutdownEvent'")
Set objEventObject = objEventSource.NextEvent
WScript.Echo "Computer is shutting down."
SINK_OnObjectReadyでも取得できないようでしたし・・・
これって、どうやって使うんだろう・・・
まさか使えないClassを用意しているとも思えませんし・・・
To さかもと さん 2005年 01月 11日 12時 09分 04秒
> vbs内にて、「Win32_LogicalFileSecuritySetting」クラスを使用し、
> ファイルのACL情報を取得しているのですが、
> パスに「'(シングルクォーテーション)」を含む場合に
> エラーが発生してしまいます。
直接GetObjectで取得するのは無理みたいですね。
(私が知らないだけ?)
SWbemServicesのExecQuery Methodを使用して、
WHERE句でPath = 'D:\\hoge\'hoge'
こんな感じで出来ました。
ただし、対象Pathの"\"および"'"は事前にそれぞれ
"\\", "\'"に置換して置いてください。
To: ばんのしゃーによかばんた さん
> ※Shell.OpenにsURLを渡せば、ieが起きます。
厳密に言うと、httpの関連付けが起きるので、IE以外をデフォルト
ブラウザに使っている場合は注意が必要です。
> ※特に必要がなければ、WScriptのCreateObjectでなく、VBScriptのCreateObject
を使います。
私は特に必要なくても(第二引数とかが)、WScript.CreateObjectを使いますねー。
WSHのスクリプトだというのがハッキリするので好きなんです。
まあこの辺は、好みの問題になってきますね。
>管理人むたぐち さん 2005年 01月 07日 18時 00分 38秒
>To: つかさ さん
>ShellオブジェクトのWindowsメソッドは、起動されているIE・エクスプローラの
>Windowオブジェクトのコレクションを返します。
バグ見っけ。デバッグモードに入ります。:-)
ShellオブジェクトのWindowsメソッドは、起動されているIE・エクスプローラの
「IWebBrowser2」オブジェクトのコレクションを返します。
これは、Set ie=CreateObject("InternetExplorer.Application")
と同じものです。
したがって、変数名も、For Each Window In Shell.Windowsでなく、
For Each ie In Shell.Windowsとしたほうがぴったりです。
※そもそもWindowsメソッドという名前やその説明がよくないです。:-<
Function Windows() As Object
The collection of open folder windows
※事ほど左様に、名前はソフトウェア品質上、重要です。
サンプルも、美しくなーい。我流にlintします。:-)
※VBScriptのlintがほしいー。
Set Shell=CreateObject("Shell.Application")
sURL="http://www.roy.hi-ho.ne.jp/mutaguchi/bbs/index.shtml"
For Each ie In Shell.Windows
If TypeName(ie.Document)="HTMLDocument" Then Exit For
Next
If IsEmpty(ie) Then
Shell.Open sURL
Else
ie.Navigate sURL
End If
※特に必要がなければ、WScriptのCreateObjectでなく、VBScriptのCreateObject
を使います。
※構造的に、ループの中で、見つけて、処理して、脱出、でなく、
ループの中で、見つけて、脱出して、処理、のほうがすっきり。
※For Eachは満了するとEach変数がEmptyなので、それで途中脱出を判定します。
※Shell.OpenにsURLを渡せば、ieが起きます。
後に処理が続くなら、CreateObjectでieを起こしたほうがよい。
ところで、今回は、多重環境で厳密な動作精度を要求されるケースでは
ないのでしょうね。以前、後から段々厳しい動作条件を小出しされて、
それまでの話が何度も御破算になったりしました。
今回の処理も多重に起動すれば、複数のウィンドウが開きますし、
タイミングによりオブジェクトの先(ie.〜)の参照がエラーになることがあるので、
業務用途だとエラーリカバリを組み込む必要があります。
>管理人むたぐち さん 2005年 01月 08日 21時 42分 17秒
>Dim x()
>ReDim x(-1)
「VBScriptの変数」の説明に、
――――――――――――――――――――――――――――――――――――――
動的配列も Dim ステートメントまたは ReDim ステートメントを使用してプロシージャの最初に宣言します。ただし、動的配列の宣言には、次のコード例のように、かっこの中に配置する配列サイズと次元数がありません。次にコード例を示します。
Dim MyArray()
ReDim AnotherArray()
――――――――――――――――――――――――――――――――――――――
とあります。「または」なので、ReDimだけでよく、Dimは必要ありません。
実際、Option Explicitしていても大丈夫です。
ただ、この説明の後半は間違っていて、ReDimはサイズを省略できません。
>ReDim x(-1)は、私もたまたま思いついたんですが、
>果たして正式な(?)方法なんでしょうか。
VBのほうのReDimの説明に、
――――――――――――――――――――――――――――――――――――――
-1 を使って配列の次元の上限を宣言できます。これは、配列が Nothing ではなく空であることを意味し、共通言語ランタイムの一部の関数では区別が必要です。ただし、Visual Basic のコードではこのような配列に正しくアクセスできません。アクセスしようとすると、実行時に IndexOutOfRangeException エラーが発生します。
――――――――――――――――――――――――――――――――――――――
とあるので、きっと大丈夫でしょう。
vbs内にて、「Win32_LogicalFileSecuritySetting」クラスを使用し、ファイルのACL情報を取得しているのですが、
パスに「'(シングルクォーテーション)」を含む場合にエラーが発生してしまいます。
----------------------------------------
Dim arg
Set arg = Wscript.Arguments
If arg.Count <> 0 Then
Call GetAclInfo( arg(0) )
Else
Wscript.echo "ERROR NOT ARGUMENT"
End If
Sub GetAclInfo( fPath )
On Error Resume Next
Set wmiFileSecSetting = GetObject("winmgmts:Win32_LogicalFileSecuritySetting.path='" & fPath & "'")
RetVal = wmiFileSecSetting. _
GetSecurityDescriptor(wmiSecurityDescriptor)
If Err.Number <> 0 Then
WScript.Echo "GetSecurityDescriptor FAILED" _
& VBCRLF & Err.Number & VBCRLF & Err.Description
WScript.Quit
Else
WScript.Echo "GetSecurityDescriptor SUCCEEDED"
End If
' Retrieve the DACL array of Win32_ACE objects.
DACL = wmiSecurityDescriptor.DACL
For each wmiAce in DACL
wscript.echo "Access Mask: " & wmiAce.AccessMask
wscript.echo "ACE Type: " & wmiAce.AceType
' Get Win32_Trustee object from ACE
Set Trustee = wmiAce.Trustee
wscript.echo "Trustee Domain: " & Trustee.Domain
wscript.echo "Trustee Name: " & Trustee.Name
' Get SID as array from Trustee
SID = Trustee.SID
For I = 0 To UBound(SID) - 1
strsid = strsid & SID(I) & ","
Next
strsid = strsid & SID(I)
wscript.echo "Trustee SID: {" & strsid & "}"
Next
End Sub
----------------------------------------
※ 下記WMIにて取得部分にて、
パスをシングルクォーテーションで囲む
最初のシングルクォーテーションから、
パス内のシングルクォーテーションまでを
パス名として認識されてしまっているようなんですが。
Set wmiFileSecSetting = GetObject("winmgmts:Win32_LogicalFileSecuritySetting.path='" & fPath & "'")
パス自体をダブルクォーテーションで囲う、<>で囲うなどしてみたのですが、
どうしてもエラーが出てしまいます。
もし、回避方法など分かりましたら教えていただきたく思います。
よろしくお願いいたします。
ScriptControl経由でJScriptのArrayを使ったソートの改版。
fsoのFolder.FilesをDateLastModifiedの昇順にソートします。
「VBScriptの配列」を「JScriptの配列」の要素に入れてソートします。
Set SC = CreateObject("ScriptControl")
SC.Language = "JScript"
SC.AddCode "" & _
"function sort(array,vbfunc){return(array.sort(compare));" & _
"function compare(x,y){return(vbfunc(x,y));}}"
Set JS=SC.Eval("new Array()")
Set fso=CreateObject("Scripting.FileSystemObject")
Set Folder=fso.GetFolder("c:\windows\system32")
k=0
For Each File In Folder.Files
: JS.push(Array(k,File.Path,File.DateLastModified))
: k=k+1
Next
Function compare(x,y)
compare=Sgn(x(2)-y(2))
If compare=0 Then compare=Sgn(x(0)-y(0))
End Function
Call SC.Run("sort",JS,GetRef("compare"))
For Each arr In JS
: WScript.Echo arr(1),arr(2)
Next
※随分使い易くなったと思いません?
To: ばんのしゃーによかばんた さん
私の最近の動的配列の使い方は、こんな感じです。
Dim x()
ReDim x(-1)
For I = 0 To 9
ReDim Preserve x(UBound(x)+1)
x(UBound(x)) = I
Next
MsgBox Join(x)
ReDim x(-1)は、私もたまたま思いついたんですが、
果たして正式な(?)方法なんでしょうか。
>管理人むたぐち さん 2004年 12月 29日 16時 10分 24秒
>HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\System\Scripts\Logoff\0\0キーに
>「Script」という名前の文字列が、ログオフスクリプトのパスのようです。
試してみましたが、駄目でした。:-<
>が、パス以外にも色々設定項目があるようですし、レジストリを弄るだけで
>何とかなるものでもなさそうな気がしてきました。
同感です。MSDN Libraryにも、
>use Group Policy. Do not edit the registry.
と書いてあるように、無理そうです。
XP Home Editionユーザは、Logoff/Shutdownスクリプトの恩恵を受けられない
ってことですね。:-<
代替手段は、
ExcelのAuto_Close()
VBのFormのQueryUnload()
を使う方法ですが、どちらも、有料ソフトが必要だし。
.NETなら、Form.Closing event ? 要研究。。。
本年もよろしくお願いします。
2005年の最初のお題は、VBScriptの動的配列の宣言方法です。
今まで、動的配列は、Dim x()で宣言してました。
Dim argv()
Dim argc
Dim arg
Dim k
For Each arg In WScript.Arguments
ReDim Preserve argv(argc)
argv(argc)=arg
argc=argc+1
Next
For k=0 To argc-1
arg=argv(k)
Next
のように。
でも、これだと、
For k=0 To UBound(argv)
arg=argv(k)
Next
なんてすると場合によってエラーになるんです。
Dim x()
MsgBox UBound(x) 'NG
それで、動的配列の宣言は、Dim x()でなく、正しくは、
ReDim argv(-1)
にすべきだと分かりました。
ReDim x(-1)
MsgBox UBound(x) '-1
動的配列の宣言は、Dim x()でなく、ReDim x(-1)と覚えましょう。
――――――――――――――――――――――――――――――――――――――
ところで、
※これも、バグ繕いしていて思ったことです。
Option Explicitで、宣言してない変数を使うとエラーになりますが、
逆に、
[1] 宣言だけして、使ってない変数を検出する方法
※ソースを流用して作ると、よくあるんです。ソースレビューの最初の作業です。
とか、
[2] ローカルで使われてるグローバル変数を検出する方法
※ローカルで宣言を忘れて、グローバル変数を変更するバグがありました。
について、何かよい方法がありましたら教えてください。
管理人むたぐち様
ありがとうございます、ばっちりです。答えを
全部教えてもらって本当に助かりました。
bExitWindow はbExistWindowのミススペルです。
# 終了してどうする(汗
To: つかさ さん
ShellオブジェクトのWindowsメソッドは、起動されているIE・エクスプローラの
Windowオブジェクトのコレクションを返します。
これを利用します。
IEとエクスプローラの違いは、Window.documentオブジェクトのTypeNameを調べます。
"HTMLDocument"ならIEということになります。
起動してるIEがみつからなかった場合は、新たにIEを立ち上げ、ページにNavigateさせます。
以下、サンプルです。
Set Shell = WScript.CreateObject("Shell.Application")
sURL = "http://www.roy.hi-ho.ne.jp/mutaguchi/bbs/index.shtml"
bExitWindow = False 'IEのウィンドウがあるかどうか
For Each Window In Shell.Windows
If TypeName(Window.document)="HTMLDocument" Then
Window.Navigate sURL '開いてるウィンドウ上で移動
bExitWindow = True
Exit For
End If
Next
If Not bExitWindow Then 'IEのウィンドウが無い場合は、IEを立ち上げる。
Set IE = WScript.CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate sURL
End If
急遽、VBScriptを書くようになった者です。
VBScriptからIEを開き、特定URLを表示させるだけの
プログラムなのですが、再起動した回数だけIEの
ウインドウが開いてしまいます。
Set IeApp = CreateObject("InternetExplorer.Application")
IeApp.Visible = True
IeApp.Navigate( "http://***.***.***/)
これをIEのウインドが無いときだけウインドウを開き
ウインドウが存在するときは、新規に開かず、その
ウインドウに特定URLさせるにはどうしたら良い
でしょうか。いろいろ調べたのですが、わからずここを
来ることになりました。よろしくお願い致します。
みなさま、明けましておめでとうございます。
本年度も私むたぐちと、WSH Lab.をよろしくお願いします。
今年はMSMVPとして、新たなる活動も考え中なので、期待せずに(?)
お待ちください。
》 ばんのしゃーによかばんた さん 2004年 12月 26日 16時 02分 15秒
>>管理人むたぐち さん 2004年 12月 24日 19時 55分 43秒
>>XPにはschtasksコマンドなんてあるんですね。
>>知らなかったです。
>あれ、そんなの、ありませんよ。またしても、Home Edition だから? :-<
当方のProfessional Editionにはありました。
下記を見ると、エディションによるみたいですね。Homeには無いのかな?
http://www.dj.st44.arena.ne.jp/xwin2/mainhtml/kanto/gr9expproclninst.html
その一方で、KB834853 には、"Home Edition"が記載されています。不思議。
http://support.microsoft.com/kb/834853/JA/
To: ばんのしゃーによかばんた さん 2004年 12月 26日 16時 03分 02秒
> gpedit.mscは、HomeEditionをチェックして動かないようです。:-<
> そのため、対応するレジストリキーを調べることもできません。:-<
> どなたか調べて教えていただけませんか。
HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\System\Scripts\Logoff\0\0キーに
「Script」という名前の文字列が、ログオフスクリプトのパスのようです。
が、パス以外にも色々設定項目があるようですし、レジストリを弄るだけで
何とかなるものでもなさそうな気がしてきました。
(管理人により削除)
ちゃっぴ さん
ご返答ありがとうございます。
2004年 12月 25日 13時 18分 39秒のショッカーです。
Firewallの設定は無効の状態です。
テスト環境が現在無いので、Usernameを「Hostname\Account」
は明日試してみます。Passwordは""ではありません。
Firewallでは無いのですが、リモートマシンにはSymantecの
ウィルススキャンソフトが入っており、Symantec WMI Serviceなる
サービスがあります。(スタートアップ:自動、サービス状態:停止)
何か関係しているかもしれませんので、ウィルススキャンソフトが
入っていないマシンでテストしてみようと思います。
またご連絡いたしますので、宜しくお願い致します。
>ばんのしゃーによかばんた さん 2004年 05月 30日 15時 58分 38秒
>ロック、逐次化の方法です。
このロックメカニズムは、「オープン中のファイルは削除できない」という、
Windows OSの、特筆すべき「長所」を利用しています。
※このエラー回避のためにロックが欲しい?何か因果は巡るというような感じ。
この特性は、メインフレームなら当たり前で、何処が珍しいのかと言われそうですが、
かといって普遍的なものでは決してなく、実際、Windowsの対抗馬であるUnix/Linuxでは、
「オープン中のファイルも削除できる」という、けったいな仕様が罷り通っています。
Unixの仕様で、もし、ひとつだけ直してくれるというのなら、一番はこれです。
作者自身が執着するcreat()のスペルミスなんか、どうでもいいです。
※二番目はcompressがデフォルトで元ファイルを削除すること。
※実際、昔、顧客企業でインターネットサービス運用中のデータベースがオペミスで
削除/復元されてしまったのですが、そうとは分からず、DBMSのDB破壊障害が疑われて、
えらく苦労しました。全く迷惑な仕様です。:-<
※データベースのコピーを採ろうとしてcompressしたら、運用中のデータベースが
消えちゃった。
こんなOS(Unix/Linux)は危なくてミッションクリティカル用途に使えない、
とWindowsの逆宣伝に使えそうなもんです。
logon/logoff/startup/shutdown scriptの件。
>管理人むたぐち さん 2004年 11月 04日 16時 53分 35秒
>> 2000やXPのProfessionalからgpedit.mscさえ持って来れば、使えるのかな。
>対応するレジストリキーの書き換えだけで十分だと思いますよ。
gpedit.mscは、HomeEditionをチェックして動かないようです。:-<
そのため、対応するレジストリキーを調べることもできません。:-<
どなたか調べて教えていただけませんか。
>管理人むたぐち さん 2004年 05月 20日 12時 27分 04秒
>今、こちら(WinXP)で確認したところ、たしかにワイルドカードが
>効きませんね。他のOSを使用されてる方、検証お願いします。
>いつの間にか仕様が変わったのでしょうか。
>CopyHere
遅れ馳せながら、XPで試してみましたが、ワイルドカードがちゃんと効きます。
変ですね。
>管理人むたぐち さん 2004年 12月 24日 19時 55分 43秒
>しかし、このスクリプトは非同期で動作するため、
>スクリプトが終了すると、タスクも中断されてしまうという
>問題点があります。
>これを回避するには、このスクリプトの後に
>WScript.Sleep 10000
>のように、適度にウェイトを入れるなどの方法があると思います。
>(この例だと10秒です)
Verbを省略するとプロパティ(&R)になって、
この場合は、待ち合わせが必要なようです。
>もっといい方法はばんのしゃーによかばんたさんにお任せしましょう(汗
はい、では、hidden explorer方式。
Set Shell=CreateObject("Shell.Application")
この1行の代わりに、
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
ie=Empty
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
Set Shell=ie.Document.Application
とします。
解説
既存のExplorerからIShellDispatch*を取り出します。
ないときは、隠しのExplorerを常駐させます。
ただし、Explorer.exeは、プロセスとしてはすぐ消えます。
デスクトップのExplorer.exe空間に同居するんですね。
一方、IExplore.exeの場合は、プロセスが残ります。
>管理人むたぐち さん 2004年 12月 24日 19時 55分 43秒
>XPにはschtasksコマンドなんてあるんですね。
>知らなかったです。
あれ、そんなの、ありませんよ。またしても、Home Edition だから? :-<
ないので、分かりませんが、
>JAM さん 2004年 12月 21日 11時 26分 43秒
>WindowsXPで言うところのschtasksコマンドの/runのような機能を
>実現したいのですが可能でしょうか?
ということなので、
Set Shell = CreateObject("Shell.Application")
Set Folder = Shell.NameSpace("::{d6277990-4c6a-11cf-8d87-00aa0060f5bf}")
For Each FolderItem In Folder.Items
WScript.Echo FolderItem.Name
If FolderItem.Name = "新しいタスク" Then
For Each Verb In FolderItem.Verbs
WScript.Echo Verb.Name
Next
FolderItem.InvokeVerb "タスクの実行(&U)"
Exit For
End If
Next
でしょうか。
この場合は、待ち合わせは不要なようです。
なぜか、このFolderは、ParseName(name)やItems.Item(name)が駄目なようですね。
――――――――――――――――――――――――――――――――――――――
>まつだ さん 2004年 01月 23日 16時 43分 34秒
> runasでとも考えたのですが、管理者パスワードは周知したくありません。
> runas+sendkeys等で可能かな?とは思っているのですが、
> 何か他に良い方法はないでしょうか?
schtasksコマンドの/runや上記のスクリプトが、この用途に使える?
訂正です。
> エラー:アクセスが拒否されました。
なので、Username, Passwordが違っている可能性も高いかと・・・
Usernameを「Hostname\Account」にしてみるとどうなりますか?
また、Passwordは""ではないですよね?
ショッカー さん 2004年 12月 25日 13時 18分 39秒 へ
最近WMI & ADSI にずっぽり使っているちゃっぴです。
> エラー:アクセスが拒否されました。
> コード:80070005
> ソース:SWbemLocator
ですと、SWbemLocator.ConnectServerがWBEM_E_ACCESS_DENIEDの
Errorを返していると思いますので、RPCでのClientへ接続が
出来ていないのでは?
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/iwbemlocator_connectserver.asp
XP SP2とかあるので、Firewallの設定あたりを見直してみるとよいかも?
でわ
はじめまして。
WMI+VBSでリモートマシンの制御を行いたいと思っているのですが、
エラーが出てしまいます。
WMI関連の情報が結構少なく、エラーの対処方法がわからない状態です。
この掲示板で質問する内容ではないかもしれませんが、
お力をお貸し下さい。
ローカルマシン(Win2000-SP4 or WinXP-SP1)からリモートマシン
(WinXP-SP1/SP2)のリモートデスクトップの有効/無効を制御
したいのですが、アクセスが拒否されるとエラーが表示されます。
WMIがリモートマシンの制御にDCOM、RPCを利用するらしいのですが、
よくわかりません。
(一応、リモートマシンのDCOMは有効です)
エラー、スクリプトは以下の通りです。
(ユーザ、パスワードはリモートマシンのadmin権限を持っています。)
宜しくお願いします。
エラー:アクセスが拒否されました。
コード:80070005
ソース:SWbemLocator
Const ENABLE_CONNECTIONS = 1
Const DISABLE_CONNECTIONS = 0
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objSWbemServices = objSWbemLocator.ConnectServer("リモート
マシン名", "root\cimv2", "ユーザ名", "パスワード")
Set colKlasse = objSWbemServices.ExecQuery("Select * from
Win32_TerminalServiceSetting")
For Each objTing in colKlasse
errAngivelse = objTing.SetAllowTSConnections(ENABLE_CONNECTIONS)
Next
To: JAM さん
XPにはschtasksコマンドなんてあるんですね。
知らなかったです。
代替案の方向性としては、こんな感じだと思います。
Set Shell = WScript.CreateObject("Shell.Application")
Set oFolder = Shell.NameSpace("C:\WINDOWS\Tasks")
For Each oItem In oFolder.Items
If oItem.Name = "タスク名" Then
oItem.InvokeVerb
Exit For
End If
Next
しかし、このスクリプトは非同期で動作するため、
スクリプトが終了すると、タスクも中断されてしまうという
問題点があります。
これを回避するには、このスクリプトの後に
WScript.Sleep 10000
のように、適度にウェイトを入れるなどの方法があると思います。
(この例だと10秒です)
もっといい方法はばんのしゃーによかばんたさんにお任せしましょう(汗
(管理人により削除)
>管理人むたぐち さん 2004年 11月 11日 22時 09分 29秒
>To: オズ さん
>> スケジューラで実行しているスクリプト中でFileSystemObjectを用いてファイルを削除する処理があるのですが、そこでたびたびエラーが出て困っております。
>実は私も困っています。
>WSHではperlのように、ファイルにロックをかけたり、ロックがかかってるかどうかを
>調べたりができないので、ファイル処理が上手くいかなかった場合のフォローが
>難しいです
私は今まで、WSHでロックを掛けたいと思うようなケースに、実際に遭遇した
ことがないのですが、あります?
上記の場合も、ロックがあると、何かよいことがありますでしょうか?
ロックは関係ないような気がします。
しかし、頭では、ロックが必要なこともあるかなと思い、
>ばんのしゃーによかばんた さん 2004年 05月 30日 15時 58分 38秒
>ロック、逐次化の方法です。
を考えたのですが、実際に使う機会が未だありません。
一番の用途は二重起動防止、二番はログファイル書き出しかな、と思うのですが、
今まで適用事例なし。それ以外の用途は、ちょっと思い付きません。
もし、WSHでロックが欲しい、と思ったときにはご利用ください。
ReadLine/ReadAllのNUL文字障害は、最近のレベルダウンかと思ったら、
随分、昔からあるようですね。
2001年5月のタイムスタンプのあるWSHLAB.HTAにその苦労の跡が見えます。
対策の丙案ですね。
――――――――――――――――――――――――――――――――――――――
if (hitlist.length != 50 && !kijifiles[x].is_newkiji) {
warning(kijifiles[x].path, kijifiles[x].num);
}
return true;
}
function warning(fname, num) { // 警告メッセージの表示
var n = hitlist.length - 1;
var test = (hitlist[n].kiji.search(/\x00/) != -1);
var s = '<font color="blue">過去記事リスト['+num+"] <"+fname+">";
if (test) {
if (hitlist.num == 2 && hitlist.length == 19) {
s += " の 741 行目";
} else {
s += " の "+(50-n)+" 番目の記事";
}
s += "にある文字コード 0 を取り除いてください。";
} else {
s += " は正常に読み込めないか、壊れている可能性があります。";
}
s += '</font>';
set_status(s, true);
}
――――――――――――――――――――――――――――――――――――――
過去記事リストにNUL文字が混入して、記事が欠落した様子が伺えます。
言ってくだされば、もっと早く代替関数を提供できましたのに。
3年半も経って、まだ直ってないということは、MSも認識してないのかも。
ま、ここで話題になったので、きっと、そのうち直るでしょう。
はじめまして。
Windows2000のタスクスケジューラで作成したタスクをWSHで実行したい
と考えております。
WindowsXPで言うところのschtasksコマンドの/runのような機能を
実現したいのですが可能でしょうか?
To: ばんのしゃーによかばんた さん 2004年 12月 16日 19時 20分 37秒
> 他の方法で対処済みなので、もう興味をなくされているかも知れませんが、
> 出来れば、以下を試していただけませんか。
>
> >ばんのしゃーによかばんた さん 2004年 12月 12日 18時 08分 28秒
> >#! C:\Windows\System32\CMD.EXE /C ECHO
> >とすると、一時ファイル名が表示されるはずです。
ごめんなさい、An HTTPD自体が今、すごく不安定でして、設定ダイアログを
開くだけで落ちてしまうという体たらくです。
あまりに変なことをやらせすぎてるからでしょうか(苦笑
ただ、これは前に*.batで一応確認してみました。
すると、カレントディレクトリがHTMLの代わりに表示されるだけで、
後は何も起こらなかったです。
すぐ使える(主に)WMIを利用したシステム管理用WSHコード断片
が集められていることで、有用なサイトとして知られる、
TechNet: スクリプト センタ
http://www.microsoft.com/japan/technet/scriptcenter/default.mspx
内のコンテンツに、
Tales from the Script
http://www.microsoft.com/japan/technet/community/columns/scripts/default.mspx
というのがあります。
今年1月から始まった、初心者向けWSHスクリプト解説ということですが
(恥ずかしながら私はちっとも知らなかった)、
妙にこだわりを感じるのは気のせいでしょうか?
現在、コマンドライン引数とエラートラップの記事が上げられています。
しかし、半年に一度しか更新がないのは寂しいですね。
1ヶ月に1回くらいなら、私が寄稿してみようかな。。
WSH Labも相当内容が古くなっちゃいましたし、
心機一転って感じでいければいいですねぇ。
12/18のMSMVP 2004 Japan Community Open Dayに参加された方々、
どうもお疲れ様でした&ありがとうございました。
残念ながら私はMicrosoft社とのNDA(秘密保持契約)を締結しているため、
詳細についてはお話できないのです。が、参加者の皆様から様々な
知識をいただくことができましたので、その経験を生かし、
これからのこの掲示板での活動の糧としたいと思いますので、
引き続き、当掲示板と私、むたぐちをよろしくお願いします。
さて、それに合わせてという訳でもないですが、せっかく作ったWSHch(http://librage.mine.nu:2424/wshbbs/wsh/index.html)なので、
利用しましょう。
ということで、お題自由の雑談スレッドを建てました。
ご自由にご利用ください。
雑談スレッド
http://librage.mine.nu:2424/wshbbs/test/read.cgi/wsh/1103464611/
VBScriptで可変個引数を実現するパラダイムです。
定番のScriptControlとJScriptを利用します。
Call AddCode("Proc1",3)で関数名と引数数を登録すると、
js.Proc1()で可変個引数が使えます。省略した引数はEmptyになります。
――――――――――――――――――――――――――――――――――――――
Set SC=CreateObject("ScriptControl")
SC.Language="JScript"
Call SC.AddObject("Me",Me)
Sub AddCode(proc,n)
Dim code,k,m
code="function " & Proc & "(x){" & vbCRLF & _
"switch(arguments.length){" & vbCRLF
For k=0 To n
code=code & "case " & k & ":return(eval('Me." & Proc & "("
For m=0 To k-1
If m Then code=code & ","
code=code & "'+arguments[" & m & "]+'"
Next
For m=k To n-1
If m Then code=code & ","
code=code & "undefined"
Next
code=code & ")'));break;" & vbCRLF
Next
code=code & "}" & vbCRLF & "}" & vbCRLF
SC.AddCode(code)
End Sub
Function Proc1(a,b,c)
Proc1=a+b+c
End Function
Call AddCode("Proc1",3)
WScript.Echo SC.Run("Proc1")
WScript.Echo SC.Run("Proc1",1)
WScript.Echo SC.Run("Proc1",1,1)
WScript.Echo SC.Run("Proc1",1,1,1)
Set js=SC.CodeObject
WScript.Echo js.Proc1()
WScript.Echo js.Proc1(1)
WScript.Echo js.Proc1(1,1)
WScript.Echo js.Proc1(1,1,1)
――――――――――――――――――――――――――――――――――――――
ところで、VBScriptで途中引数を省略するとどうなるか、知ってました?
VBScriptのはVB/VBAのOptionalキーワードがないので、構文エラーになる
と思っていたら、違いました。
call s(1,,2)
sub s(a,b,c)
wscript.echo typename(b) 'Error
end sub
ファイルの関連付けで、commandキーの@値に環境変数が使えるか。
という問題について。
RegEditで、関連付けのコマンドラインを、他からコピーして、追加しました。
起動すると、「アクセスが拒否されました。」
commandキーの@値に%SystemRoot%があるせいです。自力で展開するか、
@値を"REG_EXPAND_SZ"タイプに変えればよいのですが、これがなかなか。
いろいろ試してみると、以下の結果になりました。
――――――――――――――――――――――――――――――――――――――
RegEdit.exeからは、@値は"REG_SZ"タイプになって、変更できないので、不可。
「フォルダオプション」-「ファイルの種類」からも、同様に不可。
――――――――――――――――――――――――――――――――――――――
wShell.RegWriteで"REG_EXPAND_SZ"タイプで書き込めば、可。
WMIからも同様に可。
OpenAsからも可。
――――――――――――――――――――――――――――――――――――――
To: ばんのしゃーによかばんた さん
いつも回答ありがとうございます。
> >むちゃ さん 2004年 12月 07日 10時 07分 26秒
> >HTA でステータスバーを表示することはできないでしょうか??
>
> もし、コモンコントロールが使える環境ならば、可能です。
> 以下でも使ってます。普通の使い方とはちょっと違いますが。
>
> >ばんのしゃーによかばんた さん 2004年 07月 21日 13時 13分 27秒
> >ファイル(複数可)を、アイコンでなく、ウィンドウにドロップすると、
> >フルパス名のリストをクリップボードに入れるHTAです。
> >ToClip.HTA
確かに、コモンコントロール でできそうですね。
この場合、端末によって実行ができない可能性はあるのでしょうか??
(コモンダイアログ のように使えない場合があるとか・・・)
また、ウィンドウ に直接 ステータスバー を付加したい場合、
Win32API を使用しなければならないと思うのですが、
Shell.Application の Windows コレクションでは HTA のウィンドウを取得することができません。(iexplore.exe でないから??不明です・・・)
HTA の ウィンドウハンドル を取得しようとした場合、通常どおりに API の列挙で探すしかないのでしょうか??
> 或いは、ステータスバー擬というのはどうでしょう。試しに作ってみました。
>
> <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>
私もこの方法は考えました。(この記事検索の HTA を参考にしました)
やっぱりこの方法が一番いいのかなぁ・・・
>あんのうん さん 2004年 07月 31日 14時 12分 39秒
>HTAでスクリーンセーバを作ってみました。
Internet Development SDK
Dynamic Properties: Orbits Sample
ms-help://MS.MSDNQTR.2003FEB.1041/dhtml/workshop/samples/author/dhtml/overview/orbits.htm
これなんか、スクリーンセーバにぴったりです。
アルファベットなんかでなく、もっと惑星っぽくしたいところですが、
ちょっと私の手には余ります。:-p
>管理人むたぐち さん 2004年 11月 15日 21時 08分 06秒
>一応検証用のコードです。test.cgi
>拡張子.cgiには「#!の行を調べる」をチェックしています。
>また、一行目を省略して、test.vbsとした場合は
>正常に動作することを確認しています。
>#!C:\Windows\System32\CScript.EXE //E:VBS //nologo
>「Windows Script Host の実行に失敗しました。 (この操作を完了するのに十分な記憶域がありません。 ) 」
>これ、どういうエラーか分かるかた、いますか?
同じメッセージに遭遇しました。
cscript -e:vbs con
CScript エラー: Windows Script Host の実行に失敗しました。 (この操作を完了するの
に十分な記憶域がありません。 )
>管理人むたぐち さん 2004年 12月 11日 23時 29分 19秒
>ということは、やはり、#!の後の文字列のプログラムを実行して、
>そこは読み捨て、そこから最後までを標準入力に
>渡しているという実装みたいですね。
>となると、VBS on WSHがダメだった理由は、やっぱりWSHに由来する
>何らかの問題があるんだと思われます。
>さて、どこに報告すればいいのかな?
普通の一時ファイルでなく、なにか特別なファイル擬を渡しているのかも。CONとか?
WSHは、ただOpenすりゃいいものを、Open前に、普通のファイルしか持ってない、
存在/サイズ/アクセス権か何かを確認しようとしている、のかも。
他の方法で対処済みなので、もう興味をなくされているかも知れませんが、
出来れば、以下を試していただけませんか。
>ばんのしゃーによかばんた さん 2004年 12月 12日 18時 08分 28秒
>#! C:\Windows\System32\CMD.EXE /C ECHO
>とすると、一時ファイル名が表示されるはずです。
>管理人むたぐち さん 2004年 12月 15日 21時 21分 38秒
>ちなみに、試してないのですが、cscript.exeの//U オプションを使えば、
>WScript.StdInにUnicodeが渡るはずなので、
>Set StdIn = Fs.GetStandardStream(0,True)
>と同じ効果が得られると思います。
この場合には、ReadLine/ReadAllの障害は出ないようです。
つまり、ReadLine/ReadAllの障害は、コード変換バッファで起こっている?
※ところで、cscript.exeの//CP:codepageオプション(隠し)は
どういう使い方ができるのか、不明です。分かります?
>ばんのしゃーによかばんた さん 2004年 12月 14日 17時 59分 49秒
>※shell.NameSpace()からだと、
>FolderItem.InvokeVerb("copy")
>dFolder.Items.Item("圧縮 (zip 形式) フォルダ.ZFSendToTarget").InvokeVerb("paste")
>が使えないので、'Hidden Explorer'の技を使います。
というより、
Set shell=CreateObject("Shell.Application")からだと駄目で、
Set shell=ie.Document.Applicationから
shell.NameSpace()すればよいようです。