←
▼
▲
Sub Stream::LoadFromFile( Path as string )
ファイルの内容をストリームにリードします。
を設定して
呼び出す前に
を呼び出しておいてください。
サンプル
参考
←
▼
▲
Sub Stream::SaveToFile( Path as string [, Options as integer ] )
ストリームの内容をファイルにライトします。
adSaveCreateNotExist (=1)
adSaveCreateOverWrite (=2)
上書きできるようにします
←
▼
▲
Function Stream::Read( [ SizeOfByte as integer ] ) as array of Byte
バイナリ・ストリームからバイナリ・データをリードします。
adReadAll (=-1)
SizeOfByte 引数
リードするバイト数、または 下記の定数を指定します。
省略時は、adReadAll を指定したときと同じ動きをします。
ストリーム全体をリードします。
Read( 1 ) のときは、返り値は配列ではなくなります。
サンプル
リードするデータが1つも無いときは、Null が返ります。
←
▼
▲
Function Stream::ReadText( LengthOfChar as integer ) as string
テキスト・ストリームからテキストをリードします。
LengthOfChar 引数
リードする文字数、または 下記の定数を指定します。
ストリーム全体をリードします。
1行だけリードします。
バイナリ・ストリームでは使えません。
の影響を受けます。
サンプル
←
▼
▲
Property Get Stream::EOS as boolean
ストリームの末尾かどうか
←
▼
▲
Sub Stream::Write( Data as array of Byte )
バイナリ・ストリームへバイナリ・データをライトします。
←
▼
▲
Sub Stream::WriteText( Text as string [, Options as integer ] )
テキスト・ストリームへテキストをライトします。
Options 引数
最後に改行文字もライトします
普通にライトします
adWriteChar (=0)
省略すると、adWriteChar を指定したときと同じ動きになります。
←
▼
▲
Sub Stream::SetEOS()
ストリームの中の現在位置以後のデータを削除します。
で現在位置を戻したときに使います。
←
▼
▲
Property Stream::Position as integer
現在位置。 リードまたはライトするバイト位置。
先頭は 0 です。
ファイルの末尾(Position=Size-1)の次(Position=Size)より後に
Position を設定しようとするとエラーになります。
Mode = adModeReadWrite でもエラーになります。
←
▼
▲
Property Stream::Size as integer
ストリーム・バッファーのサイズ(バイト)
←
▼
▲
Sub Stream::CopyTo( DstStream as Stream , Size as integer )
ストリームの一部を、別のストリームへコピーします。
←
▼
▲
WSH から使えるネットワークに関するライブラリです。
←
▼
▲
Function Network::EnumNetworkDrives() as IWshCollection
ネットワーク・ドライブと、そのリンク先を一覧します。
【引数】
返り値
ネットワーク・ドライブと、そのリンク先の一覧
Dim i
Dim net : Set net = WScript.CreateObject("WScript.Network")
Dim drives : Set drives = net.EnumNetworkDrives()
For i = 0 to drives.Count - 1 Step 2
echo drives(i) +" = "+ drives(i+1)
Next
サンプル
出力例:
H: = \\pc01\home
N: = \\pc01\export
←
▼
▲
Internet Explorer に表示されているフォームに自動入力したり、ボタンを押したりできます。
Sub Main( Opt, AppKey )
'// ホームページを開く
Set ie = CreateObject("InternetExplorer.Application")
ie.Navigate "http://www.google.co.jp/"
ie.Visible = True
WaitForNavigateIE ie
Assert ie.LocationURL = "http://www.google.co.jp/"
'// 検索キーワードを入力
ie.Document.getElementById("q").Value = "検索キーワード"
WScript.Sleep 100
'// 検索ボタンクリック
ie.Document.all("btnG").Click
WaitForNavigateIE ie
'// 1件目のサイトのタイトルを表示
echo ie.Document.getElementById("res") _
.getElementsByTagName("li")(0) _
.getElementsByTagName("h3")(0) _
.innerText
'// ブラウザーを閉じる
ie.Quit
End Sub
Sub WaitForNavigateIE( ie )
Do While ie.Busy = True Or ie.readystate <> 4
WScript.Sleep 100
Loop
Do Until objIE.document.ReadyState = "complete"
WScript.Sleep 100
Loop
End Sub
参考
'プルダウンメニューを選択
objIE.Document.getElementById(“aetas”).SelectedIndex = “1″
getElementById の ID を調べるには
・
・
・
HTML のソースを調べます。
ブラウザーにある画像の上にマウスカーソルを持っていき、テキストが表示されれば、
<img alt> の可能性があります。
メニュー(ポップアップ・メニュー)は、ポップアップしたメニューの中の項目を右クリック
して、プロパティ。
<INPUT CLASS="saveButton" TYPE="BUTTON" VALUE="新規実行"
onClick="doSubmit('1')">
は?
関連
←
▼
▲
'*************************************************************************
' <<< [GetWebBrowsers] >>>
'*************************************************************************
Function GetWebBrowsers()
Set browsers = new ArrayClass
Set shell = CreateObject( "Shell.Application" )
For Each window In shell.Windows
If window.name = "Internet Explorer" Then
browsers.Add window
End If
Next
GetWebBrowsers = browsers.Items
End Function
'*************************************************************************
' <<< [GetWebBrowser] >>>
'*************************************************************************
Function GetWebBrowser( URL )
browsers = GetWebBrowsers()
For Each browser In browsers
opened_URL = browser.LocationURL
If StrCompEx( opened_URL, URL, Empty ) = 0 Then
Set GetWebBrowser = browser
Exit Function
End If
Next
Raise E_PathNotFound, "<ERROR msg=""指定した URL を開いている Internet Explorer が見つかりません。"">"+ _
GetEchoStr( URL ) +"</ERROR>"
End Function
指定した URL を開いている Internet Explorer オブジェクトを取得する
←
▼
▲
Sub WaitForNavigateIE( ie )
Do While ie.Busy = True or ie.readystate <> 4
WScript.Sleep 100
Loop
Do Until objIE.document.ReadyState = "complete"
WScript.Sleep 100
Loop
End Sub
←
▼
▲
Sub WebBrowser::Navigate( URL as string )
指定した URL を開きます。
参考
←
▼
▲
Set g_sh = WScript.CreateObject("WScript.Shell")
WScript.Echo g_sh.RegRead( "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\"+_
"Explorer\Shell Folders\My Pictures" )
g_sh.RegWrite "HKEY_CURRENT_USER\Software\_Test\Sample", "Value1", "REG_SZ"
WScript.Echo g_sh.RegRead( "HKEY_CURRENT_USER\Software\_Test\Sample" )
g_sh.RegDelete "HKEY_CURRENT_USER\Software\_Test\Sample"
g_sh.RegDelete "HKEY_CURRENT_USER\Software\_Test\" '// キーを削除するときは末尾に \
レジストリのパスが間違っていると、80070002 エラーになります。
レジストリに読み書きできます。
WScript.Shell クラス
StdRegProv クラス
アクセス権が無かったときは、下記のエラーになります。
[ERROR](0x80070005) レジストリ キー "HKEY_CLASSES_ROOT\.lbk\" のルートが無効です
[ERROR](70) 書き込みできません
vbslib
RegWrite
関連
64ビット Windows 上で 32ビット・アプリケーションがレジストリにアクセスすると、一部のキーは
リダイレクトされます。
→ 64ビットWindows (WOW64) のレジストリ
←
▼
▲
Windows NT 4.0 Service Pack 4 以降
Distributed Management Task Force (DMTF) が監視する業界標準に基づいている。
スクリプトを使って OS の管理機能にアクセスする。(WIN32 API を使わない)
物理メモリサイズ、プロセス管理、サービス、共有、ネットワーク管理など
参考
レジストリを操作するクラスです。
←
▼
▲
レジストリを操作するクラスです。
.EnumKey
.EnumValues
(他にもあります)
Sub RegEnumKey( Path, out_Keys )
Dim reg, i, root_key
i = InStr( Path, "\" )
Select Case Left( Path, i - 1 )
Case "HKEY_CLASSES_ROOT" : root_key = &h80000000
Case "HKEY_CURRENT_USER" : root_key = &h80000001
Case "HKEY_LOCAL_MACHINE" : root_key = &h80000002
Case "HKEY_USERS" : root_key = &h80000003
Case "HKEY_PERFORMANCE_DATA":root_key= &h80000004
Case "HKEY_CURRENT_CONFIG": root_key = &h80000005
Case "HKEY_DYN_DATA" : root_key = &h80000006
Case Else : Err.Raise &h80070002
End Select
Path = Mid( Path, i + 1 )
Set reg = GetObject("winmgmts:{impersonationLevel=impersonate}!root/default:StdRegProv")
reg.enumkey root_key, Path, out_Keys
End Sub
サンプル
レジストリの Path のキーのサブキーの名前を out_Keys 配列に列挙します。
サブキーが無いときは out_Keys = Null になります。
←
▼
▲
サンプル
Assert get_WMI( Empty, "Win32_TimeZone" ).Bias = 540 '// TZD = +09:00 = 9*60 = 540
TZD = タイムゾーン, TimeZoneDesignator
←
▼
▲
←
▼
▲
セクションの進捗具合をログに出力すると良いでしょう。
新プロセスの出力をファイルに保存、stdout_stderr_redirect 引数
2つのテキストファイルを比較して、異なれば diff ツールを開きます。
プロセスを起動するときのパラメーターをファイルに保存
セクション
←
▼
▲
自動化すると、途中で失敗したときに、また最初から行わなければならないことがあります。
それを避けるため、復元ポイントに到達したことを記録していきます。
処理を続きから実行するかどうかについては、
<CurrentXxx>
<Specification name="(changing)" from="Base" to="New">
<EnvVars current="New" from="Old" to="New"/>
<Regs current="Old" from="Old" to="New"/>
</Specification>
</CurrentXxx>
関連
→ SAU問題 (Set After Use)
<CurrentXxx>
<Specification name="Base">
<EnvVars current="New"/>
<Regs current="New"/>
</Specification>
</CurrentXxx>
定常状態のステータス・ファイル
コミット・ファイル と 代理更新ファイル
Makefile や
活性化状態のステータス・ファイル
MakeRule クラス(vbslib)
を使うと、複雑な依存関係も対処できるでしょう。
を活用して
←
▼
▲
ロールバックとは、時間のかかる処理の途中にある復元ポイントから次の復元ポイントまで実行
する途中でエラーが発生したときに、前の復元ポイントの状態にデータやファイルを戻すことです。
次の復元ポイントまで行う処理を、一時フォルダの中で実行すれば、その一時フォルダを削除する
だけで、復元ポイントまで戻ることができます。
次の復元ポイントまで行う処理によって変更されるファイルの範囲に対して、バックアップを取れば、
リストアするだけで、復元ポイントまで戻ることができます。
復元ポイント1
復元ポイント2
一時フォルダ
バックアップ
エラーが発生したところでプログラムは異常終了させます。 次に起動したときに、一時フォルダや
バックアップの存在などから、復元ポイントの途中であることを検出して、ロールバックしてから、
再度復元ポイントから処理を開始させます。
→ コミット・ファイル と 代理更新ファイル
関連
ロールバック処理は、通常の処理の前に常に行ってください。
場合によっては、通常のロールバック処理より大きな単位のロールバック処理が必要になること
があります(たとえば、リビルド)。 大きな単位のロールバック処理を実現する手段は、MakeFile
で指定したターゲットファイルの一部、またはすべてを削除することなどがあります。
←
▼
▲
GUI でも CUI でも、ユーザーが入力したデータをすべて1つの構造体にまとめます。
階層化やインターフェイスを使って、領域を分割します。
メンバ変数名の先頭に m_ を付けるなどのルールがあれば、検索しやすくなります。
まとめると、現在の設定値を再利用して、差分の入力を自由にカスタマイズできます。
ユーザー入力を自動化すると、差分入力の仕様の変更に弱くなるので、自動化するときは、
構造体にパラメータを指定します。
←
▼
▲
環境変数はグローバルなので扱いにくい場合もあります。
そこで環境変数を VBS のクラスのメンバ変数に入れて、各種自動処理を行います。
←
▼
▲
←
▼
▲
Sub main2( Opt, AppKey )
Dim t0, t1, arr
ReDim arr( 10000000 )
t0 = Timer
CallWithArray arr
t1 = Timer - t0
WScript.Echo FormatNumber( t1, 3 ) & "(sec)" '// 0.000(sec)
t0 = Timer
CallWithByValArray arr
t1 = Timer - t0
WScript.Echo FormatNumber( t1, 3 ) & "(sec)" '// 0.753(sec)
t0 = Timer
LetArray arr
t1 = Timer - t0
WScript.Echo FormatNumber( t1, 3 ) & "(sec)" '// 0.783(sec)
End Sub
Sub CallWithArray( arr )
End Sub
Sub CallWithByValArray( ByVal arr )
End Sub
Sub LetArray( arr )
Dim b : b = arr
End Sub
配列を渡すとき、ByVal を付けるとコピーが発生して遅くなります。
ByVal が無ければ、一瞬で渡ります。
関連
←
▼
▲
ReDim Preserve arr( UBound( arr ) + 1 )
arr( UBound( arr ) ) = 1234
上記のように、1要素ずつ増やすと、処理速度はかなり遅くなります。
Sub T_AddToFastUBound_Speed( Opt, AppKey )
Const n = 100000
'//=== pre ReDim
ReDim arr(-1)
t0 = Timer
ReDim Preserve arr( n )
For i=0 To n
arr( i ) = i
Next
t1 = Timer - t0
WScript.Echo "1. "+ FormatNumber( t1, 3 ) & "(sec)" '// 0.016(sec)
Assert UBound( arr ) = n
For i=0 To n : Assert arr( i ) = i : Next
'//=== ReDim each add
ReDim arr(-1)
t0 = Timer
For i=0 To n
ReDim Preserve arr( UBound( arr ) + 1 )
arr( UBound( arr ) ) = i
Next
t1 = Timer - t0
WScript.Echo "2. "+ FormatNumber( t1, 3 ) & "(sec)" '// 0.152(sec)
Assert UBound( arr ) = n
For i=0 To n : Assert arr( i ) = i : Next
'//=== arr_fast_ubound : +1
ReDim arr(-1)
t0 = Timer
arr_fast_ubound = UBound( arr )
For i=0 To n
If UBound(arr) <= arr_fast_ubound Then _
ReDim Preserve arr( ( arr_fast_ubound + 100 ) * 4 )
arr_fast_ubound = arr_fast_ubound + 1
arr( arr_fast_ubound ) = i
Next
ReDim Preserve arr( arr_fast_ubound )
t1 = Timer - t0
WScript.Echo "3. "+ FormatNumber( t1, 3 ) & "(sec)" '// 0.043(sec)
Assert UBound( arr ) = n
For i=0 To n : Assert arr( i ) = i : Next
'//=== arr_fast_ubound : +plus
ReDim arr(-1)
plus = +1
t0 = Timer
arr_fast_ubound = UBound( arr )
For i=0 To n
If UBound(arr) < arr_fast_ubound + plus Then _
ReDim Preserve arr( ( arr_fast_ubound + plus + 100 ) * 4 )
arr_fast_ubound = arr_fast_ubound + plus
arr( arr_fast_ubound ) = i
Next
ReDim Preserve arr( arr_fast_ubound )
t1 = Timer - t0
WScript.Echo "4. "+ FormatNumber( t1, 3 ) & "(sec)" '// 0.055(sec)
Assert UBound( arr ) = n
For i=0 To n : Assert arr( i ) = i : Next
'//=== ArrayClass
Set arrc = new ArrayClass
t0 = Timer
For i=0 To n
arrc.Add i
Next
t1 = Timer - t0
WScript.Echo "5. "+ FormatNumber( t1, 3 ) & "(sec)" '// 0.273(sec)
Assert UBound( arrc.Items ) = n
For i=0 To n : Assert arrc.Items( i ) = i : Next
'//=== ArrayClassFastUBound
Set arrc = new ArrayClassFastUBound
arrc.StartFastUBound
t0 = Timer
For i=0 To n
arrc.AddToFastUBound i
Next
arrc.EndFastUBound
t1 = Timer - t0
WScript.Echo "6. "+ FormatNumber( t1, 3 ) & "(sec)" '// 0.133(sec)
Assert UBound( arrc.Items ) = n
For i=0 To n : Assert arrc.Items( i ) = i : Next
'//=== Dictionary
Set arrc = CreateObject( "Scripting.Dictionary" )
t0 = Timer
For i=0 To n
arrc.Add i, Empty
Next
t1 = Timer - t0
WScript.Echo "7. "+ FormatNumber( t1, 3 ) & "(sec)" '// 0.215(sec)
Assert arrc.Count = n + 1
i=0 : For Each an_item In arrc.Keys : Assert an_item = i : i=i+1 : Next
'//=== FastListATestClass
If False Then '// This code raises exception
Set arrc = new FastListATestClass
t0 = Timer
For i=0 To n
arrc.AddNotObject i
Next
t1 = Timer - t0
WScript.Echo "8. "+ FormatNumber( t1, 3 ) & "(sec)" '// 0.387(sec)
Assert arrc.Count = n + 1
i = n : Set element = arrc.First : Do Until element is Nothing
Assert element.Item = i
Set element = element.Next_ : i=i-1
Loop
End If
End Sub
→ T_Arr.vbs # [T_AddToFastUBound_Speed]
下記のコードと、そのコメントにある計測結果の時間を参考に、高速化してください。
pre ReDim が最速ですが制限があり、arr_fast_ubound が汎用的に使えます
参考
1. 0.016(sec) : pre ReDim
2. 0.152(sec) : ReDim each add
3. 0.043(sec) : arr_fast_ubound : +1
4. 0.055(sec) : arr_fast_ubound : +plus
5. 0.273(sec) : ArrayClass
6. 0.133(sec) : ArrayFastClass
7. 0.215(sec) : Dictionary
8. 0.387(sec) : FastListATestClass