R:\home\mem_cache\MyDoc\src\vbslib new\_src\vbslib.svg *********************************************************************** <<< vbslib6 >>> *********************************************************************** vbslib6 - shorthand library for vbscript - 5.93 interim version 2017/ 3/20 VBScript (WSH) 言語を、バッチファイルのように簡単に使えるようにするスクリプト・プログラミング・ ライブラリーです。 vbslib を使ったスクリプトは、インストールしなくても、 コピーするだけ で使える ようになります。 また、スクリプト・ファイルへのオプション付きショートカットを作成するだけで、 エラーが発生した場所を デバッガー で確認できるように VBScript を拡張しており、定型作業の 自動化やテスト駆動開発(TDD)が快適に行えるようになります。 サンプル 解説 → スクリプトを作成する Sub Main( Opt, AppKey ) echo "Hello, world!" End Sub Main echo sample.vbs テキスト・エディターで編集 ダブルクリックで実行 ダウンロード → vbslib ホームページ for Windows 7 / 8 / 10 (32bit/64bit) → vbslib - Git Hub (開発中) 初めて使ってみるときは、 vbslib Prompt.vbs をダブルクリックしてください。 (help) インストール → はじめに → エディター等の変更 → デバッガー → アンインストール 画面で見るマニュアル vbslib ヘルプ vbslib のマニュアル(本書)です → 目次 VBScript (WSH) vbslib のプログラミング言語 VBScript の説明です バッチファイル コマンドラインやバッチファイルの説明です。 参考 → Microsoft スクリプト センター TechNet (Web) ライセンス vbslib は、修正BSDライセンスであり、無料でお使いいただけますが、無保証です。 再頒布や加工も vbs ファイルに書かれた下記を削除しなければ自由にできます。 商用利用可。 vbslib を参考にして作成したスクリプトやライブラリの著作権は、あなたにあります。 パッケージには、GPL ライセンスのプログラムを scriptlib\GPL フォルダーなどに含んでいます。 '* VBScript ShortHand Library (vbslib) '* vbslib is provided under 3-clause BSD license. '* Copyright (C) Sofrware Design Gallery "Sage Plaisir 21" All Rights Reserved. 参考 → BSDライセンス - Wikipedia (Web) → GPL のプログラムを含む vbslib の再配布の注意点 サポート先 ソフトウェアデザイン館 Sage Plaisir 21 http://www.sage-p.com/ *********************************************************************** <<< 目次 >>> *********************************************************************** 目次 → はじめに (scriptlib フォルダー) → ショートハンド・プロンプト (Prompt.vbs) → エディター等の設定変更 (setting フォルダー) → vbslib2 から vbslib3 へ移植するには → ユーザーインターフェース → ファイル操作 → プロセス制御と include → 自動テスト → 変数、定数、文字列、配列、日時 → システム、OS、レジストリ → ネットワーク → vbs_inc (vbslib のベース・システム) → バージョン判定、環境変数 → エラー処理 (Err2) → 困ったときは? (デバッグ) Snap Note を使えば _src\vbslib.svg を開くことができ、 本文中の (src) が、ソースへのハイパーリンクになります。 *********************************************************************** <<< はじめに (scriptlib フォルダー) >>> *********************************************************************** はじめに (scriptlib フォルダー) vbslib を使うと、ファイル操作やプログラムの起動などを行う、スクリプトの作成(プログラ ミング)が簡単になり、いろいろなことが自動化できます。 そして、作成したスクリプトを、 起動が素早くできるようになります。 ショートハンド・プロンプト の形式にすれば、スクリプトの scriptlib フォルダーは、メイン・スクリプト・ファイルがあるフォルダーか、その親フォルダー に格納してください。 そこに、vbslib や様々なスクリプト関係のファイルが格納されています。 インストール vbslib や、vbslib を使うスクリプトのインストールは、ダウンロードした圧縮ファイルを解凍 するだけです。 vbslib を内部で使うスクリプトを始めて使う PC でも、vbslib をインストールするプログラム を実行したり、パスを通す設定をしたりする必要はありません。 スクリプト・ファイルと一緒に scriptlib フォルダーをコピーまたは、それらを含むフォルダー をコピーしたり、圧縮ファイルを解凍するだけで、ダブルクリックしてスクリプトを起動できます。 コピー/解凍するだけで、 複雑な処理を自動化 .vbs スクリプト PC + scriptlib デバッガーのインストールについては、 → デバッグ, g_debug 参考 → GPL のプログラムを含む vbslib の再配布の注意点 スクリプトで自動化できること ・ファイルのコピー、移動、削除、開くことの自動化 ・テキスト・ファイル(HTML, XML, CSV, プログラミング言語など)の編集の自動化 ・数値の計算、データの集計の自動化 ・コンパイル、テスト駆動開発(TDD)、問題の検索や通知の自動化 ・バイナリ・ファイルの読み書きの自動化 ・MSオフィスなど ActiveX アプリケーションのファイルの編集を含む処理の自動化 コマンド名は、MS-DOSバッチファイルや Linux シェル標準に準拠しています。 左のツリーを開いてください。いろいろな関数が用意されています。これらの関数や あなたのオリジナルの関数を使ったスクリプトが、インストーラを実行することなく、 コピーするだけで使えるようになります。 vbslib は、テスト駆動開発(TDD)も強力にサポートします。 単純な自動テスト・スクリ プトを作ってから、そのテストが動くためのプログラムを開発するスタイルは、開発の ゴールが明確になり、迷走することが無くなります。 スクリプトを作成する 新規に vbslib を使ったスクリプトを作成するときは、sample.vbs (メイン)と、scriptlib フォルダ を、作業を行う任意のフォルダにコピーしてください。 (この作業は、         の 3 を選んでもできます。) そして、コピーした sample.vbs をテキストエディタ で編集するか、右クリック [ 編集 ] してください。 実行するときは、sample.vbs をダブル クリックしてください。 vbslib を使ったスクリプトは、下記のように vbslib include があります。 vbslib Short Hand Prompt.vbs vbslib のメインフォルダ (任意の作業フォルダ) scriptlib scriptlib samples コピー sample.vbs (メイン) sample.vbs sample.vbs (メイン) (src) Sub Main( Opt, AppKey ) echo "Hello, world!" End Sub '--- start of vbslib include ------------------------------ : (vbslib をインクルードして main を呼び出すコード) Main echo vbslib include とりあえず使ってみるときは、左のツリーにある「ユーザインターフェース」、「ファイル 操作」、「プロセス制御」の章を参照して、sample.vbs を修正してみてください。 vbslib からエディターなどのツールを起動することがありますが、どのツールを使うのか を、選択することができます。 → エディター等の変更 ウィンドウを表示しないときや最小化するときは、 → g_CommandPrompt 作成したスクリプトを ショートハンド・プロンプト にすると使いやすくなります。 作成したスクリプトのデバッグをするときは、 → 困ったときは? (デバッグ) テスト駆動開発(TDD)を行うには、「テスト・プロンプト (Test.vbs)」の章を参照してください。 上記の、scriptlib フォルダがどのように作られているかの詳細について知りたいときは、 「vbs_inc」 と 「setting フォルダ」 の章を参照してください。(中級者以上) 思い通りに動かなかったときは、「デバッグ」 、「困ったときは?」 の章を参照してください。 PCを借りているときは情報漏えいに注意してください。 → テンポラリ フォルダー MS オフィスなどのアプリケーションの操作は、WSH の ActiveX 機能を使ってください。 → オブジェクト、アプリ操作 ログファイルへの出力したいときは、コマンドプロンプトから下記のように入力してください。 safetee はネットから入手してください cscript sample.vbs | safetee -o log.txt ベースとなる VBScript(WSH) は、Windows 2000 から、プリインストールされています。 デバッガは、Visual Studio 2003 以降の Standard 以上または、フルインストールの MS-Office があれば使えます。vbslib のソースは、構造化エディタに対応しています。 .vbs ファイルをダブルクリックしてから実行開始まで時間がかかるときは、ウィルス対策ソフトの スクリプトに関するチェックをしないようにしてください。 チェックをしなくても、Windows のセキュ リティ機能によって、ユーザーの許可無く悪意のあるスクリプトが実行されることはありません。 共有フォルダー(サーバー)にインストールする vbslib を使ったスクリプトは、共有フォルダーに配置して、共有フォルダーから起動する こともできます。 ただし、共有フォルダーにアクセスすると遅い場合があります。 遅くならないように、内部的にスクリプトをローカルのダウンロードして実行することも できます。 下記のフォルダーにあるサンプルを参照してください。 参考 → Samples\DownloadStart フォルダー ダウンロードしたスクリプトは、 テンポラリ・フォルダー の中のフォルダーに格納されます。 そのフォルダーの名前は、スクリプトのタイムスタンプです。 アンインストール vbslib の zip ファイルを展開したフォルダーを削除してください。 上記で説明している scriptlib フォルダーをコピーしていたら、それも削除してください。 PCを借りているときは情報漏えいに注意してください。 → テンポラリ・フォルダー GPL のプログラムを含む vbslib の再配布の注意点 vbslib を再配布する際、vbslib に含まれる GPL のプログラムに注意する必要があります。 ただし、以下の内容は、vbslib 開発者独自の解釈の可能性があります。 vbslib 自体は、修正BSDライセンスなので、再配布は自由ですが、GPL_bin_fullset および、 scriptlib\GPL フォルダーの中に GPL のプログラムが入っているので、そのまま再配布するには GPL の要求(下記★)を満たさなければ、GPL 支持者の反感を買います。 ただし、法的根拠は グレーで、判例もありません。 vbslib のユーザーが、GNUが言う 「GPL と両立しないライセンス」でも配布することができる ことを考慮して、GPL のコードやバイナリーが必要ないときに、すぐに削除できるよう、 GPL_bin_fullset および、scriptlib\GPL フォルダーにまとめています。 なお、vbslib は、修正BSDライセンスであり、GNUが言う 「GPL と両立したライセンス」なので、 vbslib の再配布ができなくなることはありません。 参考 → さまざまなライセンスとそれらについての解説 - フリーソフトウェアファウンデーション (Web) vbslib は、内部で scriptlib\GNU\*\bin に入っている GPL のプログラムをコマンドライン経由で 呼び出し、出力「データ」を使用しています。 このため、GPL の派生プログラムに該当しない (両立する必要がない、ライセンスが伝播しない)ものと考えています。 参考 → GNUライセンスに関してよく聞かれる質問 - フリーソフトウェアファウンデーション (Web) また、GPLと両立しないパッケージでも、 GPL のプログラムを同梱することができます。 ただし、GPL のソフトは、それ単体で GPL で使用できる形でリリースされる必要があります。★ 具体的には、_src\GPL フォルダーに GPL のソフトをそのまま格納し、README にその場所を 書いています。 参考 → GNUライセンスに関してよく聞かれる質問 - フリーソフトウェアファウンデーション (Web) 簡易 vbslib リンク 機能 メイン.vbs は、scriptlib フォルダが入っているフォルダ(上記の場合はScriptA フォルダ) のサブフォルダーに置くこともできます。 逆に言えば、scriptlib フォルダを、親フォルダに 移動することができます。 よって、ScriptA フォルダの中ならどこでも、scriptlib フォルダ にある vbs ファイルの機能を使うことができます。 メイン.vbs のファイル名を変えることはできますが、scriptlib フォルダの名前を変えること はできません。(すべての vbs ファイルの g_vbslib_path 変数を変えない限り。) vbslib include vbslib include は、vbslib などのライブラリを使えるようにします。 参考 → vbs_inc, vbslib include (vbslib のコア・システム) *********************************************************************** <<< 開発方針 >>> *********************************************************************** 開発方針 ・ユーザーの体験が、シンプル&ビジュアルであること ・検索可能なサンプルからコピーして、見よう見真似で、すぐに試せること ・結果が同じであれば、エラーにしないこと(宣言型プログラミング)。   例:ファイルが無いパスを指定して削除したとき ・タイプミスは、未宣言エラーではなく設定値参照で見つける … 例: /g_debug オプション ・結果がユーザーの想定外になるときは、仕様の通りであっても失敗したと伝えること ・対処法は、概念を介して説明するのではなく、サンプルを使ってダイレクトに示すこと ・エラーが発生して復帰するまでは、次のエラーが発生しても、最初のエラーを表示すること ・ユーザーから見ると意味が異なる、ボトムアップから定義された用語は使わないこと ・略語は標準化されたもののみ。 データ(名詞)か処理(動詞)の区別を明示すること。 ・同じ機能が既存の技術にあれば、操作方法(コマンド名など)をそれに合わせること *********************************************************************** <<< ショートハンド・プロンプト (Prompt.vbs) >>> *********************************************************************** キーワード: STH ショートハンド・プロンプト (Prompt.vbs) → vbslib に付属のアプリケーション → ショートハンド・プロンプト → ショートカットやバッチファイルなどから実行する vbslib に付属のアプリケーション vbslib は、すぐに使えるちょっとしたアプリケーションを提供しています。 vbslib Prompt 1. ヘルプ(SVG形式)の表示 (Google Chrome や Snap Note で見えます) 2. ヘルプ(Internet Explorer - VML形式)の表示 3. ■ vbs ファイルを新規作成する [MakeNewScript] 4. ショートハンド・プロンプトを新規作成する [MakeNewPrompt] 5. タブ文字と空白文字を変更する [SpaceToTab] 6. Test テンプレート・フォルダーを開く [test] 7. 最新の vbslib に変換する [ConvertToNewVbsLib] 8. このプロンプトのソースを開く 9. vbslib フォルダーを開く 番号またはコマンド > 1つは、スタート・メニューから選ぶように、vbslib Prompt.vbs ファイルをダブルクリックして 起動する形式のアプリケーションです。(ショートハンド・プロンプト形式) → ショートハンド・プロンプト (vbslib Prompt.vbs) (vbslib付属) → ショートハンド・プロンプト (ライブラリ) もう1つは、特定のフォルダーに .vbs ファイルをコピーして、そのフォルダーに対する処理を するスクリプト・ファイル形式のアプリケーションです。 スクリプト・ファイル形式のアプリ ケーションを、ショートハンド・プロンプトにまとめることも簡単にできます。 → スクリプト・データ・ファイル (vbslib付属) ショートハンド・プロンプト ショートハンド・プロンプト(CUI)から、コマンドを入力すると、特別に用意されたスクリプトを素早く 起動することができます。 ドキュメントにコマンド名を書くと便利になります。 家計簿.vbs ↓ ダブルクリックすると開く 家計簿プロンプト 1. 今月の家計簿ファイルを開く [op] 2. バックアップする [bk] 3. 家計簿フォルダーを開く [fo] 番号またはコマンド >op ← 番号またはコマンドを入力する op → ショートハンド・プロンプトの活用 … バッチ・ファイル等から起動する → MakeNewPrompt コマンド … ショートハンド・プロンプトを、新規作成する → InputCommand 関数 … ショートハンド・プロンプトを起動する関数 参考 → コマンド・プロンプトが嫌いな人でも使える CUI とは (Web) *********************************************************************** <<< vbslib に付属のショートハンド・プロンプト (vbslib Prompt.vbs) >>> *********************************************************************** vbslib に付属のショートハンド・プロンプト (vbslib Prompt.vbs) vbslib Prompt.vbs ファイルをダブルクリックすると、スクリプトの開発を支援する スクリプトを起動することができます。 下記のようにメニューが表示されるので、番号を入力 してください。 また、メニューに表示されていないコマンドを入力することもできます。 初めて使ってみるときは、3 を選んで、簡単なスクリプトを動かしてみましょう。 vbslib Prompt.vbs ↓ ダブルクリックすると開く vbslib - Short Hand Library 1. ヘルプ(SVG形式)の表示 (Google Chrome や Snap Note で見えます) 2. ヘルプ(Internet Explorer-VML形式)の表示 3. ■ vbs ファイルを新規作成する [MakeVbsLibSample] 4. エディターなど外部プログラム設定 [Setting] 5. ショートハンド・プロンプトを新規作成する [MakeNewPrompt] 6. Test テンプレート・フォルダーを開く 8. このプロンプトのソースを開く 9. vbslib フォルダーを開く 番号またはコマンド >3 3. ■ vbs ファイルを新規作成する [MakeVbsLibSample] 3 「3. vbs ファイルを新規作成する」を選ぶと、下記ような内容のファイルができます。 sample.vbs 解説 → スクリプトを作成する Option Explicit Sub main2( Opt, AppKey ) echo "Hello, world!" End Sub 左のツリーを展開すると、使えるコマンドの詳細を見ることができます。 (現在のページに対応する左のツリーの表示は、ページの左上外にある 「←」 を押してください) 例: → FindFile → grep → Shutdown → GetHash → fdiv → ReplaceSymbols → Translate → CreateTask → CutSharpIf コマンド名は、大文字と小文字を区別しません。 つまり、コマンド名の大文字の文字が小文字に なっていたとしても起動できます。 コマンドの速記形を追加したり、独自のコマンドを追加したり、処理内容をカスタマイズしたりする ことができます。 → ショートハンド・プロンプトの活用 *********************************************************************** <<< ショートハンド・プロンプトの活用 >>> *********************************************************************** ショートハンド・プロンプトの活用 特別なスクリプトを起動するために、キーボードからコマンドを入力できる状態であることを示す 記号、またはそのウィンドウを、「ショートハンド・プロンプト」と呼びます。 特定の目的を達成するために作成した多くのスクリプトを、1つのスクリプト・ファイルにまとめた ものが、ショートハンド・プロンプトのスクリプト・ファイルです。 Prompt.vbs ↓ ダブルクリックすると開く ------------------------------------------------------------------------------- Short Hand Prompt 1. RunProgram 2. InvestigateLog 他. Document.svg を参照 (Google Chrome や Snap Note で見えます) 番号またはコマンド >2 ------------------------------------------------------------------------------- ログ・ファイルのパス >C:\Log\Test_log.txt Test_log_summary.html を出力しました。 2 C:\Log\Test_log.txt 上記の黄色い部分が、ユーザーが入力する部分です。 コマンド名は、大文字と小文字を区別しません。 つまり、コマンド名の大文字の文字が小文字に なっていたとしても起動できます。 コマンドを入力した後、パラメーターやファイルへのパスの入力を求められることがあります。 パスは、ファイルをプロンプトにドラッグ&ドロップすることでも入力できます。 → 画面で見るマニュアル とのコラボレーション → メニュー項目やコマンド名(の速記形)をカスタマイズする → ショートカットやバッチファイルなどから専用コマンドを実行する → cscript 環境変数を使ったバッチファイル → エラーの原因がスクリプトの内容にあると疑われるとき → 既存のプログラムを使いやすくする → サンプル コード (InputCommand) 画面で見るマニュアル とのコラボレーション 入力できる専用コマンドは、多くの場合、アプリケーションのマニュアルに書かれています。 自分がしたいことをマニュアルの目次から見つけたら、その本文から専用コマンドを探してください。 画面で見るマニュアルを見ているのなら、専用コマンドをコピー&ペーストできます。 ただし、 ペーストするときは、右クリックして [ 貼り付け ] をクリックしてください。 よく使うコマンドは、Snap Note のノート・バーなどに一時的に貼り付けておくと便利に使えます。 画面で見るマニュアル テンポラリ・フォルダー vbslib を使ったスクリプトを実行すると、その実行のために内部的に必要になる ファイルが、テンポラリ・フォルダーに作られることがあります。 テンポラリ・フォルダーを開く Prompt.vbs OpenTemp ここを選択して、右クリックして [ コピー ] をクリック、 Prompt.vbs をダブルクリックして表示されるショートハンド・プロンプトを、 右クリックして [ 貼り付け ] マニュアルを作成するときは、ユーザーがしたいこと(ユースケース)ごとの章と、コマンドごとの 章(索引)の両方を用意するとよいでしょう。 メニュー項目やコマンド名(の速記形)をカスタマイズする スクリプトファイル (Prompt.vbs) をテキスト・エディターで編集すれば、よく使うコマンドをメニュー 項目に追加したり、よく使うコマンドの名前を短くすることができます。 カスタマイズするには、InputCommand 関数に指定するパラメーターを編集してください。 参考 → サンプル コード (InputCommand) ショートカットやバッチファイルなどから専用コマンドを実行する ショートハンド・プロンプトが開くアプリケーション(*.exe, *.vbs など) を、マウスの右ボタンで ドラッグ&ドロップして [ ショートカットをここに作成 ] を選ぶと、ダブルクリックするだけで すぐに専用コマンドを起動できるようにできます。 マウスの右ボタンでドラッグ&ドロップして [ ショートカットをここに作成 ] Prompt - ショートカット ショートカットを右クリックして [ プロパティ ] で、リンク先を修正。 リンク先: (簡易) "C:\Fo\Prompt.vbs" GetHash "C:\Fo\Prompt.vbs" GetHash ↑専用コマンド名 リンク先: (厳密) cmd.exe /K (%cscript% //nologo "C:\Fo\Prompt.vbs" CommandA "C:\Log\file.txt") cmd.exe /K (%cscript% //nologo "C:\Fo\Prompt.vbs" CommandA "C:\Log\file.txt" ↑ cmd.exe /K が必要な場合もある ↑専用コマンド名 ↑パラメーター %cscript% については、 → cscript 環境変数 パラメーターを並べていくことで、ユーザーの入力を自動的にできます。 "" を指定すると Enter のみの入力もできます。 ただし、「リンク先」の先頭に cmd.exe が必要です。 " や \' を VBScript に渡すときは、右のリンク先に示す逆変換が必要です。 cmd.exe があると、専用コマンドが終了してもウィンドウが閉じなくなり、結果を確認できます。 /K を /C に変えると、ウィンドウが自動的に閉じるようになります。 \' → " の変換の詳細 → ウィンドウが開いてしまうとき こうしてできたショートカット・ファイルをダブルクリックすると、専用コマンドがすぐに実行されます。 ファイルの関連付けに設定すれば、ファイルをダブルクリックして実行することもできます。 一般のコマンドプロンプトや、バッチファイルなどから、専用コマンドを実行するときは、 → cscript 環境変数 ショートハンド・プロンプトの .vbs スクリプトをバッチファイルなどから起動した場合、実行が 完了したら、そのプロセス(ショートハンド・プロンプト)は終了します。 関連 → ショートハンド・プロンプトのテスト サンプル → Samples\BatchFiles フォルダー cscript 環境変数を使ったバッチファイル 一般のコマンドプロンプトや、バッチファイルなどから、専用コマンドを実行することもできます。 ただし、cmd.exe を使わないで、cscript.exe を使ってください。 64ビットWindows にも対応する には、下記のように cscript 環境変数の値が変わるようにして、cscript 環境変数を使って .vbs ファイルを起動してください。 できれば、VBScript を使って、Prompt.vbs の内容を参考にして、関数を直接呼び出すように してください。 / から始まるオプションは、全てのパラメーターの後に指定してください。 これは、/ から始まる Linux のパスもパラメーターに指定できるようにするためです。 sample.bat @echo off if "%ProgramFiles(x86)%" == "" set cscript=cscript if not "%ProgramFiles(x86)%" == "" set cscript=%windir%\SysWOW64\cscript.exe %cscript% //nologo Prompt.vbs CommandA "C:\Log\file.txt" /option:1 pause %cscript% //nologo CommandA "C:\Log\file.txt" Prompt.vbs の CommandA 関数を呼び出します。 CommandA 関数の中で、input 系の 呼び出しが1つのときは、パラメーターは "C:\Log\file.txt"、残りの /option:1 はオプション。 エラーの原因がスクリプトの内容にあると疑われるとき エラーが発生したときに g_debug = 1 を設定するように表示されたら、/g_debug:1 を追加すると、 デバッガーに接続して、エラーが発生した場所を確認することができます。 cscript.exe Prompt.vbs CommandA "C:\Log\file.txt" /g_debug:1 /g_debug:1 参考 → デバッグ, g_debug 既存のプログラムを使いやすくする 使い勝手の悪い専門的なプログラムは、それを支援するスクリプトを vbslib などで作成して、 アプリケーション・プロンプトの形にして、画面で見るマニュアル を用意することで、使いやすく なります。 画面で見るマニュアルから、専用コマンドをコピー&ペーストしたり、ショートカットを作成する ことで、次々と魔術(スクリプト)を繰り出す速記原典(ショートハンド)のように、次々と処理を 起動させることができるようになります。 使いやすさは、CUI や GUI に関わらず、電子マニュアルの構成によって、大きく左右されます。 検索可能なユースケース・ベースのハイパーテキストでできたマニュアルを、Snap Note などで 作成するとよいでしょう。 参考 → InputCommand ショートハンド・プロンプトに入る関数 *********************************************************************** <<< スクリプト・データ・ファイル (vbslib) >>> *********************************************************************** スクリプト・データ・ファイル (vbslib) スクリプト・データ・ファイルは、アプリケーションと関連付けられたデータ・ファイルの ように扱えるスクリプト・ファイルです。 スクリプト・データ・ファイルをテキスト・エディターで 開けば、設定を編集することができ、ダブルクリックすれば、その設定に従ってスクリプトが 起動します。 scriptlib … 中にアプリケーションの本体がある scriptlib フォルダー Sample App.vbs … アプリケーションのデータ 兼 起動アイコン ↓ ダブルクリックすると開く ---------------------------------------------------------------------- Short Hand Prompt 1. RunProgram 2. InvestigateLog 番号またはコマンド >2 スクリプト・データ・ファイルをコピーしたときに、もし起動できなかったときは、アプリケー ションの本体が入った scriptlib フォルダーが親フォルダー(または、その親フォルダー、…) に存在しない可能性があります。 そのときは、scriptlib フォルダーもコピーしてください。 スクリプト・データ・ファイルの内容は、おおよそ、下記のようになっています。 データ部分は、 XML形式、 ini 形式、 JSON 形式、 CSV 形式 など、アプリケーションによって 形式が異なります。 どの形式であるかは、データ部分の最初と最後の行の行末にある [ ] で囲まれた部分を参考に判断できます。 下記の場合、[FileInScript.xml] なので、 XML 形式です。 ただし、どの形式でも、行頭に ' が必要です。(VBScript の言語仕様のため) データ部分の最初と最後の行は、変更しないでください。 関連付け部分は、アプリケーションと関連づけの設定があります。 下記の場合 Sample_App 関数がアプリケーションです。 関数の引数は変えないでください。 Sample App.vbs '---------------------------------------------[FileInScript.xml] ' ' ' '--------------------------------------------[/FileInScript.xml] Sub Main( Opt, AppKey ) Sample_App AppKey, new_FilePathForFileInScript( Empty ) End Sub '--- start of vbslib include ------------------------------ : (vbslib をインクルードして main を呼び出すコード) データ部分 Main Sample_App new_FilePathForFileInScript 関連付け部分 vbslib include vbslib が提供するスクリプト・データ・ファイルに対応したアプリケーションは下記のものが あります。 例: → CommitCopy → SyncFilesX *********************************************************************** <<< Base64 >>> *********************************************************************** Base64 バイナリーデータを base64 方式のテキストに変換します。 または、その逆変換をします。 番号またはコマンド >base64 --------------------------------------------------------------------------- 1) Base64形式に変換する [Encode] 2) バイナリー・ファイルに戻す [Decode] 番号またはコマンド名>2 入力ファイル(テキスト形式)のパス>C:\input.txt 出力ファイルのパス(上書きします)>C:\output.jpg 出力しました。 base64 参考 → Base64 関連 → new_BinaryArrayFromBase64 → Base64 (BinaryArray) *********************************************************************** <<< BashSyntax >>> *********************************************************************** BashSyntax [ 親: vbslib のショートハンド・プロンプト ] bash シェル・スクリプト・ファイルの " ", ' ', ` ` の対応関係が複数行にまたがっている場所を探します。 番号またはコマンド >BashSyntax シェル・スクリプト・ファイルのパス >sample.sh " " BashSyntax sample.sh ソース → vbslib Prompt.vbs *********************************************************************** <<< CheckEnglishOnly >>> *********************************************************************** CheckEnglishOnly 英語以外の文字がファイルに入っていないことをチェックします。 番号またはコマンド >CheckEnglishOnly テキスト・ファイルの中に、英文字以外の文字が含まれるファイルを一覧します。 サブフォルダーも含めてチェックします。 Enter のみ:C:\vbslib\Samples\Translate\SettingForCheckEnglish.ini 設定ファイルのパス> 調べるフォルダのパス>C:\ProjA\src CheckEnglishOnly C:\ProjA\src 参考 → CheckEnglishOnly (exeファイル) 設定ファイル → CheckEnglishOnly 関数 ソース → vbslib Prompt.vbs テスト → T_CheckEnglishOnly.vbs T_CheckEnglishOnly_sth *********************************************************************** <<< CommitCopy >>> *********************************************************************** CommitCopy [ 親: スクリプト・データ・ファイル (vbslib付属) ] CommitCopy は、共有フォルダーにある他の人が編集したファイルを上書きしないように排他制御 しながら、前回同期した内容と同じときだけ、上書き同期コピー(コミット/更新)をします。 SubVersion のようなサーバーは必要なく、単純なファイル・プロトコル(SMB)を使用し、 共有フォルダーに謎のファイルを作りません。 排他制御も行います。 コミット(共有フォルダーを変更)したら、_history\(現在日時) フォルダーにコピーが作られます。 他の人も編集していたときは、マージする必要があるファイルをワーク・フォルダーに作ります。 同期 ワーク・フォルダー 共有フォルダー (ローカルPC内) (ファイル・サーバー内、ローカルも可) 同期するファイル 同期するファイル 同期するフォルダー 同期するフォルダー … メイン・スクリプト … 変更されたら作られる _CommitCopy.vbs _history scriptlib … 親フォルダーにあってもよい 2014-01-01T12:00:00 (start) _synced … 前回の同期のフォルダー 2014-01-01T12:00:00 userA 2014-01-02T12:00:00 userB 前回同期したファイル history.xml 前回同期したフォルダー … 変更されたら作られる _history 2014-01-01T12:00:00 (start) 2014-01-01T12:00:00 userA history.xml 初めて使うときの画面: 共有フォルダー:(PC01) \\PC01\folder\share 1 .チェックアウト(ワーク・フォルダーへコピー) [CheckOut] 3. 排他制御のテスト [TestMutex] 4. ワーク・フォルダーを開く [OpenWork] 5. 共有フォルダーを開く [OpenShare] 6. 前回の同期のフォルダーを開く [OpenSynced] 使い方は下記。 前回の同期のフォルダーが無いときにこの画面になります。 初めて使うサーバーでは、複数のローカルPCから、TestMutex を実行してください。 2回目以降の画面: 共有フォルダー:(PC01) \\pc01\folder\share 2. 比較 [Compare] 4. ワーク・フォルダーを開く [OpenWork] 5. 共有フォルダーを開く [OpenShare] 6. 前回の同期のフォルダーを開く [OpenSynced] 7. 更新(ワーク・フォルダーへコピー) [Update] 8. コミット(共有フォルダーへコピー) [Commit] 9. 前回の同期をコピーして更新 [UpdateForMerge] 使い方 1. Samples\CommitCopy フォルダー にある _CommitCopy.vbs ファイル と、その親の親 フォルダーにある scriptlib フォルダー を、ローカル PC の新しいフォルダー(ワーク ・フォルダーに相当)にコピーします。 なお、scriptlib フォルダーは、_CommitCopy.vbs ファイルがあるフォルダーの親フォルダーに置くこともできます。 scriptlib _CommitCopy.vbs 2. _CommitCopy.vbs ファイルをテキスト・エディターで開き、XML 形式の設定を 編集して保存します。 参考:下記 3. 新しく共有フォルダーを作成するときは、共有フォルダーを作成して、その中にファイル をコピーしてください。 4. _CommitCopy.vbs ファイルをダブルクリックすると、アプリケーションが起動します。 初めて使うときは、チェックアウトを選んでください。 サンプル _CommitCopy.vbs '---------------------------------------------[FileInScript.xml] ' '--------------------------------------------[/FileInScript.xml] Sub Main( Opt, AppKey ) CommitCopy_App AppKey, new_FilePathForFileInScript( Empty ) End Sub '--- start of vbslib include ------------------------------ : (vbslib をインクルードして main を呼び出すコード) vbslib include → スクリプト・データ・ファイル (vbslib) XML 形式に設定可能な項目 share_folder_path 共有フォルダーのパス work_folder_path ワーク・フォルダーのパス。デフォルトは、カレント・フォルダー name プロンプトの中の共有フォルダーのパスの前に表示される内容。 デフォルトは、"CommitCopy" is_history_in_share 共有フォルダーに _history フォルダーを作るかどうか。 "yes" or "no"、デフォルトは "no" 履歴フォルダー 前回のコミットと異なるファイルまたはフォルダーのコピーを履歴フォルダーに格納します。 前回のコミットと同じファイルやフォルダーは入りません。 更新(Update や UpdateForMerge コマンド)では、履歴フォルダーを更新しません。 履歴は、history.xml ファイルに記録されます。 ファイルまたはフォルダーの一覧が確認できます。 ファイルまたはフォルダーが削除されたことは、history.xml ファイルから分かります。 手動で XML 形式のコメント を書くことができます。 フォルダー名は、W3CDTF 形式の現在日時とコミットしたユーザー名です。 ユーザー名は、CommitCopyUI_Class::UserName で、デフォルトは、 %USERDOMAIN%\%USERNAME% です。 共有フォルダーの直下のフォルダーの中の一部が異なっていても、直下のフォルダー 全体のコピーが作られます。 サンプル history.xml entity は、ファイルまたはフォルダーが入っている _history フォルダーの中のフォルダー 名です。 ソース → CommitCopy フォルダー → CommitCopyLib.vbs テスト → T_CommitCopyUI.vbs 関連 → CopyNotOverwriteFileClass → SynchronizeFolder → DeleteSameFileClass → SyncFilesMenu → RepliCmp → 競合しないように編集する *********************************************************************** <<< ConvertDocumetCommentFormat >>> *********************************************************************** [ 親: vbslib のショートハンド・プロンプト ] ConvertDocumetCommentFormat プログラムのソースファイルの中にある、ドキュメントに変換できるコメントの形式を変換 します。 番号またはコマンド >ConvertDocumetCommentFormat プログラムのソースファイルの中にある、ドキュメントに変換できるコメントの 形式を変換します。 変換する前のソースが入ったフォルダー >C:\src 変換後のソースを入れるフォルダー(★上書きします)>C:\out Enter のみ: NaturalDocs 1. C言語の NaturalDocs [NaturalDocs] 変換前のコメント形式 > Enter のみ: ${vbslib}\Samples\DocComment\doxygen.xml 出力するコメントのテンプレートが書かれたファイルのパス > ConvertDocumetCommentFormat C:\src C:\out 現在、C言語の NaturalDocs 形式コメントから、doygen (Javadoc)形式コメントへの変換の 一部のみ可能です。 サンプル → T_ConvertDCF フォルダー テンプレートの一部を示します。 上記のテンプレートは、Text タグの id 属性が Function なので、以下のようにキーワード が Function に指定された NaturalDocs 形式コメントが適用対象です。 NaturalDocs 形式コメントの例: /******************************************************** * Function: SampleFunction * This is a brief. * * Arguments: * Source - Input * Destination - Output * * Return Value: * Error Code. 0=No Error. * * Description: * The output from . * * Example: * > void main() * > {} *********************************************************/ errnum_t SampleFunction( int Source, int Destination ) { return Source + Destination; } そして、上記のサンプルは、下記に示す doxygen 形式のコメントに変換します。 doxygen 形式コメントの例: /** * @brief This is a brief. * * @param Source Input * @param Destination Output * @return Error Code. 0=No Error. * * @par Description * The output from @ref SampleFunction. * * @par Example * @code * void main() * {} * @endcode */ errnum_t SampleFunction( int Source, int Destination ) { return Source + Destination; } ${Descriptions} は、Return Value: より下の部分に該当します。 行頭に> があると、@code 〜 @endcode で囲みます。 < > で囲まれたキーワードは、@ref (ハイパーリンク) が付きます。 見出しは、@par が付きます。 ソース → vbslib Prompt.vbs → DocComment フォルダー 関連 → ConvertDocumetCommentFormat 関数 *********************************************************************** <<< ConvertToNewVbsLib >>> *********************************************************************** ConvertToNewVbsLib [ 親: vbslib のショートハンド・プロンプト ] スクリプトが使っている古い vbslib を最新の vbslib に置き換えます。 番号またはコマンド >ConvertToNewVbsLib スクリプトが使っている古い vbslib を最新の vbslib に置き換えます。 ver4 → ver5 事前に変換を行うフォルダーの ★バックアップ をとっておいてください。 変換を行うフォルダーのパス >C:\folder ConvertToNewVbsLib C:\folder メイン.vbs の中にある vbslib include のコードを最新版に更新し、 scriptlib フォルダーにある vbs_inc.vbs と vbslib* フォルダーの内容を最新版に更新します。 メイン.vbs かどうかは、拡張子が *.vbs で、ファイルの中に "--- start of vbslib include ---" があるかどうかで判定しています。 vbslib が入っている scriptlib フォルダーかどうかは、指定したフォルダーの中にある scriptlib フォルダーの直下に vbs_inc.vbs ファイルがあるかどうかで判定しています。 scriptlib フォルダーを直接指定することもできます。 ソース → vbslib Prompt.vbs → ToolsLib.vbs テスト → T_VbsLibUpdater.vbs *********************************************************************** <<< CopyOnlyExist >>> *********************************************************************** CopyOnlyExist [ 親: vbslib のショートハンド・プロンプト ] コピー先に存在するファイルだけコピーします。 番号またはコマンド >CopyOnlyExist コピー先に存在するファイルだけコピーします。 コピー先に存在するファイルがコピー元に無いときはエラーになります。 コピー元フォルダのパス>FolderA コピー先フォルダのパス>FolderB CopyOnlyExist FolderA FolderB ソース → vbslib Prompt.vbs テスト → T_CopyOnlyExist フォルダ 関連 → copy_ex 関数 *********************************************************************** <<< CreateFromTextSections >>> *********************************************************************** CreateFromTextSections [ 親: vbslib のショートハンド・プロンプト ] セクション化されたテキストを集めます。 番号またはコマンド >CreateFromTextSections セクション化されたテキストを集めます。 MixedText タグがある XML ファイルのパス >C:\_setup_generated\_TextSectionPath.xml Enter のみ:CreateFile タグに記述されたすべてのファイル MixedText の id 属性 >C_Type 集めたテキストの出力ファイルのパス(★上書きします)>C:\Users\user1\Desktop\a.txt 集めました。 CreateFromTextSections C:\_setup_generated\_TextSectionPath.xml C_Type C:\Users\user1\Desktop\a.txt TextSection タグの path 属性に # があるとき SettingA.xml File1.txt File2.txt 出力内容 First Text _ Second String _ Third Text String _ First Text _ Second String _ Last Text _ First Text _ Third Text String _ Last Text _ # の後は、検索キーワードです _ は空白を表す TextSection タグの path 属性に # があるときは、 構造化テキストフォーマット のページの区切り(空白)をセクションの区切りとして処理します。 セクション化されたテキストのアドレスを、下記のサンプルのような XML で指定してください。 入力した「MixedText の id 属性」が C_Type の場合、/MixedText[@id='C_Type'] が指す XML 要素 の子ノード(TextSection 要素)の path 属性が指すセクションを集めます。 File1.txt などの空白だけの行はセクションの区切りです。 path="File1.txt#Third" の場合、File1.txt ファイルの中をキーワード Third で検索すると Third Text の行がヒットします。 ヒットした行を含むセクションを集めます。 ModuleMixer は、_setup_generated\_TextSectionPath.xml に MixedText タグがある XML ファイル を出力します。 TextSection タグに start_line 属性と end_line 属性があるとき SettingA.xml File1.txt File2.txt 出力内容 A_1 A_2 A_3 A_4 A_5 A_6 B_1 B_2 B_3 B_4 B_5 B_6 A_3 A_4 A_5 B_2 TextSection タグに start_line 属性と end_line 属性があるときは、start_line から end_line に 記述された行番号の範囲のテキストを抽出します。 CreateFile タグがあるとき CreateFile タグがあると、出力ファイルのパスの入力を省略できるようになります。 ソース → vbslib Prompt.vbs 関連 → CreateFromTextSections 関数 *********************************************************************** <<< CreateTask >>> *********************************************************************** CreateTask [ 親: vbslib のショートハンド・プロンプト ] 指定時間に1回だけ実行するタスクを新規に登録します。 番号またはコマンド >CreateTask 指定時間に1回だけ実行するタスクを新規に登録します。 タスク名(任意)>vbslib_test 実行するコマンド>C:\Window\notepad.exe 例: 13:00 ... 今が午前10時なら、今日の午後1時に実行する 例: 1:00 ... 今が午前10時なら、明日の午前1時に実行する 例: +1:00 ... 今から1時間後に実行する いつ実行を開始しますか>+0:01 CreateTask vbslib_test C:\Window\notepad.exe +0:01 ソース → vbslib Prompt.vbs テスト → T_Task フォルダ 関連 → SetTask → OpenTask *********************************************************************** <<< CutComment >>> *********************************************************************** CutComment [ 親: vbslib のショートハンド・プロンプト ] ソース ファイルからコメントを削除します。 番号またはコマンド >CutComment C言語のコメント(/* */ と // )を削除します。 以下にフォルダーのパスを入力すると、*.c, *.h, *.cpp に対して処理します。 ファイルまたはフォルダーのパス(★上書きします)>C:\src CutComment C:\src コメントを削除する前の内容は上書きされて無くなるので、バックアップを取ってから 実行してください。 in_Path にフォルダーを指定したときは、サブ フォルダーも含めて、拡張子が c と h と cpp のファイルを処理対象にします。 /* から */ の間と、// から その行末までを、削除します。 コメントだけからなる行は削除され、それより下の行は上に詰められます。 /* から */ の間が複数行のときにも対応しています。 コメントの中のコメント記号は、正しく無視します。 /* から */ は、ネストしないように扱われます。 サンプル 削除前: 削除後: // This is comment. int g = 0; /**************************** * Function: Sample *****************************/ void Sample() { } int g = 0; void Sample() { } ソース → vbslib Prompt.vbs 関連 → CutCommentC 関数 *********************************************************************** <<< CutLineFeedAtRightEnd >>> *********************************************************************** CutLineFeedAtRightEnd [ 親: vbslib のショートハンド・プロンプト ] コマンドプロンプトの右端からあふれた文字列を1行にまとめます。 番号またはコマンド >CutLineFeedAtRightEnd コマンドプロンプトの右端からあふれた文字列を1行にまとめます。 ファイルのパス>Text.txt Enter のみ:80 1行の幅> CutLineFeedAtRightEnd Text.txt ABCDEFGHIJKLMNOPQRST UVWXYZ END ABCDEFGHIJKLMNOPQRSTUVWXYZ END 参考 → CutLineFeedAtRightEnd ソース → vbslib Prompt.vbs *********************************************************************** <<< CutSharpIf >>> *********************************************************************** CutSharpIf [ 親: vbslib のショートハンド・プロンプト ] #ifdef 〜 #endif をカットします。 番号またはコマンド >CutSharpIf #ifdef 〜 #endif をカットします。 変換するソースファイルのパス >C:\Source.c #define シンボル >MY_PRIVATE 1) 定義されているときのコードを削除する 0) 定義されていないときのコードを削除する 番号を入力してください >1 変換しました。 CutSharpIf C:\Source.c MY_PRIVATE サンプル #ifdef MY_PRIVATE printf( "Private\n" ); #else printf( "Public\n" ); #endif printf( "Public\n" ); 対応: #ifdef 〜 #endif、 #ifndef 〜 #endif、 #if 〜 #endif #ifdef 〜 #else 〜 #endif、 #ifndef 〜 #else 〜 #endif、 #if 〜 #else 〜 #endif 非対応: #elif ソース → vbslib Prompt.vbs テスト → T_CutSharpIf フォルダー 関連 → CutSharpIf 関数 *********************************************************************** <<< DelTemp >>> *********************************************************************** [ 親: vbslib のショートハンド・プロンプト ] DelTemp テンポラリ・フォルダー を削除します。 番号またはコマンド >DelTemp DelTemp ソース → vbslib Prompt.vbs 関連 → OpenTemp *********************************************************************** <<< Diff >>> *********************************************************************** Diff [ 親: vbslib のショートハンド・プロンプト ] 2つ、または3つのテキストファイルの差分を表示します。 参考 → Setting_getDiffCmdLine 使用する Diff ツールの変更 番号またはコマンド >diff [Diff] テキストファイルの比較 フォルダーのパスを指定すると、ファイルへの相対パスのベースフォルダーとして処理し ます。 path1>C:\folder\file1.txt path2>C:\folder\file2.txt Enter のみ : 2つのファイルの比較 path3> diff C:\folder\file1.txt C:\folder\file2.txt SVG ファイルを指定すると、その SVG ファイルは Snap Note から作成されたものとし、 Snap Note の「比較ツール用テキストを出力」した後のテキストを比較します。 フォルダーのパスを指定すると、ファイルへの相対パスのベースフォルダーとして処理します。 下記の場合、C:\FolderA\File.txt と C:\FolderB\File.txt を比較します。 同じベースフォルダーの組み合わせを続けたいときに、毎回2つまたは3つのファイルを 指定する必要が無く、2つまたは3つのフォルダーの中の1つのファイルだけ指定すれば、 比較ができます。 番号またはコマンド >diff [Diff] テキストファイルの比較 フォルダーのパスを指定すると、ファイルへの相対パスのベースフォルダーとして処理し ます。 path1>C:\FolderA path2>C:\FolderB Enter のみ : 2つのファイルの比較 path3> 入力したベースフォルダーの中のファイルを指定してください。 Enter のみ:終了 path>C:\FolderA\File.txt Enter のみ:終了 path> diff C:\FolderA C:\FolderB C:\FolderA\File.txt ソース → vbslib Prompt.vbs 関連 → diff 関数 → ThreeWayMerge 関数 → SyncFilesX ツール → SyncFilesT ツール → Rekisa - テキスト比較ツール → TortoiseMerge - テキスト比較ツール *********************************************************************** <<< Diff1 >>> *********************************************************************** Diff1 テキスト ファイルの 1行を 1文字ずつ比較します。 参考 → Setting_getDiffCmdLine 使用する Diff ツールの変更 番号またはコマンド >Diff1 テキスト ファイルの 1行を 1文字ずつ比較します。 Enter のみ: クリップボードにある2行のテキストを比較する \ のみ: 終了 ファイル 1 > C:\Base.txt 行番号 1 > 2 ファイル 2 > C:\New.txt 行番号 2 > 2 Diff1 C:\Base.txt 2 C:\New.txt 2 一般的な diff ツールを使って、下記のように差分が見つかったとき、 その行に対して Diff1 コマンドを使うと、下記のように表示されます。 ソース → vbslib Prompt.vbs テスト → T_fc_Manually.vbs T_Diff1 → T_AssertFC フォルダー 関連 → GetDiffOneLineCmdLine 関数 *********************************************************************** <<< DiffClip >>> *********************************************************************** [ 親: vbslib のショートハンド・プロンプト ] DiffClip テンポラリ・ファイルを使って、2つ、または3つのテキストの差分を表示します。 参考 → Setting_getDiffCmdLine 番号またはコマンド >DiffClip [DiffClip] テキストの比較 次に表示されるファイルに、比較するテキストの1つ目を保存してください。 続行するには Enter キーを押してください . . . 次に表示されるファイルに、比較するテキストの2つ目を保存してください。 続行するには Enter キーを押してください . . . 2つのファイルの比較ですか[Y/N] 一時的に保存したファイルを削除しますか[Y/N] DiffClip ソース → vbslib Prompt.vbs *********************************************************************** <<< DiffTag >>> *********************************************************************** [ 親: vbslib のショートハンド・プロンプト ] DiffTag diff ツールなどがコンフリクトして出力したタグ付きテキストから、GUI の diff ツールを開きます。 番号またはコマンド >DiffTag ------------------------------------------------------------------------------- diff ツールなどがコンフリクトして出力したタグ付きテキストから、GUI の diff ツー ルを開きます。 タグ付きテキストの例: <<<<<<< Left.txt Left ||||||| Base.txt Base ======= Right >>>>>>> Right.txt 終了するときは、Exit と入力してください。 クリップボードにタグ付きテキストをコピーしたら、Enter を押してください。 DiffTag diff ツールで以下のように表示できます。 ソース → vbslib Prompt.vbs テスト → T_fc.vbs T_DiffTag 関連 → diff → ThreeWayMerge *********************************************************************** <<< DiffWithoutKS >>> *********************************************************************** [ 親: vbslib のショートハンド・プロンプト ] DiffWithoutKS Keyword Substitution の値をカットして、GUI の diff ツールを開きます。 番号またはコマンド >DiffWithoutKS ------------------------------------------------------------------------------- [DiffWithoutKS] テキストファイルの比較、Keyword Substitution の値を削除してから 。 path1>C:\FolderA path2>C:\FolderB Enter のみ : 2つのファイルの比較 path3> DiffWithoutKS デスクトップの _DiffWithoutKS フォルダーを作り、その中に Keyword Substitution を以下のように カットしたファイルをコピーして、Diff ツールを開きます。 Diff ツールについては、 → Setting_getDiffCmdLine → Setting_getFolderDiffCmdLine /************************* * $Rev: 43 $ **************************/ /************************* * $Rev: $ **************************/ 43 参考 → SubVersion - Keyword Substitution ソース → vbslib Prompt.vbs 関連 → DiffWithoutKS 関数 *********************************************************************** <<< DoTextShrink >>> *********************************************************************** DoTextShrink 使用していないセクション(C言語の NaturalDocs で区切ったソース ファイル)を削除します。 番号またはコマンド >DoTextShrink セクション(NaturalDocs で区切ったソース ファイル)のうち、使用していないセクシ ョンを削除します。 .txmx ファイルのパス >Shrink.txmx DoTextShrink Shrink.txmx 参考 → Natural Docs サンプル → T_TextShrink フォルダー .txmx ファイル(設定ファイル)の CallerFile に指定するファイル(ユーザー) void main() { FuncB(); } SourceFile に指定するファイル(入力) shrinked_path に指定するファイル(出力) #include /* * Function: FuncA */ void FuncA() {} /* * Function: FuncB */ void FuncB() {} /* * End of File: */ #include /* * Function: FuncB */ void FuncB() {} /* * End of File: */ /* * Function: FuncA */ void FuncA() {} CallerFile に FuncB があるため、 FuncB のセクションは残ります。 単語単位・大文字小文字区別で判定します。 SourceFile の中の NaturalDocs コメントの中に FuncA があっても、使用していないとして FuncA を 削除します。 最初の NaturalDocs コメントより前と、 File のコメントのセクションと、 End of File のコメントのセクションは、 使用していなくても残ります。 .txmx ファイル(設定ファイル)の例 MainFolder\* CallerFile SourceFile txmx:Project txmx:CallerFile ユーザーのファイルのパス。 複数可能。 vbslib のワイルドカードを指定可能 呼び出し元の関数など。 CallerFile に指定したフォルダーの中に、入力ファイル(SourceFile/@path) があるように設定することもできます。 この場合、入力ファイルはユーザー のファイルではなくなります。 txmx:UseSymbol text() プロジェクトに追加するシンボル。 関数名など。 txmx:SourceFile ユーザーが使用していないセクションを削除する、ファイルに関する設定。 呼び出し先の関数など。 ユーザーが使用しているかどうかは、セクション名がユーザーのファイルに 単語単位・大文字小文字区別で存在するかどうかで判定されます。 @path 入力ファイルのパス。 vbslib のワイルドカードを指定可能 相対パスの基準は、.txmx ファイルがあるフォルダー。 @base_path 入力ファイルのベース フォルダーのパス。 入力ファイルに対応する 出力ファイルを @shrinked_path や @cache_path に指定したフォルダー の中に格納する場所を指す、相対パスを得るために使われます。 @shrinked_path 出力ファイルを格納するベース フォルダーのパス。 省略時は、入力ファイルに出力する。 @cache_path セクションに関する中間ファイルを格納するベース フォルダーのパス 関連 → DoTextShrink 関数 → MakeCrossedOldSections *********************************************************************** <<< doxygen >>> *********************************************************************** doxygen [ 親: vbslib のショートハンド・プロンプト ] ソースファイルのコメントからドキュメントを生成します。 番号またはコマンド >doxygen ソースファイルにあるコメントを HTML に変換します。 ソースファイルがあるフォルダーのパス>C:\src HTML を格納するフォルダーのパス(★上書きします)>C:\_html doxygen C:\src C:\_html コマンドラインから実行 したとき、/silent オプションをつけると、ブラウザーが開かないようになります。 参考 → doxygen ソース → vbslib Prompt.vbs 関連 → MakeDocumentBy_doxygen 関数 → NaturalDocs → ConvertDocumetCommentFormat *********************************************************************** <<< EvaluateByVariableXML >>> *********************************************************************** EvaluateByVariableXML [ 親: vbslib のショートハンド・プロンプト ] ${ } 形式の変数が定義された XML を参考に、テキスト ファイルの中の変数を値に置き換えます。 番号またはコマンド >EvaluateByVariableXML ${ } 形式の変数が定義された XML を参考に、テキスト ファイルの中の変数を値に置き換えます。 変数が定義された XML ファイルのパス> C:\Folder\variable.xml Enter のみ:クリップボードを展開する。 置き換えるテキスト ファイルのパス> C:\Folder\Text.txt 置き換えるテキスト ファイルのパス> ${Var1} ABC EvaluateByVariableXML C:\Folder\variable.xml C:\Folder\Text.txt サンプル variable.xml ファイル ${Var1} ${Var2} 置き換える前の Text.txt ファイル Var1 = ${Var1} Var2 = ${Var2} 置き換えた後の Text.txt ファイル Var1 = ABC Var2 = DEF 参考 → Variable タグ ソース → vbslib Prompt.vbs テスト → T_LazyDictionary.vbs T_EvaluateByVariableXML_sth 関連 → ReplaceSymbols *********************************************************************** <<< fc >>> *********************************************************************** fc [ 親: vbslib のショートハンド・プロンプト ] 2つのテキストファイルを比較します。 参考 → IsSameTextFile 番号またはコマンド >fc [fc] Compare text file path1>C:\folder\file1.txt 入力例: Shift_JIS, EUC-JP, Unicode, UTF-8, UTF-8-No-BOM, ISO-8859-1 Enter のみ : 自動判定 文字コードセット > path2>C:\folder\file2.txt 文字コードセット > same text, same binary. fc C:\folder\file1.txt C:\folder\file2.txt ソース → vbslib Prompt.vbs 関連 → feq *********************************************************************** <<< fdiv >>> *********************************************************************** fdiv [ 親: vbslib のショートハンド・プロンプト ] 大きなファイルを分割します。 結合するバッチファイルも生成します。 番号またはコマンド >fdiv 分割するファイル >C:\folder\file1.txt 分割後の1つのファイル・サイズ(MB) >500 Reading file1.txt ... Writing file1.txt.001 ... Saving file1.txt.001 ... Writing file1.txt.002 ... Saving file1.txt.002 ... CreateFile file1_resume.bat OK. fdiv C:\folder\file1.txt 500 メモリーより大きいファイルには対応していません。 関連 → WriteFromBinaryArray (BinaryArray) ソース → vbslib Prompt.vbs *********************************************************************** <<< feq >>> *********************************************************************** feq [ 親: vbslib のショートハンド・プロンプト ] 2つのバイナリファイル、またはフォルダーが同じかどうかを調べます。 参考 → IsSameBinaryFile 番号またはコマンド >feq [feq] 2つのバイナリファイル、またはフォルダーが同じかどうかを調べます。 path1>C:\folder\file1.txt path2>C:\folder\file2.txt same. feq C:\folder\file1.txt C:\folder\file2.txt ソース → vbslib Prompt.vbs *********************************************************************** <<< FindFile >>> *********************************************************************** FindFile [ 親: vbslib のショートハンド・プロンプト ] find フォルダーの中のファイルを検索します。 番号またはコマンド >FindFile 探す場所(フォルダのパス)>FolderA ファイル名のすべてまたは一部>1 C:\Folder\FolderA\1.txt C:\Folder\FolderA\sub\1.txt FindFile ファイル名を比較対象とします。 ファイルの内容は比較しません。 探す場所を入力するときは、フォルダーをエクスプローラーからドラッグ&ドロップ して入力することもできます。 ソース → vbslib Prompt.vbs テスト → T_FindFile フォルダ 関連 → grep *********************************************************************** <<< FindFile_Install >>> *********************************************************************** FindFile_Install [ 親: vbslib のショートハンド・プロンプト ] フォルダーの右クリック・メニューに、[ ファイル名から検索 ] を追加します。 番号またはコマンド >FindFile_Install ------------------------------------------------------------------------------- フォルダーの右クリック・メニューに、[ ファイル名から検索 ] を追加します。 続行するには Enter キーを押してください . . . FindFile_Install ソース → vbslib Prompt.vbs *********************************************************************** <<< FindFile_Uninstall >>> *********************************************************************** FindFile_Uninstall [ 親: vbslib のショートハンド・プロンプト ] フォルダーの右クリック・メニューから、[ ファイル名から検索 ] を削除します。 番号またはコマンド >FindFile_Uninstall ------------------------------------------------------------------------------- フォルダーの右クリック・メニューから、[ ファイル名から検索 ] を削除します。 続行するには Enter キーを押してください . . . + FindFile_Uninstall ソース → vbslib Prompt.vbs *********************************************************************** <<< GetHash >>> *********************************************************************** GetHash [ 親: vbslib のショートハンド・プロンプト ] GetHashPS ファイルのハッシュ値(MD5など)を表示し、クリップボードに入っているハッシュ値と比較します。 番号またはコマンド >GetHash ------------------------------------------------------------------------------- ファイルのハッシュ値(MD5など)を表示し、クリップボードに入っているハッシュ値と 比較します。 メモリー不足になったときは、GetHashPS コマンドを使ってください。 ファイルのパス>C:\Folder\Sample.zip MD5: 5c1d447971bc0c49f09b2e965ac4ed37 SHA1: 9a2bc4d84e027936ff81b9ddabc453806f768410 SHA256: 0253329bb1c815e1815b0e2e0eadcb8a91e0f322ca38063b8eae4b5264a8457c SHA384: 0ac25937d851e26f3ebc0a9913e62f8dfc70de5305121e9458c28649e0b73101a1d57d34 9dbdedb9dcb3e0ea598608d1 SHA512: 2ceba6d566b4d8155e655470665f86e2c6464e4dfc654fecf5f04e47336857727e813922 b72074425a8f75df7d250fcc0a875aa48dc14dc1fd836e12017b3cf1 RIPEMD160: 04d95f54d38558e9018dcc336a5bfe6d37038808 クリップボードの内容と一致するハッシュ値は、MD5 です。 GetHash C:\Folder\Sample.zip 上記は、クリップボードに、テキスト 5c1d447971bc0c49f09b2e965ac4ed37 が入っているときの 表示です。 GetHash コマンドでメモリー不足になったときは、GetHashPS コマンドを使ってください。 番号またはコマンド >GetHashPS ------------------------------------------------------------------------------- ファイルのハッシュ値(MD5など)を表示し、クリップボードに入っているハッシュ値と 比較します。(大容量ファイル対応版) ファイルのパス>C:\Folder\Sample.zip 1. MD5 2. SHA1 3. SHA256 4. SHA384 5. SHA512 6. RIPEMD160 番号またはコマンド >1 FAB1775D0F32382B07B3763E134E4E63FECA6592 クリップボードの内容と一致しました。 GetHashPS C:\Folder\Sample.zip 1 ソース → vbslib Prompt.vbs 関連 → MD5 (BinaryArray) → GetHashOfFile → MD5List → GetVersionString サンプル *********************************************************************** <<< GetStepPath, GetRelativePath >>> *********************************************************************** GetStepPath, GetRelativePath [ 親: vbslib のショートハンド・プロンプト ] フル・パスから相対パスに変換します。 番号またはコマンド >GetStepPath フル・パスから相対パスに変換します。 フル・パス>C:\FolderA\File.txt 基準フォルダのフル・パス>C:\FolderB ..\FolderA\File.txt GetStepPath C:\FolderA\File.txt C:\FolderB ソース → vbslib Prompt.vbs テスト → T_GetStepPath フォルダ 関連 → GetStepPath 関数 *********************************************************************** <<< GetShortPath >>> *********************************************************************** GetShortPath [ 親: vbslib のショートハンド・プロンプト ] 短いファイル・パス(8.3形式)に変換します。 番号またはコマンド >GetShortPath 短いパス(ファイルやフォルダーの 8.3形式パス)に変換します。 (長い)フル・パス>C:\Documents and Settings\File.txt C:\DOCUME~1\File.txt GetShortPath C:\Documents and Settings\File.txt ソース → vbslib Prompt.vbs *********************************************************************** <<< grep >>> *********************************************************************** grep [ 親: vbslib のショートハンド・プロンプト ] テキストファイルの内容を検索します。 grep は、コマンドプロンプトの find コマンドを内部で使用する場合もあります。 番号またはコマンド >grep [grep] ファイルの中のテキストを検索します 検索対象フォルダー、またはファイル >C:\FolderA 正規表現の メタ文字 一覧:. $ ^ { } [ ] ( ) | * + ? \ キーワード(正規表現)>3\.14 使えるオプション : -u, -i, -l, -L オプション > Enter のみ : 表示のみ 結果の出力先ファイル(上書きします)> >grep -r 3\.14 "C:\FolderA\*" C:\FolderA\readme.txt:13: PI // 3.14 C:\FolderA\RepliCmpLib.vbs:118: PI = 3.1415926535 grep C:\FolderA 3\.14 検索対象がファイルのときは、ファイルのパスを出力しませんが行番号を出力します。 参考 → grep 関数 ソース → vbslib Prompt.vbs テスト → T_Grep.vbs T_grep_sth 関連 → RegExpTest 正規表現でマッチするかどうかをテスト → FindStringLines 関数 → SortLines *********************************************************************** <<< InfiniteLoop >>> *********************************************************************** InfiniteLoop [ 親: vbslib のショートハンド・プロンプト ] CPUを走らせ続けます。 番号またはコマンド >InfiniteLoop Infinite Loop ... CPU に負荷をかけます。 ソース → vbslib Prompt.vbs *********************************************************************** <<< MakeFileList >>> *********************************************************************** MakeFileList フォルダーに入っているファイルの名前の一覧をファイルに保存します。 番号またはコマンド >MakeFileList ------------------------------------------------------------------------------- ファイル名を一覧します。 調べるフォルダーのパス >C:\Folder ファイル リストのファイル パス(出力先)>C:\File.txt 1. 相対パスの一覧 [Step] 2. ツリー形式・ファイルなし [DirTree] 3. ツリー形式・ファイルあり [Tree] 番号またはコマンド名>1 MakeFileList C:\Folder C:\File.txt 1 サンプル 相対パスの一覧 [Step] 1.txt 2.txt Sub Sub\1.txt Sub\2.txt ツリー形式・ファイルなし [DirTree] フォルダー パスの一覧 ボリューム シリアル番号は 00000200 FFFF:0000 です C:\FOLDER \---Sub ツリー形式・ファイルあり [Tree] フォルダー パスの一覧 ボリューム シリアル番号は 00000200 FFFF:0000 です C:\FOLDER | 1.txt | 2.txt | \---Sub 1.txt 2.txt ソース → vbslib Prompt.vbs *********************************************************************** <<< MakeNewPrompt >>> *********************************************************************** MakeNewPrompt [ 親: vbslib のショートハンド・プロンプト ] ショートハンド・プロンプト を新規作成します。 番号またはコマンド >MakeNewPrompt Enter のみ : デスクトップに Prompt.vbs を作成します。 作成するファイルのパス>C:\FolderA\Prompt.vbs MakeNewPrompt C:\FolderA\Prompt.vbs 参考 → InputCommand ソース → vbslib Prompt.vbs スクリプトの記述場所 番号またはコマンド >OpenFolder OpenFolder (例) ショートハンド・プロンプトに入力したコマンドによって、呼ばれる関数は、コマンド名と同じ 名前の関数です。 パラメーターは main と同じく Opt と AppKey で構成されています。 Sub OpenFolder( Opt, AppKey ) Set c = g_VBS_Lib path = InputPath( "ファイルのパス>", c.CheckFolderExists ) Setting_openFolder path End Sub OpenFolder InputPath Setting_openFolder *********************************************************************** <<< MakeNewScript >>> *********************************************************************** [ 親: vbslib のショートハンド・プロンプト ] MakeNewScript メイン・スクリプトを新規作成します。 番号またはコマンド >MakeNewScript ------------------------------------------------------------------------------- ((( [MakeVbsLibSample] ))) どのタイプのファイルを作成しますか 1. シンプル vbslib スクリプト 続行するには Enter キーを押してください . . . 1 Enter のみ : デスクトップに sample.vbs を作成します。 作成するファイルのパス> >copy_ren "samples\sample.vbs", "C:\Users\user1\Desktop\sample.vbs" ------------------------------------------------------------------------------- vbs ファイルを作成しました。 テキスト・エディターで、vbs ファイルの最後にある main2 関数を編集してください。 vbs ファイルをダブルクリックすると編集した内容を実行します。 MakeNewScript ソース → vbslib Prompt.vbs 関連 → MakeNewPrompt *********************************************************************** <<< MD5List >>> *********************************************************************** [ 親: vbslib のショートハンド・プロンプト ] MD5List MD5 リスト を作成またはチェックします。 番号またはコマンド >MD5List ------------------------------------------------------------------------------- ((( [MD5List] ))) 1) [Make] MD5リストを作成します 2) [Check] MD5リストをチェックします 3) [Stamp] MD5リストをチェックしてタイムスタンプを合わせます 4) [Append] MD5リストに追加します 5) [Search] MD5リストの中を検索します 6) [Fragment] _FullSet.txt があるフォルダーから同じ内容のファイルを削除しま す 7) [Defragment] _FullSet.txt があるフォルダーを完全形に復帰します 8) [CopyDiff] MD5 リストを使って差分コピーします 番号またはコマンド >1 調べるフォルダーのパス >C:\Folder MD5 リストのファイル パス(出力先)>C:\MD5.txt タイムスタンプを含めますか[Y/N]y MD5List 1 C:\Folder C:\MD5.txt y → CopyDiff (MD5List) ソース → vbslib Prompt.vbs テスト → T_fc.vbs T_MD5List_Ascii T_MakeFolderMD5List_TimeStamp_EmptyFolder T_MD5List_SearchPrompt T_OpenForDefragment_Prompt 関連 → MD5 リスト → GetHash *********************************************************************** <<< CopyDiff (MD5List) >>> *********************************************************************** CopyDiff (MD5List) [ 親: vbslib のショートハンド・プロンプト ] << MD5List コピー元とコピー先のMD5 リストを使って、ファイルやフォルダーの差分をコピーします。 番号またはコマンド >MD5List 番号またはコマンド >CopyDiff コピー元とコピー先の MD5リストを使って、ファイルやフォルダーの差分をコピーします。 コピー元のフォルダーのパス >C:\FolderA コピー先のフォルダーのパス >E:\USB コピー元の MD5リストのパス >E:\Revision-02.txt コピー先の MD5リストのパス >E:\Revision-01.txt MD5List CopyDiff C:\FolderA E:\USB E:\Revision-02.txt E:\Revision-01.txt 番号またはコマンド >MD5List 番号またはコマンド >CopyDiff コピー元とコピー先の MD5リストを使って、ファイルやフォルダーの差分をコピーします。 コピー元のフォルダーのパス >E:\USB コピー先のフォルダーのパス >C:\BackUp\FolderA コピー元の MD5リストのパス >E:\Revision-02.txt コピー先の MD5リストのパス >E:\Revision-01.txt MD5List CopyDiff E:\USB C:\BackUp\FolderA E:\Revision-02.txt E:\Revision-01.txt MD5リストを使うことで、パッチのように USBメモリーやファイル サーバーを経由して PC 間の差分 コピーをすることができます。 また、下記のステップ1をする PC には、コピー先のフォルダーは、 必要ありません。 コピー元にないコピー先のファイルは削除します。 空フォルダーの作成や、ファイルの削除による空フォルダーの削除も正しく処理します。 C:\FolderA E:\USB C:\BackUp\FolderA 3.txt 3.txt 3.txt 5.txt 5.txt 5.txt ステップ1 2.txt (削除) ステップ2 2.txt (削除) E:\Revision-02.txt E:\Revision-01.txt 60631deb298f23dc7e3a4ada23d8372c 1.txt e53a0a2978c28872a4505bdb51db06dc 3.txt fadc3390060b1ba5ef3bef593b7c930d 4.txt 60631deb298f23dc7e3a4ada23d8372c 5.txt 60631deb298f23dc7e3a4ada23d8372c 1.txt d41d8cd98f00b204e9800998ecf8427e 2.txt 202cb962ac59075b964b07152d234b70 3.txt fadc3390060b1ba5ef3bef593b7c930d 4.txt 3.txt は、MD5 の値が異なるため、コピーします。 5.txt は、コピー元だけにあるパスなので、コピーします。 5.txt は、すでにコピー先のフォルダー にある 1.txt と同じハッシュ値ですが、コピー元のフォルダーからコピーします。 改名しながら コピーすることはできません。 2.txt は、コピー先だけにあるパスなので、削除します。 関連 → CopyDiffByMD5List 関数 *********************************************************************** <<< mkdir >>> *********************************************************************** mkdir [ 親: vbslib のショートハンド・プロンプト ] 深いフォルダーを作ります。または、相対パスを使ってフォルダーを作ります。 番号またはコマンド >mkdir [MkDir] make directory 深いフォルダーを作ります。または、相対パスを使ってフォルダーを作ります。 作成するフォルダーのパス、または、相対パスの基準フォルダ >C:\FolderA 作成するフォルダの相対パス >a\b Open folder "C:\FolderA\a\b" mkdir C:\FolderA a\b 「送る」 メニューから mkdir コマンドを使えるようにするには vbslib Prompt.vbs ファイルへのショートカット・ファイルを OpenSendTo で表示されるフォルダー の中に作成して、ショートカット・ファイルのファイル名を 「mkdir」 に変えて、ショートカット・ ファイルを右クリック [ プロパティ > リンク先 ] の先頭に、「wscript」と空白文字、末尾に 空白文字と 「mkdir」 を入力してください。 wscript "C:\.......\vbslib new\vbslib Prompt.vbs" mkdir フォルダーを右クリックして [ 送る > mkdir ] から起動した場合、相対パスの基準フォルダーの 入力が不要になります。 テスト → T_mkdir フォルダ ソース → vbslib Prompt.vbs 関連 → mkdir 関数 *********************************************************************** <<< ModuleAssort2 >>> *********************************************************************** ModuleAssort2 [ 親: vbslib のショートハンド・プロンプト ] 簡易バージョン管理&構成管理ツール。 マスターズ フォルダーに、プロジェクトの構成要素であるモジュール(ファイルの集合)の各リビジョンを 入れておけば、そこから、1つまたは複数のモジュールをコピーしてプロジェクトを構成することが できるようになります。 また、プロジェクトからマスターズ フォルダーにモジュールを抽出コピーすること で、リビジョン アップしたモジュールを追加することもできます。 A_Project Masters A_Part ModuleA コピー A_Source.c 01 … リビジョン A_Source.c B_Part 02 … リビジョン B_Source.c A_Source.c コピー ModuleB B_Project 01 … リビジョン A_Part B_Source.c A_Source.c コピー Example.proja … 設定ファイル B_Part MD5List.txt … MD5リスト B_Source.c CheckOut → Download コマンド Assort → CheckOut コマンド → Assort コマンドと Commit → Make コマンド → Publish コマンド → Keyword Substitution (リビジョン番号の埋込み) → リファレンス → ModuleAssort2 の作業の順番 ソース → T_ModuleAssort2.vbs T_ModuleAssort2_RunPrompt_Main (関数名は暫定) テスト → T_ModuleAssort2.vbs T_ModuleAssort2_RunPrompt 関連 → Diff ファイルやフォルダーの内容の違いを表示する → UpdateModule モジュールを新しいリビジョンに置き換える → SyncFilesT モジュール内のターゲット間の同期をする → MakeCrossedOldSections 新しいテキスト セクションの構成に合わせる *********************************************************************** <<< Download コマンド >>> *********************************************************************** Download コマンド << ModuleAssort2 Download コマンドは、サーバーにあるモジュールの圧縮ファイルをまとめてローカルPCにダウン ロードして解凍することで、プロジェクトのフォルダー、または、モジュール(マスターズ フォルダー) のコピーを作ります。 番号またはコマンド >ModuleAssort2 番号またはコマンド名>Download ModuleAssort Downloader モジュールやプロジェクトをダウンロードします。 サーバーのパス >\\PC-01\Masters\ModuleA\01 Enter のみ:C:\Users\user1\Downloads\ModuleAssort\Pub ダウンロードしたファイルを入れる、ローカル フォルダーのパス > 指定したローカル フォルダーは存在しません。作りますか。[Y/N]y サーバーにある _FullSet.txt ファイルに書かれた一覧から構成されるモジュールをダ ウンロード、または、.proja ファイルに書かれたプロジェクトをチェックアウトします。 サーバーにある下記をここへドラッグアンドドロップしてください。 ・サーバーにある _FullSet.txt ファイル(が入ったフォルダー) ・サーバーにある .proja ファイル(が入ったフォルダー) サーバーの中のパス >Projects\ProjectA ModuleAssort2 Download \\PC-01\Masters\ModuleA\01 y Projects\ProjectA サーバーのパスを入力するところまでは、サーバーに配置しているバッチファイルで自動的に 入力されることがあります。 サーバーにある圧縮されたファイルがあるフォルダーは、 Publish コマンド で構成します。 テスト → T_ModuleAssort2.vbs T_ModuleAssort2_Publish *********************************************************************** <<< CheckOut コマンド >>> *********************************************************************** CheckOut コマンド << ModuleAssort2 CheckOut コマンドは、過去に コミット したプロジェクトのフォルダーを復帰します。 その内部では、モジュールのターゲットやリビジョンごとに整理された「マスターズ フォルダー」から いくつかのフォルダーを「プロジェクト フォルダー」にコピーする処理が行われます。 他の人がコミットしたマスターズ フォルダーを入手するには、マスターズ フォルダーを圧縮した ファイルを入手するか、 Download コマンド でマスターズ フォルダーをダウンロード&解凍します。 サンプル Example.proja ModuleAssort2 設定ファイル ModuleA ModuleB タグの中で、プロジェクト(Project-A のリビジョン 01) が構成するモジュール ( タグ)について、マスターズ フォルダー内のフル パスと、プロジェクト フォルダー内の 相対パスを記述します。 相対パスの基準パスは、Project/@path に記述していますが、 コマンドによっては別の相対パスが使われます。 XML タグ( < > で囲まれた部分 )の外は、 コメントとして何でも記述でき、その内容は無視されます。 このサンプルでは タグ が記述されていませんが、記述することで変数を使うこと ができます。 (別のサンプルを参照) vbslib Prompt.vbs ファイルをダブルクリックして、以下の黄色の部分を入力すると、CheckOut できます。 番号またはコマンド >ModuleAssort2 設定ファイル(.proja)のパス >C:\Example.proja 以下のいずれかを入力してください。 ・プロジェクトをチェックアウトまたはリリースする空のフォルダーのパス ・メイクする最終ターゲットのプロジェクト名+リビジョン名。例:Project\01 ・アソート&コミットする XML の Project/@path に記述したパス ・Enter のみ : メンテナンス メニューへ パス >C:\Workspace\ProjectB 1. 指定したパスにプロジェクトを出力する [CheckOut] 3. 指定したパスにパッケージを出力する [MakePackage] Enter のみ: 戻る 番号またはコマンド名>CheckOut プロジェクトをチェックアウトします。 Enter のみ: 戻る プロジェクト名\リビジョン(例:ProjectA\01)>Project-A\01 ${Masters}\ModuleA\02 ${Masters}\ModuleB\02 チェックアウトしてできたフォルダーのパスを .proja ファイル(XML形式)の中の Project/@path 属性に記述してから ModuleAssort を起動すると、アソート&コミ ットできるようになります。 なお、ファイルの中に記述された ${...} は、 Variable タグで定義している変数です。 完了しました。 ModuleAssort2 C:\Example.proja C:\Workspace\ProjectB CheckOut Project-A\01 サンプル Example.proja ModuleAssort2 設定ファイル ModuleA ModuleB タグで、Project-A や Project-B のデフォルト リビジョンがどれであるかについて 記述しています。 タグに記述したプロジェクトは、ModuleAssort2 を起動したときに、 一覧されます。 タグ で変数を定義しています。 タグで、それぞれのプロジェクト(Project-A のリビジョン 01、Project-B のリビジョン 01、 同 02 ) が構成するモジュール( タグ)について、マスターズ フォルダー内のフル パスと、 プロジェクト フォルダー内の相対パスを記述しています。 タグで、同じ内容のファイルを探すための MD5リスト のパスを設定しています。 マスターズ フォルダーの中で、同じ内容のファイルを1つだけにする Fragment コマンドによって、 フォルダーのサイズを削減する処理がが行われていなければ、記述は不要です。 vbslib Prompt.vbs ファイルをダブルクリックして、以下の黄色の部分を入力すると、CheckOut できます。 番号またはコマンド >ModuleAssort2 設定ファイル(.proja)のパス >C:\Example.proja ------------------------------------------------------------------------------- 1. Project-A 2. Project-A\B ------------------------------------------------------------------------------- 以下のいずれかを入力してください。 ・上記の番号 ・プロジェクトをチェックアウトまたはリリースする空のフォルダーのパス ・メイクする最終ターゲットのプロジェクト名+リビジョン名。例:Project\01 ・アソート&コミットする XML の Project/@path に記述したパス ・Enter のみ : メンテナンス メニューへ 上記の番号、または、パス >2 ------------------------------------------------------------------------------- Project Root = C:\ProjectB Project Name = Project-B\02 フォルダーが見つかりません。 1. プロジェクトをチェックアウトする [CheckOut] 3. プロジェクトのモジュールを一覧する [Modules] 9. カレント モジュールを変更する [GoTo] 番号またはコマンド>1 ${Masters}\ModuleA\02 ${Masters}\ModuleB\02 Completed. ModuleAssort2 C:\Example.proja 2 1 *********************************************************************** <<< Assort コマンドと Commit >>> *********************************************************************** Assort コマンドと Commit << ModuleAssort2 Assort コマンドは、新しいリビジョンのプロジェクトが決まった後で、マスターズ フォルダーの中にある モジュールを更新する(リビジョン アップしたフォルダーを追加する)作業を支援します。 Commit コマンドは、プロジェクトの構成を記録し、後で CheckOut コマンドで復帰できるようにします。 Assort コマンドを実行すると、カレント プロジェクトの中にあるファイルと、マスターズ フォルダーの 中にあるファイルの比較を行い、プロジェクトで変更(更新)があったモジュールのファイルについて は、隣の Work フォルダーにプロジェクトからコピーします。 変更がなければ Work フォルダーは できません。 ModuleA ModuleA 02 02 Work … プロジェクトから抽出コピー vbslib Prompt.vbs ファイルをダブルクリックして、以下の黄色の部分を入力すると、Assort できます。 番号またはコマンド >ModuleAssort2 設定ファイル(.proja)のパス >C:\Example.proja 以下のいずれかを入力してください。 ・プロジェクトをチェックアウトまたはリリースする空のフォルダーのパス ・メイクする最終ターゲットのプロジェクト名+リビジョン名。例:Project\01 ・アソート&コミットする XML の Project/@path に記述したパス ・Enter のみ : メンテナンス メニューへ パス >C:\Workspace\ProjectB ------------------------------------------------------------------------------- Project Root = C:\Workspace\ProjectB Module in Project = . Project Name = Project\01 Module in Masters = ${Masters}\ModuleA\02 1. 現在のモジュールのフォルダーを比較する [Diff] 2. プロジェクトをアソート&コミットする [Assort] 3. プロジェクトのモジュールを一覧する [Modules] 4. フォルダーを開く - マスターの中のモジュール 6. フォルダーを開く - プロジェクトの中のモジュール 9. カレント モジュールを変更する [GoTo] 番号またはコマンド>Assort ${Masters}\ModuleA\02 プロジェクトから抽出したモジュール: ${Masters}\ModuleA\Work ${Masters}\ModuleA_Copy\02 プロジェクトから抽出したモジュール: ${Masters}\ModuleA_Copy\Work 警告の数 = 2 ------------------------------------------------------------------------------- *1. ${Masters}\ModuleA\02 2. ${Masters}\ModuleA_Copy\02 ------------------------------------------------------------------------------- 以下のいずれかを入力してください。 ・上記の番号 ・プロジェクトをチェックアウトまたはリリースする空のフォルダーのパス ・アソート&コミットする XML の Project/@path に記述したパス ・Enter のみ : メンテナンス メニューへ 上記の番号、または、パス >1 ------------------------------------------------------------------------------- Project Root = C:\Workspace\ProjectB Module in Project = . Project Name = Project\01 Module in Masters = ${Masters}\ModuleA\02 ${Masters}\ModuleA\Work 1. 現在のモジュールのフォルダーを比較する [Diff] 2. プロジェクトをアソート&コミットする [Assort] 3. プロジェクトのモジュールを一覧する [Modules] 4. フォルダーを開く - マスターの中のモジュール 5. フォルダーを開く - マスターの中のワーク モジュール 6. フォルダーを開く - プロジェクトの中のモジュール 9. カレント モジュールを変更する [GoTo] 番号またはコマンド> ModuleAssort2 C:\Example.proja C:\Workspace\ProjectB Assort 1 Assort コマンドを実行すると、 タグに書かれたリビジョンと Work フォルダーの内容を 比較するメニューが表示されます。 モジュールにファイルを追加するときは、Work フォルダーにコピーしてください。 ただし、内容は 任意で構いません。 後で再度 Assort コマンドを実行するときに、プロジェクトから内容がコピー されます。 新しいモジュールを作成するときは、新しいモジュール名のフォルダーを作成し、 その中に Work フォルダーを作成して、その中に構成するファイルを入れてください。 ただし、 内容は任意で構いません。 後で再度 Assort コマンドを実行するときに、プロジェクトから内容が コピーされます。 新しいリビジョンで削除するファイルや移動するファイルがあるときは、Work フォルダーの中で、削除や移動をしてください。 分かる範囲で構いません。 Commit するまでは、 何度でも Work フォルダーの構成を変更して、Assort コマンドでプロジェクトからコピーすることが できます。 もし、Work フォルダーの直下に _FullSet.txt ファイルがあるときは、Work フォルダーにファイルを 追加・削除するのではなく、_FullSet.txt ファイルの中の行を追加・削除してください。 タイムスタンプとハッシュ値は任意の値で構いませんが、値の長さは変えないでください。 後で再度 Assort コマンドを実行するときに、タイムスタンプとハッシュ値がプロジェクトにある ファイルの内容に合わせて更新され、また、プロジェクトからファイルがコピーされます。 プロジェクトのリビジョンを上げるときは、設定ファイルの中のにある前のリビジョンの を前のリビジョンからコピーし、新しいリビジョンのプロジェクトに関する を作成して、CheckOut コマンドを実行します。 この内容も分かる範囲で構いません。 Commit するまでは、何度でも を変更して、CheckOut コマンドや Assort コマンドを実行することができます。 Project-B\03 ModuleA\03 追加 Work フォルダーが新しいリビジョンの内容になったら、フォルダー名を設定ファイルに記述した 最新のリビジョン名に変更し、 タグに記述してあったリビジョンを最新のリビジョン名に 変更し、Assort コマンドを実行してください。 モジュールのマスターとプロジェクトに違いがなけ れば、Work フォルダーは作られず、あったとしても削除されます。 ModuleA ModuleA 02 02 Work 03 すべてのモジュールがプロジェクトと違いがなったら、Commit するかどうかを聞かれます。 Commit すると、CheckOut コマンドでプロジェクト フォルダーが復帰できるようにするために、 MD5リストが更新されます。 : 番号またはコマンド>Assort ${Masters}\ModuleA\02 ${Masters}\ModuleA_Copy\02 正しくチェックアウトできるか確認しています ... C:\Users\OWNER\AppData\Local\Temp\Report\__CheckOutTest ${Masters}\ModuleA\02 ${Masters}\ModuleA_Copy\02 >MakeFolderMD5List >CheckFolderMD5List Project\01 を正しくチェックアウトできることを確認しました。 下記 date 属性を設定ファイルに追加することをお勧めします。 コミットしますか[Y/N]y 警告の数 = 0 Assort y *********************************************************************** <<< Make コマンド >>> *********************************************************************** Make コマンド << ModuleAssort2 タグを設定ファイルに記述することで、make コマンドのような実行を行ったことを 記録することができます。 Make コマンドで、メイク ツリーを表示できます。 参考 → MakeRule XML リファレンス *********************************************************************** <<< Publish コマンド >>> *********************************************************************** Publish コマンド << ModuleAssort2 Publish コマンドは、 Download コマンド でダウンロード&解凍するときのサーバーに配置する フォルダーを構成します。 サーバーに配置するフォルダーは、次の手順で作成します。 サーバーに配置するフォルダーの元となるフォルダー(Pubフォルダー)を作ります。 Pub フォルダーの中にプロジェクトの設定ファイル(*.proja)を配置します。 このとき、分かりやすく分類して作成したフォルダーの中に配置します。 Publish コマンドを実行すると、指定した Pub フォルダーの中にあるすべてのプロジェクトを 構成するマスターズ(モジュール)の圧縮ファイルが Pub フォルダーの中に作成されます。 すでにマスターズのフォルダーがあるときは、そのフォルダーを作成する処理はスキップされます。 Pub フォルダーの中のプロジェクトの Fragment タグ に指定した MD5リストのファイルも 作成または更新します。 この MD5リストを参照して、Pub フォルダーの中で同じファイルが複数 存在しないように圧縮ファイルが作られます。 こうしてできた Pub フォルダーをサーバーにコピーしてください。 番号またはコマンド >ModuleAssort2 設定ファイル(.proja)のパス >C:\Local.xml.proja パス >C:\Pub 番号またはコマンド名>Publish ModuleAssort2 C:\Local.xml.proja C:\Pub Publish *********************************************************************** <<< Keyword Substitution (リビジョン番号の埋込み) >>> *********************************************************************** Keyword Substitution (リビジョン番号の埋込み) << ModuleAssort2 Keyword Substitution 形式($<属性名>: 値 $)をソース ファイルに記述すると、 ソース ファイルに埋め込むリビジョン番号が自動的に更新されるようになります。 '*********************************************************************** '* File: Sample.vbs '* '* - $Version: vbslib 5.91 $ '* - $ModuleRevision: {vbslib}\Public\74 $ '* - $Date: 2016-12-30T11:01:04+09:00 $ '*********************************************************************** WScript.Echo "Hello, world." vbslib 5.91 {vbslib}\Public\74 2016-12-30T11:01:04+09:00 $Version 設定ファイルの Version タグ に書かれたバージョン $ModuleRevision マスターズ フォルダーの中のモジュールの相対パス $Date ファイルのタイムスタンプ、更新日時 設定ファイルの Project タグの keyword_substitution 属性 を no に設定すると、Keyword Substitution 形式の値を自動的に編集しないようになります。 yes に設定した場合、$ModuleRevision があれば 必ず編集しますが、$ModuleRevision がなければ内容に変更があるときだけ編集します。 (※現在、 Fragment タグ を使用しなければ、自動的に編集されません。) Assort コマンド を実行してマスターズ フォルダーにソース ファイルが入るときは、Keyword Substitution 形式の値が空欄になります。 空欄にすることで、リビジョンが更新されても内容が更新されなかった ファイルの内容が変化しないようになります。 * - $Version: $ * - $ModuleRevision: $ * - $Date: $ CheckOut コマンド を実行すると、Keyword Substitution 形式の値を埋め込みます。 参考 → SubVersion - ファイルにリビジョン番号を埋め込む (svn:keywords、Keyword Substitution) → EnumerateToLeafPathDictionaryByFullSetFile の TimeStamp *********************************************************************** <<< ModuleAssort2 のプロジェクト ファイル (.xml.proja) のリファレンス >>> *********************************************************************** ModuleAssort2 のプロジェクト ファイル (.xml.proja) のリファレンス << ModuleAssort2 ModuleAssort2 の設定ファイル。 Variable タグ と ${ } 形式の変数を記述できます。 /ModuleAssort2_Projects/Project/ 複数可能 @name プロジェクト名とリビジョン名。 例: "ProjectX\01" @path プロジェクトのワークがあるフォルダーのパス。 省略可能。 ${ } 形式の変数可能。 @keyword_substitution または @KS Keyword Substitution を自動的に編集するかどうか。 "yes" or "no"。 省略時は "yes"。 /ModuleAssort2_Projects/Project/Module/ 複数可能 @master マスターがあるフォルダーのパス。 フル パス。 CheckOut コマンドでのコピー元。 ${ } 形式の変数可能。 @project プロジェクトのワークの中の相対パス。 CheckOut コマンドでのコピー先。 ${ } 形式の変数可能。 @keyword_substitution または @KS Keyword Substitution を自動的に編集するかどうか。 "yes" or "no"。 省略時は "Project/@keyword_substitution" の設定値。 /ModuleAssort2_Projects/ProjectTag/ 複数可能 主なプロジェクトのリビジョン。 起動時に一覧されます。 @name プロジェクトのタグ名。 例: "ProjectX" @value プロジェクト名とリビジョン名。 例: "ProjectX\01" /ModuleAssort2_Projects/Fragment/ 複数可能 @list タイムスタンプ付き MD5List のパス。 ${ } 形式の変数を指定可能。 マスターがあるフォルダーに、 _FullSet.txt かあるときに参照する、 存在するファイルの一覧が書かれているものとします。 /ModuleAssort2_Projects/Version/ 複数可能 バージョン。 主なリビジョン。 通常、 SubProject タグ/@path が指すファイルに記述します。 @name バージョン名。 例: "ModuleA 1.00"。 ソース ファイルの中の $Version: $ に埋め込む値。 → Keyword Substitution @path バージョン名に対応するリビジョンのマスターがあるフォルダーのパス。 相対パス可能。 ${ } 形式の変数可能。 /ModuleAssort2_Projects/SubProject/ 複数可能 @path プロジェクト ファイル (.xml.proja) の内容の一部が書かれたファイルのパス。 ${ } 形式の変数可能。 /ModuleAssort2_Projects/MakeRule/ 複数可能 参考 → MakeRule XML リファレンス ソース → ModuleAssort2_SettingFileClass::Load (.vbs) *********************************************************************** <<< ModuleAssort2 の作業の順番 >>> *********************************************************************** ModuleAssort2 の作業の順番 << ModuleAssort2 ModuleAssort2 でプロジェクトを CheckOut する。 動作確認。 プログラミング。 ModuleAssort2 で Assort & Commit する。 Work を 01(リビジョン番号) に変える。 以下は、マスターズの中にあるリビジョンのフォルダーの名前の補足。 _Tmp ビルドを通していなければ、末尾に _Tmp を付ける。 _Branch, _Merged 古いモジュール(例:リビジョン 03)のプロジェクトを変更したら(すでにもっと新しいリビジョンが あれば)、ブランチ 03_A_01_Branch にする。 すでにあるときは、03_B_01_Branch にする。 後で、CheckOutAndUpdate するときに警告されるので、そのときに Branch の直前リビジョンとの 差分を最新に反映する。 反映したら、空のフォルダー 03_A_01_Branch_05_Merged を作成する。 なお、05 はマージした後のリビジョン番号。 Revert したときは、05_A_Branch_04_Merged のように、以前のリビジョン(04)を付ける。 _fork_to_, _joined_to_ 一部が別のターゲットに分離したら、<分離前のリビジョン>_fork_to_<分離先> という名前の 空フォルダーを作成する。 すべてが移動したら、<移動前のリビジョン>_joined_to_<分離先> という名前の空フォルダーを作成する。 ターゲット間の同期 SyncFilesT の設定ファイルと同期するフォルダーが入ったプロジェクトを CheckOut する。 ModuleAssort の Modules コマンドで、新しいリビジョンがあるかチェックして、あれば プロジェクトにあるフォルダーと置き換える。 SyncFilesT で同期する。 同期したら、同期に関する表(HTML) を保存する。 同期したら、リビジョンのフォルダーの名前の末尾に _Synced_Tmp を付ける。 (未開発) FindCross、FindCrossSymbol でファイルが所属するモジュールを調整する。 → FindCross コマンド コミットしたものから内容はなるべく変えないこと。 変えるのは、上記 SyncFilesT で。 #include するファイルを変えるなど、最低限変えるのはよい。 内容を更新したとき、モジュールのリビジョン フォルダー名の末尾に、_Tmp を付ける。 プロジェクトの暫定コミットは、リビジョン名の末尾に、_NoCross を付ける。 ループ *********************************************************************** <<< 内部コールツリー >>> *********************************************************************** 内部コールツリー << ModuleAssort2 → Download コマンド T_ModuleAssort2_Publish (.vbs) CheckOut (ModuleAssort2_PromptClass) (.vbs) For Each module In project_.Modules.Items DownloadOneFolderStart (ModuleAssort2_PromptClass) (.vbs) DownloadStart (OpenForDefragmentClass) (.vbs) DownloadStart (DownloadAndExtractFileIn7zClass) DownloadAndExtractFileIn7zClass (.vbs) Get7zFullPathInServer (DownloadAndExtractFileIn7zClass) (.vbs) CopyAndRenameStart (CopyWindowClass) CopyWindowClass (.vbs) CheckOutOneFolder (ModuleAssort2_PromptClass) (.vbs) CopyFolder CopyFolder (OpenForDefragmentClass) (.vbs) GetLocalPath (DownloadAndExtractFileIn7zClass) (.vbs) 7z.exe *********************************************************************** <<< NaturalDocs >>> *********************************************************************** NaturalDocs [ 親: vbslib のショートハンド・プロンプト ] ソースファイルのコメントからドキュメントを生成します。 番号またはコマンド >NaturalDocs ソースファイルにあるコメントを HTML に変換します。 ソースファイルがあるフォルダーのパス>C:\src HTML を格納するフォルダーのパス(★上書きします)>C:\_html NaturalDocs C:\src C:\_html コマンドラインから実行 したとき、/silent オプションをつけると、ブラウザーが開かないようになります。 参考 → NaturalDocs 対応コメント → Natural Docs ソース → vbslib Prompt.vbs 関連 → MakeDocumentByNaturalDocs 関数 → doxygen → ConvertDocumetCommentFormat → DoTextShrink → MakeCrossedOldSections *********************************************************************** <<< OpenByStepPath >>> *********************************************************************** OpenByStepPath [ 親: vbslib のショートハンド・プロンプト ] 相対パスを指定して、ファイルを開きます。(絶対パスも可) 番号またはコマンド >OpenByStepPath 相対パスを指定して、ファイルやフォルダーを開きます。(絶対パスも可) 基準パス >C:\FolderA Enterのみ: 基準パスの入力へ ファイルのパス >File1.txt ファイルのパス >File2.txt ファイルのパス > 基準パス >C:\FolderB ファイルのパス >File1.txt OpenByStepPath C:\FolderA File1.txt File2.txt C:\FolderB File1.txt 上記の場合、C:\FolderA\File1.txt 、C:\FolderA\File2.txt 、C:\FolderB\File1.txt が開きます。 相対パスの最後に (行番号) や #キーワードを指定できます。 詳細 → GetEditorCmdLine 番号またはコマンド >OpenByStepPath 相対パスを指定して、ファイルやフォルダーを開きます。(絶対パスも可) 基準パス >C:\FolderA Enterのみ: 基準パスの入力へ ファイルのパス >File1.txt(5) OpenByStepPath C:\FolderA File1.txt(5) ソース → vbslib Prompt.vbs *********************************************************************** <<< OpenFolder >>> *********************************************************************** OpenFolder [ 親: vbslib のショートハンド・プロンプト ] 指定したパスのフォルダー、または指定したパスのファイルがあるフォルダーを開きます。 番号またはコマンド >OpenFolder ファイルのパスを入力すると、そのファイルを含むフォルダーを開きます。 ファイルのパス >C:\FolderA\File.txt OpenFolder C:\FolderA\File.txt 上記の場合、C:\FolderA が開き、File.txt を選択した状態になります。 ソース → vbslib Prompt.vbs 関連 → OpenFolder 関数 → Setting_openFolder *********************************************************************** <<< OpenSendTo, SendTo >>> *********************************************************************** OpenSendTo, SendTo [ 親: vbslib のショートハンド・プロンプト ] ファイル、または、フォルダーを右クリック [ 送る ] の内容となるフォルダーを開きます。 番号またはコマンド >OpenSendTo OpenSendTo ソース → vbslib Prompt.vbs *********************************************************************** <<< OpenStartUp >>> *********************************************************************** OpenStartUp [ 親: vbslib のショートハンド・プロンプト ] スタートアップ・フォルダーを開きます。 番号またはコマンド >OpenStartUp OpenStartUp ソース → vbslib Prompt.vbs *********************************************************************** <<< OpenTask >>> *********************************************************************** OpenTask [ 親: vbslib のショートハンド・プロンプト ] Windows のタスクを開きます。 番号またはコマンド >OpenTask OpenTask ソース → vbslib Prompt.vbs テスト → T_Task フォルダ 関連 → CreateTask → SetTask *********************************************************************** <<< OpenTemp >>> *********************************************************************** OpenTemp [ 親: vbslib のショートハンド・プロンプト ] テンポラリ・フォルダ を開きます。 番号またはコマンド >OpenTemp OpenTemp ソース → vbslib Prompt.vbs 関連 → DelTemp *********************************************************************** <<< OpenVBSLibSource >>> *********************************************************************** OpenVBSLibSource [ 親: vbslib のショートハンド・プロンプト ] デバッガーに表示されているソース コードをテキスト エディターで開きます。 番号またはコマンド >OpenVBSLibSource Visual Studio で表示されている WSH (VBScript) のソースをテキスト エディター で開きます。 Visual Studio で表示されている行番号を記憶してください。 Visual Studio で表示されているソース ファイルの内容をすべて選択してクリップ ボードにコピーしたら、Enter を押してください。 記憶した行番号 > OpenVBSLibSource vbslib Prompt.vbs のショートカットを作成し、 リンク先を以下のように設定すると、手順を 短縮できます。 ov は、OpenVBSLibSource の略語に設定されいます。 "...\vbslib Prompt.vbs" ov "" Visual Studio 2010 以降のデバッガーは、 include (Execute) したスクリプト(ソース コード) がすべて1つのウィンドウにまとめられるため、ソース コードの行番号がデバッガーに 表示される行番号と一致しなくなってしまいます。 本コマンドは、この問題に対処します。 まとめられたソース コードは、include したそれぞれの vbs ファイルの先頭に、 '// g_SrcPath= から始まる行があり、それを検索して処理します。 ソース → vbslib Prompt.vbs *********************************************************************** <<< PickUpCopy >>> *********************************************************************** PickUpCopy フォルダーの一部をコピーします。 番号またはコマンド >PickUpCopy フォルダーの一部をコピーします。 PickUpCopy タグがある XML ファイルのパス >C:\Folder\PickUpCopy.xml コピー元フォルダーのパス >C:\Workspace C:\Workspace_cleaned 上記のフォルダーに出力します。 PickUpCopy C:\Folder\PickUpCopy.xml C:\Workspace サンプル PickUpCopies.xml File.txt ファイルと SubFolder フォルダーをコピーします。 ただし、SubFolder\Temporary はコピーしません。 default_destination_path 属性には、${SourceFolderName} を指定できます。 これは、 コピー元のフォルダーのパスに置き換わります。 → FF-path 属性対応の XML、path 属性と、Except タグ → XML ソース → vbslib Prompt.vbs 関連 → OpenPickUpCopy 関数 *********************************************************************** <<< Prompt >>> *********************************************************************** Prompt [ 親: vbslib のショートハンド・プロンプト ] VBScript が実行できるプロンプトを開始します。 番号またはコマンド >Prompt ((( VBScript プロンプト ))) ? は、このプロンプトに結果を表示するコマンドです。 高機能な電卓として使うことができます。 VBScript の関数や定義した関数も使えます。 グローバル変数を定義することもできます。 サンプル: ------------------------------------------------------------- > ?1+2 3 > ?2+3*4 14 > ?"0x"+Hex( 0x14+0x38 ) 0x4C > a=2 > ?a+3 5 ------------------------------------------------------------- コマンドを入力してください。 > Prompt ソース → vbslib Prompt.vbs 参考 Samples\BatchFiles\VBS_Prompt.bat 関連 → Prompt 関数 *********************************************************************** <<< RegExpTest >>> *********************************************************************** RegExpTest [ 親: vbslib のショートハンド・プロンプト ] 正規表現でマッチするかどうかをテストします。 番号またはコマンド >RegExpTest 正規表現でマッチするかどうかをテストします。 正規表現の メタ文字 一覧:. $ ^ { } [ ] ( ) | * + ? \ Enterのみ: 正規表現と対象文字列との入力を切り替え 正規表現>b.*e 対象文字列>abcdef マッチした位置 = 2 マッチした文字数 = 4 マッチした文字列 = bcde 対象文字列>abcd マッチしませんでした 対象文字列> 正規表現>ab.* マッチした位置 = 0 マッチした文字数 = 4 マッチした文字列 = abcd 正規表現> 対象文字列> RegExpTest b.*e abcdef abcd ab.* 参考 → 正規表現 (VBScript.RegExp) ソース → vbslib Prompt.vbs 関連 → grep *********************************************************************** <<< Rename >>> *********************************************************************** Rename [ 親: vbslib のショートハンド・プロンプト ] キーワード: ファイル名の変更 ファイルの名前の変更 ファイル名の一部を修正したり、名前の一部を追加したりします。 番号またはコマンド >Rename -------------------------------------------------------- 1. ファイル名の先頭に追加する 2. ファイル名の先頭を変更する 3. ファイル名の先頭数文字を削除する 4. ファイル名の末尾数文字を削除する 9. 終了する 番号を入力してください>1 -------------------------------------------------------- 処理を行うフォルダのパス>Work >1 最初に追加する名前>A 下記のフォルダにあるファイルのすべてのファイルの先頭に "A" を追加します。 C:\Work よろしいですか?[Y/N]y Rename 1 Work A y ソース → vbslib Prompt.vbs テスト → T_Rename フォルダ *********************************************************************** <<< RenumberIniFileData >>> *********************************************************************** RenumberIniFileData [ 親: vbslib のショートハンド・プロンプト ] .ini ファイルの内容のうち、= より左にある ( ) の中の番号を振り直します。 番号またはコマンド >RenumberIniFileData ------------------------------------------------------------------------------- クリップボードに入った、.ini ファイルの内容のうち、= より左にある ( ) の中の番号 を振り直します。 Enter のみ:1 開始番号> Enter のみ:Y 空行があるときだけ番号を+1しますか。[Y/N] RenumberIniFileData サンプル・データ Data(2) = ABC Data(5) = DEF Data(6) = DEF 入力 出力 Data(1) = ABC Data(2) = DEF Data(3) = DEF ソース → vbslib Prompt.vbs 参考 → RenumberIniFileData 関数 *********************************************************************** <<< ReplaceShortcutFilesToFiles >>> *********************************************************************** ReplaceShortcutFilesToFiles ショートカット ファイルを通常のファイルに変換します。 番号またはコマンド >ReplaceShortcutFilesToFiles ショートカット・ファイルを通常のファイルに変換します。 サブ フォルダーを含めて変換します。 変換するフォルダーのパス >C:\Folder 0個のファイルをコピーしました。 1個のリンク先が見つかりませんでした。 ReplaceShortcutFilesToFiles C:\Folder ソース → vbslib Prompt.vbs 関連 → ReplaceShortcutFilesToFiles 関数 *********************************************************************** <<< ReplaceSlash, sl >>> *********************************************************************** ReplaceSlash, sl クリップボードにあるテキストの / と \ を置き換えます。 番号またはコマンド >ReplaceSlash クリップボードにあるテキストの / と \ を置き換えました。 ReplaceSlash 先頭の C:\ は、/mnt/c/ と置き換えます。 → Bash on Ubuntu on Windows (lxss) サンプル \ があるテキスト / があるテキスト Sub\File.txt Sub/File.txt C:\Folder /mnt/c/Folder ソース → vbslib Prompt.vbs *********************************************************************** <<< ReplaceSymbols >>> *********************************************************************** ReplaceSymbols [ 親: vbslib のショートハンド・プロンプト ] 複数のファイルの中の複数の単語(文字列)を一度に置き換えます。 番号またはコマンド >ReplaceSymbols -------------------------------------------------------- ReplaceSymbols の設定ファイルのパス> ReplaceSymbols ReplaceSymbols の設定ファイル マッチしないときは whole_word="no" にしてみてください。 Target タグに指定する変換対象のファイルは、複数指定できます。 またワイルドカードを 使って、サブフォルダーにあるすべてのファイルも変換できます。 CheckExist タグを使うと、変換後に指定したキーワードが存在することをチェックでき ます。 存在しなければエラーメッセージが表示されます。 README.txt の置き換える前 This is Temporary File. TEMP is TEMPORARY. replace. README.txt の置き換えた後 This is Sample File. SAMPLE is TEMPORARY. replay. 複数行や連続した空白文字を含むときは、, タグを使って、 で 囲んでください。 ソース → vbslib Prompt.vbs 関連 → ReplaceSymbolsClass → ReplaceStringTemplate → EvaluateByVariableXML *********************************************************************** <<< RepliCmp >>> *********************************************************************** RepliCmp 同じ名前のファイルの内容をマージする手助けをします。 → RepliCmp *********************************************************************** <<< SearchOpen >>> *********************************************************************** SearchOpen [ 親: vbslib のショートハンド・プロンプト ] 指定のパスのテキストファイルを開いて、指定の行番号またはキーワードを検索します。 番号またはコマンド >SearchOpen [SearchOpen] 指定のパスのテキストファイルを開いて、指定の行番号またはキーワードを検索します。 path>C:\FolderA\File.txt#[FuncA] SearchOpen C:\FolderA\File.txt#[FuncA] C:\FolderA\File.txt#[FuncA] は、C:\FolderA\File.txt をテキスト・エディターで開いて、 "[FuncA]" を検索します。 C:\FolderA\File.txt(100) と入力すると、100行目を表示します。 詳細は、 → GetEditorCmdLine ショートカットやバッチファイルなどから SearchOpen を呼び出すときのパラメーターに " や \' を含めたいときは、 \' → " の変換の逆変換 をしてください。 ソース → vbslib Prompt.vbs Snap Note との連携 プログラミング補助機能を使うとき、SearchOpen.exe が無くても、vbslib があれば使えます。 Snap Note の svgcats.ini ファイルに下記のように設定してください。 SearchOpen = "cscript ""...\vbslib\vbslib Prompt.vbs"" SearchOpen ""%1#%2""" /close:5 /close *********************************************************************** <<< Setting >>> *********************************************************************** Setting [ 親: vbslib のショートハンド・プロンプト ] エディター等 vbslib 外部プログラムの設定を変更します。 → エディター等の設定変更 設定をテストすることもできます。 番号またはコマンド >Setting vbslib 外部プログラム設定 以下のフォルダーとサブ フォルダーから起動したスクリプトに対する設定です。 C:\home\vbslib 1. 設定ファイルを入れるフォルダーの一覧 [List] 2. フォルダーを開くプログラムの設定とテスト [Folder] 3. テキストファイルを開くプログラムの設定とテスト [Text] 4. テキストファイルを比較するプログラムの設定とテスト [Diff] 5. フォルダーを比較するプログラムの設定とテスト [DiffFolder] 9. 設定終了 [Exit] 番号またはコマンド名>5 ------------------------------------------------------------------------------- >copy_ren "C:\vbslib\scriptlib\vbslib\setting_default", "C:\Users\user1\AppData\Local\Temp\Report\160919\Test_setting_default" >copy_ren "C:\vbslib\scriptlib\vbslib\setting", "C:\Users\user1\AppData\Local\Temp\Report\160919\Test_setting" >copy_ren "C:\vbslib\scriptlib\vbslib\setting", "C:\Users\user1\AppData\Local\Temp\Report\160919\Test_setting3" フォルダーを比較する Diff ツール の設定(Setting_getFolderDiffCmdLine 関数) 現在の設定は、以下のファイルにあります。 下のほうにあるファイルの設定が優先されます。 C:\vbslib\scriptlib\vbslib\setting_default\PC_setting_default.vbs 1. 設定する [Set] 2. テストする [Test] 9. 戻る [Exit] 番号またはコマンド名>1 ------------------------------------------------------------------------------- 設定を格納するフォルダーを次から選んでください。 なお、PC 全体の設定をするファイルに変更を加えるときは警告されますので、警告内容を確認してください。 1. vbslib のデフォルト設定(変更しないでください): C:\vbslib\scriptlib\vbslib\setting_default 2. PC 全体の設定 [PC]: C:\Users\user1\AppData\Roaming\Scripts 3. USB メモリーに入っている PC 全体の設定 [Mem]: R:\home\mem_cache\prog\scriptlib\setting_mem 4. フォルダーごとの設定 [Local]: C:\vbslib\scriptlib\vbslib\setting 数字が大きいほど優先されます。 Enter のみ:戻る 番号または [] の中の名前>2 ------------------------------------------------------------------------------- >CreateFile "C:\Users\user1\AppData\Roaming\Scripts\PC_setting.vbs", ""+vbCRLF+... 新規作成しました。 設定ファイル(スクリプト)を開きます。 編集したら保存してテストしてください。 続行するには Enter キーを押してください . . . >start "C:\Program Files (x86)\sakura\sakura.exe" -Y=3 "C:\Users\user1\AppData\Roaming\Scripts\PC_setting.vbs" ------------------------------------------------------------------------------- 1. フォルダーを比較するテスト [Open] 9. 戻る [Exit] 番号またはコマンド名> Setting ソース → vbslib Prompt.vbs テスト → T_ToolSetting\README 関連 → Start_VBS_Lib_Settings 関数 *********************************************************************** <<< SetTask >>> *********************************************************************** SetTask [ 親: vbslib のショートハンド・プロンプト ] タスクの開始時間を再設定します。 番号またはコマンド >SetTask タスクの開始時間を再設定します。 タスク名(登録済みのもの)>vbslib_test 例: 13:00 ... 今が午前10時なら、今日の午後1時に実行する 例: 1:00 ... 今が午前10時なら、明日の午前1時に実行する 例: +1:00 ... 今から1時間後に実行する いつ実行を開始しますか>+0:01 SetTask vbslib_test +0:01 ソース → vbslib Prompt.vbs テスト → T_Task フォルダ 関連 → CreateTask → OpenTask *********************************************************************** <<< Shutdown >>> *********************************************************************** Shutdown [ 親: vbslib のショートハンド・プロンプト ] PCの電源を切ったり再起動したりします。 番号またはコマンド >shutdown 1) PowerOff 2) Reboot 3) Hibernate 4) Sleep 5) Standby 番号を入力してください > shutdown ソース → vbslib Prompt.vbs 参考 → Shutdown *********************************************************************** <<< SortLines >>> *********************************************************************** SortLines テキストファイルの内容を行単位でソート(整列)します。 番号またはコマンド >SortLines テキストファイルの内容を行単位でソート(整列)します。 入力ファイルのパス >C:\Folder\Input.txt 出力ファイルのパス(★上書きします)>C:\Folder\Output.txt Enter のみ:残さない 同じ内容の行をそのまま残しますか [Y/N] 出力しました。 SortLines C:\Folder\Input.txt C:\Folder\Output.txt 同じ内容の行をそのまま残すとき: Input.txt Output.txt Beckham Christiano Aguirre Diego Beckham Aguirre Beckham Beckham Christiano Diego 同じ内容の行をそのまま残さないとき: Input.txt Output.txt Beckham Christiano Aguirre Diego Beckham Aguirre Beckham Christiano Diego ソース → vbslib Prompt.vbs 関連 → SortStringLines 関数 → grep *********************************************************************** <<< SpaceToTab, TabToSpace, st, ts >>> *********************************************************************** SpaceToTab, TabToSpace, st, ts [ 親: vbslib のショートハンド・プロンプト ] テキストファイルのタブ文字と空白文字を変換します。 変換したら変換後のテキストファイルが開きます。 番号またはコマンド >SpaceToTab テキストファイルのタブ文字と空白文字を変換します。 1) 行頭のタブ文字→空白文字 [TabToSpace] 2) 行頭の空白文字→タブ文字 [SpaceToTab] 3) 行頭の文字は変換しない [NoChange] 番号またはコマンド名を入力してください >SpaceToTab 1) 行頭以外のタブ文字→空白文字 [TabToSpace](←Enterのみのとき) 2) 行頭以外の空白文字→タブ文字 [SpaceToTab] 3) 行頭以外の文字は変換しない [NoChange] 番号またはコマンド名を入力してください >TabToSpace タブ文字のサイズ(Enterのみ=4)> 変換前のテキストが書かれたファイルのパス >C:\file.txt SpaceToTab SpaceToTab TabToSpace C:\file.txt st コマンドを実行すると、行頭の空白文字→タブ文字が自動的に選ばれます。 ts コマンドを実行すると、行頭のタブ文字→空白文字が自動的に選ばれます。 コマンドラインで /AutoExit オプションを付けて起動したときは、変換後に自動的に終了します。 /AutoExit:1000 とすると 1秒後に自動的に終了します。 サンプル → Samples\SpaceToTab フォルダー ソース → vbslib Prompt.vbs 参考 → タブ文字の幅を変えても崩れないソースコードの書き方 (Web) テスト → T_ChangeTabSpace フォルダ 関連 → タブ文字変換関数、ChangeHeadSpaceToTab など *********************************************************************** <<< StopScreenSaver >>> *********************************************************************** StopScreenSaver [ 親: vbslib のショートハンド・プロンプト ] スクリーンセーバーを起動しないようにします。 番号またはコマンド >StopScreenSaver ------------------------------------------------------------------------------- 30秒ごとに自動的にシフトキーを押すことで、スクリーンセーバーを起動しないようにし ます。 スクリーンセーバーを停止する時間(分)> 60 残り 60分 StopScreenSaver 60 ソース → vbslib Prompt.vbs *********************************************************************** <<< Switches >>> *********************************************************************** [ 親: vbslib のショートハンド・プロンプト ] Switches 仮想的なスイッチの設定に従って、複数のファイルを編集します。 たとえば、デバッグ用の設定とリリース用の設定を切り替えるスイッチを定義して、 デバッグに必要ないくつかのソース ファイルや設定ファイルの編集をまとめて行います。 サンプル debug.h debug.h スイッチ : // #define DEBUG 1 : : #define DEBUG 1 : ↑ コメント アウト // による無効化 ↑ コメント アウト削除による有効化 Switches.swit 設定ファイル: → 詳細 #define DEBUG 1 // #define DEBUG 1 Switches を実行すると、 Debug 設定にスイッチします。 … … スイッチの1つを定義。 スイッチの値は、コンマ区切り (CSV 形式)、で指定します。 … Debug にスイッチしたときと、 Release にスイッチしたときの debug.h ファイルの一部の テキストを指定しています。 Switch タグ、File タグ、T タグは、複数指定できます。 debug.h ファイルの中で、// #define DEBUG 1 を検索して、見つかったら、 #define DEBUG 1 に置き換えます。 どのスイッチの値も対象のファイルにないときは、エラーになります。 番号またはコマンド >Switches ------------------------------------------------------------------------------- 環境に合わせて複数のテキスト ファイルを自動編集します。 設定ファイルのパス >C:\work\Switches.trans ------------------------------------------------------------------------------- C:\work\Text1.txt C:\work\Text2.txt C:\work\File.txt C:\work\Folder 以上のファイルを編集します。 続行するには Enter キーを押してください . . . ------------------------------------------------------------------------------- C:\work\Text1.txt C:\work\Text2.txt C:\work\File.txt C:\work\Folder 編集しました。 Switches コードのサイズを減らすために #if を使うと、整合性を取ることが非常に難しくなります。 注意 DoTextShrink でコードのサイズを減らすとよいでしょう。 ソース → vbslib Prompt.vbs → ToolsLib.vbs → (test) ToolsLib.vbs テスト → T_Switches.vbs 関連 → Translate *********************************************************************** <<< Switches の設定ファイル >>> *********************************************************************** Switches の設定ファイル << Switches Switches の設定ファイルに記述できる XML の内容を説明します。 下記の他に、 Variable タグ も、記述できます。 Switches/SwitchNow 1つのみ @target_set_names 切り替えた後のスイッチの値。 複数の値を指定するときは、CSV 形式(コンマ区切り)で記述します。 切り替えるたびに記述しなおしてください。 例: target_set_names="Debug, Minimum" @verbose デバッグ用の詳細表示をするかどうか。 "yes" か "no"。 Switches/Switch 複数可能 @set_names スイッチの値の定義。 CSV 形式(コンマ区切り)で記述します。 通常、オンかオフに相当する2つのシンボルを記述しますが、 3つ以上記述することもできます。 複数のスイッチを定義できますが、スイッチの値の名前空間はグローバル ですので、衝突しないようにしてください。 Switches/File 複数可能 @path 内容を置き換えるテキストファイルのパス。 Variable タグ で定義した変数を参照することができます。 Switches/File/T 複数可能 @line 省略時は、置き換えるテキストが行の途中にあっても置き換えます。 "head" の時は、行の先頭のみ置き換えます。 "whole" の時は、行の全体に対して置き換えます。 @text_type 省略時は、スイッチの値のタグで囲まれたテキストでファイルの内容を 置き換えますが、 "path" を指定すると、スイッチの値のタグで囲まれたテキストを、 ファイルやフォルダーのパスとして処理します。 そして、スイッチの値に よって、ファイルやフォルダーをコピーして置き換えます。 パスを指定しな かったときは、ファイルやフォルダーを削除します。 File\FileX.txt File\FileY.txt 例: SetX にスイッチすると、File\FileX.txt から File.txt にコピーします。 SetY にスイッチすると、File\FileY.txt から File.txt にコピーします。 SetZ にスイッチすると、File.txt を削除します。 Switches/File/T/(スイッチの値) 複数可能 text() スイッチの値がこれまで設定されていたときは、置き換える前のテキスト。 スイッチの値がこれから設定しようとしているときは、置き換えた後のテキスト。 @variable text() で、 Variable タグ で定義した変数を参照するかどうか。 "yes" か "no"。 "no" のときは、${Var} のようなテキストは、変数の値に置き換わりません。 @cut_indent text() から、行頭の空白やタブをカットしたテキストで処理するかどうか。 "yes" か "no"。 参考: → CutIndentOfMultiLineText @indent text() に、行頭の空白やタブを追加したテキストで処理するようにします。 "${Count}*${Character}" 形式で指定します。 例: "2* " … 2つのタブ、 "8* " … 4つの空白 なお、&#〜; は、 → CutIndentOfMultiLineText XML の文字参照 です。 @dump "yes" のときは、text() の内容をバイナリー形式でダンプします。 文字コード セットは、BOM 付き Unicode です。 省略時は "no" です。 スイッチの値がマッチしないときのヒントになります。 スイッチのスイッチには対応していません。 もし対応していれば、たとえば、A, B or C がオンの場合 X がオン、D or E がオンの場合 Y がオン が定義できれば、同じ text() を 3つと 2つ書く必要がなくなります。 Switches/File/T/(スイッチの値)/(スイッチの値)/ ... 複数可能 ネストしたスイッチの値は、And 条件として処理します。 なお、OR 条件を指定する方法はありません。 Variable タグを活用してテキストを指定して ください。 Debug and Minimun Debug and Full Release and Minimun Release and Full 例: Switches/File/T/LinesStart[attribute_of='T'] 1つのみ text() 置き換える範囲の直前の行にマッチするキーワード。 このキーワードにマッチした行の次の行から、LinesEnd[attribute_of='T']/text() に指定したキーワードにマッチした行の前の行までが、同じ T タグを親要素に 持つタグで指定したテキストで置き換える範囲です。 StartLine EndLine Minimun Full 例: 上記の設定で Full にスイッチすると、下記のように置き換わります。 Minimum -- StartLine -- Minimum -- EndLine -- Minimum Minimum -- StartLine -- Full -- EndLine -- Minimum Switches/File/T/LinesEnd[attribute_of='T'] 1つのみ text() 置き換える範囲の直後の行にマッチするキーワード。 参考 → LinesStart[attribute_of='T'] *********************************************************************** <<< SyncByShortcut >>> *********************************************************************** [ 親: vbslib のショートハンド・プロンプト ] SyncByShortcut ショートカットが指すファイルを2つのフォルダー間で同期コピーします。 番号またはコマンド >SyncByShortcut ------------------------------------------------------------------------------- ショートカットが指すファイルを2つのフォルダー間で同期コピーします。 設定ファイルのパス > フォルダー (1): "C:\FolderA" フォルダー (2): "C:\FolderB" C:\FolderA\A.txt C:\FolderB\sub\A.txt 以上のファイルを、対応するフォルダーにコピーします。 SyncByShortcut ソース → vbslib Prompt.vbs テスト → T_SyncByShortcut フォルダー *********************************************************************** <<< SyncFilesT >>> *********************************************************************** [ 親: vbslib のショートハンド・プロンプト ] SyncFilesT 複数のターゲット間でファイルの内容を一度に同期(マージ)することで、全てのターゲットが 最新の状態であることを維持できるようになります。 行がファイル、列がモジュールのターゲット、という表を表示して、同期するファイルの状況を 一覧できます。 番号またはコマンド >SyncFilesT ------------------------------------------------------------------------------- >SyncFilesT 行がファイル、列がモジュールのターゲット、という表を表示して、すべてのターゲット 間で同期(マージ)することを支援します。 設定ファイルのパス >C:\Folder\SyncFilesT_Sample.xml ------------------------------------------------------------------------------- ターゲット間で比較するファイルの kind 値を入力してください。 1. kind 値 1 のファイルを比較する 2. kind 値 2 のファイルを比較する : 97. 再スキャンして、一覧を表示する [Reload] 98. 詳細を表示する [ShowDetail] 96. HTML ファイルを保存する [SaveHTML] 99. 終了 [Exit] kind 値または上記の番号またはコマンド名> SyncFilesT C:\Folder\SyncFilesT_Sample.xml SyncFilesT を、起動すると、下記のサンプルのような表が表示されます。 ターゲット間でファイルを比較する、を選ぶと、 Diff ツール が起動するのでファイルの内容に ついては、手動で同期してください。 → サンプル → 新規 SyncFilesT 設定ファイルの生成 → ファイルの同期手順 → SyncFilesT の設定ファイルの詳細 サンプル ModuleX TargetA g1.c g3.c TargetB g1.c g3.c TargetC g2.c g3.c 表が崩れているのは、ブラウザーが標準仕様に対応していないためです。 上記の表は、下記の設定ファイルを開いたとき(SyncFilesT コマンドを起動したとき)に表示 されます。 表の色から、g1.c ファイルは、TargetA と TargetB で内容が同じであることを表しています。 同様に g3.c ファイルは、TargetB と TargetC で内容が同じであることを表しています。 同じ色でも行が異なれば、同じ内容ではありません。 01\A は、リビジョン 01、description 記号 A という意味です。 リビジョンは、01 から始まる 整数に限られます。 description 記号が同じファイルは、同じ内容であるべきということを 表しています。 ファイル名の左にある番号は、kind 番号です。 ターゲットによってファイル名が異なって いても、kind 番号を合わせれば比較対象になり、同じ行に配置されます。 SyncFilesT の設定ファイル: → 新規作成 → 詳細 上記の TargetA (index=1) の g2.c ファイルは、TargetB, TargetC の g3.c ファイルと同期を とるように kind 番号を合わせています。 line_num の値は、自動的に更新されます ターゲットのフォルダーの一部だけを比較対象にするときは、Folder タグ、File タグ、Except タグを 記述してください。 詳細 → FF-path 属性対応の XML、path 属性と、Except タグ TargetFiles タグの path 属性は、子ノードに Folder タグ、File タグ、Except タグがあるときは、 ターゲットのルート フォルダーを指定するたけで、比較対象のフォルダーにはなりません。 必要なら、上記のように、Folder タグで改めて指定してください。 ソース → SyncFilesMenuLib.vbs → SyncFilesT_Class、全ターゲット表 テスト → T_SyncTable フォルダー 関連 → ModuleAssort *********************************************************************** <<< 新規 SyncFilesT 設定ファイルの生成 >>> *********************************************************************** 新規 SyncFilesT 設定ファイルの生成 << SyncFilesT SyncFilesT の設定ファイル を新規に作成するときは、比較する各種ターゲットを1つのフォルダーに まとめてから、 SyncFilesT_new コマンド を使って自動作成します。 ただし、TargetFiles/@index、File/@kind、 File/@description は、調整する必要があります。 比較する各種ターゲットを1つのフォルダーにまとめて、 ModuleX … このフォルダーを指定します。 TargetA g1.c g3.c TargetB g1.c g3.c TargetC g2.c g3.c vbslib のショートハンド・プロンプト の SyncFilesT_new コマンドを実行すると、 番号またはコマンド >syncfilest_new ------------------------------------------------------------------------------- >SyncFilesT SyncFilesT で使う設定ファイルのテンプレートを生成します。 各ターゲットのフォルダーが入ったフォルダーのパス >C:\ModuleX >OpenForWrite "C:\_SyncFilesT_ModuleX.xml" 生成した上記の設定ファイルでよければ、上書きされないためにファイル名を変えて ください。 syncfilest_new SyncFilesT の設定ファイルが、指定したフォルダーの親フォルダーにできます。 _SyncFilesT_ModuleX.xml → 詳細 上記は、TargetC の g2.c ファイルが、TargetA, TargetB の g1.c ファイルと同期をとるように 調整済みです。 TargetFiles タグを追加するときは、新規 index 属性の値が、他の index 属性の値と衝突していない ことを検索して確認してください。 TargetFiles タグの index 属性の値を変更したときは、File タグの description 属性も合わせて変更してください。 File タグを追加するときは、新規 kind 属性の値が、他の kind 属性の値と衝突していないことを 検索して確認してください。 File タグの kind 属性の値を変更したときは、CommittedFile タグの revision 属性も合わせて変更してください。 → CommittedFile タグのサンプル フォルダーの中の一部ファイルだけ同期するときは、同期するファイルだけを抽出するようにコピーを するスクリプトを独自に作成して、コピーしたフォルダーに対して SyncFilesT ツールを使うとよいでしょ う。 また、逆方向のコピーをするスクリプトも作成するとよいでしょう。 *********************************************************************** <<< ファイルの同期手順 >>> *********************************************************************** ファイルの同期手順 << SyncFilesT あるターゲットの1つのファイルに更新があったとき、SyncFilesT が表示する表は、下記のように変わります。 なお、表の中の 01\A(ブラウザーによっては 01\A) の 01 は、リビジョン番号、A は、ターゲットの description 記号です。 description 記号が同じなら、同じ内容のファイルであるべきことを表します。 更新があったファイル(TargetA の g1.c)の更新内容を、他のターゲットのファイル(TargetC の g1.c)に 反映して同期するときは、下記の黄色い文字のように入すると Diff ツール または SyncFilesX ツール が開くので、手動で同期してください。 前回、同期した内容の MD5 リスト を設定ファイルの HashList タグに指定したときだけ、前回、同期したときの内容とも比較ができる SyncFilesX ツール が起動します。 TargetB は、TargetA と同じ内容になるべきなので、後述のようにコピーして同期します。 ターゲット間で比較するファイルの kind 値を入力してください。 1. kind 値 1 のファイルを比較する 2. kind 値 2 のファイルを比較する : 97. 再スキャンして、一覧を表示する [Reload] 98. 詳細を表示する [ShowDetail] 96. HTML ファイルを保存する [SaveHTML] 99. 終了 [Exit] kind 値または上記の番号またはコマンド名>1 ------------------------------------------------------------------------------- 1) Enter のみ:終了 c+番号:ターゲット間でコピーする Target Number (Left or c+Source) >1 Target Number (Right) >3 1 1 3 Diff ツールで(TargetC を)同期させた後、リロード(Enter で戻ってから 97. Reload)すると、次のように 表示が変わります。 TargetA の g1.c ファイルの内容をすべて TargetB の g1.c ファイルにコピーするときは、次の黄色い 文字のように入力していってください。 ただし、コピー元のターゲット番号を入力するときは、番号の 先頭に c を付けてください。 kind 値または上記の番号またはコマンド名>1 ------------------------------------------------------------------------------- 1) Enter のみ:終了 c+番号:ターゲット間でコピーする Target Number (Left or c+Source) >c1 Enter のみ:コピー終了 Target Number (Destination) >2 source_path = "C:\TargetA\g1.c" destination_path = "C:\TargetB\g1.c" コピーします。[Y/N]y 1 c1 2 y (TargetB に)コピーして同期させた後、リロード(Enter で戻ってから 97. Reload)すると、次のように 表示が変わります。 表の内容が、new_* (例:new_1\A、ブラウザーによっては new_1\A)のときは、まだコミット(確定)してい ないことを表しています。 コミット(確定)するには、 SyncFilesT の設定ファイル に、以下のような CommittedFile タグを追加します。 この CommittedFile タグは、ModuleX モジュールに含まれる、ファイルの kind 番号= 1、リビジョン 番号= 02、ターゲットの description 記号= A、のファイルをコミットしたことを表しています。 その ファイルの内容に対応する MD5 ハッシュ値 は、9a0baa2ed090b16796c55c156b5ffca9 です。 追加する CommittedFile タグに近い内容は、98. 詳細を表示する [ShowDetail] を選ぶと開くファイルの 最後に書かれています。 この詳細ファイルは、97. リロード で更新されます。 ただし、リビジョン番号は、 すでにある番号と異なる番号に変更する必要があります。 また、ターゲットの description 記号は、正しく 修正しなければならないことがあります。 → コミット済の設定ファイルのサンプル CommittedFile タグを追加した後、リロード(Enter で戻ってから 97. Reload)すると、次のように表示が 変わります。 同期する前に比べてリビジョン番号が増えています。 Modified の列が空欄になったら、 同期完了です。 96. HTML ファイルを保存 [SaveHTML] しておくとよいでしょう。 更新が必要ないファイルについても、リビジョン番号を更新したコミットをしてください。 このコミットに より、更新内容を反映する必要がなかったことが表わせます。 すべてのファイルがコミット済みであっ ても、リビジョン番号が異なれば、まだ反映していないとして、Modified の列に * が表示されます。 下記の表は、TargetA の更新内容を TargetB とTagetC に反映した結果、TargetC には変更がなかっ たので、TargetA と TargetB に対してのみ新しい CommittedFile タグを追加したときの表です。 リビジョン 番号が小さい TargetC を、リビジョン番号01 から 02 に上げるように、MD5 ハッシュ値が同じ下記のような CommittedFile タグを追加してください。 … 追加 : … 既存 現在、同じハッシュ値の CommittedFile タグは、最新リビジョンにしか付けられません。 既存の CommittedFile タグのタグ名を変えるなどして無効にしてください。 *********************************************************************** <<< SyncFilesT の設定ファイルの詳細 >>> *********************************************************************** SyncFilesT の設定ファイルの詳細 << SyncFilesT 参考 → 新規作成 → サンプル 詳細 /SyncFilesT/ModuleFiles (1つ) モジュールを構成するファイルの集合 1つのモジュールに対して、複数の ModuleFiles タグを指定できます。 @module_name 子ノードに指定するファイルが所属するモジュールの名前。 /SyncFilesT/ModuleFiles/TargetFiles (1つ、または、複数) ターゲット。 モジュールの子ノード @index このターゲットに対応する description 属性の値の中の要素番号。 先頭は 1。 複数のターゲットで同じ要素番号を共有することも可能です。 @target_name ターゲットの名前。 表の列のタイトルに表示されます。 @path ファイルが入ったフォルダーのパス。 相対パスの基準は、設定ファイルが 入っているフォルダー。 /SyncFilesT/ModuleFiles/File (1つ、または、複数) ファイル。 モジュールの子ノード @kind Kind値。 ファイルの種類を表す番号。 ターゲットが異なるときにファイル名が 異なるときに、同じ番号を割り当て、比較対象にします。 @description Description値。 同じ内容であるべきファイルを表す文字の並び。CSV形式。 空白文字は、ファイルが存在しないことを表します。 @name ファイル名。 FA File Name 形式 。 同じ名前のファイルが1つしかないときは、 フォルダー名を指定する必要はありません。 @line_num 設定ファイル内の行番号。 自動的に更新されます。 /SyncFilesT/ModuleFiles/CommittedFile (0、1つ、または、複数) コミットしたファイルのリビジョン @hash ファイルの内容のハッシュ値。 MD5形式。 @revision リビジョン。 形式は、モジュール名\Kind値\リビジョン番号\Description値。 例: ModuleX\1\01\A /SyncFilesT/HashList (0、または、1つ) コミットしたファイルの場所 @path MD5 リスト のパス *********************************************************************** <<< SyncFilesX >>> *********************************************************************** SyncFilesX [ 親: スクリプト・データ・ファイル (vbslib付属) ] 同じ、または、ほぼ同じ内容に保つことが求められる2つのファイルがあるとき、その片方または両方 の内容がそれぞれで更新されても、改めて同じ、または、同様の差分があるように戻す(同期する) ことを支援します。 前回 同期したときの内容のとの差分も確認できるので、差分が追加すべき内容 なのか、削除すべき内容なのかを確認することもできます。 また、フォルダーを同期するときは、同期をとる必要があるファイルを一覧します。 ペアにするファイル名や相対パスが異なるときでも対応できます。 PatchAndBackUp の更新内容を見ることにも使えます。 → 概要 → SyncFilesX スクリプト → SyncFilesX を内部で使うツールとの比較 → ファイルの改名・結合・分離・部分移動があったとき → その他のヒント → SyncFilesX ソース 概要 環境A用フォルダー 環境B用フォルダー ほぼ同じ内容に保つ Image.bmp Image.bmp Source.c SourceCpp.cpp ( Source.c とペア) printf( "Hello!\n" ); std::cout << "Hello!" << std::endl; 同期管理フォルダー (_patch or _synced) SyncFilesX (メイン・スクリプト) 前回、同期したときの環境A用フォルダー コミットしたらここにコピーされる 前回、同期したときの環境B用フォルダー 番号またはコマンド >SyncFilesX ------------------------------------------------------------------------------- >SyncFilesX 同じ、または、ほぼ同じ2つのフォルダー(またはファイル)があって、その両方または 片方の内容を更新したときに、その2つを同期(マージ)することを支援します。 ただ し、この作業では、前回同期したときの2つのバックアップが必要です。 4つのパス(NewWork, NewBase, SynchronizedWork, SynchronizedBase)を入力してくだ さい。 NewWork:新しいワークのフォルダーまたはファイルのパス> NewBase:新しいベースのフォルダーのパス> SynchronizedWork:前回同期したときのワークのフォルダーのパス> SynchronizedBase:前回同期したときのベースのフォルダーのパス> 前回コミット時のベース: "_synced\Base" 前回コミット時のワーク: "_synced\Work" *:同期されていないファイル、=:未同期でワークとペースの内容が同じ ------------------------------------------------------------------------------- ■ベース(ModuleX : 環境A): "..\Project\Base" ■ワーク(ModuleX : 環境B): "..\Project\Work" 1. .=. Image.bmp 2. *!. SourceCpp.cpp 91. 再スキャンして一覧する 92. ルート・フォルダーを開く 99. 終了 番号 >2 ------------------------------------------------------------------------------- ベース:C:\ProjectX\Project\Base\Source.c" ワーク:C:\ProjectX\Project\Work\SourceCpp.cpp" ベース・ファイルとワーク・ファイルは「同じ内容」でした 手動で同期したら、コミットしてください。 ------------------------------------------------------------------------------- ★ベース(ModuleX : 環境A): Source.c (変更) ★ワーク(ModuleX : 環境B): SourceCpp.cpp (不変) 1. Diff で開く:同期するファイル (*異なる) [ ベース / ワーク ] 2. Diff で開く:前回の同期 (=同じ) [ ベース / ワーク ] 4. Diff で開く:ベース (変更) [ 前回コミット時 / 現在 ] 5. Diff で開く:ワーク (不変) [ 前回コミット時 / 現在 ] 44.Diff で開く:[ 前回コミット時のベース / ベース / ワーク ] 55.Diff で開く:[ ベース / ワーク / 前回コミット時のワーク ] 6. ファイルまたはフォルダーを開く 7. 再スキャンする 8. 同期をコミットする 9 または Enter : 戻る 番号 > SyncFilesX ペアとなるファイルの内容が適切な関係にある状態(同期された状態)になったら、コミットと呼ぶ 操作をします。 SyncFilesX におけるコミットは、同期された状態のコピーを作成することです。 コミットした後は、ペアの片方のファイルを更新しても、コミット時のファイルのコピーがあるので、 それを参考に、もう片方のファイルを更新することができます。 ただし、更新をどのように反映 させるべきかは Diff ツールを使って人間が反映させてください。 構成するモジュールごとに、同期管理フォルダーを作成するとよいでしょう。 環境Aをアプリケーション環境(統合)、環境Bを個別環境(ベース以外の単体)とすることが よくあります。 → ヒント 親子関係(統合-個別関係)ではないときは、更新が多い方のフォルダーの中の同期管理フォル ダーに、「SyncFilesX による同期は、関係先のフォルダーにあります」のようなメモだけあると よいでしょう。 そこに、関係先のモジュール名の一覧があるとよいでしょう。 SyncFilesX スクリプト 下記のサンプルのような .vbs ファイルを作成してください。 → スクリプト・データ・ファイル (vbslib) SyncFilesX を使うときは、Diff ツールが必要です。 → Setting_getDiffCmdLine 設定部分の行頭には、' が必要です。 → new_FilePathForFileInScript File タグと Folder タグについての補足 → new_PathDictionaryClass_fromXML SyncFilesX.vbs 同期をとるファイルやフォルダーを設定します。 '------------------------------------------------------------[FileInScript.xml] ' ' ' ' ' ' ' ' ' ' ' ' ' '-----------------------------------------------------------[/FileInScript.xml] Sub Main( Opt, AppKey ) SyncFilesX_App AppKey, new_FilePathForFileInScript( Empty ) End Sub '--- start of vbslib include ------------------------------ : (vbslib をインクルードして main を呼び出すコード) vbslib include Image.bmp ファイルに対するそれぞれのパスは次のようになります。 環境A: ..\Project\Base\Image.bmp 環境B: ..\Project\Work\Image.bmp 前回、コミットしたときの環境A: _synced\Base\Image.bmp _synced\Work\Image.bmp 前回、コミットしたときの環境B: SourceCpp.cpp (Source.c) ファイルに対するそれぞれのパスは次のようになります。 same="no" が設定されているこのファイルは、同期しても内容が異なります。 ただし、 前回、同期した内容との差分を、同期相手に反映する必要があります。 same 属性 は、yes か no を明示的に指定することもできますが、省略すると前回の同期内容が 同じかどうかと今回の同期内容が同じかどうかが異なるときに警告します。 環境A: ..\Project\Base\Source.c 環境B: ..\Project\Work\SourceCpp.cpp 前回、コミットしたときの環境A: _synced\Base\Source.c _synced\Work\SourceCpp.cpp 前回、コミットしたときの環境B: SubFolder フォルダーは、フォルダーの中にある(サブフォルダーも含めた)ファイルが 同期対象です。 ただし、SubFolder\porting.c ファイルは、同期しても内容が異なります。 前回、コミットしたときのファイルやフォルダーのパスを指定するときは、synced_base 属性や synced_path 属性を記述します。 FileInScript.xml に書く設定には、以下の SynchronizingSet タグを使用できます。 SynchronizingSet タグがあるときは、どの SynchronizingSet タグのセットを選択するかの メニューが追加されます。 また、Variable タグを使って、変数を定義できます。 → new_LazyDictionaryClass Variable タグで定義した変数の参照は、 path, base, synced_path, synced_base に指定できます。 ${Synced} は、Variable タグの変数の値に 置き換わります。 つまり、左の場合、 synced_base="_synced\BaseSub" になります。 UpdateBoth.txt ファイルに対するそれぞれのパスは次のようになります。 環境A: B\UpdateBoth.txt 環境B: W\UpdateBoth.txt 前回、コミットしたときの環境A: _synced\BaseSub\UpdateBoth.txt 前回、コミットしたときの環境B: _synced\WorkSub\UpdateBoth.txt SynchronizingSet タグの ID 属性を指定すると、その値が画面に表示されます。   例: >> *********************************************************************** SyncFilesX を内部で使うツールとの比較 SyncFilesX.xml SyncFilesX 内部 UpdateModule Patch&BackUp ThrerWayMerge synced_base OldBase ModuleSync BackUp Base base NewBase ModuleNew Patch Right synced_path OldWork TargetSync OldTarget Left path NewWork TargetMerged NewTarget Merged *********************************************************************** <<< ファイルの改名・結合・分離・部分移動があったとき >>> *********************************************************************** ファイルの改名・結合・分離・部分移動があったとき << SyncFilesX 前回同期したときのファイルと新しいファイルの中で、一部のコードが別のファイルに移動していたりしたときは、 その移動だけを行った中間リビジョンを作成しなければ、前回との差分を知ることができません。 中間リビジョンを作成して同期する方法を示します。 SyncFilesX … 4way マージ 1A 1B 2A 2B Before … SyncFilsX 開始時の 1A〜2B CrossBack … Back からファイルの移動だけ行った結果。 マージ開始時の 1A〜2B CrossTool … Back からファイルの移動だけを自動的に行った結果(前回) CrossToolNew … Back からファイルの移動だけを自動的に行った結果(今回) 現在作業中の SyncFilesX に、 がないと、新規または削除が表示されない ことがあるので注意してください。 CrossBefore フォルダーを作成する。 CrossBefore フォルダーとは、 Before から全部or一部を移動しただけのファイルが入ったフォルダーです。 内容は変更されていません。 CrossBefore\1A、CrossBefore\2A は、1A のファイル構成に従います。 CrossBefore\1B、CrossBefore\2B は、1B のファイル構成に従います。 Natural Docs のタグが追加されたり、キーワードが修正されたりすることもあります。 MakeCrossOld.vbs を実行。 初回は、CrossByTool にできます。 そのコピーが、CrossBefore にできます。 また、1A, 1B, 2A, 2B を、Before、BeforeNoTag にコピーします。 SyncFilesX.vbs を CrossBefore にコピーして起動したとき、追加・削除のファイルは無いはずです。 2回目は、CrossByToolNew にできます。 diff "CrossTool\*", "CrossToolNew\*" の差分を diff "CrossTool\*", "CrossToolNew\*", "CrossBefore\*" へ反映させてください。 diff "Before\*", "CrossByToolNew\*" 1A のファイル構成を変えていないときは、"Before\1A", "CrossBefore\1A" に差分は無いはずです。 1B のファイル構成を変えていないときは、"Before\1B", "CrossBefore\1B" に差分は無いはずです。(後記) 2回目の MakeCrossOld.vbs で差分が追加されたときは、1A、1B が Before からコピーされていない 可能性があります。 __Moved_Sections.txt でエラーが出たとき(差分が出たとき)は、 ● Before\*、1A、1B の中に、Natural Docs のタグを追加、または、編集する ● MakeCrossOld.vbs に改名を設定 して、MakeCrossOld.vbs を再実行してください。 (●1A、1B は、未編集なら Before からコピーできます) CrossByToolNew\*\__Moved_Sections.txt で、ERROR NotFoundInBefore や ERROR NotRequestedFromNew になっているキーワードについては、全文検索して、状況と合うように同様の対処をします。 たとえば、Function: Foo の場合、Function と Foo の両方が検索のキーになります。 新規追加されたセクション(NotFoundInBefore エラー)は、もし余分だったら後で同期するときに分かるので、 クロス処理(ここ)においては無視できますが、前回のファイルに Natural Docs のタグだけがないとき (grep で見つかるとき)は対処する必要があります。 削除されたセクション(NotRequestedFromNew エラー)は、削除が正しいなら無視してよい。 以上の問題がなくなったら、次へ。 SyncFilesX.vbs で 1A、1B について、最新のファイル名や内部構成(内容以外)になるように、 ファイル名を変更したり、テキスト セクションを移動したりします。 Natural Docs のキーワードやコードは 変更しません。 ファイルのコミットはしません。 確認したら、CrossBefore、CrossByTool、CrossByToolNew を削除し、一度だけ、MakeCrossOld.vbs を 再実行します。 diff "Before\*", "CrossBefore\*" 以下は、対処されているはずです。 そうでなければ、diff "Before\*", "CrossByToolNew\*" へ戻る。 "Before" にあるファイルの内容がすべて "CrossBefore" にあること。 失っていないこと。 CrossByToolNew\*\__Moved_Sections.txt にリストアップされている内容が同じであること。 diff "Before", "CrossBefore" の右は、1つのセクションだけ CrossBefore からコピーした一時新規ファイル 2A, 2B を削除して代わりに CrossBefore\2A、CrossBefore\2B からコピーする。 (元の 2A, 2B は、BeforeNoTag にあります) 1A, 1B は CrossBefore\1A、CrossBefore\1B とすでに同じはずです。 __Moved_Sections.txt は 2A, 2B に入れません。 ● SyncFilesX で同期を実行。 SyncFilesX を起動、または、再スキャンする。 ただし、起動直後に追加・削除のファイルがないはず。 同期したら、1A, 1B を Masters に入れます。 .moas にSynchronized タグの追加が必要なら追加します。 ● CrossBefore\* も Masters に入れます。 * は、1A, 1B, 2A, 2B です。 CrossBefore と BeforeNoTag に差分がなければ、入れる必要はありません。 Masters 内のフォルダー名は、同期前のリビジョン番号+_xfor_+今回できた最新のリビジョン番号。 _Tmp は外す。 *_xfor_* フォルダーは、上記 CrossBefore フォルダーのバックアップです。 1A の例:02_xfor_03、 1B の例: 01_xfor_03。 すでにあるときは、同じ内容のはずです。 CrossBefore にできている __Moved_Sections.txt も Masters に入れます。 *********************************************************************** <<< その他のヒント >>> *********************************************************************** << SyncFilesX その他のヒント アプリケーション環境(統合)が、ベースとなる環境から、1つのモジュールだけを追加する 場合は、SyncFilesX を使わなくとも、一般的なパッチをあてるだけで構いません。 ベースを更新する場合は、パッチをあてたときにエラーにならないようにパッチを調整します。 追加モジュールを更新する場合は、更新されたパッチをあてます。 ModuleA ベース 統合 + ModuleB パッチ ただし、ファイルの場所の移動や改名があるときは、一般的なパッチではベースとなるファイル の内容が更新されたときにモジュールに反映されなくなるので、SyncFilesX も併用すると よいでしょう。 つまり、パッチからエラーが出なくなった後で、SyncFilesX を使って確認します。 ベースとなる環境から、複数のモジュールを追加する場合、SyncFilesX を使うとよいでしょう。 環境Aをアプリケーション環境(統合)、環境Bを個別環境(ベース以外の単体)とすることが よくあります。 この構造の場合、片方向の参照関係となり、環境Aをリリースするときだけ SyncFilesX を使って同期を取ればよくなります。 環境A 環境B ModuleA ModuleB ModuleC ModuleC 両方向の参照関係がある状態でもリリースするときだけ同期を取ればよくするには、 SyncFilesX のメイン・スクリプトを相互に作成します。 更新する環境だけで更新された 内容は、同期する必要はありません。 環境A 環境B ModuleA ModuleC ModuleB ModuleC 環境A, B とも、同期する関数AがファイルAに、同期する関数BがファイルBにあるとき、 環境Aでは関数CがファイルAに、環境Bでは関数CがファイルBに存在すると、同期が 難しくなります。 なぜなら、ファイルの対応関係が1対1ではなくなるからです。 その場合、 ファイルCを新規に作成するなど、ファイルを分けてください。 (関数Cが環境Aで存在し、環境Bで存在しないときは、ファイルの対応関係が1対1になる ので難しくありません。) 環境A 環境B ファイルA ファイルA 関数A 関数C 関数A ファイルB ファイルB 関数B 関数C 関数B 環境Aでは関数CがライブラリーAに存在、環境Bでは関数CがライブラリーBに存在する 場合は、管理が難しくなることが予想されます。 ライブラリーCを新規に作成するか、 統合的なライブラリーに含めるとよいでしょう。 *********************************************************************** <<< Test.vbs >>> *********************************************************************** Test.vbs 単体テストを実行するスクリプトです。 ダブルクリックすると、 テスト・プロンプト が開きます。 → Test.vbs *********************************************************************** <<< ThreeWayMerge >>> *********************************************************************** ThreeWayMerge 3ウェイ マージ(3方向マージ)をします。 関連 → UpdateModule 更新するパッチをターゲットにあてます 古いパッチを新しいターゲットにあてます 番号またはコマンド >ThreeWayMerge ------------------------------------------------------------------------------- 3ウェイ マージ(3方向マージ)をします。 ベースにするファイル >C:\Base.txt 更新したベースにするファイル(左側) >C:\Left.txt 更新したベースにするファイル(右側) >C:\Right.txt マージした結果の出力先ファイル(★上書きします) >C:\_Merged.txt Enter のみ:マージの設定ファイルを使わない。 マージの設定ファイル > ThreeWayMerge C:\Base.txt C:\Left.txt C:\Right.txt C:\_Merged.txt マージ設定ファイル に ThreeWayMergeSet タグがあれば、比較するフォルダーを毎回入力 しなくても済むようになります。 番号またはコマンド >ThreeWayMerge ------------------------------------------------------------------------------- 3ウェイ マージ(3方向マージ)をします。 Setting オプションで、設定ファイルを入力します。 例:/Setting:C:\Merge.xml ベースにするファイル >/Setting:Files\Merge\MergeSetting.xml ThreeWayMerge /Setting:Files\Merge\MergeSetting.xml マージ設定ファイル 下記のように ThreeWayMergeSet タグを設定をすれば、00_Base フォルダーをベース、 01_Left フォルダーをある人の更新、02_Right フォルダーを別の人の更新、という3つの フォルダーをマージした 03_Merged フォルダーを作成し、そのマージ結果を確認することが できます。 ThreeWayMergeSet タグには、比較するフォルダーのパスを指定します。 FF-path 属性 が使えます。 属性名は、base_path、left_path、right_path、merged_path で それぞれ名前が異なるファイルをマージできます。 ReplaceTemplate タグ には、自動的にマージした後で置き換えるテキストを設定します。 Variable タグ を使って、変数を使うこともできます。 その他のタグ名は、 ThreeWayMergeOptionClass のメンバー変数名と同じです。(一部除く) ReplaceTemplate.xml のタグも使えます。 サンプル True True Single #include Unique ThreeWayMergeSet base_path, left_path, right_path, merged_path は、すべて 同じ値でも それぞれ 指定が必要 です。 SingletonKeywords UniqueLineKeywords ThreeWayMerge_sth ソース (src) 設定ファイルに があるとき: SyncFilesX_Class::Merge (src) AttachPatchAndBackUpDictionary CopyFilesToLeafPathDictionary ThreeWayMerge (src) ThreeWayMerge_autoMergeExSub // コンフリクトを自動解決する '// AutoMerge for "bracket_A" set '// AutoMerge for "bracket_B" set ThreeWayMerge_replaceByMergeTmplateSub ReplaceTemplateClass::RunReplace ReplaceStringTemplate SyncFilesX_Class::OpenCUI (src) → SyncFilesX ソース それ以外のとき: ThreeWayMerge (上記) 関連 → ThreeWayMerge 関数 → TwoWayMerge → UpdateModule → SyncFilesX 手動で 3ウェイ マージをします。 → SyncFilesX を内部で使うツールとの比較 左は旧パッチ、右は新ベース *********************************************************************** <<< ToRegularXML >>> *********************************************************************** ToRegularXML [ 親: vbslib のショートハンド・プロンプト ] XML ファイルを Diff ツールで比較できるように、空白やタブを同じように整形します。 番号またはコマンド >ToRegularXML ------------------------------------------------------------------------------- 整形する XML ファイルのパス > ToRegularXML サンプル 参考 → save (IXMLDOMDocument) ソース → vbslib Prompt.vbs *********************************************************************** <<< Translate >>> *********************************************************************** Translate [ 親: vbslib のショートハンド・プロンプト ] 翻訳ファイルの記述に従って、テキストファイルを、英訳します。 番号またはコマンド >Translate 英訳します。 翻訳ファイル (*.trans) のパス、または、フォルダーのパス >C:\folder\sample.trans 次のファイルを上書きします。 sample.txt 続行するには Enter キーを押してください . . . Translate C:\folder\sample.trans → 複数のファイルを翻訳する → 複数行のテキストを翻訳する サンプル → Samples\Translate フォルダー サンプル スクリプト Translate "sample.trans", "JP", "EN" sample.trans (翻訳ファイル) sample.txt の翻訳前 sample.txt 日本語Japanese 英語 English 日本語から英語に変換します。 sample.txt の翻訳後 JapaneseからEnglishに変換します。 File タグに指定したファイルを翻訳します。 の間と、 の間は、複数行にしないでください。 TranslateTest を通すと、翻訳するファイル名と行番号が追記され、行番号の順番でソートされます。 英語 English 16 sample.txt 翻訳するファイルの文字コードセットを指定するときは、File タグの charset 属性に指定します。 sample.txt 英語以外が残っていてもエラーにしないようにするには、次のようにします。 サンプル : 複数のファイルを翻訳する スクリプト Translate "JapaneseToEnglish.trans", "EN", "JP" JapaneseToEnglish.trans (翻訳ファイル) sample1.txt の翻訳前 SubFolder sample1.txt sample2.c 日本語Japanese 英語English English から Japanese へ sample1.txt の翻訳後 英語 から 日本語 へ sample2.c の翻訳前 French から Japanese へ File タグは、T タグの後に置くこともできます。 sample2.c の翻訳後 BaseFolder は、File タグに指定した相対パス のベース・フォルダーのパスです。 省略時は、.trans ファイルが入っている フォルダーのパスになります。 French から 日本語 へ BaseFolder は、 TranslateEx の in_out_Config.BaseFolderPath が指定されると、 無視されます。 あるファイルに1つでも日本語が残っていると、エラーとなり、残りのファイルは翻訳 しません。 フォルダーの中のすべてのファイルに対して、残っている日本語を 一覧するときは、 CheckEnglishOnly をお使いください。 テスト → T_Translate.vbs # [T_Translate1] サンプル : 複数行のテキストを翻訳する スクリプト Translate "JapaneseToEnglish.trans", "EN", "JP" MultiLine.txt の翻訳前 JapaneseToEnglish.trans (翻訳ファイル) MultiLine.txt int main() { // メイン // 関数 } int sub() { // サブ // 関数 } MultiLine.txt の翻訳後 int main() { // Main // Function } int sub() { // Sub // Function } 複数行の置き換えをするときは、cut_indent="yes" と、 indent="…" を XML タグに付けてください。 cut_indent 属性により、XML タグの直後の改行と すべての行のインデントが翻訳テキストの指定から 外れます。 indent 属性により、すべての行のインデ ントが翻訳テキストの指定に追加されます(置き換わります)。 置き換える対象のテキストの改行コードは、CR+LF に設定してください。 翻訳前のテキストを単純な単語にしてから、翻訳後のテキストを編集することで、cut_indent や indent の効果をいろいろ試すことができます。 補足 翻訳前の単語が長い単語から置き換えが行われます。 これにより、翻訳ファイルに指定する 順番によって結果が変わる可能性が少なくなります。 ソース → vbslib Prompt.vbs テスト → T_Translate.vbs # [T_Translate1] 関連 → TranslateTest すべて英訳されるか調べる → Translate 関数 → CheckEnglishOnly (exeファイル) フォルダー全体に英語以外が無いか調べる → Switches *********************************************************************** <<< TranslateTest >>> *********************************************************************** TranslateTest [ 親: vbslib のショートハンド・プロンプト ] 翻訳ファイルの情報に従って、テキストファイルがすべて翻訳できているかどうかチェックします。 番号またはコマンド >TranslateTest 英訳のテストをします。 ★翻訳ファイル (*.trans) は上書きされます。 翻訳ファイル (*.trans) のパス、または、フォルダーのパス >C:\folder\sample.trans Enter のみ : 出力しませんが、翻訳後に日本語が残っていないことをチェックします 出力フォルダーのパス(★上書きされます)> TranslateTest C:\folder\sample.trans 翻訳ファイルの内容は上書きされるため注意してください。 翻訳するファイル名と行番号が追記され、行番号の順番でソートされます。 参考 → TranslateTest 関数 TranslateTest の関数 → Translate コマンド 翻訳するコマンド、翻訳ファイルの説明 → Translate 関数 翻訳する関数 → CheckEnglishOnly (exeファイル) フォルダー全体に英語以外が無いか調べる TranslateTest_Install コマンド を使って、*.trans ファイルの拡張子と関連付けすると、 *.trans ファイルをダブルクリックするだけですべて翻訳できているかどうかのチェックが できるようになります。 参考 → ショートカットやバッチファイルなどから専用コマンドを実行する ソース → vbslib Prompt.vbs *********************************************************************** <<< TranslateTest_Install >>> *********************************************************************** TranslateTest_Install [ 親: vbslib のショートハンド・プロンプト ] *.lines ファイルをダブルクリックしたときに、 TranslateTest が起動するようにします。 関連 → TranslateTest_Uninstall ソース → vbslib Prompt.vbs *********************************************************************** <<< TranslateTest_Uninstall >>> *********************************************************************** TranslateTest_Uninstall [ 親: vbslib のショートハンド・プロンプト ] *.lines ファイルをダブルクリックしても、 TranslateTest が起動しないようにします。 ソース → vbslib Prompt.vbs *********************************************************************** <<< TwoWayMerge >>> *********************************************************************** TwoWayMerge 2ウェイ マージ(2方向マージ)をします。 番号またはコマンド >TwoWayMerge ------------------------------------------------------------------------------- 2ウェイ マージ(2方向マージ)をします。 比較するファイル(左側) >C:\Left.txt 比較するファイル(右側) >C:\Right.txt マージした結果の出力先ファイル(★上書きします) >C:\_Merged.txt TwoWayMerge C:\Left.txt C:\Right.txt C:\_Merged.txt ソース → vbslib Prompt.vbs → ToolsLib.vbs 関連 → ThreeWayMerge → diff 関数 *********************************************************************** <<< unzip >>> *********************************************************************** unzip [ 親: vbslib のショートハンド・プロンプト ] zip 形式の圧縮ファイルを展開します。 番号またはコマンド >unzip ------------------------------------------------------------- zip ファイルを展開します。 zip ファイルと同じ名前のフォルダーを作成し、その中に展開します。 zip ファイルのパス >C:\sample1.zip "sample1_old" に改名しました。: "C:\sample1" 展開しました。 unzip C:\sample1.zip zip ファイルと同じ名前のフォルダーができ、その中に展開します。 すでに zip ファイルと同じ名前のフォルダーがあったときは、これまであった フォルダーを *_old に改名し、同じ名前のフォルダーに展開します。 すでに *_old フォルダーもあったときは、*_old2 フォルダーに改名します。 zip ファイルの中のルートに1つのフォルダーだけがあるときは、そのフォルダー の中を展開します。 テスト → T_Zip.vbs # [T_unzip_sth] 関連 → unzip 関数 *********************************************************************** <<< UpdateModule >>> *********************************************************************** UpdateModule パッチ(新モジュールのフォルダーと旧モジュールのフォルダー)があるときに、 プロジェクト フォルダーの中にある旧モジュール(の一部を変更したもの)を新モジュール (の一部を変更したもの)に置き換える、作業フォルダーをデスクトップの _UpdateModule に 作成して、モジュールを更新する作業を 3ウェイ マージを使って支援します。 Menu-5 5_Target (1B) 2_Merged(1A) Menu-2 Menu-1 4_Old (2B) 1_New (2A) Menu-4 新モジュールが共通の旧モジュールからブランチしたものでも、それをマージするのであれば、 UpdateModule コマンドが使えます。 古いパッチを新しいターゲットにあてることもできますが、新旧の関係とベース/ワークの 関係が逆に表示されます。 番号またはコマンド >UpdateModule ------------------------------------------------------------------------------- プロジェクト フォルダーの中にある、古いリビジョンのモジュールを、新しいリビジョ ンに置き換えます。 作業フォルダーをデスクトップの _UpdateModule に作成します。 New :新モジュールが入ったフォルダーのパス >C:\patch Old :旧モジュールが入ったフォルダーのパス >C:\back_up Target:旧モジュールが入ったプロジェクト フォルダーのパス >C:\Target Enter のみ:マージの設定ファイルを使わない。 マージの設定ファイル > 同期するファイルの一覧: 中央の記号の意味: [=]同じ [!]異なる [ ]両方不在 左右の記号の意味: [*]変更 [+]追加 [-]削除 [.]不変 [ ]不在 左はベース、右はワーク ------------------------------------------------------------------------------- 前回コミット時のベース: "2B_ModuleSynchronized" 前回コミット時のワーク: "1B_TargetSynchronized" ------------------------------------------------------------------------------- ■ベース(Module): "2A_ModuleNew" ■ワーク(Target): "1A_TargetMerged" 1. .=. Image.bmp 2. *!. Source.c 91. 再スキャンする [Rescan] 92. ルート・フォルダーを開く 99. 終了 番号 >2 ------------------------------------------------------------------------------- ベース:C:\2A_ModuleNew\Source.c" ワーク:C:\1A_TargetMerged\Source.c" 次のメニューの 1.で開く2つのファイルを手動で同期したら、コミットしてください。 ------------------------------------------------------------------------------- ★ベース(Module): Source.c (*変更) ★ワーク(Target): Source.c (.不変) 1. Diff で開く:同期するファイル (*異なる) [ ベース / ワーク ] 2. Diff で開く:前回コミット時の同期内容 (=同じ) [ ベース / ワーク ] 4. Diff で開く:ベース (*変更) [ 前回コミット時 / 現在 ] 5. Diff で開く:ワーク (.不変) [ 前回コミット時 / 現在 ] 44.Diff で開く:[ 前回コミット時のベース / ベース / ワーク ] 55.Diff で開く:[ ベース / ワーク / 前回コミット時のワーク ] 6. ファイルまたはフォルダーを開く 8. 同期をコミットする 9. 戻る 番号 > 同期が完了したら、その内容をプロジェクトに反映させてください。 同期済み:"C:\1A_TargetMerged" Targetプロジェクト:"C:\Target" UpdateModule C:\patch C:\back_up C:\Target プロジェクト フォルダーは、複数のモジュールからなるフォルダーという意味で、特別な構成をした フォルダーではなく、普通のフォルダーです。 UpdateModule では、置き換える対象となる モジュールを持っているプロジェクト フォルダーのことをターゲットと呼んでいます。 「ベース」と表示されているものは、モジュール単体です。 「ワーク」と表示されているものは、ターゲット プロジェクトです。 「6. ファイルまたはフォルダーを開く」 で選ぶファイルの意味は、次のとおりです。 表示 UpdateModule コマンドでの意味 1. ベース 新モジュール単体 [New, 2A] 2. ワーク ターゲット(マージ後) [Merged, 1A] 4. 前回コミット時のベース コミット前は、旧モジュール単体 [Old, 2B] コミット後は、新モジュール単体 5. 前回コミット時のワーク コミット前は、ターゲット(マージ前) [Target, 1B] コミット後は、ターゲット(マージ後) 3ウェイ マージの Base, Left, Right は、UpdateModule の 4. Old (2B), 1. New (2A), 5. Target (1B) です。 3ウェイ マージにおける、それぞれの差分と、上記メニュー(SyncFilesX のメニュー)との 対応は、次の通りです。 なお、可能な限り自動的にマージを行って 2. Merged(1A) を作成して いますが、2. Merged(1A) に ThreeWayMerge のコンフリクトのタグが付くこともあります。 Menu-5 5. Target (1B) 2. Merged(1A) Menu-2 Menu-1 4. Old (2B) 1. New (2A) Menu-4 Menu-2 の差分が Menu-1 の差分と同じ、または、Menu-4 の差分が Menu-5 の差分と同じなら 一般にマージ完了です。 差分が少ないほうのペアで調整するとよいでしょう。 参考 → MakePatchAndBackUpDictionary 新旧モジュールからパッチをあてます → ThreeWayMerge 3ウェイ マージ → マージ設定ファイル → SyncFilesX 新旧の比較、プロジェクトとモジュールの比較 ソース → vbslib Prompt.vbs → SyncFilesX ソース テスト → T_ModuleAssort.vbs T_UpdateModule_sth → AttachPatchAndBackUpDictionary のテスト 関連 → ModuleAssort モジュール/ターゲット/リビジョンに分類 → SyncFilesX → SyncFilesX を内部で使うツールとの比較 *********************************************************************** <<< XmlText >>> *********************************************************************** XmlText テキストを XML/HTML の実体参照に変換します。 番号またはコマンド >XmlText ------------------------------------------------------------------------------- テキストを XML/HTML の実体参照に変換します。 1) テキスト → XML/HTML テキストの実体参照 [ToRef] 番号またはコマンド名を入力してください >1 Enter のみ:クリップボードの内容を入力とします。 変換前のテキストが書かれたファイルのパス > 変換しました。 XmlText 1 連続空白 の置き換えは行いません。 関連 → XmlText *********************************************************************** <<< 開発サポートツール >>> *********************************************************************** 開発サポートツール [ 親: vbslib のショートハンド・プロンプト ] vbslib を使って作られたツールです。 vbslib_updater vbslib を使ったスクリプトをバージョンアップする RepliCmp 複数のフォルダで指定した名前のファイルの内容をマージする手助けをします。 PartCmp テキストファイルの一部が同じかどうか比較します。 PartRep テキストファイルの一部を置き換えます。 Syncs 2つのファイルの同期を自動的に取ります SearchNewFile 新しく更新したファイルを探します XmlFilter XML の一部を取り出します。 ConvSymbol C言語の #define から、数値と文字列の配列のコードを生成します。 vbslib を使うときに役に立つプログラムを参考に挙げます。 → Microsoft Visual Studio (Web) スクリプト・デバッガが使えるのは、Standard 以上 → Microsoft Script Editor (Web) MS Office をフルインストールしたときに使えます → 構造化エディタ (Web) vbslib は構造化テキストになっています → Rekisa テキスト比較 diff ツール → サクラエディタ (Web) テキスト・エディター → Snap Note (Web) ドキュメントからソースコードにジャンプできます 関連 → 開発環境操作、 Visual Studio *********************************************************************** <<< CheckEnglishOnly (exeファイル) >>> *********************************************************************** CheckEnglishOnly (exeファイル) CheckEnglishOnly.exe /Folder:FolderA /Setting:Setting.ini テキスト・ファイルの中に、英文字以外の文字が含まれるファイルを一覧します。 【引数】 /Folder チェックするフォルダーのパス /Setting 設定ファイルのパス コマンド・プロンプトから実行してください。 実行ファイルまたはソースがある場所: → scriptlib\vbslib\CheckEnglishOnly フォルダー → _src\Test\tools\scriptlib\vbslib\CheckEnglishOnly フォルダー 設定ファイルの例: Setting.ini [CheckEnglishOnlyExe] ExceptFile = *.exe ExceptFile = *.lib ExceptFile = *.dll ; comment ExceptFile = *\AnyFolder.txt ExceptFile = Sub\StepPath.txt ExceptFile = *\SubFolder\* * から始まる設定の場合は、すべてのフォルダーに対する設定になります。 相対パスの基準は、設定ファイルがあるフォルダーです。 出力の例: テキストファイルが英語だけになっているかチェックします。 チェックするファイルまたはフォルダーのパス: TestData 設定ファイルのパス: TestData\SettingForCheckEnglish.ini 相対パスの基準は、設定ファイルがあるフォルダーです。 ただし、/Setting オプションがないときは、チェックするフォルダーです。 ソース → CheckEnglishOnly_src_121106.zip テスト → T_CheckEnglishOnly.vbs # T_CheckEnglishOnly 関連 → CheckEnglishOnly vbslib 版 → CheckEnglishOnly コマンド・プロンプト版 → TranslateTest *********************************************************************** <<< コールツリー (CheckEnglishOnly) >>> *********************************************************************** コールツリー (CheckEnglishOnly) CheckEnglishOnly CheckEnglishOnly.exe /Folder:"FolderPath" /Setting:"SettingForCheckEnglish.ini" ファイル一覧、設定ファイル関係: /* Set "except_names" : 設定ファイルに指定した "ExceptFile" */ → CheckEnglishOnly.c if ( IniStr_isLeft( line, _T("ExceptFile") ) ) { e= Set2_alloc( &except_names, &except_name, StrMatchKey ); /* Set "paths" : チェックするファイルのパスの集合。 FileT_callByNestFind Main_getFilePathFromNestFind /* "path" が、チェックをしないファイル "except_names" に含まれるならスキップする */ if ( StrMatchKey_isMatch( except_name, path ) ) { break; } *********************************************************************** <<< ReplaceSymbolsClass >>> *********************************************************************** ReplaceSymbolsClass (src) 複数のファイルの中の複数の単語(文字列)を一度に置き換えます。 参考 → ReplaceSymbols コマンド サンプル Set w_= AppKey.NewWritable( "." ).Enable() Set rep = new ReplaceSymbolsClass rep.Load "ReplaceSymbols.xml" rep.ReplaceFiles ユーザーに確認を求めないときは、rep.IsSubmit = False してください。 テスト → T_ReplaceSymbols フォルダー *********************************************************************** <<< Load (ReplaceSymbolsClass) >>> *********************************************************************** [ 親: ReplaceSymbolsClass ] Load (ReplaceSymbolsClass) Sub ReplaceSymbolsClass::Load( XML_Path as string, Config as ReplaceSymbolsLoadConfigClass ) ReplaceSymbols の設定ファイル を読み込みます。 【引数】 XML_Path ReplaceSymbols の設定ファイルのパス Config Empty または、設定 ReplaceSymbolsLoadConfigClass Class ReplaceSymbolsLoadConfigClass Public IsReverse '// as boolean End Class IsReverse = True なら、Replace タグの from と to を入れ替えて、置き換えます。 *********************************************************************** <<< ReplaceFiles (ReplaceSymbolsClass) >>> *********************************************************************** [ 親: ReplaceSymbolsClass ] ReplaceFiles (ReplaceSymbolsClass) Sub ReplaceSymbolsClass::ReplaceFiles() 設定に従って、指定した複数のファイルの中の文字列の単語を置き換えます。 設定するには、 Load メソッド を使います。 *********************************************************************** <<< ConvSymbol >>> *********************************************************************** ConvSymbol (src) → ConvSymbol フォルダ Sub ConvSymbol( InPath as string, OutPath as string, Opt as ConvSymbolOption ) ConvSymbolOption cscript.exe ConvSymbol.vbs /in_type:CDefine /in:file.h /out_type:CLang /out:file.c /strs_array_name:g_Symbols_strs /ids_array_name:g_Symbols_ids シンボルを定義しているC言語の #define から、数値と文字列の配列のコードを生成します。 【引数】 in_type CDefine 固定 in C言語の #define が書かれたテキスト・ファイルのパス out_type CLang 固定 out 数値と文字列の配列の C言語コードの出力先となるファイルのパス strs_array_name 文字列の配列の変数名 ids_array_name 数値の配列の変数名 ConvSymbolOption クラス Class ConvSymbolOption Public InType Public OutType Public StrsFuncName Public IDsFuncName End Class 内容は、上記引数と同じ サンプル サンプル・スクリプト: Set conv_option = new ConvSymbolOption Set o = conv_option o.InType = "CDefine" o.OutType = "CLang" o.StrsFuncName = "g_Symbols_strs" o.IDsFuncName = "g_Symbols_ids" ConvSymbol "file.h", "file.c", conv_option 入力ファイル・サンプル: #define Sym1 10 #define Sym2 11 出力ファイル・サンプル: TCHAR* g_Symbols_strs[] = { _T("Sym1"), _T("Sym2"), }; int g_Symbols_ids[] = { 10, 11, }; StrT_convStrToId 関数(clib) を使うと、文字列から数値に変換することができます。 int id; TCHAR str[256]; _tcscpy_s( str, _countof(str), _T("Sym1") ); id = StrT_convStrToId( str, g_Symbols_strs, g_Symbols_ids, sizeof(g_Symbols_strs)/sizeof(*g_Symbols_strs), 0 ); 参考 → StrT_convStrToId C ファイルから、ヘッダファイルを作成するスクリプトは、下記のようになります。 '//=== make g("OutTableH") Dim rep, line Set rep = StartReplace( g("OutTableC"), g("OutTableH"), True ) rep.w.WriteLine "#if __cplusplus" rep.w.WriteLine " extern ""C"" {" rep.w.WriteLine "#endif" rep.w.WriteLine "" Do Until rep.r.AtEndOfStream line = rep.r.ReadLine() If InStr( line, "g_Symbols_strs" ) > 0 or InStr( line, "g_Symbols_ids" ) > 0 Then rep.w.WriteLine "extern "+ Replace( line, " = {", ";" ) End If Loop rep.w.WriteLine "" rep.w.WriteLine "#if __cplusplus" rep.w.WriteLine " } // extern ""C""" rep.w.WriteLine "#endif" rep.w.WriteLine "" rep.w.WriteLine "// "+ g("OutTableH") +" was made by """+ WScript.ScriptName +"""" rep.Finish テスト → Test_ConvSymbol フォルダ *********************************************************************** <<< TortoiseMerge >>> *********************************************************************** TortoiseMerge テキストの差分を表示するプログラムです。 TortoiseSVN (SubVersion) に付属しています。 参考 → TortoiseMergeの使い方 - TortoiseSVN (Web) *********************************************************************** <<< Rekisa >>> *********************************************************************** Rekisa テキストの差分を表示するプログラムです。 開発元 → FrozenLib (Web) 関連 → Rekisa - 窓の杜 (Web) → Rekisa - ベクターソフトニュース (Web) 推奨初期設定 [ 設定 | 比較フィルタ | タブと空白を削除 ] を選択してから、Rekisa を再起動します。 [ 設定 | 外部ツール ] サクラエディタで開く(&S) C:\Program Files\sakura\sakura.exe "$(PATH)" -Y=$(Y+1) ( -X=$(X+1) は使いにくい) → サクラエディタとの連携 (Web) フォルダを開く(&F) explorer /SELECT, "$(PATH)" *********************************************************************** <<< ArgsLog >>> *********************************************************************** ArgsLog ArgsLog.exe に指定したパラメーターを、カレント・フォルダーの ArgsLog.txt ファイルに追記出力します。 テスト用です。 テスト プログラムが、テスト対象のプログラム(exe ファイル)を起動する代わりに ArgsLog.exe を起動 したり、テスト対象のプログラムに例えば /ArgsLog オプションを付けることで関数の内部から起動する exe ファイルを ArgsLog.exe に切り替えたりすることがよくあります。 たとえば、テスト対象のプログラム がテキスト エディターを起動する関数を呼び出したとき、その関数の中で ArgsLog.exe が起動され、 テキスト エディターが起動したものとしてテストを実施し、起動したコマンドラインについて ArgsLog.txt ファイルをチェックします。 参考 → ArgsLog フォルダー → テキスト エディターで開くファイルのパスをテストでチェックするとき → Diff ツールで開くファイルのパスをテストでチェックするとき 関連 → ArrayFromCmdLine → ログ *********************************************************************** <<< エディター等の設定変更 (vbslib 外部プログラム設定、setting フォルダー) >>> *********************************************************************** エディター等の設定変更 (vbslib 外部プログラム設定、setting フォルダー) vbslib を使ったスクリプトは、スクリプトがテキスト・ファイルを開くために起動するエディターや、 テキストを比較するツールなどを、「C:\Program Files」 フォルダーを調べて自動的に探します。 探し方を変更するときは、 vbslib Prompt.vbs の Setting コマンド で設定を変更してください。 なお、設定は、 setting_default フォルダーや setting フォルダー の PC_setting_default.vbs や PC_setting.vbs に入っている下記の関数定義です。 vbslib が呼び出すユーザー設定関数 setting フォルダー の中の .vbs ファイルに、ユーザーが定義する関数です。 PC_setting.vbs PC_setting_default.vbs Setting_openFolder 関数 フォルダーを開きます。 Setting_getEditorCmdLine 関数 テキスト エディターのパスを返します。 Setting_getDiffCmdLine 関数 テキスト比較(Diff)ツールのパスを返します。 Setting_getFolderDiffCmdLine 関数 フォルダー比較(Diff)ツールのパスを返します。 Setting_getAdminUserName 関数 管理者のユーザ名を返します。 vbs_inc_setting.vbs Setting_getIncludePathes インクルードする外部 .vbs ファイルのパスの配列を返す。 Setting_onAfterInclude すべてのモジュールをインクルードした後のコールバック。 関連 → ArgsLog テスト用に、外部プログラムを起動したログを出力する *********************************************************************** <<< setting フォルダー, setting_default フォルダー >>> *********************************************************************** setting フォルダー, setting_default フォルダー [ 親: setting フォルダ ] setting フォルダーは、vbslib の設定を記述した vbs ファイルを格納するフォルダーです。 scriptlib\vbslib\setting フォルダーなどの中に、スクリプト・ファイルを配置し、関数定義を 記述することで設定を行います。 例) Setting_getEditorCmdLine 関数 scriptlib vbslib setting ← setting フォルダー、下記の 1. 2. 3. 4. があるフォルダー Xxx_setting.vbs ← 設定ファイル 設定ファイルの中では、vbs_inc_sub.vbs ファイルで定義されている関数だけを使用できます。 スクリプトを実行すると、はじめに vbs_inc によって、setting フォルダーに入っている、 すべての vbs ファイルの内容を実行します。 つまり、vbs ファイルの名前は、自由に付ける ことができます。 この実行によって、関数が定義されます。 setting フォルダーは、複数あり ますが、下記の 1. 2. 3. 4. 5. の順番で実行します。 同じ関数を他の .vbs ファイルでも定義して いるときは、後で定義したものが優先されます。 4 の setting フォルダーにある設定が最も 優先されます。 ただし、 include や ExecuteGlobal を呼び出すと定義は変更されます。 (任意のフォルダー) メイン.vbs ← 5. スクリプトの中の include や ExecuteGlobal scriptlib vbslib setting Xxx_setting.vbs ← 4. 上記(任意のフォルダー)の中の設定 setting_default Xxx_setting_default.vbs ← 1. デフォルト設定(通常、編集しません) Windows 7, 10 : C:\Users\user1\AppData\Roaming Windows XP : C:\Document and Settings\user1\Application Data %APPDATA% Scripts Xxx_setting.vbs ← 2. PC全体の設定 (*2) %myhome_mem%\prog\scriptlib\setting_mem 環境変数を使用 Xxx_setting.vbs ← 3. USB メモリーに入っている PC全体の設定 2.が設定されていない PC を一時的に使うときのため 下記の 1. 2. 3. 4. 5. の順番で実行し、後で定義したものが優先されます。 1. 2. 3. 4. のファイルがあるフォルダーのパスは、 g_vbslib_setting_paths にあります。 1. g_vbslib_ver_folder の setting_default フォルダの中の全 .vbs ファイル 2. %APPDATA%\Scripts フォルダの中の全 .vbs ファイル (*2) 3. %myhome_mem%\prog\scriptlib\setting_mem フォルダの中の全 .vbs ファイル (*1) 4. g_vbslib_ver_folder の setting フォルダの中の全 .vbs ファイル 5. スクリプトの中の include や ExecuteGlobal (*1) 環境変数 myhome_mem は、必要に応じて設定してください。 [ スタート | コンピューター ] を右クリック [ プロパティ | 詳細設定 | 環境変数 ] [ ユーザー環境変数 ] に設定してください。 (*2) コマンドプロンプトを開いて、echo %APPDATA%\Scripts と入力すると、実際の パスが分かります。 ソース → 処理フロー (vbs_inc/setting) テスト → [T_Setting] setting フォルダのテスト 関連 → 部分Empty構造体パラメータ *********************************************************************** <<< 関数定義の変更方法 >>> *********************************************************************** 関数定義の変更方法 Main 関数を呼び出す前に関数定義を変えるには、 setting フォルダー, setting_default フォルダー に変更後の関数定義が入ったスクリプトを配置します。 Main 関数を呼び出した後は、 include や ExecuteGlobal などを呼び出すと関数定義は変更されます。 テスト スクリプトから呼ばれる関数の定義を変更するときは、include するとよいでしょう。 変更する前の関数も呼び出すときは、 FuncRedir_add を使ってください。 *********************************************************************** <<< 設定を操作する関数 >>> *********************************************************************** 設定を操作する関数 *********************************************************************** <<< CheckSettingFunctionExists >>> *********************************************************************** CheckSettingFunctionExists Sub CheckSettingFunctionExists( FunctionName as string ) setting フォルダーにあるスクリプトに書くべき関数があることをチェックします。 【引数】 FunctionName 定義されているかどうかをチェックする関数の名前 IsDefined との違いは、関数が無ければ下記のようなエラーが発生することです。 サンプル 設定関数をチェックしてから、呼び出します。 CheckSettingFunctionExists "Setting_getNaturalDocsPerlPath" natural_docs_path = Setting_getNaturalDocsPerlPath() ソース → vbs_inc_sub.vbs 関連 → GetExistPathInSetting *********************************************************************** <<< GetExistPathInSetting >>> *********************************************************************** GetExistPathInSetting [ 親: setting フォルダー ] Function GetExistPathInSetting( Paths as array of string, SettingFuncName as string ) Paths 配列に格納されているパスのうち、最初にファイルが存在するパスを返します。 【引数】 Paths パスの配列 SettingFuncName 本関数を呼び出している関数の名前 返り値 ファイルが存在するパス GetExistPathInSetting は、setting フォルダーの中で定義する関数の中から呼び出せる関数です。 Paths の要素に Empty を含んでいてもエラーにはなりません。 もし、該当するファイルが存在しなければ、setting フォルダーにある vbs ファイルを修正する ように、警告が表示されます。 CheckSettingFunctionExists の呼び出しも検討してください。 サンプル Function Setting_getEditorCmdLine( i ) paths = Array( _ g_sh.ExpandEnvironmentStrings( "%ProgramFiles%\sakura\sakura.exe" ), _ g_sh.ExpandEnvironmentStrings( "%windir%\notepad.exe" ) ) exe = GetExistPathInSetting( paths, "Setting_getEditorCmdLine" ) → Setting_getEditorCmdLine のサンプル (src) ソース → vbs_inc_sub.vbs *********************************************************************** <<< EditAndRunScript >>> *********************************************************************** EditAndRunScript (src) Sub EditAndRunScript( ScriptPath as string, IsKeepThisProcessIfRun as boolean ) VBScript ファイルをテキスト・エディターで開いて、編集後に実行します。 【引数】 ScriptPath VBScript ファイルのパス。 Empty = WScript.ScriptFullName IsKeepThisProcessIfRun False=実行開始したら現在のプロセスを終了する 本関数を呼び出すと、 Setting_getEditorCmdLine に登録したテキスト・エディターを使って VBScript ファイル開きます。 テキスト・エディターを閉じたら、編集した VBScript ファイルを実行するかどうかを確認する ウィンドウが開きます。 実行するを選んだら、実行を開始して、IsKeepThisProcessIfRun = False なら、現在実行中のプロセスは終了します。 つまり、新しい VBScript ファイルの プロセスに切り替わります。 IsKeepThisProcessIfRun = True なら、実行を開始して、 本関数から戻ります。 実行することをキャンセルすると選んだら、そのまま本関数から戻ります。 サンプル Sub EditAndRunThisScript() EditAndRunScript Empty, False End Sub テスト → T_EditAndRunScript フォルダ *********************************************************************** <<< Setting_getExistSettingPath >>> *********************************************************************** Setting_getExistSettingPath Function Setting_getExistSettingPath( StepPath as string ) as string setting フォルダー に存在する1つのファイルまたはフォルダーのパスを返します。 【引数】 StepPath 存在をチェックするファイルまたはフォルダーの相対パス 返り値 見つかったファイルまたはフォルダーの絶対パス、または、Empty g_vbslib_setting_paths 配列にあるフォルダーに、ファイルまたはフォルダーが存在するかどうかを チェックし、最も優先するパスを返します。 g_vbslib_setting_paths 配列の後の方の要素ほど優先します。 サンプル AssertExist g_vbslib_ver_folder + "setting_default" AssertExist g_vbslib_ver_folder + "setting" setting_path = Setting_getExistSettingPath( "MySetting.xml" ) If not IsEmpty( setting_path ) Then '// ... End If Assert setting_path = g_vbslib_ver_folder + "setting" setting_path "MySetting.xml" setting フォルダーの2つに MySetting.xml ファイルがあるとき、優先する方のファイルのパスを setting_path 変数に代入しています。 ソース → vbs_inc_sub.vbs テスト → T_Setting.vbs T_Setting_getExistSettingPath *********************************************************************** <<< g_vbslib_setting_paths >>> *********************************************************************** g_vbslib_setting_paths Dim g_vbslib_setting_paths( ) as string setting フォルダー のパスの配列。 配列の要素は、以下の通りです。 g_vbslib_ver_folder + "setting_default" g_vbslib_ver_folder env("%myhome_mem%\prog\scriptlib\setting_mem") env %myhome_mem% が定義されている場合のみ env(""%APPDATA%\Scripts"") g_vbslib_ver_folder + "setting" ソース → vbs_inc_sub.vbs 関連 → Setting_getExistSettingPath setting フォルダーに存在する1つのファイルのパスを返します。 *********************************************************************** <<< Setting_getIncludePathes >>> *********************************************************************** Setting_getIncludePathes (src) [ 親: setting フォルダー ] Function Setting_getIncludePathes( IncludeType as string ) as array of string scriptlib フォルダーの中で、インクルードする .vbs ファイルのパスの配列を返します。 参考 → include → IncludeType 引数 (旧 g_IncludeType) scriptlib フォルダに共通な環境変数の設定も、Setting_getIncludePathes 関数の中で行います。 参考 → デフォルトの環境変数の設定タイミング サンプル scriptlib\vbslib\setting\vbs_inc_setting.vbs Function Setting_getIncludePathes( IncludeType ) Setting_getIncludePathes = Array(_ "vbslib.vbs", "sample_lib.vbs" ) End Function vbslib.vbs sample_lib.vbs パスは、vbs_inc_sub.vbs ファイルがあるフォルダからの相対パスです。 vbc_inc_400.vbs ファイルは、指定しなくてもインクルードされます。 IncludeType 引数 (旧 g_IncludeType) IncludeType は通常 Empty ですが、下記のように scriptlib ヘッダで、IncludeType 変数の値を 設定すると、IncludeType 引数に値が渡ります。 この値に応じて、インクルードするモジュール を選択することができます '--- start of parameters for vbslib include ------------------------------- g_Vers.Add "IncludeType", "TypeA" TypeA Function Setting_getIncludePathes( IncludeType ) If IncludeType = "TypeA" Then Setting_getIncludePathes = Array( "vbslib.vbs", "sample_lib.vbs" ) End If End Function TypeA ソース → vbs_inc_setting.vbs コールツリー → Setting_getIncludePathes 関連 → vbs_inc *********************************************************************** <<< Setting_onAfterInclude >>> *********************************************************************** [ 親: setting フォルダー ] Setting_onAfterInclude Sub Setting_onAfterInclude() すべてのモジュールをインクルードした後にコールバックされる関数。 非推奨 Setting_onAfterInclude を使うと暗黙的に処理が行われるので、推奨されません。 代わりに include と SearchParent を使って、あるフォルダー(scriptlib フォルダーがある フォルダーなど)の中にあるすべてのスクリプトに共通の処理を、インクルードして、呼び 出してください。 メイン.vbs Sub main() include SearchParent( "Common.vbs" ) Common_main End Sub Common.vbs Sub Common_main() '// Setting_onAfterInclude 関数の代わり set_ "VAR", "value" End Sub 参考 → TestCommon.vbs Setting_getIncludePathes で返される .vbs ファイルをインクルードした後で行う処理を、 Setting_onAfterInclude 関数に記述してください。 Setting_onAfterInclude 関数の中では、 .vbs ファイルで定義されている関数などを呼び出すことができます。 あるフォルダの中(scriptlib フォルダごと)にあるすべてのスクリプトの既定の環境変数を 設定することなどを行います。 → 処理フロー コールツリー *********************************************************************** <<< Setting_openFolder >>> *********************************************************************** Setting_openFolder (src) [ 親: setting フォルダー ] Sub Setting_openFolder( in_FolderOrFilePath ) フォルダーを開きます。 【引数】 in_FolderOrFilePath フォルダー、またはファイルのパス この関数の内容を変えることで、エクスプローラー以外のファイラーを使うことが出来ます。 in_FolderOrFilePath 引数にファイルのパスが渡されたときは、そのファイルを選択状態にしてくだ さい。 ファイラーがその処理に対応していないときは、ファイルを選択状態にしなくても構いません。 アプリケーションは、Setting_openFolder 関数を呼び出すのではなく、 OpenFolder 関数 を呼び出して ください。 開くファイルのパスをテストでチェックするとき Setting_openFolder 関数を呼び出したときに、フォルダーを開かずに、開こうとしたフォルダーのパス を echo 表示するには、下記のコードのようにしてください。 include SearchParent( "scriptlib\vbslib\ArgsLog\SettingForTest_pre.vbs" ) include SearchParent( "scriptlib\vbslib\ArgsLog\SettingForTest.vbs" ) SetVar "Setting_openFolder", "echo" '// echo 出力に変更する Setting_openFolder "FolderA" 参考 → scriptlib\vbslib\ArgsLog\SettingForTest_pre.vbs → scriptlib\vbslib\ArgsLog\SettingForTest.vbs → 関数定義の変更方法 参考 → エディター等の変更 (setting フォルダー) → Diff ツールなどで開くファイルのパスをテストでチェックするとき ソース → PC_setting_default.vbs *********************************************************************** <<< Setting_getEditorCmdLine >>> *********************************************************************** Setting_getEditorCmdLine [ 親: setting フォルダー ] Function Setting_getEditorCmdLine( i as integer or string ) as string テキスト エディターを開くコマンドラインを返します。 【引数】 i パス(文字列)、または、コマンドラインの種類(数値) 返り値 コマンドライン文字列, i に対応していないときは Empty 参考 → エディター等の変更 (setting フォルダー) 使用サンプル → GetEditorCmdLine i が文字列のとき i は、開こうとするテキストファイルの絶対/相対パスと、行番号、または開いた後に 検索するキーワードであるとして、実際に実行するコマンドラインを返します。 上記「使用サンプル」を参照。 i の例: C:\FolderA\FileA.txt 行番号を含む i の例: C:\FolderA\FileA.txt(100) キーワードを含む i の例: C:\FolderA\FileA.txt#FuncA 参考 → GetEditorCmdLine のソース i=0 のとき テキストエディタのパスのみ返す。 "" で囲まないこと 返り値の例: C:\Windows\notepad.exe i=1 のとき 開くパスを %1 にした、テキストエディタを起動するコマンドラインを返す。 返り値の例: "C:\Windows\notepad.exe" "%1" i=2 のとき 開くパスを %1、開く行番号を %L にした、テキストエディタを起動するコマンドライン を返す。 %L に対応できないときは、%1 だけ使ったコマンドラインを返します。 返り値の例: "C:\Program Files\sakura\sakura.exe" -Y=%L "%1" 返り値の例: "C:\Windows\notepad.exe" "%1" i=3 のとき 開くパスを %1、開いた後に検索するキーワードを %2 にした、テキストエディタを 起動するコマンドラインを返す。 %2 に対応できないときは、%1 だけ使ったコマンド ラインを返します。 返り値の例: "C:\Program Files\search_open\search_open.exe" "%1#%2" 返り値の例: "C:\Windows\notepad.exe" "%1" テキスト エディターで開くファイルのパスをテストでチェックするとき Setting_getEditorCmdLine 関数の中で ArgsLog を呼び出すスクリプトを include (関数定義を上書き)すると、テキスト エディターで開こうとしたファイル のパスを、ArgsLog.txt に追記するようになります。 ArgsLog.txt の内容を チェックすれば、開くファイルのパスが正しいかどうかをチェックできます。 参考 → _src\Test\tools\T_SyncFiles\SettingForTest.vbs → 関数定義の変更方法 ソース → PC_setting_default.vbs テスト → T_Open_1.vbs 関連 → GetEditorCmdLine *********************************************************************** <<< Setting_getDiffCmdLine >>> *********************************************************************** Setting_getDiffCmdLine [ 親: setting フォルダー ] Function Setting_getDiffCmdLine( i as integer ) as string テキスト ファイルの比較(Diff)を実行するコマンドラインのテンプレートを返します。 【引数】 i コマンドラインの種類 返り値 コマンドライン文字列、Empty=対応できない 参考 → エディター等の変更 (setting フォルダー) i=0 のとき Diff のパスのみ返す。 "" で囲まないこと 例: C:\Program Files\Rekisa\Rekisa.exe i=2 のとき 比較する2つのファイルのパスを %1, %2 にした、Diff を起動するコマンド ラインを返す。 例: "C:\Program Files\Rekisa\Rekisa.exe" "%1" "%2" 例: "C:\Program Files\WinMerge\WinMergeU.exe" "%1" "%2" i=3 のとき 比較する3つのファイルのパスを %1, %2, %3 にした、Diff を起動する コマンドラインを返す。 対応できないときは、Empty を返す。 例: "C:\Program Files\Rekisa\Rekisa.exe" "%1" "%2" "%3" i=21 のとき 比較する2つのファイルのパスを %1, %2 にして、%1 の行番号を %L にした、Diff を起動するコマンドラインを返す。 例: "C:\Program Files\Rekisa\Rekisa.exe" -Y+1=%L -ActiveFile="%1" "%1" "%2" i=22 のとき 比較する2つのファイルのパスを %1, %2 にして、%2 の行番号を %L にした、Diff を起動するコマンドラインを返す。 例: "C:\Program Files\Rekisa\Rekisa.exe" -Y+1=%L -ActiveFile="%2" "%1" "%2" i=31 のとき 比較する3つのファイルのパスを %1, %2, %3 にして、%1 の行番号を %L にした、Diff を起動するコマンドラインを返す。 例: "C:\Program Files\Rekisa\Rekisa.exe" -Y+1=%L -ActiveFile="%1" "%1" "%2" "%3" i=32 のとき 比較する3つのファイルのパスを %1, %2, %3 にして、%2 の行番号を %L にした、Diff を起動するコマンドラインを返す。 例: "C:\Program Files\Rekisa\Rekisa.exe" -Y+1=%L -ActiveFile="%2" "%1" "%2" "%3" i=33 のとき 比較する3つのファイルのパスを %1, %2, %3 にして、%3 の行番号を %L にした、Diff を起動するコマンドラインを返す。 例: "C:\Program Files\Rekisa\Rekisa.exe" -Y+1=%L -ActiveFile="%2" "%1" "%2" "%3" Diff ツールなどで開くファイルのパスをテストでチェックするとき Setting_getDiffCmdLine 関数の中で ArgsLog を呼び出すスクリプトを include (関数定義 を上書き)すると、Diff ツールで開こうとしたファイルのパスを、ArgsLog.txt に追記するように なります。 ArgsLog.txt の内容をチェックすれば、開くファイルのパスが正しいかどうかを チェックできます。 例: include SearchParent( "_src\Test\tools\T_SyncFiles\SettingForTest_pre.vbs" ) include SearchParent( "_src\Test\tools\T_SyncFiles\SettingForTest.vbs" ) old_setting = GetVar( "Setting_getDiffCmdLine" ) SetVar "Setting_getDiffCmdLine", "ArgsLog" '// ログへの記録に変更する start GetDiffCmdLine( "file1.txt", "file2.txt" ) AssertFC "ArgsLog.txt", "Files\DiffAnswer.txt" '// ログをチェックする SetVar "Setting_getDiffCmdLine", old_setting '// ログへの記録をやめる 下記の vbs は、g_Setting_getEditorCmdLine などの関数定義も上書きして、ArgsLog.txt に追記 します。 参考 → _src\Test\tools\T_SyncFiles\SettingForTest_pre.vbs → _src\Test\tools\T_SyncFiles\SettingForTest.vbs → 関数定義の変更方法 → Diff ツールなどで開くフォルダーのパスをテストでチェックするとき ソース → PC_setting_default.vbs 関連 → GetDiffCmdLine Diffを実行するコマンドラインを返す → Rekisa - テキスト比較ツール → TortoiseMerge - テキスト比較ツール *********************************************************************** <<< Setting_getFolderDiffCmdLine >>> *********************************************************************** Setting_getFolderDiffCmdLine Function Setting_getFolderDiffCmdLine( i as integer ) as string フォルダーの比較(Diff)を実行するコマンドラインのテンプレートを返します。 【引数】 i コマンドラインの種類 返り値 コマンドライン文字列、Empty=対応できない 参考 → エディター等の変更 (setting フォルダー) i=0 のとき Diff のパスのみ返す。 "" で囲まないこと 例: C:\Program Files\DF\DF.exe i=2 のとき 比較する2つのフォルダーのパスを %1, %2 にした、Diff を起動するコマンドラインを返す。 例: "C:\Program Files\DF\DF.exe" "%1" "%2" i=3 のとき 比較する3つのフォルダーのパスを %1, %2, %3 にした、Diff を起動して比較を実行する コマンドラインを返す。 対応できないときは、Empty を返す。 例: "C:\Program Files\DF\DF.exe" "%1" "%2" "%3" i=30〜37のとき 比較する3つのフォルダーのパスを %1, %2, %3 にした、Diff を起動するコマンドラインを返す。 ただし、i=30 のときは比較を実行しない(起動後にユーザーが開始することはできる)。 i = 33, 35, 36 のときは、2つの比較を実行する。 i の 1の位は、%1=1, %2=2, %3=4 の論理和。 つまり、33=%1と%2、34=%1と%3、36=%2と%3 を比較する。 起動後にユーザーが 3つの比較を することはできる。 対応できないときは、Empty を返す。 例: "C:\Program Files\master2\master2.exe" "%1" "%2" "%3" -e=5 Diff ツールなどで開くフォルダーのパスをテストでチェックするとき Setting_getFolderDiffCmdLine 関数の中で DiffCUI_InCurrentProcess を呼び出すスクリプトを include (関数定義を上書き)すると、Diff ツールで開こうとしたファイルのパスを表示します。 表示したログをチェックすれば、開くファイルのパスが正しいかどうかをチェックできます。 例: include SearchParent( "_src\Test\tools\T_SyncFiles\SettingForTest_pre.vbs" ) include SearchParent( "_src\Test\tools\T_SyncFiles\SettingForTest.vbs" ) SetVar "Setting_getFolderDiffCmdLine", "DiffCUI" '// DiffCUI を起動するようにする start GetDiffCmdLine( "file1.txt", "file2.txt" ) AssertFC "ArgsLog.txt", "Files\DiffAnswer.txt" '// ログをチェックする 下記の vbs は、g_Setting_getEditorCmdLine などの関数定義も上書きして、ArgsLog.txt に追記 します。 参考 → _src\Test\tools\T_SyncFiles\SettingForTest_pre.vbs → _src\Test\tools\T_SyncFiles\SettingForTest.vbs → 関数定義の変更方法 ソース → PC_setting_default.vbs 関連 → GetDiffCmdLine Diffを実行するコマンドラインを返す *********************************************************************** <<< Setting_getAdminUserName >>> *********************************************************************** Setting_getAdminUserName [ 親: setting フォルダー ] Function Setting_getAdminUserName() as string 管理者のユーザー名を返します。 %APPDATA%\Scripts\account_setting.vbs ファイルを新規作成して下記のように記述してください。 Function Setting_getAdminUserName() Setting_getAdminUserName = "Administrator" End Function Windows XP で自分が管理者であったり、Windows 7 で管理者になれる ユーザであれば、関数定義の記述は不要です。 管理者のユーザー名は、 g_admin = 1 にしたときに使われます。 参考 → setting フォルダに入れる関数の作り方 *********************************************************************** <<< Setting_buildTestPrompt >>> *********************************************************************** Setting_buildTestPrompt (src) [ 親: setting フォルダー ] Sub Setting_buildTestPrompt( Prompt as TestPrompt ) テスト・プロンプトの設定を行います。 【引数】 Prompt 設定 (TestPrompt_Setting.vbs のサンプルを参照) プロンプトのメニュー項目を設定します。 テスト・スクリプト(Test.vbs)を登録します。 → Tests::AddTestScriptAuto → 設定ファイル TestPrompt_Setting.vbs 参考 → テスト・プロンプト (Test.vbs) → setting フォルダに入れる関数の作り方 *********************************************************************** <<< Setting_get7zExePath >>> *********************************************************************** Setting_get7zExePath [ 親: setting フォルダー ] Function Setting_get7zExePath() as string 7-Zip の 7z.exe のパスを返します。 ソース → PC_setting_default.vbs *********************************************************************** <<< Setting_getTemp >>> *********************************************************************** Setting_getTemp [ 親: setting フォルダー ] Sub Setting_getTemp( out_FolderPath as string, out_LimitDate as Date ) テンポラリ・ファイルやテンポラリ・フォルダーの設定値を取得します。 【引数】 out_FolderPath (出力) テンポラリ・フォルダのパス out_LimitDate (出力) 保存期限 参考 → GetTempPath テンポラリ・ファイルのパスを返す → setting フォルダに入れる関数の作り方 サンプル 下記は、Setting_getTemp を定義していないときと同じ設定です Sub Setting_getTemp( out_FolderPath, out_LimitDate ) out_FolderPath = env( "%Temp%\Report" ) out_LimitDate = DateAdd( "d", -2, Now() ) '// "d" = day End Sub env DateAdd out_FolderPath や out_LimitDate に値を代入しなかったら、デフォルト値が 使われます。 out_LimitDate 引数に出力した日時より前のタイムスタンプを持つファイルは、 GetTempPath で削除されます。 参考 → 日付の比較 設定の変更 Setting_getTemp は、起動時に(vbslib.vbs の InitializeModule で)呼ばれます。 動的にテンポラリ・ファイルやテンポラリ・フォルダーの設定値を変更するときは、 以下のようにコーディングしてください。 include "Setting_getTemp.vbs" g_TempFile = Empty '// Setup to set another folder path get_TempFile g_TempFile Dim g_TempFile as TempFileClass テンポラリ・フォルダの設定に関するオブジェクト。 get_TempFile Sub get_TempFile() テンポラリ・ファイルやテンポラリ・フォルダーを設定します。 起動時に(vbslib.vbs の InitializeModule で)呼ばれます。 *********************************************************************** <<< Setting_getDiffPath >>> *********************************************************************** Setting_getDiffPath Function Setting_getDiffPath() as string GnuWin の diff.exe のパスを返します。 diff.exe がないと、 GetExistPathInSetting による警告がされます。 この関数の定義は、ユーザーが変更できます。 定義サンプル Function Setting_getDiffPath() Setting_getDiffPath = GetExistPathInSetting( Array( _ g_vbslib_folder +"GPL\GnuWin\bin\diff.exe" ), _ "Setting_getDiffPath" ) End Function ソース → PC_setting_default.vbs *********************************************************************** <<< Setting_getDiff3Path >>> *********************************************************************** Setting_getDiff3Path Function Setting_getDiff3Path() as string diff3 (Diffutils) が入っているフォルダーのパスを返します。 diff3.exe がないと、 GetExistPathInSetting による警告がされます。 この関数の定義は、ユーザーが変更できます。 定義サンプル Function Setting_getDiff3Path() Setting_getDiff3Path = GetExistPathInSetting( Array( _ g_vbslib_folder +"GPL\GnuWin\bin\diff3.exe" ), _ "Setting_getDiff3Path" ) End Function ソース → PC_setting_default.vbs *********************************************************************** <<< Setting_getPatchPath >>> *********************************************************************** Setting_getPatchPath Function Setting_getPatchPath() as string GnuWin の patch.exe のパスを返します。 patch.exe がないと、 GetExistPathInSetting による警告がされます。 この関数の定義は、ユーザーが変更できます。 Windows の UAC によって、『要求された操作には管理者特権が必要です。』 と表示されるときは、patch.exe を p_atch.exe などに改名し、Setting_getPatchPath の返り値も、それに合わせてください。 定義サンプル Function Setting_getPatchPath() Setting_getPatchPath = GetExistPathInSetting( Array( _ g_vbslib_folder +"GPL\GnuWin\bin\patch.exe" ), _ "Setting_getPatchPath" ) End Function ソース → PC_setting_default.vbs *********************************************************************** <<< Setting_getPerlPath >>> *********************************************************************** Setting_getPerlPath [ 親: setting フォルダー ] Function Setting_getPerlPath() as string Perl スクリプトのホスト(.exe) のパスを返します。 Perl がインストールされていないと、 GetExistPathInSetting による警告がされます。 この関数の定義は、ユーザーが変更できます。 定義サンプル Function Setting_getPerlPath() Setting_getPerlPath = GetExistPathInSetting( Array( _ g_vbslib_folder +"perl\bin\perl.exe", _ g_sh.ExpandEnvironmentStrings( "%ProgramFiles%\perl-strawberry-perl\perl\bin\perl.exe" ), _ g_sh.ExpandEnvironmentStrings( "%ProgramFiles(x86)%\perl-strawberry-perl\perl\bin\perl.exe" ) ), _ "Setting_getPerlPath" ) End Function ソース → PC_setting_default.vbs *********************************************************************** <<< Setting_getNaturalDocsPerlPath >>> *********************************************************************** Setting_getNaturalDocsPerlPath [ 親: setting フォルダー ] Function Setting_getNaturalDocsPerlPath() as string Natural Docs の本体(Perl スクリプト)のパスを返します。 NaturalDocs がインストールされていないと、 GetExistPathInSetting による警告がされます。 この関数の定義は、ユーザーが変更できます。 定義サンプル Function Setting_getNaturalDocsPerlPath() Setting_getNaturalDocsPerlPath = GetExistPathInSetting( Array( _ g_sh.ExpandEnvironmentStrings( "%ProgramFiles%\NaturalDocs\NaturalDocs" ), _ g_sh.ExpandEnvironmentStrings( "%ProgramFiles(x86)%\NaturalDocs\NaturalDocs" ) ), _ "Setting_getNaturalDocsPerlPath" ) End Function ソース → PC_setting_default.vbs *********************************************************************** <<< Setting_getDoxygenPath >>> *********************************************************************** Setting_getDoxygenPath [ 親: setting フォルダー ] Function Setting_getNaturalDocsPerlPath() as string doxygen のフォルダーのパスを返します。 doxygen がインストールされていないと、 GetExistPathInSetting による警告がされます。 この関数の定義は、ユーザーが変更できます。 定義サンプル Function Setting_getDoxygenPath() Setting_getDoxygenPath = GetExistPathInSetting( Array( _ g_sh.ExpandEnvironmentStrings( "%ProgramFiles%\doxygen" ), _ g_sh.ExpandEnvironmentStrings( "%ProgramFiles(x86)%\doxygen" ) ), _ "Setting_getDoxygenPath" ) End Function ソース → PC_setting_default.vbs *********************************************************************** <<< Setting_getSnapNotePath >>> *********************************************************************** Setting_getSnapNotePath [ 親: setting フォルダー ] Function Setting_getSnapNotePath() as string Snap Note の本体のパスを返します。 Snap Note が見つからないと、 GetExistPathInSetting による警告がされます。 この関数の定義は、ユーザーが変更できます。 定義サンプル Function Setting_getSnapNotePath() Setting_getSnapNotePath = GetExistPathInSetting( Array( _ g_sh.ExpandEnvironmentStrings( "%ProgramFiles%\Snap Note\Snap Note.exe" ) ), _ "Setting_getSnapNotePath" ) End Function ソース → PC_setting_default.vbs *********************************************************************** <<< その他 >>> *********************************************************************** その他 → g_Vers *********************************************************************** <<< ユーザーインターフェース >>> *********************************************************************** ユーザーインターフェース → echo コマンドプロンプト、またはウィンドウにメッセージを表示します。 → pause Enter キーを押すまで待ちます。 → input プロンプトを表示し、ユーザからのキーボード入力を待ちます。 → InputCommand ショートハンド・プロンプト に入ります。 → SendKeys キーボード入力をエミュレーションします。 → Play 音楽ファイルや効果音ファイルを鳴らします。 → SystemSound コントロールパネルに設定されている効果音を鳴らします。 他にもあります。左のツリーから選択してください。 テスト → ユーザインターフェースのテスト *********************************************************************** <<< echo >>> *********************************************************************** echo Function echo( Message as variant ) as string コマンドプロンプト、またはウィンドウにメッセージを表示します。 【引数】 Message 表示する内容、またはオブジェクト 返り値 表示した内容(文字列) ファイル: vbslib.vbs サンプル: 実行結果: echo "はろー" echo 1+1 はろー 2 サンプル: 実行結果: 名前は、太郎です。 Dim name name = "太郎" echo "名前は、"+ name +"です。" サンプル: 実行結果: a = 5 Dim a a = 5 echo "a = "& a サンプル: 実行結果: あなたの名前は >次郎 次郎さんですね。 Dim name name = input( "あなたの名前は?>" ) echo name +"さんですね。" input echo サンプル: Set obj = new ClassX echo obj '// obj.xml プロパティを表示する サンプル: ファイルとコマンドプロンプトの両方に出力する Dim out : Set out = OpenForWrite( "_out.txt", Empty ) out.WriteLine echo( "はろー" ) echo は、 g_CommandPrompt で、コマンドプロンプトを表示しているときは、コマンド・ プロンプトの中に、そうではないときは、ウインドウに表示します。 EchoOff オブジェクト があるときは、出力しません。 Message にオブジェクトを指定した場合、Value プロパティを表示します。 参考 → GetEchoStr Class ClassX Public Property Get Value() テスト・プロンプト (Test.vbs) を使っているときは、Test_logs.txt ファイルにも出力します。 EchoOff オブジェクトがあるときでも出力したいときは、echo_v を使うか、標準出力して ください。 例:echo_r "text", "" ソース → vbslib.vbs テスト → T_Var.vbs # T_LoadEnvVars 関連 → echo_flush 今まで echo した内容をウィンドウで表示します。 → EchoOff echo で出力しないようにします。 → echo_r 標準出力かファイルに、文字列を出力します。 → GetEchoStr Message を表示可能な文字列に変換します。 → WScript::Echo VBScript / WSH の標準的な表示関数。 → echo 出力して、その内容が正しいことをチェックするテスト *********************************************************************** <<< echo_flush >>> *********************************************************************** echo_flush (src) Sub echo_flush() コマンド・プロンプトを表示していないとき、今まで echo した文字列をウィンドウで表示します。 ファイル: vbslib.vbs コマンド・プロンプトを表示しているときは、何もしません。 echo_flush を呼び出さなくても、プログラム終了時、pause、input 時、何度も echo したときは、 ウインドウに自動的に表示します。 サンプル: echo "注意してください。" echo_flush 参考 → g_CommandPrompt コマンドプロンプトを表示するかどうか *********************************************************************** <<< echo_line >>> *********************************************************************** echo_line (src) Sub echo_line() 水平線を表示します。 ファイル: vbslib.vbs 表示内容: ------------------------------------------------------------ *********************************************************************** <<< EchoOff オブジェクト >>> *********************************************************************** EchoOff オブジェクト EchoOff オブジェクトがあるときは、 echo で出力しません。 通常、下記のように使います。 Function FuncA( Param1 ) echo ">FuncA " & Param1 Dim ec : Set ec = new EchoOff echo "SubA" ec = Empty echo FuncA End Sub 呼び出した関数名を表示する EchoOff echo で表示しないようにする ここの echo では表示されません。 実際は、FuncA 関数から呼び 出す関数の中から呼ばれる echo による表示を抑制します EchoOff オブジェクトの削除で、表示を復活します。 ec=Empty しない場合でも、FuncA から返ると自動的に復活します。 (デストラクタによるため) EchoOff オブジェクトがあるときに、長い処理の進捗状況を表示したいときは、echo_r で標準出力へ出力して ください。 EchoOff オブジェクトを生成した関数から呼び出す関数の中で echo 出力を再開するときは、 EchoOff オブジェクトの Close を呼び出してください。 ソース → vbslib.vbs → vbslib_mini.vbs 関連 → DisableEchoOff → echo_r *********************************************************************** <<< g_EchoObj.m_bEchoOff >>> *********************************************************************** g_EchoObj.m_bEchoOff Dim g_EchoObj.m_bEchoOff as boolean EchoOff オブジェクト によって出力しないかどうか。 サンプル echo_v "EchoOff = "+ CStr( g_EchoObj.m_bEchoOff ) ソース → vbslib.vbs *********************************************************************** <<< DisableEchoOff >>> *********************************************************************** DisableEchoOff (src) Sub DisableEchoOff() EchoOff オブジェクトがあっても、echo 出力するようにします。 ファイル: vbslib.vbs サンプル: Sub main() DisableEchoOff : 関連 → EchoOff オブジェクト *********************************************************************** <<< echo_v >>> *********************************************************************** echo_v Function echo_v( Message as string ) as string 文字列を出力します。 フィルタリングされません。 【引数】 Message 出力する内容の文字列(文字列以外は指定できません) ファイル: vbs_inc_sub.vbs エラーメッセージは、echo ではなく echo_v を使用してください。 EchoOff オブジェクト の影響を受けません。(= フィルタリングされません) g_verbose を使うときは、echo_v を使用してください。 サンプル If g_verbose Then echo_v "処理は1つも行われませんでした。" ソース → vbs_inc_sub.vbs テスト → T_Verbose.vbs # [T_Verbose] 関連 → g_verbose *********************************************************************** <<< echo_r >>> *********************************************************************** echo_r Function echo_r( Message as string, RedirectPath as string ) as string 標準出力かファイルに、文字列を出力します。 【引数】 Message 出力する内容の文字列など(echo と同じ) RedirectPath 出力先のファイルパス、Empty のときは出力しない、""=標準出力へ 返り値 出力した内容の文字列 サンプル echo_r "エラー", "" ソース → vbslib.vbs 関連 → echo *********************************************************************** <<< Execute_Echo >>> *********************************************************************** Execute_Echo (src) Function Execute_Echo( ExpressionStr as string, Label as string ) as string 式とその計算結果を表示します。 デバッグ用です。 【引数】 ExpressionStr 式(文字列) Label 表示内容の最初に表示するラベル 返り値 Execute に渡すコード ファイル: vbslib.vbs 書きかけ サンプル 関連 → ウォッチ (WS, WD, WX) *********************************************************************** <<< GetEchoStr >>> *********************************************************************** GetEchoStr (src) Function GetEchoStr( Message as variant ) as string Message を表示可能な文字列に変換します。 ファイル: vbslib.vbs サンプル: s = GetEchoStr( object ) Message がオブジェクトの場合、 xml_sub メソッド の返り値を返します。 Message が Dictionary の場合、キーとアイテムの両方を文字列にします。 このとき、アイテムを再帰的に GetEchoStr に渡します。 Message が配列または ArrayClass の場合、すべての要素を文字列にします。 テスト → T_Value.vbs T_EchoStr *********************************************************************** <<< g_CustomEchoStrGenerators >>> *********************************************************************** g_CustomEchoStrGenerators (src) Dim g_CustomEchoStrGenerators as dictionary of Function 表示可能な文字列に変換する関数の辞書。 GetEchoStr の引数に指定したオブジェクトのクラスに、 xml_sub メソッド を定義できないときは、 InitializeModule 関数の中で、g_CustomEchoStrGenerators に関数を登録してください。 登録する関数は、xml_sub メソッドと同じ形式の文字列を返すようにしてください。 サンプル Function InitializeModule( ThisPath ) Set g_CustomEchoStrGenerators( "ClassA" ) = GetRef( "ClassA_xml_sub" ) End Function Function ClassA_xml_sub( m as Object, Level as integer ) ClassA_xml_sub = GetTab(Level)+ "<"+TypeName(m)+" Name='"+ XmlAttrA( m.Name ) +_ "'/>"+ vbCRLF End Function 参考 → xml_sub メソッド (vbsool) *********************************************************************** <<< g_EchoCopyStream >>> *********************************************************************** g_EchoCopyStream Dim g_EchoCopyStream as TextStream or Empty TextStream Echo 出力のコピーを横取りするストリーム オブジェクト。 Echo 出力するときに、g_EchoCopyStream が Empty ではないときは、 その出力内容を WriteLine メソッドに渡します。 次の Echo 出力のコピーは、横取りできます。 → echo → echo_v → echo_r 次の Echo 出力のコピーは、横取りできません。 → WScript::Echo → WScript::StdOut, StdErr テスト → T_Verbose.vbs → Test.vbs T_EchoCopyStream → T_EchoCopyStream.vbs *********************************************************************** <<< Pause >>> *********************************************************************** Pause vbslib.vbs (src) vbslib_mini.vbs (src) Sub Pause() コマンドプロンプトにメッセージを表示して、Enter キーを押すまで待ちます。 ファイル: vbslib.vbs サンプル: Pause メッセージの内容: 続行するには Enter キーを押してください . . . サンプル: echo "処理を開始します。" If not ArgumentExist( "silent" ) Then Pause "処理を開始します。" silent Pause デバッグするときは、Pause より MsgBox を使った方がよいでしょう。 Pause は、子プロセスがからむと、メッセージが表示されない可能性があるためです。 *********************************************************************** <<< pause2 >>> *********************************************************************** pause2 Sub pause2() コマンドプロンプトを使う .vbs ファイルをダブルクリックしたときだけ pause します。 プログラムの最後で pause2 すると、コマンドプロンプトに出力した内容を確認できます。 ソース → vbslib.vbs *********************************************************************** <<< PauseForDebug >>> *********************************************************************** PauseForDebug Sub PauseForDebug() 呼び出し元がデバッグ モードのときに、実行を一時停止します。 次のように表示されて一時停止します。 a と Enter : 今後は止めない 続行するには Enter キーを押してください . . . a (Enter) が入力されると、それ以降の PauseForDebug では何もしません。 デバッグ モードの内容は、PauseForDebug を呼び出すモジュールによります。 ソース → vbslib.vbs *********************************************************************** <<< Input >>> *********************************************************************** Input Function Input( Prompt as string ) as String プロンプトを表示し、ユーザからのキーボード入力を待ちます。 【引数】 Prompt 表示する内容 返り値 ユーザが入力した文字列、入力なし="" ファイル: vbslib.vbs Ctrl+C を押すと、プログラムは中断します。エラーにもなりません。 サンプル Dim key key = Input( "キーワードを入力してください >" ) echo key Input echo サンプル Yes と No の選択入力 key = Input( "〜します。[Y/N]" ) If key <> "y" and key <> "Y" Then _ Exit Sub ' ... Cancel サンプル メニュー echo "1. コマンドAを起動する [CommandA]" echo "2. コマンドBを起動する [CommandB]" echo "9. 終了 [Exit]" key = Trim( Input( "番号またはコマンド名>" ) ) Select Case key Case "1": key = "CommandA" Case "2": key = "CommandB" End Select If StrComp( key, "CommandA", 1 ) = 0 Then : ElseIf StrComp( key, "Exit", 1 ) = 0 Then Exit Do End If 長い文字を入力するときの注意 254文字以上は入力できません。 コマンドプロンプトから入力した場合、128文字以上を入力したときに日本語文字が入って いると、128文字目付近の文字が消えてしまうため、 InputBox を使って再入力を要求します。 コマンドプロンプトから入力した場合、128文字目が日本語文字の場合は、cscript.exe が、 例外を発生してしまいます。 ソース → vbslib.vbs → vbslib.vbs#CUI → vbslib_mini.vbs テスト → [T_UI] → [T_ExecStdIn] → [T_ExecStdIn_300] 関連 → InputPath : ファイルパスを入力する → InputCommand : メニュー選択や専用コマンド入力をするモード → 自動入力 (set_input) → /GUI_input オプション → ユーザーインターフェース・構造体 *********************************************************************** <<< 自動入力 (set_input) >>> *********************************************************************** 自動入力 (set_input) input や pause 関数を使った場合、自動的にキー入力することもできます。 → set_input 関数 → /set_input オプション、g_CUI.SetAutoKeysFromMainArg 関連 → ショートカットやバッチファイルなどから専用コマンドを実行するときのパラメーター *********************************************************************** <<< set_input >>> *********************************************************************** set_input (src) Sub set_input( Keys as string ) input でユーザーが入力する内容を、指定した内容で自動的に入力するようにします。 ファイル: vbslib.vbs 次のようにすると、input を呼び出したときに、自動的に [1][Enter][2][Enter] と入力します。 g_CUI.m_Auto_KeyEnter = "." set_input "1.2." Enter に対応する文字をピリオドから変更したいときは、次のようにします。 g_CUI.m_Auto_KeyEnter = "/" set_input "1/2/" 子プロセスに set_input の内容を引き継ぐには、下記の手順をしてください。 /set_input オプション と SetAutoKeysFromMainArg で、または、 InputCommand を使う子プロセスに g_InputCommand_Args(の一部)を渡すことで、 子プロセスに入力内容を渡します。 サンプル → g_InputCommand_Args g_CUI.SetAutoKeysFromMainArg を呼び出した後で、set_input を呼び出すと、/set_input オプションによる指定は無視されます。 関連 → g_CUI.SetAutoKeysFromMainArg、/set_input オプション テスト → [T_UI_Auto] 自動入力のテスト *********************************************************************** <<< /set_input オプション、g_CUI.SetAutoKeysFromMainArg >>> *********************************************************************** /set_input オプション、g_CUI.SetAutoKeysFromMainArg (src) cscript.exe を起動したときのパラメータに、/set_input オプションを指定すると、 input などでユーザーが入力する内容を、オプションに指定した内容で自動的に入力します。 ただし、main 関数の先頭などで g_CUI.SetAutoKeysFromMainArg を呼び出す必要があります。 コマンドライン cscript.exe sample.vbs /set_input:1.2. VBS のソースに必要な呼び出し g_CUI.SetAutoKeysFromMainArg 関連 → input → set_input テスト → [T_UI_Auto] 自動入力のテスト *********************************************************************** <<< /set_input_enter オプション >>> *********************************************************************** /set_input_enter オプション (src) cscript.exe を起動したときのパラメータに、/set_input_enter オプションを指定すると、 /set_input に指定した文字のうち、/set_input_enter オプションで指定した文字は、Enter の 入力にします。 /set_input_enter オプションが指定されなかったときは、ピリオドが Enter の入力になります。 日本語文字を指定すると、すべてのAscii 文字が使えるようになります。 コマンドライン cscript.exe sample.vbs /set_input:1.2. /set_input_enter:. *********************************************************************** <<< /set_input_debug オプション、g_CUI.m_Auto_DebugCount >>> *********************************************************************** /set_input_debug オプション、g_CUI.m_Auto_DebugCount (src) /set_input オプション を指定したときに、1つずつ Enter キーを入力するまで待ちます。 これにより、ユーザーの入力を自動的に行うときに、入力内容を確認しながら実行できます。 指定した値の回数目の入力から待ちます。 VBS のソース g_CUI.m_Auto_DebugCount = 1 コマンドライン cscript.exe sample.vbs /set_input:1.2. /set_input_debug:1 関連 → input *********************************************************************** <<< /GUI_input オプション >>> *********************************************************************** /GUI_input オプション input を呼び出したとき、コマンドライン・スクリプトでも、強制的に GUI から入力する オプションです。 起動コマンドの例: cscript Sample.vbs /GUI_input RunProg や Shell::Exec で cscript.exe を起動したプロセスで input を使うと、 標準入力待ちでハングアップするので、代わりに内部で、GUI から入力する InputBox が呼ばれます。 InputBox が呼ばれるかどうかは、スクリプトを起動したときに指定するコマンド ライン・オプションに /GUI_input:1 を指定したかどうかで決まります。 RunProg で、cscript を起動すると、/GUI_input:1 は、自動的に指定されます。 子プロセスで pause したとき、pause メッセージを子プロセスから受け取ったら 親プロセスで、Enter の入力待ちをします。 Enter を押したら、子プロセスの 標準入力にも Enter を転送します(EchoStream関数)。 自動入力するときは、 pause メッセージに少し手を加えて、親プロセスで待たないようにします。 参考 → RunProg ソース → vbslib.vbs テスト → [T_ExecStdIn] Exec で起動したプロセスの標準入力 *********************************************************************** <<< InputPath >>> *********************************************************************** InputPath (src) Function InputPath( Prompt as string, Flags as integer ) as string プロンプトを表示し、ユーザからファイルのパス(場所)の入力を待ちます。 【引数】 Prompt 表示する内容 Flags 0 または c.CheckFileExists など(下記) 返り値 ユーザが入力したパス、入力なし="" ファイル: vbslib.vbs ユーザは、 " "で囲んだパスを入力することができます。このとき、返り値は、" " を含みません。 相対パスを入力したら、 g_start_in_path を基準とした相対パスとみなし、返り値は、フル パスに なります。 InputPath を呼び出す前に、g_start_in_path は、変更することができます。 ${ から始まる入力をしたときは、フル パスを値に持つ ${ } 変数 であるとして、フル パスに しません。 Flags 引数 下記を設定します。 複数設定するときは、or してください。 c は g_VBS_Lib です。 何も設定しない ときは、0 を指定してください。 c.CheckFileExists ファイルとして存在するかチェックします。 c.CheckFolderExists フォルダとして存在するかチェックします。 c.AllowEnterOnly 何も入力しなかったときに再入力を要求しません。 このとき、返り値="" c.AllowWildcard ワイルドカードが入力できるようにします。 c.UseArgument1 スクリプトを起動したときの第1パラメーターがあれば、それを入力とする (*1) c.UseArgument2 スクリプトを起動したときの第2パラメーターがあれば、それを入力とする (*1) (*1) UseArgument1 や UseArgument2 を指定した場合、 set_input で指定した自動入力の内容や ショートハンド・プロンプトのパラメーター は、次の番目に進みません。 次の自動入力や パラメーターの番目がいくつのときでも指定した番目のものが入力できるからです。 サンプル Set c = g_VBS_Lib echo "[SampleTool]" path = InputPath( "path>", c.CheckFileExists or c.CheckFolderExists or _ c.UseArgument1 or c.AllowEnterOnly ) If path = "" Then path = GetPathOfClipboardText() InputPath GetPathOfClipboardText サンプル画面 [SampltTool] path>aaa not found path>C:\ サンプル Linux のパスも入力できるようにするとき Dim path, param If ArgumentExist( "Path" ) Then path = WScript.Arguments.Named.Item( "Path" ) echo "パス>"+ path Else path = InputPath( "パス>", Empty ) End If param = input( "Param>" ) Linux のパスは、オプションと解釈されてしまうため、/Path オプションを使って指定して ください。 cscript Sample.vbs /Path:/home/user1/file Param2 テスト → Test.vbs # T_InputPath_WorkFolder_File → Test.vbs # T_InputPathArg → Test.vbs # T_InputCommand_WindowsParam → Test.vbs # T_InputCommand_LinuxParam 関連 → input → g_start_in_path → サンプル (ドラッグ&ドロップからテキスト処理) *********************************************************************** <<< InputCommand >>> *********************************************************************** InputCommand (src) Sub InputCommand( LeadOrOpt as string or InputCommandOpt, Prompt as string, Opt as variant, AppKey as AppKeyClass ) InputCommandOpt ショートハンド・プロンプト に入ります。 入力するコマンドは、呼び出す関数の名前です。 【引数】 LeadOrOpt リード文、または、オプション → InputCommandOpt Prompt プロンプトの表示内容。 Empty="番号またはコマンド" Opt Main 関数の Opt 引数 AppKey Main 関数の AppKey 引数 ファイル: vbslib.vbs ユーザーが入力したコマンドと同じ名前の関数が呼ばれます。 たとえば、SymcSymbols と入力したら、 ImputCommand 関数の中から、GetRef 関数を使って、SymcSymbols 関数が呼ばれます。 呼ばれる 関数の引数は、main2 関数と同じ、Opt と AppKey にしてください。 ImputCommand Empty, "コマンド >" Sub SyncSymbols( Opt, AppKey ) echo "SyncSymbols 関数が呼ばれました。" End Sub コマンド >SyncSymbols プロンプトのみ(メニュー項目なし) サンプル Sub main2( Opt, AppKey ) InputCommand "Document.svg を参照 (Google Chrome や Snap Note で見えます)", _ "コマンド >", Opt, AppKey End Sub Sub SyncSymbols( Opt, AppKey ) echo "SyncSymbols 関数が呼ばれました。" End Sub InputCommand 実行画面 FuncA コマンドを実行したところ -------------------------------------------------------------------------------- Document.svg を参照 (Google Chrome や Snap Note で見えます) コマンド >SyncSymbols -------------------------------------------------------------------------------- SyncSymbols 関数が呼ばれました。 -------------------------------------------------------------------------------- Document.svg を参照 (Google Chrome や Snap Note で見えます) コマンド > SyncSymbols サンプル メニューから選択する Sub Main( Opt, AppKey ) Set o = new InputCommandOpt o.Lead = "Document.svg を参照 (Google Chrome や Snap Note で見えます)" Set o.CommandReplace = Dict(Array( "1","RunProgram", "2","InvestigateLog" )) Set o.MenuCaption = Dict(Array( "1","起動コマンド [%name%]" )) InputCommand o, Empty, Opt, AppKey End Sub Sub InvestigateLog( Opt, AppKey ) Set c = g_VBS_Lib path = InputPath( "ログ・ファイルのパス >", c.CheckFileExists ) key = input( "よろしいですか。[Y/N]" ) If key<>"y" and key<>"Y" Then Exit Sub ' ... Cancel Investivate path echo "解析しました。" End Sub InputCommandOpt InputCommand InputPath input 実行画面 下記はメニュー2を選んだところ。 2 の代わりに InvestigateLog も入力できます。 ------------------------------------------------------------------------------- Document.svg を参照 (Google Chrome や Snap Note で見えます) 1. 起動コマンド [RunProgram] 2. InvestigateLog 番号またはコマンド >2 ------------------------------------------------------------------------------- ログ・ファイルのパス >C:\Log\Test_log.txt よろしいですか。[Y/N]y 解析しました。 2 C:\Log\Test_log.txt y キーワード: Lead, CommandReplace, MenuCaption InputCommandOpt クラス → サンプル Class InputCommandOpt Public Lead '// as string Public CommandReplace '// as Dictionary of string Public MenuCaption '// as Dictionary of string Public AllTestName '// as string End Class → AllTest コマンド Lead は、ショートハンド・プロンプトの最初に表示される「リード文」です。 CommandReplace は、要素番号 0 から始まる配列で、 要素番号が偶数の要素は、コマンドの番号または略称、 要素番号が奇数の要素は、実行する関数名です。 MenuCaption は、要素番号 0 から始まる配列で、 要素番号が偶数の要素は、コマンドの番号または略称、 要素番号が奇数の要素は、ショートハンド・プロンプトに表示されるメニュー項目です。 ショートハンド・プロンプトのテスト InputCommand 関数を呼び出すスクリプトは、起動するときに専用コマンドをパラメーターに指定すると、 ユーザの入力待ちにはならず、InputCommand 関数の中からすぐに専用コマンドに対応する関数を呼び 出すようになります。 関数から返ったら(InputCommand から返り)、スクリプトのプロセスは終了します。 すぐに関数を呼び出したかどうかをスクリプト内で判断したいときは、 g_InputCommand_Args .Count が 1 以上かどうかで判定します。 専用コマンド名の次やそれ以降のパラメーター(上記の C:\folder\file.txt と y )は、内部で set_input に渡されて、自動的に入力するようになります。 ただし、Enter の入力は "." と記述するのではなく、 パラメーターの区切りが Enter の入力になります。 Enter のみの入力をしたいときは、下記のように cmd.exe から起動して、"" を指定してください。 コマンド >CommandA 入力1 >param1 入力2 > 実行しました。 CommandA 親フォルダーにある Prompt.vbs から起動できるショートハンド・プロンプトに、 CommandA コマンドを入力、入力1に param1 を入力、入力2に Enter のみ 入力するときの、テスト・スクリプトは、下記のようになります。 param1 Dim r r = RunProg( "cscript.exe //nologo """+ SearchParent( "Prompt.vbs" )+_ """ CommandA param1 """"", "out.txt" ) CheckTestErrLevel r Assert "out.txt", "T_ans.txt" del "out.txt" SearchParent Prompt.vbs CommandA param1 """" T_ans 参考 → ショートカットやバッチファイルなどから専用コマンドを実行する AllTest コマンド コマンド入力するときに、「AllTest」 と入力すると、InputCommandOpt クラスの CommandReplace に登録 した関数をすべて呼び出します。 コマンド名を 「AllTest」 以外にしたいときは、InputCommandOpt クラスの AllTestName を設定してください。 Dim r r = RunProg( "cscript //nologo T_Target.vbs AllTest", "" ) CheckTestErrLevel r ショートハンド・プロンプトのデバッグ 下記のようにして、CommandA_debug コマンドを起動すると、入力する内容を自動的に入力します。 Sub CommandA( Opt, AppKey ) dbg = Opt("command_debug") Set c = g_VBS_Lib If dbg Then g_CUI.m_Auto_KeyEnter = "/" If dbg Then set_input "C:\Folder\File1.txt" path = InputPath( "ファイルのパス >", c.CheckFileExists ) : End Sub Sub CommandA_debug( Opt, AppKey ) Opt("command_debug") = True CommandA Opt, AppKey End Sub dbg = Opt("command_debug") If dbg Then g_CUI.m_Auto_KeyEnter = "/" If dbg Then set_input "C:\Folder\File1.txt" Sub CommandA_debug( Opt, AppKey ) Opt("command_debug") = True CommandA Opt, AppKey End Sub テスト → T_InputCommand_Manually.vbs # main → Test.vbs # T_InputCommand_Param → T_InputCommand_Target.vbs # [main2] → T_InputCommand_Target2.vbs # [main2] 関連 → ショートハンド・プロンプト *********************************************************************** <<< g_InputCommand_Args >>> *********************************************************************** g_InputCommand_Args Dim g_InputCommand_Args as array of string ショートハンド・プロンプト のパラメーター。 g_InputCommand_Args(0) は、専用コマンド名、g_InputCommand_Args(1) 以降は、パラメーターです。 g_InputCommand_Args.Count = 0 のときは、対話式のショートハンド・プロンプトが使われてます。 g_InputCommand_Args.Count >= 1 のときは、ショートハンド・プロンプトをバッチ処理で実行しています。 サンプル 子プロセスにパラメーターを渡します。 Set parameters = new_ArrayClass( g_InputCommand_Args ) If parameters.Count >= 1 Then _ parameters.Remove 0, 1 '// Remove special command name parameters = CmdLineFromStr( parameters.Items ) set_input "" '// 現在のプロセスに設定されている自動入力データをクリアする RunProg "cscript //nologo Prompt.vbs CommandX_Child "+ _ parameters +" /g_debug__:1", "" /g_debug__ *********************************************************************** <<< ChangeNumToCommandOrNot >>> *********************************************************************** ChangeNumToCommandOrNot Function ChangeNumToCommandOrNot( in_Key as string, in_CommandDictionary as dictionary of string, _ in_NumName as string, in_IsInputNumOrCommand as boolean ) as string リストとコマンド番号が重なったときは、どちらかキーボードから選択するようにユーザーに要求しjます。 【引数】 in_Key 入力した番号の文字列 in_CommandDictionary コマンド名の辞書。 キー=番号の文字列 in_NumName リストの項目の名前 in_IsInputNumOrCommand in_Key の番号にリストの項目があるかどうか 返り値 番号(リストの項目の番号の文字列)、または、コマンド名 ソース → vbslib.vbs テスト → T_Value.vbs *********************************************************************** <<< SendKeys >>> *********************************************************************** SendKeys (src) Sub SendKeys( WindowTitle as string, KeyCords as string, LateTime as integer ) キーボード入力をエミュレーションして自動的にキー操作をします。 【引数】 WindowTitle "" または、キーボード・コードを送るウィンドウのタイトル(下記) KeyCords キーボード・コード (下記) LateTime 0 または、キーボード・コードを送るまでの時間(ミリ秒) ファイル: vbslib.vbs サンプル: SendKeys "メモ帳", "%FS", 200 Alt キー + [F] + [S] …… 保存 WindowTitle 引数 WindowTitle 引数に指定した文字列が、ウィンドウのタイトルに、前方一致、または、 後方一致したウィンドウに対して、キー操作をします。 KeyCords 引数 制御キーの入力は、次のように指定します。 キー入力 KeyCords 引数 説明 [Alt]+[F], [S] "%FS" Alt キーを押しながら F、離して S [Ctrl]+[C] "^C" [Shift]+[X], [P] "+XP" シフトキーを押しながら、X、離して、P [Shift]+[X], [Shift]+[P] "+(XP)" シフトキーを押しながら連続して、X、P [+] "{+}" [{] "{{}" [[] "{[}" [Enter] "{ENTER}" [Esc] "{ESC}" [Tab] "{TAB}" その他のキー → SendKeys メソッド (Web) LateTime 引数 キーコードを送る前に待つ時間を指定します。 直前の処理がウィンドウを開く処理など、キーコードを送る対象が準備できるまでに 時間がかかるときに指定してください。 参考 → キーボード・コードを送る → WshShell::SendKeys → Windows管理者のためのWindows Script Host入門:第5回 (4-4) - @IT (Web) テスト → T_UI1_Manual.vbs # SendKeys *********************************************************************** <<< Prompt >>> *********************************************************************** Prompt Sub Prompt( TCHAR* Desc, HANDLE* out_Obj ); VBScript が実行できるプロンプトを開始します。 これまでにグローバル変数に設定していた値を参照することもできます。 Prompt 関数を呼び出した関数のローカル変数は参照できません。 参考 → Prompt コマンド ソース → System.vbs *********************************************************************** <<< Play >>> *********************************************************************** Play (src) Sub Play( Path as string ) 音楽ファイルや効果音ファイルを鳴らします。 【引数】 Path .wav, .mp3 などのファイルパス ファイル: vbslib.vbs サンプル Play env( "%windir%\Media\tada.wav" ) Play "sample.mp3" 鳴らし始めると、すぐに Play 関数から戻り、音声が流れながらスクリプトの続きを実行します。 WaitForSound を使えば、音声が終わるまで待つことができます。 スクリプトを終了すると、音声は止まります。 動画ファイルを指定すると、音声だけが流れます。 テスト → T_Sound.vbs # [T_Sound] 関連 → WaitForSound → SetVolume → 音を鳴らす (VBScript) *********************************************************************** <<< WaitForSound >>> *********************************************************************** WaitForSound (src) Sub WaitForSound( Timeout_msec as integer ) Play で再生した音声が終わるまで待ちます。 【引数】 Timeout_msec タイムアウト(ミリ秒)、または Empty (タイムアウトなし) タイムアウトになったら、音声は停止します。 ファイル: vbslib.vbs サンプル 音声が終わるまで待つ Play "sample.mp3" WaitForSound Empty Empty サンプル 5秒たっても音声が終わらなかったら止める Play "sample.mp3" WaitForSound 5000 5000 サンプル すぐに音声を止める Play "sample.mp3" WaitForSound 0 0 テスト → T_Sound.vbs # [T_Sound] 関連 → Play *********************************************************************** <<< SetVolume >>> *********************************************************************** SetVolume (src) Sub SetVolume( Volume as integer ) 音量を設定します。 0 が最小、100 が最大。 【引数】 Volume 音量。デフォルトは 100 ファイル: vbslib.vbs サンプル SetVolume 100 テスト → T_Sound.vbs # [T_Sound] 関連 → Play *********************************************************************** <<< SystemSound >>> *********************************************************************** SystemSound (src) Sub SystemSound( Sound as string ) コントロールパネルに設定されている効果音を鳴らします。 【引数】 Sound 効果音の種類(下記) 音声の止め方や音量の調整は、 Play と同じです。 スクリプトを終了時に鳴らしても、数秒の効果音であれば、 WaitForSound しなくても、すぐに音声は停止しません。 サンプル SystemSound ".Default" ".Default" 一般の警告音 "SystemAsterisk" メッセージ(情報) "SystemExclamation" メッセージ(警告) "SystemHand" システムエラー "SystemQuestion" メッセージ(問い合わせ) "SystemStart" Windowsの起動 "SystemExit" Windowsの終了 "WindowsLogon" Windowsログオン "WindowsLogoff" Windowsログオフ "DeviceConnect" デバイスの接続 "DeviceDisconnect" デバイスの切断 "Navigating" ナビゲーションの開始 (フォルダやハイパーリンクをクリックしたときの音) テスト → T_Sound.vbs # [T_Sound] 関連 → システムの警告音を鳴らす (VBScript) *********************************************************************** <<< GetTextFromClipboard >>> *********************************************************************** GetTextFromClipboard (src) Function GetTextFromClipboard() as string クリップボードにあるテキストを返します。 クリップボードにテキストが無ければ、E_BadType エラーになります。 ファイル: vbslib.vbs 使用するには、vbslib フォルダーに、 vbslib_helper.exe が必要です。 テスト → T_Clipboard_Manually.vbs # [T_GetTextFromClipboard] *********************************************************************** <<< GetPathOfClipboardText >>> *********************************************************************** GetPathOfClipboardText (src) Function GetPathOfClipboardText() as string クリップボードにあるテキストをファイルに出力して、そのパスを返します。 クリップボードにテキストが無ければ、E_BadType エラーになります。 ファイル: vbslib.vbs 使用するには、vbslib フォルダーに、 vbslib_helper.exe が必要です。 クリップボードの内容が入ったファイルが不要になったら削除してください。 サンプル Set g = g_VBS_Lib echo "Enter のみ:クリップボードの内容を入力とします。" path = InputPath( "path>", g.CheckFileExists or g.CheckFolderExists or _ g.UseArgument1 or g.AllowEnterOnly ) is_clipboard = False If path = "" Then path = GetPathOfClipboardText() : is_clipboard = True If is_clipboard Then del path テスト → T_Clipboard_Manually.vbs # [T_GetTextFromClipboard] *********************************************************************** <<< SetTextToClipboard >>> *********************************************************************** SetTextToClipboard (src) Sub SetTextToClipboard( Text as string ) クリップボードにテキストをコピーします。 ファイル: vbslib.vbs 使用するには、vbslib フォルダーに、 vbslib_helper.exe が必要です。 テスト → T_Clipboard_Manually.vbs # [T_GetTextFromClipboard] *********************************************************************** <<< データ、変数、定数、文字列、配列、日時 >>> *********************************************************************** [ テスト ] データ、変数、定数、文字列、配列、日時 定数 → 定数、g_VBS_Lib 構造化された定数 集合(コレクション) → ArrayClass クラス 配列を扱いやすくするクラスです。 → ArrayDictionary クラス 標準の Dictionary の Item を、配列にしたクラスです。 配列 (Array) → IsSameArray 配列のすべての要素が等しいか判定します。 → DicToArr Dictionary を配列に変換します。 → AddArrElem 配列の要素を追加コピーします。 → ArrayToNameOnlyClassArray 配列を、NameOnlyClass の配列に変換します。 → ArrayFromCSV CSV 形式の1行を解析して、配列に格納する。 → ArrayFromCSV_Int CSV 形式の1行を解析して、数値の配列に格納する。 辞書、ハッシュ (Dictionary) → Dict 辞書を生成します。 → DicItem 登録されていないときも、新規に登録しない辞書参照。 → GetDicItem Empty でもオブジェクトでも取得できる辞書参照。 → Dic_addNewObject オブジェクトを生成して、辞書に追加します。 → Dic_addElem 辞書の要素を設定します。 → Dic_add 辞書を加算します。 → Dic_sub 辞書を減算します。 並べ替え、ソート → QuickSort_fromDic 辞書に入っているデータをクイックソートします。 → QuickSort 配列をクイックソートします。安定ソートではありません。 → ShakerSort_fromDic 辞書に入っているデータをシェーカーソートします。 → ShakerSort 配列をシェーカーソートします。安定ソートです。 オブジェクト → CreateGuid GUID を生成します。 → get_Object 静的オブジェクトを取得します。 → get_ObjectFromFile スクリプトファイルから静的オブジェクトを取得します。 → get_ObjectsFromFile スクリプトファイルから静的オブジェクトを一覧します。 → include_objs 静的オブジェクト・スクリプトファイルをインクルードします。 → new_X 文字列で指定した名前のクラスのオブジェクトを生成します。 その他 → CInt2 文字列を数値に変換します。 → StrMatchKey クラス ワイルドカードにマッチするかどうか判定します。 → StringStream クラス 文字列を TextStream と同じようにアクセスします。 → MeltCmdLine コマンドラインの1項目を取り出し、通常の文字列に戻す。 他にもあります。左のツリーから選択してください。 関連 → 文字列 (VBS) → 変数、Empty、型、配列 (VBS) → 環境変数 *********************************************************************** <<< g_VBS_Lib >>> *********************************************************************** g_VBS_Lib (src) vbslib で定義されている定数と一部の変数は、g_VBS_Lib オブジェクトのプロパティになっています。 これは、なるべくグローバル・スコープにおいてシンボルが重複しないようにするためです。 次のように、ローカル変数 c を使ってアクセスすることができます。 Sub FuncA() Set c = g_VBS_Lib If StrCompLastOf( "ABC", "BC", c.CaseSensitive ) = 0 Then ... End Sub g_VBS_Lib CaseSensitive 定数の内容については、左のツリーからサブ・ツリーを参照してください。 参考 → get_ModuleConsts : クラスの定数 (vbsool) *********************************************************************** <<< CaseSensitive (g_VBS_Lib) >>> *********************************************************************** CaseSensitive (g_VBS_Lib) Dim g_VBS_Lib:CaseSensitive as integer 2つの英文字の文字列比較において、大文字・小文字を区別すること CaseSensitive が指定できる引数に、CaseSensitive を指定しなかったときは、 大文字と小文字を同じ文字であるとして、文字列比較を行います。 サンプル: Set c = g_VBS_Lib If StrComp( "ABC", "abc", StrCompOption( c.CaseSensitive ) ) = 0 Then ... If StrCompLastOf( "ABC", "BC", c.CaseSensitive ) = 0 Then ... 参考 → StrCompOption *********************************************************************** <<< WholeWord (g_VBS_Lib) >>> *********************************************************************** WholeWord (g_VBS_Lib) Dim g_VBS_Lib:WholeWord as integer 文字列の検索において、単語全体がマッチするものだけヒットさせます。 (単語単位検索、完全一致) 参考 → InStrEx *********************************************************************** <<< LastNextPos (g_VBS_Lib) >>> *********************************************************************** LastNextPos (g_VBS_Lib) Dim g_VBS_Lib:LastNextPos as integer 検索した結果を、ヒットした位置の次の位置にします。 ABCDE の中で C を検索したら、D の位置を検索した結果にします。 ABCDE の中で BCD を検索したら、E の位置を検索した結果にします。 参考 → InStrEx *********************************************************************** <<< g_VBS_Lib_System >>> *********************************************************************** g_VBS_Lib_System vbslib の System.vbs で定義される g_VBS_Lib 。 *********************************************************************** <<< NotExistFileMD5 (g_VBS_Lib_System) >>> *********************************************************************** NotExistFileMD5 (g_VBS_Lib_System) Dim g_VBS_Lib_System:NotExistFileMD5 as string ファイルが存在しないことを明示的に示すときのハッシュ値。 値は、0が32桁の文字列です。 NotExistFileMD5 = "00000000000000000000000000000000" ソース → System.vbs 関連 → 空のフォルダーの MD5 *********************************************************************** <<< ArrayClass >>> *********************************************************************** ArrayClass 配列を扱いやすくするクラスです。 要素は、オブジェクトでもそれ以外でも格納できます。 配列番号以外でも要素にアクセスできます。 → ItemFunc (ArrayClass) 関連 → 配列、Array、ReDim Preserve (VBScript) サンプル 基本的な使い方: Dim a : Set a = new ArrayClass a.Add 1 echo a(0) echo "count = " & a.Count Dim arr : Set arr = new ArrayClass : arr.AddElems Array( 1, 2, 3 ) For 文で使う: Dim item For Each item In a.Items echo item Next a が ArrayClass オブジェクト While 文で使う: Dim a : Set a = new ArrayClass Dim iter : Set iter = a.NewIterator() While iter.HasNext() echo iter.GetNext() WEnd a が ArrayClass オブジェクト iter は、ArrayClassIterator オブジェクト → ArrayClassIterator クラス メンバー .Item 配列の要素。 配列番号。 (デフォルト・プロパティ) .Items VBScript 標準の配列 (プロパティ) .ToEmpty 要素をすべて削除する .Add 要素を最後に追加する .Push 要素を最後に追加する .Pop 最後の要素を返し、配列から要素を削除する .Count 要素数を返す .Value 配列のすべての要素を文字列にする .Echo すべての要素を表示する .Copy すべての要素をコピーする ソース → vbslib.vbs テスト → T_Arr.vbs # [T_ArrClass] 性能比較 → ArraySpeed.vbs → 配列要素を追加する速度 関連 → BinaryArray クラス *********************************************************************** <<< new_ArrayClass >>> *********************************************************************** new_ArrayClass (src) [ 親: ArrayClass クラス ] Function new_ArrayClass( InitialValues as array of variant ) as ArrayClass 配列から ArrayClass のオブジェクトを生成します。 【引数】 InitialValues ArrayClass のオブジェクトの初期値の配列 返り値 ArrayClass のオブジェクト ファイル: vbslib.vbs サンプル Set arr = new_ArrayClass( Array( 1, 2, 3 ) ) Assert arr(0) = 1 Assert arr(1) = 2 Assert arr(2) = 3 new_ArrayClass サンプル Assert new_ArrayClass( Array( 1, 2, 3 ) ).CSV = "1,2,3" *********************************************************************** <<< Item、配列番号 (ArrayClass) >>> *********************************************************************** [ 親: ArrayClass クラス ] Item、配列番号 (ArrayClass) (src) Default Property ArrayClass::Item( i as integer ) 配列番号を使って、配列の要素を参照します。 (デフォルト・プロパティ) 【引数】 i 配列の要素の番号。 先頭は 0 サンプル: Dim a : Set a = new ArrayClass a.Add 1 echo a(0) '// a.Item(0) と同じ a(0) オブジェクトを Set するときは、次のように記述してください。 Set a(0) = new ClassA i 引数が配列の要素数以上のときは、エラーになります。 ItemFunc プロパティに関数を登録すると、引数 i に文字列などを指定できるようになります。 関連 → ItemFunc (ArrayClass) *********************************************************************** <<< ItemFunc (ArrayClass) >>> *********************************************************************** [ 親: ArrayClass クラス ] ItemFunc (ArrayClass) Dim ArrayClass::ItemFunc as Function( Items as Array, Name as variant ) as variant 配列の要素を取得する関数。 Item プロパティにアクセスすると呼ばれる関数。 Item デフォルト・プロパティにアクセスするときに、要素を決定する方法をカスタマイズできます。 サンプル: Dim arr : Set arr = new ArrayClass Set arr.ItemFunc = GetRef( "ClassA_getItem" ) Set obj = arr( "Name" ) Function ClassA_getItem( Items, Name ) Dim s If IsNumeric( Name ) Then Set ClassA_getItem = Items( Name ) Else For Each s In Items If s.Name = Name Then Set ClassA_getItem = s : Exit Function Next End If End Function テスト → T_Arr_Target # [T_ArrayCustom] 関連 → Item (ArrayClass) → Item デフォルト・プロパティ : 動的定義メンバー (vbsool) → NameOnlyClass 配列番号以外の数値型で要素を識別するとき *********************************************************************** <<< Items (ArrayClass) >>> *********************************************************************** [ 親: ArrayClass クラス ] Items (ArrayClass) (src) Dim ArrayClass::Items as array of variant ArrayClass クラスがラップしている配列です。 要素は、オブジェクトでもそれ以外でも格納できます。 For 文で使う: Dim arr : Set arr = new ArrayClass Dim item For Each item In arr.Items echo item Next Items ソート関数に渡すときは、Items ではなく、ArrayClass オブジェクトを渡してください。 Dim arr : Set arr = new ArrayClass : ShakerSort ShakerSort arr, 1, arr.UBound_, GetRef("CmpFunc1"), Empty arr arr *********************************************************************** <<< m_Array (ArrayClass) >>> *********************************************************************** m_Array (ArrayClass) (src) Items と同じです。 廃止される予定です。 → Items (ArrayClass) *********************************************************************** <<< ReDim_ (ArrayClass) >>> *********************************************************************** [ 親: ArrayClass クラス ] ReDim_ (ArrayClass) (src) Sub ArrayClass::ReDim_( UBound as integer ) 配列の要素数を変更します。 ReDim Preserve と同じです。 【引数】 UBound 新しい配列の最大要素番号 ReDim の末尾にアンダースコアが付いています。 (ReDim は予約語であるため。) *********************************************************************** <<< Add (ArrayClass) >>> *********************************************************************** Add (ArrayClass) (src) [ 親: ArrayClass クラス ] Sub ArrayClass::Add( Elem as variant ) 配列の最後に要素を追加します。 【引数】 Elem 配列に追加する要素(オブジェクト、またはそれ以外) ArrayClass::Push と同じです。 Elem に配列を指定すると、ArrayClass の中の1つの要素の中に Elem 配列を追加します。 ArrayClass の中に複数の要素を追加するときは、AddElem を使ってください。 関連 → AddElems (ArrayClass) *********************************************************************** <<< AddElems (ArrayClass) >>> *********************************************************************** AddElems (ArrayClass) (src) [ 親: ArrayClass クラス ] Sub ArrayClass::AddElems( SrcArr as variant or array or ArrayClass ) 配列のすべての要素を追加コピーします。 これまで入っていた要素の後に追加します。 サンプル: Dim a Set a = New ArrayClass a.Add 1 a.AddElems Array( 2, 3 ) '// a は、{ 1, 2, 3 } AddElems 関連 → AddArrElem → Add (ArrayClass) *********************************************************************** <<< AddNewObject (ArrayClass) >>> *********************************************************************** AddNewObject (ArrayClass) (src) [ 親: ArrayClass クラス ] Function ArrayClass::AddNewObject( ClassName as string, ObjectName as string ) as ClassName 指定した名前を付けたオブジェクトを生成して、配列の最後に追加します。 【引数】 ClassName クラス名 ObjectName オブジェクトの名前 返り値 Name プロパティが ObjectName のオブジェクト ClassName に指定したクラスに、Name プロパティ、またはメンバー変数が必要です。 内部で new_X を使っているので、たとえば、ClassA に対して new_ClassA 関数の定義が必要です。 すでに同じ名前のオブジェクトが配列にあっても、オブジェクトを生成します。 サンプル: Set objects = new ArrayClass Set o = objects.AddNewObject( "ClassA", "ObjectA" ) Class ClassA Public Name End Class Function new_ClassA() Set new_ClassA = new ClassA End Function 関連 → Dic_addNewObject テスト → [T_AddNewObj] *********************************************************************** <<< AddCSV (ArrayClass) >>> *********************************************************************** AddCSV (ArrayClass) (src) [ 親: ArrayClass クラス ] Sub ArrayClass::AddCSV( CSV as string, Type_ as integer ) 配列の最後に複数の要素を追加します。 【引数】 CSV 追加する要素を CSV(文字列)にしたもの Type_ 追加する要素の型、例:vbInteger, vbString サンプル: Dim a : Set a = new ArrayClass a.AddCSV "12, 34", vbInteger 関連 → (CSV) ArrayFromCSV, ArrayFromCSV_Int → CSV (ArrayClass) *********************************************************************** <<< Insert (ArrayClass) >>> *********************************************************************** Insert (ArrayClass) (src) [ 親: ArrayClass クラス ] Sub ArrayClass::Insert( in_BeforeIndex0 as integer, in_AddingElement as variant ) 配列の途中に要素を追加します。 【引数】 in_BeforeIndex0 追加する位置の直前の配列番号、0以上 in_AddingElement 追加する要素 *********************************************************************** <<< Push (ArrayClass) >>> *********************************************************************** Push (ArrayClass) (src) [ 親: ArrayClass クラス ] Sub ArrayClass::Push( Elem as variant ) 配列の最後に要素を追加します。 【引数】 Elem 配列に追加する要素(オブジェクト、またはそれ以外) ArrayClass::Add と同じです。 スタックのように要素を取り出すときは、 → Pop (ArrayClass) キューのように要素を取り出すときは、 → Remove (ArrayClass) *********************************************************************** <<< Pop (ArrayClass) >>> *********************************************************************** Pop (ArrayClass) (src) [ 親: ArrayClass クラス ] Function ArrayClass::Pop() as variant 配列の最後の要素を返し、その要素を配列から除外します。 【引数】 返り値 配列の最後の要素(オブジェクト、またはそれ以外) サンプル 削除する配列番号をスタックにプッシュして、ポップしながら modules 配列の要素を削除する Set i_stack = new ArrayClass For i=0 To modules.UBound_ If modules(i) = "delete" Then i_stack.Push i End If Next Do If i_stack.Count = 0 Then Exit Do modules.Remove i_stack.Pop(), 1 Loop Pop *********************************************************************** <<< Search (ArrayClass) >>> *********************************************************************** Search (ArrayClass) Function ArrayClass::Search( in_KeyItem as variant, in_CompareFunction as Function, in_ParameterOfCompareFunction as variant, in_StartIndexOrEmpty ) as integer or array of integer 比較関数て定義された条件を満たす要素を列挙します。 【引数】 in_KeyItem in_CompareFunction の第2引数 in_CompareFunction 比較関数 in_ParameterOfCompareFunction in_CompareFunction の第3引数 in_StartIndexOrEmpty 比較を開始する要素番号 0以上、または Empty 返り値 配列番号、または、配列番号の配列 in_StartIndexOrEmpty 引数が数値なら、返り値は配列番号です。 見つからなかったら、Empty を返します。 in_StartIndexOrEmpty 引数が Empty なら、返り値は配列番号の配列です。 見つからなかったら 要素数 0 の配列を返します。 ソース → vbslib.vbs テスト → T_Arr.vbs T_ArrayClass_Search *********************************************************************** <<< Remove (ArrayClass) >>> *********************************************************************** Remove (ArrayClass) (src) [ 親: ArrayClass クラス ] Sub ArrayClass::Remove( i as integer, n as string ) as variant 要素を配列から削除して、後の要素を詰めます。 【引数】 i 配列の要素の番号。 先頭は 0 n 削除する要素の数 サンプル Set arr = new_ArrayClass( Array( 0, 1, 2, 3, 4, 5 ) ) arr.Remove 1, 2 Assert IsSameArray( arr.Items, Array( 0, 3, 4, 5 ) ) Remove テスト → T_Arr.vbs # T_ArrClass_Remove *********************************************************************** <<< RemoveObject (ArrayClass) >>> *********************************************************************** RemoveObject (ArrayClass) (src) [ 親: ArrayClass クラス ] Function ArrayClass::RemoveObject( a_Object as object ) as object 指定したオブジェクトを指している配列の要素1つを、配列から除外します。 【引数】 a_Object 配列から除外するオブジェクト 返り値 除外したとき = a_Object、 無かったとき = Nothing オブジェクト 配列要素がすべてオブジェクトでないとエラーになります。 除外した配列番号には、+1の配列番号だったオブジェクトが入り、詰められます。 サンプル: objs.RemoveObject b 実行前: objs.UBound_=3, objs(0)= a, (1)= b, (2)= c, (3)= d ならば 実行後: objs.UBound_=2, objs(0)= a, (1)= c, (2)= d テスト → T_Arr.vbs T_AddNewObj *********************************************************************** <<< RemoveEmpty (ArrayClass) >>> *********************************************************************** RemoveEmpty (ArrayClass) (src) [ 親: ArrayClass クラス ] Sub ArrayClass::RemoveEmpty() Empty になっている配列の要素を詰めます。 サンプル Set arr = new_ArrayClass( Array( 0, Empty, 2, Empty, Empty, 5 ) ) arr.RemoveEmpty Assert IsSameArray( arr.Items, Array( 0, 2, 5 ) ) テスト → T_Arr.vbs # T_ArrClass_RemoveEmpty *********************************************************************** <<< RemoveByIndexes (ArrayClass) >>> *********************************************************************** RemoveByIndexes (ArrayClass) Sub ArrayClass::RemoveByIndexes( in_Indexes as array of integer ) 指定した配列番号の要素を配列から除外します。 【引数】 in_Indexes 除外する要素の配列番号の配列 サンプル Set an_array = new_ArrayClass( Array( "A", "B". "C", "D" ) ) an_array.RemoveByIndexes Array( 1, 3 ) Aseert IsSameArray( an_array, Array( "A", "C" ) ) ) ソース → vbslib.vbs テスト → T_Arr.vbs T_ArrayClass_RemoveByIndexes *********************************************************************** <<< ToEmpty (ArrayClass) >>> *********************************************************************** ToEmpty (ArrayClass) (src) [ 親: ArrayClass クラス ] Sub ArrayClass::ToEmpty() 配列を空にします。 配列要素数は 0 になります。 *********************************************************************** <<< LookUpDic (ArrayClass) >>> *********************************************************************** LookUpDic (ArrayClass) (src) [ 親: ArrayClass クラス ] Function ArrayClass::LookUpDic( Key as string, Value as variant ) as Dictionary 配列の要素の中から、指定した値を持つ辞書を返します。 配列の要素が辞書のときに使えます。 該当する要素が無かったときは、Nothing を返します。 サンプル Set dic1 = CreateObject( "Scripting.Dictionary" ) dic1.Item( "name" ) = "Item1" Set dic2 = CreateObject( "Scripting.Dictionary" ) dic2.Item( "name" ) = "Item2" Set arr = new_ArrayClass( Array( dic1, dic2 ) ) Assert arr.LookUpDic( "name", "Item1" ) Is dic1 "name", "Item1" テスト → T_Dic.vbs # T_LookUpDicInArray 関連 → SearchInSimpleArray *********************************************************************** <<< NewIterator (ArrayClass) >>> *********************************************************************** [ 親: ArrayClass クラス ] NewIterator (ArrayClass) (src) Dim ArrayClass::NewIterator as ArrayClassIterator ArrayClassIterator オブジェクトを生成します。 初めて ArrayClassIterator::GetNext を呼んだときは、先頭の要素を返します。 *********************************************************************** <<< Count (ArrayClass) >>> *********************************************************************** [ 親: ArrayClass クラス ] Count (ArrayClass) (src) Property Get ArrayClass::Count() as integer 配列の要素数を返します。 Count = 2 なら、LBound( Items ) = 0, UBound( Items ) = 1 です。 Visual Basic 系言語では、要素数のシンボルは Count です。 Java 系言語では、要素数のシンボルは Length です。 *********************************************************************** <<< Length (ArrayClass) >>> *********************************************************************** Length (ArrayClass) (src) [ 親: ArrayClass クラス ] Property Get ArrayClass::Length() as integer 配列の要素数を返します。 Length = 2 なら、LBound( Items ) = 0, UBound( Items ) = 1 です。 Visual Basic 系言語では、要素数のシンボルは Count です。 Java 系言語では、要素数のシンボルは Length です。 *********************************************************************** <<< UBound_ (ArrayClass) >>> *********************************************************************** UBound_ (ArrayClass) (src) [ 親: ArrayClass クラス ] Property Get ArrayClass::UBound_() as integer 配列の最大要素番号を返します。 UBound の末尾にアンダースコアが付いています。 (UBound をオーバーライドすると、ArrayClass が実装できなくなるため。) サンプル: For i=0 To Arr.UBound_ Next *********************************************************************** <<< CSV (ArrayClass) >>> *********************************************************************** CSV (ArrayClass) (src) [ 親: ArrayClass クラス ] Property Get ArrayClass::CSV() as string CSV 形式にした配列のすべての要素。 サンプル Dim a : Set a = new ArrayClass a.Add "abc" a.Add "def" echo a.CSV '// "abc,def" CSV サンプル Assert new_ArrayClass( Array( 1, 2, 3 ) ).CSV = "1,2,3" 関連 → AddCSV (ArrayClass) *********************************************************************** <<< Code (ArrayClass) >>> *********************************************************************** Code (ArrayClass) [ 親: ArrayClass クラス ] Property Get ArrayClass::Code() as string VBScript のコードに変換した、配列のすべての要素。 サンプル Dim a : Set a = new ArrayClass a.Add "abc" a.Add "def" echo a.Code '// [ "abc","def" ]と表示 ソース → vbslib.vbs テスト → T_Arr.vbs T_ArrClass_Code *********************************************************************** <<< Copy (ArrayClass) >>> *********************************************************************** Copy (ArrayClass) (src) [ 親: ArrayClass クラス ] Sub ArrayClass::Copy( SrcArr as array or ArrayClass ) 配列のすべての要素をコピーします。 これまで入っていた要素は無くなります。 サンプル: Dim a Set a = New ArrayClass a.Add 1 a.Copy Array( 2, 3 ) '// a は、{ 2, 3 } Copy *********************************************************************** <<< Value (ArrayClass) >>> *********************************************************************** Value (ArrayClass) [ 親: ArrayClass クラス ] 古い仕様です。廃止予定です。 次のように代用できます。 Set arr = new ArrayClass s = GetEchoStr( arr ) Property Get ArrayClass::Value() as string 配列のすべての要素を文字列にします。 *********************************************************************** <<< Echo (ArrayClass) >>> *********************************************************************** Echo (ArrayClass) (src) [ 親: ArrayClass クラス ] 古い仕様です。廃止予定です。 次のように代用できます。 Set arr = new ArrayClass echo arr Sub ArrayClass::Echo() 配列のすべての要素を表示します。 廃止予定です。 Value プロパティを echo 表示してください。 → echo → Value (ArrayClass) *********************************************************************** <<< ArrayClassIterator クラス >>> *********************************************************************** ArrayClassIterator クラス (src) ArrayClass の要素を順番にたどっていくクラスです。 サンプル Dim a : Set a = new ArrayClass Dim iter : Set iter = a.NewIterator() While iter.HasNext() echo iter.GetNext() WEnd 取得 → NewIterator (ArrayClass) メンバー .GetNext 次の要素を返す。 次回の呼び出しでは、その次の要素を返す。 .HasNext 次の要素があるかどうか .GetNextOrSentinel 次の要素を返す。 次の要素が無いときは、番兵を返す。 参考 → イテレーター (JavaScript 1.7) テスト → T_Arr_Target # [T_ArrIter] *********************************************************************** <<< GetNext (ArrayClassIterator) >>> *********************************************************************** GetNext (ArrayClassIterator) → ArrayClassIterator クラス Function ArrayClassIterator::GetNext() as variant 次の要素を返す。 次回の呼び出しでは、その次の要素を返す。 次の要素が無いときは、エラーになります。 エラーにしたくないときは、 GetNextOrSentinel を使ってください。 補足 Java2 の Iterator パターン、JavaScript 1.7 のイテレーターでは、next に相当します。 Next は、VB言語の予約語であることと、Me に副作用があるため、プロパティではなくメソッド であり、メソッドは動詞で始まる方が読みやすいため、GetNext に変更しています。 *********************************************************************** <<< HasNext (ArrayClassIterator) >>> *********************************************************************** HasNext (ArrayClassIterator) → ArrayClassIterator クラス Function ArrayClassIterator::HasNext() as boolean 次の要素があるかどうかを返す。 *********************************************************************** <<< GetNextOrSentinel (ArrayClassIterator) >>> *********************************************************************** GetNextOrSentinel (ArrayClassIterator) → ArrayClassIterator クラス Function ArrayClassIterator::GetNextOrSentinel( Sentinel as variant ) as variant 次の要素を返す。 ただし、次の要素が無いときは、Sentinel 引数(番兵)を返す。 サンプル: Dim f, line, a, elem, iter Set a = new ArrayClass : a.Add new Elem Set iter = a.NewIterator Set sentinel = new Elem Set elem = iter.GetNextOrSentinel( sentinel ) Set f = OpenForRead( path ) Do Until f.AtEndOfStream line = f.ReadLine() If elem.IsMatch( line ) Then '// ここで番兵が使われることがある ... elem = iter.GetNextOrSentinel( sentinel ) '// GetNext ではここでエラーになってしまうことがある End If Loop f = Empty elem = Empty iter = Empty GetNextOrSentinel GetNextOrSentinel *********************************************************************** <<< ArrayDictionary クラス >>> *********************************************************************** ArrayDictionary クラス (src) 標準の Dictionary の Item を、配列にしたクラスです。 1つのキーに対して、複数のアイテムを関連付けするときに使います。 Dictionary Key, Item * ArrayClass * Item サンプル: Dim dic Set dic = new ArrayDictionary dic.Add "key1", "item11" dic.Add "key1", "item12" dic.Add "key1", "item13" dic.Add "key2", "item21" dic.Echo Dim i,j For Each j in dic.Dic.Items() : For Each i in j.Items WScript.Echo i Next : Next 上記スクリプトの出力 item11 item12 item13 item21 メンバ Dic VBScript 標準の Dictionary (プロパティ) ToEmpty すべての要素を削除します Add キーに要素を登録する。キーは重複可能 Count 要素の数 Echo すべての要素を表示する テスト → T_Arr_Target.vbs [T_ArrayDic1] *********************************************************************** <<< Dic (ArrayDictionary) >>> *********************************************************************** Dic (ArrayDictionary) (src) Dim ArrayDictionary::Dic as Dictionary of variant ArrayDictionary クラスがラップしている辞書です。 要素(Item)は、オブジェクトでもそれ以外でも格納します。 *********************************************************************** <<< ToEmpty (ArrayDictionary) >>> *********************************************************************** ToEmpty (ArrayDictionary) (src) Sub ArrayDictionary::ToEmpty() 辞書に要素を空にします。 要素数は 0 になります。 *********************************************************************** <<< Add (ArrayDictionary) >>> *********************************************************************** Add (ArrayDictionary) (src) Sub ArrayDictionary::Add( Key as string, Item as variant ) 辞書に要素を追加します。 【引数】 Key 要素に関連付けるキー文字列 Item 辞書に追加する要素(オブジェクト、またはそれ以外) *********************************************************************** <<< Count (ArrayDictionary) >>> *********************************************************************** Count (ArrayDictionary) (src) Function ArrayDictionary::Count() as integer 辞書の要素数を返します。 【引数】 返り値 辞書の要素数 1つのキーに複数の要素が関連付けされることがあるので、 要素数はキーの数と一致しないことがあります。 *********************************************************************** <<< Echo (ArrayDictionary) >>> *********************************************************************** Echo (ArrayDictionary) (src) Sub ArrayDictionary::Echo() 辞書のすべての要素を表示します。 *********************************************************************** <<< ObjectSetClass >>> *********************************************************************** ObjectSetClass 重複しないでオブジェクトをまとめるコレクション。 サンプル Set objects = new ObjectSetClass Set a_object = new NameOnlyClass Set b_object = new NameOnlyClass objects.Add a_object objects.Add b_object objects.Add b_object echo objects.Count '// 2 objects.Remove b_object echo objects.Count '// 1 ソース → vbslib.vbs テスト → T_Dic.vbs T_ObjectSetClass 関連 → DestroyerClass → g_ObjectIDs *********************************************************************** <<< Add (ObjectSetClass) >>> *********************************************************************** Add (ObjectSetClass) << ObjectSetClass Sub ObjectSetClass::Add( Object as variant ) コレクションに追加されていなければ、コレクションに追加します。 【引数】 Object 追加するオブジェクト *********************************************************************** <<< Count (ObjectSetClass) >>> *********************************************************************** Count (ObjectSetClass) << ObjectSetClass Property Get ObjectSetClass::Count() コレクションに追加されているオブジェクトの数を返します。 【引数】 返り値 コレクションに追加されているオブジェクトの数 *********************************************************************** <<< Items (ObjectSetClass) >>> *********************************************************************** Items (ObjectSetClass) << ObjectSetClass Property Get ObjectSetClass::Items() For 文に指定できるオブジェクトの集合を返します。 *********************************************************************** <<< Exists (ObjectSetClass) >>> *********************************************************************** Exists (ObjectSetClass) << ObjectSetClass Function ObjectSetClass::Exists( Object as variant ) as boolean コレクションに追加されているかどうかを返します。 *********************************************************************** <<< Remove (ObjectSetClass) >>> *********************************************************************** Remove (ObjectSetClass) << ObjectSetClass Sub ObjectSetClass::Remove( Object as variant ) コレクションに追加されていれば、コレクションから除外します。 【引数】 Object 除外するオブジェクト *********************************************************************** <<< RemoveAll (ObjectSetClass) >>> *********************************************************************** RemoveAll (ObjectSetClass) << ObjectSetClass Sub ObjectSetClass::RemoveAll() コレクションからすべてのオブジェクトを除外します。 *********************************************************************** <<< ${ } 変数, LazyDictionaryClass >>> *********************************************************************** ${ } 変数, LazyDictionaryClass 辞書の値に、辞書のキーへの参照を入れて、遅延評価する辞書です。 LazyDictionaryClass のオブジェクトは名前空間に相当し、キーは変数名に相当します。 Set g = new LazyDictionaryClass g("${RootPath}") = "C:\Folder${Target}" g("${Target}") = "A" Assert g("${RootPath}") = "C:\FolderA" OSの環境変数を参照することもできます。 Set g = new LazyDictionaryClass Assert g("${USERPROFILE}\Desktop") = "C:\Users\user1\Desktop" キーは、${ 〜 } 形式(例: ${A})にしてください。 $〜 形式(例: $A)は、エラーになります。 キーの ${ 〜 } の中に "$", "{", "}" は使えませんが、他の記号、Unicode文字(日本語など) は使えます。 キーの展開は参照時( g("${Var}") を Get するとき)に行われる(遅延評価である)ため、 キーを含むアイテム(値)を設定するときに、そのキーが定義されていなくても構いません。 例:上記 ${Target}。 つまり、連続して設定するときは、設定する順番を問いません。 参照時にキーが存在しないときは、エラーになります。 簡単な文字列変換関数なら、 辞書のデータに置き換えることができます。 → アイテムを一覧表示する → デバッグ・モード → 既存の変数の値を、別の変数によって間接参照させる → 文字列以外の値の参照 → 配列を値にする → 数列、CSV 形式、ToCSV → 関数を呼び出す → 2つの辞書を加算する → 遅延評価する前の値や式の参照 → 値から変数に戻す → 参照記号 ${ } のエスケープ → 文字列のスペルミス対策、${> } → 説明変数の活用 → new_LazyDictionaryClass XML の Variable タグを変数にした辞書を返します → GetPathLazyDictionary パスに関する変数か定義された辞書を返します → ParseDollarVariableString ${ } を使った式を解析します ソース → vbslib.vbs テスト → T_LazyDictionary.vbs 関連 → FF-path 属性対応の XML、path 属性と、Except タグ → DictionaryClass → 関数型プログラミング → DicItemOfItem → PHPやPerlで変数の記号に「$」が使われる理由 - 小粋空間 (Web) → Dollar sign >> Programming languages - Wikipedia (Web) アイテムを一覧表示する EchoToEditor メソッドを呼び出すと、アイテムのキーと展開前の値と展開後の値が書かれた テキスト エディターが開きます。 内容は、GetSetListString の返り値と同じです。 Set g = new LazyDictionaryClass g("${Var1}") = "Value1" g("${Var2}") = "${Var1}-2" g.EchoToEditor EchoToEditor テキスト エディターで開く内容: ${Var1} = "Value1" ${Var2} = "${Var1}-2" = "Value1-2" デバッグ・モード 下記のように、デバッグ・モードをオンにすると、設定した内容を echo 表示したり、参照時にキーを 1つずつ展開する様子を echo 表示します。 ただし、スクリプトの中の LazyDictionaryClass のオブジェクト(下記の g)の特定が必要です。 g.DebugMode = True '// [TODO] 追加 g("${Target}") = "B" echo g("${RootPath}") echo 表示の内容: B C:\Folder${Target} C:\FolderB 既存の変数の値を、別の変数によって間接参照させる 元々、下記のように使われていた変数 ${RootPath} があるとします。 g("${RootPath}") = "C:\FolderA" Assert g("${RootPath}") = "C:\FolderA" 変数の値を、別の変数の値によって動的に変えたい場合は、下記のどちらの記述もできます。 g("${RootPath}") = "C:\Folder${Target}" g("${Target}") = "A" Assert g("${RootPath}") = "C:\FolderA" g("${Target}") = "B" Assert g("${RootPath}") = "C:\FolderB" g("${RootPath}") = "${${Target}/RootPath}" g("${TargetA/RootPath}") = "C:\FolderA" g("${TargetB/RootPath}") = "C:\FolderB" g("${Target}") = "TargetA" Assert g("${RootPath}") = "C:\FolderA" g("${Target}") = "TargetB" Assert g("${RootPath}") = "C:\FolderB" 単純な変換関数であれば、関数をデータに置き換えることもできます。 下記の RootPath が、関数の代わりです。 キーが存在しなければ、エラーになります。 g("${RootPath( TargetA )}") = "C:\FolderA" g("${RootPath( TargetB )}") = "C:\FolderB" target = "TargetA" Assert g("${RootPath( "+ target +" )}") = "C:\FolderA" 文字列以外の値の参照 式を参照すると、文字列になります。 式とは、${ } で囲まれた変数以外の文字がある文字列です。 g("${Var}") = True Assert g("${Var}") = True '// 式ではないので boolean 型のまま Assert g("Var=${Var}") = "Var=True" '// 式なので文字列に変換 オブジェクトの設定と参照ができます。 Set g("${Var}") = new NameOnlyClass echo g("${Var}").Name GetFullPath メソッド は、変数の値を参照し、フル パスを返します。 g("${F1}") = "C:\Folder1" g("${F2}") = "C:\Folder2" Assert g.GetFullPath( "File.txt", "C:\Folder1" ) = "C:\Folder1\File.txt" Assert g.GetFullPath( "File.txt", "${F1}" ) = "C:\Folder1\File.txt" Assert g.GetFullPath( "${F2}\File.txt", "${F1}" ) = "C:\Folder2\File.txt" Assert g.GetFullPath( "File.txt", "${No}" ) '// Error 関連 → GetFullPath 配列を値にする 値( = の右)に配列を指定することができます。 また、配列の要素に、配列を値を持つ変数への参照を指定すると、ネストしないで展開されます。 Set g = new LazyDictionaryClass g("${Array1}") = Array( "${Var}/1", "${Var}/2" ) g("${Array2}") = Array( "${Array1}", "${Var}/3", "${Var}/4", "${Var}/5" ) g("${Var}") = "x" array1 = g("${Array1}") array2 = g("${Array2}") Assert IsSameArray( array1, Array( "x/1", "x/2" ) ) Assert IsSameArray( array2, Array( "x/1", "x/2", "x/3", "x/4", "x/5" ) ) For Each value In g("${Array2}") echo value Next Each_ や EachFormula を使えば、配列の要素をループ変数のように扱って変換できます。 また、辞書を参照するときに、配列を指定することもできます。 Set g = new LazyDictionaryClass g("${Workspace/Lib}") = "FolderA" g("${Workspace/Sample}") = "FolderB" values1 = g.Each_( "${Workspace/${i}}", "${i}", Array( "Lib", "Sample" ) ) Assert IsSameArray( values1, Array( "FolderA", "FolderB" ) ) formulas = g.EachFormula( "${Workspace/${i}}", "${i}", Array( "Lib", "Sample" ) ) Assert IsSameArray( formulas, Array( "${Workspace/Lib}", "${Workspace/Sample}" ) ) values2 = g( formulas ) Assert IsSameArray( values2, values1 ) 数列、CSV 形式、ToCSV Assert g("${ToCSV( %d, 1, 3 )}") = "1, 2, 3" Assert g("${ToCSV( %d, 2, 5 )}") = "2, 3, 4, 5" Assert g("${ToCSV( %d, 2, 5 )}") = "5, 4, 3, 2" Assert g("${ToCSV( %02d, 1, 3 )}") = "01, 02, 03" g("${N}") = "Num" Assert g("${ToCSV( ${N} = %d, 1, 3 )}") = "Num = 1, Num = 2, Num = 3" Assert g("${N} = ${ToCSV( %d, 1, 3 )}") = "Num = 1, 2, 3" ( ) の中のパラメーターは、 C言語の printf 書式 、開始の値、最後の値です。 ( ) の中のパラメーターは、CSV としてパースされるので、" "で囲むこともできます。 C言語の printf 書式の中に、${ } 変数を記述できます。 参考 → Python - 数列 (range クラス) テスト → T_LazyDictionary.vbs T_LazyDictionaryCSV 関数を呼び出す ${Function( parameters )} 形式を指定すると、アプリケーションが定義した関数を呼び出す、 または、VBScript で定義した関数をコールバックさせることができます。 UpperCase 関数をパラメーター abc, def で呼び出し、ABC, DEF が返されたことをチェックする には、次のように記述します。 Assert g("${UpperCase( abc, def )}") = "ABC, DEF" コールバックする関数を設定するには、次のように記述します。 Set g("${UpperCase()}") = GetRef( "UpperCase" ) 関数は下記の型である必要があります。 Function LazyDictionaryFunction( ref_Dictionary as LazyDictionaryClass, in_FunctionName as string, in_Parameter as string ) as Variant LazyDictionaryFunction LazyDictionaryClass で ${Function( parameters )} 形式を指定したときに呼び出す関数の型。 【引数】 ref_Dictionary LazyDictionaryClass のオブジェクト in_FunctionName 関数名。 例:"${FunctionName()}" in_Parameter 括弧の中のすべてのパラメーター 返り値 ${Function( parameters )} を置き換えた後の値 in_Parameter の中にあるそれぞれのパラメーターを取得するときは、 ArrayFromCSV などを使ってください。 ref_Dictionary の Delegate メンバー変数は、LazyDictionaryClass オブジェクトを生成 したユーザーが設定して、コールバック関数で参照することができます。 サンプル Sub Main() Set g = new LazyDictionaryClass Set g("${GetObject()}") = GetRef( "My_GetObject" ) Set object = g("${GetObject( a,b )}") Assert object.Name = " a,b " Set g("${UpperCase()}") = GetRef( "My_UpperCase" ) g.Delegate = "UserDefined" Assert g("before ${Upper( a,b )} after") = _ "before ( A,B ) after" End Sub Function My_GetObject( ref_Dictionary, in_FunctionName, in_Parameter ) Set object = new NameOnlyClass object.Name = in_Parameter Set My_GetObject = object End Function Function My_UpperCase( ref_Dictionary, in_FunctionName, in_Parameter ) Assert in_FunctionName = "${My_UpperCase()}" Assert ref_Dictionary.Delegate = "UserDefined" My_GetObject = "("+ UCase( in_Parameter ) +")" End Function 2つの辞書を加算する (AddDictionary) Set a = new LazyDictionaryClass Set b = new LazyDictionaryClass a.AddDictionary b 関連 → Dic_add 遅延評価する前の値や式の参照 遅延評価する前の値を参照するには、Formula プロパティを使います。 g("${RootPath}") = "C:\Folder${Target}" g("${Target}") = "A" Assert g.Formula("${RootPath}") = "C:\Folder${Target}" Assert g("${RootPath}") = "C:\FolderA" Formula EvaluateReverse と異なり、変数の値に一致しても、変数に戻ることはありません。 g("${RootPath}") = "C:\Folder\A" g("${Target}") = "A" Assert g.Formula("${RootPath}") = "C:\Folder\A" Assert g.Formula("${RootPath}") <> "C:\Folder\${Target}" XML の Variable タグの type 属性は、Type_ プロパティで参照できます。 サンプル type file.WriteLine "" Type_ サンプル path = t("C:\Folder")+"\Sub\Setting.xml" base_path = GetParentFullPath( path ) Set root = LoadXML( path, Empty ) Set g = LoadVariableInXML( root, path ) Assert g.Formula("${FullPath1}") = t("C:\Folder")+"\ABC" Assert g.Formula("${StepPath}") = "..\ABC" Assert g.Formula("${ABC}") = "ABC" Assert g.Formula("${FullPath2}") = "${FullPath1}\File.txt" Assert g.Formula("${FullPath3}") = t("C:\Folder")+"\Sub\${StepPath}\File.txt" Set file = OpenForWrite( "_out.xml", g_VBS_Lib.UTF_8 ) file.WriteLine "" file.WriteLine "" file.WriteLine "" For Each variable_name In Array( _ "${FullPath1}", "${StepPath}", "${ABC}", "${FullPath2}", "${FullPath3}" ) If not IsFullPath( g.Formula( variable_name ) ) Then file.WriteLine "" Else file.WriteLine "" End If Next file.WriteLine "" file.WriteLine "" file = Empty LoadVariableInXML FullPathType 値から変数に戻す (EvaluateReverse, GetStepPath) Set g = new LazyDictionaryClass g("${A}") = "AAA" g("${B}") = "BB" Assert g.EvaluateReverse( "1AAA2BB3AAA4" ) = "1${A}2${B}3${A}4" EvaluateReverse Set g = new LazyDictionaryClass g("${A3}") = "AAA" g("${A4}") = "AAAA" g("${A2}") = "AA" Assert g.EvaluateReverse( "AAAA" ) = "${A4}" 値の文字列の長さが長い変数に優先的に変換されます。 Set g = new LazyDictionaryClass g("${XA}") = "X:\FolderA" g("${Extension}") = ".txt" Assert g.GetStepPath( "X:\FolderA\File.xml", "X:\" ) = "${XA}\File.xml" Assert g.GetStepPath( "C:\FolderA\File.xml", "C:\FolderA" ) = "File.xml" Assert g.GetStepPath( "C:\FolderA\File.txt", "C:\FolderA" ) = "File${Extension}" GetStepPath GetStepPath メソッドでは、フル パスが格納された変数に戻らなかったときだけ、 指定した基準パスからの相対パスに変換されます。 ちなみに、戻した変数を一覧するときは、指定する 正規表現 を、 \$\{.*\} ではなく、 \$\{[^\}]*\} にします。 複数の変数があるときでも正しく処理するようになります。 ParseDollarVariableString でも変数を一覧することができます。 参照記号 ${ } のエスケープ $\{ と書くと、${ という文字列データができます。 この処理は、変数の展開をしないために、 最後に行われます。 展開した結果に $\ があるときは、$ に置き換わります。 g("$\{") = "${" '// $\ は $ に置き換わります g("$\\") = "$\" g("$\}") = "$}" g("$A") = "$A" '// $ の後に { がないと、そのまま (メモ) このエスケープにより、単純に "${" を検索すれば、それが展開すべき変数かどうかが 分かります。 逆に、変数でない ${ を含む文字列を、${ 〜 } 変数を変換しようとする文字列に入れる場合は、 次の変換をします。 '// "$\" => "$\\", "${" => "$\{" text = Replace( Replace( text, "$\", "$\\" ), "${", "$\{" ) Set g = new LazyDictionaryClass echo g(text) 関連 → GrepKeyword 文字列のスペルミス対策、${> } キーが存在しないときに自動的にキーを追加しないため、文字列のスペルミスを防ぐことができます。 ただし、キーとアイテムが異なることが一般的である辞書型では、アイテムを調べなければ 文字列を知ることができないため、開発効率が落ちます。 そこで、キーの先頭が ">" から、アイテムと同じであるようなルールにするとよいでしょう。 なお、> を選んだ理由は、メールの引用(コピー)記号や、NaturalDocs の空白を維持する記号に 近い意味を持っているからです。 Set g = new LazyDictionaryClass g("${>Spell}") = "Spell" ${> } 形式の記述は、次の関数でも使われています。 → GetPercentURL 特殊な URL 予約文字をエスケープしない → GetTagJumpParams ${>#} で、# をファイル名の一部にする 参考 → 参照記号 ${ } のエスケープ 説明変数の活用 辞書を参照するコードが長くなるときは、役割を説明する説明変数をローカルで(関数内のスコープ をもつ変数を)活用するとよいでしょう patch_path = g("${Repository_workspace}\Sample_Test_patch\patch") 参考 → 説明変数 *********************************************************************** <<< LoadVariableInXML >>> *********************************************************************** LoadVariableInXML Function LoadVariableInXML( in_RootXML_Element as IXMLDOMElement, in_FilePathOfXML as string ) as LazyDictionaryClass XML の Variable タグ で定義された変数を持つ、遅延評価する辞書を生成します。 【引数】 in_RootXML_Element XML のルート要素オブジェクト、または、FilePathClass のオブジェクト in_FilePathOfXML in_RootXML_Element が書かれている XML ファイルのパス 返り値 遅延評価する辞書 → LazyDictionaryClass スクリプトの内部では、 LoadVariableInXML 関数 で、Variable タグによる変数定義をロードします。 変数を参照するときは、DOM API で値を取得した後で、評価(変数の展開を)する処理を書く 必要があります。(下記サンプル コードを参照) 2つの辞書を合成するときは、 AddDictionary または Dic_add を呼び出してください。 Variable タグ Variable タグに対応した XML ファイルには、${ } 形式の変数の定義と、変数の参照を記述する ことができます。 変数の定義は、以下のように Variable タグを記述します。 ただし、name は、${ から始まり、} で 終えてください。 Variable タグは、XML の中のどこでも記述することができます。 変数の定義の例: ${Var1} 変数名は ${Var1} で、その値は ABC です。 思ったように展開されないときは、 デバッグ・モード を試してみてください 手動で変数の展開をするときは、 EvaluateByVariableXML コマンド が使えます。 type 属性を FullPathType に設定すると、値をフル パスにすることができます。 値に OS の環境変数を指定する ことができます。 変数の参照を記述する場所によって値を変更するときは、 LocalVariable タグ で定義してください。 変数の参照を記述できる場所は、XML ファイルの種類やアプリケーションによって異なります。 それぞれの仕様を確認してください。 たとえば、Project タグの path 属性に変数を指定できる 仕様の場合、以下のように記述できます。 変数の定義と参照の例: ${Var1} path 属性は C:\ABC.txt になります。 変数の参照を記述できる場所には、 OS の環境変数を指定する こともできます。 ${ } 変数は、 LazyDictionaryClass によって管理されるため、遅延評価されます。 アプリケーション定義の関数を呼び出す ことができます。 サンプル スクリプト: Set root = LoadXML( "Sample.xml", Empty ) Set variables = LoadVariableInXML( root, "Sample.xml" ) data = root.selectSingleNode( "Data" ).getAttribute( "data" ) Assert data ="${Var1}DEF" data = variables( data ) Assert data = "ABCDEF" variables LoadVariableInXML variables Sample.xml ${Var1} ${Var1} type 属性 "FullPathType" (Variable タグ) type 属性を "FullPathType" にすると、value 属性を相対パスとして、変数を参照したときは フル・パスが返ります。 通常、基準フォルダーは XML ファイルがあるフォルダーです。 XML に記述する value 属性は、相対パスを指定してください。 value 属性がフル パスの値を 持つ変数から始まるときは、type 属性に "FullPathType" を指定しないでください。 value 属性を、ピリオド 3つから始めると、内部で SearchParent を呼び出して、親フォルダー を探しにいきます。 new_LazyDictionaryClass 関数の引数に FilePathClass のオブジェクトを指定すると、 FilePathClass::FilePath の親フォルダーを基準にします。 引数に文字列を指定した場合は、 相対パスの基準はカレント・フォルダーになります。 XML のルート要素オブジェクトは、 FilePathClass::Text に指定してください。 フル・パスに変換するタイミングは、new_LazyDictionaryClass 関数を呼び出したときで、 遅延評価ではありません。 サンプル type="FullPathType" サンプル Sample.xml スクリプト: Set xml = new FilePathClass xml.FilePath = "Sample.xml" Set xml.Text = LoadXML( xml.FilePath, Empty ) Set variables = new_LazyDictionaryClass( xml ) base_path = GetParentFullPath( xml.FilePath ) Assert variables( "${FullPath1}" ) = GetFullPath( "..\File.txt", base_path ) Assert variables( "${FullPath2}" ) = GetFullPath( "..\File.txt", base_path ) Assert variables( "${ErrorPath}" ) = _ base_path +"\"+ GetFullPath( "..\File.txt", base_path ) '// Example: "C:\Folder\Sub\C:\Folder\File.txt" Assert variables.Formula( "${ErrorPath}" ) = "C:\Folder\Sub\${ErrorPath}" ${FullPath1} OS の環境変数を指定する ${ } の中に OS の環境変数名を記述すると、その値を参照することができます。 変数を定義する Variable タグの value 属性や、${ } 変数を参照できる場所に、OS の環境変数の 参照を記述できます。 サンプル ${USERPROFILE} ${USERPROFILE} USERPROFILE は、OS の環境変数の名前です。 アプリケーション定義の関数を呼び出す アプリケーションによっては、${ } の中に ( ) が付いた関数呼び出しを記述することができます。 サンプル 参考 → LazyDictionaryClass - 関数を呼び出す ソース → vbslib.vbs → vbslib_mini.vbs テスト → T_LazyDictionary.vbs T_LazyDictionaryXML 関連 → LoadLocalVariableInXML → EvaluateByVariableXML *********************************************************************** <<< LoadLocalVariableInXML >>> *********************************************************************** LoadLocalVariableInXML Function LoadLocalVariableInXML( in_CurrentXML_Element as IXMLDOMElement, in_GlobalVariables as LazyDictionaryClass, in_FilePathOfXML as string ) as LazyDictionaryClass XML の LocalVariable タグで定義された変数を持つ、遅延評価する辞書を生成します。 【引数】 in_CurrentXML_Element 変数の参照がある XML 要素のオブジェクト in_GlobalVariables LoadVariableInXML 関数 の返り値 in_FilePathOfXML in_CurrentXML_Element が書かれている XML ファイルのパス 返り値 遅延評価する辞書 → LazyDictionaryClass in_CurrentXML_Element 引数に指定した XML要素の親方向のすべての XML要素の直下にある と、すべての による変数の定義が返り値に含まれます。 in_CurrentXML_Element 引数に、XML要素 A の兄弟 XML要素 B を指定して返る辞書は、XML要素 A を 指定して返る辞書と同じ内容です。 LocalVariable タグ LocalVariable タグは、 Variable タグ と同じく変数を定義する XML タグですが、参照する場所によって 値が異なるローカル変数を定義することができます。 ただし、Variable タグが定義できる XML ファイルやアプリケーションであっても、LocalVariable タグは 無視される場合があります。 また、XML 属性やテキストによっては、LocalVariable タグによって定義 された変数を参照できない場合もあります。 それぞれの仕様を確認してください。 逆に LocalVariable タグが使える場所では、 Variable タグも記述できます。 ローカル変数の定義の例: ${Var1} 変数名は ${Var1} で、その値は ABC です。 type 属性を FullPathType に設定すると、値をフル パスにすることができます。 値に OS の環境変数を指定する ことができます。 LocalVariable タグを記述する場所は、変数を参照している XML タグの兄弟ノード、または、親方向の ノードの子ノードに記述してください。 同じ名前の変数を記述したときは、変数を参照している XML タグに近い定義の値が得られます。 ローカル変数の参照の例: ${Var1} ${Var1} ${Var1} ProjectA の path 属性は AA.txt になります。 ProjectB の path 属性は BB.txt になります。 ProjectC の path 属性は CC.txt になります。 サンプル path = "Sample.xml" Set root = LoadXML( path, Empty ) Set global_variables = LoadVariableInXML( root, path ) Set project_tag = root.selectSingleNode( "Tree/ProjectA" ) Set variables = LoadLocalVariableInXML( project_tag, global_variables, path ) path = project_tag.getAttribute( "path" ) path = variables( path ) "Tree/ProjectA" variables LoadLocalVariableInXML variables ソース → vbslib.vbs テスト → T_LazyDictionary.vbs T_LazyDictionaryXML_Local → T_LazyDictionaryXML_Local.xml *********************************************************************** <<< new_LazyDictionaryClass >>> *********************************************************************** new_LazyDictionaryClass 注意 廃止されました。 代わりは、 → LoadVariableInXML Function new_LazyDictionaryClass( RootXML_Element as IXMLDOMElement ) as LazyDictionaryClass XML の Variable タグで定義された変数を持つ、遅延評価する辞書を生成します。 【引数】 RootXML_Element XML のルート要素オブジェクト、または、FilePathClass のオブジェクト 返り値 遅延評価する辞書 → LazyDictionaryClass RootXML_Element 引数 以下のどちらかを指定できます。 → LoadXML XML のルート要素オブジェクト FilePathClass のオブジェクト → FilePathClass *********************************************************************** <<< GetPathLazyDictionary >>> *********************************************************************** GetPathLazyDictionary Function GetPathLazyDictionary() as LazyDictionaryClass パスに関する変数か定義された辞書を返します。 【引数】 返り値 パスに関する変数か定義された辞書 OSの環境変数だけでなく、下記の変数も参照することができます。 → ${ } 変数, LazyDictionaryClass ${vbslib} vbslib Prompt.vbs があるフォルダーのフル パス。 vbslib Prompt.vbs を起動したときだけ定義されます。 ${scriptlib} scriptlib フォルダーのフル パス。 g_vbslib_folder と異なり、末尾に \ なし。 ソース → vbslib.vbs *********************************************************************** <<< ParseDollarVariableString >>> *********************************************************************** ParseDollarVariableString Sub ParseDollarVariableString( the_String as string, out_SubStringArray as array of string, out_VariableArray as array of string ) 文字列の中の ${ } を使った変数の部分とそれ以外の部分に分割します。 【引数】 the_String 分割する前の文字列 out_SubStringArray (出力) 変数以外の部分の配列 out_VariableArray (出力) 変数の部分の配列 文字列の先頭に "${ }" があるときは、out_SubStringArray(0) = "" になります。 サンプル ParseDollarVariableString "abc ${VAR1}, ${VAR2} def", sub_strings, variables Assert IsSameArray( sub_strings, Array( "abc ", ", ", " def" ) ) Assert IsSameArray( variables, Array( "${VAR1}", "${VAR2}" ) ) ソース → ToolsLib.vbs テスト → T_Str.vbs T_ParseDollarVariableString 関連 → ScanFromTemplate → ParsePercentVariableString *********************************************************************** <<< 配列 (Array) >>> *********************************************************************** 配列 (Array) *********************************************************************** <<< new_EmptyArray >>> *********************************************************************** new_EmptyArray Function new_EmptyArray( in_UBound as integer ) as array 指定した要素数の空要素を持つ配列を生成します。 【引数】 in_UBound 最大配列番号。 要素数−1 返り値 生成した配列 VBScript (WSH) だけでなく、エクセル VBA でも使えます。 ソース → vbslib.vbs *********************************************************************** <<< AddArrElem >>> *********************************************************************** AddArrElem Sub AddArrElem( Dst, Src ) 配列の要素を追加コピーします。 【引数】 Dst コピー先配列。 この配列の末尾に追加 Src コピー元の要素が入った配列、またはコピー元の単体。 これまで入っていた要素の後に追加します。 Dst には、Me.Property 形式ではなく、Property 形式にしてください。(下記) AddArrElem Me.SampleArray, Array( 1,2 ) Me. ×:追加されない AddArrElem SampleArray, Array( 1,2 ) ○:追加される サンプル AddArrElem arr1, arr2 '// Set "arr1" AddArrElem arr1, new ClassA '// Set "arr1" ソース → vbslib.vbs テスト → T_Arr.vbs T_Arr1 関連 → AddElems (ArrayClass) → 値渡しと参照渡し → AddArrElemEx → AddNewObject (ArrayClass) *********************************************************************** <<< AddArrElemEx >>> *********************************************************************** AddArrElemEx Function AddArrElemEx( Dst, Src, IsReturn ) as Dst or Empty 配列の要素を追加コピーします。(機能拡張版) 【引数】 Dst コピー先配列。 この配列の末尾に Src 引数を追加 Src コピー元の要素が入った配列、またはコピー元の単体。 IsReturn True = 返り値は追加コピーした内容、False = 返り値は Empty 参考 → AddArrElem ソース → vbslib.vbs *********************************************************************** <<< FlatArray >>> *********************************************************************** FlatArray Sub FlatArray( out_FlatArray as array, NestedArray as array ) 配列の中に配列がネストして入っているとき、フラットにします。 【引数】 out_FlatArray (出力) フラットにした配列 NestedArray 配列がネストして入っている配列 サンプル input_array = Array( "a", "b", Array( "ca", "cb" ), "d", Array( "ea", "eb" ) ) FlatArray out_array, input_array Assert IsSameArray( out_array, Array( "a", "b", "ca", "cb", "d", "ea", "eb" ) ) ソース → vbslib.vbs テスト → T_Arr.vbs T_FlatArray *********************************************************************** <<< CopyArr >>> *********************************************************************** CopyArr (src) Sub CopyArr( Dst, Src ) 廃止されました。 Dim arr() とすると arr = Array はできませんが、 Dim arr とすると arr = Array ができます。 配列の要素をコピーします。 【引数】 Dst コピー先 Arr コピー元 Arr が配列ではないときは、Dst(0) に Src をコピーします。 Dst に ArrayClass::Items を指定してもコピーした内容は ArrayClass に格納されません。 ArrayClass::Copy を使ってください。 *********************************************************************** <<< SearchInSimpleArray >>> *********************************************************************** SearchInSimpleArray (src) Function SearchInSimpleArray( InData as variant, InArray as array of variant, OutBaseNumOrArray as array of variant, DefaultOut as variant ) as variant 配列を検索して、別の配列の内容を返します。 【引数】 InData 配列の要素と比較する値。 数値、文字列など = で判定できるもの InArray InData を比較する値を要素に持つ配列 OutBaseNumOrArray 出力する値を要素に持つ配列。 または、出力の最小数値 DefaultOut InData が InArray に見つからなかったときに出力する値 返り値 OutBaseNumOrArray に指定した配列の要素の1つなど サンプル num = SearchInSimpleArray( "SymbolB", _ Array( "SymbolA", "SymbolB" ), _ Array( 1, 2 ), _ Empty ) '// num = 2 サンプル num = SearchInSimpleArray( "SymbolB", Array( "SymbolA", "SymbolB" ), 5, Empty ) '// num = 6 出力の最小数値が 5 で、2番目の配列要素にヒットしたので、5 + ( 2 -1 ) = 6 を返します。 関連 → LookUpDic (ArrayClass) *********************************************************************** <<< GetFirst >>> *********************************************************************** GetFirst Function GetFirst( in_Collection as variant ) as variant コレクションの最初の要素を返します。 【引数】 in_Collection 配列や辞書コレクション 返り値 配列やコレクションの最初の要素、辞書の場合は最初のキー サンプル Assert GetFirst( Array( 1, 2 ) ) = 1 ソース → vbslib.vbs 関連 → GetDicItemByIndex *********************************************************************** <<< IsSameArray >>> *********************************************************************** IsSameArray (src) Function IsSameArray( Array1, Array2 ) as boolean 配列のすべての要素が等しいか判定します。 各要素は = で判定します。 要素数も等しいか調べます。 順番も合っている必要があります。 Array1, Array2 は、Empty, 配列型、ArrayClass 型のいずれかを指定できます。 Array1 = Empty, Array2 = Empty のときは、True を返します。 ソース → vbslib.vbs テスト → T_Arr.vbs T_IsSameArray 関連 → IsSameArrayOutOfOrder *********************************************************************** <<< IsSameArrayOutOfOrder >>> *********************************************************************** IsSameArrayOutOfOrder Function IsSameArrayOutOfOrder( in_Array1 as array, in_Array2 as array, Option_ ) as boolean 配列のすべての要素が等しいか判定します。 ただし、順番が異なっていても等しいとします。 各要素は = で判定します。 Option_ 引数 Empty または、下記の論理和 (or) が指定できます。 c.StopIsNotSame 違った要素を見つけた瞬間に、デバッガーで停止します c は、g_VBS_Lib です。 ソース → vbslib.vbs テスト → T_Arr.vbs T_IsSameArrayOutOfOrder 関連 → IsSameArray *********************************************************************** <<< IsSameArrayEx >>> *********************************************************************** IsSameArrayEx Function IsSameArrayEx( Array1 as array, Array2 as array, Option_ as IsSameArrayExOptionClass ) as boolean 配列のすべての要素が等しいか判定します。 ソース → vbslib.vbs IsSameArrayExOptionClass .IsOutOfOrder 順番が異なっていても等しいとするかどうか → IsSameArrayOutOfOrder .IsStopNotSame 違った要素を見つけた瞬間に、デバッガーで停止します .CompareFunction 比較関数 .ParameterOfCompareFunction CompareFunction の第3引数に渡す値 ソース → vbslib.vbs *********************************************************************** <<< ReverseObjectArray >>> *********************************************************************** ReverseObjectArray Sub ReverseObjectArray( in_Array as array, out_Array as array ) 配列を内容(オブジェクトのみ)を逆順にします。 【引数】 in_Array 配列。逆順にする前の内容 out_Array (出力) 逆順の配列の内容 配列の要素が、オブジェクト以外が入っていたり、Empty になっているとエラーになります。 ArrayToNameOnlyClassArray で変換してください。 out_Array と in_Array は同じ配列を指定できません。 ただし、in_Array 引数に、array_object.Items (array_object は ArrayClass) を指定したら、 out_Array 引数に、array_object を指定できます。 ただし、ArrayClass ではなくなります。 サンプル ReverseObjectArray an_array.Items, an_array For Each an_item In an_array Next ソース → vbslib.vbs テスト → T_Arr.vbs T_ReverseObjectArray 関連 → Reverse_COM_ObjectArray *********************************************************************** <<< Reverse_COM_ObjectArray >>> *********************************************************************** Reverse_COM_ObjectArray Sub Reverse_COM_ObjectArray( in_Array, out_Array ) .Count プロパティで要素数を参照する配列を、逆順にします。 参考 → ReverseObjectArray ソース → vbslib.vbs テスト → T_Arr.vbs T_ReverseObjectArray *********************************************************************** <<< ReverseNotObjectArray >>> *********************************************************************** ReverseNotObjectArray Sub ReverseNotObjectArray( in_Array, out_Array ) 要素がオブジェクト型ではない配列を、逆順にします。 ソース → vbslib.vbs *********************************************************************** <<< RemoveObjectArray >>> *********************************************************************** RemoveObjectArray Sub RemoveObjectArray( in_out_Array, ElementObject ) オブジェクトが格納された配列から、指定したオブジェクトを除外します。 【引数】 in_out_Array オブジェクトが格納された配列 ElementObject 除外するオブジェクト ソース → vbslib.vbs 関連 → AddNewObject (ArrayClass) → Dic_addNewObject *********************************************************************** <<< RemoveObjectsByNames >>> *********************************************************************** RemoveObjectsByNames Sub RemoveObjectsByNames( in_out_Array, Names as variant ) オブジェクトが格納された配列から、Name プロパティがマッチするオブジェクトを除外します。 【引数】 in_out_Array Name プロパティがあるオブジェクトが格納された配列 Names Name プロパティと比較するもの Names が文字列のとき Name プロパティと単純に比較します。 Names が RegExp 型のとき Name プロパティと正規表現で比較します。 → 正規表現 (VBScript.RegExp) Names がオブジェクトのとき Name プロパティと Name プロパティを比較します。 Names が配列型のとき 配列の要素のそれぞれについて、1つでのマッチしたら除外します。 要素は、文字列、RegExp、Name プロパティを持つオブジェクトを混在できます。 ソース → vbslib.vbs テスト → T_Arr.vbs T_RemoveObjectsByNames *********************************************************************** <<< ArrayToNameOnlyClassArray >>> *********************************************************************** ArrayToNameOnlyClassArray (src) Function ArrayToNameOnlyClassArray( aArray as array of not object ) as array of NameOnlyClass オブジェクトではない要素を持つ配列を、NameOnlyClass の配列に変換します。 【引数】 aArray オブジェクトではない要素を持つ配列 返り値 NameOnlyClass の配列 → NameOnlyClass ソートできる配列にします。 NameOnlyClass の Delegate メンバーは Empty になります。 サンプル arr = ArrayToNameOnlyClassArray( Array( "a", "b", "c" ) ) 関連 → QuickSort → ShakerSort → NameOnlyClassArrayToArray 逆の変換 → DicItemToNameOnlyClassItem 辞書版 テスト → T_ShakerSort.vbs T_SortByPath *********************************************************************** <<< NameOnlyClassArrayToArray >>> *********************************************************************** NameOnlyClassArrayToArray (src) Function NameOnlyClassArrayToArray( aArray as array of object ) as array of variant Name プロパティを持つオブジェクトの配列を、Name プロパティの値の配列に変換します。 【引数】 aArray Name プロパティを持つオブジェクトの配列 → NameOnlyClass 返り値 Name プロパティの値の配列 ソートできる配列から戻します。 関連 → ArrayToNameOnlyClassArray 逆の変換 → NameOnlyClassItemToDicItem 辞書版 テスト → T_ShakerSort.vbs T_SortByPath *********************************************************************** <<< その他 >>> *********************************************************************** その他 → (CSV) ArrayFromCSV, ArrayFromCSV_Int → DicToArr → DicKeyToArr → DicItemToArr → Dic_addFromArray → 並べ替え、ソート *********************************************************************** <<< 辞書 (Dictionary) >>> *********************************************************************** 辞書 (Dictionary) 辞書 → Dictionary クラス (ハッシュ、Scripting.Dictionary) 辞書は、次のように生成します。 Set dic = CreateObject( "Scripting.Dictionary" ) 参考 → Dictionary クラス (ハッシュ、Scripting.Dictionary) → Dic_addNewObject 無ければ追加する辞書 → Dic_addInArrayItem 配列の辞書 *********************************************************************** <<< Dict >>> *********************************************************************** Dict Function Dict( Elems as array ) as Dictionary 辞書を生成します。 Elems の奇数番目の要素は、キー、偶数番目の要素は、アイテムになります。 キーは文字列のみですが、アイテムはオブジェクトなども指定できます。 生成した辞書のキーは大文字小文字を区別しません。 サンプル Set dic = Dict(Array( "Key1","Item1", "Key2","Item2" )) 上記は下記と同じ処理内容です Set dic = CreateObject( "Scripting.Dictionary" ) dic.Item( "Key1" ) = "Item1" dic.Item( "Key2" ) = "Item2" サンプル Set obj = Dict(Array( "Attr1", 123, "Attr2", "ABC" )) echo obj("Attr1") & obj("Attr2") ソース → vbs_inc_sub.vbs テスト → T_Dic.vbs # T_Dict 関連 → Dic_addFromArray → JSON (JavaScript Object Notation) *********************************************************************** <<< DictionaryClass >>> *********************************************************************** DictionaryClass キーが存在しないときに参照しても、自動的にキーを追加しない辞書。 ソース → vbslib.vbs テスト → T_Dic.vbs T_DictionaryClass 文字列のスペルミス対策 キーが存在しないときに自動的にキーを追加しないため、文字列のスペルミスを防ぐことができます。 ただし、キーとアイテムが異なることが一般的である辞書型では、アイテムを調べなければ 文字列を知ることができないため、開発効率が落ちます。 そこで、キーの先頭が ">" から、アイテムと同じであるようなルールにするとよいでしょう。 Set g = new DictionaryClass g(">Spell") = "Spell" 関連 → Dictionary クラス (VBScript) → LazyDictionaryClass *********************************************************************** <<< DicTable >>> *********************************************************************** DicTable (src) Function DicTable( DataArray as array ) as array of Dictionary テーブルのように使う、辞書の配列を生成します。 データ構造 array Key, Item * Dictionary * in_Item サンプル For Each t In DicTable( Array( _ "Item", "Price", "Number", Empty, _ "Book", 2000, 2, _ "Pen", 100, 12, _ "Eraser", 60, 10 ) ) echo t("Item") &" : "& t("Price") * t("Number") Next 1行目は、辞書のキー(属性名)を並べ、行末は Empty にします。 2行目以降は、辞書のアイテム(値)を並べます。 値には、配列やオブジェクトも指定できます。 上記を実行した結果の出力は、下記のようになります。 Book : 4000 Pen : 1200 Eraser : 600 辞書の内容を見るには、echo o で出力するか、?GetEchoStr( t ) をイミディエイトウィンドウで実行します。 ?GetEchoStr( t ) "Item=Book Price=2000 Number=2" デバッグのために一時的に途中から始めるときは、スキップするデータを For の上に移動し、 次のように Array を使ってダミーの配列を作成すれば無効化できます。 Array _ Array _ "Book", 2000, 2, _ "Pen", 100, 12, _ 0 : Skipped For Each t In DicTable( Array( _ "Item", "Price", "Number", Empty, _ "Eraser", 60, 10 ) ) echo t("Item") &" : "& t("Price") * t("Number") Next 0 : Skipped テスト → T_Dic.vbs T_DicTable 関連 → テストケースの組み合わせ → JoinDicTable → Dict → JSON (JavaScript Object Notation) → Dic_addInArrayItem *********************************************************************** <<< JoinDicTable >>> *********************************************************************** JoinDicTable (src) Function JoinDicTable( DicTable1 as array of Dictionary, KeyField as string, DicTable2 as array of Dictionary ) as array of Dictionary 2つのテーブル(辞書の配列)を、指定のフィールドが一致する行で、結合します。 【引数】 DicTable1 テーブル(辞書の配列) KeyField 比較するフィールド名(辞書のキー) DicTable2 テーブル(辞書の配列) 返り値 結合後のテーブル(辞書の配列) KeyField を持ち、KeyField が Empty ではない行について、SQL の FULL OUTER JOIN 演算を行います。 サンプル table1 = DicTable( Array( _ "Item", "Price", Empty, _ "Book", 2000, _ "Pen", 100, _ "Eraser", 60 ) ) For Each t In JoinDicTable( table1, "Item", Array( _ "Item", "Number", Empty, _ "Book", 2, _ "Pen", 12, _ "Eraser", 10 ) ) echo t("Item") &" : "& t("Price") * t("Number") Next DicTable Item JoinDicTable Item Item 上記の結合をした結果は、下記と同じです。 For Each t In DicTable( Array( _ "Item", "Price", "Number", Empty, _ "Book", 2000, 2, _ "Pen", 100, 12, _ "Eraser", 60, 10 ) ) echo t("Item") &" : "& t("Price") * t("Number") Next 関連 → DicTable → SQL の JOIN の詳細 テスト → T_Dic.vbs # T_DicTable *********************************************************************** <<< GetDicItem >>> *********************************************************************** GetDicItem Sub GetDicItem( in_Dictionary as dictionary, in_Key as string, out_Item as variant ) キーに対応するアイテムを取得します。 【引数】 Dic 辞書 Key 辞書のキー out_Item (出力)辞書のアイテム (オブジェクト または 非オブジェクト) アイテムがオブジェクトでも非オブジェクトでもエラーが発生しないで、アイテムを取得できます。 辞書からアイテムを取得するときの LetSet です。 → LetSetWithBracket 下記のどちらかのコードに相当します。 out_Item = in_Dictionary( in_Key ) Set out_Item = in_Dictionary( in_Key ) 登録されていない Key を指定したときは、out_Item = Empty になります。 このとき、値が Empty の要素を in_Dictionary 引数に指定した辞書に追加しません。 キーが登録されていることと、キーのアイテムが Empty ことの区別をするときは、Dictionary::Exists を使ってください。 サンプル GetDicItem dic, "key1", item '// Set "item" If IsEmpty( item ) Then _ Set item = new ItemClass : item.Name = "key1" ソース → vbslib.vbs テスト → T_Dic.vbs T_GetDicItem 関連 → GetDicItemOrError → LetSetWithBracket → Dictionary::Item → GetDicItemByIndex → GetFirst *********************************************************************** <<< GetDicItemOrError >>> *********************************************************************** GetDicItemOrError Sub GetDicItemOrError( in_Dictionary as Dictionary, in_Key as string, out_Item as variant, in_DictionaryName as string ) 指定したキーが登録されていなければエラーになる GetDicItem です。 【引数】 in_Dictionary 辞書 in_Key 辞書のキー out_Item (出力)辞書のアイテム (オブジェクト または 非オブジェクト) in_DictionaryName 辞書を特定するためにエラーメッセージに表示する辞書の名前 サンプル GetDicItem dic, "Last", item, "検索結果" '// Set "item" エラーメッセージは、下記のようになります。 ソース → vbslib.vbs テスト → T_Dic.vbs T_GetDicItem 関連 → GetDicItem *********************************************************************** <<< DicItem >>> *********************************************************************** DicItem (src) Function DicItem( Dic as Dictionary, Key as string ) as variant 登録されていないときも、新規に登録しない、 Dictionary::Item です。 登録されていないときは、Empty を返します。 Dictionary::Item では dic.Item("key1") DicItem では DicItem( dic, "key1" ) テスト → T_Dic.vbs # T_GetDicItem *********************************************************************** <<< GetDicItemByIndex >>> *********************************************************************** GetDicItemByIndex Sub GetDicItemByIndex( in_Dictionary as dictionary, in_IndexNum as string, out_Item as variant ) 番号で辞書のアイテムを参照します。 【引数】 in_Dictionary 辞書 in_IndexNum キーの番号。 0 以上、キーの数未満 out_Item (出力)辞書のアイテム in_IndexNum 引数に指定する値は、in_Dictionary.Keys で取得できるキーの集合の順番に対応します。 番号が大きすぎるか小さすぎるときは、out_Item = Empty になります。 サンプル GetDicItemByIndex dic, 0, item '// Set "item" ソース → vbslib.vbs テスト → T_Dic.vbs T_GetDicItem 関連 → GetFirst *********************************************************************** <<< DicItemOfItem >>> *********************************************************************** DicItemOfItem (src) Function DicItemOfItem( Dic as Dictionary, Key as string ) as variant 辞書の Item が $ か % で囲んだ変数なら、それを Key とした Item を返します。 辞書の Item が % か で囲んだ変数ではないなら、辞書の Item をそのまま返します。 サンプル Set dic = CreateObject( "Scripting.Dictionary" ) dic.Item( "Key1" ) = "$Key3" dic.Item( "Key2" ) = "%Key3%" dic.Item( "Key3" ) = "Item3" Assert DicItemOfItem( dic, "Key1" ) = "Item3" Assert DicItemOfItem( dic, "Key2" ) = "Item3" Assert DicItemOfItem( dic, "Key3" ) = "Item3" テスト → T_Dic.vbs # T_DicItemOfItem 関連 → LazyDictionaryClass *********************************************************************** <<< Dic_addElem >>> *********************************************************************** Dic_addElem Sub Dic_addElem( ref_Dictionary as dictionary, in_Key as string, in_Item as variant ) 辞書に要素(キーと値)を追加します。 【引数】 ref_Dictionary (入出力) 編集する辞書 in_Key 辞書のキー in_Item 辞書に追加する値 (オブジェクト または 非オブジェクト) in_Item がオブジェクトかどうかで、Set を記述するかどうかを区別する必要がありません。 in_Item が Empty のときは、ref_Dictionary からキーを削除します。 すでに指定したキーが登録されてあったときは、値を変更します。 サンプル Dic_addElem dic, "key1", item ソース → vbslib.vbs テスト → T_Dic.vbs # T_DicAdd 関連 → LetSetWithBracket → Dic_add *********************************************************************** <<< Dic_addElemOrError >>> *********************************************************************** Dic_addElemOrError Sub Dic_addElemOrError( ref_Dictionary as dictionary, in_Key as string, in_Item as variant, in_DictionaryName as string ) 指定したキーがすでに登録されていたらエラーになる Dic_addElem です。 【引数】 ref_Dictionary (入出力) 編集する辞書 in_Key 辞書のキー in_Item 辞書に追加する値 (オブジェクト または 非オブジェクト) in_DictionaryName 辞書を特定するためにエラーメッセージに表示する辞書の名前 サンプル Dic_addElemOrError dic, "key1", item, "検索結果" '// Set "item" エラーメッセージは、下記のようになります。 ソース → vbslib.vbs テスト → T_Dic.vbs # T_DicAdd → Dic_addElem 関連 → Dic_addUniqueKeyItem *********************************************************************** <<< Dic_addUniqueKeyItem >>> *********************************************************************** Dic_addUniqueKeyItem 注意 Dic_addElemOrError の使用を推奨します。 Sub Dic_addUniqueKeyItem( ref_Dictionary as Dictionary, in_Key as string, in_Item as variant ) 辞書の要素を追加します。 すでに同じキーがあるときは、エラーになります。 【引数】 in_out_Dic (入出力) 編集する辞書 Key キー Item 辞書に追加する アイテム ref_Dictionary.Add in_Key, in_Item とほぼ同じですが、違いは下記のとおりです。 ・in_Item が Empty のときは、ref_Dictionary からキーを削除します。 ・すでに同じキーがあるときのエラーメッセージに、そのキーが表示されます。 テスト → T_Dic.vbs # T_DicAdd ソース → vbslib.vbs 関連 → Dic_add *********************************************************************** <<< Dic_addNewObject >>> *********************************************************************** Dic_addNewObject (src) Function Dic_addNewObject( Dic as Dictionary, ClassName as string, ObjectName as string, IsDuplicate as boolean ) as ClassName 指定した名前がキーになければ、その名前を付けたオブジェクトを生成し、辞書に追加します。 【引数】 Dic 辞書。 キーが ObjectName の要素が追加される ClassName クラス名 ObjectName オブジェクトの名前、辞書のキーになります。 IsDuplicate False = すでに辞書にあるときはエラーにする 返り値 Name プロパティが ObjectName のオブジェクト すでに同じ名前のオブジェクトが辞書にあるとき、かつ、IsDuplicate = True なら追加しないで、 辞書に入っていたものを返します。 IsDuplicate = False なら E_AlreadyExist エラーになります。 辞書に無いときは、オブジェクトを生成します。 ClassName に指定したクラスに、Name プロパティ、またはメンバー変数が必要です。 内部で new_X を使っているので、new_ClassA 関数の定義が必要です。 生成したオブジェクトの Name プロパティに、ObjectName 引数の値が設定されます。 サンプル Set objs = CreateObject( "Scripting.Dictionary" ) Set obj = Dic_addNewObject( objs, "ClassA", "ObjectA", True ) Class ClassA Public Name End Class g_Vers("CutPropertyM") = False にすると、Name の代わりに m_Name を使います。 g_Vers("CutPropertyM") = False Class ClassA Public m_Name End Class 関連 → AddNewObject (ArrayClass) テスト → T_Dic.vbs [T_DicAddObj] *********************************************************************** <<< Dic_addFromArray >>> *********************************************************************** Dic_addFromArray Function Dic_addFromArray( in_out_Dic as Dictionary, Keys as array of string, Items as variant ) 配列を使って、辞書に追加します。 【引数】 in_out_Dic (入出力) 加算される辞書、 Empty 可能 Keys キーとなる文字列が入っている配列 Items キーに対応する値、または、その配列 返り値 in_out_Dic と同じ サンプル Set dic = CreateObject( "Scripting.Dictionary" ) Dic_addFromArray dic, Array( "key1", "key2" ), True 上記は下記と同じ内容です。 Set dic = CreateObject( "Scripting.Dictionary" ) dic.Item( "key1" ) = True dic.Item( "key2" ) = True サンプル Set dic = Dic_addFromArray( Empty, Array( "key1", "key2" ), True ) in_out_Dic 引数に Empty を指定した場合、新規に作成した辞書を返します。 サンプル Dic_addFromArray dic, Array( "key1", "key2" ), Array( 1, 2 ) 上記は下記と同じ内容です。 dic.Item( "key1" ) = 1 dic.Item( "key2" ) = 2 ソース → vbs_inc_sub.vbs テスト → T_Dic.vbs # [T_DicArray] *********************************************************************** <<< Dic_addPaths >>> *********************************************************************** Dic_addPaths Sub Dic_addPaths( in_out_Dic as Dictionary, BasePath as string, StepPaths as array of string, Item as variant ) 複数の相対パスをそれぞれのキーとして、辞書の要素を設定します。 【引数】 in_out_Dic (入出力) 編集する辞書、または、 PathDictionaryClass BasePath 相対パスの基準パス StepPaths キーとする相対パスの配列 Item 辞書に追加する アイテム サンプル Set files = CreateObject( "Scripting.Dictionary" ) Dic_addPaths files, "C:\Folder", Array( "a.txt", "b.txt" ), 12 上記のコードは、下記のコードと同じ処理をします。 Set files = CreateObject( "Scripting.Dictionary" ) files( "C:\Folder\a.txt" ) = 12 files( "C:\Folder\b.txt" ) = 12 ソース → vbslib.vbs テスト → T_Dic.vbs # T_DicAdd *********************************************************************** <<< DicKeyToArr >>> *********************************************************************** DicKeyToArr (src) Sub DicKeyToArr( Dic as Dictionary, out_Array as array of string ) Dictionary のキーを配列に変換します。 *********************************************************************** <<< DicItemToArr >>> *********************************************************************** DicItemToArr (src) Sub DicItemToArr( Dic as Dictionary, out_Array as array of variant ) Dictionary のアイテムを配列に変換します。 *********************************************************************** <<< DicKeyToCSV >>> *********************************************************************** DicKeyToCSV (src) Function DicKeyToCSV( Dic as Dictionary ) as string Dictionary のキーを CSV に変換します。 ファイル: vbslib.vbs Dic に要素が1つも無いときは、"" を返します。 サンプル Set dic = CreateObject( "Scripting.Dictionary" ) dic.Item( "Key1" ) = "Item1" dic.Item( "Key2" ) = "Item2" Assert DicKeyToCSV( dic ) = "Key1,Key2" DicKeyToCSV テスト → T_Dic.vbs # [T_DicKeyToCSV] *********************************************************************** <<< DicToArr >>> *********************************************************************** DicToArr (src) Sub DicToArr( Dic as Dictionary, out_Arr as array of DicElem ) Dictionary を配列に変換します。 配列の要素は DicElem 型になります。 【引数】 Dic Dictionary out_Arr (出力) DicElem 型の配列。 Dic の内容を Arr に変換すると、デバッガで内容を見ることができます。 (Visual Studio 2005) サンプル: DicToArr dic, arr '//[out] arr DicElem クラス (src) Class DicElem Public Key Public Item Public Property Get/Let Name '// Key と同じ Public Sub Init( a_Key, a_Item ) End Class 関連 → DicKeyToArr → DicItemToArr → Dic_addFromArray → ShakerSort_fromDicKey *********************************************************************** <<< DicElemArrayKeyToArr >>> *********************************************************************** DicElemArrayKeyToArr Sub DicElemArrayKeyToArr( a_DicElemArray as array of DicElem, out_Array as array of variant ) DicElem クラス の配列から、DicElem::Key の配列を抽出します。 ソース → vbslib.vbs *********************************************************************** <<< IsSameDictionary >>> *********************************************************************** IsSameDictionary Function IsSameDictionary( DicA as dictionary, DicB as dictionary, Option_ as integer ) as boolean 辞書のすべての要素が等しいかどうかを判定します。 【引数】 DicA DicB と比較する辞書 DicB DicA と比較する辞書 Option_ オプション(下記) 返り値 辞書のすべての要素が等しいかどうか 各要素は = で判定します。 Option_ 引数 c.CompareOnlyExistB DicB に存在する要素のみ比較します c.StopIsNotSame デバッグ用。 異なる要素が見つかったら、本関数の 中から Stop 命令を呼び出す c は g_VBS_Lib の返り値です。 ソース → vbslib.vbs テスト → T_Dic.vbs T_IsSameDictionary *********************************************************************** <<< Dic_add >>> *********************************************************************** Dic_add Sub Dic_add( in_out_Dic as Dictionary, PlusDic as Dictionary ) 辞書を加算します。 【引数】 in_out_Dic (入出力) 加算される辞書 PlusDic 加算する内容が入っている辞書 PlusDic にあるキーがすでに in_out_Dic にあるときは、上書きします。 PlusDic のアイテムが Empty のキーは、in_out_Dic から削除されます。 そのキーが in_out_Dic にないときは、何もしませんし、エラーにもなりません。 値が Empty の変数を in_out_Dic に指定すると、内部で辞書を生成します。 サンプル Set dic = Dict(Array( "Key1","Item1", "Key2","Item2" )) Dic_add dic, Dict(Array( "Key2","ITEMS", "Key3","Item3" )) '//[out] dic Assert dic.Count = 3 Assert dic.Item( "Key1" ) = "Item1" Assert dic.Item( "Key2" ) = "ITEMS" Assert dic.Item( "Key3" ) = "Item3" テスト → T_Dic.vbs # T_DicAdd ソース → vbslib.vbs 関連 → Dic_addElem → Dic_sub → 2つの辞書を加算する (LazyDictionaryClass) *********************************************************************** <<< Dic_sub >>> *********************************************************************** Dic_sub (src) Sub Dic_sub( out_Dic as Dictionary, WholeDic as Dictionary, BaseDic as Dictionary, CompareFunc as function, CompareFuncParam as variant ) 辞書を減算します。 【引数】 out_Dic (出力) WholeDic から BaseDic を減算した結果の辞書 WholeDic BaseDic に out_Dic を加算した結果と同一の内容が入った辞書 BaseDic Dic_add で加算する前と同一の内容が入った辞書 CompareFunc 通常 Empty、 比較関数 、Empty = StdCompare CompareFuncParam 通常 Empty、CompareFunc の第3引数 WholeDic - BaseDic = out_Dic の演算をします。 BaseDic に out_Dic を加算(Dic_add)した結果が、WholeDic になるような out_Dic を取得します。 out_Dic に、値が Empty の変数を指定すると、Dic_sub の内部で生成した辞書が取得できます。 同じキーのアイテムを CompareFunc した結果、等価でなければ、out_Dic にコピーされます。 辞書のアイテムがオブジェクトのときは、WholeDic のアイテムと同一のオブジェクトを指します。 BaseDic にあって WholeDic にないキーは、out_Dic にもできますが、アイテムは Empty と なります。 out_Dic に Empty が入った変数を指定したら、内部で新しく辞書を生成します。 out_Dic に 辞書が入った変数を指定したときは、その辞書を空にしてから、その辞書に出力します。 サンプル: Dic_sub dic, whole_dic, base_dic, Empty, Empty '//[out] dic サンプル: Dic_sub dic, _ Dict(Array( "Key1","Item1", "Key2","ITEMS", "Key3","Item3" )), _ Dict(Array( "Key1","Item1", "Key2","Item2", "Key4","Item4" )), _ Empty, Empty '//[out] dic '// dic = Dict(Array( "Key2","ITEMS", "Key3","Item3", "Key4",Empty )) テスト → T_Dic.vbs # T_DicAdd *********************************************************************** <<< Dic_addInArrayItem >>> *********************************************************************** Dic_addInArrayItem Sub Dic_addInArrayItem( ref_Dictionary as dictionary of ArrayClass, _ in_Key as string, in_Item as variant ) 配列をアイテムに持つ辞書に、配列の要素を追加します。 【引数】 ref_Dictionary 配列をアイテムに持つ辞書 in_Key 辞書のキー in_Item 配列に追加するアイテム (オブジェクト または 非オブジェクト) 同じ要素を重複して追加する可能性があるので注意してください。 サンプル Dic_addInArrayItem dic, "key", item データ構造 ref_Dictionary Key, Item * ArrayClass * in_Item 内部の動作 登録されていない辞書のキーを指定したときは、内部で ArrayClass のオブジェクトを新規作成して、 辞書のアイテムにします。 すでに登録されている辞書のキーを指定したときは、そのキーのアイテムである配列の末尾に 追加します。 要素でループする For Each key In files.Keys For Each item In files( key ).Items : Next Next ソース → vbslib.vbs テスト → T_Dic.vbs T_DicArrayItem 関連 → Dic_removeInArrayItem → Dic_addExInArrayItem → ArrayDictionary クラス → DicTable *********************************************************************** <<< Dic_addExInArrayItem >>> *********************************************************************** Dic_addExInArrayItem Sub Dic_addExInArrayItem( ref_Dictionary as dictionary of ArrayClass, _ in_Key as string, in_Item as variant, _ in_CompareFunction as CompareFunction, in_ParameterOfCompareFunction as variant, _ in_Option as integer ) 配列をアイテムに持つ辞書に、重複しないように、配列の要素を追加します。 【引数】 ref_Dictionary 配列をアイテムに持つ辞書 in_Key 辞書のキー in_Item 配列に追加するアイテム、in_CompareFunction の第2引数 in_CompareFunction 比較関数 in_ParameterOfCompareFunction in_CompareFunction の第3引数 in_Option c.ReplaceIfExist または c.IgnoreIfExist またはc.AddAlways in_Option 引数の c は、g_VBS_Lib です。 c.ReplaceIfExist 比較関数が 0 を返す要素がすでにあるときは、置き換えます。 c.IgnoreIfExist 比較関数が 0 を返す要素がすでにあるときは、追加しません。 c.AddAlways 比較関数の結果に関わらず、追加します。 ソース → vbslib.vbs テスト → T_Dic.vbs T_DicArrayItem *********************************************************************** <<< Dic_removeInArrayItem >>> *********************************************************************** Dic_removeInArrayItem Sub Dic_removeInArrayItem( arg_Dictionary as dictionary of ArrayClass, _ in_Key as string, in_Item as variant, _ in_CompareFunction as CompareFunction, in_ParameterOfCompareFunction as variant, _ in_IsErrorIfNotFound as boolean, in_IsMultiRemove as boolean ) 配列をアイテムに持つ辞書から、配列の要素を除外します。 【引数】 arg_Dictionary 配列をアイテムに持つ辞書 in_Key 辞書のキー in_Item 比較対象のアイテム、in_CompareFunction の第2引数 in_CompareFunction 比較関数 in_ParameterOfCompareFunction in_CompareFunction の第3引数 in_IsErrorIfNotFound 1つも一致しなかったらエラーにするかどうか in_IsMultiRemove 複数の要素が一致したら、そのすべて除外するかどうか 参考 Dic_addInArrayItem のデータ構造 辞書の中にある、指定されたキーに対応するアイテムを探し、 そのアイテムである配列の中のすべての要素に対して比較関数をコールバックし、 比較関数が 0を返したら、比較関数に渡した要素を配列から除外します。 配列の要素がすべて除外されたら、該当する辞書のキーやアイテムも除外します。 in_IsErrorIfNotFound に True を指定すると、登録されていない辞書のキーを指定したときや、 比較対象のアイテムと一致する配列要素が1つのなかったときに、E_NotFoundSymbol エラー になります。 サンプル Dic_removeInArrayItem dic, "KeyA", "ItemA", GetRef( "StdCompare" ), Empty, True, False ソース → vbslib.vbs テスト → T_Dic.vbs T_DicArrayItem 関連 → Dic_addInArrayItem *********************************************************************** <<< Dic_searchInArrayItem >>> *********************************************************************** Dic_searchInArrayItem Function Dic_searchInArrayItem( ref_Dictionary as dictionary of ArrayClass, _ in_Key as string, in_Item as variant, _ in_CompareFunction as CompareFunction, in_ParameterOfCompareFunction as variant ) as array of integer 配列をアイテムに持つ辞書から、条件に合う配列番号を列挙します。 【引数】 ref_Dictionary 配列をアイテムに持つ辞書 in_Key 辞書のキー in_Item 比較対象のアイテム、in_CompareFunction の第2引数 in_CompareFunction 比較関数 in_ParameterOfCompareFunction in_CompareFunction の第3引数 返り値 配列番号の配列 サンプル indexes = Dic_searchInArrayItem( dic, "KeyA", "ItemA", GetRef( "StdCompare" ), Empty ) ソース → vbslib.vbs テスト → T_Dic.vbs T_DicArrayItem *********************************************************************** <<< Dic_getCountInArrayItem >>> *********************************************************************** Dic_getCountInArrayItem Function Dic_getCountInArrayItem( ref_Dictionary as dictionary of ArrayClass ) as integer 配列をアイテムに持つ辞書に入っているすべての要素の数を返します。 【引数】 ref_Dictionary 配列をアイテムに持つ辞書 返り値 要素の数 ソース → vbslib.vbs テスト → T_Dic.vbs T_DicArrayItem *********************************************************************** <<< GetDicItemAsArrayClass >>> *********************************************************************** GetDicItemAsArrayClass Function GetDicItemAsArrayClass( Dic as dictionary, Key as string ) as ArrayClass 辞書のアイテムにある ArrayClass で参照します。 アイテムがなければ ArrayClass を作成します。 【引数】 Desc 辞書 Key 辞書のキー 返り値 辞書の要素である ArrayClass のオブジェクト 指定したキーに対応するアイテムがないときは、新規作成した ArrayClass のオブジェクトを、 キーに対応するアイテムに追加します。 サンプル Dim dic, arr Set dic = CreateObject( "Scripting.Dictionary" ) Set arr = GetDicItemAsArrayClass( dic, "key1" ) dic, "key1" ソース → vbslib.vbs テスト → T_Dic.vbs # T_GetDicItem *********************************************************************** <<< Dic_searchParent >>> *********************************************************************** Dic_searchParent Function Dic_searchParent( Dictionay as dictionary, BasePath as string, Path as string ) as string パスがキーに入っている辞書の中から、指定したパスの親フォルダーのパスを検索します。 【引数】 Dictionay 検索対象の辞書 BasePath Dictionay 引数のキーがフル パスのときの基準(フル パス)、Empty 可 Path 検索キーとなるファイル、または、フォルダーのパス、または、Empty 返り値 親フォルダーのパス、または、Empty = 見つからない FileSystemObject::GetParentFolderName に近い処理をします。 BasePath 引数は、Dictionay 引数のキーがフル パスのとき、かつ、Path が相対パスのときに必要です。 それ以外のときは、Empty を指定できます。 サンプル Set dic = CreateObject( "Scripting.Dictionary" ) dic( "123" ) = 0 dic( "123\456" ) = 0 Assert Dic_searchParent( dic, "C:\Folder", "123\456\a.txt" ) = "123\456" Assert Dic_searchParent( dic, "C:\Folder", "123\4567\a.txt" ) = "123" Assert IsEmpty( Dic_searchParent( dic, "C:\Folder", "123" ) ) サンプル サブ フォルダーの Item を、親フォルダーの Item を参考に作成します Function GetOrAddIfNot( Path ) If dic.Exists( Path ) Then Set GetOrAddIfNot = dic( Path ) Else Set parent_item = Dic_searchParent( dic, "C:\Folder", Path ) If IsEmpty( parent_item ) Then Error Set sub_item = NewSubFromParent( parent_item, Path ) Set dic( Path ) = sub_item Set GetOrAddIfNot = sub_item End Sub ソース → vbslib.vbs テスト → T_Wildcard.vbs T_PathDictionary_SearchParent 関連 → PathDictionaryClass の SearchParent → SearchParent *********************************************************************** <<< Dic_searchChildren >>> *********************************************************************** Dic_searchChildren Sub Dic_searchChildren( Dictionay as dictionary, BasePath as string, Path as string, out_PathArray as array of string, Option_ as Empty ) パスがキーに入っている辞書の中から、指定したパスの子ノードのパスを検索します。 【引数】 Dictionay 検索対象の辞書 BasePath Dictionay 引数のキーがフル パスのときの基準(フル パス)、Empty 可 Path 検索キーとなるファイル・フォルダーのパス、または、Empty out_PathArray (出力) 子のフォルダーまたはファイルのパスの配列 Option_ Empty を指定してください フォルダーとサブ フォルダーに入っているファイルを一覧することに近い処理をします。 BasePath 引数は、Dictionay 引数のキーがフル パスのとき、かつ、Path が相対パスのときに必要です。 それ以外のときは、Empty を指定できます。 out_PathArray 引数の配列要素がフル パスか相対パスかは、Dictionay 引数のキーがフル パスか 相対パスかによります。 サンプル Set dic = CreateObject( "Scripting.Dictionary" ) dic( "123\456" ) = 0 dic( "123\456\File.txt" ) = 0 Dic_searchChildren dic, "C:\Folder", "123", an_array, Empty '//(out)an_array Assert IsSameArray( an_array, Array( "123\456", "123\456\File.txt" ) ) Dic_searchChildren dic, "C:\Folder", "123\456", an_array, Empty '//(out)an_array Assert IsSameArray( an_array, Array( "123\456\File.txt" ) ) Dic_searchChildren dic, "C:\Folder", "12", an_array, Empty '//(out)an_array Assert IsSameArray( an_array, Array( ) ) ソース → vbslib.vbs テスト → T_Wildcard.vbs T_PathDictionary_SearchChildren *********************************************************************** <<< QuickSortDicByKey >>> *********************************************************************** QuickSortDicByKey Sub QuickSortDicByKey( in_out_Dictionary as dictionary ) 辞書に入っているデータをクイック ソートします。 辞書のキーでソートします。 【引数】 in_out_Dictionary ソートする辞書 辞書の Keys の順番が変わります。 辞書の Item はオブジェクト(Set で代入するもの)を指定してください。 比較関数 PathCompare を使ってソート(並べ替え)します。 ソース → vbslib.vbs 関連 → QuickSortDicByKeyForNotObject → 並べ替え、ソート *********************************************************************** <<< QuickSortDicByKeyForNotObject >>> *********************************************************************** QuickSortDicByKeyForNotObject Sub QuickSortDicByKeyForNotObject( in_out_Dictionary as dictionary ) 辞書に入っているデータをクイック ソートします。 辞書のキーでソートします。 【引数】 in_out_Dictionary ソートする辞書 辞書の Keys の順番が変わります。 辞書の Item はオブジェクト以外(Set で代入しないもの)を指定してください。 比較関数 PathCompare を使ってソートします。 ソース → vbslib.vbs テスト → GetIdentifiableFileNames のテスト *********************************************************************** <<< DicItemToNameOnlyClassItem >>> *********************************************************************** DicItemToNameOnlyClassItem Sub DicItemToNameOnlyClassItem( ref_Dictionary ) オブジェクトではない辞書のアイテムを、NameOnlyClass のオブジェクトに変換します。 【引数】 ref_Dictionary アイテムを変換する辞書 ソートできる辞書にします。 NameOnlyClass の Delegate メンバーは Empty になります。 サンプル Set dic = CreateObject( "Scripting.Dictionary" ) DicItemToNameOnlyClassItem dic ソース → vbslib.vbs テスト → GetIdentifiableFileNames のテスト 関連 → ArrayToNameOnlyClassArray 配列版 *********************************************************************** <<< NameOnlyClassItemToDicItem >>> *********************************************************************** NameOnlyClassItemToDicItem Sub NameOnlyClassItemToDicItem( ref_Dictionary ) NameOnlyClass のオブジェクトが入っている辞書を、Name プロパティの値の辞書に変換します。 【引数】 ref_Dictionary アイテムを変換する辞書 ソートできる配列から戻します。 サンプル Set dic = CreateObject( "Scripting.Dictionary" ) NameOnlyClassItemToDicItem dic ソース → vbslib.vbs テスト → GetIdentifiableFileNames のテスト 関連 → NameOnlyClassArrayToArray 配列版 *********************************************************************** <<< QuickSort_fromDic >>> *********************************************************************** QuickSort_fromDic (src) Sub QuickSort_fromDic( Dic as dictionary, out_Arr as array of object, CompareFunc as function, Param as variant ) 辞書に入っているデータ(Dictionary::Item)をクイックソートします。 比較関数を指定します。 【引数】 Dic ソートするデータが入った辞書。(辞書はソートされません) out_Arr (出力) ソートした結果の配列。配列の要素はオブジェクト CompareFunc 比較関数 Param compare_func の第3引数 サンプル QuickSort_fromDic dic, arr, GetRef("StdCompare"), Empty '//[out]arr 関連 → DicToArr → QuickSort *********************************************************************** <<< QuickSort_fromDicKey >>> *********************************************************************** QuickSort_fromDicKey Sub QuickSort_fromDicKey( in_out_Dictionary as dictionary, out_SortedKeysArray as array of string, in_Empty as Empty ) 辞書に入っているデータをクイック ソートします。 辞書のキーでソートします。 【引数】 in_out_Dictionary ソートする前のキーが入った辞書 out_SortedKeysArray (出力) ソートした後のキーが入った配列。配列の要素は DicElem オブジェクト in_Empty Empty を指定してください ソートした結果は、out_SortedKeysArray 引数に出力されます。 比較関数 PathCompare を使ってソートします。 サンプル Set dic = CreateObject( "Scripting.Dictionary" ) QuickSort_fromDicKey dic, sorted_items, Empty '//[out] sorted_items For Each item In sorted_items echo item.Key +" : "+ item.Item Next ソース → vbslib.vbs 関連 → DicElemArrayKeyToArr *********************************************************************** <<< ShakerSortDicByKey >>> *********************************************************************** ShakerSortDicByKey Sub ShakerSortDicByKey( Dic as Dictionary ) 辞書に入っているデータをシェーカーソートします。 辞書のキーでソートします。 【引数】 Dic ソートする辞書 辞書の Item はオブジェクト(Set で代入するもの)を指定してください。 比較関数 PathCompare を使ってソート(並べ替え)します。 ソース → vbslib.vbs テスト → T_ShakerSort.vbs T_ShakerSortDicByKey *********************************************************************** <<< ShakerSortDicByKeyCompare >>> *********************************************************************** ShakerSortDicByKeyCompare Sub ShakerSortDicByKeyCompare( Dic as Dictionary, CompareFunc as function, CompareFuncParam as variant ) 辞書に入っているデータをシェーカーソートします。 辞書のキーでソートします。 【引数】 Dic ソートする辞書 CompareFunc 比較関数 CompareFuncParam CompareFunc の第3引数 辞書の Item はオブジェクト(Set で代入するもの)を指定してください。 サンプル ShakerSortDicByKeyCompare dic, GetRef( "NumStringCompare" ), Empty ソース → vbslib.vbs テスト → T_ShakerSort.vbs T_ShakerSortDicByKeyCompare *********************************************************************** <<< ShakerSort_fromDic >>> *********************************************************************** ShakerSort_fromDic (src) Sub ShakerSort_fromDic( dic as Dictionary, out_arr as object array, sign as integer, compare_func as function, param as variant ) 辞書に入っているデータ(Dictionary::Item)をシェーカーソートします。 【引数】 dic ソートするデータが入った辞書。(辞書はソートされません) out_arr ソートした結果の配列。配列の要素はオブジェクト。 sign 正の数=dic の順がベース、負の数=dicの逆順がベース(*1) compare_func 比較関数 param compare_func の第3引数 (*1) sign 引数の説明 dic.Item の For ループの順番どおりの配列を作成してからシェーカーソートを開始 するか、逆順の配列を作成してからシェーカーソートを開始するかを指定します。 sign < 0 のときでも、compare_func は、sign > 0 のときの compare_func の返り値の マイナスを返すようにしてください。 参考 → ShakerSort *********************************************************************** <<< ShakerSort_fromDicKey >>> *********************************************************************** ShakerSort_fromDicKey (src) Sub ShakerSort_fromDicKey( Dic as Dictionary, out_Array as array of DicElem, Option_ as Empty ) 辞書に入っているデータをシェーカーソートします。 辞書のキーでソートします。 【引数】 Dic ソートするデータが入った辞書。(辞書はソートされません) out_Array ソートした結果の配列。配列の要素は DicElem オブジェクト Option_ Empty を指定してください 比較関数 PathCompare を使ってソートします。 サンプル Set dic = CreateObject( "Scripting.Dictionary" ) ShakerSort_fromDicKey dic, sorted_items, Empty '//[out] sorted_items For Each item In sorted_items echo item.Key +" : "+ item.Item Next dic, sorted_items *********************************************************************** <<< ReverseDictionary >>> *********************************************************************** ReverseDictionary Sub ReverseDictionary( ref_Dictionary as Dictionary ) 辞書に入っているデータの並びを逆にします。 【引数】 ref_Dictionary 並びを逆にする辞書 ソース → vbslib.vbs テスト → T_ShakerSort.vbs T_ReverseDictionary *********************************************************************** <<< 関連 >>> *********************************************************************** 関連 → ArrayDictionary クラス *********************************************************************** <<< ツリー構造(木構造)、グラフ理論 >>> *********************************************************************** ツリー構造(木構造)、グラフ理論 *********************************************************************** <<< GraphVertexClass >>> *********************************************************************** GraphVertexClass GraphVertexClass の配列は、内部構造が隣接リストである、グラフ理論のグラフです。 ツリー構造に使うこともできます。 (ツリー構造はグラフの特殊形です) グラフは、任意の数の頂点(ノード、Vertex)と、任意の数の辺(Edge)から構成されます。 1つの GraphVertexClass は、頂点に相当し、AdjacentIndexes メンバー変数は、辺に相当します。 辺は、GraphVertexClass の配列の番号で表し、無向グラフでは必ず双方向に設定されます。 参考 → グラフ (グラフ理論) サンプル 1 4 0 3 2 上の図の番号は、グラフ全体の頂点配列(GraphVertexClass の配列)の配列番号です。 配列番号 2 の GraphVertexClass の AdjacentIndexes メンバー変数は、( 0, 1, 4 ) です。 配列番号 4 の GraphVertexClass の AdjacentIndexes メンバー変数は、( 2, 3 ) です。 GraphVertexClass の配列 = グラフ GraphVertexClass Item GraphVertexClass Item Edge Edge Edge GraphVertexClass Item GraphVertexClass Item Edge GraphVertexClass Item … ライブラリが定義するクラス … ユーザーが定義&生成するクラス メンバー変数 .Item ユーザーだけが設定&参照する、頂点のオブジェクト .Index 頂点生成時に自動的に設定される、頂点番号。 グラフ全体の配列番号と同じ値 .AdjacentIndexes 関数の内部で設定され、参照可能な、隣接頂点のグラフ全体の配列番号の配列 .Edges 関数の内部で設定され、参照も可能な、辺のオブジェクトの配列 .ParentIndex ユーザーも設定&参照できる、親頂点(探索元)の配列番号 関数 CreateGraphVertex グラフの頂点を生成して、グラフに追加します。 SetNDEdgeInGraph グラフの辺にあたる変数に値を設定します。(無向グラフ) SetEdgeInGraph グラフの辺にあたる変数に値を設定します。(有向グラフ) GetNDEdgeInGraph グラフの辺にあたる変数の値を返します。(無向グラフ) GetEdgeInGraph グラフの辺にあたる変数の値を返します。(有向グラフ) GetDirectionIndex 辺の変数の中にある頂点に対応する配列番号を返します。 BreadthFirstSearch 幅優先探索を行います。 ResetSearchDataOfGraphVertex 前回探索した結果を格納する内部変数をリセットします。 ソース → vbslib.vbs テスト → T_Tree.vbs T_GraphVertexClass T_BreadthFirstSearch *********************************************************************** <<< CreateGraphVertex >>> *********************************************************************** CreateGraphVertex Function CreateGraphVertex( in_out_Graph as array of GraphVertexClass ) as GraphVertexClass グラフの頂点を生成して、グラフに追加します。 【引数】 in_out_Graph 生成した頂点を追加するグラフ 返り値 生成した頂点 → GraphVertexClass 生成された頂点のオブジェクトは、in_out_Graph 配列の最後に追加されます。 返り値の GraphVertexClass::Index 変数には、その配列番号が代入されます。 返り値の GraphVertexClass::Item 変数には、Empty が代入されます。 サンプル graph = Array( ) Set vertex1 = CreateGraphVertex( graph ) Set vertex = new UserDefinedVertexClass Set vertex1.Item = vertex Assert graph( vertex1.Index ) is vertex1 CreateGraphVertex ソース → vbslib.vbs テスト → T_Tree.vbs T_GraphVertexClass *********************************************************************** <<< SetNDEdgeInGraph >>> *********************************************************************** SetNDEdgeInGraph Sub SetNDEdgeInGraph( in_out_Graph as array of GraphVertexClass, in_BaseIndex as integer, in_TargetIndex as integer, in_EdgeObject as variant ) グラフの辺にあたる変数に値を設定します。(無向グラフ) 【引数】 in_out_Graph 設定対象のグラフ in_BaseIndex 辺の頂点番号。 in_TargetIndex 辺のもう片方の頂点番号 in_EdgeObject 辺にあたる変数に格納する値やオブジェクト ND は、無向グラフの略語です。 双方向に頂点の参照を設定します。 in_BaseIndex と in_TargetIndex には、CreateGraphVertex で登録された頂点番号を指定してください。 in_EdgeObject には、数値、文字列、Empty なども指定可能です。 1つの辺に、有向グラフと無向グラフを共存することはできません。 異なる辺ならできます。 サンプル graph = Array( ) Set vertex1 = CreateGraphVertex( graph ) Set vertex1.Item = new UserDefinedVertexClass Set vertex2 = CreateGraphVertex( graph ) Set vertex2.Item = new UserDefinedVertexClass Set new_edge = new UserDefinedEdgeClass SetNDEdgeInGraph graph, vertex1.Index, vertex2.Index, new_edge Set edge = GetNDEdgeInGraph( graph, vertex1.Index, vertex2.Index, Empty ) Assert edge is new_edge SetNDEdgeInGraph GetNDEdgeInGraph ソース → vbslib.vbs テスト → T_Tree.vbs T_GraphVertexClass 関連 → SetEdgeInGraph 有向グラフ版 *********************************************************************** <<< SetEdgeInGraph >>> *********************************************************************** SetEdgeInGraph Sub SetEdgeInGraph( in_out_Graph as array of GraphVertexClass, in_BaseIndex as integer, in_TargetIndex as integer, in_EdgeObject as variant ) グラフの辺にあたる変数に値を設定します。(有向グラフ) 【引数】 in_out_Graph 設定対象のグラフ in_BaseIndex 辺の元の頂点番号 in_TargetIndex 辺の先の頂点番号 in_EdgeObject 辺にあたる変数に格納する値やオブジェクト 片方向の頂点の参照を設定します。 逆方向には辺が存在しないようにできます。 in_BaseIndex と in_TargetIndex には、CreateGraphVertex で登録された頂点番号を指定してください。 in_EdgeObject には、数値、文字列、Empty なども指定可能です。 1つの辺に、有向グラフと無向グラフを共存することはできません。 異なる辺ならできます。 サンプル graph = Array( ) Set vertex1 = CreateGraphVertex( graph ) Set vertex1.Item = new UserDefinedVertexClass Set vertex2 = CreateGraphVertex( graph ) Set vertex2.Item = new UserDefinedVertexClass Set new_edge = new UserDefinedEdgeClass SetEdgeInGraph graph, vertex1.Index, vertex2.Index, new_edge Set edge = GetEdgeInGraph( graph, vertex1.Index, vertex2.Index, Empty ) Assert edge is new_edge SetEdgeInGraph GetEdgeInGraph ソース → vbslib.vbs テスト → T_Tree.vbs T_GraphVertexClass 関連 → SetNDEdgeInGraph 無向グラフ版 *********************************************************************** <<< GetNDEdgeInGraph >>> *********************************************************************** GetNDEdgeInGraph Function GetNDEdgeInGraph( in_out_Graph as array of GraphVertexClass, in_BaseIndex as integer, in_TargetIndex as integer, in_EdgeIfNotFound as variant ) as variant グラフの辺にあたる変数に格納されている値を返します。(無向グラフ) 【引数】 in_out_Graph 対象のグラフ in_BaseIndex 辺の頂点番号 in_TargetIndex 辺のもう片方の頂点番号 in_EdgeIfNotFound 辺が見つからなかったときの返り値 返り値 辺にあたる変数に格納されている値やオブジェクト ND は、無向グラフの略語です。 in_BaseIndex と in_TargetIndex を入れ替えても同じ変数を参照します。 1つの辺に、有向グラフと無向グラフを共存することはできません。 異なる辺ならできます。 in_BaseIndex と in_TargetIndex が in_out_Graph の配列番号の範囲外であったときは、エラーになります。 in_EdgeIfNotFound に指定する値を、辺がオブジェクトなら Empty、オブジェクトでないなら Nothing に すると、返り値を格納するときに Set か Let (Setなし) の違いによって、エラーを発生させることが できます。 サンプル Set edge = GetNDEdgeInGraph( graph, vertex1.Index, vertex2.Index, Empty ) ソース → vbslib.vbs テスト → T_Tree.vbs T_GraphVertexClass 関連 → GetEdgeInGraph 有向グラフ版 *********************************************************************** <<< GetEdgeInGraph >>> *********************************************************************** GetEdgeInGraph Function GetEdgeInGraph( in_out_Graph as array of GraphVertexClass, in_BaseIndex as integer, in_TargetIndex as integer, in_EdgeIfNotFound as variant ) as variant グラフの辺にあたる変数に格納されている値を返します。(有向グラフ) 【引数】 in_out_Graph 対象のグラフ in_BaseIndex 辺の元の頂点番号 in_TargetIndex 辺の先の頂点番号 in_EdgeIfNotFound 辺が見つからなかったときの返り値 返り値 辺にあたる変数に格納されている値やオブジェクト 1つの辺に、有向グラフと無向グラフを共存することはできません。 異なる辺ならできます。 辺が存在しなければ、エラーになります。 逆方向には辺が存在しないことがあります。 in_BaseIndex と in_TargetIndex が in_out_Graph の配列番号の範囲外であったときは、エラーになります。 in_EdgeIfNotFound に指定する値を、辺がオブジェクトなら Empty、オブジェクトでないなら Nothing に すると、返り値を格納するときに Set か Let (Setなし) の違いによって、エラーを発生させることが できます。 サンプル Set edge = GetEdgeInGraph( graph, vertex1.Index, vertex2.Index, Empty ) ソース → vbslib.vbs テスト → T_Tree.vbs T_GraphVertexClass 関連 → GetNDEdgeInGraph 無向グラフ版 *********************************************************************** <<< GetDirectionIndex >>> *********************************************************************** GetDirectionIndex Function GetDirectionIndex( in_TargetVertexIndex as intege, in_OppositeVertexIndex as intege ) 辺の変数の中にある頂点に対応する配列の配列番号 0 か 1 のどちらかを返します。 【引数】 in_TargetVertexIndex 対象の頂点に対応するグラフ全体の頂点配列番号 in_OppositeVertexIndex 反対側の頂点に対応するグラフ全体の配列番号 返り値 辺の変数の中にある頂点に対応する配列の配列番号 0 か 1 辺ごとに異なる頂点のデータは、辺の中にある要素数2の配列に格納しますが、 どちらの頂点がどちらの配列要素に対応するかを、本関数で調べます。 グラフの配列番号が小さいほうを配列番号0、大きいほうを配列番号1としています。 これは、有向 グラフでも無向グラフでも同じです。 辺ごとに異なることがない頂点のデータは、頂点のクラスのメンバーにします。 サンプル 4 1 0 12:00発 3 番号は、グラフ全体の頂点配列番号 2 Class TrainLineClass Public TrainTime '// 発車時刻 as array(0..1) of Date Private Sub Class_Initialize() Me.TrainTime = Array( Empty, Empty ) End Sub End Class Set edge = new TranLineClass edge.TrainTime( GetDirectionIndex( 2, 4 ) ) = CDate( "12:00" ) SetNDEdgeInGraph graph, 2, 4, edge Set edge = GetNDEdgeInGraph( graph, 4, 2, Empty ) Assert edge.TrainTime( GetDirectionIndex( 2, 4 ) ) = CDate( "12:00" ) GetDirectionIndex SetNDEdgeInGraph GetNDEdgeInGraph GetDirectionIndex ソース → vbslib.vbs テスト → T_Tree.vbs T_GraphVertexClass *********************************************************************** <<< BreadthFirstSearch >>> *********************************************************************** BreadthFirstSearch << GraphVertexClass Sub BreadthFirstSearch( in_Array as array of GraphVertexClass, in_FirstIndex as integer, out_QueuedNodes as array of integer, in_CompareFunction as function, ref_ParameterOfCompareFunction as variant, in_Option as Empty or boolean ) 幅優先探索(最短経路探索)を行います。 頂点ごとにコールバック関数を呼び出します。 【引数】 in_Array 頂点の配列 → GraphVertexClass in_FirstIndex 開始頂点の(in_Array の)配列番号 out_QueuedNodes (出力) 探索した/探索予定の頂点の配列番号の配列 in_CompareFunction 頂点を探索するときにコールバックされる 比較関数 か Empty ref_ParameterOfCompareFunction in_CompareFunction の第3引数 in_Option Empty または g_VBS_Lib.NotResetFoundFlag in_Array 引数に、GraphVertexClass の Item, AdjacentIndexes メンバー変数が設定済みのオブジェクトの 配列を指定します。 コールバック関数 in_CompareFunction の第1引数と第2引数には、in_Array 配列の要素である GraphVertexClass 型のオブジェクトが渡ります。 第2引数より第1引数のほうが、探索開始頂点に 近いです。 ただし、最初のコールバックでは、第1引数は Empty、第2引数は探索開始頂点です。 コールバック関数で 0 を返すと、探索を途中で終了します。 見つかった頂点を出力するときは、コールバック関数の第3引数経由で出力してください。 第3引数は、 ref_ParameterOfCompareFunction 引数の参照なので、出力できます。 コールバック関数 in_CompareFunction で 0 を返すと、探索を終了します。 out_QueuedNodes 引数に指定した変数には、コールバック関数が呼び出されたときの対象頂点と、 それに隣接する頂点が格納されます。 重複する頂点は格納されません。 対象頂点と隣接する 頂点とは、たとえば、下記の頂点 2 についてコールバックされたとき、0, 1, 4 が隣接する頂点です。 0, 2, 1 と探索して終了した場合、out_QueuedNodes 引数に指定した変数には、0, 2, 1, 4 が格納 されますが、探索済みの頂点は、0, 2, 1 のみです(判別方法は後述)。 1 4 0 out_QueuedNodes = Array( 0, 2, 1, 4 ) 3 2 コールバック関数が呼び出されると、コールバック関数が呼び出されたときの対象頂点の GraphVertexClass ::ParentIndex が設定されます。 この変数が Empty でないかどうかで、探索済みか どうかを判定できます。 開始頂点の ParentIndex は Null が設定されます。 上記のグラフで、0, 2, 1 と探索して終了した場合、各頂点の ParentIndex は、次のようになります。 Vertex(0).ParentIndex = Null Vertex(1).ParentIndex = 2 Vertex(2).ParentIndex = 0 Vertex(3).ParentIndex = Empty Vertex(4).ParentIndex = Empty 相互参照しているとき、すでに探索済みの頂点は、探索しません。 エラーにもなりません。 in_Option 引数に g_VBS_Lib.NotResetFoundFlag を指定すると、内部の先頭で ResetSearchDataOfGraphVertex を呼び出さなくなります。 参考 → 幅優先探索 (グラフ) サンプル an_array(0).Item 0 ReDim an_array( 5 ) For Each t In DicTable( Array( _ "Index", "AdjacentIndexes", "ParentIndex", Empty, _ 0, Array( 1, 3, 2 ), Null, _ 1, Array( 5, 4 ), 0, _ 2, Array( ), 0, _ 3, Array( ), 0, _ 4, Array( ), 1, _ 5, Array( ), 1 ) ) i = t("Index") Set an_array(i) = new GraphVertexClass Set an_array(i).Item = Nothing an_array(i).AdjacentIndexes = t("AdjacentIndexes") Next BreadthFirstSearch an_array, 0, queued, Empty, Empty, Empty '//(out) queued Assert IsSameArray( queued, Array( 0, 1, 3, 2, 5, 4 ) ) an_array(1).Item 1 an_array(5).Item 4 an_array(4).Item 5 an_array(3).Item 2 an_array(2).Item 3 赤色の数字は、コールバック される順番を表します。 BreadthFirstSearch ソース → vbslib.vbs テスト → T_Tree.vbs T_BreadthFirstSearch 関連 → 幅優先探索 (グラフ) *********************************************************************** <<< DepthFirstSearch >>> *********************************************************************** DepthFirstSearch << GraphVertexClass Sub DepthFirstSearch( in_Array as array of GraphVertexClass, in_FirstIndex as integer, in_CompareFunction as function, ref_ParameterOfCompareFunction as variant, in_Option as Empty or boolean ) 深さ優先探索を行います。 頂点ごとにコールバック関数を呼び出します。 【引数】 in_Array 頂点の配列 → GraphVertexClass in_FirstIndex 開始頂点の(in_Array の)配列番号 in_CompareFunction 頂点を探索するときにコールバックされる 比較関数 か Empty ref_ParameterOfCompareFunction in_CompareFunction の第3引数 in_Option Empty または g_VBS_Lib.NotResetFoundFlag in_Array 引数に、GraphVertexClass の Item, AdjacentIndexes メンバー変数が設定済みのオブジェクトの 配列を指定します。 コールバック関数 in_CompareFunction の第1引数と第2引数には、in_Array 配列の要素である GraphVertexClass 型のオブジェクトが渡ります。 第2引数より第1引数のほうが、探索開始頂点に 近いです。 ただし、最初のコールバックでは、第1引数は Empty、第2引数は探索開始頂点です。 コールバック関数で 0 を返すと、探索を途中で終了します。 見つかった頂点を出力するときは、コールバック関数の第3引数経由で出力してください。 第3引数は、 ref_ParameterOfCompareFunction 引数の参照なので、出力できます。 コールバック関数 in_CompareFunction で 0 を返すと、探索を終了します。 コールバック関数が呼び出されると、コールバック関数が呼び出されたときの対象頂点の GraphVertexClass ::ParentIndex が設定されます。 この変数が Empty でないかどうかで、探索済みか どうかを判定できます。 開始頂点の ParentIndex は Null が設定されます。 相互参照しているとき、すでに探索済みの頂点は、探索しません。 エラーにもなりません。 in_Option 引数に g_VBS_Lib.NotResetFoundFlag を指定すると、内部の先頭で ResetSearchDataOfGraphVertex を呼び出さなくなります。 サンプル an_array(0).Item 0 ReDim an_array( 5 ) For Each t In DicTable( Array( _ "Index", "AdjacentIndexes", "ParentIndex", Empty, _ 0, Array( 1, 3, 2 ), Null, _ 1, Array( 5, 4 ), 0, _ 2, Array( ), 0, _ 3, Array( ), 0, _ 4, Array( ), 1, _ 5, Array( ), 1 ) ) i = t("Index") Set an_array(i) = new GraphVertexClass Set an_array(i).Item = Nothing an_array(i).AdjacentIndexes = t("AdjacentIndexes") Next DepthFirstSearch an_array, 0, Empty, Empty, Empty Assert IsSameArray( queued, Array( 0, 1, 5, 4, 3, 2 ) ) an_array(1).Item 1 an_array(4).Item 2 an_array(5).Item 3 an_array(2).Item 4 an_array(3).Item 5 赤色の数字は、コールバック される順番を表します。 DepthFirstSearch 参考 → 深さ優先探索 (グラフ) ソース → vbslib.vbs テスト → T_Tree.vbs T_DepthFirstSearch *********************************************************************** <<< SearchSubGraphs >>> *********************************************************************** SearchSubGraphs << GraphVertexClass Function SearchSubGraphs( in_Array as array of GraphVertexClass, in_Empty as Empty ) as array of array of integer すべての部分グラフと、辺がない頂点を列挙します。 【引数】 in_Array 頂点の配列 → GraphVertexClass in_Empty Empty を指定してください 返り値 すべての部分グラフと辺がない頂点を構成する頂点番号の配列の配列 サンプル 2 6 1 5 0 3 4 9 sub_graphs = SearchSubGraphs( a_graph, Empty ) sub_graphs(0), Array( 0, 2, 4, 6 ) sub_graphs(1), Array( 1, 3, 5, 9 ) sub_graphs(2), Array( 7 ) sub_graphs(3), Array( 8 ) ソース → vbslib.vbs テスト → T_Tree.vbs T_SearchSubGraphs *********************************************************************** <<< GetDistanceInGraph >>> *********************************************************************** GetDistanceInGraph Function GetDistanceInGraph( in_Array as array of GraphVertexClass, in_Index as integer ) as integer 検索を開始した頂点から、指定した頂点までの間にある辺の数を返します。 【引数】 in_Array 頂点の配列 → GraphVertexClass in_Index 頂点 返り値 辺の数 ソース → vbslib.vbs テスト → T_Tree.vbs T_DepthFirstSearch *********************************************************************** <<< ResetSearchDataOfGraphVertex >>> *********************************************************************** ResetSearchDataOfGraphVertex Sub ResetSearchDataOfGraphVertex( in_out_Graph as array of GraphVertexClass ) 前回探索した結果を格納する内部変数をリセットします。 【引数】 in_out_Graph 操作対象のグラフ 探索を行う関数の内部から呼ばれます。 GraphVertexClass ::ParentIndex を Empty に設定します。 ソース → vbslib.vbs テスト → T_Tree.vbs T_BreadthFirstSearch *********************************************************************** <<< 未対応 >>> *********************************************************************** 未対応 *********************************************************************** <<< RemoveNDEdgeInGraph >>> *********************************************************************** RemoveNDEdgeInGraph Sub RemoveNDEdgeInGraph( in_out_Graph as array of GraphVertexClass, in_BaseIndex as integer, in_TargetIndex as integer ) 未対応。 AdjacentIndexes の調整ができていません。 グラフの辺にあたる変数を削除します。(無向グラフ) 【引数】 in_out_Graph 対象のグラフ in_BaseIndex 辺の頂点番号 in_TargetIndex 辺のもう片方の頂点番号 ND は、無向グラフの略語です。 1つの辺に、有向グラフと無向グラフを共存することはできません。 異なる辺ならできます。 ソース → vbslib.vbs 関連 → RemoveEdgeInGraph 有向グラフ版 *********************************************************************** <<< RemoveEdgeInGraph >>> *********************************************************************** RemoveEdgeInGraph Sub RemoveEdgeInGraph( in_out_Graph as array of GraphVertexClass, in_BaseIndex as integer, in_TargetIndex as integer ) 未対応。 AdjacentIndexes の調整ができていません。 グラフの辺にあたる変数を削除します。(有向グラフ) 【引数】 in_out_Graph 対象のグラフ in_BaseIndex 辺の元の頂点番号 in_TargetIndex 辺の先の頂点番号 1つの辺に、有向グラフと無向グラフを共存することはできません。 異なる辺ならできます。 ソース → vbslib.vbs 関連 → RemoveNDEdgeInGraph 無向グラフ版 *********************************************************************** <<< TreeA_Class >>> *********************************************************************** TreeA_Class ツリー構造を持ったコレクションです。 TreeA_NodeClass の Item メンバーに、ユーザーが使うオブジェクトを設定します。 参考 → 木構造 (データ構造) - Wikipedia (Web) TreeA_Class TreeA_NodeClass Item TreeA_NodeClass Item TreeA_NodeClass Item TreeA_NodeClass Item TreeA_NodeClass Item TreeA_Class のオブジェクト(ルート)のみ LifeGroupClass のハンドルを持っているため、TreeA_Class の オブジェクトが参照されなくなったときに、すべてのノードが削除されます。 注意 辞書 のキーや配列番号で参照することで、オブジェクト同士の直接の相互参照をしなければ、 TreeA_Class を使用しなくてもよいかもしれません。 サンプル Class SampleClass Public TreeNode End Class Sub Main() Set tree = new_TreeA_Class( new SampleClass ) Set tree.Item.TreeNode = tree.TreeNode '// Don't set "tree" Set child_item = new SampleClass Set child_item.TreeNode = Me.TreeNode.AddNewNode( child_item ) End Sub ソース → vbslib.vbs テスト → T_Tree.vbs T_TreeA_1 *********************************************************************** <<< new_TreeA_Class >>> *********************************************************************** new_TreeA_Class Function new_TreeA_Class( Item ) as TreeA_Class ツリーのルートを生成します。 【引数】 Item ルートのノードと関連付けるオブジェクト、または、Nothing 返り値 ツリーのルート → TreeA_Class ソース → vbslib.vbs *********************************************************************** <<< TreeA_Class >>> *********************************************************************** TreeA_Class ツリー構造のルート。 TreeA_Class のオブジェクト(ルート)のみ LifeGroupClass のハンドルを持っているため、TreeA_Class の オブジェクトが参照されなくなったときに、すべてのノードが削除されます。 (参照されていないノードのみ) .Item ノードと関連するオブジェクト .TreeNode 相互参照するときのルート ノード → TreeA_NodeClass .ParentNode Nothing .ParentItems 親ノードの Item の配列。 Me のノードは含まない。 最後はルート。 .ChildNodes 直下の子ノードの配列 .ChildItems 末端まで含めた子ノードの配列 ソース → vbslib.vbs *********************************************************************** <<< TreeA_NodeClass >>> *********************************************************************** TreeA_NodeClass ツリー構造のノード。 ルート(根ノード)、ブランチ(内部ノード)、リーフ(葉ノード)。 .Item ノードと関連するオブジェクト .TreeNode 相互参照するときのルート ノード。 Me と同じ .ParentNode 親ノード .ParentItems 親ノードの Item の配列。 Me のノードは含まない。 最後はルート。 .ChildNodes 直下の子ノードの配列 .ChildItems 末端まで含めた子ノードの配列 ソース → vbslib.vbs *********************************************************************** <<< CrossFindClass >>> *********************************************************************** CrossFindClass モジュールを構成する要素が同じかどうかで分類します。 分類したものをモジュール タイプと呼びます。 モジュール名と要素名(モジュールを構成する要素の名前)が、プロジェクトで1つである 状況で使えます。 サンプル 下記サンプルの は分類する前のモジュールの構成を表します。 は、CrossFindClass で解析した結果を表しています。 の子要素である は、要素ごとに、所属しているモジュール タイプを 子要素に持っています。 たとえば、a1 という要素は、   ・プロジェクト p1 に含まれる t11 モジュール   ・プロジェクト p2 に含まれる t21 モジュール   ・プロジェクト p3 に含まれる t31 モジュール に含まれていますが、これらのモジュールは、構成要素ごとに、   ・{ a1, a2 } から構成されるモジュール タイプ   ・{ a1, b1 } から構成されるモジュール タイプ に分類されます。 データのサンプル: a1, a2 b1, b2 a1, a2 b1, b2 a1, b1 a2 b2 a1, a2 a1, b1 a1, a2 b1, b2 a1, b1 b1, b2 a1, a2 a1, a2 参考 → T_CrossFind.vbs - Variable: A1.xml コードのサンプル: Set find_ = new CrossFindClass Set project = find_.AddProject( "p1" ) project.AddModule "t11", Array( "a1", "a2" ) project.AddModule "t12", Array( "b1", "b2" ) Set project = find_.AddProject( "p2" ) project.AddModule "t21", Array( "a1", "a2" ) project.AddModule "t22", Array( "b1", "b2" ) Set project = find_.AddProject( "p3" ) project.AddModule "t31", Array( "a1", "b1" ) project.AddModule "t32", Array( "a2" ) project.AddModule "t33", Array( "b2" ) For Each element_name In find_.OutElements.Keys echo "element_name = "+ element_name Set element = find_.OutElements.Item( element_name ) For k=0 To element.OutModuleTypes.Count - 1 Set module_type = element.OutModuleTypes.Item(k) echo vbTab +"module_type.Names = "+ module_type.Name echo vbTab +"Elements = "+ new_ArrayClass( module_type.Delegate.Elements ).CSV echo "" Next Next データ構造 CrossFindClass (.vbs) ArrayClass of CrossFind_ProjectClass (.vbs) .Projects dictionary of CrossFind_OutElementClass (.vbs) .OutElements dictionary array NameOnlyClass CrossFind_ModuleClass (.vbs) .ModuleTypesByElement CrossFind_OutModuleTypeClass .OutModuleTypes ソース → ToolsLib.vbs 主な処理は、 → OutElements (CrossFindClass) テスト → T_CrossFind.vbs *********************************************************************** <<< AddProject (CrossFindClass) >>> *********************************************************************** AddProject (CrossFindClass) << CrossFindClass Function CrossFindClass::AddProject( in_ProjectName as string ) as CrossFind_ProjectClass CrossFindClass のプロジェクトを追加します。 【引数】 in_ProjectName プロジェクト名 返り値 追加したプロジェクト → CrossFind_ProjectClass ソース → ToolsLib.vbs *********************************************************************** <<< OutElements (CrossFindClass) >>> *********************************************************************** OutElements (CrossFindClass) << CrossFindClass Property CrossFindClass::OutElements() as dictionary of CrossFind_OutElementClass Key=ElementName CrossFindClass の解析結果。 キーは、 AddModule (CrossFind_ProjectClass) で追加したモジュール名。 アイテムは、 → CrossFind_OutElementClass ソース → ToolsLib.vbs *********************************************************************** <<< CrossFind_ProjectClass >>> *********************************************************************** CrossFind_ProjectClass << CrossFindClass CrossFindClass のプロジェクト。 string .Name 要素の名前 ArrayClass of CrossFind_ModuleClass .Modules モジュールの配列 → AddModule ソース → ToolsLib.vbs *********************************************************************** <<< AddModule (CrossFind_ProjectClass) >>> *********************************************************************** AddModule (CrossFind_ProjectClass) Sub CrossFindClass::AddModule( in_ModuleName as string, in_Elements as array of string ) CrossFindClass のプロジェクトにモジュールを追加します。 【引数】 in_ModuleName モジュール名 in_Elements モジュールを構成する要素の名前の配列 ソース → ToolsLib.vbs *********************************************************************** <<< CrossFind_OutElementClass >>> *********************************************************************** CrossFind_OutElementClass << CrossFindClass CrossFindClass の解析結果。 OutElements (CrossFindClass) で取得します。 string .Name 要素の名前 → CrossFind_OutModuleTypeClass CrossFind_OutModuleTypeClass .OutModuleTypes ソース → ToolsLib.vbs *********************************************************************** <<< CrossFind_OutModuleTypeClass >>> *********************************************************************** CrossFind_OutModuleTypeClass CrossFindClass の解析結果。 OutModuleTypes (CrossFind_OutElementClass) で取得します。 ArrayClass of string .Names 同じ構成要素を持つモジュールの名前の配列 ArrayClass of string .Elements モジュールを構成する要素の名前の配列 ソース → ToolsLib.vbs *********************************************************************** <<< アルゴリズム メモ (CrossFindClass) >>> *********************************************************************** アルゴリズム メモ (CrossFindClass) << CrossFindClass すべての要素を含むモジュールを見つける a1 => { a1, a2 }, { a1, b1 } => { a1, a2 }, { a1, b1 } b1 => { b1, b2 }, { a1, b1 } { a1, b1 } => { a1, b1 } 候補を絞っていく 候補がなくなったら、Module を追加する(A1.xml)か、 Element を追加する(A3.xml)か、どっち? 要素すべて(a1 と b1)が既存なので (既存の異なる2つのモジュールをクロスするので) a1 => { a1, a2 } { a1, b1 } b1 => { b1, b2 } { a1, b1 } { a1, b1 } をすべて(a1, b1)に追加する 新規 (a3) を除いたのが一部のときは、 ({ a1, a3 } については、) Module を追加する (すべての)新規 (a3) を除いたモジュールがあれば、 a1 => { a1, a2 } a2 => { a1, a2 } a3 => { a1, a2, a3 } { a1, a2, a3 } { a1, a2, a3 } a1 => { a1, a2 } a2 => { a1, a2 } a3 => { a1, a3 } { a1, a3 } a3 に 全ての要素 { a1, a2, a3 } を追加 a3 を除いた { a1, a2 } を変更する a3 を除いたのが { a1, b1 } でないときは、すべて追加する *********************************************************************** <<< 並べ替え、ソート >>> *********************************************************************** 並べ替え、ソート *********************************************************************** <<< QuickSort >>> *********************************************************************** QuickSort Sub QuickSort( Arr as object array, iLeft as integer, iRight as integer, CompareFunc as function, CompareFuncParam as variant ) 配列をクイックソートします。安定ソートではありません。 【引数】 Arr ソートする配列。(*1) iLeft ソートする範囲。配列番号の最小値 iRight ソートする範囲。配列番号の最大値 CompareFunc 比較関数 CompareFuncParam CompareFunc の第3引数 (*1) 配列の要素はオブジェクトであること。 → ArrayToNameOnlyClassArray Arr 引数は、Visual Basic 標準の配列でも、ArrayClass でも構いませんが、 ArrayClass::Items は指定できません。(ソートされません。) サンプル Option Explicit Class ClassA : Public id : End Class Sub Main( Opt, AppKey ) ReDim arr(4) Set arr(0) = new ClassA : arr(0).id = 6 Set arr(1) = new ClassA : arr(1).id = 3 Set arr(2) = new ClassA : arr(2).id = 4 Set arr(3) = new ClassA : arr(3).id = 4 Set arr(4) = new ClassA : arr(4).id = 1 QuickSort arr, 0, UBound( arr ), GetRef("CmpFunc1"), Empty echo arr(0).id &","& arr(1).id &","& arr(2).id &","& _ arr(3).id &","& arr(4).id End Sub Function CmpFunc1( left, right, param ) CmpFunc1 = left.id - right.id '// 降順なら right.id - left.id End Function 出力 1,3,4,4,6 参考 → クイックソート ソース → vbslib.vbs テスト → T_QSort.vbs 関連 → QuickSort_fromDic → QuickSortDicByKey *********************************************************************** <<< ShakerSort >>> *********************************************************************** ShakerSort (src) Sub ShakerSort( Arr as array of Object, iLeft as integer, iRight as integer, CompareFunc as function, CompareFuncParam as variant ) 配列をシェーカーソートします。安定ソートです。 【引数】 Arr ソートする配列。(*1) iLeft ソートする範囲。配列番号の最小値。 通常 0 iRight ソートする範囲。配列番号の最大値。 通常 UBound(Arr) CompareFunc 比較関数 CompareFuncParam CompareFunc の第3引数 (*1) 配列の要素はオブジェクトであること。 → ArrayToNameOnlyClassArray Arr 引数は、Visual Basic 標準の配列でも、ArrayClass でも構いませんが、 ArrayClass::Items は指定できません。(ソートされません。) サンプル Class ClassA : Public id : End Class Redim arr(4) Set arr(0) = new ClassA : arr(0).id = 6 Set arr(1) = new ClassA : arr(1).id = 3 Set arr(2) = new ClassA : arr(2).id = 4 Set arr(3) = new ClassA : arr(3).id = 4 Set arr(4) = new ClassA : arr(4).id = 1 ShakerSort arr, 0, UBound( arr ), GetRef("CmpFunc1"), Empty WScript.Echo arr(0).id &","& arr(1).id &","& arr(2).id &","& _ arr(3).id &","& arr(4).id Function CmpFunc1( Left, Right, Param ) CmpFunc1 = Left.id - Right.id '// 降順なら Right.id - Left.id End Function 文字列を昇順にソートするサンプル Dim line ReDim lines(-1) Set f = OpenForRead( target_result_txt ) Do Until f.AtEndOfStream Set line = new String1 line.s = f.ReadLine() ReDim Preserve lines( UBound( lines ) + 1 ) Set lines( UBound( lines ) ) = line Loop f = Empty ShakerSort lines, 0, UBound( lines ), GetRef("StrCmpFunc"), 1 Function StrCmpFunc( Left, Right, Param ) StrCmpFunc = StrComp( Left.s, Right.s, Param ) End Function Class String1 Public s End Class 参考 → シェーカーソート (ShakerSort) テスト → T_ShakerSort.vbs 関連 → ShakerSort_fromDic → ShakerSort_fromDicKey → ShakerSortDicByKey → ShakerSortDicByKeyCompare *********************************************************************** <<< CompareFunction 型、比較関数型 >>> *********************************************************************** CompareFunction 型、比較関数型 Function CompareFunction( Left as variant, Right as variant, Parameter as variant ) as integer 2つのパラメーターを比較する関数の型。 関数名は、CompareFunction とは限りません。 【引数】 Left 1つ目の比較対象 Right 2つ目の比較対象 Parameter 比較に使う補助パラメーター 返り値 0:等しい、正の数:Left が大きい、負の数:Rightが大きい (昇順:小→大のとき) StrComp も、この関数型ですが、GetRef("StrComp") はエラーになります。 Left、Right は、 ShakerSort などの関数に指定するコレクションの要素です。 Param には、ShakerSort などの関数にある引数がそのまま渡ります。 昇順:小→大にするときは、Left - Right の値を返してください。 降順にするときは、返り値の正と負を変えてください。 サンプル Function SampleStaticClass_comparePriority( in_Left, in_Right, in_Parameter ) SampleStaticClass_comparePriority = in_Left.Priority - in_Right.Priority End Function 関連 → StdCompare → NameCompare → LengthCompare → LengthNameCompare → StrCompOption → CopyFunction 型、コピー関数型 *********************************************************************** <<< StdCompare >>> *********************************************************************** StdCompare Function StdCompare( Left as variant, Right as variant, Param as variant ) as integer 2つのパラメーターを標準的な方法で比較します。 (StdCompare = Standard Compare) 比較関数型 です。 Param 引数は、Left と Right が文字列のときだけ有効です。 Left Right 返り値 数値 数値 -1, 0, 1 のどれか。(=や>と同じ) 文字列 文字列 StrComp と同じ (=や>と同じ)。Param 引数も同じ オブジェクト オブジェクト is 演算子 の結果が True なら 0、 False なら -1 Empty Empty 0 Empty Empty 以外 1 (昇順でソートすると、Emptyが最後になる) Empty 以外 Empty -1 日付 日付 古い方が小さい値となる返り値 (=や>と同じ) 任意の型 Left と異なる型 -1 (エラーにはならない) ソース → vbslib.vbs テスト → T_QSort.vbs # [T_CompareFunc] *********************************************************************** <<< NameCompare >>> *********************************************************************** NameCompare Function NameCompare( Left as variant, Right as variant, Param as variant ) as integer 2つのパラメーターを Name プロパティで比較します。 比較関数型 です。 Param 引数は、StrComp 関数と同じです。 Left Right 返り値 オブジェクト オブジェクト Name プロパティを StrComp に渡した結果 オブジェクト以外 オブジェクト以外 0 オブジェクト オブジェクト以外 -1 (昇順でソートすると、オブジェクト以外が最後になる) オブジェクト以外 オブジェクト 1 ソース → vbslib.vbs テスト → T_QSort.vbs # [T_CompareFunc] *********************************************************************** <<< NumStringCompare >>> *********************************************************************** NumStringCompare Function NumStringCompare( Left as variant, Right as variant, Param as variant ) as integer 文字列の中の数字を複数桁の正の整数値として比較します。 比較関数型 です。 Param 引数には、Empty または c.CaseSensitive を指定してください。 ファイル名でソート したときと同じになります。 ただし、フォルダーの区切り記号 \ や / を含む文字列 を比較するときは、 PathCompare を使ってください。 Left Right 返り値 "A1" "A2" 負の数値(Left < Right) "A10" "A2" 正の数値(Left > Right)、数値10と2 の比較 "A10" "A10.2" 負の数値(Left < Right) "A10.10" "A10.2" 正の数値(Left > Right)、小数ではなく整数.整数とする "A-1" "A-2" 負の数値(Left < Right)、マイナスとは見なさない "A" "a" 負の数値(Left < Right) "B" "a" 正の数値(Left > Right)、大文字小文字を区別しない 10.10 は小数ではなく、バージョン番号のように 10 の 10 であるとします。 ソース → vbslib.vbs テスト → T_QSort.vbs T_NumStringCompare 関連 → shlwapi.dll の StrCmpLogicalW → NumStringNameCompare *********************************************************************** <<< NumStringNameCompare >>> *********************************************************************** NumStringNameCompare (src) Function NumStringNameCompare( Left as variant, Right as variant, Param as variant ) as integer Name プロパティの文字列の中の数字を複数桁の正の整数値として比較します。 比較関数型 です。 Param 引数には、Empty または c.CaseSensitive を指定してください。 参考 → NumStringCompare 比較する処理の詳細 ソース → vbslib.vbs テスト → T_QSort.vbs T_NumStringNameCompare *********************************************************************** <<< LengthCompare >>> *********************************************************************** LengthCompare (src) Function LengthCompare( Left as variant, Right as variant, Param as variant ) as integer 2つのパラメーターの長さを比較します。 比較関数型 です。 文字列型のときは、文字列の長さを比較します。 Param がマイナスなら、返り値の正と負が入れ替わります。 ソース → vbslib.vbs *********************************************************************** <<< LengthNameCompare >>> *********************************************************************** LengthNameCompare (src) Function LengthNameCompare( Left as variant, Right as variant, Param as variant ) as integer 2つのパラメーターの Name プロパティを LengthCompare で比較します。 比較関数型 です。 Param = -1 にすると、逆順になります。 ソース → vbslib.vbs *********************************************************************** <<< PathCompare >>> *********************************************************************** PathCompare Function PathCompare( Left as string, Right as string, Param as variant ) as integer 2つの文字列をパスとして比較します。 比較関数型 です。 参考 → PathNameCompare パスとして比較する処理の詳細 ソース → vbslib.vbs テスト → T_ShakerSort.vbs T_SortByPath 関連 → PathNameCompare *********************************************************************** <<< PathNameCompare >>> *********************************************************************** PathNameCompare Function PathNameCompare( Left as variant, Right as variant, Param as variant ) as integer 2つのオブジェクトの Name プロパティをパスとして比較します。 比較関数型 です。 Param を負の値とすると、大小比較の結果が逆になります。 そうでないときは、Param = Empty または Param を正の値にしてください。 フォルダーの中にあるフォルダーやファイルは、連続します。 たとえば、通常の文字コードでソートしたら "A!B", "A\!", "A\*", "A\C" の順になりますが、 PathNameCompare では、"A\*", "A\!", "A\C", "A!B" の順になります。 フォルダー区切り記号(\,/)、ワイルドカード(*)、ピリオド(.)を、文字コードが小さい文字(タブ) として処理します。 参考 → Ascii コード ファイル名でソート したときのように、数字は整数として比較します。 参考 → NumStringCompare サンプル arr = ArrayToNameOnlyClassArray( Array( "F", "EE\!", "EE\*", "EE", "E!E", "E\F", "E" ) ) ShakerSort arr, 0, UBound( arr ), GetRef("PathNameCompare"), Empty arr = NameOnlyClassArrayToArray( arr ) Assert IsSameArray( arr, Array( "E", "E\F", "E!E", "EE", "EE\*", "EE\!", "F" ) ) ソース → vbslib.vbs テスト → T_ShakerSort.vbs T_SortByPath 関連 → PathCompare → ExpandWildcard_Sort 変数 → StrCmpLogicalW - Win32API *********************************************************************** <<< ParentPathCompare >>> *********************************************************************** ParentPathCompare Function ParentPathCompare( Left as string, Right as string, Param as variant ) as integer パスをソートした状態から、親フォルダーを後にするような比較を行います。 比較関数型 です。 通常、Param = -1 (Param <= 0) にして、親フォルダーが後になるようにします。 Param < 0 のときは、親フォルダーが前になるようにします。 親子関係以外の順序は変更しません。 サンプル ParentPathCompare を使ってソートしたときの例: ソート前: "a", "a\1", "aa", "b", "b\1", "b\1\2" ソート後: "a\1", "a", "aa", "b\1\2", "b\1", "b" ソース → vbslib.vbs テスト → T_ShakerSort.vbs T_SortByParentPath *********************************************************************** <<< NoCompareFunction >>> *********************************************************************** NoCompareFunction Function NoCompareFunction( Left as variant, Right as variant, Param as variant ) as integer Param 引数の内容をそのまま返します。 比較関数型 です。 ソース → vbslib.vbs *********************************************************************** <<< IsReverseSortOption >>> *********************************************************************** IsReverseSortOption Function IsReverseSortOption( in_Option as variant ) as boolean 逆順でソートするオプションが指定されているかどうかを返します。 in_Option 引数の値 返り値 Empty False c.CaseSensitive False -1 True 0 False +1 False ソース → vbslib.vbs テスト → T_ShakerSort.vbs *********************************************************************** <<< 関連 >>> *********************************************************************** 関連 → QuickSortDicByKey → QuickSort_fromDic → ShakerSort_fromDic → ShakerSort_fromDicKey → ShakerSortDicByKey → PArray_doShakerSort (clib) → XmlSort → SearchInSimpleArray *********************************************************************** <<< 文字列 >>> *********************************************************************** 文字列 関連 → ファイル名・パス *********************************************************************** <<< CInt2 >>> *********************************************************************** CInt2 (src) Function CInt2( v as string ) as integer 文字列を数値に変換します。 CInt でエラーが発生する値を v に指定したときは、0 を返します。 VBScript では、CInt は、符号付き16ビット整数ですが、CInt2 は CLng に相当する 符号付き32ビット整数に対応しています。 関連 → CLng("&h8000") → Eval → GetNumWithZeroAtLeft *********************************************************************** <<< Trim2, LTrim2, RTrim2 >>> *********************************************************************** Trim2, LTrim2, RTrim2 (src) Function Trim2( v as string ) as string Function LTrim2( v as string ) as string Function RTrim2( v as string ) as string 文字列の端の空白文字だけでなく、タブ文字、改行文字もカットした文字列を返します。 *********************************************************************** <<< AlignString >>> *********************************************************************** AlignString Function AlignString( in_InputData as integer, in_MinimumLength as integer, in_FillingCharacter as string, in_ValueIfOver as Empty or string ) as string 文字列や数値の左または右に、空白や 0 などを並べて、幅を合わせた文字列に変換します。 【引数】 in_InputData 変換される文字列や数値 in_MinimumLength 返り値の文字数の最小値、マイナス=左詰め in_FillingCharacter 幅を広げるときに並べる文字 in_ValueIfOver in_MinimumLength を超えたときの返り値、または、Empty 返り値 幅を合わせた文字列 in_ValueIfOver = Empty のときは、返り値が in_MinimumLength を超える文字数になる 可能性があります。 サンプル out = AlignString( "a", 3, " ", Empty ) : Assert out = " a" out = AlignString( 123, 6, "0", Empty ) : Assert out = "000123" out = AlignString(-123, 6, " ", Empty ) : Assert out = " -123" out = AlignString( "AB",-5," ", Empty ) : Assert out = "AB " out = AlignString(-123, 3, " ", "###" ) : Assert out = "###" out = AlignString(-123, 3, " ", Empty ) : Assert out = "-123" out = AlignString(-123, 6, " ", "###" ) : Assert out = " -123" ソース → vbslib.vbs テスト → T_Str.vbs T_AlignString *********************************************************************** <<< CutLastOf >>> *********************************************************************** CutLastOf (src) Sub CutLastOf( in_out_Str as string, LastStr as string, Opt as integer ) in_out_Str の最後が LastStr と一致したら、それをカットします。 【引数】 in_out_Str (入出力) カットされるかもしれない文字列 LastStr 比較する文字列 Opt Empty または c.CaseSensitive サンプル: s = "file1.txt" CutLastOf s, "1.txt", Empty Assert s = "file" テスト → T_Str.vbs # [T_StrComp] 関連 → CutLastOfFileName ファイル名(拡張子を除く)の最後を削除します → StrCompLastOf 文字列の末尾を比較します → GetPathWithSeparator Path の最後を区切り記号にします → GetLastSeparatorOfPath 末尾にあるフォルダーの区切り記号を返します *********************************************************************** <<< LenK >>> *********************************************************************** LenK (src) Function LenK( Str as string ) as integer 英文字を 1文字、日本語(文字コード256以上)を 2文字として文字数を返します。 サンプル: LenK( "123" ) = 3 LenK( "123あいう" ) = 9 Len( "123あいう" ) = 6 関連 → GetLineNumsExistNotEnglighChar *********************************************************************** <<< StrCount >>> *********************************************************************** StrCount (src) Function StrCount( Str as string, Keyword as string, StartPos as integer, Opt as integer ) as integer 文字列が存在する数を返します。 【引数】 Str 数を数えられる文字列 Keyword 数を数える文字列 StartPos Str の中の、数え始める位置。 先頭=1 Opt Empty または c.CaseSensitive 返り値 Str の中にある Keyword の数 Str 引数の値 Keyword 引数の値 返り値 "ABCABC" "ABC" 2 "ABCABC" "A" 2 "ABCABC" "D" 0 "/Folder/File" "/" 2 テスト → T_Str.vbs # [T_StrCount] *********************************************************************** <<< GetTab >>> *********************************************************************** GetTab (src) Function GetTab( Level as integer ) as string インデント数を指定して、空白文字を返します。 インデント数×2の空白文字を返します。 関連 → CutIndentOfMultiLineText *********************************************************************** <<< CutLineFeedAtRightEnd >>> *********************************************************************** CutLineFeedAtRightEnd Function CutLineFeedAtRightEnd( Text as string, Width as integer ) as string コマンドプロンプトの右端からあふれた文字列を1行にまとめます。 【引数】 Text コマンドプロンプトからコピーした文字列 Width コマンドプロンプトの幅 返り値 修正した文字列 ソース → ToolsLib.vbs サンプル Width = 20 の場合、 01234567890123456789 ABCDEFGHIJKLMNOPQRST UVWXYZ END ABCDEFGHIJKLMNOPQRSTUVWXYZ END *********************************************************************** <<< StrCompOption >>> *********************************************************************** StrCompOption Function StrCompOption( Opt as integer ) as integer StrComp の Option 引数に指定する値を返します。 Opt 引数の値 返り値 Empty vbTextCompare (=1) 大文字小文字は区別しない c.CaseSensitive vbBinaryCompare (=0) 大文字小文字は区別する その他 vbTextCompare (=1) いろいろな関数の Opt 引数が、StrCompOption の Opt 引数と同じ意味を持つことが よくあります。 サンプル Set c = g_VBS_Lib If StrComp( "ABC", "BC", StrCompOption( c.CaseSensitive ) ) = 0 Then ... サンプル Set c = g_VBS_Lib If StrCompLastOf( "ABC", "BC", c.CaseSensitive ) = 0 Then ... ソース → vbslib.vbs テスト → T_ShakerSort.vbs 関連 → CompareFunction 型、比較関数型 *********************************************************************** <<< StrCompHeadOf >>> *********************************************************************** StrCompHeadOf Function StrCompHeadOf( Str as string, HeadStr as string, Opt as integer ) as integer 文字列の先頭を比較します。 【引数】 Str 比較される文字列 HeadStr Str の先頭と比較する文字列 Opt Empty または c.CaseSensitive または c.AsPath 返り値 Str の先頭 = HeadStr なら、0 。 StrComp と同じ 比較関数型 です。 0 のとき、c.AsPath が設定されていないとき、 Str 引数の値 LastStr 引数の値 返り値 "ABCDE" "ABC" 0 (=一致) "ABCDE" "CDE" 0以外(=異なる)、負の値 "ABCDE" "AAA" 0以外(=異なる)、正の値 "ABCDE" "" 0 (=一致) c.AsPath が設定されているとき、 親フォルダー、またはその親フォルダー、… であるかどうかを比較します。 Str 引数の値 LastStr 引数の値 返り値 "ABCDE" "ABC" 0以外(=異なる)、正の値 "ABC\DE" "ABC" 0 (=一致) "ABC/DE" "ABC" 0 (=一致) "ABC\DE" "ABC\" 0 (=一致) "ABC" "ABC\" 0以外(=異なる)、負の値 "ABCDE" "." 0 (=一致) "ABCDE" "" 0 (=一致) "ABCDE" Empty (*1) 0以外(=異なる) *1 LastStr 引数 = Empty のときは、親フォルダーがなく、該当する親フォルダーに 入っていないために「異なる」という結果にしています。 ソース → vbslib.vbs テスト → T_Str.vbs # [T_StrComp] 関連 → StrCompLastOf *********************************************************************** <<< StrCompLastOf >>> *********************************************************************** StrCompLastOf (src) Function StrCompLastOf( Str as string, LastStr as string, Opt as integer ) as integer 文字列の末尾を比較します。 【引数】 Str 比較される文字列 LastStr Str の末尾と比較する文字列 Opt Empty または c.CaseSensitive 返り値 Str の末尾 = LastStr なら、0 → StrComp 比較関数型 です。 Str 引数の値 LastStr 引数の値 返り値 "ABCDE" "CDE" 0 (=一致) "ABCDE" "ABC" 0以外(=異なる)、正の値 テスト → T_Str.vbs # [T_StrComp] 関連 → StrCompLastOfFileName → CutLastOf → StrCompHeadOf *********************************************************************** <<< AddIfNotExist >>> *********************************************************************** AddIfNotExist (src) Function AddIfNotExist( WholeStr as string, AddStr as string, Separator as string, Opt ) as string 列挙された文字列のどれにも一致しなければ、先頭に追加します。 【引数】 WholeStr 文字列の列挙 AddStr 追加する文字列 Separator 文字列の列挙を区切る文字列 Opt Empty または c.CaseSensitive 返り値 AddStr+Separator+WholeStr、または、WholeStr サンプル Assert AddIfNotExist( "ABC;DEF", "XYZ", ";", Empty ) = "XYZ;ABC;DEF" Assert AddIfNotExist( "ABC,XYZ", "XYZ", ",", Empty ) = "ABC;XYZ" Assert AddIfNotExist( "", "XYZ", ";", Empty ) = "XYZ;" XYZ XYZ サンプル PATH 環境変数 に "..\bin" フォルダーのフル・パスを追加する set_ "PATH", AddIfNotExist( env("%PATH%"), _ GetFullPath( "..\bin", Empty ), ";", Empty ) テスト → T_Str.vbs # [T_AddIfNotExist] 関連 → GetPathWithSeparator *********************************************************************** <<< MeltQuot >>> *********************************************************************** MeltQuot (src) Function MeltQuot( Line as string, in_out_Start as integer ) as string " " で囲まれた部分を取り出す。 【引数】 Line 文字列全体 in_out_Start (入力) 取り出しを開始する文字の位置、(出力)次に取り出す〜 返り値 " " で囲まれた部分文字列。Empty=項目に値が無い サンプル i = 1 Do s = MeltQuot( line, i ) If not IsEmpty( s ) Then (s を使った処理) If i = 0 Then Exit Do Loop サンプル Assert MeltCmdLine( """double_quotation""", 1 ) = "double_quotation" テスト → T_Str.vbs # [T_MeltQuot] 関連 → MeltCmdLine → MeltCSV *********************************************************************** <<< sprintf >>> *********************************************************************** sprintf Function sprintf( in_Format as string, in_Parameter as array of integer ) as string C言語の printf 書式 で整形した文字列を返します。 【引数】 in_Format C言語の printf 書式 in_Parameter C言語の printf 書式のパラメーター 返り値 C言語の printf 書式で整形した文字列 C言語の printf 書式のすべてはサポートしていません。 %d と %s は、そのまま文字列に挿入します。 %02d のように 0 から始まる数値が % と d の間にあれば、その桁数だけ上位に 0 が付きます。 % と d の間だけでなく、d 以外でも上位に 0 が付きます。 %X または %d は、16進数に変換して挿入します。 10進数の 10〜15 は、%X では A〜F、%x では a〜f になります。 サンプル Assert sprintf( "number = %d", Array( 2 ) ) = "number = 2" Assert sprintf( "n = %02d, %02d, %02d", Array( 3, 5, 10 ) ) = "n = 03, 05, 10" Assert sprintf( "0x%X, 0x%X, 0x%X, 0x%x", Array( 8, 9, 10, 11 ) ) = "0x8, 0x9, 0xA, 0xb" Assert sprintf( "alphabet = %s", Array( "A" ) ) = "alphabet = A" Assert sprintf( "alphabet = (%-4s)", Array( "A" ) ) = "alphabet = (A )" ソース → vbslib.vbs テスト → T_Str.vbs T_sprintf 関連 → sscanf *********************************************************************** <<< sscanf >>> *********************************************************************** sscanf Function sscanf( String, Format ) 文字列の途中を取り出します。 【引数】 String 文字列全体 Format 取り出す部分を指定する文字列。 "%d" または "%s" を含む 返り値 取り出した文字列、または、数値 ファイル: vbslib.vbs サンプル: 数値を取り出すときは、%d を使います。 Assert sscanf( "ABC123DEF", "ABC%dDEF" ) = 123 サンプル: 文字列を取り出すときは、%s を使います。 Assert sscanf( "===[ABC]===", "[%s]" ) = "ABC" サンプル: 複数にマッチする場合、最も左にあるものとマッチします Assert sscanf( "===[123] [456]===", "[%s]" ) = "123" Assert sscanf( "===[ [ 123 ] ]===", "[%s]" ) = " [ 123 " %d, %s 以外の部分がマッチしないときは、エラーになります。 ソース → vbslib.vbs テスト → T_Str.vbs T_sscanf 関連 → sprintf → ScanFromTemplate → ScanMultipleFromTemplate → ReadFileInTag → grep (検索) *********************************************************************** <<< ScanFromTemplate >>> *********************************************************************** ScanFromTemplate Function ScanFromTemplate( ScanString as string, TemplateString as string, KeywordArray as array of string, Option_ as Empty ) as dictionary of string 文字列の途中を複数取り出します。 【引数】 ScanString 取り出す文字列を含む文字列 TemplateString 取り出す部分を指定する文字列 KeywordArray TemplateString に書かれた取り出す部分の文字列の配列 Option_ Empty または g_VBSLib.WithDollarVariable 返り値 取り出した文字列の辞書 KeywordArray 配列の要素は、TemplateString の中に含まれる順番に指定してください。 KeywordArray 配列の要素は、${ } や % % で囲んだ形式である必要はありません。 大文字小文字は区別します。 ${ 文字を指定するときに $\{ を指定したときは、Option_ に g_VBSLib.WithDollarVariable を指定してください。 ScanString が TemplateString にマッチしないときは、エラーになります。 サンプル Set out = ScanFromTemplate(_ "ab12cde34xyz",_ "b${First}cde${Second}xy",_ Array( "${First}", "${Second}" ), Empty ) Assert out("${First}") = "12" Assert out("${Second}") = "34" サンプル 変数が TemplateString 引数の端にあるとき Set out = ScanFromTemplate(_ "abc def ghi"+ vbCRLF,_ "%A% %B% %C%",_ Array( "%A%", "%B%", "%C%" ), Empty ) Assert out("%A%") = "abc" Assert out("%B%") = "def" Assert out("%C%") = "ghi"+ vbCRLF ソース → vbslib.vbs テスト → T_Str.vbs T_ScanFromTemplate 関連 → SearchStringTemplate → sscanf → ScanMultipleFromTemplate → ParsePercentVariableString → SearchStringTemplate *********************************************************************** <<< ScanMultipleFromTemplate >>> *********************************************************************** ScanMultipleFromTemplate Sub ScanMultipleFromTemplate( ScanString as string, TemplateString as string, Keywords as array of string, Option_ as Empty, out_Scaned as array of dictionary of string ) 文字列からテンプレートを複数回適用してテンプレートの変数部分を取り出します。 【引数】 ScanString 取り出す文字列を含む文字列 TemplateString 取り出す部分を指定する文字列 Keywords TemplateString に書かれた取り出す部分の文字列の配列 Option_ Empty を指定してください out_Scaned 取り出した文字列の辞書の配列 参考 → ScanFromTemplate テンプレートを1回適用する場合 サンプル ScanMultipleFromTemplate _ " [1,2] [3,4] ",_ "[${A},${B}]",_ Array( "${A}", "${B}" ), Empty, out '//(out) out Assert out(0)("${A}") = "1" Assert out(0)("${B}") = "2" Assert out(1)("${A}") = "3" Assert out(1)("${B}") = "4" サンプル KeywordArray に配列ではない文字列を指定した場合、out_Scaned には辞書ではない 配列が出力されます。 ScanMultipleFromTemplate _ " [1] [2] ",_ "[#]", "#", Empty, out '//(out) out Assert out(0) = "1" Assert out(1) = "2" ソース → vbslib.vbs テスト → T_Str.vbs T_ScanMultipleFromTemplate 関連 → ScanFromTemplate *********************************************************************** <<< InStrEx >>> *********************************************************************** InStrEx (src) Function InStrEx( WholeString as string, Keyword as string, StartIndex as integer, Opt as integer ) as integer オプションを指定して文字列を検索します。 【引数】 WholeString 検索対象になる文字列 Keyword 検索するキーワード。 複数指定するときは配列型で StartIndex 検索を開始する位置。先頭=1。 全体を検索(先頭または末尾)=0 Opt 下記のフラグ、または Empty 返り値 見つかった文字列の先頭の位置。 0=見つからなかった サンプル 単語全体にマッチする文字列を検索します Set c = g_VBS_Lib Assert InStrEx( "answer ans", "ans", 1, c.WholeWord or c.CaseSensitive ) = 8 "answer ans", "ans" サンプル 指定したキーワードのどれか最初にマッチした文字列を検索します pos = InStrEx( text, Array( "{{", "}}", "=" ), pos, Empty ) Array( "{{", "}}", "=" ) Opt 引数 下記のフラグを複数指定するときは、or で接続してください。 なお、c は、g_VBS_Lib の返り値です。 c.WholeWord 英語の単語全体にマッチする文字列を検索します。 このフラグを指定しなければ、単語の一部にキーワードを含む単語も 検索にヒットします。 参考 → IsWholeWord c.CaseSensitive 大文字、小文字を区別します。 このフラグを指定しなければ、大文字、小文字が異なる文字列も 検索にヒットします。 c.Rev 前方(左上方向)に向かって検索します。 このフラグを指定しなければ、後方(右下方向)に向かって検索します。 c.LastNextPos 返り値を、見つかった文字列の末尾の次の位置にします。 参考 → InStrLast c.LineHead 検索キーワードが行頭にある場所を検索します。 c.LineTail 検索キーワードが行末にある場所を検索します。 テスト → T_Str.vbs T_InStrEx T_InStrExWholeWord T_InStrExArray T_InStrExLineHeadTail *********************************************************************** <<< InStrLast >>> *********************************************************************** InStrLast Function InStrLast( WholeString as string, Keyword as string ) as integer 文字列を検索して、最初に見つかったキーワードの末尾の次の位置を返します。 【引数】 WholeString 検索対象になる文字列 Keyword 検索するキーワード 返り値 キーワードの末尾の次の位置、見つからない=0 ソース → vbslib.vbs サンプル InStrLast( "ABCDEF", "CD" ) = 5 '// E の位置 テスト → T_Str.vbs # [T_InStrLast] 関連 → InStrEx *********************************************************************** <<< IsWholeWord >>> *********************************************************************** IsWholeWord (src) Function IsWholeWord( WholeString as string, StartIndex as integer, SubWordLen as integer ) as integer 文字列の中の指定した範囲が、単語単位になっているかどうかを返します。 【引数】 WholeString 検索対象になる文字列 StartIndex 範囲の開始位置。 先頭=1。文字単位 SubWordLen 範囲の長さ(文字数) 返り値 単語単位になっているかどうか ソース → vbslib.vbs サンプル Assert IsWholeWord( "This is a pen.", 6, 2 ) = True Assert IsWholeWord( "This", 2, 2 ) = False 範囲の中に複数の単語があっても、両端が単語の単位になっていれば True になります。 Assert IsWholeWord( "This is", 1, 7 ) = True 関連 → InStrEx *********************************************************************** <<< StrMatchKey クラス >>> *********************************************************************** StrMatchKey クラス (src) * のワイルドカードを使って、マッチするかどうかを高速に判定します。 * は2つ以上指定できません。エラーになります。 サンプル: Set match = new StrMatchKey match.Keyword = LCase( "*.TXT" ) If match.IsMatch( "file1.txt" ) Then : End If *.TXT file1.txt .Keyword Property Keyword as string ワイルドカードを含むキーワード。 大文字小文字を区別しないときは、LCase を使って小文字にしてください。 .IsMatch Function StrMatchKey::IsMatch( TestStr as string ) as Boolean TestStr が、.Keyword で設定したワイルドカードにマッチするかどうかを返す。 大文字小文字を区別しません。 .IsMatchULCase Function StrMatchKey::IsMatch( TestStr as string ) as Boolean TestStr が、.Keyword で設定したワイルドカードにマッチするかどうかを返す。 大文字小文字を区別します。 .Test .IgnoreCase RegExp と同じ テスト → T_Wildcard.vbs # [T_StrMatchKey] 関連 → ReplaceFileNameWildcard *********************************************************************** <<< StringReplaceSetClass >>> *********************************************************************** StringReplaceSetClass テキストを置き換える手順のオブジェクト。 同じ手順を繰り返すことや、置き換える手順をパラメーター化できます。 .Replace テキストを置き換えることを登録します。 .ReplaceRange 指定のタグで囲まれたテキストを置き換えることを登録します。 .DoReplace 登録しておいた処理を実行します。 サンプル Set rep = new StringReplaceSetClass rep.Replace "from", "to" output_text = rep.DoReplace( input_text ) ソース → vbslib.vbs テスト → T_Wildcard.vbs T_StringReplaceSet T_StringReplaceSet_Range 関連 → OpenForReplace *********************************************************************** <<< Replace (StringReplaceSetClass) >>> *********************************************************************** [ 親: StringReplaceSetClass クラス ] Replace (StringReplaceSetClass) Sub StringReplaceSetClass::Replace( FromText as string, ToText as string ) テキストを置き換えることを登録します。 【引数】 FromText 置き換える前のテキスト ToText 置き換えた後のテキスト 参考 → Replace (ReplaceTextFile1) *********************************************************************** <<< ReplaceRange (StringReplaceSetClass) >>> *********************************************************************** ReplaceRange (StringReplaceSetClass) [ 親: StringReplaceSetClass クラス ] Sub StringReplaceSetClass::ReplaceRange( StartOfFromText as string, EndOfFromText as string, ToText as string ) 指定のタグで囲まれたテキストを置き換えることを登録します。 【引数】 StartOfFromText 置き換える前のテキストが始まる場所にあるタグ(テキスト) EndOfFromText 置き換える前のテキストが終わる場所にあるタグ(テキスト) ToText 置き換えた後のテキスト。 通常、タグも含む。 参考 → ReplaceRange (ReplaceTextFile1) *********************************************************************** <<< DoReplace (StringReplaceSetClass) >>> *********************************************************************** DoReplace (StringReplaceSetClass) [ 親: StringReplaceSetClass クラス ] Function StringReplaceSetClass::DoReplace( InputText as string ) as string 登録しておいた処理を実行します。 【引数】 InputText 置き換える前のテキスト 返り値 置き換えた後のテキスト *********************************************************************** <<< new_RegExp >>> *********************************************************************** new_RegExp new Regular Expression Function new_RegExp( Pattern as string, IsCaseSensitive as boolean ) as RegExp 正規表現 (VBScript.RegExp) オブジェクトを簡易的に生成します。 【引数】 Pattern 正規表現 → 正規表現 IsCaseSensitive 大文字小文字を区別するかどうか 返り値 正規表現オブジェクト サンプル Set re = new_RegExp( "Function\(.*\)", True ) ソース → vbslib.vbs *********************************************************************** <<< FindStringLines >>> *********************************************************************** FindStringLines Function FindStringLines( in_BeforeString as string, in_RegularExpression as string or RegExp, in_Option as Empty ) 複数行の文字列を、正規表現でマッチする行だけにします。 【引数】 in_BeforeString 変換前の文字列 in_RegularExpression 正規表現の文字列、または RegExp オブジェクト → 正規表現 in_Option Empty または False (=マッチしない行だけにする) 返り値 変換後の文字列 サンプル Assert FindStringLines( "abc"+ vbCRLF +"def", "ab", Empty ) = "abc"+ vbCRLF Assert FindStringLines( "abc"+ vbCRLF +"def", ".*", Empty ) = "abc"+ vbCRLF +"def" Set rep = OpenForReplace( "file1.txt", Empty ) rep.Text = FindStringLines( rep.Text, """ERROR""", Empty ) rep = Empty 参考 → 正規表現 ソース → vbslib.vbs テスト → T_Wildcard.vbs T_FindStringLines 関連 → grep コマンド → Text (ReplaceTextFile1) (OpenForReplace) → ArrayFromLines → StartReplace → PassThroughLineFilters → find (DOS バッチファイル) → find → find_c *********************************************************************** <<< SortStringLines >>> *********************************************************************** SortStringLines Function SortStringLines( in_BeforeString as string, in_IsDuplicated as boolean ) 複数行の文字列を、行単位で整列(ソート)します。 【引数】 in_BeforeString 整列前の文字列 in_IsDuplicated 重複する行をそのまま残すかどうか。 False = 重複したら1行にする 返り値 整列後の文字列 整列前の文字列の最後の行に改行文字がないときは、先頭の行にある改行文字が追加されます。 in_IsDuplicated = False のとき、改行文字だけ異なる行も、1行にします。 サンプル lines = _ "A"+ vbCRLF +_ "C"+ vbCRLF +_ "F"+ vbCRLF +_ "C" lines = SortStringLines( lines, False ) Assert lines = _ "A"+ vbCRLF +_ "C"+ vbCRLF +_ "F"+ vbCRLF ソース → vbslib.vbs テスト → T_Wildcard.vbs T_FindStringLines 関連 → SortLines コマンド → sort (DOS バッチファイル) → uniqバッチファイル Windows Script Programming (Web) → ソートされたファイルから重複した行を削除するには (Web) → ArrayFromLines *********************************************************************** <<< GetLeftEndOfLinePosition >>> *********************************************************************** GetLeftEndOfLinePosition Function GetLeftEndOfLinePosition( in_Text as string, in_PositionInText as integer ) 現在位置にある行の先頭の位置を返します。 【引数】 in_Text 全体の文字列 in_PositionInText 現在位置、先頭 = 1 返り値 現在位置にある行の先頭の位置 サンプル lines = _ "A"+ vbCRLF +_ "C"+ vbCRLF +_ "F"+ vbCRLF +_ "K" Assert GetPreviousLinePosition( lines, InStr( lines, "F" ) ) = InStr( lines, "F" ) Assert GetPreviousLinePosition( lines, InStr( lines, "F" ) + 1 ) = InStr( lines, "F" ) Assert GetPreviousLinePosition( lines, 1 ) = 1 ソース → vbslib.vbs テスト → T_Replace_target.vbs T_GetPreviousLinePosition 関連 → GetNextLinePosition → GetPreviousLinePosition *********************************************************************** <<< GetNextLinePosition >>> *********************************************************************** GetNextLinePosition Function GetNextLinePosition( in_Text as string, in_PositionInText as integer ) 1つ下の行の先頭の位置を返します。 【引数】 in_Text 全体の文字列 in_OverPositionInText 現在位置、先頭 = 1 返り値 1つ下の行の先頭の位置、0=下の行はない in_OverPositionInText 引数に行の途中の位置を指定したときは、その次の行の先頭を返します。 in_OverPositionInText 引数に、最終行の中のどこかを指定したときは、0 を返します。 in_Test の末尾が改行のとき、その改行の次の文字にある行は、最終行ではありません。 Line1(CR+LF) Line2(CR+LF) … Line2 が最終行 Line1(CR+LF) Line2 … Line2 が最終行 Line1(CR+LF) (CR+LF) … Line1の次の行が最終行 ソース → vbslib.vbs テスト → T_Replace_target.vbs T_GetPreviousLinePosition *********************************************************************** <<< GetPreviousLinePosition >>> *********************************************************************** GetPreviousLinePosition Function GetPreviousLinePosition( in_Text as string, in_OverPositionInText as integer ) 1つ上の行の先頭の位置を返します。 【引数】 in_Text 全体の文字列 in_OverPositionInText 現在位置、先頭 = 1 返り値 1つ上の行の先頭の位置 in_OverPositionInText 引数に行の途中の位置を指定したときは、その行の先頭を返します。 in_OverPositionInText 引数に 1 (先頭) を指定したときは、0 を返します。 サンプル lines = _ "A"+ vbCRLF +_ "C"+ vbCRLF +_ "F"+ vbCRLF +_ "K" Assert GetPreviousLinePosition( lines, InStr( lines, "F" ) ) = InStr( lines, "C" ) Assert GetPreviousLinePosition( lines, InStr( lines, "F" ) + 1 ) = InStr( lines, "F" ) Assert GetPreviousLinePosition( lines, 1 ) = 0 ソース → vbslib.vbs テスト → T_Replace_target.vbs T_GetPreviousLinePosition 関連 → FindStringLines *********************************************************************** <<< StringStream クラス >>> *********************************************************************** StringStream クラス 文字列を TextStream と同じようにアクセスします。 .SetString( Str as string ) 全体の文字列を設定し、ファイルポインタを先頭に戻す。 .ReadLine 1行入力します。 TextStream 互換 .AtEndOfStream すべて入力したかどうか。 TextStream 互換 全体を入力します。 TextStream 互換 .ReadAll 文字列を出力します。 TextStream 互換 .Write 1行を出力します。 TextStream 互換 .WriteLine .IsWithLineFeed リードする1行の末尾に改行コードを含める .ReadingLineFeed 改行文字。初期値は vbLF (LF or CR+LF)。 vbCRLF のときは、LF は行に含む .Line プロパティ 次にリードする行番号(1〜) サンプル 文字列からリードする Set file = new StringStream file.SetString "123" +vbCRLF+ "456" Do Until file.AtEndOfStream() echo file.ReadLine() ' 改行(vbCR+vbLF)は含まない Loop file = Empty サンプル 文字列へライトする Set file = new StringStream file.WriteLine "123" file.WriteLine "456" Assert file.ReadAll() = "123"+ vbCRLF +"456"+ vbCRLF file = Empty 改行文字は、vbLF でも構いません。 出力した文字列は、ReadAll で取得できます。 Write したものを先頭から Read するときは、ReadAll したものを SetString してください。 改行文字を維持するときは、IsWithLineFeed = True にして ReadLine → Write してください。 SplitLineAndCRLF を使えば、改行文字を分けることができます。 ソース → vbslib.vbs テスト → T_Replace_target.vbs T_StringStream 関連 → FindStringLines → ArrayFromLines → GetPreviousLinePosition *********************************************************************** <<< 関連 >>> *********************************************************************** 関連 → (CSV) ArrayFromCSV, ArrayFromCSV_Int CSV 形式の1行を配列に格納する。 → XmlAttr " " で囲む XML の属性値に変換します。 → OpenForReplace テキストファイルの内容を変更します。 → ファイル名・パス → IsWildcard → CutCRLF 改行文字を削除します。 → GetLineCount 行数をカウントします → StringStream クラス 文字列 TextStream → GetTextFromClipboard クリップボードから文字列を取得します → ToRegExpPattern 正規表現で使われるメタ文字も検索できるように変換します。 *********************************************************************** <<< 日付 (Date) >>> *********************************************************************** 日付 (Date) *********************************************************************** <<< TestableNow >>> *********************************************************************** TestableNow Function TestableNow() as Date テストに使える現在の日時です。 【引数】 返り値 現在の日時、または、 new_TestableNow の設定値 ソース → vbslib.vbs 関連 → Now 関数 → new_TestableNow *********************************************************************** <<< new_TestableNow >>> *********************************************************************** new_TestableNow Function new_TestableNow( a_Date as Date ) as TestableNowClass TestableNow が返す値を設定します。 【引数】 a_Date TestableNow が返す値 → Date 型 返り値 削除したときに、TestableNow が返す値を現在日時に戻すオブジェクト サンプル Set tn = new_TestableNow( DateSerial( 2014, 1, 1 ) ) echo TestableNow() tn = Empty ソース → vbslib.vbs *********************************************************************** <<< IsTimeOnlyDate >>> *********************************************************************** IsTimeOnlyDate (src) Function IsTimeOnlyDate( aDateTime as Date ) as boolean Date 型の値が、日付指定のない時刻だけの値であるかどうかを返します。 サンプル: IsTimeOnlyDate( CDate("2009/1/1") ) = False IsTimeOnlyDate( CDate("13:00") ) = True *********************************************************************** <<< DateAddStr >>> *********************************************************************** DateAddStr (src) Function DateAddStr( BaseDate as Date, Plus as string ) as Date 日付時刻の加減算をします。 サンプル d = DateAddStr( CDate("2009/1/1"), "+1month 10days" ) '// d = CDate("2009/2/11") t = DateAddStr( CDate("17:00"), "-8hours" ) '// t = CDate("9:00") t = DateAddStr( CDate("10:00"), "+1hours -5min" ) '// t = CDate("10:55") t = DateAddStr( CDate("10:00"), "-1hours -5min" ) '// t = CDate("8:55") t = DateAddStr( CDate("10:00"), "-1hours 5min" ) '// t = CDate("8:55") t = DateAddStr( CDate("10:00"), "-1hours +5min" ) '// t = CDate("9:05") t = DateAddStr( CDate("10:00"), "+2:30" ) '// t = CDate("12:30") t = DateAddStr( CDate("10:00"), "-2:30" ) '// t = CDate("7:30") Plus 引数 先頭は、"+" か "-" を指定します。 先頭の "+" か "-" を省略すると "+" になります。 先頭以外の "+" か "-" を省略すると、それまでの "+" か "-" を引き継ぎます。 時分は、00:00 形式で指定できます。 単位に指定できるキーワードは次のものがあります。 "year", "years", "month", "months", "day", "days" "hour", "hours", "minute", "minutes", "min", "second", "seconds", "sec" サンプル 日時でも、差分(1日前など)でもできる入力 echo "日時の例:2008/06/11, 14:28:01, -1day, -2hours" echo "Enter のみ:"+ limit_str_default limit_str = Input( "日時 >" ) If limit_str = "" Then limit_str = limit_str_default Select Case Left( limit_str, 1 ) Case "+", "-" : limit = DateAddStr( Now(), limit_str ) Case Else : limit = CDate( limit_str ) End Select テスト → T_Date.vbs # main 関連 → DateAdd (VBScript) → 時間の加減算 (clib) → MakeRule_compare *********************************************************************** <<< GetOldestDate >>> *********************************************************************** GetOldestDate (src) Function GetOldestDate() as Date Data 型の最も過去の値を返します。 *********************************************************************** <<< W3CDTF >>> *********************************************************************** W3CDTF (src) Function W3CDTF( SourceTimeDate as Date or string ) as string or Date 日時を文字列(W3C-DTF)に変換します。 または、その逆変換をします。 日時を引数に指定したら、文字列が返ります。 文字列を引数に指定したら、日時が返ります。 それ以外を指定したら、Empty が返ります。 サンプル 日本(UTC+9時間)の場合 W3CDTF( CDate( "2001/2/2 1:15" ) ) = "2001-02-02T01:15:00+09:00" W3CDTF( "2001-02-02T01:15:00+09:00" ) = CDate( "2001/02/02 1:15:00" ) W3CDTF( "2001-02-02T00:00:00Z" ) = CDate( "2001/02/12 9:00" ) テスト → T_Date.vbs # W3CDTF W3C-DTF, ISO8601 XML などで国際的に使える日時の表記法。 タイムゾーンを考慮している。 ISO 8601:1988 に基づく。 XML Schema の dateTime 型より厳密で単純。 W3Cの標準仕様ではない。 0000 YYYY 0000-00 YYYY-MM 0000-00-00 YYYY-MM-DD 0000-00-00T00:00+00:00 YYYY-MM-DDThh:mmTZD 0000-00-00T00:00:00+00:00 YYYY-MM-DDThh:mm:ssTZD 0000-00-00T00:00:00.0+00:00 YYYY-MM-DDThh:mm:ss.sTZD 年月日時分秒が 1桁のときは 01 のように 0 をつけること。 年は4桁。小数部は何桁でもよい。 時刻(hh:mm:ss)は、現地の時刻を記述する。 TZD(タイムゾーン, TimeZoneDesignator ) は、"Z", "+00:00", "-00:00" のいずれか。 W3C-DTF の文字列は、ファイル名に使うことができません。 : を ; に置き換えてください。 *********************************************************************** <<< CDateFromEMailDate >>> *********************************************************************** CDateFromEMailDate Function CDateFromEMailDate( DateString as string ) as Date e-mail (MIME) 形式の日付を、VBScript の Date 型に変換します。 【引数】 DateString e-mail (MIME) 形式の日付 返り値 日付 サンプル a_date = CDateFromEMailDate( "Date: Fri, 25 Oct 2013 22:07:30 +0900" ) Assert W3CDTF( a_date ) = "2013-10-25T22:07:30+09:00" ソース → vbslib.vbs テスト → T_Date.vbs T_EMailDate 関連 → MIME *********************************************************************** <<< GetMonthNumberFromString >>> *********************************************************************** GetMonthNumberFromString Function GetMonthNumberFromString( MonthStr as string ) as integer 3文字からなる月の英語表記を、月の数字に変換します。 【引数】 MonthStr 3文字からなる月の英語表記 返り値 月の数字 サンプル Assert GetMonthNumberFromString( "Jan" ) = 1 ソース → vbslib.vbs テスト → T_Date.vbs T_GetMonthNumberFromString *********************************************************************** <<< ConvertTimeZone >>> *********************************************************************** ConvertTimeZone (src) Function ConvertTimeZone( DateTime as Date or string, FromTZD as string, ToTZD as string ) as Date or string タイムゾーンを変更した時刻を返します。 【引数】 DateTime 変更前の時刻。 Date 型、または W3C-DTF 形式の文字列 FromTZD 変更前のタイムゾーン、または Empty → TimeZoneDesignator ToTZD 変更後のタイムゾーン、または Empty 返り値 変更後の時刻。 DateTime 引数と同じ型(Date型または文字列) DateTime に W3C-DTF を指定するときは、FromTZD は Empty または、DateTime に指定した タイムゾーンと同じタイムゾーンを指定できます。 DateTime に Date 型を指定するときに、FromTZD を Empty にすると、現在 OS に設定されている タイムゾーンを指定したことと同じになります。 ToTZD に Empty にすると、現在 OS に設定されているタイムゾーンを指定したことと同じになります。 サンプル ConvertTimeZone( "2002-02-02T11:02:02+09:00", "+09:00", "Z" ) = "2002-02-02T02:02:02Z" ConvertTimeZone( CDate("2:02"), "Z", "+9:00" ) = CDate("11:02") テスト → T_Date.vbs # ConvertTimeZone *********************************************************************** <<< TimeZoneDesignator >>> *********************************************************************** TimeZoneDesignator (src) Function TimeZoneDesignator( MinuteBias as integer ) as string W3C-DTF のタイムゾーンの部分の文字列を返します。 【引数】 MinuteBias 時差。単位は分。 Empty = OS に設定されているタイムゾーン 返り値 W3C-DTF のタイムゾーンの部分 サンプル TimeZoneDesignator( 540 ) = "+09:00" TimeZoneDesignator( Empty ) = "+09:00" '// 日本の場合 テスト → T_Date.vbs # TimeZoneDesignator *********************************************************************** <<< MinusTZD >>> *********************************************************************** MinusTZD (src) Minus Time Zone Disignator Function MinusTZD( MinuteBias as integer ) as string W3C-DTF のタイムゾーンの部分の文字列をマイナスにして返します。 【引数】 MinuteBias 時差。単位は分。 Empty = OS に設定されているタイムゾーン 返り値 W3C-DTF のタイムゾーンの部分のマイナス サンプル MinusTZD( 540 ) = "-09:00" MinusTZD( Empty ) = "-09:00" '// 日本の場合 テスト → T_Date.vbs # MinusTZD *********************************************************************** <<< BenchStart >>> *********************************************************************** BenchStart (src) Sub BenchStart() 全体の処理時間の計測を開始します。 ファイル: vbslib.vbs サンプル Sub Main() BenchStart Bench 1 '// セクション1の計測区間 Bench 2 '// セクション2の計測区間 Bench 0 '// 計測対象外 BenchEnd '// 表示 Pause End Sub 計測結果の表示例 Benchmark Result: Sampling Count = 3 Elapsed Time = 0.022(sec) Max is Section 1 Section 1: 1times 0.012(sec) Section 2: 1times 0.010(sec) サンプル BenchStart For Each x In Items Bench 1 '// セクション1の計測区間 Bench 2 '// セクション2の計測区間 Bench 0 Next BenchEnd Pause 計測結果の表示例 Benchmark Result: Sampling Count = 1401 Elapsed Time = 0.151(sec) Max is Section 2 Section 1: 3times 0.032(sec) Section 2: 3times 0.102(sec) 参考 → 性能のボトルネックを検出できる vbslib 4 - livedoor Blog(ブログ) (Web) テスト → T_Date.vbs # T_Bench *********************************************************************** <<< Bench >>> *********************************************************************** Bench (src) Sub Bench( SectionNum as integer ) セクション(全体の中の一部の区間)の処理時間の計測を開始します。 【引数】 SectionNum セクションの識別番号 ファイル: vbslib.vbs 計測するセクションの開始位置に、SectionNum に1以上の値を指定して、Bench を呼び出してください。 計測するセクションの終了位置に、SectionNum に0を指定して、Bench を呼び出してください。 計測するセクションの終了位置が、次のセクションの開始位置であるときは、SectionNum に0を指定 しなくても、次のセクションの識別番号を指定できます。 参考 → BenchStart *********************************************************************** <<< BenchEnd >>> *********************************************************************** BenchEnd (src) Sub BenchEnd() 全体の処理時間の計測を終了し、計測結果を表示します。 ファイル: vbslib.vbs 参考 → BenchStart *********************************************************************** <<< ProgressTimer (g_VBS_Lib) >>> *********************************************************************** ProgressTimer (g_VBS_Lib) Dim g_VBS_Lib.ProgressTimer as g_VBS_Lib_ProgressTimerClass 進捗状況を表示するオブジェクト。 グローバルに1つだけ存在します。 サンプル 12回のループの進捗を 100ミリ秒ごとに表示する場合 Set pr_timer = g_VBS_Lib.ProgressTimer pr_timer.Start Empty, 12, 100, "" Do Until pr_timer.Count >= pr_timer.MaxCount Sleep 50 '// Do Anything pr_timer.Plus +1, Empty Loop pr_timer.End_ "" Start サンプル 表示のタイミングだけ見る場合 Set pr_timer = g_VBS_Lib.ProgressTimer pr_timer.Interval_msec = 100 Do If pr_timer.GetShouldShow() Then _ echo_v "7/20" Loop データ構造 Interval_msec 表示の更新間隔(ミリ秒)。 小さすぎると遅くなります。 デフォルトは、1000 ミリ秒。 Count カウント値。 0以上 .MaxCount 以下。 MaxCount カウント値の最大値。、 ShowFormat 表示のフォーマット。 以下の変数を指定できます。 ${Percent} .Count × 100 ÷ .MaxCount ${Count} .Count の値 ${MaxCount} .MaxCount の値 ${Text} Start、End_、Plus、Show メソッドの in_Text 引数 デフォルト: " ${Percent}% ${Count}/${MaxCount} ${Text}" ソース → vbslib.vbs テスト → T_Date.vbs T_ProgressTimer *********************************************************************** <<< Start (g_VBS_Lib.ProgressTimer) >>> *********************************************************************** Start (g_VBS_Lib.ProgressTimer) Sub g_VBS_Lib_ProgressTimerClass::Start( in_ShowFormat as string, _ in_MaxCount as integer, in_Interval_msec as integer, in_Text as string ) 進捗状況を表示を開始します。 【引数】 in_ShowFormat ShowFormat プロパティ に設定する値 in_MaxCount MaxCount プロパティ に設定する値 in_Interval_msec Interval_msec プロパティ に設定する値 in_Text ShowFormat プロパティ の ${Text} から置き換える文字列 in_Text に Empty を指定したときは、開始したすぐには表示をしません。 *********************************************************************** <<< End_ (g_VBS_Lib.ProgressTimer) >>> *********************************************************************** End_ (g_VBS_Lib.ProgressTimer) Sub g_VBS_Lib_ProgressTimerClass::End_( in_Text as string ) 表示するタイミングではないときにカウント値が最大値になったときのために、表示します。 【引数】 in_Text ShowFormat プロパティ の ${Text} から置き換える文字列 in_Text に Empty を指定したときは、表示を更新しません。 Start 〜 End_ は、ネストすることができます。 最も外側の Start 〜 End_ 以外は、何もしません。 *********************************************************************** <<< Plus (g_VBS_Lib.ProgressTimer) >>> *********************************************************************** Plus (g_VBS_Lib.ProgressTimer) Sub g_VBS_Lib_ProgressTimerClass::Plus( in_PlusCount as integer, in_Text as string ) 進捗状況のカウント値をプラスして、表示するタイミングだったら、表示内容を変更します。 【引数】 in_PlusCount カウント値をプラスする値 in_Text ShowFormat プロパティ の ${Text} から置き換える文字列 *********************************************************************** <<< GetShouldShow (g_VBS_Lib.ProgressTimer) >>> *********************************************************************** GetShouldShow (g_VBS_Lib.ProgressTimer) Function g_VBS_Lib_ProgressTimerClass::GetShouldShow() as boolean 表示するタイミングかどうかを返します。 *********************************************************************** <<< メモ >>> *********************************************************************** メモ Reset メソッドは廃止。 ネストできないため。 *********************************************************************** <<< IsSame >>> *********************************************************************** IsSame Function IsSame( Left, Right ) as boolean = とほぼ同じですが、Empty, Null と "" を比較しても False を返します。 ソース → vbslib.vbs テスト → T_Arr.vbs T_IsSame *********************************************************************** <<< Add >>> *********************************************************************** Add Function Add( Operand1 as type1, Operand2 as type1 ) as type1 加算します。 type1 は、以下の型を指定できます。 ・ + 演算子が使える型(数値型、文字列型) ・配列型 ソース → vbslib.vbs テスト → T_Arr.vbs T_AddArray *********************************************************************** <<< CalculateVariables >>> *********************************************************************** CalculateVariables (src) Function CalculateVariables( Formula as string, Variables as dictionary ) as variant 文字列で表現された計算式を計算します。 【引数】 Formula 計算式。 VBScript の文法で表現したもの Variables 計算式で使える変数の集合 返り値 計算結果 ファイル: vbslib.vbs 計算式に、Variables 引数に指定した変数を使うことができます。 変数の値は、数値だけでなく、文字列やオブジェクトも指定できます。 サンプル Set vars = CreateObject( "Scripting.Dictionary" ) vars.Item( "a" ) = 2 Assert CalculateVariables( "a + 3", vars ) = 5 "a + 3" 変数の値が文字列型であっても、数値として計算します。 変数の値が他の変数の参照にすることもできます。 Set vars = CreateObject( "Scripting.Dictionary" ) vars.Item( "a" ) = 2 vars.Item( "b" ) = "3" vars.Item( "c" ) = "b" Assert CalculateVariables( "a + b + c", vars ) = 8 テスト → T_Calc.vbs # [T_Calc] 関連 → Eval → Execute *********************************************************************** <<< NestPos クラス >>> *********************************************************************** NestPos クラス (src) 処理順序におけるネスト(入れ子)の位置をカウント・アップします。 Set pos = new NestPos '// pos.PosArr = Array( 0 ) pos.Start '// pos.PosArr = Array( 1, 0 ) pos.End_ '// pos.PosArr = Array( 1 ) pos.Start '// pos.PosArr = Array( 2, 0 ) pos.Start '// pos.PosArr = Array( 2, 1, 0 ) pos.End_ '// pos.PosArr = Array( 2, 1 ) pos.End_ '// pos.PosArr = Array( 2 ) .PosArr Dim NestPos::PosArr as Array of integer 現在のネストの位置。 配列番号は、ネストの深さに対応します。 .Start Sub NestPos::Start() ブロックの開始。 カウント・アップして、配列の要素を1つ増やします。 .End_ Sub NestPos::End_() ブロックの終了。 配列の要素を1つ減らします。 *********************************************************************** <<< オブジェクト >>> *********************************************************************** オブジェクト → LetSet オブジェクトかどうかによって、Out = In_ または Set Out = In_ をします。 → get_Object 静的オブジェクト (または演算器的なオブジェクト) を取得します。 → get_ObjectFromFile スクリプトファイルをインクルードして、静的オブジェクトを取得します。 → get_ObjectsFromFile 静的オブジェクト・スクリプトファイルをすべて取得して一覧できるようにします。 → new_X 文字列で指定した名前のクラスのオブジェクトを生成します。 → include_objs 静的オブジェクト・スクリプトファイルをインクルードします。 → get_DefineInfoObject 単純な DefineInfo オブジェクトを生成します。 → get_NameDelegator 指定のインターフェースを持った、静的な一般名オブジェクトを取得します。 → new_ObjectFromStream ストリームから、オブジェクトを1つ生成します。 → new_ObjectsFromStream ストリームから、オブジェクトをいくつか生成して、配列に格納します。 → NameOnlyClass Name 変数と、Delegate 変数の対応関係を表すクラスです。 → LifeGroupClass 相互参照しているオブジェクトのライフサイクルを管理します。 → DefaultFunction 何もしないコールバック関数の本体。 → EventRespondersClass イベントが発生したらコールバックされる関数の集合。 *********************************************************************** <<< LetSet >>> *********************************************************************** LetSet Sub LetSet( Out as variant, In_ as variant ) In_ がオブジェクトかどうかによって、Out = In_ または Set Out = In_ をします。 サンプル: LetSet v, dic("name") '// Set "v" 実装: If IsObject( In_ ) Then Set Out = In_ Else Out = In_ 一般に、LetSet を呼び出すより、IsObject で判定(上記のコード)を記述した方が高速ですが、 In_ に関数や Dictionary::Item などの重い処理を記述するときは、その重い処理を 2度実行させないLetSet の方が高速です。 Out 引数にオブジェクトのプロパティを指定しないでください。 設定されません。 なぜなら、プロパティを引数に指定すると、値渡しになるからです。 ソース → vbs_inc_sub.vbs テスト → T_Var.vbs T_LetSet 関連 → LetSetWithBracket 代入先が配列、または、辞書のとき → GetDicItem 代入元が辞書のとき *********************************************************************** <<< LetSetWithBracket >>> *********************************************************************** LetSetWithBracket Sub LetSetWithBracket( out_Collection as variant, in_Index as variant, in_Item as variant ) 配列、または、辞書の要素に登録します。 【引数】 out_Collection (入出力) 配列 または 辞書、( ) で要素にアクセスできるコレクション in_Index 配列番号 または 辞書のキー in_Item 配列 または 辞書に追加する値 (オブジェクト または 非オブジェクト) 配列、または、辞書に代入するときの LetSet です。 → GetDicItem 下記のどちらかのコードに相当します。 out_Collection( in_Index ) = in_Item Set out_Collection( in_Index ) = in_Item サンプル LetSetWithBracket dic, "key", 1 ソース → vbs_inc_sub.vbs テスト → T_Var.vbs T_LetSet 関連 → Dic_addElem → GetDicItem *********************************************************************** <<< get_Object >>> *********************************************************************** get_Object (src) Function get_Object( Name as string ) as Object 静的オブジェクト (または演算器的なオブジェクト) を取得します。 【引数】 Name 取得するオブジェクトのクラス名 返り値 オブジェクト Name が動的に変わることがないときは、get_ClassA 関数を直接呼び出して ください。 静的オブジェクトが無ければ、エラーになります。 サンプル: Dim name : name = "ClassA" Dim obj : Set obj = get_Object( name ) Name が変数ではないときは、直接 get_ClassA を呼び出すことができます。 Dim obj : Set obj = get_ClassA() new でオブジェクトを生成すると、get_ClassA で取得できるオブジェクトと別の インスタンスになります。 get_Object は、機能的には、"get_" + Name の関数を呼び出すだけなので、 別途関数を用意する必要があります。 たとえば、Name = "ClassA" なら、get_ClassA の関数が呼ばれます。 Dim g_ClassA Function get_ClassA() '// has_interface_of ClassI If IsEmpty( g_ClassA ) Then _ Set g_ClassA = new ClassA : ErrCheck Set get_ClassA = g_ClassA End Function ClassA ClassA ClassI ClassA ClassA ClassA ClassA ClassA 関連 → get_ClassA, get_Object : 静的オブジェクト、演算器要求 テスト → T_GetObject.vbs [T_IncludeObjs1] *********************************************************************** <<< get_ObjectFromFile >>> *********************************************************************** get_ObjectFromFile (src) Function get_ObjectFromFile( ModulePath as string, Name as string ) as Object スクリプトファイルをインクルードして、静的オブジェクトを取得します。 【引数】 ModulePath スクリプトファイルのパス Name 取得するオブジェクトのクラス名 返り値 取得したオブジェクト サンプル: SampleLib.vbs ファイルで定義されている Sample オブジェクトを取得する。 Dim m : Set m = get_ObjectFromFile( "Lib\SampleLib.vbs", "Sample" ) 上記サンプルは、下記と同じです。 include "Lib\SampleLib.vbs" Dim m : Set m = get_Sample() オブジェクトを取得する部分は、機能的には、"get_" + Name の関数を呼び出すだけなので、 スクリプトファイルの中で、別途関数を定義する必要があります。 参考 → get_Object テスト → T_GetObject.vbs get_ObjectFromFile [T_NewModule] *********************************************************************** <<< get_ObjectsFromFile >>> *********************************************************************** get_ObjectsFromFile (src) Sub get_ObjectsFromFile( GetFuncs as string or Array of Function, InterfaceName as string, out_Objs as Array of Object ) 静的オブジェクト・スクリプトファイルをすべて取得して一覧できるようにします。 【引数】 GetFuncs スクリプトのパス、または include_objs の out_GetFuncs InterfaceName Empty または、取得するオブジェクトが持つインターフェース out_Objs 取得したオブジェクトの配列 サンプル: インクルードと同時に、静的オブジェクトを取得する get_ObjectsFromFile "Lib\*_obj.vbs", "ClassI", m_Objs '// [out] m_Objs サンプル: インクルードした後で、静的オブジェクトを取得する(ファイルを走査しない) include_objs "Lib\*_obj.vbs", Empty, m_CreateFuncs '// [out] m_CreateFuncs get_ObjectsFromFile m_CreateFuncs, "ClassI", m_Objs '// [out] m_Objs 静的オブジェクトを一覧できるようにするには、それぞれのスクリプトで、get_StaticObjects 関数を定義する必要があります。 get_ObjectsFromFile や include_objs は、別のスクリプト ファイルであれば、同じ関数名でも異なる関数インスタンスになります。 Sub get_StaticObjects( InterfaceName, out_Obj ) If IsEmpty( InterfaceName ) or InterfaceName = "ClassI" Then Set out_Obj = get_ClassA() ElseIf InterfaceName = "ClassI2" Then out_Obj = Array( get_ClassA(), get_ClassB() ) End If End Sub 参考 → get_StaticObjects : 静的オブジェクト テスト → T_GetObject.vbs [T_IncludeObjs2] [T_IncludeObjs3] *********************************************************************** <<< new_X >>> *********************************************************************** new_X (src) Function new_X( Name as string ) as object 文字列で指定した名前のクラスのオブジェクトを生成します。 ただし、多くの場合、get_Object の方が適していることが多いので、get_Object を使うことを検討 してください。 → get_Object サンプル: Dim obj : Set obj = new_X( "ClassA" ) 機能的には、"new_" + Name の関数を呼び出すだけなので、別途関数を用意する必要があります。 たとえば、Name = "ClassA" なら、new_ClassA の関数が呼ばれます。 引数は、なしにしてください。 Function new_ClassA() Set new_ClassA = new ClassA End Function 参考 → 名前参照 (vbsool) *********************************************************************** <<< include_objs >>> *********************************************************************** include_objs (src) Sub include_objs( Wildcard as string, Flags as Empty, out_GetFuncs as Array of Funcion ) 静的オブジェクト・スクリプトファイルをインクルードします。 【引数】 Wildcard スクリプトファイルのパス、またはフォルダパス Flags Empty を指定してください out_GetFuncs Empty、または、静的オブジェクトを取得する関数の集合 Flags = Empty かつ out_GetFuncs = Empty なら、include で代用できます。 out_GetFuncs は、静的オブジェクトを取得する関数の集合です。 get_ObjectsFromFile の第1引数 に渡すと、文字列を渡したときより高速に処理します。 include_objs は、インクルードのみ行います。 オブジェクトの生成は、new で生成するか、 get_ObjectsFromFile で行います。 サンプル: Lib フォルダをインクルードして、その中で定義された ClassA オブジェクトを生成する。 include_objs "Lib\*_obj.vbs", Empty, Empty Set obj : Set obj = new ClassA : ErrCheck out_CreateFuncs が Empty ではないときのサンプル → new_X_array 関連 → include テスト → T_GetObject.vbs [T_IncludeObjs1c] → T_GetObject.vbs [T_IncludeObjs3] → T_GetObject.vbs [T_IncludeObjsMulti] → T_GetObject.vbs [T_IncludeObjsMulti_NoWild] → T_GetObject.vbs [T_IncludeObjsEmptyArray] *********************************************************************** <<< get_DefineInfoObject >>> *********************************************************************** get_DefineInfoObject (src) Sub get_DefineInfoObject( in_out_Object as DefineInfoClass, FullPath as string ) 単純な DefineInfo オブジェクトを生成します。 DefineInfo オブジェクトに FullPath プロパティしか必要ないときのみ使えます。 他のプロパティがあるときは、 → DefineInfo プロパティ (vbsool) サンプル: Dim g_SrcPath If IsEmpty( g_SrcPath ) Then MsgBox "This is vbslib object file." : WScript.Quit Dim g_Sample_vbs : get_DefineInfoObject g_Sample_vbs, g_SrcPath '// g_Sample_vbs.FullPath g_SrcPath 参考 → DefineInfo プロパティ (vbsool) *********************************************************************** <<< get_NameDelegator >>> *********************************************************************** get_NameDelegator (src) Function get_NameDelegator( Name as string, TrueName as string, InterfaceName as string ) as InterfaceName_Delegator 指定のインターフェースを持った、正式名オブジェクトに委譲する、静的な一般名オブジェクトを取得します。 【引数】 Name 一般名。 取得するオブジェクトの Name プロパティ TrueName 正式名。 取得するオブジェクトの委譲先 (*1) InterfaceName 一般名オブジェクトと正式名〜が共通に持つ、インターフェースの名前 (*2) 返り値 一般名オブジェクト (*3) 返り値となる一般名オブジェクトは、Name プロパティと委譲元となるオブジェクトの実体の違いを除けば、 同じ1つの正式名オブジェクトとして扱うことができます。 参考: 下記の図の「ある1つのインスタンス」 get_NameDelegator 関数は、 ものです。 get_NameDelegator 関数は、get_(一般名) 関数の内部からのみ呼ばれるようにしてください。 get_Object 関数 の内部で呼ばれる get_(一般名) 関数の実装を支援する (*1) (InterfaceName) インターフェースを持った、静的な正式名オブジェクトを取得することができる get_(TrueName) 関数が定義されていること。 参考:get_Object (*2) NameDelegator インターフェース と、(InterfaceName) インターフェースを持ったインスタンス (ここでは一般名オブジェクト)を生成することができる、new_(InterfaceName)_Delegator 関数が定義されていること。 参考:new_X (*3) Name と TrueName の組み合わせが初めてのときは、get_NameDelegator の内部で、 new_(InterfaceName)_Delegator 関数を呼び出して、オブジェクトを生成します。 返り値となるオブジェクトにアクセスすると、Name プロパティとオブジェクトの実体の違いを除けば、 正式名オブジェクトにアクセスします。 サンプル: Function get_GeneralObject() Set get_GeneralObject = get_NameDelegator( "GeneralObject", "TrueName", "InterfaceName" ) End Function Function get_TrueName() : ... : End Function Function new_InterfaceName_Delegator() : ... : End Function 一般名と正式名の関係は、1対多、または、多対1があります。 ClassA Name = "ClassN", TrueName = "ClassA" ClassI 一般名で選択 ClassB Name = "ClassN", TrueName = "ClassB" ClassI 参照 → オブジェクトの Name と TrueName Name 以外は 委譲 参照 場面Aの関数 場面Aでの Name ある1つのインスタンス 場面Bの関数 場面Bでの Name TrueName (正式名) ClassI ClassI_Delegator クラス (一般名) 参照 → 名前参照、Name と TrueName が多対1の場合 NameDelegator インターフェース Class NameDelegator '// defined_as_interface Public Name Public Property Get TrueName() : TrueName = NameDelegator_getTrueName( Me ) : End Property Public m_Delegate ' as ClassA or ClassB or string(before validated) Public Property Get DefineInfo() : Set DefineInfo = m_Delegate.DefineInfo : End Property End Class Const F_ValidateOnlyDelegate = &h40000000 Dim g_bNeedValidateDelegate Function NameDelegator_getTrueName( m ) Sub NameDelegator_validate( m, Flags ) Function NameDelegator_getXML( m ) Public Property Get DefineInfo() : Set DefineInfo = m_Delegate.DefineInfo : End Property DefineInfo プロパティは、オプションです。 → DefineInfo プロパティ テスト → T_NameDelegator_vbslib フォルダ *********************************************************************** <<< new_ObjectFromStream >>> *********************************************************************** new_ObjectFromStream (src) Sub new_ObjectFromStream( out_Obj as object, ClassName as string, Stream as variant ) ストリームから、オブジェクトを1つ生成します。 【引数】 out_Obj (出力) ストリームから生成した1つのオブジェクト、または Empty ClassName 生成するオブジェクトのクラス名 (下記) Stream XML ストリーム (下記) new_X に対応した関数の準備 内部で、new_X を呼び出しています。 new_X を使うのに必要な関数を用意する必要が あります。 たとえば、ABC クラスなら、new_ABC 関数が必要です。 参考 → new_X ClassName 引数 XML のタグ名がクラス名に対応します。 XML のタグの中の属性まで一致するデータを元にオブジェクトを生成するときは、 XPath と同様に下記のようにします。 VBScript コード Set xml = LoadXML( "Sample.xml", Empty ) new_ObjectFromStream obj, "ClassA[@attr='value']", xml XMLデータ 参考 → XPath の [@name='value'] (属性の値) Stream 引数 ChangeToXml の引数に指定できるものを指定できます。 テスト → T_ObjectFromStream フォルダ *********************************************************************** <<< new_ObjectsFromStream >>> *********************************************************************** new_ObjectsFromStream (src) Sub new_ObjectsFromStream( out_Objs as array of object, ClassName as string, Stream as variant ) ストリームから、オブジェクトをいくつか生成して、配列に格納します。 【引数】 out_Objs (出力) ストリームから生成したオブジェクトが入った配列 ClassName 生成するオブジェクトのクラス名 Stream XML ストリーム 1つもオブジェクトを生成しなかったときでも、out_Objs には配列が格納されます。 ClassName, Stream については、 → new_ObjectFromStream テスト → T_ObjectFromStream フォルダ *********************************************************************** <<< NameOnlyClass >>> *********************************************************************** NameOnlyClass (src) Class NameOnlyClass Public Name Public Delegate End Class Name 変数(任意の型の識別値)と、Delegate 変数(指しているオブジェクトなど)の 対応関係を表すクラスです。 Delegate 変数を使わずに、Name だけのオブジェクトとして使うこともできます。 xml プロパティ に対応しています。 関連 → ArrayToNameOnlyClassArray → JoinedClass *********************************************************************** <<< new_NameOnlyClass >>> *********************************************************************** new_NameOnlyClass (src) Function new_NameOnlyClass( in_Name as string, in_Delegate as variant ) as NameOnlyClass NameOnlyClass のオブジェクトを生成します。 *********************************************************************** <<< JoinedClass >>> *********************************************************************** JoinedClass (src) Class JoinedClass Public Left Public Right End Class Left 変数の値と Right 変数の値の対応関係を表すクラスです。 関連 → ArrayClass 配列番号 0 と 1 で対応関係を表すことができます → NameOnlyClass → PointerPairClass (clib) → pair - cpprefjp - C++ Library Reference (Web) *********************************************************************** <<< new_JoinedClass >>> *********************************************************************** new_JoinedClass Function new_JoinedClass( Left as variant, Right as variant ) as JoinedClass JoinedClass のオブジェクトを生成します。 【引数】 Left 生成するオブジェクトの Left プロパティに設定する値 Right 生成するオブジェクトの Right プロパティに設定する値 返り値 生成された JoinedClass のオブジェクト → JoinedClass ソース → vbslib.vbs *********************************************************************** <<< g_ObjectIDs >>> *********************************************************************** g_ObjectIDs オブジェクトに数値の ID を割り当て、ID からオブジェクトが取得できるようにします。 相互参照しているときの Class_Terminate が期待通りに動作するようになります。 .Add 新規 ID を取得します .Remove ID を返却します .Item 渡された ID に対応するオブジェクトを返します Add できる最大数、同時に存在できる ID の数は 0x7FFE です。 同時に存在できる ID の数を超えて、Remove と Add を繰り返すと、返却された ID を再利用します。 同じオブジェクトに複数の ID が割り当てられる状況になっても、エラーにはなりません。 サンプル Element メンバー SampleRootClass SampleElementClass RootObjectID メンバー (g_ObjectIDs 経由) Set root = new SampleRootClass Set element = new SampleElementClass '// Link element.RootObjectID = root.ObjectID Set root.Element = element '// Call a method element.Method Class SampleRootClass Public ObjectID Public Element Private Sub Class_Initialize() Me.ObjectID = g_ObjectIDs.Add( Me ) End Sub Private Sub Class_Terminate() g_ObjectIDs.Remove Me.ObjectID End Sub End Class Class SampleElementClass Public RootObjectID Public Sub Method() Set root = g_ObjectIDs( Me.RootObjectID ) End Sub End Class g_ObjectIDs g_ObjectIDs g_ObjectIDs ソース → vbslib.vbs 関連 → ObjectSetClass *********************************************************************** <<< LifeGroupClass >>> *********************************************************************** LifeGroupClass 相互参照しているオブジェクトに対して、適切に Class_Terminate が呼ばれるようにします。 A B 相互参照 注意 メンバー変数やメソッドにアクセスするときは、メンバー変数 p を介する必要があります。 root.p.Member → グループのルートの使用サンプル 辞書 のキーや配列番号で参照することで、相互参照が原因で Class_Terminate が呼ばれなく なる状況を回避することができます。 → g_ObjectIDs オブジェクトの Set A B 辞書のキーや配列番号 参考 → 相互参照しているときの Class_Terminate → ガーベージコレクション (GC) 一般に、関数が終了したときにオブジェクトを参照している変数がなくなると、ガーベージコレクター によって Class_Terminate が呼ばれますが、相互参照していると Class_Terminate は呼ばれません。 プログラム終了時に呼ばれます。 LifeGroupClass は、相互参照しているオブジェクトでも Class_Terminate が呼び出されるようにします。 内部で相互参照するグループに LifeGroupClass を使うと下記の図のような構成になります。 グループに所属しているオブジェクトの Class_Terminate が呼び出されるタイミングは、 グループに所属しているオブジェクト(ルート オブジェクトも含む)を参照するすべてのハンドルが、 すべてのユーザーの変数から参照されなくなったときです。 ( ) の中の数字は、削除される順番です。 (1) と (3)、(2) と (4)、(5) と (7) の順番は入れ替わることがあります。 (1) だけが削除されたときは、(3)が削除されるまで、(4)以降のオブジェクトは残ります。 (1) (3) ユーザーの変数 ユーザーの変数 (2) (4) ハンドル(ルートへ) ハンドル(ルート以外へ) as LifeHandleClass p p (6) LifeGroup DestroyReferences (5) (7) 所属オブジェクト(ルート) 所属オブジェクト(ルート以外) → グループのメンバーの生成 → グループのルートの生成 相互参照 所属オブジェクトのメンバー変数やメソッドにアクセスするときは、ハンドルのメンバー変数 p を 介する必要があります。 このように相互参照しているオブジェクトとハンドルのオブジェクトを分けることで、 参照している変数がなくなったことをハンドルで検出できるようにしています。 ソース → vbslib.vbs テスト → T_Dic.vbs T_LifeGroupClass 関連 → g_ObjectIDs オブジェクト ID を経由することで Class_Terminate を呼び出す → DestroyerClass p を介する必要がないが、多少手間がかかるライフサイクル管理 *********************************************************************** <<< グループのルートの生成 (LifeGroupClass) >>> *********************************************************************** グループのルートの生成 (LifeGroupClass) << LifeGroupClass 相互参照しているオブジェクトのグループのうち、最初に生成するオブジェクトのハンドルの クラスは、下記のように定義します。 RootBodyClass を最初に生成するオブジェクトのクラス名 に変更すること以外は、そのままにしてください。 グループのルート(下記の RootClass)は、 LifeHandleClass と同じメンバーを持ちます。 使用サンプル Set root = new RootClass root.p.Member p … p の追加が必要 メンバー変数やメソッドにアクセスするときは、メンバー変数 p を介する必要があります。 相互参照しているオブジェクトを使用するコードに、この変更を要求することがどうしても できないなら、p を介すだけのメソッドやプロパティを定義します。 定義サンプル Class RootClass Public p '// as RootBodyClass : Target object of this handle Private Sub Class_Initialize() Set group = new LifeGroupClass group.AddHandle Me, new RootBodyClass End Sub Private Sub Class_Terminate() If not IsEmpty( Me.p.LifeGroup.Group ) Then _ Me.p.LifeGroup.Group.AddTerminated Me.p End Sub End Class RootClass LifeGroupClass AddHandle RootBodyClass 最初に生成するオブジェクトのクラスは、メンバー変数 LifeGroup と、 DestroyReferences メソッド を定義してください。 Class RootBodyClass : Public LifeGroup '// Don't write except for LifeGroupClass ■追加 Public Sub DestroyReferences() '// ■追加 Me.Reference = Empty End Sub End Class RootBodyClass DestroyReferences Reference *********************************************************************** <<< グループに所属するオブジェクトの生成 (LifeGroupClass) >>> *********************************************************************** グループに所属するオブジェクトの生成 (LifeGroupClass) << LifeGroupClass 相互参照しているオブジェクトのグループに所属するオブジェクトのメソッドから、グループに 所属させるオブジェクトを新しく生成するときは、下記の CreateMember メソッドのように、 グループに追加します。 そうしなければ、グループが削除されるタイミングで、生成した オブジェクトに対して DestroyReferences が呼ばれなくなります。 CreateMember メソッドの返り値は、 LifeHandleClass です。 使用サンプル Set root = new RootClass Set member = root.p.CreateMember() 定義サンプル Class RootBodyClass : Public LifeGroup '// Don't write except for LifeGroupClass Function CreateMember() Set CreateMember = Me.LifeGroup.Group.Add( new MemberClass ) : End Function End Class Add MemberClass すぐに CreateMember の返り値を参照しなくなっても、DestroyReferences がすぐに呼ば れることはありません。 グループに所属するすべてのオブジェクトが参照されなくなった ときに呼び出されます。 ルートのハンドルが参照されなくなったときに、グループに所属する一部のオブジェクトが 削除されても構わないときは、ハンドルの代わりに生成したオブジェクトを返しても構いま せん。 定義サンプル グループに所属するオブジェクトのクラスは、メンバー変数 LifeGroup と、 DestroyReferences メソッド を定義してください。 Class MemberClass : Public LifeGroup '// Don't write except for LifeGroupClass ■追加 Public Sub DestroyReferences() '// ■追加 Me.Reference = Empty End Sub End Class MemberClass *********************************************************************** <<< グループに所属するオブジェクトの出力 (LifeGroupClass) >>> *********************************************************************** グループに所属するオブジェクトの出力 (LifeGroupClass) 相互参照しているオブジェクトを出力するときは、下記の SearchMember メソッドのように、 Add (LifeGroupClass) を呼び出し、 LifeHandleClass を生成して返してください。 そうしなければ、ルートのハンドルが削除されるタイミングで、グループに所属する一部の オブジェクトが削除されてしまいます。 ルートのハンドルが参照されなくなったら、グループ に所属する一部のオブジェクトが削除されても構わないときは、LifeHandleClass を生成 しなくても構いません。 ただし、グループの中で参照するときは、LifeHandleClass を生成しないでください。 使用サンプル Set root = new RootClass Set member = root.p.GetReference() 定義サンプル Class RootBodyClass : Public LifeGroup '// Don't write except for LifeGroupClass Function GetReference() Set GetReference = Me.LifeGroup.Group.Add( Me.Reference ) End Function End Class GetReference *********************************************************************** <<< DestroyReferences メソッド >>> *********************************************************************** DestroyReferences メソッド << LifeGroupClass Sub (グループのに所属するオブジェクトのクラス)::DestroyReferences() 相互参照を切ります。 グループのユーザーは、本メソッドを直接呼び出さないでください。 AddTerminated (LifeGroupClass) から呼ばれます。 Class_Terminate メソッド(デストラクター)が呼び出されて、オブジェクトが 破棄されるように、相互参照を切ってください。 つまり、相互に参照している 関係にあるメンバー変数に Empty や Nothing を代入してください。 定義サンプル Class RootBodyClass : Function DestroyReferences() Me.Member = Empty End Function End Class *********************************************************************** <<< LifeHandleClass >>> *********************************************************************** LifeHandleClass << LifeGroupClass LifeGroupClass (グループ)に所属する、相互参照しているオブジェクトを参照できるハンドル。 オブジェクトのメンバー変数やメソッドにアクセスするときは、メンバー変数 p を介する必要が あります。 LifeHandleClass が参照している、相互参照しているオブジェクトを、グループの外にある変数 に直接格納しないでください。 もしそうしてしまうと、すべてのハンドルへの参照が無くなったときに、 相互参照が切れたオブジェクトになり、正しく動作しなくなります。 サンプル Set root = new RootClass Set member = root.p.CreateMember() '// member as LifeHandleClass member.p.Method 生成 → グループのルートの生成 → グループのメンバーの生成 メンバー → p 相互参照しているオブジェクトを参照します。 → Class_Terminate AddTerminated (LifeGroupClass) を呼び出します。 *********************************************************************** <<< p (LifeHandleClass) >>> *********************************************************************** p (LifeHandleClass) << LifeHandleClass Dim LifeHandleClass::p as Object グループに所属している相互参照しているオブジェクトを参照します。 オブジェクトのメンバー変数やメソッドにアクセスするときは、ハンドルのメンバー変数 p を 介する必要があります。 このように相互参照しているオブジェクトとハンドルのオブジェクトを 分けることで、参照している変数がなくなったことをハンドルで検出できるようにしています。 参考 → LifeGroupClass *********************************************************************** <<< Class_Terminate (LifeHandleClass) >>> *********************************************************************** Class_Terminate (LifeHandleClass) << LifeHandleClass Sub LifeHandleClass::Class_Terminate() ハンドルが参照されなくなったときに、 AddTerminated (LifeGroupClass) を呼び出します。 *********************************************************************** <<< LifeGroupClass のメンバー >>> *********************************************************************** LifeGroupClass のメンバー << LifeGroupClass → AddHandle オブジェクトをグループに追加し、ハンドルからオブジェクトを参照できるようにします → Add オブジェクトをグループに追加して、そのオブジェクトを参照するハンドルを生成します オブジェクトをグループから除外します → Remove ハンドルから参照されるカウンターを減らし、必要なら相互参照を切ります → AddTerminated *********************************************************************** <<< AddHandle (LifeGroupClass) >>> *********************************************************************** AddHandle (LifeGroupClass) << LifeGroupClass のメンバー Sub LifeGroupClass::AddHandle( Handle as Object, Object as Object ) オブジェクトをグループに追加し、ハンドルからオブジェクトを参照できるようにします。 【引数】 Handle (ルートの)ハンドル Object ハンドルが参照しようとしているオブジェクト *********************************************************************** <<< Add (LifeGroupClass) >>> *********************************************************************** Add (LifeGroupClass) << LifeGroupClass のメンバー Function LifeGroupClass::Add( Object as Object ) as LifeHandleClass オブジェクトをグループに追加して、そのオブジェクトを参照するハンドルを生成して返します。 【引数】 Object ハンドルが参照しようとしているオブジェクト 返り値 生成されたハンドル *********************************************************************** <<< Remove (LifeGroupClass) >>> *********************************************************************** Remove (LifeGroupClass) << LifeGroupClass のメンバー Sub LifeGroupClass::Remove( Object as Object ) オブジェクトをグループから除外します。 【引数】 Object ハンドルが参照しているオブジェクト *********************************************************************** <<< AddTerminated (LifeGroupClass) >>> *********************************************************************** AddTerminated (LifeGroupClass) << LifeGroupClass のメンバー Sub LifeGroupClass::AddTerminated( Object as Object ) ハンドルから参照されるカウンターを減らし、必要なら相互参照を切ります。 【引数】 Object 参照されなくなったハンドルが参照しているオブジェクト グループのユーザーは、本メソッドを直接呼び出さないでください。 LifeHandleClass の Class_Terminate から呼ばれます。 相互参照を切ることで、グループに所属するすべてのオブジェクトが削除されます。 自分(Me)も削除されます。 グループに所属するオブジェクトを参照するハンドルが他にもあるときは、 Object を参照しているハンドルだけが削除され、Object は残ります。 参考 → LifeGroupClass *********************************************************************** <<< DestroyerClass >>> *********************************************************************** DestroyerClass 注意 DestroyerClass の代わりに LifeGroupClass の使用を推奨します。 相互参照しているオブジェクトを削除するタイミングを制御するオブジェクト。 DestroyerClass のオブジェクトが削除されるときに、相互参照を切るメソッド DestroyReferences を呼び出し、相互参照していたオブジェクトの Class_Terminate が呼び出されます。 Destroyer A B 相互参照を切る 関数が終了したときにオブジェクトを参照している変数がなくなると、ガーベージコレクターによって Class_Terminate が呼ばれますが、相互参照していると Class_Terminate は呼ばれません。 プログラム終了時に呼ばれます。 DestroyerClass は、相互参照しているオブジェクトでも Class_Terminate が呼ばれるようにします。 参考 → 相互参照しているときの Class_Terminate → ガーベージコレクション (GC) 相互参照するクラスは、相互参照を切る DestroyReferences メソッドと、DestroyerClass に 登録されると True になる IsDestroyer 属性(プロパティ)を実装してください。 下記サンプルの MutualClass を参照。 サンプル Case1 WScript.echo "End of Main" Case2 WScript.echo "End of Main" WScript.echo "もし、ここ以降でデストラクターが動くときは、"+_ "プログラム終了時にすべてのオブジェクトを削除する"+_ "ことによるデストラクター呼び出しです。" Sub Case1() WScript.echo vbCRLF +"Case1:" Set destroyer = new DestroyerClass Set a_object = new MutualClass : a_object.Name = "a" : destroyer.Add a_object Set b_object = new MutualClass : b_object.Name = "b" : destroyer.Add b_object Set a_object.Reference = b_object Set b_object.Reference = a_object End Sub Sub Case2() WScript.echo vbCRLF +"Case2:" Set destroyer = new DestroyerClass Set a_object = new MutualClass : a_object.Name = "a" Set b_object = new MutualClass : b_object.Name = "b" Set a_object.Reference = b_object Set b_object.Reference = a_object End Sub Class MutualClass Public Name Public Reference Public IsDestroyer '// ■追加 Private Sub Class_Terminate() WScript.echo Me.Name +".Class_Terminate" CheckUnderDestroyer Me '// ■追加 End Sub Public Sub DestroyReferences() '// ■追加 Me.Reference = Empty End Sub End Class DestroyerClass Add CheckUnderDestroyer 表示例: Case1: Case1: a.Class_Terminate Case1: b.Class_Terminate Case2: End of Main もし、ここ以降でデストラクターが動くときは、プログラム終了時にすべての オブジェクトを削除することによるデストラクター呼び出しです。 Case2: a.Class_Terminate Case2: b.Class_Terminate ソース → vbslib.vbs テスト → T_Dic.vbs T_DestroyerClass 関連 → LifeGroupClass *********************************************************************** <<< Add (DestroyerClass) >>> *********************************************************************** Add (DestroyerClass) << DestroyerClass Sub DestroyerClass::Add( Object as variant ) 相互参照するオブジェクトを登録します。 【引数】 Object 登録するオブジェクト 本関数は、Object の IsDestroyer 属性(プロパティ)を True に設定します。 DestroyerClass が削除されるタイミングで、Object の DestroyReferences メソッドが 呼ばれます。 *********************************************************************** <<< Remove (DestroyerClass) >>> *********************************************************************** Remove (DestroyerClass) << DestroyerClass Sub DestroyerClass::Remove( Object as variant ) 登録から除外します。 【引数】 Object 除外するオブジェクト DestroyerClass が削除されるときよりも早く削除するオブジェクトを指定してください。 本関数は、Object の IsDestroyer 属性(プロパティ)を False に設定します。 *********************************************************************** <<< CheckUnderDestroyer >>> *********************************************************************** CheckUnderDestroyer Sub CheckUnderDestroyer( Object as variant ) Destroyer によって管理されていなければ、エラーにします。 *********************************************************************** <<< DefaultFunction >>> *********************************************************************** DefaultFunction Sub DefaultFunction( Argument1 as variant ) 何もしないコールバック関数の本体。 【引数】 Argument1 第1引数(無視します) ソース → vbslib.vbs 参考 → GetRef *********************************************************************** <<< EventRespondersClass >>> *********************************************************************** EventRespondersClass イベントが発生したらコールバックされる関数の集合。 イベント関数を呼び出すオブジェクトのプロパティに、本クラスのオブジェクトを設定します。 .Add イベントが発生したときにコールバックされる関数を登録します。 .Remove コールバックされる関数を登録解除します。 .Calls イベントが発生したときに、登録されているコールバック関数を呼び出します。 ソース → vbslib.vbs テスト → T_Item_vbslib フォルダ 未対応 参考 → EventResponders : イベント応答 (vbsool) 書きかけ *********************************************************************** <<< Add (EventResponders) >>> *********************************************************************** Add (EventResponders) EventResponders クラス Sub EventResponders::Add( Func as EventFunction, Responder as variant, Priority as integer ) イベントが発生したときにコールバックされる関数を登録します。 【引数】 Func コールバックされる関数 → EventFunction Responder イベントに応答するオブジェクト Priority 優先度 サンプル caller_object.OnEventX.Add GetRef( "ResponderClass_OnEventX" ), Me, 1000 Priority 引数 1000 が標準。 EventResponders のオブジェクトに登録した複数のコールバックのうち、 Priority が小さいものから先にコールバックされます。 参考 → コールバックされるメソッドを、メンバー変数に登録する (vbslib) ソース → vbslib.vbs *********************************************************************** <<< EventFunction >>> *********************************************************************** EventFunction Sub EventFunctionSample( Responder as variant, Caller as variant, Args as variant ) イベント関数。 イベントが発生したらコールバックされる関数の型。 【引数】 Responder イベントに応答するオブジェクト Caller イベントが発生したオブジェクト Args イベントのパラメーター(イベントの内容による) *********************************************************************** <<< Remove (EventResponders) >>> *********************************************************************** Remove (EventResponders) EventResponders クラス Sub EventResponders::Remove( Responder as variant ) コールバックされる関数を登録解除します。 【引数】 Responder イベントに応答するオブジェクト サンプル caller_object.OnEventX.Remove Me ソース → vbslib.vbs *********************************************************************** <<< Calls (EventResponders) >>> *********************************************************************** Calls (EventResponders) EventResponders クラス Sub EventResponders::Calls( Caller as variant, Args as variant ) イベントが発生したときに使い、登録されているコールバック関数を全て呼び出します。 【引数】 Caller イベントが発生したオブジェクト Args イベントのパラメーター(イベントの内容による) サンプル: Me.OnEventX.Calls Me, Empty ソース → vbslib.vbs 参考 → イベントが発生したら、登録されているメソッドを呼び出す (vbsool) *********************************************************************** <<< その他 >>> *********************************************************************** その他 → ErrCheck Class_Initialize でエラーが発生してもエラーが発生しない問題に対応します。 *********************************************************************** <<< CreateGuid >>> *********************************************************************** CreateGuid (src) Function CreateGuid() as string GUID を生成します。 返り値の例: 2D7E3038-E395-460A-86CC-C8AB3C3D5D54 グローバル変数 g_TestModeFlags に、F_NotRandom を設定すると、 テスト・プログラム用に 00000000-0000-0000-0000-000000000000 から順番に +1 された値が返ります。 g_TypeLib = 0 にすると、再び 1 から順番に値を返します。 *********************************************************************** <<< KeyClass >>> *********************************************************************** KeyClass 以前登録した特定のオブジェクトかどうかを判定します。 KeyClass から特定のオブジェクトを取得することはできないので、グローバルスコープに、 KeyClass オブジェクトを置いても、特定のオブジェクトへの参照を複製することから守ります。 Function KeyClass::SetKey( Key as object ) as object キーとなるオブジェクトを登録します。 一度しか登録できません。 返り値は、Key です。 Function KeyClass::IsSame( Key as object ) as boolean 以前登録したキーと同じかどうかを判定します。 サンプル: Dim g_AppKey Dim AppKey : Set AppKey = new KeyClass ' for Ident only Set g_AppKey = new KeyClass : g_AppKey.SetKey( AppKey ) If not g_AppKey.IsSame( AppKey ) Then Err.Raise 1,,"Invalied AppKey" 参考 → NewWritable (AppKeyClass) *********************************************************************** <<< 関連 >>> *********************************************************************** 関連 → (CSV) ArrayFromCSV, ArrayFromCSV_Int → ArrayFromCmdLine → (XML) LoadXML → 数値演算、論理演算、ビット演算 → 日付、時間 → 文字列 → クラス (VBScript) → FinObj クラス (Finallyブロック) → Dictionary クラス (ハッシュ、Scripting.Dictionary) → 変数、Empty、型、配列 → BinaryArray クラス → オプション引数、ビットフラグ *********************************************************************** <<< ファイル操作 >>> *********************************************************************** ファイル操作 ファイルを操作する主な関数を下に一覧します。 すべての関数は、左のツリーを展開してください。 参考 → ファイル名、パス (Windows) コマンドプロンプト準拠関数 cd カレントフォルダを移動します。 copy src から dst にファイルまたはフォルダをコピーします。 move src から dst にファイルまたはフォルダを移動します。 unzip 圧縮(zip)ファイルを解凍します。 ren ファイル名を変更します。 del ファイルまたはフォルダを削除します。 mkdir フォルダを作成します。 exist フォルダまたはファイルが存在するかどうかを返します。 fc ファイル、またはフォルダが同一かどうかを比較します。 grep テキストファイルの中で、指定したキーワードを含む行を返します。 type_ テキストファイルの内容を表示します。 vbslib オリジナル関数 CreateFile 指定のテキストを内容とした、テキストファイルを作成します。 Out of Writable 警告 スクリプトが想定していない場所にライトしたときの警告 NewWritable 書き込み可能なフォルダの設定オブジェクトを生成します。 Writables::Enable 書き込み可能なフォルダを設定します。 SetWritableMode 書き込み可能でない場所にライトしたときの動きを設定します。 OpenForRead テキストファイルを開きます。(リード用) OpenForWrite テキストファイルを開きます。(ライト用) OpenForReplace テキストファイルの内容を変更します。 GetFullPath フル・パスを返します。 GetStepPath 相対パスを返します。 GetTempPath テンポラリ・フォルダの中のパスを返します。 ExpandWildcard ワイルドカードを展開します。 サブ・フォルダーも検索します。 EnumFolderObjectDic サブフォルダのオブジェクトを高速に辞書に列挙します。 SetBreakByFName 指定した名前のファイルをライトするときにブレークさせます。 IsWriteAccessDenied 負荷が高いときに発生する書き込み拒否エラーに対処します。 バイナリ混在テキスト 一部がバイナリになっているテキストファイルを作成します。 ArrayFromCSV CSV 形式の1行を解析して、配列に格納します。 LoadXML XML ファイル、または XML 形式の文字列を読み込みます。 g_fs FileSystemObject を参照するグローバル変数です。 他にもあります。左のツリーから選択してください。 テスト → ファイル操作のテスト *********************************************************************** <<< cd >>> *********************************************************************** cd (src) Sub cd( Path as string ) カレント・フォルダーを変更します。 【引数】 Path 新しいカレント・フォルダーのパス ファイル: vbslib.vbs 参考 → パスの記述方法、相対パス、フル・パス、カレントフォルダー → ファイル名、パス (Windows) main 関数、または main2 関数を呼ばれたときのカレント・フォルダーは、プロセス起動時 のカレント・フォルダーではなく、メイン.vbs ファイルがあるフォルダーになります。 メイン.vbs ファイルがあるフォルダーからの相対パスを指定するときは、cd 関数を呼び 出す必要はありません。 (この仕様は、vbslib4 から) サンプル cd "FolderA" t = ReadFile( "File.txt" ) "FolderA" カレント・フォルダーの中にある FolderA フォルダーに、カレント・フォルダー を変更します。 File.txt は、FolderA フォルダーにあるファイルになります。 サンプル cd g_start_in_path g_start_in_path 現在のカレント・フォルダーを、プロセス起動時のカレント・フォルダーに 変更します。 存在しないフォルダを指定すると、E_WIN32_FILE_NOT_FOUND エラーになります。 ファイルのパスを指定すると、E_WIN32_DIRECTORY エラーになります。 テスト → T_cd_do.vbs # cd 関連 → CurDirStack → pushd → popd → CurrentDirectory (Shell) → ReplaceFileNameWildcard *********************************************************************** <<< CurDirStack >>> *********************************************************************** CurDirStack (src) オブジェクトが破棄されるタイミングで、カレント・フォルダーを元に戻すオブジェクトです。 下記の場合、関数 funcA から返ると、CurDirStack オブジェクトのデストラクタで、関数に 入ったときのカレント・フォルダーに戻ります。 ファイル: vbslib.vbs サンプル Sub funcA() Dim ds_:Set ds_= new CurDirStack cd "sub" End Sub '// 元のフォルダに戻る テスト → T_cd_do.vbs # CurDirStack 関連 → cd *********************************************************************** <<< pushd >>> *********************************************************************** pushd (src) Sub pushd( dir as string ) カレントフォルダを移動します。 ただし、popd で戻れるようにします。 ファイル: vbslib.vbs サンプル pushd "FolderA" popd '// 元のフォルダに戻る テスト → T_cd_do.vbs # pushd 関連 → popd → CurDirStack *********************************************************************** <<< popd >>> *********************************************************************** popd (src) Sub popd() カレントフォルダを pushd する前に戻します。 ファイル: vbslib.vbs サンプル pushd "FolderA" popd '// 元のフォルダに戻る テスト → T_cd_do.vbs # popd 関連 → pushd *********************************************************************** <<< cd_UpperCaseDrive >>> *********************************************************************** cd_UpperCaseDrive Sub cd_UpperCaseDrive() カレント・フォルダーのドライブの文字を大文字に変更します。 サンプル cd "c:\Folder" cd_UpperCaseDrive Assert g_sh.CurrentDirectory = "C:\Folder" ソース → vbslib.vbs [cd_UpperCaseDrive] テスト → T_cd_do.vbs # [T_cd_UpperCaseDrive] *********************************************************************** <<< copy >>> *********************************************************************** copy Sub copy( SrcPath as string, DstFolderPath as string ) SrcPath のファイルまたはフォルダを、DstFolderPath フォルダーの中にコピーします。 【引数】 SrcPath コピー元のファイルパス、またはフォルダーパス DstFolderPath コピー先のフォルダーパス (ファイルパスは不可) → copy_ren ファイル: vbslib.vbs 参考 → ファイル名、パス (Windows) → Out of Writable 警告 [E_OutOfWritable] サンプル src フォルダーを dst フォルダーの中にコピーします copy "src", "dst" copy "src\*", "dst" src\* src フォルダーの内容を dst フォルダーの中にコピーします 注意 vbslib ver3 の copy やコマンドプロンプトの copy と動きが異なる場合があります。(下記) コピー先にファイルがあっても、上書き確認をユーザーに行わずに、上書きします。 ユーザーには、上書きするフォルダーやファイルのバックアップをとるようにガイドしてください。 フォルダーをコピーするとき、SrcPath のフォルダーと DstFolderPath のフォルダーを全く同じ ファイル構成にしたいときは、DstFolderPath のフォルダーを削除してからコピーしてください。 そうしなければ、DstFolderPath の中にあるファイルと同じ場所にあるファイルが SrcPath の 中にに無くても、そのファイルは無くならないためです。 これは、エクスプローラーなどの一般的 なファイラーの動きと同じです。 Src Dst Dst FileA.txt FileB.txt FileA.txt FileB.txt コピー元のフォルダー コピーする前のコピー先 コピーした後のコピー先 vbslib ver3 との違い vbslib3 の copy の DstFolderPath に指定したパスがフォルダーではないときは、ファイル名を 変える動きでしたが、vbslib4 の copy では、必ず DstFolderPath の新規フォルダーを作成して、 その中へコピーします。 これは、エクスプローラーなどの一般的なファイラーの動きと同じです。 コピーと同時にファイル名を変える時は、copy_ren を使ってください。 仕様を変更した理由は、copy する前の DstFolderPath がフォルダーであるかないかによって、 コピー先が変わらないようにするためです。 (あるかないかを判定する If 文が不要になります) vbslib3 で作成したスクリプトをそのまま動かすと、DstFolderPath にファイルパスを指定した copy は、指定したファイル名と同じ名前のフォルダの中にコピーするようになります。 しかし、 そのまま、実行を続けても、開こうとするファイルがフォルダーであるため開けない、というエラー でブレークするため、大きな問題にはならないでしょう。 また、ファイルには一般に拡張子が 付いているので、vbslib3 で作成した copy を vbslib4 で動かすと、拡張子が付いたフォルダー が作られます。拡張子が付いたフォルダーがあれば、copy の移植を検討してください。 vbslib3 の仕様に戻したいときは、下記のように設定してから copy を呼び出してください。 g_Vers("CopyTargetIsFileOrFolder") = 1 エラー E_FileNotExist SrcPath に指定したファイルが見つからない E_WriteAccessDenied DstFolderPath がロックされているか、ファイルが存在する サンプル copy 関数は、ファイルやフォルダの有無によって動きが変わらないようにするため、コマンド プロンプトの copy や FileSystemObject の CopyFile 関数と、若干動きが異なります。 しかし、エクスプローラーなどの一般的なファイラーの動きと同じです。 SrcPath 引数 DstFolderPath 引数 動作 a.txt ファイル C:\dst_folder a.txt を dst_folder にコピーします (dst_folderがフォルダのとき) C:\dst_folder\a.txt a.txt フォルダーを作成して、その中に a.txt を コピーします aa フォルダー C:\dst_folder フォルダ aa を dst_folder の中にコピーします C:\dst_folder\aa フォルダ aa を作成して、aa フォルダの中に aa フォルダをコピーします C:\dst_folder\bb フォルダ bb を作成して、bb フォルダの中に aa フォルダをコピーします ワイルドカード C:\dst_folder ファイルとフォルダを dst_folder にコピーします C:\dst_folder\bb フォルダ bb を作成して、その中へファイルと フォルダをコピーします。 参考 → ファイルコピーの引数 (FileSystemObject の場合) ソース → vbslib.vbs → vbslib_mini.vbs テスト → T_Copy.vbs # [T_Copy] → [T_Writable] 関連 → copy_ren → copy_ex → move → CreateShortcut (Shell) *********************************************************************** <<< copy_ren >>> *********************************************************************** copy_ren (src) Sub copy_ren( SrcPath as string, DstPath as string ) ファイルまたはフォルダーの名前を変えてコピーします。 (copy and rename) 【引数】 SrcPath コピー元のファイル、または、フォルダーのパス DstPath コピー先のファイル、または、フォルダーのパス ファイル: vbslib.vbs SrcPath がファイルなら、DstPath に指定したパスもファイルにしてください。 SrcPath がフォルダーなら、DstPath に指定したパスもフォルダーにしてください。 コピー先にファイルがあっても、上書き確認をユーザーに行わずに、上書きします。 ユーザーには、上書きするフォルダーやファイルのバックアップをとるようにガイド してください。 フォルダーをコピーするとき、SrcPath のフォルダーと DstPath のフォルダーを 全く同じファイル構成にしたいときは、DstPath のフォルダーを削除してからコピー してください。 参考 → copy の注意 サンプル copy_ren "src", "dst" src フォルダーの内容を dst フォルダーの中にコピーします。 または、src ファイルの内容を、dst ファイルの中にコピーします。 サンプル copy_ren "src", "dst" copy "src\*", "dst" 上記の2行は、同じ処理です。 src フォルダーの内容を dst フォルダーの中にコピーします。 テスト → T_Copy.vbs # [T_Copy] 関連 → copy *********************************************************************** <<< copy_ex >>> *********************************************************************** copy_ex (src) Sub copy_ex( SrcPath as string, DstPath as string, Option_ as integer ) Option_ に指定したように、特殊なコピーをします。 【引数】 SrcPath コピー元のパス。 ワイルドカードが使えます DstPath コピー先のフォルダーのパス Option_ 特殊なコピーの内容 ファイル: vbslib.vbs 参考 → Option_ = c.CutTag のとき (タグをカットするコピー) → Option_ = c.ExistOnly のとき (存在するファイルのみコピー) → Option_ = c.NotExistOnly のとき (存在しないファイルのみコピー) → Option_ = c.MakeShortcutFiles のとき (ショートカットを作成する) Option_ = c.CutTag のとき (タグをカットするコピー) SrcPath に指定したワイルドカード以外の部分をカットしたファイル名になるようにコピーします。 サブフォルダにあるファイルもコピーします。 複数のファイルが入ったフォルダが複数あって、それらを上書きコピーして合成したフォルダから、 元の1つのフォルダを取り出すようなコピーができます。 Dim c : Set c = g_VBS_Lib copy_ex "src\*_set1.*", "dst", c.CutTag _set1 src フォルダーにある _set1. を名前に含むファイルを、dst フォルダーにコピーします。 ただし、ファイル名の一部にある _set1 はカットされます。 src フォルダ dst フォルダ file1_set1.txt file1.txt file1_set2.txt file2_set1.txt file2.txt file2_set2.txt テスト → T_CopyEx.vbs T_CopyTagFiles Option_ = c.ExistOnly のとき (存在するファイルのみコピー) コピー先に同じ名前のファイルがあるファイルだけ、コピーします。 Set c = g_VBS_Lib copy_ex "src\*", "dst", c.ExistOnly src フォルダ dst フォルダ file1.txt file1.txt file2.txt file3.txt file3.txt file4.txt file1.txt と file3.txt だけコピーします。 テスト → T_CopyEx.vbs T_CopyExists 関連 → CopyOnlyExist コマンド Option_ = c.NotExistOnly のとき (存在しないファイルのみコピー) コピー先に同じ名前のファイルや空フォルダーがないファイルだけ、コピーします。 Set c = g_VBS_Lib copy_ex "src\*", "dst", c.NotExistOnly src フォルダ dst フォルダ file1.txt file1.txt file2.txt file3.txt file3.txt file4.txt EmptyFolder file2.txt と file4.txt と EmptyFolder だけコピーします。 テスト → T_CopyEx.vbs T_CopyNotExists Option_ = c.MakeShortcutFiles のとき (ショートカットを作成する) コピー先にコピー元のそれぞれのファイルへのショートカットを作成します。 Set c = g_VBS_Lib copy_ex "src\*", "dst", c.MakeShortcutFiles src フォルダ dst フォルダ (新規作成) file1.txt file1.lnk file2.txt file2.lnk sub\file1.txt sub\file1.lnk テスト → T_CopyEx.vbs T_MakeShortcutFiles 関連 → copy *********************************************************************** <<< OpenPickUpCopy >>> *********************************************************************** OpenPickUpCopy Function OpenPickUpCopy( in_PathWithID as string ) as OpenPickUpCopyClass OpenPickUpCopyClass コピーするフォルダーの一部がどこかの情報が書かれた XML を開きます。 【引数】 in_PathWithID PickUpCopies XML ファイルのパス、または、それと、# と、XML の id 属性 返り値 コピーするフォルダーの一部がどこかの情報が入ったオブジェクト コピーは上書きコピーを行います。 コピー先にすでにあるファイルが不要なら、削除した後で コピーしてください。 in_PathWithID 引数に FilePathClass を指定することもできます。 その場合、最初の PickUpCopy タグ の内容が使われます。 サンプル OpenPickUpCopy( "PickUpCopy.xml" ).Copy "Folder1", "OutputFolder", Empty "PickUpCopy.xml" "Folder1", "OutputFolder" PickUpCopy.xml ファイルに書かれた設定に従って、Folder1 フォルダーの一部から OutputFolder フォルダーへコピーします。 OpenPickUpCopy 関数が返した OpenPickUpCopyClass のオブジェクトの Copyメソッド を呼び出しています。 参考 → PickUpCopy コマンド 設定ファイル PickUpCopy.xml の説明 サンプル PickUpCopies.xml Example Variable タグ で定義した ${ } 変数は、path, default_source_path, default_destination_path 属性から参照できます。 default_source_path, default_destination_path 属性は、 の引数に Empty を指定したときに使われます。 Copy メソッド(OpenPickUpCopyClass) PickUpCopies タグの名前は変更できます。 path 属性に ${RegExp( ... )} を記述すれば、 正規表現 で複数のファイルを指定できます。 スクリプト Set copy_ = OpenPickUpCopy( "PickUpCopies.xml#Example" ) Set w_= AppKey.NewWritable( copy_.GetDefaultOutputPath( Empty ) ).Enable() copy_.Copy Empty, Empty, Empty "PickUpCopies.xml#Example" #Example を指定すると、id 属性の値が Example の PickUpCopy タグの 設定を使います。 #以下を指定しなければ、最初の PickUpCopy タグの 設定を使います。 コールツリー OpenPickUpCopy (.vbs) OpenPickUpCopyClass::Copy (.vbs) new_PathDictionaryClass_fromXML (.vbs) new_PathDictionaryClass_fromXML_Ex (.vbs) LazyDictionaryClass::Item (.vbs) LazyDictionaryClass::Me_Expand (.vbs) LazyDictionaryClass::Me_Call (.vbs) PathDictionaryClass_onRegExp (.vbs) // 正規表現を展開する。 PathDictionaryClass::LeafPaths (.vbs) PathDictionaryClass::Scan (.vbs) '// ソート「ファイル > \ あり * > \ なし * (拡張子のデフォルト) > フォルダー」 ExpandWildcard (.vbs) // ファイルを一覧する。 copy_ren // コピーする。 テスト → T_Wildcard.vbs T_PathDictionary_XML_PickUpCopy → PickUpCopy1.xml *********************************************************************** <<< OpenPickUpCopyClass >>> *********************************************************************** OpenPickUpCopyClass OpenPickUpCopy の返り値のクラス。 *********************************************************************** <<< Copy (OpenPickUpCopyClass) >>> *********************************************************************** Copy (OpenPickUpCopyClass) << OpenPickUpCopyClass Sub OpenPickUpCopyClass::Copy( in_SourcePath as string, in_DestinationPath as string, in_Empty as Empty ) XML に指定したファイルまたはフォルダーをコピーします。 【引数】 in_SourcePath コピー元の基準フォルダーのパス、または、Empty in_DestinationPath コピー先の基準フォルダーのパス、または、Empty in_Empty Empty を指定してください in_SourcePath 引数に Empty を指定したときは、XML の default_source_path 属性に指定したパス が使われます。 in_DestinationPath 引数に Empty を指定したときは、XML の default_destination_path 属性に指定 したパスが使われます。 *********************************************************************** <<< GetDefaultSourcePath (OpenPickUpCopyClass) >>> *********************************************************************** GetDefaultSourcePath (OpenPickUpCopyClass) << OpenPickUpCopyClass Function GetDefaultSourcePath() as string コピー元の基準フォルダーのパスを返します。 Copy メソッド の in_SourcePath 引数に Empty を指定したときの、コピー元の基準 フォルダーのパスを返します。 フル パスが返ります。 XML の default_source_path 属性に指定した ${ } 変数が展開された値が返ります。 *********************************************************************** <<< GetDefaultDestinationPath (OpenPickUpCopyClass) >>> *********************************************************************** GetDefaultDestinationPath (OpenPickUpCopyClass) << OpenPickUpCopyClass Function GetDefaultDestinationPath( in_SourcePath as string ) as string コピー先の基準フォルダーのパスを返します。 【引数】 in_SourcePath コピー元の基準フォルダーのパス、または、Empty 返り値 コピー先の基準フォルダーのパス Copy メソッド の in_DestinationPath 引数に Empty を指定したときの、コピー先の基準 フォルダーのパスを返します。 フル パスが返ります。 XML の default_destination_path 属性に指定した ${ } 変数が展開された値が返ります。 XML の default_destination_path 属性に指定した ${SourceFolderName} は、 コピー元の基準フォルダーのパスに展開された値が返ります。 *********************************************************************** <<< CopyWindowClass >>> *********************************************************************** CopyWindowClass 進捗ウィンドウを表示しながらファイルをコピーします。 複数のファイルを並行してコピーします。 サンプル Set copies = new CopyWindowClass copies.CopyAndRenameStart "large-1.bin", "_work\large-1-copy.bin" copies.CopyAndRenameStart "large-2.bin", "_work\large-2-copy.bin" copies.WaitUntilCompletion CopyAndRenameStart WaitUntilCompletion ソース → Network.vbs → CopyWithProcessDialog.vbs テスト → T_CopyEx.vbs T_CopyWindowClass 参考 → Folder::CopyHere *********************************************************************** <<< CopyAndRenameStart (CopyWindowClass) >>> *********************************************************************** CopyAndRenameStart (CopyWindowClass) << CopyWindowClass Sub CopyWindowClass::CopyAndRenameStart( in_SourceFilePath as string, in_DestinationFilePath as string ) ファイルのコピーを開始します。 【引数】 in_SourceFilePath コピー元のファイルのパス in_DestinationFilePath コピー先のファイルのパス コピーを開始したらすぐに関数から返ります。 連続して呼び出すと、並行してコピーを行います。 スクリプトを中断しても、コピーは継続します。 進捗ウィンドウの中断ボタンを押してください。 再起動したスクリプト(プロセス)で同じコピーをする前に中断してください。 コピー中かどうかは、下記のパスにファイルやフォルダーが存在するかどうかで判断する ことができます。 in_DestinationFilePath in_DestinationFilePath +".updating" コピー前 なし、またはファイルが存在 なし、またはフォルダーが存在 コピー中 なし、またはファイルが存在 フォルダーが存在 コピー完了 ファイルが存在 なし コピー前かどうかを判断するときは、 DestinationFullPath (CopyWindowClass) にあるかどうかで判断できます。 なければ前です。 中断された後で CopyWindowClass を 生成した後のコピー前でも同じ方法で判断できます。 なぜ、コピー中のフォルダー名に ".updating" があるのかの理由は、 NewWritable (AppKeyClass) する必要がないからです。 テンポラリ フォルダー にしない理由は、テンポラリ フォルダー があるドライブと異なるドライブに in_DestinationFilePath が指定されても in_DestinationFilePath にコピーしたファイルを移動できる(高速で処理できる)からです。 *********************************************************************** <<< WaitUntilCompletion (CopyWindowClass) >>> *********************************************************************** WaitUntilCompletion (CopyWindowClass) << CopyWindowClass Sub CopyWindowClass::WaitUntilCompletion() コピーが完了するまで待ちます。 デストラクターからも呼ばれます。 *********************************************************************** <<< DestinationFullPath (CopyWindowClass) >>> *********************************************************************** DestinationFullPath (CopyWindowClass) << CopyWindowClass Dim CopyWindowClass::Processes(i).DestinationFullPath as string コピー中、または、コピーしたファイルのパス。 ローカルのパス。 Wait を呼び出した後は、CopyWindowClass::Processes 配列の要素は無くなります。 *********************************************************************** <<< cat >>> *********************************************************************** cat (src) Sub cat( FilePathss as string or array of string, OutputPath as string ) テキスト・ファイルの内容を連結します。 【引数】 FilePathss ファイルのパスの配列 OutputPath 連結した内容を格納するファイルのパス ファイル: vbslib.vbs サンプル log.txt ファイルの内容に out.txt ファイルの内容を追加します。 cat Array( "log.txt", "plus.txt" ), "log.txt" "log.txt", "plus.txt" "log.txt" 実行前の log.txt plus.txt 実行後の log.txt 123 456 ABC DEF 123 456 ABC DEF + = サンプル プログラムの出力を out に追加します。 Dim out, out1 : out = "log.txt" : out1 = "log1.txt" del out r= RunProg( "...", out1 ) cat Array( out, out1 ), out del out1 out, out1 out 参考 → cat コマンド(Linux) テスト → T_fc.vbs # [test_in_file] *********************************************************************** <<< CopyNotOverwriteFileClass >>> *********************************************************************** CopyNotOverwriteFileClass (src) フォルダーをコピーします。 ただし、コピー先のファイルが前回コピーした内容と異なるファイルはコピーしないで、 SyncFilesMenu メニューに一覧します。 メニューを閉じるまで、Copy メソッドから戻りません。 コピー先にのみ存在するファイルは、存在し続けます。 サンプル Set o = new CopyNotOverwriteFileClass o.SourcePath = "work\Source" o.DestinationPath = "work\Destination" o.SynchronizedPath = "work\Synchronized" o.Copy Copy の代わりに CopyForce を呼び出すと、メニューを表示しないで、強制上書きします。 .SourcePath は、コピー元のフォルダーのパス。 .DestinationPath は、コピー先のフォルダーのパス。 .SynchronizedPath は、.DestinationPath にコピーしたファイルのコピーが入ります。 .SynchronizedPath にあるファイルと .DestinationPath にあるファイルの内容が異なれば、 .DestinationPath にあるファイルが修正されたと判断されます。 テスト → T_CopyDelNotOver フォルダ 関連 → DeleteSameFileClass → CommitCopy *********************************************************************** <<< ReplaceShortcutFilesToFiles >>> *********************************************************************** ReplaceShortcutFilesToFiles Sub ReplaceShortcutFilesToFiles( FolderPath as string, Option_ as Empty ) ショートカット・ファイルを通常のファイルに変換します。 【引数】 FolderPath 変換するフォルダーのパス Option_ Empty を指定してください サブ フォルダーを含めて変換します。 ソース → vbslib.vbs 関連 → ReplaceShortcutFilesToFiles コマンド → CreateShortcut (Shell) *********************************************************************** <<< CopyFunction 型、コピー関数型 >>> *********************************************************************** CopyFunction 型、コピー関数型 Function CopyFunction( in_SourcePath as string, in_DestinationPath as string, ref_Option as variant ) as variant コピーまたは移動をする関数の型。 関数名は、CopyFunction とは限りません。 【引数】 in_SourcePath コピー元のアドレスやパス in_DestinationPath コピー先のアドレスやパス ref_Option ユーザー定義、または、コール元定義 返り値 コール元定義 パスが相対パスで渡されたとき、その基準パスはカレント フォルダーです。 サンプル Function SampleStaticClass_copy( in_SourcePath, in_DestinationPath, ref_Option ) copy_ren in_SourcePath, in_DestinationPath End Function Set a_copy = GetRef( "SampleStaticClass_copy" ) copy_ren 関連 → CopyFolder (OpenForDefragmentClass) → CompareFunction 型、比較関数型 → CallForEach_copy *********************************************************************** <<< その他 >>> *********************************************************************** その他 → CopyDiffByMD5List MD5リストから、ファイルやフォルダーを差分コピーします。 → OpenForReplace テキストファイルの内容を変更します。 → ConvertToFullPath テキストファイルの中の相対パスをフル・パスに変換してコピーします。 → SafeFileUpdateEx ファイルを安全に更新します。 → CreateShortcut ショートカットを作成します。 → CallForEach_copy 複数のファイルをファイルコピーです。 → MakeFileClass ファイルのタイムスタンプを比較して、必要ならコマンドを実行します。 *********************************************************************** <<< move >>> *********************************************************************** move (src) Sub move( SrcPath as string, DstFolderPath as string ) SrcPath のファイルまたはフォルダを、DstFolderPath フォルダーの中に移動します。 【引数】 SrcPath 移動元のファイルパス、またはフォルダーパス DstFolderPath 移動先のフォルダーパス (ファイルパスは不可) → move_ren ファイル: vbslib.vbs 参考 → copy 移動先にファイルやフォルダーがあるときは、上書き確認しないで、上書きします。 移動先のフォルダーにあるファイルが、移動元に無くても残ります。 サンプル data フォルダを do_test フォルダの中に移動します move "data", "do_test" move "src\*", "src_copy" src フォルダの内容を src_copy フォルダに移動します テスト → T_Copy.vbs T_Move T_Move2 関連 → ReplaceFileNameWildcard → SafeFileUpdate *********************************************************************** <<< move_ren >>> *********************************************************************** move_ren (src) Sub move_ren( SrcPath as string, DstPath as string ) ファイルまたはフォルダーの名前を変えて移動します。 【引数】 SrcPath コピー元のパス DstPath コピー先のパス SrcPath がファイルなら、DstPath に指定したパスもファイルにしてください。 SrcPath がフォルダなら、DstPath に指定したパスもフォルダにしてください。 移動先にファイルやフォルダーがあるときは、上書き確認しないで、上書きします。 移動先のフォルダーにあるファイルが、移動元に無くても残ります。 (Ver 5.00以降) 移動先のフォルダーにあるファイルが、移動元に無いときは、そのファイルは削除されます。 (Ver 5.00より前) ソース → vbslib.vbs テスト → T_Copy.vbs T_Move T_Move2 関連 → move → ren *********************************************************************** <<< unzip >>> *********************************************************************** unzip (src) Sub unzip( Src as string, Dst as string, Opt as integer ) Opt 圧縮 (zip形式) フォルダーを解凍します。 【引数】 Src コピー元 = 圧縮 (zip形式) フォルダー(= zip ファイル)のパス Dst コピー先 = 解凍してできるフォルダーのパス Opt Emtpy または、オプション・フラグ → Opt 引数 ファイル: zip.vbs 参考 → zip 圧縮展開 → ファイル名、パス (Windows) → Out of Writable 警告 [E_OutOfWritable] zip ファイルの中のルートに1つのフォルダーだけがあるときは、そのフォルダーの中を 展開します。 ダウンロードした zip ファイルを解凍するために、vbslib の unzip を使わないでください。 不正な zip ファイルに対するテストをしていません。 Windows のエクスプローラーなどから展開してください。 サンプル1 相対パス指定 unzip "sample1.zip", "sample1", F_AfterDelete sample1 sample1 sample1.zip カレントフォルダー sample1 (新規作成) sample1 解凍 file1.txt (新規作成) file1.txt 上記 sample1.zip は、次のように作成します。 sample1 sample1.zip file1.txt フォルダを右クリック [ 送る | 圧縮(zip)フォルダ ] sample1.zip をエクスプローラで開くと、次のようになります。 sample1.zip sample1 file1.txt ダブルクリックで開かないときは、右クリック [ プログラムから開く | Compressed Folders ] サンプル2 フル・パス指定、インストール向け unzip "sample1.zip", "C:\folderA\sample1", F_AfterDelete C:\folderA\ sample1.zip C:\ folderA sample1 sample1 file1.txt file1.txt 関連 → env 環境変数を指定する → SpecialFolders (Shell) 特殊フォルダを指定する Opt 引数 整数型のときは、ビットフィールドの Flags です。 なお、c = g_VBS_Lib です。 c.AfterDelete 解凍する前にフォルダを削除します すでにフォルダーが存在し、zip の内容と異なるときはエラーにします すでにフォルダーが存在していたら何もしません すでにフォルダーが存在していたらエラーにします c.CheckSameIfExist c.IgnoreIfExist c.ErrorIfExist boolean 型のときは、次のとおりです。 True F_AfterDelete と同じ。 解凍する前にフォルダを削除します F_IfNotExist と同じ。 すでにフォルダが存在していたら何もしません False ソース → zip.vbs テスト → T_Zip.vbs # [T_unzip] 関連 → unzip コマンド → unzip2 → Setting_get7zExePath → DownloadAndExtractFileIn7zClass *********************************************************************** <<< zip 圧縮展開 >>> *********************************************************************** zip 圧縮展開 zip 形式の圧縮ファイルを扱います。 zip\unzip2.exe の内部で使っている zlib について → scriptlib\zip\zip_readme.txt ダウンロードした zip ファイルを解凍するために、vbslib の unzip を使わないでください。 不正な zip ファイルに対するテストをしていません。 Windows のエクスプローラーなどから展開してください。 リファレンス → unzip 圧縮 (zip形式) フォルダーを解凍します。 → unzip2 zip ファイルを解凍します。 ファイル構成 scriptlib vbslib setting vbs_inc_setting.vbs Setting_getIncludePathes = Array(_ : "zip\zip.vbs",_ zip zip_readme.txt zip.vbs *********************************************************************** <<< unzip2 >>> *********************************************************************** unzip2 (src) Sub unzip2( ZipPath as string, ExtractFolderPath as string ) zip ファイルを解凍します。 解凍先フォルダーを指定できます。 【引数】 ZipPath zip ファイルのパス ExtractFolderPath 解凍先フォルダーのパス ファイル: zip.vbs ExtractFolderPath のフォルダーの中に、フォルダーができるかどうかは、 zip ファイルの内容によります。 zip ファイルの中のルートに zip ファイルと 同じ名前のフォルダーがあるときは、そのフォルダーの中を展開します。 サンプル unzip2 "sample1.zip", "C:\folderA" sample1.zip C:\folderA sample1.zip C:\ folderA sample1 sample1 file1.txt file1.txt file2.txt file2.txt テスト → T_Zip.vbs # [T_unzip2] 関連 → unzip → zip, unzip.exe *********************************************************************** <<< zip2 >>> *********************************************************************** zip2 Sub zip2( ZipPath as string, SourceFolderPath as string, IsFolderName as boolean ) フォルダーを圧縮して、zip ファイルを作成します。 【引数】 ZipPath zip ファイルのパス SourceFolderPathObj 圧縮するフォルダーのパス IsFolderName zip ファイルの中に、ZipPath に指定したフォルダー名を入れるかどうか ソース → zip.vbs テスト → T_Zip.vbs T_zip2 関連 → zlib (clib) *********************************************************************** <<< DownloadAndExtractFileIn7zClass >>> *********************************************************************** DownloadAndExtractFileIn7zClass 圧縮ファイルをコピー(ダウンロード)してから、解凍したファイルのパスを返します。 コピーは、複数のファイルで並行して行われるようにもできます。 サンプル Set downloader = new DownloadAndExtractFileIn7zClass paths_in_server = Array( "Server\FileA.txt", "Server\FileB.txt" ) '// 複数のファイルで並行してコピーします。 For Each path In paths_in_server downloader.DownloadStart path Next '// 展開したファイルのパスを取得します。 path_in_local = downloader.GetLocalPath( path(0) ) Assert path = "Temporary\Fragments\8f\8f97b7e131a6d059a17cb42b988c9101\FileA.txt" path_in_local = downloader.GetLocalPath( path(1) ) Assert path = "Temporary\Fragments\4b\4b46a773b6b3582891edbed39bdc2974\FileA.txt" 引数に指定するパスは、圧縮ファイルを展開したときにできるパスです。 圧縮ファイル _Fragment.7z があるときは、圧縮ファイルを テンポラリ フォルダー の中の Fragments フォルダーに一旦コピーしてから解凍します。 これは、コピー元がネットワークや DVD-ROM など アクセスが遅いときに高速に処理するためです。 テンポラリ フォルダーは、キャッシュの役割をします。 コピー元の圧縮ファイルの名前は、_Fragment.7z 固定です。 ファイル名は、圧縮ファイルの MD5 に改名され、MD5 の先頭 2文字のフォルダーに格納され ます。 また、解凍した内容が入ったフォルダーも作られます。 そのフォルダー名は、圧縮ファイルの 名前と同じ MD5 です。 すでに圧縮ファイルがあるときは、テンポラリ フォルダーにコピーする処理は スキップされ、早く次の処理に進みます。 Server _Fragment.7z FileA.txt ← in_PathIn7zInServer 引数が指すファイル FileB.txt コピー テンポラリ フォルダー \Fragments 8f 8f97b7e131a6d059a17cb42b988c9101.7z ファイル名は、7z ファイルの MD5 内容は、_Fragment.7z と同じ 解凍 8f97b7e131a6d059a17cb42b988c9101 FileA.txt ← 返り値が指すファイル FileB.txt 7e 7eb5bc036d02ec0e8a401aa7ea1192af-Fragment-7z.txt ファイル名は、コピー元の フォルダーのパスの MD5。 つまり、文字列 "Server" の MD5。 内容は、_Fragment.7z の MD5、つまり、 8f97b7e131a6d059a17cb42b988c9101 ソース → zip.vbs テスト → T_Zip.vbs T_DownloadAndExtractFileIn7z コールツリー T_DownloadAndExtractFileIn7z (.vbs) downloader.GetLocalPath (.vbs) downloader.DownloadStart (.vbs) CopyWindowClass::CopyAndRenameStart (.vbs) Me.DownloadThreads.Add downloader.Dispatch CopyWindowClass::Dispatch (.vbs) 関連 → CopyFolder (OpenForDefragmentClass) → 7-Zip *********************************************************************** <<< DownloadStart (DownloadAndExtractFileIn7zClass) >>> *********************************************************************** DownloadStart (DownloadAndExtractFileIn7zClass) << DownloadAndExtractFileIn7zClass Function DownloadAndExtractFileIn7zClass::DownloadStart( in_PathIn7zInServer as string ) as DownloadAndExtractFileIn7z_ThreadClass 指定したファイルが入った圧縮ファイルのコピー(ダウンロード)を開始します。 【引数】 in_PathIn7zInServer コピーする前の圧縮ファイルを展開してできるファイルのパス 返り値 コピーのスレッド 内部で CopyWindowClass を使い、並列してコピーします。 *********************************************************************** <<< GetLocalPath (DownloadAndExtractFileIn7zClass) >>> *********************************************************************** GetLocalPath (DownloadAndExtractFileIn7zClass) << DownloadAndExtractFileIn7zClass Function DownloadAndExtractFileIn7z::GetLocalPath( in_PathIn7zInServer as string ) as string 圧縮ファイルをコピー(ダウンロード)してから、解凍したファイルのパスを返します。 【引数】 in_PathIn7zInServer コピーする前の圧縮ファイルを展開してできるファイルのパス 返り値 Empty、または解凍したファイルのパス、ファイルがないこともあります 先に DownloadStart で先に並列してダウンロードしたほうが、高速に処理できます。 返り値に入っているパスには、ファイルがないこともあります。 圧縮ファイル _Fragment.7z がない ときは、Empty が返ります。 *********************************************************************** <<< ren >>> *********************************************************************** ren (src) Sub ren( src as string, dst as string ) src から dst にファイル名を変更します。 【引数】 src 名前を変更するファイルのパス、またはフォルダーのパス dst 変更後のファイル名。 フォルダー・パスの指定は不要。 ファイル: vbslib.vbs 参考 → ファイル名、パス (Windows) → Out of Writable 警告 [E_OutOfWritable] サンプル ren "FolderA\File1.txt", "File2.txt" "FolderA\File1.txt" ファイルを "FolderA\File2.txt" ファイルに改名します。 dst にフォルダー・パスを指定しても無視されます。 ren "FolderA\File1.txt", "FolderB\File2.txt" 上記を実行したら、FolderB\File2.txt ではなく、FolderA\File2.txt にファイルが ある状態になります。 別のフォルダーに移動するときは、move または move_ren を使ってください。 テスト → T_Ren.vbs # [main2] 関連 → move_ren *********************************************************************** <<< del >>> *********************************************************************** del Sub del( path as string ) ファイルまたはフォルダーを削除します。 【引数】 path 削除するファイルのパス、またはフォルダーのパス path 引数に、 PathDictionaryClass のオブジェクト も指定できます。 リードオンリー属性のファイルやフォルダーも削除します。 参考 → ファイル名、パス (Windows) → Out of Writable 警告 [E_OutOfWritable] サンプル del "File1.txt" "File1.txt" path に Empty を指定したときは、何もしません。 テスト → T_Copy.vbs # [T_Del] ソース → vbslib.vbs → vbslib_mini.vbs 関連 → del_to_trashbox → del_confirmed → FileSystemObject::DeleteFile → CallForEach_del *********************************************************************** <<< del_subfolder >>> *********************************************************************** del_subfolder (src) Sub del_subfolder( Path as string or array of string ) ファイルまたはフォルダーを削除します。 サブ・フォルダーにある同名のものも含めて削除します。 【引数】 Path 削除するファイルまたはフォルダーのパス、またはその配列 ファイル: vbslib.vbs サブ・フォルダー(フォルダーの中のフォルダー)をすべて調べて、Path に指定したパスの、 ファイル名の部分に一致する名前のファイルやフォルダーを削除します。 サンプル del_subfolder "FolderA\text1.txt" "FolderA\text1.txt" FolderA フォルダーとそのサブ・フォルダーにある text1.txt を削除します。 削除されるファイルやフォルダーの例: FolderA\sub1\text1.txt FolderA\sub2\text1.txt FolderA\sub1\sub3\text1.txt FolderA\sub1\text1.txt\file.txt 削除されないファイルやフォルダーの例: FolderA\sub1\text2.txt FolderA\sub1\sometext1.txt サンプル del_subfolder "FolderA\*.txt" FolderA フォルダーとそのサブ・フォルダーにある *.txt を削除します。 テスト → T_Copy.vbs # del_subfolder *********************************************************************** <<< del_to_trashbox >>> *********************************************************************** del_to_trashbox (src) Sub del_to_trashbox( path as string ) ファイルまたはフォルダを vbslib のゴミ箱へ移動します。 【引数】 path 削除するファイルのパス、またはフォルダーのパス ファイル: vbslib.vbs ゴミ箱の場所は、 テンポラリ・フォルダー の中の _RecycleBin フォルダーです。 指定したパスにファイルかフォルダーが無いときは、何もしません。 エラーにもなりません。 移動できなかったときは、エラー 17 になります。 サンプル del_to_trashbox "File1.txt" "File1.txt" 参考 → Folder::MoveHere テスト → T_Trash.vbs # del_to_trashbox *********************************************************************** <<< del_confirmed >>> *********************************************************************** del_confirmed (src) Function del_confirmed( Path as string ) as boolean ファイルまたはフォルダがあれば、ユーザに確認してから削除します。 【引数】 path 削除するファイルのパス、またはフォルダーのパス ファイル: vbslib.vbs ユーザーが Y を選ばなかったら、削除しないで続きを実行します。 サンプル del_confirmed "File1.txt" If exist( "File1.txt" ) Then Error "File1.txt" 確認画面の例 削除してよろしいですか? : work\file1.txt (Y/N) テスト → T_Del_Manually.vbs # [T_del_confirmed] *********************************************************************** <<< del_empty_folder >>> *********************************************************************** del_empty_folder Sub del_empty_folder( FolderPath as string or array of string ) ファイルやフォルダーが入っていないフォルダーを削除します。 【引数】 path 削除するフォルダーのパス、またはその配列 ファイル: vbslib.vbs FolderPath のサブ・フォルダーも、その中にファイルやフォルダーが入ってなければ、削除します。 最後がピリオド(例:Folder\. )のときは、サブ・フォルダーは削除しません。 ソース → vbslib.vbs テスト → T_Copy.vbs T_del_empty_folder 関連 PathDictionaryClass の DeleteFolderPaths プロパティ *********************************************************************** <<< DeleteSameFileClass >>> *********************************************************************** DeleteSameFileClass (src) フォルダーの中に入っているファイルと同じ内容であれば削除します。 ただし、内容が異なるファイルは、 SyncFilesMenu メニューに一覧します。 メニューを閉じるまで、Delete メソッドから戻りません。 サンプル Set o = new DeleteSameFileClass o.SourcePath = "work\Source" o.DestinationPath = "work\Destination" o.SynchronizedPath = "work\Synchronized" o.Delete Delete の代わりに DeleteForce を呼び出すと、メニューを表示しないで、強制削除します。 Delete の代わりに DeleteSameOnly を呼び出すと、メニューを表示しないで、削除もしません。 .SourcePath は、比較するファイルが入ったフォルダーのパス。 .DestinationPath は、削除するファイルが入ったフォルダーのパス。 .SynchronizedPath は、 CopyNotOverwriteFileClass のものと同じ。 テスト → T_CopyDelNotOver フォルダ *********************************************************************** <<< mkdir >>> *********************************************************************** mkdir Function mkdir( Path as string ) フォルダーを作成します。 【引数】 Path 作成するフォルダーのパス 返り値 作成したフォルダーの数 ファイル: vbslib.vbs 参考 → ファイル名、パス (Windows) → Out of Writable 警告 [E_OutOfWritable] c:\a という空のフォルダーがあるとき、c:\a\b というフォルダーがなくても、c:\a\b\c の ようにネストして(孫フォルダーを)指定することができます。 フル・パスが250文字以上の長いパスになるフォルダーは作れません。 Path に指定した場所に、すでにフォルダーがあるときは、何もしませんし、エラーにも なりません。 サンプル カレント・フォルダーに sub フォルダーを作成します。 mkdir "sub" "sub" テスト → T_File.vbs # [T_MkDir] ソース → vbslib.vbs → vbslib_mini.vbs 関連 → mkdir_for → FileSystemObject::CreateFolder *********************************************************************** <<< mkdir_for >>> *********************************************************************** mkdir_for Sub mkdir_for( FilePath as string ) 指定のファイルを作成するためのフォルダを作成します。 ファイルは作成しません。 【引数】 FilePath ファイルのパス ソース → vbslib.vbs サンプル mkdir_for "sub\file1.txt" sub\file1.txt ファイルを格納する sub フォルダを作成します。 テスト → T_File.vbs # [T_MkDir] *********************************************************************** <<< rmdir >>> *********************************************************************** rmdir (src) Sub rmdir( Path as string ) フォルダーを削除します。 【引数】 Path 削除するフォルダーのパス del でも、rmdir と同じようにフォルダを削除できます。 ソース → vbslib.vbs サンプル rmdir "sub" テスト → T_Copy.vbs # [T_Del] 関連 → del *********************************************************************** <<< exist >>> *********************************************************************** exist Function exist( path as string ) as boolean フォルダーまたはファイルが存在するかどうかを返します。 ワイルドカードを指定することもできます。 Empty を指定したら、False が返ります。 参考 → ファイル名、パス (Windows) サンプル If exist( "file1.txt" ) Then ... ソース → vbslib.vbs → vbslib_mini.vbs テスト → T_File.vbs T_Exist 関連 → AssertExist → exist_ex → FileSystemObject::FileExists → FileSystemObject::FolderExists → GetExistPathInSetting → ExistenceCacheClass *********************************************************************** <<< exist_ex >>> *********************************************************************** exist_ex Function exist_ex( Path as string, Opt as Empty or integer ) as boolean フォルダーまたはファイルが存在するかどうかを返します。 【引数】 Path 存在を調べるパス Opt オプション、 Empty または c.CaseSensitive 返り値 存在するかどうか サンプル Set c = g_VBS_Lib If exist_ex( "a.txt", c.CaseSensitive ) Then ソース → vbslib.vbs テスト → T_File.vbs T_Exist 関連 → exist *********************************************************************** <<< IsEmptyFolder >>> *********************************************************************** IsEmptyFolder Function IsEmptyFolder( in_Path as string ) as boolean 空のフォルダーかどうかを返します。 【引数】 in_Path 調べるパス 返り値 空のフォルダーかどうか パスが指す先 返り値 空のフォルダー True False 何か入ったフォルダー False 何もない ファイル False ソース → vbslib.vbs テスト → T_File.vbs T_IsEmptyFolder *********************************************************************** <<< ExistenceCacheClass >>> *********************************************************************** ExistenceCacheClass ファイルやフォルダーが存在するかどうかをキャッシュによって高速に調べます。 FileSystemObject の FileExists や FolderExists は、毎回ファイル システムにアクセス するため遅いです。 特にネットワーク上の共有フォルダーの中にアクセスすると遅いです。 キャッシュは、ExistenceCacheClass のオブジェクトの中にある変数です。 ファイルやフォルダーが変化したときは、ExistenceCacheClass のオブジェクトを 生成し直してください。 サンプル Set cache = new ExistenceCacheClass Assert cache.Exists( "C:\Folder" ) Assert not cache.FileExists( "C:\NotFound.txt" ) Assert cache.FolderExists( "\\PC-01\Share\A.txt" ) 説明 ExistenceCacheClass(キャッシュA)を使うモジュールA が、 ExistenceCacheClass(キャッシュB)を使うモジュールB を使うときは、 モジュールA とモジュールB からキャッシュA を共有するように モジュールB のメンバー変数が指すオブジェクトを置き換えるほうが早くなります。 そのとき、キャッシュB は使いません。 メソッド .Exists( ) ファイルまたはフォルダーがあるかどうかを返します。 .FileExists( ) ファイルがあるかどうかを返します。 .FolderExists( ) フォルダーがあるかどうかを返します。 .Save( ) キャッシュをファイルに保存します。 .Load( ) キャッシュをファイルから読込みます。 プロパティ .IsEnabled boolean キャッシュの有効・無効。 初期値は有効 .TargetRootPath string キャッシュに入れるパスのルート。 "\\" ならすべての共有フォルダー。 "" ならすべてのパス。 初期値は "\\"。 .CountOfCheckingExistence integer 有無をチェックした回数 .CountOfEnumeration integer フォルダーの直下を一覧した回数 ソース → Network.vbs テスト → T_Path.vbs T_ExistenceCache → README *********************************************************************** <<< Exists (ExistenceCacheClass) >>> *********************************************************************** Exists (ExistenceCacheClass) << ExistenceCacheClass Function ExistenceCacheClass::Exists( in_Path as string ) as boolean ファイルまたはフォルダーの有無を、キャッシュを使いながら確認します。 【引数】 in_Path 調べるパス 返り値 ファイルまたはフォルダーの有無 ソース → Network.vbs *********************************************************************** <<< FileExists (ExistenceCacheClass) >>> *********************************************************************** FileExists (ExistenceCacheClass) << ExistenceCacheClass Function ExistenceCacheClass::FileExists( in_Path as string ) as boolean ファイルの有無を、キャッシュを使いながら確認します。 【引数】 in_Path 調べるパス 返り値 ファイルの有無 ソース → Network.vbs *********************************************************************** <<< FolderExists (ExistenceCacheClass) >>> *********************************************************************** FolderExists (ExistenceCacheClass) << ExistenceCacheClass Function ExistenceCacheClass::FolderExists( in_Path as string ) as boolean フォルダーの有無を、キャッシュを使いながら確認します。 【引数】 in_Path 調べるパス 返り値 フォルダーの有無 ソース → Network.vbs *********************************************************************** <<< Save (ExistenceCacheClass) >>> *********************************************************************** Save (ExistenceCacheClass) << ExistenceCacheClass Sub ExistenceCacheClass::Save( in_CacheFilePath as string, in_BasePath as string, in_RootPath as string ) キャッシュをファイルに保存します。 【引数】 in_CacheFilePath 保存するファイルのパス in_BasePath 相対パスの基準、Empty=in_CacheFilePath の親フォルダー in_RootPath 保存するパスのルート、""=すべて in_RootPath が指すフォルダーの外に関するキャッシュは保存しません。 ソース → Network.vbs *********************************************************************** <<< Load (ExistenceCacheClass) >>> *********************************************************************** Load (ExistenceCacheClass) << ExistenceCacheClass Sub ExistenceCacheClass::Load( in_CacheFilePath as string, in_BasePath as string ) キャッシュをファイルから読込みます。 【引数】 in_CacheFilePath 読込むファイルのパス in_BasePath 相対パスの基準、Empty=in_CacheFilePath の親フォルダー ソース → Network.vbs *********************************************************************** <<< type_ >>> *********************************************************************** type_ Sub type_( Path as string ) テキストファイルの内容を表示します。 【引数】 Path 表示するファイルのパス 参考 → ファイル名、パス (Windows) type は、VBScript の予約語なので、type の後に末尾にアンダースコアを付けた名前にしています。 サンプル: type_ "result.txt" *********************************************************************** <<< ReadFile >>> *********************************************************************** ReadFile Function ReadFile( Path as string ) as string テキストファイルの全体を読み込みます。 【引数】 Path 読み込むテキストファイルのパス、または FilePathClass 返り値 テキストファイルの内容 サンプル: text = ReadFile( "a.txt" ) ファイルが存在しないときでもエラーにならず、"" を返します。 エラーにするときは次のようにします。 Set file = OpenForRead( "a.txt" ) text = ReadAll( file ) 多くの場合、行末に改行文字があります。 ReadFile で取得した末尾に 改行文字があることに注意してください。 CreateFile で作成したファイルは、改行文字は付きません。 a.txt Text1 ReadFile( "a.txt" ) = "Text1"+vbCRLF 文字コードを指定するときは、 new_TextFileCharSetStack を使って ください。 ただし、Shift-JIS, Unicode, UTF-8(BOMあり) は、使わな くても自動的に文字コードを判定して、正しく読み込みます。 Set cs = new_TextFileCharSetStack( "EUC-JP" ) t = ReadFile( "a.txt") cs = Empty ソース → vbslib.vbs → vbslib_mini.vbs テスト → T_File.vbs # [T_ReadFile] 関連 → ReadAll → ReadFileInTag → CreateFile *********************************************************************** <<< ReadFileInTag >>> *********************************************************************** (src) ReadFileInTag Function ReadFileInTag( Path as string, StartOfText as string, EndOfText as string ) as string テキストファイルの中にある指定の開始タグと終了タグの間にあるテキストを読み込みます。 【引数】 Path 読み込むテキストファイルのパス StartOfText 読み込む範囲の先頭にあるタグ(テキスト)、または Empty(=先頭から) EndOfText 読み込む範囲の末尾にあるタグ(テキスト)、または Empty(=末尾まで) 返り値 タグの間のテキストファイルの内容。 タグ、および、先頭と末尾の改行は除く サンプル Dim text CreateFile "index.html", "abc

123

def" text = ReadFileInTag( "index.html", "

", "

" ) : Assert text = "123" CreateFile "index.html", "abc

def" text = ReadFileInTag( "index.html", "

", Empty ) : Assert text = "def" text = ReadFileInTag( "index.html", Empty, "

" ) : Assert text = "abc" 読み込みサンプル StartOfText = "", EndOfText = "" とします。 ファイル 返り値 abc123def 123 abc 123 456 def 123 456 (456の後に改行なし) テスト → T_File.vbs # [T_ReadFileInTag] 関連 → sscanf 文字列の途中を取り出します → ReplaceRange (ReplaceTextFile1) 指定のタグで囲まれたテキストを置き換えます *********************************************************************** <<< ReadAll >>> *********************************************************************** (src) ReadAll Function ReadAll( FileStream as TextStream ) as string テキストファイルをすべてリードします。 【引数】 FileStream 開いている読み込むファイル 返り値 最後までリードしたテキスト TextStream::ReadAll と異なり、ファイルサイズが 0 のときでも、エラーになりません。 関連 → ReadFile *********************************************************************** <<< ReadBinaryFile >>> *********************************************************************** ReadBinaryFile Function ReadBinaryFile( Path as string ) as BinaryArray バイナリーファイルの全体を読み込みます。 【引数】 Path バイナリーファイルのパス 返り値 バイナリー・データ → BinaryArray クラス サンプル Set bin = ReadBinaryFile( "unicode_sample.txt" ) If bin(0) = &hFF and bin(1) = &hFE Then echo "This is unicode file." End If "unicode_sample.txt" ソース → System.vbs テスト → T_Binary.vbs 関連 → Load (BinaryArray) → new_BinaryArray *********************************************************************** <<< IsSameTextFile >>> *********************************************************************** IsSameTextFile Function IsSameTextFile( PathA as string, PathB as string, in_out_Options as variant ) as boolean Function IsSameTextFile_Old( PathA as string, CharSetA as string, PathB as string, CharSetB as string, Options_ as integer ) as boolean テキスト・ファイルを比較します。 文字コードや改行文字が異なっていても構いません。 【引数】 PathA 比較するファイル A のパス CharSetA 比較するファイル A の文字コードセット (*1) PathB 比較するファイル B のパス CharSetB 比較するファイル B の文字コードセット (*1) in_out_Options オプション、または Empty 返り値 2つのファイルの内容が同じかどうか (*1) 文字コードについては、 → new_TextFileCharSetStack ただし、BOM があるときや、Shift JIS のときは、Empty を指定できます。 IsSameTextFile は、 比較関数型 です。 vbslib4 の IsSameTextFile は、IsSameTextFile_Old に置き換えてください。 サンプル Assert IsSameTextFile( "FileA.txt", "FileB.txt", Empty ) Assert IsSameTextFile_Old( "FileA.txt", Empty, "FileB.txt", "EUC-JP", Empty ) Options_ 引数 Empty または、下記の定数の or、または、OptionsFor_IsSameTextFile_Class を指定できます。 c は、g_VBS_Lib の返り値です。 c.SkipLeftSpaceLine PathA のファイルにある空行は比較しない c.RightHasPercentFunction PathB のファイルには、 % を使った変換式 を含む c.ErrorIfNotSame 内容が異なっていたら、エラーにする OptionsFor_IsSameTextFile_Class .CharSetA 比較するファイル A の文字コードセット (*1) .CharSetB 比較するファイル B の文字コードセット (*1) ソース → vbslib.vbs テスト → T_fc.vbs T_IsSameTextFile → T_fc.vbs T_IsSameTextFileRegExp 関連 → fc コマンド → TextFileExtension (g_Vers) テキストファイルの拡張子の設定 *********************************************************************** <<< IsSameBinaryFile >>> *********************************************************************** IsSameBinaryFile Function IsSameBinaryFile( PathA as string, PathB as string, Opt as integer ) as boolean バイナリ・ファイルを比較します。 【引数】 PathA 比較するファイル A のパス PathB 比較するファイル B のパス Opt Empty を指定してください 返り値 2つのファイルの内容が同じかどうか PathA か PathB のどちらかのファイルがないときは、False を返します。 PathA か PathB の両方のファイルがないときは、True を返します。 IsSameBinaryFile は、 比較関数型 です。 サンプル Assert IsSameBinaryFile( "FileA.jpg", "FileB.jpg", Empty ) ソース → vbslib.vbs テスト → T_fc.vbs T_IsSameBinaryFile 関連 → fc コマンド → FileT_isSameBinaryFile (clib) → TextFileExtension (g_Vers) テキストファイルの拡張子の設定 *********************************************************************** <<< IsSameFolder >>> *********************************************************************** IsSameFolder Function IsSameFolder( PathA as string, PathB as string, in_out_Options as variant ) as boolean フォルダーの内容が同じかどうか比較します。 【引数】 PathA 比較するフォルダー A のパス PathB 比較するフォルダー B のパス in_out_Options オプション、または Empty → 下記 返り値 2つのフォルダーの内容が同じかどうか PathA と PathB にファイルのパスを指定することもできます。 IsSameFolder は、 比較関数型 です。 フォルダーの中のファイルの比較は、デフォルトでは、 IsSameBinaryFile で比較します。 拡張子によって比較する処理を変えたいときは、拡張子で分岐する関数を作成して、オプション の IsSameFileFunction に指定してください。 → 下記 指定した両方のフォルダーが存在しないときは、True を返します。 サンプル If IsSameFolder( folder_A, folder_B, Empty ) Then in_out_Options 引数 Empty または、下記の定数の or、または、 OptionsFor_IsSameFolder_Class を指定できます。 c は、g_VBS_Lib の返り値です。 c.EchoV_NotSame 違いがあったときに、そのパスを echo_v で表示します c.NotSubFolder サブ・フォルダーは調べません サンプル Set options = new OptionsFor_IsSameFolder_Class options.BitFlags = c.EchoV_NotSame options.ExceptNames = Array( "Thumbs.db" ) If IsSameFolder( folder_A, folder_B, options ) Then OptionsFor_IsSameFolder_Class .ExceptNames as array of string Empty または 比較しないファイルまたはフォルダー名 → 下記 Thumb.db などの隠しファイルを指定すれば、そのファイルは比較対象ではなくします。 正規表現 が使えます。 .IsSameFileFunction ファイルを比較する関数。 比較関数型 .IsSameFileFunction_Parameter IsSameFileFunction に指定した関数の第3引数に渡す値 ソース → vbslib.vbs テスト → T_fc.vbs T_IsSameFolder T_IsSameFolder_Echo T_IsSameFolder_File 関連 → fc (比較) → MD5 リスト *********************************************************************** <<< fc (比較) >>> *********************************************************************** fc (比較) (src) Function fc( PathA as string, PathB as string ) ファイル、またはフォルダが同一かどうかを比較します。 【引数】 PathA 比較するファイルパスA、またはフォルダパスA PathB 比較するファイルパスB、またはフォルダパスB 返り値 同一=True 参考 → ファイル名、パス (Windows) vbslib.vbs が入ったフォルダに、feq.exe が必要です。 サンプル: Assert fc( "result.txt", "ans.txt" ) If not fc( "result.txt", "ans.txt" ) Then raise E_TestFail,"" 標準出力: ファイルの内容が同じだったとき fc "result.txt", "ans.txt" same. 標準出力: ファイルの内容が違ったとき fc "result.txt", "ans.txt" different. 標準出力: フォルダの内容が同じだったとき fc "folder1", "folder2" same. 標準出力: フォルダの内容が違ったとき fc "folder1", "folder2" Not found "sub\file1.txt" in "folder1" Not found "sub2" in "folder2" Not same "sub\file2.txt" different. テスト → T_fc フォルダ → T_feq フォルダー ソース → feq フォルダー feq.exe のソース *********************************************************************** <<< fc_r >>> *********************************************************************** (src) fc_r Function fc_r( path_a as string, path_b as string, redirect_path as string ) as boolean ファイルやフォルダの内容が同じかどうか調べます。 【引数】 path_a 1つ目のファイルのパス、またはフォルダのパス path_b 2つ目のファイルのパス、またはフォルダのパス redirect_path 調べた結果の詳細の出力先のファイルパス、Empty、"nul" 可 返り値 同じかどうか vbslib.vbs が入ったフォルダに、feq.exe が必要です。 redirect_path の値 出力先 "" 標準出力 "nul" なし Empty なし その他 ファイル 出力内容については、 → fc *********************************************************************** <<< fc_ex >>> *********************************************************************** (src) fc_ex Function fc_ex( PathA as string, PathB as string, Opt as fc_option ) as boolean ファイルやフォルダの内容が同じかどうか調べます。 【引数】 PathA 1つ目のファイルのパス、またはフォルダのパス PathB 2つ目のファイルのパス、またはフォルダのパス Opt Empty または オプション 返り値 同じかどうか vbslib.vbs が入ったフォルダに、feq.exe が必要です。 Opt 引数、fc_option Class fc_option Public FcOptionIniPath Public FcResultRedirectPath Public m_bStdOut Public IsStartDiffIfNotSame Public IsXmlComparedAsBinary End Class オプション指定ファイル fc.ini のパス 結果を出力するファイルのパス 未対応 未対応 XML として同じでも、テキストが異なれば、異なると判定する FcOptionIniPath、オプション指定ファイル fc.ini [Excludes] A = obj A = proj\Debug : : 比較を行わないファイルの一覧 IsStartDiffIfNotSame 未対応 違いが発見されたら、diff を起動。 起動したら、False になります diff ツールは、 Setting_getDiffCmdLine で設定します。 IsXmlComparedAsBinary False なら、文字コードや空白文字などの違いがあっても、XML ドキュメントのデータが同じであれば 同じと判定します。 デフォルト(Empty)は True です。 テスト → T_XML.vbs # [T_CompareXml] *********************************************************************** <<< set_fc_option >>> *********************************************************************** set_fc_option Function set_fc_option( opt as fc_option ) as fc_option fc_option fc のオプションを設定します。 デバッグ用です。 返り値は、opt 引数がそのまま返ります。 このオプションは、fc, fc_r, fc_ex のすべてに設定され、set_fc_option Empty するまで有効です。 サンプル: fc で違いが発見されたら、そのファイルに対して diff を起動します。 set_fc_option( new fc_option ).m_bStartDiff = True If not fc( file_a, file_b ) Then Fail If not fc( file_a, file_c ) Then Fail set_fc_option Empty *********************************************************************** <<< マージ、diff >>> *********************************************************************** マージ、diff → diff → ThreeWayMerge → FourWayMerge *********************************************************************** <<< diff >>> *********************************************************************** diff Function diff( in_LeftPath as string, in_RightPath as string, in_OutputPath as string, in_out_Option ) as string diff を実行して、テキスト ファイルの内容を比較します。 【引数】 in_LeftPath 1つ目の比較するテキスト ファイルのパス in_RightPath 2つ目の比較するテキスト ファイルのパス in_OutputPath 比較した結果を出力するファイルのパス in_out_Option Empty または get_ToolsLibConsts().DiffForPatch 返り値 比較した結果(in_OutputPath = Empty のとき) 比較するテキストが同じ内容だったときは、その内容がそのまま出力されます。 in_out_Option = get_ToolsLibConsts().DiffForPatch を指定すると、unified 形式で出力されます。 GnuWin の diff とは異なり、Ascii コード以外の文字にも対応しています。 ただし、get_ToolsLibConsts().DiffForPatch を指定しても、GnuWin の patch には使えなくなり ます。 vbslib の patch には使えます。 サンプル diff "Left.txt", "Right.txt", "Output.txt", Empty Left.txt Right.txt Output.txt 1 LLL 2 3 1 RRR 2 3 1 <<<<<<< Left.txt LLL ======= RRR >>>>>>> Right.txt 2 3 上記の差分は GUI で比較表示できます。 → DiffTag コマンド サンプル Set tc = get_ToolsLibConsts() diff "Left.txt", "Right.txt", "Output.txt", tc.DiffForPatch Left.txt Right.txt Output.txt 1 LLL 2 3 1 RRR 2 3 --- Left.txt 2016-09-04 17:45:05.422985300 +0900 +++ Right.txt 2016-09-04 17:45:05.423985100 +0900 @@ -1,4 +1,4 @@ 1 -LLL +RRR 2 3 diff 関数の内部と Diffutils diff 関数は、内部で scriptlib\GPL に入っている Diffutils をコマンドライン経由で 呼び出し、Diffutils の出力「データ」を使用しています。 このため、GPL の派生プログラムに 該当しない(両立する必要がない)ものと考えています。 参考 → GPL のプログラムを含む vbslib の再配布の注意点 使い易くするため、ThreeWayMerge の内部で Windows の GNU UNIX コマンドの注意 を守るための処理が行われています。 ソース → ToolsLib.vbs テスト → T_Diff.vbs T_ParseUnifiedDiff *********************************************************************** <<< ParseUnifiedDiff >>> *********************************************************************** ParseUnifiedDiff Function ParseUnifiedDiff( in_UnifiedDiff as string ) as UnifiedDiffClass diff の出力(unified 形式)を解析します。 【引数】 in_UnifiedDiff diff の出力(unified 形式) → diff の出力形式 返り値 解析結果 → UnifiedDiffClass ソース → ToolsLib.vbs テスト → T_Diff.vbs T_ParseUnifiedDiff UnifiedDiffClass (src) データ構造 UnifiedDiffClass array < UnifiedOneDifferenceClass > .Differences integer integer integer integer .PlusStart .PlusOver .MinusStart .MinusOver 追加開始行番号 追加の次の行番号 削除開始行番号 削除の次の行番号 *********************************************************************** <<< DiffWithoutKS >>> *********************************************************************** DiffWithoutKS Sub DiffWithoutKS( in_PathA as string, in_PathB as string, in_PathC as string, in_Option as Empty or DiffCmdLineOptionClass ) SubVersion などの Keyword Substitution をカットしてから、フォルダーの内容を比較します。 【引数】 in_PathA 1つ目の比較するフォルダーのパス in_PathB 2つ目の比較するフォルダーのパス in_PathC Empty または、3つ目の比較するフォルダーのパス in_Option Empty または → DiffCmdLineOptionClass デスクトップの _DiffWithoutKS フォルダーを作り、その中に Keyword Substitution をカットした ファイルをコピーして、Diff ツールを開きます。 Diff ツールについては、 → Setting_getDiffCmdLine → Setting_getFolderDiffCmdLine /************************* * $Rev: 43 $ **************************/ /************************* * $Rev: $ **************************/ 43 参考 → SubVersion - Keyword Substitution ソース → ToolsLib.vbs テスト → T_Diff.vbs T_DiffWithoutKS → KS フォルダー 関連 → DiffWithoutKS コマンド *********************************************************************** <<< patch >>> *********************************************************************** patch Sub patch( in_OldPath as string, in_DiffFilePath as string, in_OutputPath as string, in_out_Option ) patch を実行して、テキスト ファイルの内容を更新します。 (パッチをあてます) 【引数】 in_OldPath パッチをあてる前のテキスト ファイルのパス in_DiffFilePath unified 形式の差分のテキスト ファイルのパス in_OutputPath パッチをあてた後のテキスト ファイルのパス in_out_Option Empty を指定してください GnuWin の diff とは異なり、Ascii コード以外の文字にも対応しています。 patch 関数は、内部で scriptlib\GPL に入っている patch をコマンドライン経由で呼び出して います。 → diff 関数の内部と Diffutils ソース → ToolsLib.vbs テスト → T_Diff.vbs T_Patch *********************************************************************** <<< ThreeWayMerge >>> *********************************************************************** ThreeWayMerge Sub ThreeWayMerge( in_BasePath as string, in_LeftPath as string, in_RightPath as string, in_MergedOutputPath as string, in_out_Option as ThreeWayMergeOptionClass ) 3ウェイ マージ(3方向マージ)をします。 【引数】 in_BasePath ブランチする前のテキスト ファイルのパス in_LeftPath ブランチ Left で更新したテキスト ファイルのパス in_RightPath ブランチ Right で更新したテキスト ファイルのパス in_MergedOutputPath 3ウェイマージした結果を出力するファイルのパス in_out_Option Empty またはオプション → ThreeWayMergeOptionClass Left Base Merged Right コンフリクトが発生したら、E_Conflict エラーになります。 エラーのときでも、in_MergedOutputPath 引数に渡したパスにファイルが出力され、下記のように コンフリクトしたことを示す内容が出力されます。 (diff3 では、一部自動的にマージします) 参考 → ThreeWayMerge の拡張自動マージ → diff3 の詳細なサンプル カッコ: 意味: Base.txt Left.txt Right.txt <<<<<<< Left.txt LLL ||||||| Base.txt ======= RRR >>>>>>> Right.txt LLL RRR 上記の差分は GUI で比較表示できます。 → DiffTag コマンド ThreeWayMerge の内部と Diffutils ThreeWayMerge は、内部で scriptlib\GPL に入っている Diffutils をコマンドライン経由で 呼び出し、Diffutils の出力「データ」を使用しています。 このため、GPL の派生プログラムに 該当しない(両立する必要がない)ものと考えています。 参考 → GPL のプログラムを含む vbslib の再配布の注意点 使い易くするため、ThreeWayMerge の内部で Windows の GNU UNIX コマンドの注意 を守るための処理が行われています。 ソース → ToolsLib.vbs → ThreeWayMerge コマンドのソース テスト → T_Diff.vbs T_ThreeWayMerge など 関連 → ThreeWayMerge コマンド → UpdateModule コマンド *********************************************************************** <<< ThreeWayMergeOptionClass >>> *********************************************************************** << ThreeWayMerge ThreeWayMergeOptionClass ThreeWayMerge のオプションのクラスです。 マージ設定ファイル のタグ名と同じです。 一部異なる名前のものは下記に特記しています。 .IsConflictError 今までにコンフリクトが発生したかどうか。 初期値=False .IsEnableToRaiseConflictError コンフリクトが発生したらエラーにするかどうか。 初期値=True .BreakStepNum ステップ実行を開始するステップ番号、Empty=ステップ実行しない 初期値=Empty ステップ実行の詳細 → FileWatcher .IsAutoMergeEx True = 拡張自動マージ(デフォルト)、False = diff3 の -E 相当 .IsOutEach コンフリクトが発生したら、それぞれ(左と右)を並べるかどうか。 初期値=False .MergeTemplate コンフリクトが発生したときの置き換えテンプレート。 new_ReplaceTemplateClass 関数 の返り値。 → ReplaceTemplate.xml マージ設定ファイルには、MergeTemplatePath タグに、 new_ReplaceTemplateClass 関数の引数に渡すパスを指定します。 .SingletonKeywords シングルトン キーワード の配列。 正規表現で指定 → 正規表現 .UniqueLineKeywords ユニーク ライン キーワード の配列。 正規表現で指定 ソース → ToolsLib.vbs テスト → T_Diff.vbs T_ThreeWayMerge* 関連 → マージ設定ファイル → ThreeWayMerge の拡張自動マージ → LoadThreeWayMergeOptionClass *********************************************************************** <<< LoadThreeWayMergeOptionClass >>> *********************************************************************** LoadThreeWayMergeOptionClass Function LoadThreeWayMergeOptionClass( in_Path as string ) as ThreeWayMergeOptionClass ThreeWayMergeOptionClass のオブジェクトをマージ設定ファイルからロードします。 【引数】 in_Path ロードするマージ設定ファイルのパス 注意 ThreeWayMergeSet タグはロードしません。 SyncFilesX_Class::LoadScanListUpAll でロードします。 参考 → マージ設定ファイル ソース → ToolsLib.vbs *********************************************************************** <<< ThreeWayMerge の拡張自動マージ >>> *********************************************************************** << ThreeWayMerge ThreeWayMerge の拡張自動マージ ThreeWayMerge は、 Diffutils の diff3 がコンフリクトとするケースでも、その一部のケースで、自動的にマージを 行うようにすることができます。 ThreeWayMergeOptionClass ::IsAutoMergeEx = False の場合は、diff3 -E と同じ マージを行います。 True に設定した場合は、内部で diff3 -A を使って詳細な差分を調べ、より多くのケースで 自動的にマージを行い、コンフリクトするケースを減らします。 シングルトン キーワード や ユニーク ライン キーワード や ReplaceTemplate.xml などを設定すると、より多くの ケースで自動的にマージを行うことができます。 → マージ設定ファイル 参考 → diff3 の詳細なサンプル Add : 追加したケース diff3 -A の出力 自動マージ後 <<<<<<< Base.txt ======= Both >>>>>>> Right.txt Both Left と Right の両方で同じ内容を追加したものは、 そのまま残す。 同じ内容であるということは、チェック済みの可能性が高い。 <<<<<<< Left.txt LLL ||||||| Base.txt ======= RRR >>>>>>> Right.txt LLL RRR Left と Right の両方で異なる内容を追加したものは、 それぞれを残す。 それぞれが別の目的で追加した可能性が高い。 <<<<<<< Left.txt Both LLL ||||||| Base.txt ======= Both RRR >>>>>>> Right.txt Both LLL Both RRR Left と Right の両方で異なる内容を追加したものは、 それぞれを残す。 それぞれが別の目的で追加した可能性が高い。 同じ内容がある部分は、初期化関数など、それぞれで必要な ケースがある。 <<<<<<< Left.txt UniqueLineKeyword A ||||||| Base.txt ======= UniqueLineKeyword A UniqueLineKeyword B >>>>>>> Right.txt UniqueLineKeyword A UniqueLineKeyword B ユニーク ライン キーワード (要設定)がある内容を、 Left と Right の両方で異なる内容を追加したものは、 2つ目以降の同じ内容の行を追加しない。 例: #include ただし、差分があった前後にもユニーク ライン キーワードがあり、 それらの行に、追加した内容と同じ内容の行があれば、一切追加しない。 設定 → ThreeWayMergeOptionClass ::UniqueLineKeywords Modify : 変更したケース diff3 -A の出力 自動マージ後 <<<<<<< Base.txt Before ======= Both >>>>>>> Right.txt Both Left と Right の両方で同じ内容に変更したものは、 そのまま残す。 同じ内容であるということは、チェック済みの可能性が高い。 <<<<<<< Left.txt LLL ||||||| Base.txt Before ======= RRR >>>>>>> Right.txt (コンフリクト エラー、カッコ付きのまま残す) Left と Right の両方で異なる内容に変更したものは、 コンフリクト エラーにする。 (手動で直すか、特定の内容で置き換える) 変更した内容が誤っている可能性が高い。 <<<<<<< Left.txt SingletonKeyword L ||||||| Base.txt SingletonKeyword B ======= SingletonKeyword R >>>>>>> Right.txt SingletonKeyword R シングルトン キーワード (要設定)がある内容を、 Left と Right の両方で異なる内容に変更したものは、 右を残す。 ただし、マージ後に統合した内容に変えたほうが良い。 パッチをあてたほう(右)が特徴を表しているため。 例: プロジェクト名など、1つしか設定できない設定 設定 → ThreeWayMergeOptionClass ::SingletonKeywords <<<<<<< Left.txt Both LLL ||||||| Base.txt Before1 Before2 ======= Both RRR >>>>>>> Right.txt (コンフリクト エラー、カッコ付きのまま残す) Left と Right の両方で異なる内容に変更したものは、 コンフリクト エラーにする。 (手動で直す) 部分的に同じでも、変更した内容が誤っている可能性が高い。 Delete : 削除したケース diff3 -A の出力 自動マージ後 (無くす) <<<<<<< Base.txt Both ======= >>>>>>> Right.txt 同じ個所を削除したものは、 そのまま削除する。 同じ箇所の削除であるということは、チェック済みの可能性が高い。 <<<<<<< Left.txt ||||||| Base.txt Both LLL ======= LLL >>>>>>> Right.txt (コンフリクト エラー、カッコ付きのまま残す) 異なる範囲を削除したものは、 コンフリクト エラーにする。 (手動で直すか、特定の内容で置き換える) 削除した範囲が誤っている可能性が高い。 *********************************************************************** <<< FourWayMerge >>> *********************************************************************** FourWayMerge 未対応 LeftBase と RightBase の2つのほぼ同じテキストがあるとき、双方での編集をもう片方に反映させる マージです。 4-way merge は、一般的に使われている用語ではありません。 LeftBase Left LeftMerged 1 2 Left 4 5 1 AddLeft 2 Left 4 5 1 AddLeft 2 Left 4 <<<<<<< Add AddRight ======= >>>>>>> Delete 5 RightBase Right RightMerged 1 2 Right 4 5 1 2 Right 4 AddRight 5 1 <<<<<<< Add AddLeft ======= >>>>>>> Delete 2 Right 4 AddRight 5 参考 4-way merge: left-base, left, right-base, right, merged result. → version control - Git 4-way merge - Stack Overflow (Web) *********************************************************************** <<< 同期 (ファイル) >>> *********************************************************************** 同期 (ファイル) ここでの同期とは、コピーして2つになったファイルの片方が変更されたとき、もう片方に反映することです。 2つのファイルの差分が少ししかないときに、片方のファイルが変更されたとき、もう片方に反映することも 含みます。 → SyncFilesX_Class (SyncFilesX コマンドのクラス) → IsSynchronizedFilesX → ModuleAssortClass (ModuleAssort コマンドのクラス) → SyncFilesMenu → PatchAndBackUpDictionaryClass *********************************************************************** <<< SyncFilesX_Class (SyncFilesX ソース) >>> *********************************************************************** SyncFilesX_Class (SyncFilesX ソース) SyncFilesX をスクリプトで実行するときに使うクラス。 コールツリー SyncFilesX_App (src) SyncFilesX_Class::LoadScanListUpAll (src) SyncFilesX_Class::LoadScanListUp_Sub // 比較リストの作成 SyncFilesX_Class::OpenCUI (src) // セットとファイルを選択 SyncFilesX_Class::OpenFileCUI (src) 内部データ構造 SyncFilesX_Class (src) ArrayClass< SyncFilesX_SetClass > (src) .Sets ArrayClass< SyncFilesX_FileClass > (src) .Files string .BaseStepPath string .WorkStepPath boolean .IsNextAutoCommit boolean .IsNextAutoMergeFromBase マージ モード SyncFilesX_Class::Merge を呼び出すと、SyncFilesX は、マージ モード(Me.IsMerged = True)になります。 このモードでは、SyncFilesX_FileClass などのメンバー変数は、以下のリンク先のような 意味に変わります。 → SyncFilesX を内部で使うツールとの比較 ソース → SyncFilesMenuLib.vbs テスト → T_SyncFilesX フォルダー 関連 → SyncFilesX を使うツールをテストするには (SyncForTest) *********************************************************************** <<< LoadScanListUpAll (SyncFilesX_Class) >>> *********************************************************************** LoadScanListUpAll (SyncFilesX_Class) << SyncFilesX_Class Sub SyncFilesX_Class::LoadScanListUpAll( SettingFilePath as string, XML_String as string ) SyncFilesX の設定をロードして、同期の状況を調べます。 【引数】 SettingFilePath 設定ファイルのパス XML_String 設定内容(XML形式) SettingFilePath 引数は、相対パスの基準として使われます。 ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< GetWritableFolders (SyncFilesX_Class) >>> *********************************************************************** GetWritableFolders (SyncFilesX_Class) << SyncFilesX_Class Function SyncFilesX_Class::GetWritableFolders() as array of string SyncFilesX を使う際に必要となる書き込み許可するパスの配列を返します。 【引数】 返り値 書き込み許可するパスの配列 LoadScanListUpAll でロードした設定の内容によって返り値は変わります。 ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< Merge (SyncFilesX_Class) >>> *********************************************************************** Merge (SyncFilesX_Class) Sub SyncFilesX_Class::Merge( in_MergeOption as ThreeWayMergeOptionClass ) 3way マージを行います。 【引数】 in_MergeOption → ThreeWayMergeOptionClass フォルダーの 3ウェイ マージ をする ThreeWayMergeSet タグがあるときに呼び出すことができます。 参考 → マージ モード (SyncFilesX_Class) *********************************************************************** <<< GetIsAllSynchronized (SyncFilesX_Class) >>> *********************************************************************** GetIsAllSynchronized (SyncFilesX_Class) << SyncFilesX_Class Function SyncFilesX_Class::GetIsAllSynchronized() as boolean 全てのファイルが同期済みかどうかを返します。 ファイルが追加された場合は、同期済みではないと判定します。 ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< GetIsAllBaseSynchronized (SyncFilesX_Class) >>> *********************************************************************** GetIsAllBaseSynchronized (SyncFilesX_Class) << SyncFilesX_Class Function SyncFilesX_Class::GetIsAllBaseSynchronized() as boolean 全てのベースのファイルが同期済みかどうかを返します。 ワークのファイルが同期済みかどうかには影響しません。 ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< GetCountOfNotSynchronized (SyncFilesX_Class) >>> *********************************************************************** GetCountOfNotSynchronized (SyncFilesX_Class) << SyncFilesX_Class Function SyncFilesX_Class::GetCountOfNotSynchronized() as integer 全てのファイルが同期済みではないセットの数を返します。 ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< OpenCUI (SyncFilesX_Class) >>> *********************************************************************** OpenCUI (SyncFilesX_Class) << SyncFilesX_Class Function SyncFilesX_Class::OpenCUI() as array of string 同期をとる作業を行うユーザーインターフェースを開きます。 【引数】 返り値 "Exit" または "Rescan" 作業が終わると、本関数から返ります。 ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< SyncFilesX を使うツールをテストするには (SyncForTest) >>> *********************************************************************** SyncFilesX を使うツールをテストするには (SyncForTest) SyncFilesX を使うツールをテストの中に、コンフリクトした状態をユーザーが解決したケースのテスト があるときは、SyncFilesX のファイルを選択するメニューで、SyncForTest と自動的に入力するように すれば、テストをするときにユーザーの操作が必要なくなります。 SyncForTest では、ワークがベースに合わせるように、ワークのみ自動的に変更し、ベースは変更 しません。 前回の同期後 今回の同期前 今回の同期後 ベース ワーク ベース ワーク ベース ワーク old old new old new new old old old new old new old old new base new work new base new work old base old work old work old work old work old work old base old work old base old base old base old base old base old work new base old work new base new base old work old base old work old base new work old base new work old base old work new base new work new base new base new work 赤字は更新があったことを示します。 前回の同期で同じ内容になっていたとき、かつ、   ベースだけを更新したときは、     ワークの内容が、ベースの内容になります。   ワークだけを更新したときは、     なにもしません。(同期済みにはします)   ベースとワークの両方を更新したときは、     なにもしません。 (同じ内容の関係から、異なる内容の関係に変わります)(同期済みにはします) 前回の同期で異なる内容になっていたとき、かつ、   ベースを更新したときは(ワークを更新したかどうかに関わらず)、     更新した内容がワークと同じ内容なら       なにもしません。(同期済みにはします)     更新した内容がワークと異なる内容なら       ワークの内容が、ベースの内容+改行+ワークの内容になります。   ワークだけを更新したときは、     なにもしません。(同期済みにはします) 参考 → T_SyncFilesX.vbs の T_SyncFilesX_Test *********************************************************************** <<< バージョンアップ インストーラーとしての SyncFilesX >>> *********************************************************************** バージョンアップ インストーラーとしての SyncFilesX << SyncFilesX_Class SyncFilesX をアプリケーションのバージョンアップをするインストーラーとして使うことができます。 ベース=旧版、ワーク=新版、同期済み(Old)=初期設定、同期前(New)=ユーザー設定(バージョン アップ対象)、として使い、自動的にユーザー設定を更新できないときに、手動で編集できるようにします。 ただし、ユーザーとしては、すべて自動的に更新できることが望まれます。 下記の XML ファイルと、 SyncFilesX_Class の UpdateCUI メソッドを使います。 → 1.00 to 2.00.xml この XML の中で定義した タグによる変数 は、パスを指定する属性などで使用することが できます。 具体的には、restart_vbs、clean_root、base_name、work_name、synced_base、synced_path、 base、path。 SyncFilesX_Class を使うスクリプトは、下記のテストを参考にしてください。 テスト T_SyncFilesX_SyncVersionUp (src) *********************************************************************** <<< LoadRootPaths (SyncFilesX_Class) >>> *********************************************************************** LoadRootPaths (SyncFilesX_Class) << SyncFilesX_Class Sub SyncFilesX_Class::LoadRootPaths( SettingFilePath as string, XML_String as string ) SyncFilesX の設定をロードします。 【引数】 SettingFilePath 設定ファイルのパス XML_String 設定内容(XML形式) SettingFilePath 引数は、相対パスの基準として使われます。 ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< UpdateCUI (SyncFilesX_Class) >>> *********************************************************************** UpdateCUI (SyncFilesX_Class) << バージョンアップ インストーラー Sub SyncFilesX_Class::UpdateCUI() バージョンアップの作業を行うユーザーインターフェースを開きます。 作業が終わると、本関数から返ります。 ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< CustomUpdateFunction (SyncFilesX_Class) >>> *********************************************************************** CustomUpdateFunction (SyncFilesX_Class) CustomUpdateFunctionParameter (SyncFilesX_Class) Dim SyncFilesX_Class::CustomUpdateFunction as Sub ( CustomUpdateFunctionParameter ) Dim SyncFilesX_Class::CustomUpdateFunctionParameter as Variant 手動で同期する作業が終了した後で実行する関数。 *********************************************************************** <<< CustomRestartCodeForRestartVBS (SyncFilesX_Class) >>> *********************************************************************** CustomRestartCodeForRestartVBS (SyncFilesX_Class) CustomUpdateCodeForRestartVBS (SyncFilesX_Class) Dim SyncFilesX_Class::CustomRestartCodeForRestartVBS as string Dim SyncFilesX_Class::CustomUpdateCodeForRestartVBS as string 調整メニューとインストールを再度実行するスクリプトに埋め込むコード。 *********************************************************************** <<< IsSynchronizedFilesX >>> *********************************************************************** IsSynchronizedFilesX Function IsSynchronizedFilesX( Path as string or FilePathClass ) as boolean SyncFilesX で同期が必要なファイルがすべて同期済みであるかどうかを返します。 【引数】 Path SyncFilesX の設定ファイルへのパス、または、 FilePathClass 返り値 すべて同期済みであるかどうか サンプル If IsSynchronizedFilesX( new_FilePathForFileInScript( "SyncFilesX.vbs" ) ) Then If IsSynchronizedFilesX( "SyncFilesX.xml" ) Then ソース → SyncFilesMenuLib.vbs テスト → T_SyncFilesX.vbs T_SyncFilesX_CommandLine 関連 → SyncFilesX *********************************************************************** <<< ModuleAssortClass >>> *********************************************************************** ModuleAssortClass ModuleAssort をスクリプトで実行するときに使うクラス。 内部で g_FileHashCache を使っています。 → CheckOut 各種モジュールのマスター フォルダーからコピーして、プロジェクトを復元します。 → Assort プロジェクトのフォルダーから、各種モジュールのフォルダーへコピーします。 → Commit 指定したプロジェクトの構成を Projects.xml に記録します。 → ExpandPatch パッチ形式になっているマスター モジュールを完全な形に変換します。 → MakePatch マスター モジュールをパッチ形式に変換します。 ソース → SyncFilesMenuLib.vbs → コールツリー *********************************************************************** <<< コールツリー >>> *********************************************************************** コールツリー ModuleAssort → vbslib Prompt.vbs ModuleAssortClass::OpenSetting (src) '// Set "Me.FileMaps" : "ModuleAssort_WorkingClass" ModuleAssortClass::Assort '// Copy files to "Reading-" folder '// ワーキング フォルダーを比較して、同じフォルダーを削除する。 '// ワーキング フォルダーとコミットを比較して、同じフォルダーを削除する。 '// Rename "Reading-" folder to "Work-" folder '// Save "_Modules.xml" file の出力 ModuleAssortClass::OpenSetting '// Set "Me.SynchronizeTargetGraph" (src) ModuleAssortClass::Assort '// Set "target.SynchronizedWithArray" (src) BreadthFirstSearch Me_SetStatusOfSynchronizedWith (src) Me_AddSynchronizedTag (src) *********************************************************************** <<< LoadProjectList (ModuleAssortClass) >>> *********************************************************************** LoadProjectList (ModuleAssortClass) << ModuleAssortClass Sub ModuleAssortClass::LoadProjectList( in_ProjectListPath as string ) Projects.xml ファイルをロードします。 【引数】 in_ProjectListPath Projects.xml ファイルのパス ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< CheckOut (ModuleAssortClass) >>> *********************************************************************** CheckOut (ModuleAssortClass) << ModuleAssortClass Sub ModuleAssortClass::CheckOut( in_ProjectName as string, in_RevisionName as string, in_OutPath as string ) 各種モジュール/ターゲット/リビジョン のフォルダーからコピーして、プロジェクトを復元します。 【引数】 in_ProjectName コミットするプロジェクトの名前 in_RevisionName コミットするプロジェクトのリビジョン名 in_OutPath 復元するプロジェクトを格納するフォルダーのパス サンプル Set sync = new ModuleAssortClass sync.LoadProjectList "Projects.xml" sync.CheckOut "Project_X", "01", "C:\TestProject" ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< OpenSetting (ModuleAssortClass) >>> *********************************************************************** OpenSetting (ModuleAssortClass) << ModuleAssortClass Sub ModuleAssortClass::OpenSetting( in_SettingPath as string ) ModuleAssort.moas ファイルをロードします。 【引数】 in_SettingPath ModuleAssort.moas ファイルのパス ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< Assort (ModuleAssortClass) >>> *********************************************************************** Assort (ModuleAssortClass) << ModuleAssortClass Sub ModuleAssortClass::Assort() プロジェクトのフォルダーから、各種モジュール/ターゲット/リビジョン のフォルダーへコピーします。 参考 → ModuleAssort サンプル Set sync = new ModuleAssortClass sync.OpenSetting "ModuleAssort.moas" sync.Assort ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< Commit (ModuleAssortClass) >>> *********************************************************************** Commit (ModuleAssortClass) << ModuleAssortClass Sub ModuleAssortClass::Commit( in_ProjectName as string, in_RevisionName as string, in_Comment as string ) 指定したプロジェクトの構成を Projects.xml に記録することで、コミットします。 【引数】 in_ProjectName コミットするプロジェクトの名前 in_RevisionName コミットするプロジェクトのリビジョン名 in_Comment リビジョンに関するコメント コミットしたプロジェクトのリビジョンは、 CheckOut できるようになります。 ModuleAssort.moas ファイル に指定されていないファイルがあると、コミットしても元のプロジェクトが完全に 取り出せないことがあります。 そのため、コミットした後は、CheckOut して完全に取り出せることをチェック してください。 サンプル Set sync = new ModuleAssortClass sync.OpenSetting "ModuleAssort.moas" sync.Commit "Project_X", "01", "コメント" ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< ExpandPatch (ModuleAssortClass) >>> *********************************************************************** ExpandPatch (ModuleAssortClass) << ModuleAssortClass Sub ModuleAssortClass::ExpandPatch( in_PatchMasterPath as string ) パッチ形式になっているマスター モジュールを完全な形に変換します。 【引数】 in_PatchMasterPath パッチ形式になっているマスターフォルダーのパス パッチ形式のフォルダーの名前は、ベースのターゲットがパッチと同じなら、 "(リビジョン名)-Patch-of-(ベースのリビジョン名)"、そうでなければ、 "(リビジョン名)-Patch-of-(ベースのターゲット名)-(ベースのリビジョン名)" である必要があります。 完全な形が入ったフォルダーの名前は、"(リビジョン名)-Full" になります。 ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< MakePatch (ModuleAssortClass) >>> *********************************************************************** MakePatch (ModuleAssortClass) << ModuleAssortClass Sub ModuleAssortClass::MakePatch( in_FullSetMasterPath as string, in_BaseMasterPath as string ) マスター モジュールをパッチ形式に変換します。 【引数】 in_FullSetMasterPath パッチ形式に変換するマスターフォルダーのパス in_BaseMasterPath パッチのベースとするマスターフォルダーのパス パッチ形式のフォルダーの名前は、ベースのターゲットがパッチと同じなら、 "(リビジョン名)-Patch-of-(ベースのリビジョン名)" になり、そうでなければ、 "(リビジョン名)-Patch-of-(ベースのターゲット名)-(ベースのリビジョン名)" になります。 ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< SyncFilesMenu >>> *********************************************************************** SyncFilesMenu 複数のフォルダーにある複数のファイルの差分を調べて、Diff ツールやテキスト・エディターを 開くメニューを表示することで、手動でファイルの内容を同じにする作業を支援します。 比較するファイルは、AddFile メソッドを使って1つ1つ指定してください。 ファイルが同じかどうかは、ReadFile の返り値が同じかどうかで判定します。 .IsCompareTimeStamp boolean .IsCompareContents boolean .IsCallViaFile boolean CallViaFile を呼ぶメニュー 80 を追加するかどうか .AddRootFolder (src) Function AddRootFolder( IndexNum, RootFolderPath ) .AddFile (src) Sub AddFile( StepPath ) StepPath を配列にすると、それぞれのフォルダーで異なる 相対パスを設定できます。 その配列の要素数は、AddRootFolder を呼び出した回数に一致させてください。 .AddFileWithLabel Sub AddFileWithLabel( Label, StepPath ) Label 引数が追加された AddFile。 ファイルを選ぶメニューで、ファイル名の右に表示します。 .RootFolders(i).Label ラベル。 i は、AddFile の FileNum .SetParentFolderProxyName 親フォルダーの指定を、サブ・フォルダーに置き換える .Compare (src) Sub Compare() .OpenSyncMenu (src) Sub OpenSyncMenu() .IsSameFolder (src) Function IsSameFolder( FolderAIndexNum, FolderBIndexNum ) サンプル画面 Comparing Base, Update1 and Update2 1. NotSame.txt : Base≠FolderA, Base≠FolderB, FolderA≠FolderB 2. NotSameNo0.txt : Base に存在しません, FolderA≠FolderB 3. Only0.txt : Base のみに存在します 4. SameAll.txt : 同じ内容 99. 戻る ファイルの番号を入力してください >1 NotSame.txt 1. Diff ツールを開く 4. Base のファイルを開く 5. FolderA のファイルを開く 6. FolderB のファイルを開く 99. 戻る 操作の番号を入力してください > サンプル・コード Set menu = new SyncFilesMenu menu.IsCompareTimeStamp = False menu.Lead = "Comparing Base, Update1 and Update2" menu.AddRootFolder 0, "Folder0" menu.AddRootFolder 1, "Folder1" menu.AddRootFolder 2, "Folder2" menu.RootFolders(0).Label = "Base" menu.RootFolders(1).Label = "FolderA" menu.RootFolders(2).Label = "FolderB" menu.AddFile "File1.txt" menu.AddFile "File2.txt" menu.AddFile "File3.txt" menu.Compare menu.OpenSyncMenu データ構造 SyncFilesMenu SyncFilesRoot .RootFolders( Index:Num ) string .AbsPath SyncFilesFile .Files( Key:StepPath ) string .StepPath boolean .IsSameBinary[ n ] ソース → SyncFilesMenuLib.vbs テスト → T_SyncFiles.vbs # main 関連 → SyncFilesX *********************************************************************** <<< SetParentFolderProxyName (SyncFilesMenu) >>> *********************************************************************** SetParentFolderProxyName (SyncFilesMenu) (src) Sub SyncFilesMenu::SetParentFolderProxyName( IndexNum as integer, Name as string ) 親フォルダーの指定を、サブ・フォルダーに置き換えるように設定します。 【引数】 IndexNum フォルダー番号 Name サブ・フォルダー名 サンプル Set menu = new SyncFilesMenu menu.IsCompareTimeStamp = False menu.AddRootFolder 0, "Folder0" menu.AddRootFolder 1, "Folder1" menu.SetParentFolderProxyName 1, "_parent" menu.AddFile "..\Sample.txt" _parent 上記の場合、Folder0\..\Sample.txt と、Folder1\_parent\Sample.txt を比較します。 テスト → T_SyncFiles.vbs # T_SyncFilesParent *********************************************************************** <<< SynchronizeFolder >>> *********************************************************************** SynchronizeFolder Sub SynchronizeFolder( FolderA_Path as string, FolderB_Path as string, SynchronizedPath as string, Mask as string, in_out_Options as Empty ) 2つのフォルダーを同期します。 【引数】 FolderA_Path 同期をとるフォルダーのパス FolderB_Path 同期をとるもう1つのフォルダーのパス SynchronizedPath 同期した内容をとっておくフォルダーのパス Mask ファイル名のフィルター(ワイルドカード) in_out_Options Empty を指定してください 参考 → SyncFilesX_Class (SyncFilesX ソース) ソース → ToolsLib.vbs サンプル SynchronizeFolder "C:\FolderA", "C:\FolderB", "C:\Synchronized", "*", Empty 両方のフォルダーにある同じ名前のファイルが更新されていたら、手動で更新するように エラーが表示されます。 hint_path にできたファイルに、手動で同期する必要がある ファイルのパスが書かれています。 削除されたファイルや、タイムスタンプが過去に 戻ったファイルも手動で同期する必要があります。 例: C:\hint.txt >SynchronizeFolder A: "C:\FolderA" B: "C:\FolderB" 以下のファイルが、両方のフォルダーで変更されました。 "1.txt" Updated: "C:\FolderA\1.txt" Updated: "C:\FolderB\1.txt" サンプル エラーがあったら、その内容をエディターで開く If TryStart(e) Then On Error Resume Next SynchronizeFolder folder_A, folder_B, folder_S, "*.h", Empty If TryEnd Then On Error GoTo 0 If e.num <> 0 Then Set root = LoadXML( e.desc, F_Str ) hint_path = root.getAttribute( "hint_path" ) echo "" echo "自動で同期できないファイルのパスを、テキスト・エディターで表示します。" start GetEditorCmdLine( hint_path ) e.Raise End If テスト → T_SynchronizeFolder.vbs 関連 → SyncFilesX *********************************************************************** <<< その他 >>> *********************************************************************** その他 → PatchAndBackUpDictionaryClass *********************************************************************** <<< SetDateLastModified >>> *********************************************************************** SetDateLastModified Sub SetDateLastModified( in_PathAndDate as dictionary of CDate ) タイムスタンプ(ファイルの更新日時)を設定します。 【引数】 in_PathAndDate キーがタイムスタンプを更新するファイルのパス、アイテムが日付、の辞書 in_PathAndDate 引数のアイテムには、 Date 型 を指定します。 指定する日時のタイムゾーンは、ローカルです。 内部で、vbslib_helper.exe を呼び出しているため、ファイルを1つずつ指定すると遅くなります。。 サンプル SetDateLastModified Dict(Array( _ "FileA.txt", CDate( "2008/06/16 12:00:00" ), _ "FileB.txt", CDate( "2009/09/29 23:59:59" ) )) Dict ソース → vbslib.vbs → vbslib_helper.c テスト → T_File.c T_SetDateLastModified 関連 → File::DateLastModified → CheckFolderMD5List の c.TimeStamp オプション → MD5List の Stamp *********************************************************************** <<< touch >>> *********************************************************************** touch Sub touch( Path as string ) タイムスタンプ(ファイルの更新日時)を現在の日時に更新します。 【引数】 Path タイムスタンプを更新するファイルのパス Path に指定したファイルが存在しないときは、空のファイルを作成します。 ソース → vbslib.vbs → vbslib_helper.c テスト → T_File.c T_touch *********************************************************************** <<< SetDateLastModifiedKS >>> *********************************************************************** SetDateLastModifiedKS Sub SetDateLastModifiedKS( in_PathAndDate as dictionary of CDate, in_Option ) テキスト ファイルの中の $Date: 〜 $ にある日時のテキストを更新します。 【引数】 in_PathAndDate キーが日時を更新するファイルのパス、アイテムが日付、の辞書 in_Option Empty, True = 通常、False = 高速、タイムスタンプは現在にする in_PathAndDate 引数のアイテムを Empty にすると、現在のタイムスタンプに更新します。 in_PathAndDate 引数のアイテムを Date 型 または W3CDTF 形式の文字列の値にすると、 日時のテキストだけでなく、ファイルのタイムスタンプも更新します。 in_PathAndDate 引数のキーを要素数2 の CSV形式(コンマ区切り)にすると、1つ目の要素を 入力ファイルのパス、2つ目の要素を出力ファイルのパスとして処理します。 指定する日時のタイムゾーンは、ローカルです。 内部で、vbslib_helper.exe を呼び出しています。 ただし、in_Option = False を指定したときは、 呼び出しません。 その分、少し高速に処理しますが、$Date: の値を更新したことにより、 タイムスタンプが現在の日時になります。 サンプル SetDateLastModifiedKS Dict(Array( _ "FileA.txt", Empty, _ "FileB.txt", "2009-09-29T23:59:59+09:00" )), Empty Dict FileA.txt ファイルの中の $Date: 〜 $ の中を W3CDTF 形式でファイルのタイムスタンプに 設定します。 FileB.txt ファイルの中の $Date: 〜 $ を下記のように変更します。(タイムゾーンが日本の場合) // $Date: 2009-09-29T23:59:59+09:00 $ サンプル SetDateLastModifiedKS Dict(Array( _ "FileA_Template.txt, FileA.txt", Empty )), Empty FileA_Template.txt ファイルの中の $Date: 〜 $ の中を W3CDTF 形式でファイルのタイム スタンプに設定した FileA.txt ファイルを作成または上書きします。 ソース → vbslib.vbs → vbslib_helper.c テスト → T_File.c T_SetDateLastModified 関連 → SetDateLastModified → File::DateLastModified *********************************************************************** <<< grep (検索) >>> *********************************************************************** grep (検索) Function grep( Parameters as string, OutPath as string ) as array of GrepFound GrepFound ファイルの中で、指定したキーワードを含む行を検索します。 【引数】 Parameters オプションと、キーワードと、検索対象フォルダーやワイルドカード(複数可) OutPath Empty または 検索結果の出力先のファイル・パス 返り値 GrepFound オブジェクト の配列、または Empty 参考 → ファイル名、パス (Windows) Parameters は、Linux の grep コマンド のパラメーターと同じです。 ただし、オプションは、-r と -i と -l と --include のみ指定できます。   -r : サブフォルダーも検索対象にする   -i : 大文字と小文字を区別しないで検索する   -l : キーワードを含むファイルのパスのみ出力する -L : キーワードを含まないファイルのパスを出力する -c : キーワードを含む行の数を取得するだけのため、返り値の LineNum を求める処理をしない   --include : 拡張子を指定する キーワードは、必ず 正規表現 (Linux の egrep形式) で指定してください。 関連 → GrepKeyword -u オプション(vbslib オリジナル)を指定しないと、Unicode テキストにはヒットしません。 -u オプションがなければ、内部で、コマンドプロンプトの findstr コマンドを使用します。 -u オプションを指定したときは、内部で VBScript.RegExp が使われます。 OutPath 引数と返り値 OutPath 引数に 検索結果の出力先のファイル・パスを指定すると、 下記のサンプル のように 表示され、返り値は Empty になります。 返り値を GrepFound オブジェクトの配列にしたい ときは、OutPath 引数に Empty を指定してください。 RunProg 同様、 EchoOff オブジェクト を使ったり、OutPath 引数に g_VBS_Lib.NotEchoStartCommand を指定すると、見つかった場所について、echo 表示しなく なります。 サンプル "define" を検索する。 結果は返り値で取得する。 検索対象ファイルは、..\FolderA フォルダーで、サブ・フォルダーも含める。(-r) founds = grep( "-r ""define"" ""..\FolderA\*""", Empty ) '// as array of GrepFound '// 返り値のサンプル '// UBound( founds ) は、見つかった行数−1 '// founds(0).Path = "..\FolderA\grep_target1.txt" '// founds(0).LineNum = 2 '// founds(0).LineText = " #define string" For Each found In founds echo found.LineText Next \* GrepFound GrepFound::Path プロパティ Parameters に指定した検索対象のパスが、相対パスなら、Path プロパティも 相対パスになります。 そのときの基準フォルダーは、カレント・フォルダーになります。 サンプル 結果をファイルに出力する "define" を検索する。 結果は、"grep_out.txt" ファイルに出力する。 検索対象ファイルは、拡張子が .txt と .ini で、サブ・フォルダーも含める。(-r) 大文字小文字は区別しない。(-i) grep "-r -i define *.txt *.ini", "grep_out.txt" grep_out.txt ファイルのサンプル grep_target1.txt:2: define string grep_target3.txt:2: define string grep_target3.txt:4: define text sub\grep_target1.txt:2: define string サンプル ファイル・パスの一覧を得る(-l オプション) Set c = g_VBS_Lib founds = grep( "-r -l ""define"" ""..\FolderA\*""", c.NotEchoStartCommand ) For Each found In founds echo found.Path Next サンプル テキストファイルだけを検索対象にする Set ds = new CurDirStack extensions = g_Vers("TextFileExtension").Keys extensions = CSVFrom( extensions ) extensions = Replace( extensions, ",", " *." ) extensions = Left( "*." + extensions, Len( extensions ) ) cd "..\FolderA" founds = grep( "-r ""define"" "+ extensions, Empty ) '// as array of GrepFound For Each found In founds echo found.Path Next 互換性 "|" (バーチカルライン)は、OR の意味になります。 "|" を検索したいときは、"\|" のようにエスケープしてください。 "-" を検索したいときは、"\-" のようにエスケープしてください。 "/"(スラッシュ)は、一般文字であり、エスケープする必要はありません。 + のメタ文字を使うことができます。 単語単位はできません。 -u オプションがなければ、内部で、コマンドプロンプトの findstr コマンドを使用します。 -u オプションがあれば、内部で、VBScript.RegExp を使用します。 \ 文字は bash を経由したときと同じになります。 つまり、\\ が \ に、\" が " に置き換わった後の文字列が、正規表現に適用されます。 例: \( または \\( を指定すると、一般文字の(制御文字でない) ( 例: \\\\ を指定すると、一般文字の(制御文字でない) \ ExpandWildcard_Sort 変数 が使えます。 ただし、-u オプションが付いていないと無視されます。 なぜなら、 findstr で表示しながら検索するため。 ソース → vbslib.vbs テスト → T_Grep.vbs 参考 → 正規表現 → 互換性 → grep コマンド (Linux) → findstr (DOS) 関連 → sscanf 文字列の途中を取り出します。 → FindStringLines キーワードがある行だけ抽出します。 → grep コマンド (vbslib) *********************************************************************** <<< SortGrepFoundArray >>> *********************************************************************** SortGrepFoundArray Sub SortGrepFoundArray( Founds as array of GrepFound ) GrepFound GrepFound クラスのオブジェクトの配列をソートします。 【引数】 Founds GrepFound クラスのオブジェクトの配列 ソース → vbslib.vbs 関連 → ExpandWildcard_Sort 変数 *********************************************************************** <<< GrepClass >>> *********************************************************************** GrepClass ファイルの中で、指定したキーワードを含む行を検索します。 VBScript.RegExp にあるメンバーと同じものは、同じ名前にしています。 string .Pattern 検索キーワード (正規表現) \ は、bash を経由しないときと同じになります。 "" を指定すると .IsOutFileNameOnly = True なら、 すべてのファイルを検索結果に含めます。 boolean .IgnoreCase 大文字小文字を区別しないかどうか boolean .IsRecurseSubFolders サブ・フォルダーも再帰的に検索対象にする。 Execute の TargetPath 引数に PathDictionaryClass を指定したときは、無視されます boolean .IsOutFileNameOnly ファイル名のみ出力する boolean .IsInvertMatch キーワードにマッチしないものを出力する boolean .IsHitCount LineNum を求める処理をしない Function .Execute 指定したファイルの中に対して、検索を実行する サンプル Set a_grep = new GrepClass a.grep.Pattern = "" founds = a_grep.Execute( "folder\*.txt" ) ソース → vbslib.vbs テスト → T_Grep.vbs T_GrepClass1 T_Grep1 の *_U (grep -u の内部で使っている) *********************************************************************** <<< Execute (GrepClass) >>> *********************************************************************** Execute (GrepClass) << GrepClass Function GrepClass::Execute( TargetPath as variant ) as array of GrepFound GrepFound ファイルの中で、指定したキーワードを含む行を検索します。 【引数】 TargetPath 検索対象フォルダーやワイルドカード(複数可)、または PathDictionaryClass 返り値 GrepFound オブジェクト の配列、または Empty TargetPath 引数は、 VBScript.RegExp の Execute メソッドの引数と異なります。 サンプル founds = a_grep.Execute( "folder\*.txt" ) founds = a_grep.Execute( Array( "folder_A\*.txt", "folder_B\*.txt" ) ) paths = ArrayFromWildcard( "folder" ) paths.AddRemove "folder\.svn" founds = a_grep.Execute( paths ) *********************************************************************** <<< ToRegExpPattern >>> *********************************************************************** ToRegExpPattern ToOldRegExpPattern Function ToRegExpPattern( NotEscapedString as string ) as string egrep 仕様・VBScript 仕様の正規表現で使われるメタ文字も検索できるように変換します。 Function ToOldRegExpPattern( NotEscapedString as string ) as string grep 仕様の正規表現で使われるメタ文字も検索できるように変換します。 【引数】 NotEscapedString メタ文字も含む可能性がある検索キーワード 返り値 メタ文字をエスケープした検索キーワード サンプル Assert ToRegExpPattern( "[0](1)\" ) = "\[0\]\(1\)\\" Assert ToOldRegExpPattern( "[0](1)\" ) = "\[0\](1)\\" 参考 → 正規表現 → 互換性 (正規表現) → VBScript.RegExp ソース → vbslib.vbs ToRegExpPattern → vbslib.vbs ToOldRegExpPattern テスト → T_Grep.vbs # [T_GrepKeyword] 関連 → GrepKeyword *********************************************************************** <<< GrepKeyword >>> *********************************************************************** (src) GrepKeyword EGrepKeyword (src) GrepExpression (src) Function GrepKeyword( NotEscapedString as string ) as string Function EGrepKeyword( NotEscapedString as string ) as string Function GrepExpression( RegularExpression as string ) as string 検索キーワードを grep や egrep のコマンドラインに指定する形式に変換します。 【引数】 NotEscapedString 検索キーワード RegularExpression 正規表現 返り値 grep や egrep のコマンドラインに指定する形式 返り値を grep や egrep のパラメーターに指定するときは、" " で囲んでください。 ' ' で囲まないでください。 なぜなら \ がコマンドラインのエスケープ開始文字ではなく なるからです。 grep -r "\---" * RegularExpression 引数 RegularExpression 引数に指定した \ 文字は bash を経由しないときと同じになります。 例: \\\\ = \ 文字が2つをキーワードとする RegularExpression 引数の先頭に、- を指定したときにオプションと扱われないように、 先頭に \ が付いたものが返ります。 サンプル Assert GrepKeyword( "abc[0]\def" ) = "abc\\[0\\]\\\\def" Assert GrepExpression( "abc[A-Z]\def" ) = "abc[A-Z]\\def" Assert GrepKeyword( "---\" ) = "\---\\\\" Assert GrepExpression( "---\" ) = "\---\\" テスト → T_Grep.vbs # [T_GrepKeyword] 関連 → ToRegExpPattern *********************************************************************** <<< find >>> *********************************************************************** (src) find Function find( keyword as string, path as string ) as string テキストファイルの中で、指定したキーワードを含む行をまとめて返します。 【引数】 keyword 検索するキーワード path テキストファイルのパス 返り値 キーワードを含む行、または複数行 サンプル: lines = find( " Fail. 返り値のサンプル 関連 → FindStringLines *********************************************************************** <<< find_c >>> *********************************************************************** (src) find_c Function find_c( keyword as string, path as string ) as integer テキストファイルの中で、指定したキーワードを含む行数を返します。 【引数】 keyword 検索するキーワード path テキストファイルのパス 返り値 キーワードを含む行数 *********************************************************************** <<< SearchStringTemplate >>> *********************************************************************** SearchStringTemplate Function SearchStringTemplate( FolderPath as string, RegularExpressionPart as string, TemplateStrings as array of string, Opt as Empty ) as array of array of GrepFound テキストファイルの中をキーワードで検索し、どのテンプレートと一致するかを一覧します。 【引数】 FolderPath 検索対象フォルダーやワイルドカード → Execute (GrepClass) RegularExpressionPart テンプレートの中にあるキーワード。複数行不可 → 正規表現 TemplateStrings テンプレート(複数行可)、または、その配列 Opt Empty を指定してください 返り値 GrepFound オブジェクト の配列の配列 キーワードが見つかった位置が、指定したテンプレートの一部であるものと、そうでないものを 一覧します。 これを応用すれば、テンプレートの内容が違っていたり、古いテンプレートのまま になっていたりするものを見つけることができます。 TemplateStrings 引数 テンプレートは、可変の部分を "${変数名}" のように記述してください。 可変の部分は、複数行 にまたぐことができます。 SearchStringTemplate 関数はテンプレートの中の変数名を無視しま すが、テンプレートを ScanFromTemplate 関数などにそのまま渡すことができます。 ${ 文字は "$\{" と記述してください。 $\ 文字は "$\\" と記述してください。 関数名: ${FunctionName} 引数: ${Arguments} 返り値: ${RerutnValue} 返り値 返り値が founds のとき、founds(t)(i) の t は TemplateStrings 引数の配列番号、i はテンプレート にマッチした複数の場所に 0 から順番につけた番号です。 i が配列の要素数に一致する要素は、TemplateStrings 引数に指定したどのテンプレートにも マッチしなかったテキストについてです。 配列の要素は、 GrepFound オブジェクト です。 GrepFound オブジェクトのメンバー変数の内容は、次の通りです。 .Path ファイル名 .LineNum Empty .LineText Array( テンプレートの開始位置(1以上), テンプレートの次の位置 ) GetEchoStr に渡すと、次のように変わります。 .Path ファイル名 .LineNum 行番号。 キーワードがある位置の行番号 .LineText テンプレートにマッチしたファイルの中の内容。 複数行の場合あり ExpandWildcard_Sort 変数 が使えます。 サンプル TargetFolder フォルダーの中にあるテキストファイルの中から "(((" を検索し、見つかった 位置に、テンプレート(下記の複数行の文字列) がマッチしているものと、マッチしていない ものに分けます。 founds = SearchStringTemplate( "TargetFolder", "(((", _ "/***********" +vbCRLF+ _ "((( ${FunctionName} ))$\{)" +vbCRLF+ _ "************/" +vbCRLF, Empty ) Assert founds(0)(0).LineNum = 1 '// マッチした Assert founds(0)(1).LineNum = 5 '// マッチした Assert founds(1)(0).LineNum = 9 '// マッチしなかった 検索対象のテキストファイル 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: /*********** ((( FuncA ))${) ************/ /*********** ((( FuncB ))${) ************/ /*********** ((( FuncC ))) ************/ … RegularExpressionPart 引数に指定した ((( にヒットするが、   テンプレートに指定した ${ がないのでマッチしない ソース → ToolsLib.vbs テスト → T_fc.vbs T_SearchStringTemplate 関連 → ReplaceStringTemplate → EchoOld (ReplaceTemplateClass) → ScanFromTemplate → GetLineNumOfTemplateDifference → PartCmp *********************************************************************** <<< GetLineNumOfTemplateDifference >>> *********************************************************************** GetLineNumOfTemplateDifference Function GetLineNumOfTemplateDifference( TargetString as string, RegularExpressionPart as string, TemplateString as string ) as integer 指定した文字列の中で、テンプレートに一致しない場所の行番号を返します。 【引数】 TargetString テンプレートが含まれる(はずの)文字列 RegularExpressionPart テンプレートの中にあるキーワード。複数行不可 → 正規表現 TemplateString テンプレート(複数行可) 返り値 テンプレートに一致しない場所の行番号。 0=すべて一致 テンプレートの書き方について、 → SearchStringTemplate サンプル line_num = GetLineNumOfTemplateDifference( _ "----" +vbCRLF+_ "----" +vbCRLF+_ "Parameter1: abc" +vbCRLF+_ "Param2: def" +vbCRLF+_ "Parameter3: ghi" +vbCRLF+_ "----" +vbCRLF, _ _ "Parameter1", _ _ "Parameter1: ${1}" +vbCRLF+_ "Parameter2: ${2}" +vbCRLF+_ "Parameter3: ${3}" +vbCRLF ) Assert line_num = 4 '// Param2: の場所の行番号 ソース → ToolsLib.vbs テスト → T_fc.vbs T_GetLineNumOfTemplateDifference 関連 → RunGetDifference (ReplaceTemplateClass) *********************************************************************** <<< CreateFile >>> *********************************************************************** (src) mini (src) CreateFile Function CreateFile( path as string, text as string ) as string 指定のテキストを内容としたテキストファイルを作成します。 【引数】 path 作成するテキストファイルのパス text テキストファイルの内容 返り値 作成したテキストファイルのフル・パス 参考 → ファイル名、パス (Windows) → Out of Writable 警告 [E_OutOfWritable] text に指定した文字列の末尾に改行が自動的に入らないテキストが作成されます。 サンプル カレントフォルダに a.txt ファイルを作る CreateFile "a.txt", "ABC" サンプル obj の xml プロパティを、テンポラリファイルに出力して開く start start CreateFile( "*.xml", obj.xml ) obj xml Unicode 形式かどうかを維持してファイルの内容を変更する サンプル 注意 下記の方法より、 OpenForReplace の Text を変更する方が扱いやすいでしょう。 path = "_work.txt" text = ReadFile( path ) '// ここで text を変更 Set cs = new_TextFileCharSetStack( ReadUnicodeFileBOM( path ) ) CreateFile path, text cs = Empty ReadFile new_TextFileCharSetStack ReadUnicodeFileBOM 補足 new_TextFileCharSetStack を使うと、テキストファイルのフォーマットを指定できます。 new_IsSafeFileUpdateStack を使うと、内部で SafeFileUpdate を使います。 path に相対パスを指定したとき、基準フォルダはカレント・フォルダになりますが、ワイルド カードが含まれていると、テンポラリ・フォルダになります。 詳しくは、 → GetTempPath テスト → T_File.vbs [T_CreateFile] → T_File.vbs [T_CreateFile_Err] 関連 → WaitForFile → GetTempPath → OpenForWrite → テキストファイルを作成する (VBS) → FileT_create (clib) *********************************************************************** <<< Out of Writable 警告 [E_OutOfWritable] >>> *********************************************************************** Out of Writable 警告 [E_OutOfWritable] スクリプトが想定していない場所に、ファイルを出力しようとしたとき、出力してよいかユーザに 確認を取ります。 コマンドプロンプトへの出力例: [WARNING] Out of Writable, see "Out of Writable" in vbslib manual. "C:\home\scriptlib\vbslib_new\_src\Test\vbslib_test\T_Writable\work2" 確認ウィンドウ: vbslib を使ったスクリプトは、ダブルクリックした .vbs ファイルがあるフォルダ、または、ユーザが 設定した場所のフォルダのどちらかしか、ファイルを作成したり削除しないように作られます。 このルールが守られなかったとき、警告が出ます。 この機能は、スクリプト開発者のミスによって問題が起きないようにするためのものであり、 悪意のあるスクリプトは、この警告を出さないでファイルを壊すこともあります。 この警告が出る最も多い原因は、ユーザが設定した場所に書き込み許可を設定しなかった スクリプトのバグです。 スクリプト開発者は、 AppKeyClass::NewWritable を使ってください。 テンポラリ フォルダー の中と、拡張子が .updating のパスについては、NewWritable を 使う必要はありません。 グローバル変数のデストラクタでファイル操作をすると、メイン関数で作成した Writables オブジェクトが削除された後なので、必ず警告が発生します。 Out of Writable 警告のデバッグ デバッガでスクリプトを起動し、Out of Writable の警告で、プログラムの終了やキャンセルを 選ぶと、例外によりブレークします。 AppKeyClass::Ask Err.Raise E_OutOfWritable,, "Out of Writable """ & CheckPath & """" ' Watch g_CurrentWritables.CurrentPathes and CheckPath g_CurrentWritables.CurrentPathes や CheckPath をウォッチウィンドウでチェックしてください。 Writable の状況を確認したいときは、 AppKeyClass::Watch をばらまいてください。 コールツリー AppKey.NewWritable Writables::SetPathes g_CurrentWritables.AskFileAccess m_Pathes(i) = abs_path + "\" Writable の登録 m_Pathes( UBound( m_Pathes ) ) = g_TempFile.m_FolderPath + "\" テンポラリを Writable に登録 Writables::Enable Writable を有効にする WritablesStack::PushPathes CurrentWritables::PushPathes m_PathesStack.Push mkdir など g_AppKey.CheckWritable 公開キーのメソッド m_Key.CheckWritable 隠しキーのメソッド g_CurrentWritables.CheckWritable "...\*" 以外のチェック m_Key.CheckPlusWritable "...\*" で追加されたものと比較 If IsEmpty( abs_path ) Then Exit Sub Writable の中なので OK m_Key.Ask 警告の表示 m_PlusWritables( UBound( m_PlusWritables ) ) = abs_path Writable を追加 テスト → T_Writable *********************************************************************** <<< NewWritable (AppKeyClass) >>> *********************************************************************** NewWritable (AppKeyClass) (src) [ 親: Out of Writable 警告 ] Function AppKeyClass::NewWritable( Pathes as variant ) as Writables 書き込み可能なフォルダの設定オブジェクトを生成します。 【引数】 Pathes 書き込み可能なフォルダの パス 。文字列、または文字列の配列 返り値 Writable 設定オブジェクト → Writables::Enable 本関数を正しく使えば、 Out of Writable 警告 が出ないようになります。 通常は、サンプル1のように使い、NewWritable 関数の引数を調整します。 もしくは、使っているオブジェクトの GetWritable メソッド を使います。 AppKeyClass は、 Main 関数 の第2引数である AppKey のクラスです。 AppKey は、なるべく他の関数に渡さないようにしてください。 渡すと、書き込み可能なフォルダの設定を不正に変えられる可能性があります。 返り値である Writable 設定オブジェクトは、他の関数に渡すことができます。 Pathes に指定するパスの最後に "\*" があると、新規フォルダの作成を可能にし、 新規フォルダの中は書き込み可能にします。 "C:\folder1\*" とすると、C:\folder1 にファイルを作成できませんが、フォルダは作成できます。 すでに C:\folder1 にあるフォルダの中は、上書きされないように、書き込み不可 になります。 テンポラリ フォルダー の中と、拡張子が .updating のパスについては、NewWritable を使う必要はありません。 Program Files などの OS のシステムフォルダを NewWritable に指定すると、 System folder access の警告になります。 この警告を自動的に無視するときは、 NewWritable を呼び出す前に SetWritableMode に F_IgnoreIfWarn を指定して、 呼び出してください。 サンプル1: カレントフォルダを書き込み可能にする Sub Main( Opt, AppKey ) Set w_= AppKey.NewWritable( "." ).Enable() '// 書き込み可能な範囲 w_ = Empty '// これを書かないときは、関数が終わるまでが範囲 End Sub NewWritable( "." ) Enable サンプル: デスクトップに新規フォルダの作成を可能にし、新規フォルダの中だけ 書き込み可能にする。 新規フォルダを作成することができるフォルダのパスの後に \* を指定してください。 Sub Main( Opt, AppKey ) desktop = g_sh.SpecialFolders( "Desktop" ) Set w_= AppKey.NewWritable( desktop+"\*" ).Enable() mkdir desktop+"\New Folder" '// 書き込み可能な範囲 w_ = Empty '// これを書かないときは、関数が終わるまでが範囲 End Sub このエラーが発生したときは、次のいずれかがエラー メッセージに含まれます。 Cannot overwrite NOT NEW file Cannot overwrite NOT NEW folder サンプル: 複数のフォルダを書き込み可能にする Sub Main( Opt, AppKey ) Set w_= AppKey.NewWritable( Array("out1","out2") ).Enable() '// 書き込み可能な範囲 End Sub サンプル: 後で out フォルダを書き込み可能にする Sub Main( Opt, AppKey ) Set wr = AppKey.NewWritable( "out" ) sub2 wr End Sub Sub sub2( wr ) Set w_ = wr.Enable() '// "out" に書き込み可能な範囲 End Sub 関連 → Out of Writable 警告 → SetWritableMode → ファイル名、パス テスト → T_Writable フォルダ → [T_Writable] の説明 *********************************************************************** <<< GetWritable メソッド >>> *********************************************************************** GetWritable メソッド Function ClassA::GetWritable() as array of string 書き込み許可の設定が必要なフォルダーの一覧を取得します。 GetWritable メソッドは、それぞれのクラスで定義してください。 使用サンプル: Sub main2( Opt, AppKey ) Dim writable : writable = m.GetWritable If not AppKey.InPath( writable, "..\out" ) Then Error Dim w_ : Set w_= AppKey.NewWritable( writable ).Enable() '// 書き込み可能な範囲 w_ = Empty End Sub writable InPath writable NewWritable writable 定義サンプル: Class ClassA Public Function GetWritable() GetWritable = Array( "Work" ) End Function End Class *********************************************************************** <<< InPath (AppKeyClass) >>> *********************************************************************** InPath (AppKeyClass) (src) Function AppKeyClass::InPath( Paths as Array of string, EnablePath as string ) as boolean Paths に指定したパスの集合が、EnablePath の中に含まれるかどうかを返します。 【引数】 Paths パスの配列 EnablePath 許可しているパス 返り値 Paths の要素がすべて許可しているパスに含まれているかどうか ファイル: vbslib.vbs サンプル: → GetWritable メソッド *********************************************************************** <<< CheckWritable (AppKeyClass) >>> *********************************************************************** CheckWritable (AppKeyClass) (src) Sub AppKeyClass::CheckWritable( Path as string, Opt as variant ) 指定したパスが、 Enable (Writables) されているかどうかチェックします。 【引数】 Path チェックするパス Opt Empty または c.ForMkDir (*1) (*1) Opt 引数に、g_VBS_Lib.ForMkDir を指定すると、Path に指定したパスの フォルダーを作るために、Path の子フォルダー(Path より長いパス)だけが、 Enable (Writables) されていたときでも、チェックに引っかからなくなります。 Path が、Enable (Writables) されていなかったら、 Out of Writable 警告 が出ます。 サンプル g_AppKey.CheckWritable "C:\Users\user1\log.txt", Empty 関連 → mkdir_for *********************************************************************** <<< Watch (AppKeyClass) >>> *********************************************************************** Watch (AppKeyClass) (src) Sub AppKeyClass::Watch() Writable の状態を echo 出力します。 サンプル g_AppKey.Watch g_AppKey は、公開キーとして用意されているグローバル変数です。 *********************************************************************** <<< Enable (Writables) >>> *********************************************************************** Enable (Writables) (src) [ 親: Out of Writable 警告 ] Function Writables::Enable() as WritablesStack 書き込み可能なフォルダを設定します。 【引数】 返り値 WritableStack オブジェクト Writables は、 AppKeyClass::NewWritable から取得できます。 Dim w_:Set w_= AppKey.NewWritable( "." ).Enable() 返り値の WritableStack オブジェクトが、どこからも参照されなくなったら、書き込み 可能では無くなります。 1つ目の WritableStack が存在するときに、2つ目の Writable::Enable をすると、ネスト して、2つ目の WritableStack のみ有効になります。 2つ目の WritableStack が参照 されなくなったら、1つ目の WritableStack が有効になります。 Set w1 = AppKey.NewWritable( "out1" ) Set w2 = AppKey.NewWritable( "out2" ) Set w1_ = w1.Enable() '// "out1" が書き込み可能 Set w2_ = w2.Enable() '// "out2" が書き込み可能 w2_ = Empty '// "out1" が書き込み可能 w1_ = Empty 関連 → Out of Writable 警告 *********************************************************************** <<< SetWritableMode >>> *********************************************************************** SetWritableMode (src) [ 親: Out of Writable 警告 ] Sub SetWritableMode( Mode as integer ) Sub AppKeyClass::SetWritableMode( Mode as integer ) NewWritable で指定していないフォルダにライトしようとしたときの動きを設定します。 F_AskIfWarn ユーザにライトしていいかどうかを確認します(デフォルト) F_ErrIfWarn E_OutOfWritable エラーにします F_IgnoreIfWarn 警告を無視します(AppKeyClass::SetWritableMode でのみ指定可能) サンプル SetWritableMode F_ErrIfWarn サンプル: F_IgnoreIfWarn には、AppKey が必要 writable_path = env("%ProgramFiles%")+"\SampleApp" Assert InStr( writable_path, "Program Files" ) > 0 AppKey.SetWritableMode F_IgnoreIfWarn Set w_=AppKey.NewWritable( writable_path ).Enable() SetWritableMode F_AskIfWarn Program Files に書き込み許可するときは、以下の手順が最も安全です。 ・パスに Program Files が入っていることをチェック ・F_IgnoreIfWarn に設定して警告を抑制して書き込み許可を設定 ・F_AskIfWarn に設定を戻す 関連 → Out of Writable 警告 *********************************************************************** <<< g_CurrentWritables.CurrentPathes >>> *********************************************************************** g_CurrentWritables.CurrentPathes Dim g_CurrentWritables.CurrentPathes as array of string 現在書き込みを許可しているパスの配列。 関連 → Out of Writable 警告のデバッグ → Code (ArrayClass) *********************************************************************** <<< OpenForRead >>> *********************************************************************** OpenForRead Function OpenForRead( Path as string ) as TextStream テキストファイルを開きます。(リード用=ファイルから入力します) 【引数】 Path 開くファイルのパス → ファイル名、パス 返り値 ファイルのストリーム → TextStream (VBScript) FileSystemObject::OpenTextFile と異なり、エラーがあったら、 エラーメッセージに Path が付きます。 E_FileNotExist エラー または E_PathNotFound エラー になります。 返り値を使って呼び出せるメソッドは、FileSystemObject::OpenTextFile と同じです。 サンプル Set c = g_VBS_Lib Set args = WScript.Arguments.Unnamed If args.Count = 0 Then path = InputPath( "ファイルのパス >", c.CheckFileExists ) Else path = args(0) End If Set file = OpenForRead( path ) Do Until file.AtEndOfStream line = file.ReadLine() '// If InStr( line, "DEBUG" ) > 0 Then echo line Loop file = Empty OpenForRead 文字コードを指定するときは、 new_TextFileCharSetStack を使ってください。 ただし、Shift-JIS, Unicode, UTF-8(BOMあり) は、使わなくても自動的に文字コード を判定して、正しく読み込みます。 Set cs = new_TextFileCharSetStack( "EUC-JP" ) Set file = OpenForRead( args(0) ) cs = Empty Do Until file.AtEndOfStream line = file.ReadLine() Loop ソース → vbslib.vbs テスト → T_File.vbs # [T_OpenFile] 関連 → FileSystemObject::OpenTextFile → new_TextFileCharSetStack 既定の文字コードを指定します → ReadFile → ReplaceTextFile → VBScript - テキストファイルの内容を読む (Read) → StringStream クラス *********************************************************************** <<< AnalyzeCharacterCodeSet >>> *********************************************************************** AnalyzeCharacterCodeSet Function AnalyzeCharacterCodeSet( Path as string ) as integer or string ファイルの文字 コード セットを判定します。 【引数】 Path 文字コードを判定するファイルのパス 返り値 文字 コード セット 本関数は、バージョンによって解析の性能が異なります。 現在のバージョンは、以下の方法で解析しています。 Unicode の BOM (ByteOrderMaker) XML宣言 (?xml) の encoding WHITE SQUARE エンコーディング判定法 (独自) サンプル 同じ文字コードを使ってファイルを作成する Set cs = new_TextFileCharSetStack( AnalyzeCharacterCodeSet( "File1.txt" ) ) CreateFile "File1.txt", "abc" cs = Empty File1.txt MIME や HTML の charset によって、文字コードが指定される場合は、文字コードを調べて new_TextFileCharSetStack を使って開きなおしてください。 返り値 c.Unicode 先頭に UTF-16 の BOM (FF FE) があるとき c.UTF_8 先頭に UTF-8 の BOM (EF BB BF) があるとき c.No_BOM 先頭に BOM がなく、 XML宣言 (?xml) の encoding がないとき c.UTF_8_No_BOM 先頭に BOM がなく、 XML宣言 (?xml) の encoding="UTF-8" があるとき 先頭に BOM がなく、 XML宣言 (?xml) の encoding がなく、 new_TextFileCharSetStack が UTF-8 のとき (文字列) 先頭に BOM がなく、 XML宣言 (?xml) の encoding があり、"UTF-8" 以外のとき Empty 解析できないとき、Windows の OEMのとき、ファイルがないとき ソース → vbslib.vbs → vbslib_helper.c ReadCharacterEncodingCharacterCommand テスト → T_Binary.vbs T_AnalyzeCharacterCodeSet 関連 → new_TextFileCharSetStack → Read_XML_Encoding → 文字エンコーディングの指定方法 → ファイル内の文字コードの指定 *********************************************************************** <<< ReadUnicodeFileBOM >>> *********************************************************************** ReadUnicodeFileBOM Function ReadUnicodeFileBOM( Path as string ) as integer ファイルの文字コードを判定するために、ファイルの先頭にある BOM を読みます。 【引数】 Path 文字コードを判定するファイルのパス 返り値 BOM の文字コード 返り値 c.Unicode 先頭に UTF-16 の BOM (FF FE) があるとき c.UTF_8 先頭に UTF-8 の BOM (EF BB BF) があるとき c.No_BOM BOM がないとき Empty ファイルが無いとき Set c = g_VBS_Lib です。 ソース → vbslib.vbs テスト → T_File.vbs T_ReadUnicodeFileBOM 関連 → AnalyzeCharacterCodeSet *********************************************************************** <<< GetStringFromCharacterCodeSet >>> *********************************************************************** GetStringFromCharacterCodeSet Function GetStringFromCharacterCodeSet( in_CharacterCodeSetConstant as integer or string ) as string vbslib の文字コード セットの数値から、文字列に変換します。 【引数】 in_CharacterCodeSetConstant vbslib の文字コード セットの数値 返り値 文字コード セットの文字列 サンプル Assert GetStringFromCharacterCodeSet( g_VBS_Lib.Shift_JIS ) = "Shift_JIS" 詳細 vbslib の 文字コード セットの数値 文字コード セットの文字列 c.Shift_JIS "Shift_JIS" c.EUC_JP "EUC-JP" c.Unicode "Unicode" c.UTF_8 "UTF-8" c.UTF_8_No_BOM "UTF-8-No-BOM" c.ISO_2022_JP "ISO-2022-JP" c.No_BOM "Shift_JIS" Empty "Shift_JIS" 仕様の理由 Shift_JIS は、 HTML の、META タグの charset 属性に指定できる値です。 ソース → vbslib.vbs テスト → T_File.vbs T_GetStringFromCharacterCodeSet 関連 → GetCharacterCodeSetFromString *********************************************************************** <<< GetCharacterCodeSetFromString >>> *********************************************************************** GetCharacterCodeSetFromString Function GetCharacterCodeSetFromString( in_CharacterCodeSetString as string ) as integr or string 文字コード セットの文字列から、vbslib の数値に変換します。 【引数】 in_CharacterCodeSetString 文字コード セットの文字列 in_UTF_8_CharacterCodeSet "UTF-8" に対する vbslib の文字コード セットの数値 返り値 vbslib の文字コード セットの数値 サンプル Assert GetCharacterCodeSetFromString( "Shift_JIS", c.UTF_8_No_BOM ) = g_VBS_Lib.Shift_JIS 詳細 vbslib の 文字コード セットの数値 文字コード セットの文字列 "Shift_JIS" c.Shift_JIS "EUC-JP" c.EUC_JP "Unicode" c.Unicode "UTF-16" c.Unicode "UTF-8" c.UTF_8_No_BOM または c.UTF_8 in_UTF_8_CharacterCodeSet 引数の値、 "UTF-8-BOM" c.UTF_8 "UTF-8-No-BOM" c.UTF_8_No_BOM "ISO-2022-JP" c.ISO_2022_JP その他 in_CharacterCodeSetString 引数 ソース → vbslib.vbs 関連 → GetStringFromCharacterCodeSet *********************************************************************** <<< ReadLineSeparator >>> *********************************************************************** (src) ReadLineSeparator Function ReadLineSeparator( Path as string ) as integer ファイルの先頭行を読んで、改行文字の種類を返します。 【引数】 Path 改行文字の種類を判定するファイルのパス 返り値 vbCRLF または vbLF ファイルによっては、改行文字の種類がバラバラになっていることもあります。 サンプル f.LineSeparator = ReadLineSeparator( "File1.txt" ) テスト → T_File.vbs # [T_ReadLineSeparator] 関連 → new_TextFileLineSeparatorStack *********************************************************************** <<< GetLineCount >>> *********************************************************************** GetLineCount Function GetLineCount( Text as string, RoundWay as integer ) 文字列の行数をカウントします。 【引数】 Text 行数をカウントする文字列 RoundWay 通常 Empty、g_VBS_Lib.NoRound も可能 (下記) 返り値 文字列の行数 サンプル Set c = g_VBS_Lib Assert GetLineCount( "a", Empty ) = 1 Assert GetLineCount( "a" +vbCRLF, Empty ) = 1 Assert GetLineCount( "a" +vbCRLF+ "b", Empty ) = 2 Assert GetLineCount( "a" +vbLF+ "b", Empty ) = 2 Assert GetLineCount( "", Empty ) = 0 Assert GetLineCount( "a", c.NoRound ) = 1 Assert GetLineCount( "a" +vbCRLF, c.NoRound ) = 1.5 サンプル position の位置の行番号を取得する line_num = GetLineCount( Left( string, position ), Empty ) RoundWay 引数 RoundWay 引数には、通常 Empty を指定します。 g_VBS_Lib.NoRound を指定すると、最終行の行末が改行文字なら +0.5 します。 ソース → ToolsLib.vbs テスト → T_StrEx.vbs T_GetLineCount 関連 → LineNumFromTextPositionClass 行番号をカウントします *********************************************************************** <<< LineNumFromTextPositionClass >>> *********************************************************************** LineNumFromTextPositionClass 文字列の先頭からの位置から、行番号をカウントします。 処理効率を良くするため、2回目以降は前回カウントした位置からカウントを再開します。 サンプル Set counter = new LineNumFromTextPositionClass counter.Text = _ "a"+ vbCRLF + _ "b"+ vbCRLF + _ "cde" Assert counter.GetNextLineNum( 4 ) = 2 '// "b" Assert counter.GetNextLineNum( 6 ) = 2 '// vbLF Assert counter.GetNextLineNum( 7 ) = 3 '// "c" Assert counter.GetNextLineNum( 10 ) = 3 '// 最後の次 Text GetNextLineNum ソース → ToolsLib.vbs テスト → T_StrEx.vbs T_LineNumFromTextPosition *********************************************************************** <<< Text (LineNumFromTextPositionClass) >>> *********************************************************************** Text (LineNumFromTextPositionClass) Property LineNumFromTextPositionClass::Text as string '// Get/Let 行番号を調べる対象となる文字列。 設定すると、前回調べた位置と行番号の情報はクリアされます。 参考 → GetNextLineNum サンプル → LineNumFromTextPositionClass 関連 → ReplaceTextAtHere 現在位置以降の文字列を置き換える *********************************************************************** <<< GetNextLineNum (LineNumFromTextPositionClass) >>> *********************************************************************** GetNextLineNum (LineNumFromTextPositionClass) Function LineNumFromTextPositionClass::GetNextLineNum( Position as integer ) as integer 文字列の先頭からの位置から、行番号をカウントします。 【引数】 Position 文字列の先頭からの位置、1 以上 返り値 Position 引数に指定した位置の行番号 Position 引数は、1 = 先頭の文字です。 前回調べた位置と行番号を Me の内部に格納しており、行番号を数える処理は、その続きから行うことで、 効率よく処理します。 前回 GetNextLineNum 関数に指定した値と同じか、それ以上の値を Position 引数に指定しなければ エラーになります。 サンプル → LineNumFromTextPositionClass 関連 → GetLineNum 前回調べた位置より前にも対応した GetNextLineNum *********************************************************************** <<< GetLineNum (LineNumFromTextPositionClass) >>> *********************************************************************** GetLineNum (LineNumFromTextPositionClass) Function LineNumFromTextPositionClass::GetLineNum( Position as integer ) as integer 文字列の先頭からの位置から、行番号をカウントします。 【引数】 Position 文字列の先頭からの位置 返り値 Position 引数に指定した位置の行番号 GetNextLineNum との違いは、前回調べた位置より前の位置にも対応していることです。 前回調べた位置より前の位置を Position 引数に指定したときは、文字列の先頭から数え直します。 *********************************************************************** <<< ReplaceTextAtHere (LineNumFromTextPositionClass) >>> *********************************************************************** ReplaceTextAtHere (LineNumFromTextPositionClass) Sub LineNumFromTextPositionClass::ReplaceTextAtHere( SecondHalfText as string ) 行番号を調べる対象となる文字列のうち、前回調べた位置とそれ以降の部分文字列を置き換えます。 【引数】 SecondHalfText 前回調べた位置とそれ以降に設定する行番号を調べる文字列 SetText で置き換える場合と異なり、前回調べた位置と行番号の情報はクリアされません。 サンプル Set counter = new LineNumFromTextPositionClass counter.SetText _ "a"+ vbCRLF + _ "b"+ vbCRLF + _ "cde" Assert counter.GetNextLineNum( 4 ) = 2 '// "b" counter.ReplaceTextAtHere _ "XY"+ vbCRLF + _ "c" Assert counter.GetNextLineNum( 8 ) = 3 '// "c" ReplaceTextAtHere 行番号を調べる対象となる文字列は、次のように置き換わります。 a b cde a XY c *********************************************************************** <<< Position (LineNumFromTextPositionClass) >>> *********************************************************************** Position (LineNumFromTextPositionClass) Property LineNumFromTextPositionClass::Position as integer '// Get only 前回調べた文字列の位置。 *********************************************************************** <<< LineNum (LineNumFromTextPositionClass) >>> *********************************************************************** LineNum (LineNumFromTextPositionClass) Property LineNumFromTextPositionClass::LineNum as integer '// Get only 前回調べた行番号。 *********************************************************************** <<< ReadVBS_Comment >>> *********************************************************************** ReadVBS_Comment Function ReadVBS_Comment( Path as string, StartTag as string, EndTag as string, Opt as Empty ) VBScript のファイルの中のコメントを、複数行の文字列として読み込みます。 【引数】 Path VBScript ファイルのパス、# 可能、Empty = WScript.ScriptFullName StartTag VBScript ファイルの中の、読み込みを開始する1つ上の行にあるキーワード EndTag 読み込む最後の行の1つ下の行にあるキーワード Opt Empty を指定してください 返り値 読み込んだ文字列。 先頭に ' は付きません StartTag と EndTag に指定したキーワードがヒットしないよう、下記のサンプルにあるように + でつなぐ などの対策をしてください。 サンプル スクリプト text = ReadVBS_Comment( Empty, "["+"FileA.txt]", "[/"+"FileA.txt]", Empty ) '-------------------------------------------------------------------[FileA.txt] '((( これはテキストファイルの代わりです ))) ' 'END '------------------------------------------------------------------[/FileA.txt] text に入った値 ((( これはテキストファイルの代わりです ))) END 最後の行の末尾には改行があります Path に、URL のように # を付けると、StartTag と EndTag の一部になります。 下記の2つは同じ動きをします。 StartTag と EndTag に指定した引数は無視されます。 text = ReadVBS_Comment( "#FileA.txt", Empty, Empty, Empty ) text = ReadVBS_Comment( Empty, "["+"FileA.txt]", "[/"+"FileA.txt]", Empty ) XML をリードするには、次のようにします。 text = ReadVBS_Comment( Empty, "["+"A.xml]", "[/"+"A.xml]", Empty ) Set root = LoadXML( text, g_VBS_Lib.StringData ) echo root.tagName '-------------------------------------------------------------------[A.xml] ' ' ' '------------------------------------------------------------------[/A.xml] ソース → vbslib.vbs テスト → T_FileInScript.vbs T_ReadVBS_Comment 関連 → WriteVBS_Comment → new_FilePathForFileInScript *********************************************************************** <<< OpenForWrite >>> *********************************************************************** (src) OpenForWrite Function OpenForWrite( Path as string, Flags as integer ) as TextStream テキストファイルを開きます。(ライト用=ファイルへ出力します) 【引数】 Path 開くファイルのパス → ファイル名、パス Flags Empty、またはオプション(下記) 返り値 ファイルのストリーム → TextStream (VBScript) NewWritable メソッドを使って、Out of Writable 警告が出ないようにしておいてください。 FileSystemObject::OpenTextFile と異なり、エラーがあったら、エラーメッセージに Path が付きます。 返り値を使って呼び出せるメソッドは、FileSystemObject::OpenTextFile と同じです。 テキストファイルの内容を書き換えるときは、文字コード(Unicode ファイルのBOM)や改行文字を 継承する StartReplace を使ってください。 サンプル Set w_= AppKey.NewWritable( "." ).Enable() Set file = OpenForWrite( "a.txt", Empty ) file.WriteLine "abc" file = Empty NewWritable a.txt Flags 引数 Empty または 次の値 文字コードの指定は、次のどれかが指定できます。 new_TextFileCharSetStack を使うと、その他のフォーマットも指定できます。 下記の c は g_VBS_Lib です。 → g_VBS_Lib c.Unicode Unicode 形式ファイルにします。 指定しないときは、 new_TextFileCharSetStack で指定した既定の文字コードになります。 c.UTF_8 BOM 付き UTF-8 c.UTF_8_No_BOM BOM なし UTF-8 c.Shift_JIS Shift-JIS c.EUC_JP EUC(JP) 改行コードの指定は、 new_TextFileLineSeparatorStack を使ってください。 次の値と論理和をとることもできます。 c.Append 追記します。 Shift-JIS, Unicode, UTF-8(BOMあり) のときは、文字コードを指定しなくても、 元のファイルと同じ文字コードになります。 テスト → T_File.vbs [T_OpenForWrite] → T_File.vbs [T_OpenForWrite_Overwrite] 関連 → FileSystemObject::CreateTextFile → ReplaceTextFile → StringStream クラス → バイナリ混在テキスト生成 (txt2bintxt.exe) → LockByFileMutex → CreateFile *********************************************************************** <<< new_TextFileCharSetStack >>> *********************************************************************** (src) new_TextFileCharSetStack Function new_TextFileCharSetStack( CharSet as string ) as TextFileCharSetStack ファイルの文字 コード セットを指定します。 【引数】 CharSet ファイルの文字 コード セット, Empty=デフォルト 新規作成するときの出力ファイルや、ファイルから読み込むときの文字コードを指定 します。 返り値のオブジェクトが削除されたら、指定は無効になります。 CharSetの例: "Shift_JIS", "EUC-JP", "Unicode", "UTF-8", "UTF-8-No-BOM", "ISO-8859-1", "ISO-2022-JP" c.Shift_JIS, c.EUC_JP, c.Unicode, c.UTF_8, c.UTF_8_No_BOM, c.ISO_2022_JP, c.No_BOM(=c.Shift_JIS), Empty(=c.Shift_JIS) → Charset (ADODB.Stream) デフォルト(本関数を一度も呼ばなかったとき)は、"Shift_JIS" です。 CharSet 引数に指定する文字列の大文字小文字は区別しません。 c.Unicode などの数値定数を指定することもできます。 "UTF-8" は、ファイルの先頭に BOM が付きます。 "UTF-8-No-BOM" は付きません。 BOM を付けないときは XML の encoding や HTML の charset などを用いて文字 コードを記述しなければ、多くのプログラムは文字化けを起こします。 一方で、 BOM があるとエラーを起こす UTF-8 に対応していないプログラムも多くあります。 指定できる値は、レジストリの HKEY_CLASSES_ROOT\MIME\Database\Charset の サブキーを参照してください。 ただし、"UTF-8-No-BOM" はサブキーにありません。 現在指定されている文字 コード セットは、 g_FileOptions で取得できます。 サンプル Set cs = new_TextFileCharSetStack( "UTF-8" ) CreateFile "File1.txt", "abc" "UTF-8" ファイル内の文字コードの指定 XML の場合 → Read_XML_Encoding UTF-8 HTML の場合 vbslib では、解析を行いません。 UTF-8 テスト → T_File.vbs [T_OpenForWrite] 関連 → OpenForWrite → CreateFile → Charset (ADODB.Stream) → XmlWriteEncoding XML ファイルの文字コードを指定します。 → ReadUnicodeFileBOM ファイルの先頭にある BOM を読みます。 → ConvertCharCodeInHref → Text (BinaryArray) 文字コードセットを変換します。 *********************************************************************** <<< Decode_MIME_HeaderLine >>> *********************************************************************** Decode_MIME_HeaderLine Function Decode_MIME_HeaderLine( Line as string ) as string MIME ヘッダーの1行を "=? … ?=" 形式から、通常の文字列に戻します。 【引数】 Line MIME ヘッダーの1行 返り値 Line からでコードした通常の文字列 ソース → System.vbs サンプル str = Decode_MIME_HeaderLine( "Subject: =?ISO-2022-JP?B?YWJjGyRCJUYlOSVIGyhCZGVm?=" ) Assert str = "Subject: abcテストdef" テスト → T_Binary.vbs T_MIME 参考 → MIME → ISO-2022-JP → Base64 関連 → Base64 (BinaryArray) → Text (BinaryArray) 文字コードの変換 *********************************************************************** <<< new_TextFileLineSeparatorStack >>> *********************************************************************** (src) new_TextFileLineSeparatorStack Function new_TextFileLineSeparatorStack( LS as string ) as TextFileLineSeparatorStack ファイルの改行文字コードを指定します。 【引数】 LS ファイルの改行文字コード、または Empty 返り値のオブジェクトが削除されたら、指定は無効になります。 サンプル Dim ls : Set ls = new_TextFileLineSeparatorStack( g_VBS_Lib.KeepLineSeparators ) Set f = OpenForRead( Path ) ls = Empty text = f.ReadLine() LS 引数 Empty 自動判定 (下記) vbCRLF, g_VBS_Lib.CRLF CR+LF vbLF, g_VBS_Lib.LF LF g_VBS_Lib.KeepLineSeparators 改行文字の種類を継承する(下記) LS 引数 = Empty のときの動き リードするときは改行文字を自動判定、ライトするときは CR+LF、修正するとき(*下記)は 改行文字の種類を継承します。 改行文字の種類を継承するときの動き (KeepLineSeparators) 「改行文字の種類を継承する」 とは、入力ファイルに書かれた改行文字の種類が、1行 単位で、そのまま出力ファイルに書かれることです。 1つのファイルに複数の改行文字の 種類が混ざっていても、そのまま継承されることです。 OpenForReplace など、修正前のテキストと修正後のテキストの両方を指定する vbslib の関数を使ったときは、その関数の中で改行文字の種類の継承処理が行われます。 そうではなく、OpenForRead などを使ってテキストをリードして、OpenForWrite などを 使ってテキストをライトする処理をプログラミングするときは、以下で説明する詳細な 手順を参考に、改行文字の継承を行ってください。 はじめに、 ReadLineSeparator を使って、入力ファイルの先頭行の改行文字の種類を 判定して、出力ファイルのデフォルト改行文字の種類を設定します。 入力ファイル、出力ファイル、ともに、g_VBS_Lib.KeepLineSeparators (上記) のモード を使うように、new_TextFileLineSeparatorStack を呼び出します。 KeepLineSeparators モードでは、TextStream::ReadLine や TextStream::WriteLine に よってアクセスする1行のテキストの内容が、次のように変わります。 TextStream::ReadLine の返り値である1行のテキストの末尾に改行文字が加わります。 改行文字は、ファイルの内容によって、LF または CR+LF のどちらかになります。 ただし、最終行の末尾に改行文字が無いときだけ、改行文字は加わりません。 TextStream::WriteLine に渡すテキストの末尾に vbCRLF または vbLF を付けることが できます。 付けたときは、その種類の改行文字が出力され、TextStream::WriteLine に よって自動的に改行文字を付けることはなくなります。 また、デフォルトの改行文字も 指定した種類に変更されます。 改行文字を付けなかったときは、デフォルトの改行 文字が自動的に付きます。 つまり、TextStream::ReadLine で入力した1行をそのまま TextStream::WriteLine に出力すると、改行文字の種類は継承され、末尾に改行文字 を付けない新たな1行を TextStream::WriteLine に出力すると、前の行の改行文字の 種類を継承します。 TextStream::WriteLineDefault を使うと、渡したテキストの改行文字を、デフォルトの 改行文字に置き換え、渡したテキストの最後に改行文字を追加して、出力します。 テスト → T_Replace.vbs # T_StartReplace_KeepRet_1 → T_File.vbs # T_OpenFile_LineSepFromFS 参考 → LineSeparator (ADODB.Stream) 関連 → CutCRLF *********************************************************************** <<< new_IsSafeFileUpdateStack >>> *********************************************************************** (src) new_IsSafeFileUpdateStack Function new_IsSafeFileUpdateStack( IsEnabled as boolean ) as IsSafeFileUpdateStack ファイルを作成するときに SafeFileUpdate を実行します。 【引数】 IsEnabled SafeFileUpdate を実行するかどうか 返り値のオブジェクトが削除されたら、指定は無効になります。 サンプル Dim sf : Set sf = new_IsSafeFileUpdateStack( True ) CreateFile "File1.txt", "abc" テスト → T_File.vbs [T_CreateFile] *********************************************************************** <<< g_FileOptions >>> *********************************************************************** (src) g_FileOptions g_FileOptions = new FileOptionsClass Class FileOptionsClass Public Property Get CharSet '// as lower case string. ADODB.Stream.Charset Public Property Get CharSetEx '// as Empty, c.UTF_8_No_BOM Public Property Get LineSeparator '// as ADODBConsts.Keep Public Property Get IsSafeFileUpdate '// as boolean End Class → new_TextFileCharSetStack → new_IsSafeFileUpdateStack *********************************************************************** <<< WriteVBS_Comment >>> *********************************************************************** WriteVBS_Comment Sub WriteVBS_Comment( Path as string, StartTag as string, EndTag as string, Text as string, Opt as Empty ) VBScript のファイルの中のコメントに、複数行の文字列を書き込みます。 【引数】 Path VBScript ファイルのパス、Empty = WScript.ScriptFullName StartTag VBScript ファイルの中の、書き込みを開始する1つ上の行にあるキーワード EndTag 書き込む最後の行の1つ下の行にあるキーワード Text 書き込む文字列。 先頭に ' は不要です Opt Empty を指定してください StartTag と EndTag に指定したキーワードがヒットしないよう、下記のサンプルにあるように + でつなぐ などの対策をしてください。 サンプル スクリプト(実行前) WriteVBS_Comment Empty, "["+"FileA.txt]", "[/"+"FileA.txt]", _ "abc" +vbCRLF+_ "DEF" +vbCRLF, Empty '-------------------------------------------------------------------[FileA.txt] '((( これはテキストファイルの代わりです ))) ' 'END '------------------------------------------------------------------[/FileA.txt] スクリプト(実行後) WriteVBS_Comment Empty, "["+"FileA.txt]", "[/"+"FileA.txt]", _ "abc" +vbCRLF+_ "DEF" +vbCRLF, Empty '-------------------------------------------------------------------[FileA.txt] 'abc 'DEF '------------------------------------------------------------------[/FileA.txt] abc DEF ソース → vbslib.vbs テスト → T_FileInScript.vbs T_WriteVBS_Comment 関連 → ReadVBS_Comment *********************************************************************** <<< WriteVBSLibFooter >>> *********************************************************************** (src) WriteVBSLibFooter Sub WriteVBSLibFooter( OutFileStream as TextStream, Opt as WriteVBSLibFooter_Option ) vbslib include を出力します。 (メイン.vbs ファイルの最後にするとき) 【引数】 OutFileStream 開いている書き込むファイル Opt オプション or Empty 現在実行している、メイン.vbs ファイルの中にある --- start of vbslib include --- 以降を OutFileStream に出力します。 --- start of vbslib include --- が Main 関数より前にあるときは、何もしません。 サンプル WriteVBSLibFooter file, Empty WriteVBSLibFooter_Option Class WriteVBSLibFooter_Option Public CommandPromptMode '// as integer End Class CommandPromptMode … Empty でないなら g_CommandPrompt の値を変更します 関連 → WriteVBSLibHeader *********************************************************************** <<< WriteVBSLibHeader >>> *********************************************************************** (src) WriteVBSLibHeader Sub WriteVBSLibHeader( OutFileStream as TextStream, Opt as WriteVBSLibHeader_Option ) vbslib include を出力します。 (メイン.vbs ファイルの最初にするとき) 【引数】 OutFileStream 開いている書き込むファイル Opt オプション or Empty 現在実行している、メイン.vbs ファイルの中にある --- end of vbslib include --- まで(先頭から)を OutFileStream に出力します。 --- start of vbslib include --- が Main 関数より後にあるときは、何もしません。 WriteVBSLibHeader_Option Class WriteVBSLibHeader_Option Public m_OverCommandPrompt End Class … Empty でないなら g_CommandPrompt の値を変更します *********************************************************************** <<< OpenForReplace >>> *********************************************************************** OpenForReplace Function OpenForReplace( SrcPath as string, DstPath as string ) as ReplaceTextFile1 テキストファイルの内容を変更します。 【引数】 SrcPath 変更前のテキストファイルのパス DstPath 変更後のテキストファイルのパス。 SrcPath と同じ、または Empty 可。 返り値 → ReplaceTextFile1 クラス サンプル Value の設定値を 0 から 1 に変える Set file = OpenForReplace( "file1.txt", Empty ) file.Replace "Value = 0", "Value = 1" file = Empty file1.txt Value = 0 Value = 1 サンプル 上と同じ内容の短縮形 OpenForReplace( "file1.txt", Empty ).Replace "Value = 0", "Value = 1" file1.txt Value = 0 Value = 1 サンプル 文字列を編集することでテキストファイルの内容を変更する Set file = OpenForReplace( "file1.txt", Empty ) file.Text = Replace( file.Text, "Value = 0", "Value = 1" ) file = Empty file1.txt Text Value = 0 Value = 1 サンプル TopOfContexts タグの後ろに new Topic を追加する Set file = OpenForReplace( "file1.html", Empty ) file.Replace "", ""+vbCRLF+ "new Topic" file = Empty サンプル タグに囲まれた複数行を変更する → ReplaceRange (ReplaceTextFile1) 補足 変更する内容は、返り値のメソッドに指定します。 → ReplaceTextFile1 クラス 変更前が Unicode 形式ファイルのときは、変更後も Unicode 形式ファイルになります。 ランダムアクセスに対応しています。 OpenForRead や OpenForWrite のようにシーケンシャル (ファイルの先頭から順番)にアクセスする必要はなく、ReplaceTextFile1::Replace などを 任意の順番で呼び出すことができます。 DstPath を Empty にすると、DstPath = SrcPath にした時と同じ動きをします。 重要なファイルを上書き更新するときは、OpenForReplace の DstPath 引数に一時的に 出力するパスを指定し、その一時ファイルを作成した後(ファイルを閉じた後)で、 SafeFileUpdateEx を呼び出してください。 ただし、内部で2〜3回のファイルコピーを行います。 返り値のオブジェクトが削除されるタイミングでエラーが発生中(Err.Number <> 0 or g_Err2.Number <> 0) のときは、ファイルを作成または更新しません。 ソース → vbslib.vbs テスト → T_Replace.vbs T_OpenForReplace 関連 → OpenForReplaceXML → ReadFile → Replace → CreateFile → ReplaceSymbols コマンド → Switches コマンド → Translate コマンド → StringReplaceSetClass → StartReplace 行単位でファイルの一部を置き換える → SafeFileUpdateEx 重要なファイルを上書き更新するとき *********************************************************************** <<< ReplaceTextFile1 クラス >>> *********************************************************************** ReplaceTextFile1 クラス (src) テキストを置き換えます。 指定のタグで囲まれたテキストを置き換えます。 サンプル → OpenForReplace 取得 → OpenForReplace .Text 編集中のファイルの内容。 .Replace テキストを置き換えます。 .ReplaceRange 指定のタグで囲まれたテキストを置き換えます。 .Close テキストファイルの内容の変更を完了します。 *********************************************************************** <<< Text (ReplaceTextFile1) (OpenForReplace) >>> *********************************************************************** Text (ReplaceTextFile1) (OpenForReplace) Dim ReplaceTextFile1::Text as string 編集中のファイルの内容。 この内容を直接変更することで、ファイルの内容を変更することができます。 サンプル Set rep = OpenForReplace( "file1.txt", Empty ) rep.Text = Replace( rep.Text, "from", "to" ) rep = Empty テスト → T_Replace.vbs T_OpenForReplaceText 関連 → FindStringLines → Replace (RegExp) *********************************************************************** <<< Replace (ReplaceTextFile1) >>> *********************************************************************** [ 親: ReplaceTextFile1 クラス ] Replace (ReplaceTextFile1) Sub ReplaceTextFile1::Replace( FromText as string, ToText as string ) テキストを置き換えます。 【引数】 FromText 置き換える前のテキスト、または VBScript.RegExp ToText 置き換えた後のテキスト VBScript.RegExp を FromText 引数に指定すると、パターンマッチングにより置き換え対象を 検索します。 ToText は、 RegExp::Replace と同様に、$1 などを指定することもできます。 例: OpenForReplace( "file1.txt", Empty ).Replace new_RegExp( "from.*", False ), "to" OpenForReplace new_RegExp 置き換えた後のテキストが存在するときは、置き換えを行いません。 これは、VBS の Replace 関数と結果が異なりますが、追加的な置き換えをしたときに、多重的に 追加されることがなくなります。 例: f.Replace "a = 0", "a = 0 : b = 0" a = 0 の後に b = 0 を追加する 置き換える前 置き換えた後 a = 0 a = 0 : b = 0 a = 0 : b = 0 a = 0 : b = 0 … [a = 0 : b = 0 : b = 0] にはなりません ソース → vbslib.vbs テスト → T_Replace.vbs T_OpenForReplace T_OpenForReplaceCharSet T_OpenForReplaceRegExp *********************************************************************** <<< ReplaceRange (ReplaceTextFile1) >>> *********************************************************************** [ 親: ReplaceTextFile1 クラス ] ReplaceRange (ReplaceTextFile1) Sub ReplaceTextFile1::ReplaceRange( StartOfFromText as string, EndOfFromText as string, ToText as string ) 指定のタグで囲まれたテキストを置き換えます。 【引数】 StartOfFromText 置き換える前のテキストが始まる場所にあるタグ(テキスト) EndOfFromText 置き換える前のテキストが終わる場所にあるタグ(テキスト) ToText 置き換えた後のテキスト。 通常、タグも含む。 置き換える範囲は、複数行であってもかまいません。 サンプル Set file = OpenForReplace( "file1.html", Empty ) file.ReplaceRange "", "", _ ""+vbCRLF+ "new Topic" +vbCRLF+"" file = Empty 置き換えサンプル StartOfFromText = "", EndOfFromText = "" とします。 置き換える前 ToText 置き換えた後 abc123def 456 abc456def abc123def 456 abc456def 123 456 789 789 ソース → vbslib.vbs テスト → T_Replace.vbs T_OpenForReplaceRange 関連 → ReadFileInTag *********************************************************************** <<< Close (ReplaceTextFile1) >>> *********************************************************************** Close (ReplaceTextFile1) → ReplaceTextFile1 クラス Sub ReplaceTextFile1::Close() テキストファイルの内容の変更を完了します。 デストラクタから自動的に呼ばれますが、明示的に呼び出すこともできます。 *********************************************************************** <<< IsSaveInTerminate (ReplaceTextFile1) >>> *********************************************************************** IsSaveInTerminate (ReplaceTextFile1) → ReplaceTextFile1 クラス Dim ReplaceTextFile1::IsSaveInTerminate as boolean or Empty オブジェクトが削除されるタイミングで保存するかどうか。 Empty のときは、エラーが発生している状態でなければ保存します。 *********************************************************************** <<< SafeFileUpdateEx >>> *********************************************************************** SafeFileUpdateEx Sub SafeFileUpdateEx( TemporaryFilePath as string, ToFilePath as string, Option_ as string ) ファイルを安全に更新します。 上書き移動します。 【引数】 TemporaryFilePath 新しい内容が書かれた削除する一時ファイルのパス ToFilePath 更新するファイルのパス Option_ Empty、または、g_VBS_Lib.ToTrashBox サンプル temporary_path = "FileA.txt.updating" CreateFile temporary_path, "新情報!" SafeFileUpdateEx temporary_path, "FileA.txt", Empty → 拡張子 .updating "新情報!" "FileA.txt" FileA.txt の内容を、"新情報!" という内容に更新します。 一時的に存在するファイル temporary_path に、新しい内容を出力する必要があります。 SafeFileUpdateEx を呼び出した後は、temporary_path の場所にファイルは無くなります。 更新するファイルを直接開いてライトするプログラムの場合、ライトしている途中で、 容量不足になったり、接続できなくなったりしてエラーになると、更新する前の内容 が消えてしまいます。 それだけでなく、更新した後の内容も保存できない可能性が あります。 その場合、ファイルに格納していた情報がすべて消えてしまいます。 SafeFileUpdate は、そのリスクを回避します。 SafeFileUpdate を呼び出している途中で、ファイルの更新やバックアップなどに失敗 したら、エラーが発生しますが、ファイルの内容は、消えることなく、元に戻ります。 ただし、新しい内容は保存できていないので、エラー復帰して、別のディスクに保存 できるようにしてください。 内部でファイルのコピーを2〜3回行います。 Option_ = g_VBS_Lib.ToTrashBox を指定すると、 SafeFileUpdate と同じ動きになります。 拡張子 .updating 新しい内容を書くファイルの拡張子を .updating にすると、 AppKeyClass::NewWritable を使う必要がなくなります。 また、一時的に存在するファイル(一時ファイル)のパスは、出力するファイルのパスの最後に updating という拡張子を追加したパスに標準化すれば、ファイルの上書き保存に失敗した という状況が推測しやすくなります。 また、拡張子を変更することで、不完全なファイルを アプリケーションに渡さないようになります。 例: SafeFileUpdateEx path +".updating", path, Empty ソース → vbslib.vbs テスト → T_SafeCopy.vbs T_SafeFileUpdate *********************************************************************** <<< SafeFileUpdate >>> *********************************************************************** SafeFileUpdate Sub SafeFileUpdate( FromTmpFilePath as string, ToFilePath as string ) ファイルを安全に更新します。 上書き移動して、元の内容はゴミ箱に入ります。 【引数】 FromTmpFilePath 新しい内容が書かれたファイルのパス ToFilePath 更新するファイルのパス ソース → vbslib.vbs テスト → T_SafeCopy.vbs # [T_SafeFileUpdate] 関連 → SafeFileUpdateEx → new_IsSafeFileUpdateStack *********************************************************************** <<< ConvertToFullPath >>> *********************************************************************** ConvertToFullPath (src) Sub ConvertToFullPath( SrcFilePath as string, DstFilePath as string ) テキストファイルの中の相対パスや特殊フォルダのパスをフル・パスに変換してコピーします。 【引数】 SrcFilePath 変換前のファイルのパス DstFilePath 変換後のファイルのパス(新規作成または上書き), Empty不可 テキストファイルの中に書かれた %FullPath( )% などの % % で囲まれた部分を置き換えます。 変換前 変換後の例 %FullPath(..\SampleLib)% C:\folder\SampleLib (*1) %FullPath(.)% C:\folder\current (*1) %DesktopPath% C:\Documents and Settings\user1\デスクトップ (*1) DstFilePath 引数が指すファイルが入ったフォルダーを、相対パスの基準にしたフル・ パスに変換します。 基準を SrcFilePath ではなく DstFilePath にしている理由は、1つのテンプレート的な ファイル(SrcFilePath) に対して、複数の場所(DstFilePath) で使用することができるように するためです。 参考 → % を使った変換式 Unicode ファイルにするときは、次のように設定してから ConvertToFullPath を呼んでください。 Dim c : Set c = g_VBS_Lib Dim cs : Set cs = new_TextFileCharSetStack( c.Unicode ) ConvertToFullPath "ans.txt", "ans_tmp.txt" 参考 → TextFileConvertFormat::Set_ テスト → T_ConvAbs.vbs # ConvertToFullPath *********************************************************************** <<< % を使った文字列変換関数 >>> *********************************************************************** % を使った文字列変換関数 vbslib の提供するいくつかの関数の中で、% を使った文字列変換関数が使えます。 % を使った環境変数も展開されます。 サンプル ABC ***%FullPath(.)%*** ***%RegExp(.*)%*** ABC ***C:\FolderA*** ***01234567879*** 展開 関数一覧 (*1) (*2) 変換前の例 変換後の例 ○ ○ %FullPath(..\SampleLib)% C:\folder\SampleLib (*3) ○ ○ %FullPath(.)% C:\folder\current → ConvertToFullPath ○ ○ %DesktopPath% C:\Documents and Settings\user1\デスクトップ ○ ○ %Env(USERPROFILE)% 環境変数 USERPROFILE の値 ○ × %RegExp(.*)% 正規表現にマッチする任意の文字列 → 正規表現 ○ × %MultiLine% 複数行にマッチする (*4) (*1) 比較対象も指定する関数で使えるかどうか。 例: AssertFC IsSameTextFile の c.RightHasPercentFunction 比較対象を指定しない関数で使えるかどうか。 (*2) 例: ConvertToFullPath (*3) %FullPath(x)% の x に相対パスを指定したときの基準フォルダーは、%FullPath(x)% を 記述したファイルがあるフォルダーです。 → ConvertToFullPath (*4) %MultiLine% は、任意の複数行とマッチします。 また、%MultiLine% の直後にテキスト(%を使った関数可能)を置くと、その複数行が マッチするかどうかをチェックします。 start %MultiLine% end start Line1 Line2 Line3 end 展開 start %MultiLine%%FullPath(.)%> end start C:\FolderA> C:\FolderA> C:\FolderA> end 展開 関連 → ${ } 変数, LazyDictionaryClass → URL にプレースホルダーを含める → sscanf キーワード: %FullPath(.)%, %RegExp(.*)%, %MultiLine%, %DesktopPath% *********************************************************************** <<< ParsePercentVariableString >>> *********************************************************************** ParsePercentVariableString Sub ParsePercentVariableString( the_String as string, out_SubStringArray as array of string, out_VariableArray as array of string ) 文字列の中の % を使った変数の部分とそれ以外の部分に分割します。 【引数】 the_String 分割する前の文字列 out_SubStringArray 変数以外の部分の配列 out_VariableArray 変数の部分の配列 サンプル ParsePercentVariableString "abc %VAR1%, %VAR2% def", sub_strings, variables Assert IsSameArray( sub_strings, Array( "abc ", ", ", " def" ) ) Assert IsSameArray( variables, Array( "%VAR1%", "%VAR2%" ) ) ソース → ToolsLib.vbs テスト → T_Str.vbs T_ParseDollarVariableString 関連 → ScanFromTemplate → ParseDollarVariableString *********************************************************************** <<< ReplaceStringTemplate >>> *********************************************************************** ReplaceStringTemplate Sub ReplaceStringTemplate( FolderPath as string, RegularExpressionPart as string, TemplateBefore as string, TemplateAfter as string, Opt as Empty ) テキストファイルの中をキーワードで検索し、テンプレートを置き換えます。 【引数】 FolderPath 検索対象フォルダーやワイルドカード → Execute (GrepClass) RegularExpressionPart 置き換える前のキーワード。複数行不可 → 正規表現 TemplateBefore 置き換える前のテンプレート(複数行可) TemplateAfter 置き換えた後のテンプレート(複数行可) Opt オプション、または、Empty TemplateBefore に指定した変数(${ … } の部分)は、TemplateAfter に指定した ${ … } の 部分に入ります。 置き換えた後のテンプレートにある変数が、置き換える前のテンプレートにないときは、 変数のまま残ります。 ただし、Opt 引数に dictionary 型を指定して、変数に一致する キーに対応した値に置き換えることもできます。 RegularExpressionPart 引数に指定するキーワードは、TemplateBefore に含まれるキーワードを 正規表現で指定します。 キーワードは、TemplateAfter に含まれていなくても構いません。 この引数を使って内部で高速なファイル検索が行われます。 "" を指定すると、すべてのファイルに対して置き換えを試みます。 Opt 引数には、Empty か、辞書型で変数のデフォルト値を指定できます。 TemplateBefore に ない変数が TemplateAfter にあるときは、その変数をここで指定した値に置き換えます。 サンプル テンプレートのサンプル TemplateBefore TemplateAfter @param ${Arguments} @return ${RerutnValue} 関数名: ${FunctionName} 引数: ${Arguments} 返り値: ${RerutnValue} 補足: ${Note} のように指定した場合、FolderPath にマッチしたあるファイルの内容は、次のように変化します。 @param First Parameter @return None 関数名: ${FunctionName} 引数: First Parameter 返り値: None 補足: 以上のテンプレートは、XML ファイルに記述することができます。 → new_ReplaceTemplateClass ただし、Opt 引数に次のように指定したものとします。 Dict(Array( "${Note}", "" )) Dict 予約変数 テンプレートの中に次の予約変数を記述することができます。 ${FileName} ファイル名に置き換わります ソース → ToolsLib.vbs テスト → T_fc.vbs T_ReplaceStringTemplate 関連 → RunReplace (ReplaceTemplateClass) → SearchStringTemplate → PartRep → GetLineNumOfTemplateDifference → Replace → ${ } 変数, LazyDictionaryClass *********************************************************************** <<< ReplaceStringTemplates >>> *********************************************************************** ReplaceStringTemplates Sub ReplaceStringTemplates( in_FileOrFolderPath as string, in_Replaces as array of StringTemplateReplaceClass, in_Empty as Empty ) テキストファイルの中をキーワードで検索し、テンプレートを置き換えます。 【引数】 in_FileOrFolderPath 検索対象ファイルやフォルダーのパス in_Replaces テンプレートの配列(下記) in_Empty Empty を指定してください StringTemplateReplaceClass 検索対象のワイルドカード .KeywordBefore string 置き換える前のテンプレート .TemplateBefore string .TemplateAfter string 置き換えた後のテンプレート .DefaultValues dictionary< string > 変数のデフォルト値 サンプル → ReplaceStringTemplate ソース → ToolsLib.vbs テスト → new_ReplaceTemplateClass *********************************************************************** <<< new_ReplaceTemplateClass >>> *********************************************************************** new_ReplaceTemplateClass Function new_ReplaceTemplateClass( in_PathOfXML as string ) as ReplaceTemplateClass テキストファイルのテンプレートを操作するオブジェクトを生成します。 【引数】 in_PathOfXML テンプレートに関するの設定ファイルのパス → ファイルの内容 返り値 テンプレートを操作するオブジェクト in_PathOfXML 引数に、 ReplaceTemplate.xml ファイル のパスを指定してください。 in_PathOfXML 引数に、フォルダーのパスを指定したときは、そのフォルダーとサブ フォルダーに 入っている *.replace.xml ファイルの内容を設定します。 また、*.before.* と *.after.* の両方の ファイルがあれば、*.before.* を置き換える前のテンプレート、*.after.* を置き換えた後の テンプレートとして設定します。 in_PathOfXML *.after.* 置き換える前のテキストがそのまま入ったファイル *.before.* 置き換えた後のテキストがそのまま入ったファイル *.replace.xml 詳細な置き換えの設定 → ReplaceTemplate.xml テキストファイルのテンプレートを操作するオブジェクトは、次のメソッドを持ちます。 → EchoOld 合っていない(古い)テンプレートの場所を表示します → RunGetDifference 合っていない(古い)テンプレートの中の場所を表示します → RunReplace テンプレートを置き換えます サンプル → Samples\ReplaceTemplate フォルダー コールツリー new_ReplaceTemplateClass Set Me_.Files = new MultiTextXML_Class MultiTextXML_Class ReplaceTemplateClass::AppendLoadSetting replace_.ID_Before = xml_full_path + tag.getAttribute( "before" ) Me.ReplaceTemplate.Add replace_ ReplaceTemplateClass::RunReplace ReplaceStringTemplate Me.Files.GetText( replace_.ID_Before ) ソース → SyncFilesMenuLib.vbs テスト → T_ReplaceByTemplate フォルダー *********************************************************************** <<< ReplaceTemplate.xml >>> *********************************************************************** ReplaceTemplate.xml ReplaceTemplate.xml は、 new_ReplaceTemplateClass 関数 や マージ設定ファイル の ReplaceTemplate タグを記述するファイルです。 ファイル名は、ReplaceTemplate.xml とは限りません。 ${ } 変数で置き換える前の内容を置き換えた後にコピーできます。 サンプル /* Function: … */ を /* Func: … */ に置き換える設定 サンプル → Samples\ReplaceTemplate フォルダー 詳細 /MultiText/Target 処理対象のパス。複数可能。 → FF-path 属性 @path 処理対象のパス。 関連 → SetTargetPath /MultiText/ReplaceTemplate @before 置き換える前のテキストがある Text タグの URL → RunReplace (ReplaceTemplateClass) @after 置き換えた後のテキストがある Text タグの URL → RunReplace (ReplaceTemplateClass) /MultiText/Text 置き換える前または後のテンプレート text() → ReplaceStringTemplate ${ } 変数、テキストファイルのテンプレート → MultiTextXML_Class テンプレートに記述できる ---- 形式のコメント @id → MultiTextXML_Class 値の末尾が "_Keyword" のとき → EchoOld (ReplaceTemplateClass) @cut_indent @indent → CutIndentOfMultiLineText インデント、改行コード /MultiText/EnabledTemplateIDs @type "Lines" を指定してください。 text() 現在使われている(変換後の)テンプレートのアドレス。 複数指定するときは、複数行記述してください。 → EchoOld (ReplaceTemplateClass) /MultiText/ReplaceTemplateID_From text() 置き換える前のテンプレートのアドレス。 → RunReplace (ReplaceTemplateClass) /MultiText/ReplaceTemplateID_To text() 置き換えた後のテンプレートのアドレス。 → RunReplace (ReplaceTemplateClass) *********************************************************************** <<< IsPause (ReplaceTemplateClass) >>> *********************************************************************** IsPause (ReplaceTemplateClass) Dim ReplaceTemplateClass::IsPause as boolean ユーザーへの確認を行うかどうか。 たとえば、False に設定すると、 RunReplace メソッド を呼び出したとき、置き換え内容を ユーザーに要求しなくなります。 *********************************************************************** <<< EchoOld (ReplaceTemplateClass) >>> *********************************************************************** EchoOld (ReplaceTemplateClass) << new_ReplaceTemplateClass Sub ReplaceTemplateClass::EchoOld() 現在使われているテンプレートと合っていない(古い)テンプレートの場所を表示します。 ReplaceTemplate.xml の /MultiText/Text/text() に、現在使われているテンプレートを 設定してください。 そのテンプレートを囲むタグの id 属性( /MultiText/Text/@id ) と /MultiText/EnabledTemplateIDs/text() の ID が同じになるように ID を設定してください。 ただし、 /MultiText/EnabledTemplateIDs/text() の各行の先頭には # を記述してください。 # を記述することは、HTML の A href 属性と同じ仕様です。 /MultiText/EnabledTemplateIDs/text() に複数行のテキストを指定すると、複数の テンプレートについて処理を行います。 テンプレートが id="A" にあるとき(/MultiText/Text[@id='A']/text() にあるとき)、 _Keyword を末尾に追加した id 属性のテキスト (/MultiText/Text[@id='A_Keyword ']/text() ) にテンプレートの中の1行にヒットする正規表現を設定してください。 サンプル テンプレートの例 '* vbslib is provided under 3-clause BSD license. '* Copyright (C) Sofrware Design Gallery "Sage Plaisir 21" All Rights Reserved. 上記テンプレートを ReplaceTemplate.xml の一部に設定する内容の例 #vbslib_copyright EchoOld 実行時の表示内容 以下の場所にあるテキスト ファイルの一部がテンプレートがマッチしませんでした。 下記のパスの末尾にある番号は、テンプレートの中のキーワードがある行番号です。 vbslib Prompt.vbs の OpenByStepPath コマンドで開くことができます。 基準パス:"C:\Folder" GetDifference コマンドでテンプレートの中のマッチしなかった行の行番号が表示されま す。 ------------------------------------------------------------------------------- Target\a.txt(2) Target\a.txt(13) ------------------------------------------------------------------------------- 参考 → OpenByStepPath OpenByStepPath コマンド → RunGetDifference GetDifference コマンド ソース → SyncFilesMenuLib.vbs 関連 → SearchStringTemplate *********************************************************************** <<< RunGetDifference (ReplaceTemplateClass) >>> *********************************************************************** RunGetDifference (ReplaceTemplateClass) << new_ReplaceTemplateClass Sub ReplaceTemplateClass::RunGetDifference() 現在使われているテンプレートと合っていない(古い)テンプレートの中の場所を表示します。 調べる対象のファイルの入力を要求されます。 サンプル 表示内容 Enterのみ:"Target\a.txt" 調べるファイルのパス > 以下の場所にあるテンプレートがマッチしませんでした。 ------------------------------------------------------------------------------- Target\a.txt(5) ------------------------------------------------------------------------------- ソース → SyncFilesMenuLib.vbs 関連 → GetLineNumOfTemplateDifference *********************************************************************** <<< SetTargetPath (ReplaceTemplateClass) >>> *********************************************************************** SetTargetPath (ReplaceTemplateClass) Sub ReplaceTemplateClass::SetTargetPath( in_Path as string or PathDictionaryClass ) 処理対象のファイルやフォルダーのパスを設定します。 【引数】 in_Path 処理対象のファイルやフォルダーのパス ReplaceTemplate.xml の /MultiText/Target が設定されていないときは、本関数で設定する必要が あります。 ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< RunReplace (ReplaceTemplateClass) >>> *********************************************************************** RunReplace (ReplaceTemplateClass) << new_ReplaceTemplateClass Sub ReplaceTemplateClass::RunReplace() テンプレートを置き換えます。 参考 → ReplaceTemplate.xml に設定できる値 実行するかどうかの確認を要求されます。 ReplaceTemplate.xml の /MultiText/Text/text() に、置き換える前のテンプレートを設定 してください。 別の /MultiText/Text/text() に、置き換えた後のテンプレートを設定して ください。 置き換える前のテンプレートを囲むタグの id 属性( /MultiText/Text/@id ) と /MultiText/ReplaceTemplateID_From/text() の ID が同じになるように ID を設定してください。 置き換えた後のテンプレートを囲むタグの id 属性( /MultiText/Text/@id ) と /MultiText/ReplaceTemplateID_To/text() の ID が同じになるように ID を設定してください。 ただし、 /MultiText/ReplaceTemplateID_From/text() の先頭と /MultiText/ReplaceTemplateID_To/text() の先頭には # を記述してください。 # を記述することは、HTML の A href 属性と同じ仕様です。 テンプレートが id="A" にあるとき(/MultiText/Text[@id='A']/text() にあるとき)、 _Keyword を末尾に追加した id 属性のテキスト (/MultiText/Text[@id='A_Keyword ']/text() ) にテンプレートの中の1行にヒットする正規表現を設定してください。 サンプル 置き換える前のテンプレートの例 '* vbslib is provided under 3-clause BSD license. '* Copyright (C) "Sage Plaisir 21" All Rights Reserved. 置き換えた後のテンプレートの例 '* vbslib is provided under 3-clause BSD license. '* Copyright (C) Sofrware Design Gallery "Sage Plaisir 21" All Rights Reserved. 上記テンプレートを ReplaceTemplate.xml の一部に設定する内容の例 #vbslib_copyright_old #vbslib_copyright 表示内容 以下の場所にあるファイルの中にあるテンプレートを置き換えます 編集するフォルダー = Target ReplaceTemplateID_From = #vbslib_copyright_old ReplaceTemplateID_To = #vbslib_copyright 続行するには Enter キーを押してください . . . ------------------------------------------------------------------------------- >ReplaceStringTemplate "Target", "\* Function:" Target\a.txt ソース → SyncFilesMenuLib.vbs *********************************************************************** <<< StartReplace >>> *********************************************************************** StartReplace (src) Function StartReplace( SrcPath as string, TmpDstPath as string, IsDstWillBeExist as boolean ) as StartReplaceObj StartReplaceObj ファイルの一部を行単位で置き換える準備をします。 【引数】 SrcPath 置き換えようとするファイル TmpDstPath 一時ファイルのパス、または置き換えた後のパス IsDstWillBeExist TmpDstPath が置き換えた後のパスかどうか 返り値 コンテキスト 重要なファイルを上書き更新するときは、StartReplace の TmpDstPath 引数に一時的に 出力するパスを指定し、その一時ファイルを作成した後(ファイルを閉じた後)で、 SafeFileUpdateEx を呼び出してください。 ただし、内部で2〜3回のファイルコピーを行います。 サンプル Set rep = StartReplace( "a.txt", "a.txt.updating", True ) Do Until rep.r.AtEndOfStream SplitLineAndCRLF rep.r.ReadLine(), line, cr_lf '// Set "line", "cr_lf" line = Replace( line, "Value=0", "Value=1" ) rep.w.WriteLine line + cr_lf Loop rep.Finish SafeFileUpdateEx "a.txt.updating", "a.txt", Empty SplitLineAndCRLF SafeFileUpdateEx StartReplace を呼び出すと、SrcPath と TmpDstPath のファイルを開きます。 返り値を使って、ファイルにアクセスできます。(下記サンプルを参照) IsDstWillBeExist = False のときは、返り値の Finish メソッドを呼び出すと、全てのファイルを閉じ、 TmpDstPath から SrcPath へ、ファイルコピーを行い、TmpDstPath を削除します。 IsDstWillBeExist に g_VBS_Lib.DstIsBackUp を指定すると、TmpDstPath にバックアップを作成し、 SrcPath 置き換えた後の内容が入ります。 サンプル Set rep = StartReplace( "a.txt", GetTempPath("*.txt"), False ) Do Until rep.r.AtEndOfStream SplitLineAndCRLF rep.r.ReadLine(), line, cr_lf '// Set "line", "cr_lf" line = Replace( line, "Value=0", "Value=1" ) rep.w.WriteLine line + cr_lf Loop rep.Finish SplitLineAndCRLF 関連 → GetTempPath → AddLastOfFileName その他のサンプル → サンプル (ドラッグ&ドロップからテキスト処理) → サンプル (ウィザード) 改行文字コードについて CutIndentOfMultiLineText 、 MultiTextXML_Class は、改行文字コードを明示的に指定する ことができます。 改行文字コードは、SrcPath に記述されているものが、そのまま継承されます。 ただし、 get_ADODBConsts が使える環境である必要があります。 (通常、使えます) ReadLine で取得できる行の末尾には、vbCRLF または vbLF が付きます。 SplitLineAndCRLF を使えば、改行文字を分けることができます。 WriteLine で行を出力するときは、ReadLine で取得した改行文字を付けてください。 また、rep.r 「以外」のファイルから rep.w にライトするときは、リードするファイルを開くときに、 new_TextFileLineSeparatorStack ( g_VBS_Lib.KeepLineSeparators ) が必要です。 テスト → T_Replace.vbs # [T_StartReplace] 関連 → StringStream クラス → FindStringLines → OpenForReplace *********************************************************************** <<< StartReplaceObj クラス >>> *********************************************************************** StartReplaceObj クラス テキストファイルの一部を置き換えるインターフェース 取得 → StartReplace → StartReplace2 r 置き換えようとするファイルのストリーム → TextStream w 一時ファイル、または置き換えた後のファイルのストリーム → TextStream Finish 正常に完了したら呼び出す必要がある関数 ExitFinish Empty 置き換えをキャンセルします。 Class_Terminate デストラクタ。 Finish または ExitFinish が呼ばれなかったら警告します → サンプル *********************************************************************** <<< ReplaceTextFile >>> *********************************************************************** ReplaceTextFile (src) ver4 で、廃止になりました。 OpenForReplace を使ってください。 → OpenForReplace Sub ReplaceTextFile( SrcPath as string, TmpDstPath as string, bDstWillBeExist as boolean, ReplaceList as ReplaceItem, Opt as variant ) ファイルの一部を置き換えます。 【引数】 SrcPath 置き換えようとするファイル TmpDstPath 一時ファイルのパス、または置き換えた後のパス bDstWillBeExist TmpDstPath が置き換えた後のパス=True, 一時パス=False ReplaceList 置き換えるテキスト Opt Empty を指定してください サンプル: Dim reps : new_ReplaceItem_array reps, 1 reps(0).Src = "%base%" : reps(0).Dst = g_sh.CurrentDirectory ReplaceTextFile "file.txt", GetTempPath("*.txt"), False, reps, Empty 1 %base% g_sh.CurrentDirectory file.txt new_ReplaceItem_array については、 → new_ReplaceItem_array : オブジェクトの配列を生成する Class ReplaceItem Public Src Public Dst End Class 参考 → TextFileConvertFormat::Set_ *********************************************************************** <<< サンプル (ドラッグ&ドロップからテキスト処理) >>> *********************************************************************** サンプル (ドラッグ&ドロップからテキスト処理) スクリプト・ファイルに処理をするファイルを直接ドラッグ&ドロップしても、スクリプト・ファイルをダブル・ クリックして開いたウィンドウに処理するファイルをドラッグ&ドロップしても処理ができます。 「line = "> "+ line」 の部分を処理内容に書き換えてお使いください。 Sub Main( Opt, AppKey ) Dim c : Set c = g_VBS_Lib Dim path : path = InputPath( "変換するファイル >", c.CheckFileExists or c.UseArgument1 ) Dim w_:Set w_=AppKey.NewWritable( path ).Enable() Dim rep, line, cr_lf Set rep = StartReplace( path, GetTempPath("Replace_*.txt"), c.DstIsBackUp ) Do Until rep.r.AtEndOfStream SplitLineAndCRLF rep.r.ReadLine(), line, cr_lf line = "> "+ line rep.w.WriteLine line + cr_lf Loop rep.Finish start GetEditorCmdLine( path ) End Sub *********************************************************************** <<< サンプル (ウィザード) >>> *********************************************************************** サンプル (ウィザード) exe name> と表示されるので、入力すると、 デスクトップに、テンプレート・ファイルを少し加工してフォルダを作成します。 wizard sample_wizard.vbs files template.c _src\Test\vbslib_test\T_Replace\T_Replace_Sample1 にあります。 sample_wizard.vbs Sub main2( Opt, AppKey ) Dim exe_name Dim desktop : desktop = g_sh.SpecialFolders( "Desktop" ) Dim rep, line Dim w_:Set w_=AppKey.NewWritable( desktop ).Enable() '//=== Input exe name Do exe_name = input( "exe name>" ) If exist( desktop + "\" + exe_name ) Then Raise 1, "すでにデスクトップに " + exe_name + " が存在するため、新規作成できません" Else Exit Do End If Loop '//=== Make output folder mkdir desktop + "\" + exe_name copy g_vbslib_folder + "*", desktop + "\" + exe_name + "\scriptlib" '//=== Make exe_name.c Set rep = StartReplace( "files\template.c", _ desktop + "\" + exe_name + "\" + exe_name + ".c", True ) Do Until rep.r.AtEndOfStream line = rep.r.ReadLine() line = Replace( line, "Sample", exe_name ) rep.w.WriteLine line Loop rep.Finish '//=== Open output folder Setting_openFolder desktop + "\" + exe_name End Sub *********************************************************************** <<< StartReplace2 >>> *********************************************************************** StartReplace2 Function StartReplace2( SrcPath as string, MidPath as string, Flags as integer, TmpDstPath as string, bDstWillBeExist as boolean ) as StartReplaceObj StartReplaceObj ファイルの一部を置き換えて、更にフィルタ処理をするための準備をします。 【引数】 SrcPath 置き換えようとするファイル MidPath 一時ファイルのパス Flags F_Txt2BinTxt を指定してください(下記) TmpDstPath 一時ファイルのパス、または置き換えた後のパス bDstWillBeExist TmpDstPath が置き換えた後のパスかどうか 返り値 コンテキスト F_Txt2BinTxt StartReplaceObj.w に、Chr(&hFF) から始める行を出力すると、その行はバイナリになり ます。 → バイナリ混在テキスト生成 (txt2bintxt.exe) 参考 → TextFileConvertFormat::Set_ *********************************************************************** <<< PassThroughLineFilters >>> *********************************************************************** PassThroughLineFilters (src) 廃止予定 代わり → FindStringLines → Text (ReplaceTextFile1) Sub PassThroughLineFilters( SrcPath as string, TmpDstPath as string, IsDstWillBeExist as boolean, Opt as Empty, FilterArray as array of string ) 指定のキーワードを含む行を抽出します。 【引数】 SrcPath 置き換えようとするファイル TmpDstPath 一時ファイルのパス、または置き換えた後のパス IsDstWillBeExist TmpDstPath が置き換えた後のパスかどうか Opt Empty または False (=FilterArray に含まない行を抽出) FilterArray キーワードの配列 サンプル (TRACE) と (DEBUG) を含む行だけにします。 PassThroughLineFilters( "a.txt", GetTempPath("*.txt"), False, Empty, _ Array( "(TRACE)", "(DEBUG)" ) テスト → T_Replace.vbs # [T_PassThroughLineFilters] 関連 → FindStringLines → grep (検索) *********************************************************************** <<< SplitLineAndCRLF >>> *********************************************************************** SplitLineAndCRLF (src) Sub SplitLineAndCRLF( LineAndCRLF as string, out_Line as string, out_CRLF as string ) 行の本文と、行末の改行文字を分けます。 【引数】 LineAndCRLF 改行文字が末尾に含まれている可能性がある文字列 out_Line (出力) 改行文字より前の文字列 out_CRLF (出力) 行末の改行文字 ファイル: vbslib 関連 → 改行文字コードについて *********************************************************************** <<< CutCRLF >>> *********************************************************************** CutCRLF (src) Function CutCRLF( Line as string ) 改行文字を削除します。 【引数】 Line 改行文字が削除される文字列 返り値 改行文字が削除された文字列 ファイル: vbslib テスト → T_Replace.vbs # [T_CutCRLF] 関連 → SplitLineAndCRLF *********************************************************************** <<< Translate >>> *********************************************************************** Translate Sub Translate( TranslatorPath as string, FromLanguage as string, ToLanguage as string ) 翻訳ファイルの情報に従って、テキストファイルの一部を翻訳します。 【引数】 TranslatorPath 翻訳ファイル(*.trans)のパス、または、フォルダーのパス FromLanguage 翻訳前の言語。 通常 "JP" ToLanguage 翻訳後の言語。 通常 "EN" 英語に翻訳するときに、英文字以外が残っていたときは、get_ToolsLibConsts().E_NotEnglishChar エラーが発生します。 TranslatorPath 引数にフォルダーのパスを指定した場合、サブ フォルダーも含めた、拡張子が .trans のすべての翻訳ファイルから翻訳します。 ある1つの翻訳ファイルから翻訳しても英文字 以外が残っていたときは、すべての翻訳ファイルから翻訳した後でエラーが発生します。 ソース → ToolsLib.vbs テスト → T_Translate.vbs T_Translate1 T_TranslateFolder T_Translate_sth 参考 → Translate コマンド 翻訳ファイル(*.trans) の説明など 関連 → Switches スイッチに従って、複数のファイルを編集 *********************************************************************** <<< TranslateTest >>> *********************************************************************** TranslateTest Sub TranslateTest( TranslatorPath as string, FromLanguage as string, ToLanguage as string, OutFolderPath as string ) 翻訳ファイルの情報に従って、テキストファイルの一部を翻訳できるかどうかチェックします。 【引数】 TranslatorPath 翻訳ファイルのパス、または、フォルダーのパス FromLanguage 翻訳前の言語。 通常 "JP" ToLanguage 翻訳後の言語。 通常 "EN" OutFolderPath 翻訳後を格納するフォルダーのパス。 または "" = 出力しない 翻訳ファイルの内容は上書きされるため注意してください(要 NewWritable)。 翻訳するファイル名と行番号が追記され、行番号の順番でソートされます。 EN(英語)に翻訳するときは、翻訳後に Ascii 文字だけ使っているかどうかをチェックします。 Ascii 文字以外の文字があるときは、get_ToolsLibConsts().E_NotEnglishChar エラーになります。 TranslatorPath 引数にフォルダーのパスを指定した場合、サブ フォルダーも含めた、拡張子が .trans のすべての翻訳ファイルから翻訳できるかどうかチェックします。 ある1つの翻訳ファイル から翻訳しても英文字以外が残っていたときは、すべての翻訳ファイルから翻訳できるかどうか チェックした後でエラーが発生します。 ソース → ToolsLib.vbs テスト → T_Translate.vbs T_TranslateTest → T_Translate.vbs T_TranslateTest_sth 参考 → Translate コマンド 翻訳ファイル(*.trans) の説明など 関連 → Translate → TranslateTest コマンド *********************************************************************** <<< TranslateEx >>> *********************************************************************** TranslateEx Sub TranslateEx( TranslatorPath as string, FromLanguage as string, ToLanguage as string, in_out_Config as TranslateConfigClass ) 翻訳ファイルの情報に従って、テキストファイルの一部を翻訳します。 【引数】 TranslatorPath 翻訳ファイルのパス FromLanguage 翻訳前の言語。 通常 "JP" ToLanguage 翻訳後の言語。 通常 "EN" in_out_Config (入出力) 各種設定、または Empty → TranslateConfigClass TranslateConfigClass .IsTestOnly True = すべて翻訳されたかどうかチェックだけします。 (デフォルト) False = 翻訳します。 .OutFolderPath 翻訳後のファイルを格納するフォルダーのパス。 省略時は、翻訳後のファイルを出力しません。 .BaseFolderPath 翻訳ファイルの BaseFolder タグを置き換えた後のパス。 省略時は、翻訳ファイルの BaseFolder タグのテキストが使われます。 ソース → ToolsLib.vbs テスト → T_Translate.vbs 参考 → Translate コマンド 翻訳ファイル(*.trans) の説明など *********************************************************************** <<< Translate_getOverwritePaths >>> *********************************************************************** Translate_getOverwritePaths Function Translate_getOverwritePaths( TranslatorPath as string ) Translate で置き換わるすべてのファイルのフルパスを配列で返します。 【引数】 TranslatorPath 翻訳ファイルのパス 返り値 置き換わるすべてのファイルのフルパスの配列 ソース → ToolsLib.vbs テスト → T_Translate.vbs T_Translate_getOverwritePaths *********************************************************************** <<< Translate_getWritable >>> *********************************************************************** Translate_getWritable Function Translate_getWritable( TranslatorPath as string ) Translate で置き換わるすべてのファイルを含むフォルダーのフルパスを配列で返します。 【引数】 TranslatorPath 翻訳ファイルのパス 返り値 フォルダーのフルパスの配列 ソース → ToolsLib.vbs テスト → T_Translate.vbs T_Translate_getWritable *********************************************************************** <<< new_TranslateToEnglish >>> *********************************************************************** new_TranslateToEnglish (src) キーワード: 英訳、翻訳 廃止 Function new_TranslateToEnglish( DictionaryCsvPath as string ) as TranslateToEnglish TranslateToEnglish 辞書ファイルを使って、ソース・ファイルのコメントを英訳します。 【引数】 DictionaryCsvPath CSV 形式の辞書ファイルのパス モジュール・ファイル: ToolsLib.vbs サンプル: Dim tr : Set tr = new_TranslateToEnglish( "Text1.txt.trans.csv" ) '// tr.IsReverseTranslate = True Dim w_:Set w_=AppKey.NewWritable( tr.Writable ).Enable() tr.Translate Text1.txt.trans.csv 関連 → サンプル - new_TranslateToEnglish 英訳処理のサンプル いわゆる英訳ソフトのような、文法解析を行って大きな辞書を引くような翻訳ではありません。 内部では、単純なテキストの置換と、置換後のファイルに含まれる文字が英文字だけかどうか のチェックをします。 翻訳後に英文字以外の文字が残ったら、TranslateToEnglish::c. E_NotEnglishChar エラーになります。 1行目の左は、変換前のファイルパスです。 1行目の右は、変換後のファイルパスです。 1行目は、% % で囲んだ環境変数を指定できます。 1行目の右を省略すると、ファイルの置き換えをします。 2行目以降は、翻訳するキーワードを指定します。 Text1_trans.csv Text1.c, %eng%\Text1.c メイン関数, Main function サブ関数, Sub function Text1.c %eng%\Text1.c #include int main() { } // メイン関数 int sub() { } // サブ関数 #include int main() { } // Main function int sub() { } // Sub function テスト → TranslateToEnglish フォルダ 関連 → sample / CheckEnglishOnly 英文字以外が無いか、フォルダ全体をチェックする *********************************************************************** <<< TranslateToEnglish クラス >>> *********************************************************************** TranslateToEnglish クラス 廃止 取得 → new_TranslateToEnglish .DictionaryCsvPath Property TranslateToEnglish::DictionaryCsvPath as string CSV 形式の辞書ファイルのパス。 new_TranslateToEnglish に指定した引数の値と同じです。 .NotEnglishTextPath Property TranslateToEnglish::NotEnglishTextPath as string 英語以外のテキスト・ファイルのパス。 new_TranslateToEnglish を呼び出したら、翻訳 CSV ファイルに書かれたパスが格納されます。 このとき、翻訳 CSV ファイルに書かれた環境変数は展開されます。 .Translate を呼び出す前に変更することができます。 .EnglishTextPath Property TranslateToEnglish::EnglishTextPath as string 英語のテキスト・ファイルのパス。 NotEnglishTextPath と同じパスを指定できます。 new_TranslateToEnglish を呼び出したら、翻訳 CSV ファイルに書かれたパスが格納されます。 このとき、翻訳 CSV ファイルに書かれた環境変数は展開されます。 .Translate を呼び出す前に変更することができます。 .IsReverseTranslate Property TranslateToEnglish::IsReverseTranslate as boolean True なら、翻訳する方向を逆に設定します。 EnglishTextPath から NotEnglishTextPath に翻訳します。 デフォルトは False です。 .Writable Property TranslateToEnglish::Writable as string 出力ファイルのパス。 AppKey.NewWritable に指定してください。 .Translate Sub TranslateToEnglish::Translate() 翻訳を実行します。 .c.E_NotEnglishChar Property TranslateToEnglish::c.E_NotEnglishChar as integer 翻訳後も英文字以外の文字が残っていたときのエラーコード。 .Reverse が呼び出されたときは、このエラーは発生しません。 *********************************************************************** <<< サンプル - new_TranslateToEnglish >>> *********************************************************************** サンプル - new_TranslateToEnglish 廃止 翻訳ファイル *.trans.csv を、変換対象のフォルダーと同じ構成で配置して、翻訳します。 cd g_fs.GetParentFolderName( WScript.ScriptFullName ) Dim trs, tr, folder, fnames(), fname, w_, step_path, b set_ "folder_jp", "C:\FolderA" set_ "folder_en", GetFullPath( "..\folder_en", WScript.ScriptFullName ) echo_line echo "コメントを英訳します" echo "From: "+ GetVar( "folder_jp" ) echo "To: "+ GetVar( "folder_en" ) pause '//=== 翻訳 CSV ファイルを集める Set trs = new ArrayClass ExpandWildcard GetVar( "folder_en" ) +"\*.trans.csv", F_File or F_SubFolder, folder, fnames For Each fname in fnames step_path = fname : CutLastOf step_path, ".trans.csv", Empty set_ "step", step_path trs.Add new_TranslateToEnglish( folder +"\"+ fname ) Next '//=== 翻訳する。 ただし、翻訳済みファイルがあるとき(英文字以外が無く、新しいとき)は処理しない For Each tr In trs.Items b = MakeRule_compare( tr.EnglishTextPath, tr.NotEnglishTextPath ) If not b Then b = ( GetLineNumsExistNotEnglighChar( tr.EnglishTextPath, Empty ) > 0 ) If b Then Set w_=AppKey.NewWritable( tr.Writable ).Enable() tr.Translate End If Next 翻訳ファイル *.trans.csv %folder_jp%\%step%, %folder_en%\%step% 日本語, Japanese *********************************************************************** <<< GetLineNumsExistNotEnglighChar >>> *********************************************************************** GetLineNumsExistNotEnglighChar (src) Function GetLineNumsExistNotEnglighChar( Path as string, out_LineNums as Array of integer ) as integer テキスト・ファイルの中に、英文字以外の文字が含まれる行番号の配列を取得します。 【引数】 Path テキスト・ファイルのパス out_LineNums (出力) 英文字以外の文字が含まれる行番号の配列、Empty 指定可 返り値 英文字以外の文字が含まれる行数 モジュール・ファイル: ToolsLib.vbs サンプル GetLineNumsExistNotEnglighChar "Text1.txt", line_nums '//[out] line_nums For Each i In line_nums echo i Next サンプル Set tr = new_TranslateToEnglish( "Text1.txt.trans.csv" ) If GetLineNumsExistNotEnglighChar( tr.EnglishTextPath, Empty ) > 0 Then ... 関連 → CheckEnglishOnly → LenK 日本語(文字コード256以上)を 2文字として文字数を返します。 *********************************************************************** <<< CheckEnglishOnly >>> *********************************************************************** CheckEnglishOnly Function CheckEnglishOnly( CheckFolderPath as string, SettingPath as string ) as ArrayClass of CheckEnglishOnlyFound テキスト・ファイルの中に、英文字以外の文字が含まれるファイルを一覧します。 【引数】 CheckFolderPath 調べるフォルダのパス SettingPath 設定ファイルのパス。または Empty 返り値 英文字以外の文字が含まれるファイルの情報 モジュール・ファイル: ToolsLib.vbs サンプル Set founds = CheckEnglishOnly( "FolderA", "SettingForCheckEnglish.ini" ) For Each file In founds.Items For Each found In file.NotEnglishItems.Items echo file.Path +"("& found.LineNum &"): "+ found.NotEnglishText Next Next If founds.Count >= 1 Then Error 設定ファイルに下記が記述されていないときは、上記の CheckEnglishOnly 関数呼び 出しでエラーになり、続きを実行しません。 [CheckEnglishOnlyVbs] IsRaiseError = False サンプル scriptlib フォルダーをチェックする → 3.CheckNotEnglish フォルダー ソース → ToolsLib.vbs # [CheckEnglishOnly] テスト → T_CheckEnglishOnly.vbs # [T_CheckEnglishOnly] 関連 → CheckEnglishOnly (exeファイル) 実行ファイル版、設定ファイルの例 → CheckEnglishOnly コマンド コマンド・プロンプト版 → GetLineNumsExistNotEnglighChar 簡易版 → TranslateTest *********************************************************************** <<< MakeSettingForCheckEnglish >>> *********************************************************************** MakeSettingForCheckEnglish Sub MakeSettingForCheckEnglish( CheckEnglishOnlyFilePath as string, TranslateFilePaths as array of string ) CheckEnglishOnly の対象外となるファイルの一覧を翻訳ファイル(*.trans)から作成します。 【引数】 CheckEnglishOnlyFilePath ファイルの一覧が書かれる出力ファイルのパス TranslateFilePaths 翻訳ファイルのパスの配列 サンプル VBScript MakeSettingForCheckEnglish "SettingForCheckEnglish.ini", Array( "Sample.trans" ) 翻訳ファイル CheckEnglishOnly の設定ファイル Sample1.txt ..\Sample2.txt 日本語Japanese 英語English [CheckEnglishOnlyExe] ;// From "sample.trans" file ExceptFile = Sample1.txt ExceptFile = ..\Sample2.txt ソース → ToolLib.vbs # [MakeSettingForCheckEnglish] テスト → T_CheckEnglishOnly.vbs # [T_MakeSettingForCheckEnglish] 関連 → CheckEnglishOnly → Translate *********************************************************************** <<< ConvertBinaryEmulated >>> *********************************************************************** ConvertBinaryEmulated (src) 書きかけ Dim zip1, sub_fo1, step_paths, step_path, target_root, work_root '//=== convert binary file emulated zip1 = work_root +"\converted_files" unzip "converted_files.zip", zip1, Empty sub_fo1 = "target" step_paths = Array( sub_fo1+"\file1.bin", sub_fo1+"\file2.bin" ) For Each step_path In step_paths ConvertBinaryEmulated target_root +"\"+ step_path, Empty, False, _ zip1+"\src\"+step_path, zip1+"\dst\"+step_path Next del zip1 *********************************************************************** <<< その他 >>> *********************************************************************** その他 → 開発サポートツール - PartRep → ReplaceSymbolsClass 複数のファイルの中の複数の単語(文字列)を一度に置き換えます。 → % を使った変換式 → OpenForReplaceXML → ReplaceRange (ReplaceTextFile1) 指定のタグで囲まれたテキストを置き換えます 旧仕様 ConvertToAbsPath → ConvertToFullPath *********************************************************************** <<< テンポラリ フォルダー >>> *********************************************************************** テンポラリ フォルダー vbslib を使うと、PC の内臓 HDD (OSが指定するテンポラリ・フォルダの中の Report フォルダ) に、一時ファイルを作成することがあります。 PCを借りているときは情報漏えいに注意してください。 vbslib のテンポラリ フォルダーの場所の例: (Windows Vista/7 のとき) C:\Users\user1\AppData\Local\Temp\Report %USERPROFILE%\AppData\Local\Temp\Report C:\Documents and Settings\user1\Local Settings\Temp\Report (Windows XP のとき) 上記フォルダーに、日付を表すフォルダーを作成し、2日前のフォルダーは GetTempPath 関数 を呼び出したときに削除されます。 C:\Users\user1\AppData\Local\Temp\Report\010101 ↑ 年(西暦下2桁)、月、日 テンポラリ フォルダーを削除するときは、 → DelTemp テンポラリ フォルダーの設定は、 Setting_getTemp 関数を作成することで変更できます。 ゴミ箱にも一時ファイルが格納されることがあります。 → SafeFileUpdate ごみ箱を空にしてください。 バッチファイルでテンポラリ フォルダーのパスを取得する: REM // Set "work_path" for /f %%a in ('powershell -Command "(Get-Date).ToString(\"yyMMdd\")"') do set work_path=%%a set work_path=%USERPROFILE%\AppData\Local\Temp\Report\%work_path% echo "%work_path%" pause yyMMdd → タイムスタンプを取得する (LastWriteTime) *********************************************************************** <<< GetTempPath >>> *********************************************************************** (src) GetTempPath Function GetTempPath( BasePath as string ) as string テンポラリ・フォルダ の中のファイルやフォルダのパスを返します。 【引数】 BasePath ファイル名のテンプレート。 * または ? を含んでもよい 返り値 テンポラリ・フォルダの中のファイルパス BasePath に、* または ? を含んでいる場合は、ファイルまたはフォルダが存在 しないパスに変換して返します。 サンプル・ファイルパス: (Windows Vista のとき) C:\Users\user1\AppData\Local\Temp\Report\090401\DataA_090401_1300_1.xml C:\Users\user1\AppData\Local\Temp\Report\090401\DataA_1.xml ファイルパスは、環境変数 TEMP の値を使っています。 上段は * 、下段は ? を使ったとき。 サンプル: Dim f, path Dim c : Set c = g_VBS_Lib path = GetTempPath( "DataA_*.xml" ) Set f = OpenForWrite( path, c.Unicode ) f.WriteLine "" f = Empty start path GetTempPath DataA_*.xml c.Unicode CreateFile にワイルドカードを指定すれば、テンポラリ・フォルダにファイルを作る ので、簡単にテキストファイルや XML ファイルを作成できます。 サンプル: obj の xml プロパティを、テンポラリファイルに出力して開きます。 start CreateFile( "*.xml", obj.xml ) start CreateFile obj xml 本関数を呼び出すと、テンポラリ・フォルダに作成した2日以上前のファイルを削除 します。 このとき、ファイルがロックされていると再試行を繰り返して、最終的に エラーになります。 BasePath 引数は、テンポラリ・フォルダからの相対パスになり、* はタイムスタンプと 識別番号になります。 ? は識別番号になります。 存在するファイルパスにならない ように調整され、常に新しいファイルを作成します。 同時に保存期間を超えたファイル やフォルダを削除します。(起動したプロセスで初めてテンポラリ・フォルダにファイル を作成するとき、および g_TempPath= Empty のときのみ) 関連 → FileSystemObject::GetTempName *********************************************************************** <<< ファイル名、パス >>> *********************************************************************** ファイル名、パス → DesktopPath デスクトップのフル・パスを返す。 → GetFullPath フル・パスを返す。 → GetStepPath 相対パスを返す。 → GetParentFullPath 親フォルダのフル・パスを返す。 → IsFullPath フル・パスかどうかを返します。 → AddLastOfFileName ファイルパスの最後文字列を追加します。 → FilePathClass ファイルのパスか、ファイルの内容に相当する文字列の抽象。 参考 → ファイル名、パス (Windows) → サブ・フォルダー記号 (vbslib) → パスにピリオドを3つ並べた場合 (vbslib) 関連 → 文字列 → PathDictionaryClass パスの辞書(集合) → new_PathDictionaryClass_fromXML *********************************************************************** <<< DesktopPath >>> *********************************************************************** DesktopPath (src) Function DesktopPath() as string デスクトップのフル・パスを返します。 *********************************************************************** <<< GetFullPath >>> *********************************************************************** GetFullPath Function GetFullPath( StepPath as string, BasePath as string ) as string フル・パスを返します。 【引数】 StepPath 返り値と同じファイルの相対パス BasePath 基準フォルダのフル・パス、Empty でカレントフォルダ 返り値 StepPath と同じファイルのフル・パス サンプル path2 = GetFullPath( Path, BaseFolderPath ) path2 = GetFullPath( "..\"+ Path, BaseFilePath ) path2 = GetFullPath( Path, GetParentFullPath( BaseFilePath ) ) BasePath をファイルパスにしたときは、StepPath を1つ親にしてください。 GetFullPath( "file.txt", "C:\folder1" ) = GetFullPath( "..\file.txt", "C:\folder1\file2.txt" ) StepPath = Empty なら、Empty が返ります。 IsEmpty( GetFullPath( Empty, BaseFolderPath ) g_fs.GetAbsolutePathName は、StepPath に * が入っていると、ピリオドに 置き換わってしまいますが、GetFullPath では発生しません。 パスにピリオドを3つ並べた場合 (vbslib) 親フォルダー、または、その親フォルダー … と探すときは、"..." とピリオドを 3つ並べてください。 ただし、スクリプトを記述できるときは、 SearchParent を呼ぶほうが可読性が高まります。 GetFullPath( "...\file.txt", "C:\folder1\sub" ) 上記の返り値は、C:\folder1\sub\file.txt 、C:\folder1\file.txt 、C:\file.txt のいずれかになります。 または、E_PathNotFound エラーになります。 参考 → ファイル名、パス (VBS) ソース → vbslib.vbs → vbslib_mini.vbs テスト → T_Path.vbs # [T_GetFullPath] 関連 → GetCaseSensitiveFullPath 大文字小文字をファイル名に合わせます → ConvertToFullPath テキストファイルの中をフルパスにします → GetPathWithSeparator Path の最後を区切り記号にします → GetAbsolutePathName Scripting.FileSystemObject によるフル パス → GetFullPath メソッド 変数があれば展開して、フル パスを返します *********************************************************************** <<< GetStepPath >>> *********************************************************************** GetStepPath Function GetStepPath( FullPath as string, BasePath as string ) as string 相対パスを返します。 【引数】 FullPath 返り値が指すファイルと同じファイルのフル・パス BasePath 基準フォルダーのフル・パス 返り値 FullPath 引数が指すファイルと同じファイルの相対パス ソース → vbslib.vbs テスト → T_Path.vbs T_GetStepPath *********************************************************************** <<< NormalizePath >>> *********************************************************************** NormalizePath Function NormalizePath( Path as string ) as string ファイル・パスの ".." や "." をなくします。 【引数】 Path 変換する前のファイル・パス 返り値 変換した後のファイル・パス サンプル Assert NormalizePath( "C:\folder\..\a" ) = "C:\a" Assert NormalizePath( "C:\..\a" ) = "C:\..\a" Assert NormalizePath( "C:\folder\.\a" ) = "C:\folder\a" Assert NormalizePath( "C:\folder\a\" ) = "C:\folder\a" Assert NormalizePath( "C:\" ) = "C:\" Assert NormalizePath( "http://example.com/folder/" ) = "http://example.com/folder/" 末尾の \ はカットされますが、/ はカットされません。 ソース → vbslib.vbs テスト → T_Path.vbs T_NormalizePath *********************************************************************** <<< GetCaseSensitiveFullPath >>> *********************************************************************** GetCaseSensitiveFullPath Function GetCaseSensitiveFullPath( StepPath as string ) as string フル・パスを返します。 大文字小文字はファイル名に合わせます。 【引数】 StepPath 返り値と同じファイルの相対パス、または、フルパス 返り値 大文字小文字をファイル名に合わせたフル・パス 本関数は、ファイルシステムにアクセスして、ファイル名を調べます。 ファイルが存在しないときは、カレント フォルダーを基準とした相対パスとして、 フルパスを返します。 サンプル path = GetCaseSensitiveFullPath( "file.txt" ) Assert path = "C:\Folder\File.txt" file.txt に該当するファイルのフルパスが、C:\Folder\File.txt のとき。 ソース → vbslib.vbs テスト → T_Path.vbs # [T_GetFullPath] 関連 → GetFullPath *********************************************************************** <<< IsFullPath >>> *********************************************************************** IsFullPath (src) Function IsFullPath( Path as string ) as boolen Path に指定したパスがフル・パスかどうかを返します。 テスト → T_Path.vbs # [T_IsFullPath] *********************************************************************** <<< GetRootSeparatorPosition >>> *********************************************************************** GetRootSeparatorPosition Function GetRootSeparatorPosition( Path as string ) as integer Path に入っているルート・フォルダーの位置を返します。 【引数】 Path ファイルなどのパス 返り値 ルート・フォルダーの位置、0=相対パス サンプル Assert GetRootSeparatorPosition( "C:\File" ) = 3 Assert GetRootSeparatorPosition( "\File" ) = 1 Assert GetRootSeparatorPosition( "File" ) = 0 Assert GetRootSeparatorPosition( "..\File" ) = 0 Assert GetRootSeparatorPosition( "\\PC01\Folder\File" ) = 14 Assert GetRootSeparatorPosition( "http://www.example.com/" ) = 23 ソース → vbslib.vbs テスト → T_Path.vbs T_GetRootSeparatorPosition *********************************************************************** <<< GetFilePathSeparator >>> *********************************************************************** GetFilePathSeparator Function GetFilePathSeparator( Path as string ) as string Path に入っているフォルダーの区切り記号を返します。 【引数】 Path ファイルなどのパス 返り値 フォルダーの区切り記号 フォルダーの区切り記号が無いときは、"\" を返します。 最も左にある / または \ が、どちらの文字かを返します。 サンプル Assert GetFilePathSeparator( "http://www.example.com/" ) = "/" ソース → vbslib.vbs *********************************************************************** <<< GetPathWithSeparator >>> *********************************************************************** GetPathWithSeparator Function GetPathWithSeparator( in_Path as string ) as string 文字列の末尾に、フォルダーの区切り記号がなければ、追加します。 【引数】 in_Path ファイルなどのパス 返り値 フォルダーの区切り記号が最後に付いたパス フォルダーの区切り記号は、in_Path 引数の値に応じて、"\" または "/" が追加されます。 フォルダーのパスの末尾に区切り記号があれば、ファイル名やサブ フォルダー名を追加するときに、 フォルダーのパス + 追加する名前、に統一することができます。 フォルダーのパス +"\"+ 追加する名前、にしないでください。 サンプル Assert GetPathWithSeparator( "C:\BaseFolder" ) = "C:\BaseFolder\" Assert GetPathWithSeparator( "C:\" ) = "C:\" Assert GetPathWithSeparator( "" ) = "" Assert GetPathWithSeparator( "." ) = "" Assert GetPathWithSeparator( ".." ) = "..\" Assert GetPathWithSeparator( "folder" ) = "folder\" Assert GetPathWithSeparator( "folder/sub" ) = "folder/sub/" Assert GetPathWithSeparator( "http://www.example.com/fo" ) = "http://www.example.com/fo/" Assert GetPathWithSeparator( "http://www.example.com/" ) = "http://www.example.com/" ソース → vbslib.vbs テスト → T_Path.vbs T_GetPathWithSeparator 関連 → GetLastSeparatorOfPath 末尾にあるフォルダーの区切り記号を返します → CutLastOf 末尾にあればカットします → GetFullPath フルパスに変換します → AddIfNotExist 列挙している文字列の中になければ追加します *********************************************************************** <<< GetLastSeparatorOfPath >>> *********************************************************************** GetLastSeparatorOfPath Function GetLastSeparatorOfPath( in_Path as string ) as string 文字列の末尾に、フォルダーの区切り記号があれば、それを返します。 【引数】 in_Path ファイルなどのパス 返り値 "\" または "/" または "" フォルダーの区切り記号は、"\" または "/" です。 文字列の末尾が、フォルダーの区切り記号でなければ、"" を返します。 サンプル GetStepPath が削除した最後の \ を復活します。 last_separator = GetLastSeparatorOfPath( path ) step_path = GetStepPath( path, base_path ) + last_separator Assert path = "C:\Folder\Sub\" Assert last_separator = "\" Assert base_path = "C:\Folder" Assert step_path = "Sub\" ソース → vbslib.vbs 関連 → GetPathWithSeparator → CutLastOf *********************************************************************** <<< get_PathNameRegularExpression >>> *********************************************************************** get_PathNameRegularExpression Function get_PathNameRegularExpression() as VBScript.RegExp フォルダーの区切り記号で区切る正規表現オブジェクトを返します。 【引数】 返り値 正規表現オブジェクト → VBScript.RegExp フォルダーの区切り記号は、"\" または "/" です。 サンプル Set path_names = get_PathNameRegularExpression().Execute( _ "sub\a.txt" ) For Each name In path_names WScript.echo "FirstIndex = " & name.FirstIndex & _ ", Length = " & name.Length & ", Value = " & name.Value Next FirstIndex = 0, Length = 4, Value = sub\ FirstIndex = 4, Length = 5, Value = a.txt サンプル パス(検索対象) 区切った後(検索結果) "sub\a.txt" "sub\", "a.txt" "sub2/a.txt\" "sub2/", "a.txt\" "a.txt" "a.txt" "" (検索結果0件) "\a.txt" "\", "a.txt" "\\a.txt" "\", "\", "a.txt" "http://www.example.com/~user/" "http:/", "/", "www.example.com/", "~user/" ソース → ToolsLib.vbs テスト → T_Wildcard.vbs T_PathNameRegularExpression 関連 → Split *********************************************************************** <<< SplitPathToSubFolderSign >>> *********************************************************************** SplitPathToSubFolderSign (src) Sub SplitPathToSubFolderSign( in_out_Path as string, out_SubFolderSign as string, out_IsFolder as boolean, out_Separator as string ) パスから、サブ フォルダー記号を分離します。 【引数】 in_out_Path ファイルなどのパス (入力)記号あり、(出力)記号なし out_SubFolderSign (出力) サブ フォルダー記号、"." か "*" か "" out_IsFolder (出力) フォルダー指定かどうか out_Separator (出力) フォルダー区切り文字 サンプル path = "C:\Folder\.\log.txt" SplitPathToSubFolderSign path, sign, is_folder, separator Assert path = "C:\Folder\log.txt" Assert sign = "." Assert is_folder = False Assert separator = "\" サブ フォルダー記号 パスの最後の \ の左に * または . を指定することで、サブ フォルダーを 検索するかどうかを指定することができます。 "*\file.txt" *\ … サブ フォルダーも含めて file.txt を検索する ".\file.txt" .\ … サブ フォルダーも含めないで file.txt を検索する "fo\*\file.txt" *\ … サブ フォルダーも含めて fo フォルダーの中の file.txt を検索する "fo\.\file.txt" .\ … fo フォルダーにある file.txt を検索する (参考) zsh では、** がサブ フォルダーも含めて検索します。 パスの最後が \ のときは、フォルダー(ファイル以外)を指定したことになります。 つまり、 フォルダーにマッチさせたいときは、最後に \ を付けてください。 "*\folder\" \ … サブ フォルダーも含めて、フォルダー名 folder を検索する (メモ) \ を付ける理由は、Group* のように最後にワイルドカード * があるとき、ファイルと フォルダーの両方にヒットしてしまうと扱いが難しくなるためです。 関連 → vbslib のワイルドカード サンプル サブ フォル ダー記号 フォルダー 指定かどうか path (入力) path (出力) "C:\Folder\.\log.txt" "C:\Folder\log.txt" "." False "C:\Folder\*\log.txt" "C:\Folder\log.txt" "*" False "C:\Folder\*\*.txt" "C:\Folder\*.txt" "*" False "C:\Folder\log.txt" "C:\Folder\log.txt" "" False "C:\Folder\*.txt" "C:\Folder\*.txt" "" False "C:\Folder\*" "C:\Folder\*" "" False "C:\Folder\*\*" "C:\Folder\*" "*" False "C:\Folder\.\*" "C:\Folder\*" "." False "C:\.\Folder\" "C:\Folder" "." True "C:\*\Folder\" "C:\Folder" "*" True "C:\Folder\*\" "C:\Folder\*" "" True "C:\Folder\.\" "C:\Folder" "" True "C:\Folder\*\*\" "C:\Folder\*" "*" True "C:\Folder\.\*\" "C:\Folder\*" "." True 補足 次の関数に、サブ フォルダー記号が使えます。 → ArrayFromWildcard → ExpandWildcard → new_PathDictionaryClass_fromXML → PathDictionaryClass テスト → T_Path.vbs T_SplitPathToSubFolderSign *********************************************************************** <<< ReplaceRootPath >>> *********************************************************************** ReplaceRootPath Function ReplaceRootPath( BeforePath as string, BeforeRootFullPath as string, AfterRootFullPath as string, IsReplaceParent as boolean ) ルート・フォルダーを入れ替えたときのフルパスに変換します。 【引数】 BeforePath 変換する前のパス、フルパス または 相対パス BeforeRootFullPath 変換する前のルート・フォルダーのフルパス AfterRootFullPath 変換した後のルート・フォルダーのフルパス IsReplaceParent 通常 True、親フォルダー記号を "_parent" に置き換えるかどうか 返り値 BeforePath を変換した後のフルパス BeforePath 引数が相対パスのときは、変換前の BasePath の基準フォルダーが BeforeRootFullPath と して処理します。 IsReplaceParent 引数について詳細は、 → ReplaceParentPath サンプル path = ReplaceRootPath( "a.txt", "C:\FolderA", "C:\FolderB", True ) Assert path = "C:\FolderB\a.txt" サンプル path = GetParentFullPath( ReplaceRootPath( "sub\a.txt", "C:\FolderA", "C:\FolderB", True ) ) Assert path = "C:\FolderB\sub" サンプル BeforeRootFullPath = "C:\FolderA"、AfterRootFullPath = "C:\FolderB" のときのサンプルを示します。 BeforePath IsReplaceParent 返り値 "a.txt" True "C:\FolderB\a.txt" "C:\FolderA\a.txt" True "C:\FolderB\a.txt" "sub\a.txt" True "C:\FolderB\sub\a.txt" "C:\FolderA\sub\a.txt" True "C:\FolderB\sub\a.txt" "..\FolderC\a.txt" True "C:\FolderB\_parent\FolderC\a.txt" "C:\FolderC\a.txt" True "C:\FolderB\_parent\FolderC\a.txt" "..\FolderC\a.txt" False "C:\FolderC\a.txt" "D:\FolderA\a.txt" True (エラー) "C:\FolderC\a.txt" False "C:\FolderC\a.txt" "." True "C:\FolderB" ソース → vbslib.vbs テスト → T_Path.vbs T_ReplaceRootPath 関連 → GetParentFoldersName → GetInputOutputFilePaths *********************************************************************** <<< GetParentFullPath >>> *********************************************************************** GetParentFullPath (src) Function GetParentFullPath( Path as string ) as string Path に指定したファイルやフォルダの親フォルダのフル・パスを返します。 【引数】 Path 基準パス(相対パスは、カレントからの相対) 返り値 親フォルダのフル・パス サンプル cd "C:\Folder" Assert GetParentFullPath( "sub\file.txt" ) = "C:\Folder\sub" 参考 → FileSystemObject::GetParentFolderName 関連 → SearchParent *********************************************************************** <<< ReplaceParentPath >>> *********************************************************************** ReplaceParentPath Function ReplaceParentPath( Path as string, FromSign as string, ToSign as string ) as string 親フォルダーの記号を置き換えます。 【引数】 Path 置き換える前のパス FromSign 置き換える前の親フォルダーの記号 ToSign 置き換えた後の親フォルダーの記号 返り値 置き換えた後のパス 親フォルダーにアクセスさせないときに使用します。 返り値に、FromSign の文字列は、全く含まれなくなります。 内部で、 NormalizePath が呼ばれます。 親フォルダーの記号を戻すときにも ReplaceParentPath 関数が使えます。 サンプル Assert ReplaceParentPath( "..\..\folder", "..", "_parent" ) = "_parent\_parent\folder" ソース → vbslib.vbs テスト → T_Path.vbs T_ReplaceParentPath 関連 → ReplaceRootPath キーワード: _parent *********************************************************************** <<< GetCommonParentFolderPath >>> *********************************************************************** GetCommonParentFolderPath Function GetCommonParentFolderPath( in_PathA as string, in_PathB as string ) 共通する親フォルダーのパスを返します。 【引数】 in_PathA パスA in_PathB パスB 返り値 パスA と パスB に共通する親フォルダーのパス、最後は \ または / 共通する親フォルダーがあるときは、最後がフォルダーの区切り記号になります。 返す値の最後をフォルダーの区切り記号ではないようにしたいとき 共通する親フォルダーがないときは、"" が返ります。 in_PathA = in_PathB のときは、親フォルダーのパスが返ります。 片方が Empty なら、もう片方のパスがそのまま返ります。 フォルダーのの区切り記号は、\ または / のどちらでも構いません。 サンプル Assert GetCommonParentFolderPath( "C:\A\B\File.txt", "C:\A\B\File.txt" ) = "C:\A\B\" Assert GetCommonParentFolderPath( "C:\A\File.txt", "D:\A\File.txt" ) = "" Assert GetCommonParentFolderPath( "http://example.com/i", "http://example.com/i" ) = _ "http://example.com/" ソース → vbslib.vbs テスト → T_Path.vbs T_GetCommonParentFolderPath *********************************************************************** <<< GetCommonSubPath >>> *********************************************************************** GetCommonSubPath Function GetCommonSubPath( in_PathA as string, in_PathB as string, in_FilePath as string ) 共通するサブ フォルダーのパスを返します。 【引数】 in_PathA パスA in_PathB パスB in_FilePath パスがファイル名かどうか。 False=フォルダー名 返り値 パスA と パスB に共通するサブ フォルダーのパス 返す値の最後をフォルダーの区切り記号にしたいとき → GetCommonParentFolderPath サンプル Assert GetCommonSubPath( "C:\A\B\File.txt", "C:\A\B\File.txt", True ) = "C:\A\B" Assert GetCommonSubPath( "C:\A\C\File.txt", "C:\B\C\File.txt", True ) = "C" Assert GetCommonSubPath( "C:\A\C\File.txt", "C:\B\D\File.txt", True ) = "" Assert GetCommonSubPath( "C:\A\B", "C:\A\B", False ) = "C:\A\B" Assert GetCommonSubPath( "C:\A\C", "C:\B\C", False ) = "C" Assert GetCommonSubPath( "C:\A\C", "C:\B\D", False ) = "" Assert GetCommonSubPath( "", "C:\B\D", False ) = "" ソース → vbslib.vbs テスト → T_Path.vbs T_GetCommonSubPath *********************************************************************** <<< GetIdentifiableFileNames >>> *********************************************************************** GetIdentifiableFileNames Function GetIdentifiableFileNames( in_FullPathArray as array of string ) as dictionary of string フル パスから、識別可能ファイル名に変換します。 【引数】 in_FullPathArray フル パスの配列 返り値 識別可能ファイル名をキーとした、フル バスの辞書 同じファイル名がないときは、返り値のキーはファイル名になります。 同じファイル名があるときは、そのファイルの親フォルダー名もキーに含まれます。 サンプル full_paths = Array( _ "C:\Folder\Sub1\FileA.txt", _ "C:\Folder\Sub2\FileA.txt", _ "C:\Folder\Sub2\FileB.txt" ) Set output = GetIdentifiableFileNames( full_paths ) id_file_names = Array( _ "FileB.txt", _ "Sub1\FileA.txt", _ "Sub2\FileA.txt" ) full_paths = Array( _ "C:\Folder\Sub2\FileB.txt", _ "C:\Folder\Sub1\FileA.txt", _ "C:\Folder\Sub2\FileA.txt" ) Assert IsSameArray( output.Keys, id_file_names ) Assert IsSameArray( output.Items, full_paths ) 同じフル パスが含まれているときは、エラーにはなりませんが、フル パスから変換しません。 また、辞書のキーは重複できないので、1つにまとめられます。 よって、要素数が減ります。 サンプル full_paths = Array( _ "C:\Folder\Sub\File.txt", _ "C:\Folder\Sub\File.txt" ) Set output = GetIdentifiableFileNames( full_paths ) id_file_names = Array( _ "C:\Folder\Sub\File.txt" ) full_paths_answer = Array( _ "C:\Folder\Sub\File.txt" ) Assert IsSameArray( output.Keys, id_file_names ) Assert IsSameArray( output.Items, full_paths_answer ) ソース → vbslib.vbs テスト → T_Path.vbs T_GetIdentifiableFileNames *********************************************************************** <<< GetParentFoldersName >>> *********************************************************************** GetParentFoldersName (src) Function GetParentFoldersName( FilePath as string, Level as integer, SeparatorReplacedStr as Empty or string ) FilePath に指定したファイルが入ったフォルダーの名前を Level 個つなげたものを返します。 【引数】 FilePath 基準となるファイルまたはフォルダーのパス Level 親フォルダの個数。 親の方向へたどる数。 1以上 SeparatorReplacedStr フォルダー区切り文字を置き換えた後の文字 返り値 複数の親フォルダーの名前をつなげたもの Level = 1 なら、ファイルが入っているフォルダーの名前が返ります。 Level = 2 なら、ファイルが入っているフォルダーの親フォルダーの名前と、SeparatorReplacedStr 引数と、ファイルが入っているフォルダーの名前を結合した文字列が返ります サンプル cd "C:\Folder" Assert GetParentFoldersName( "sub\file.txt", 1, "/" ) = "sub" Assert GetParentFoldersName( "sub\file.txt", 2, "/" ) = "Folder/sub" Assert GetParentFoldersName( "sub\file.txt", 99, "/" ) = "C:/Folder/sub" Level が大きすぎても、エラーにはなりません。 テスト → T_Path.vbs # [T_GetParentFoldersName] 関連 → ReplaceRootPath *********************************************************************** <<< SearchParent >>> *********************************************************************** SearchParent (src) Function SearchParent( StepPath as string ) as string StepPath に指定したファイルまたはフォルダを、親フォルダに向かって探します。 【引数】 StepPath ファイル名、または相対パス 返り値 見つかったファイルまたはフォルダのフル・パス サンプル ..\common.xml などを開きます Set root = LoadXML( SearchParent( "common.xml" ), Empty ) サンプル カレント フォルダーが、C:\A\B\C で、下記のフォルダーまたはファイルがあるとき、 C:\A\A2 C:\A\B\B2 C:\A\B\C\C2 C:\A\B\C 引数と返り値の関係は、以下のようになります。 %~1 %return_value% B2 C:\A\B\B2 A2 C:\A\A2 C2 C:\A\B\C\C2 B\B2 C:\A\B\B2 NotFound Empty テスト → T_Path.vbs T_SearchParent 関連 → GetParentFullPath → GetFullPath を使ってピリオドを3つ並べる記法を展開する → Dic_searchParent *********************************************************************** <<< AddLastOfFileName >>> *********************************************************************** AddLastOfFileName (src) Function AddLastOfFileName( BasePath as string, AddName as string ) as string ファイルパスの最後(拡張子より前)に、文字列を追加します。 または拡張子を変更します。 【引数】 BasePath 追加前のファイルパス AddName 追加する文字列 返り値 追加後のファイルパス AddName に拡張子があったら、返り値の拡張子は、AddName の拡張子に変わります。 サンプル: AddLastOfFileName( "file.txt", "123" ) = "file123.txt" AddLastOfFileName( "file.txt", "123.html" ) = "file123.html" AddLastOfFileName( "file.txt", ".html" ) = "file.html" AddLastOfFileName( "file.txt", "." ) = "file" 拡張子を無くす AddLastOfFileName( path1, "."+g_fs.GetExtensionName( path2 ) ) 拡張子を合わせる キーワード: 拡張子の変更 テスト → T_Path.vbs # [T_AddLastOfFileName] 関連 → CutLastOfFileName → StrT_addLastOfFileName (clib) → GetPathWithSeparator Path の最後を区切り記号にします *********************************************************************** <<< CutLastOfFileName >>> *********************************************************************** CutLastOfFileName (src) Sub CutLastOfFileName( in_out_Path as string, LastStr as string, Opt as integer ) ファイル名(拡張子を除く)の最後に、指定した文字列があれば削除します。 【引数】 in_out_Path (入出力)パスやファイル名を含む文字列 out_Obj (出力) 削除する内容の文字列 Opt Empty または c.CaseSensitive サンプル Dim s s = "File_Add.txt" CutLastOfFileName s, "_Add", Emtpy '// s = "File.txt" File_Add.txt _Add File.txt 呼び出し前の in_out_Path LastStr 呼び出し後の in_out_Path "File_Add.txt" "_Add" "File.txt" "File_Add.txt" "_Insert" "File_Add.txt" 補足 拡張子も含めて削除するときは、 CutLastOf を使ってください。 テスト → T_Str.vbs # [T_StrComp] 関連 → CutLastOf → StrCompLastOfFileName → CutFragmentInURL *********************************************************************** <<< StrCompLastOfFileName >>> *********************************************************************** StrCompLastOfFileName (src) Function StrCompLastOfFileName( Path as string, LastStr as string, Opt as integer ) as integer ファイル名(拡張子を除く)の末尾を比較します。 【引数】 Path 比較されるファイル名またはパス LastStr Path の末尾と比較する文字列 Opt Empty または c.CaseSensitive 返り値 Path の末尾 = LastStr なら、0 → StrComp Str 引数の値 LastStr 引数の値 返り値 "ABCDE.txt" "CDE" 0 (=一致) "ABCDE.txt" "ABC" 0以外(=異なる) "ABCDE.txt" "CDE.txt" 0以外(=異なる) テスト → T_Str.vbs # [T_StrComp] 関連 → StrCompLastOf → CutLastOfFileName *********************************************************************** <<< CutFragmentInURL >>> *********************************************************************** CutFragmentInURL Function CutFragmentInURL( in_URL as string ) ファイル パスや URL に(# から始まる)フラグメントがあれば削除します。 【引数】 in_URL (入出力)パスやファイル名を含む文字列 返り値 (出力) 削除する内容の文字列 サンプル Assert CutFragmentInURL( "C:\File.txt#2" ) = "C:\File.txt" ソース → vbslib.vbs 関連 → CutLastOf → CutLastOfFileName *********************************************************************** <<< GetTagJumpParams >>> *********************************************************************** GetTagJumpParams Function GetTagJumpParams( PathAndFragment as string ) as TagJumpParams タグジャンプ形式の文字列(パス+行番号)を分解します。 サンプル: Set jumps = GetTagJumpParams( "C:\folder\file1.txt(100)" ) '// jumps.Path = "C:\folder\file1.txt" '// jumps.LineNum = 100 '// IsEmpty( jumps.Keyword ) Set jumps = GetTagJumpParams( "file1.txt#Key" ) '// jumps.Path = "file1.txt" '// jumps.Keyword = "Key" '// IsEmpty( jumps.LineNum ) Set jumps = GetTagJumpParams( "file${>#}1.txt" ) '// jumps.Path = "file#1.txt" '// IsEmpty( jumps.LineNum ) '// IsEmpty( jumps.Keyword ) ${>#} は、# 文字になり、 # で Keyword の区切り にはならない Set jumps = GetTagJumpParams( "file1.txt#${\n}" ) '// jumps.Path = "file1.txt" '// IsEmpty( jumps.LineNum ) '// jumps.Keyword = "${\n}" ${>#} 以外の ${ } は そのまま Set jumps = GetTagJumpParams( "file1.txt" ) '// jumps.Path = "file1.txt" '// IsEmpty( jumps.LineNum ) '// IsEmpty( jumps.Keyword ) GetTagJumpParams( "C:\folder\file1.txt(100)" ).Path 参考 → GetEditorCmdLine タグジャンプ形式の文字列の詳細 TagJumpParams クラス Class TagJumpParams Public Path '// パス or ""、フル・パスとは限りません Public LineNum '// as integer or Empty Public Keyword '// as string or Empty End Class ソース → vbslib.vbs テスト → T_EditorDiff_Manually.vbs T_EditorManually → T_Path.vbs T_GetTagJumpParams 関連 → GetEditorCmdLine → GetHRefBase *********************************************************************** <<< GetTagJumpPath >>> *********************************************************************** GetTagJumpPath (src) Function GetTagJumpPath( PathAndLine as string ) as string タグジャンプ形式の文字列(パス+行番号)から、パスを取り出す。 廃止予定です。 GetTagJumpParams を使ってください。 サンプル: path = GetTagJumpPath( "C:\folder\file1.txt(100)" ) path には、"C:\folder\file1.txt" が入ります。 テスト → T_Path.vbs # GetTagJumpPath 関連 → GetTagJumpParams *********************************************************************** <<< GetTagJumpLine >>> *********************************************************************** GetTagJumpLine (src) Function GetTagJumpLine( PathAndLine as string ) as integer タグジャンプ形式の文字列(パス+行番号)から、行番号を取り出す。 廃止予定です。 GetTagJumpParams を使ってください。 PathAndLine に行番号が無いときは、0 が返ります。 サンプル: line = GetTagJumpPath( "C:\folder\file1.txt(100)" ) line には、100 が入ります。 テスト → T_Path.vbs # GetTagJumpLine 関連 → GetTagJumpParams *********************************************************************** <<< IsMovablePathToPath >>> *********************************************************************** IsMovablePathToPath (src) Function IsMovablePathToPath( SrcPath as string, DstPath as string, IsDstFolder as boolean ) as boolean ファイルやフォルダーのパス SrcPath と DstPath の間で、移動ができるかどうかを返します。 【引数】 SrcPath 移動元のファイルやフォルダーのパス DstPath 移動先のファイルやフォルダーのパス IsDstFolder DstPath がフォルダーかどうか 返り値 移動ができるかどうか ドライブが異なっていたり、ネットワーク ドライブとローカル ドライブの違いがあると、移動できません。 テスト → T_Path.vbs # [T_IsMovablePathToPath] *********************************************************************** <<< FilePathClass >>> *********************************************************************** FilePathClass ファイルのパスか、ファイルの内容に相当する文字列の抽象。 一部の vbslib の関数の引数にファイル名の代わりに指定することができるファイル・パス・オブジェクトです。 文字列や、スクリプトの中のコメントなどを、ファイルとして扱います。 次の関数で FilePathClass のオブジェクトを生成することができます。 new_FilePathForString 文字列をファイルとして扱います new_FilePathForFileInScript スクリプトの中のコメントをファイルとして扱います GetFilePathString 入力ファイル・パスに相当する文字列を返します ReadFile ファイルの内容、または、それに相当する文字列を返します 次のプロパティがあります。 FilePathClass のオブジェクトを ReadFile 関数に渡し、その返り値を使ってファイルの内容を処理するコード は共通にできるでしょう。 .Text テキスト・ファイルの内容 → ReadFile .FilePath ファイル・パス 関連 → GetFilePathString 次の関数のファイル名の代わりに指定することができます。 ReadFile LoadXML AssertExist IsSynchronizedFilesX サンプル Set root = LoadXML( "sample.xml" ), Empty ) Set root = LoadXML( new_FilePathForString( "" ), Empty ) Set root = LoadXML( new_FilePathForFileInScript( Empty ), Empty ) ソース → vbslib.vbs テスト → T_XML.vbs T_LoadXML_PathObject *********************************************************************** <<< new_FilePathForString >>> *********************************************************************** new_FilePathForString Function new_FilePathForString( Text as string ) as FilePathClass 文字列をファイルとして扱うように、ファイル名の代わりに指定するオブジェクトを返します。 【引数】 Text ファイルの内容 返り値 ファイル名の代わりに指定するオブジェクト → FilePathClass サンプル Set root = LoadXML( new_FilePathForString( "" ), Empty ) ソース → vbslib.vbs テスト → T_XML.vbs T_LoadXML_PathObject *********************************************************************** <<< new_FilePathForFileInScript >>> *********************************************************************** new_FilePathForFileInScript Function new_FilePathForFileInScript( Parameter as Empty ) as FilePathClass スクリプトの中のコメントをファイルとして扱うように、ファイル名の代わりに指定するオブジェクトを返します。 【引数】 Parameter VBScript ファイルのパス、# 可能、Empty = WScript.ScriptFullName 返り値 ファイル名の代わりに指定するオブジェクト → FilePathClass メイン・スクリプト・ファイル(WScript.ScriptFullName) に書かれた [FileInScript.*] がある行の次の行から、 [/FileInScript.*] がある行の前の行までを、ファイルの内容として扱います。 * は任意の文字列です。 参考 → スクリプト・データ・ファイル (vbslib) サンプル スクリプト・ファイルの中にある XML データを CommandA に渡します。 ファイルの内容(XML データ)の部分の行頭には、' が必要です。 '------------------------------------------------------------[FileInScript.xml] ' ' ' '-----------------------------------------------------------[/FileInScript.xml] Sub Main( Opt, AppKey ) CommandA_App AppKey, new_FilePathForFileInScript( Empty ) End Sub '--- start of vbslib include ------------------------------ : (vbslib をインクルードして main を呼び出すコード) vbslib include 上記スクリプトから呼び出す CommandA_App 関数の例: Sub CommandA_App( AppKey, Path ) Set root = LoadXML( Path, Empty ) out_path = root.selectSingleNode( "./Tag" ).getAttribute( "out_path" ) Set w_=AppKey.NewWritable( out_path ).Enable() End Sub Path に、URL のように # を付けると、スクリプト・ファイルの中の行末にあるタグを検索して、 その中のデータをファイルとして扱います。 path_object = new_FilePathForFileInScript( "#FileInScript.xml" ) ソース → vbslib.vbs テスト → T_FileInScript.vbs T_new_FilePathForFileInScript 関連 → ReadVBS_Comment → LoadXML *********************************************************************** <<< GetFilePathString >>> *********************************************************************** GetFilePathString Function GetFilePathString( Path as string or FilePathClass ) as string 入力ファイル・パスに相当する文字列を返します。 【引数】 Path ファイル・パス・オブジェクト、または、入力ファイル・パス 返り値 入力ファイル・パスに相当する文字列 Path 引数が FilePathClass 型 なら、WScript.ScriptFullName を返します。 Path 引数が 文字列なら、その文字列を返します。 返り値は、データが存在するファイル・パスを表示するため、データ・ファイルがあるフォルダーの パスを取得するために使うことができます。 返り値を、 ReadFile など、ファイルの内容にアクセスする関数に渡すと、期待と異なるデータを入力 してしまうことがあります。 たとえば、 new_FilePathForFileInScript の返り値を、GetFilePath の 引数に指定したときは、スクリプトの中のコメントではなく、スクリプト・ファイル全体を入力します。 ソース → vbslib.vbs *********************************************************************** <<< その他 >>> *********************************************************************** その他 → ReplaceFileNameWildcard ワイルドカードを使って、ファイルパスを変更します。 旧仕様 IsAbsPath → IsFullPath GetAbsPath → GetFullPath GetParentAbsPath → GetParentFullPath *********************************************************************** <<< ファイル一覧、ArrayFromWildcard >>> *********************************************************************** ファイル一覧、ArrayFromWildcard Function ArrayFromWildcard( WildcardPath as string ) as PathDictionaryClass of Nothing ワイルドカードを展開します。 サブ フォルダーも検索します。 【引数】 WildcardPath ワイルドカードを含むパス。フォルダー指定も可。配列可 (*1) 返り値 PathDictionaryClass of Nothing ファイル名やフォルダー名でソートされます。 → PathNameCompare ArrayFromWildcard2 と違い、BasePath プロパティは、カレント フォルダーになります。 サンプル For Each step_path In ArrayFromWildcard( "data\*" ).FilePaths echo step_path Next (*1) WildcardPath 引数 (vbslib のワイルドカード) 可能: "*", "*.txt", "file*", "folder\*.txt", Array( "Fo\*.txt", "Fo\*.log" ), "folder", "Debug\", "Fo\*.txt | Fo\*.log", "Fo\*.txt, Fo\*.log", "NoWildcard.txt", "folder\*", "fo\*\file.txt", "*\file.txt", ".\file.txt" 不可能: "folder*\file.txt" サブ フォルダー記号 が使えます。 例: "folder\*\back_up.txt", "folder\.\*.txt" ファイルに対する処理の場合(ArrayFromWildcard の返り値の FilePaths プロパティ などが参照される場合)、フォルダーのパスを指定すると、サブ・フォルダーにある ファイルも検索します。 サブ フォルダー記号が指定されていない( .\ も *\ もない)ときは、 ワイルドカードが、ファイル名やフォルダー名に相当する部分(もっとも右の \ の右側)に あれば、サブ・フォルダーも検索します。 ただし、WildcardPath 引数に指定した サブ フォルダー記号 が優先されます。 指定したパスのファイルやフォルダーがないときはエラーにします(サブ フォルダー 記号 * や、ワイルドカードが無いときのみ)。 PathDictionaryClass のオブジェクトを指定したら、そのオブジェクトを返します。 サンプル ワイルドカードを1つだけ展開します。 path = GetFirst( ArrayFromWildcard( "Sub\File*.txt" ).FilePaths ) ソース → vbslib.vbs テスト → T_Wildcard.vbs T_ArrayFromWildcard1 性能 → ファイルを一覧するときの速度 関連 → ArrayFromWildcard2 BasePath プロパティが指定フォルダーになる ArrayFromWildcard → Expand_glob_Pattern → ファイル一覧 (VBScript) → EnumFolderObject 高速なフォルダ一覧 → CallForEach_copy ファイル・パスの配列を使ってコピーする → dir, tree (バッチ) → ファイル一覧 *********************************************************************** <<< ファイルを一覧するときの速度 >>> *********************************************************************** ファイルを一覧するときの速度 最も速いのは、 EnumFolderObject を使う方法です。 最も扱いやすいのは、 ArrayFromWildcard2 を使う方法です。 中間的なのは、 ExpandWildcard を使う方法です。 テスト → T_Wildcard.vbs # T_Wildcard_Speed 参考 → ファイルを一覧するときの速度 - VBScript *********************************************************************** <<< ExpandWildcard >>> *********************************************************************** ExpandWildcard Sub ExpandWildcard( WildcardPath as string, Flags as integer, out_Folder as string, out_StepPaths as array of string ) ワイルドカードを展開します。 サブ・フォルダーも検索します。 【引数】 WildcardPath ワイルドカードを含むパス。フォルダ指定も可。配列可 (*1) Flags フラグの論理和 (*2) out_Folder (出力) wildcard が含まれるフォルダのフル・パス out_StepPaths (出力) ワイルドカードにマッチした相対パスの配列 ソース → vbslib.vbs サンプル Set c = g_VBS_Lib ExpandWildcard "data\*", c.File or c.SubFolder, folder, step_paths For Each step_path In step_paths If InStr( step_path, "\_setup_" ) = 0 Then '// 除外する場合 echo GetFullPath( step_path, folder ) '// g_fs.BuildPath は使わないこと End If Next wildcard c.SubFolder f.txt f.bin sub\f.txt sub\abc.txt f.txt False ○ × × × f.txt True ○ × ○ × *.txt True ○ × ○ ○ sub\* True × × ○ ○ sub True × × × × (*1) WildcardPath 引数 → (*1) ArrayFromWildcard の WildcardPath 引数 (*2) Flags 引数 旧 F_File, F_Folder, F_SubFolder 下記の定数の or。 下記の c は、g_VBS_Lib の返り値。 c.File ファイルを検索する c.Folder フォルダーを検索する c.SubFolder サブ・フォルダーも検索する。 ただし、WildcardPath 引数に指定した サブ フォルダー記号 が優先されます。 サブ・フォルダーも検索するかどうかは、ワールドカードが 指定されたかどうかなどによって決めます。 c.SubFolderIfWildcard 詳細は、 → (*1) ArrayFromWildcard の WildcardPath 引数 c.NoError 指定したパスに見つからないときにもエラーにしない c.FullPath out_Folder を out_StepPaths に含め、out_Folder = Empty にする c.ArrayOfArray out_StepPaths の配列要素数を、WildcardPath に指定した配列 の要素数と同じにして、配列要素は、それぞれのワイルドカード にマッチしたパスの配列にする c.EmptyFolder 空のフォルダーを検索する。 out_StepPaths 引数に出力されるパスの末尾には \ が付きます。 ExpandWildcard_Sort 変数 下記のように設定してから、ExpandWildcard を呼び出すと、ファイル名やフォルダー名で ソートされます。 少し遅くなりますが、列挙されるファイルの順番がどのような環境でも 同じになります。 内部でそれぞれのフォルダーを展開するごとに NumStringNameCompare で比較したソートを行います。 このとき、フォルダーの区切り記号は含まれません。 g_Vers("ExpandWildcard_Sort") = True sort_setting_back_up = g_Vers("ExpandWildcard_Sort") g_Vers("ExpandWildcard_Sort") = True : g_Vers("ExpandWildcard_Sort") = sort_setting_back_up ソース → vbslib.vbs テスト → T_Wildcard.vbs # Main 性能 → ファイルを一覧するときの速度 関連 → ファイル一覧 (VBScript) → ファイル一覧 → EnumFolderObject 高速なフォルダ一覧 → CallForEach_copy ファイル・パスの配列を使ってコピーする → IsMatchedWithWildcard ワイルドカードにマッチするかどうか *********************************************************************** <<< ExpandWildcard の内部データ構造 >>> *********************************************************************** ExpandWildcard の内部データ構造 dictionary < (folder_path), ArrayClass > reg_exp_dic ExpandWildcardWorkClass work ArrayClass .items re_type (*1) .re re2_type (*1) .re2 boolean .IsSubFolder boolean .is_root_folder string .folder_path integer .first_out_count // ExpandWildcard_sub 開始時の UBound( out_StepPaths ) integer .out_fast_ubound // 実質的な UBound( out_StepPaths ) ArrayClass .sort_box array < File or Folder or (abs_path) > out_StepPaths (*1) re_type と re2_type は、以下の組み合わせのいずれかです。 WildcardPath 引数 re_type re2_type "*" Empty Empty ワイルドカードがない NameOnlyClass Empty "*" が1個のとき StrMatchKey Empty * が2つのときか、? があるとき RegExp RegExp *********************************************************************** <<< Expand_glob_Pattern >>> *********************************************************************** Expand_glob_Pattern Function Expand_glob_Pattern( in_Pattern as string ) as array of string globパターン を展開します。 【引数】 in_Pattern globパターンの文字列 返り値 globパターンを展開したパスの配列 ワイルドカードは、カレント フォルダーにあるファイルやフォルダーの名前に展開されます。 サブフォルダーは展開されません。 サンプル in_Pattern 引数 展開結果の例 "*.txt" "1.txt", "2.txt", "3.txt", "example.txt" "s/*.txt" "s\example.txt" "s/v/*.txt" "s/v\example.txt" (ワイルドカードの直前だけ\) "?.txt" "1.txt", "2.txt", "3.txt" "[12].txt" "1.txt", "2.txt" "[012].txt" "1.txt", "2.txt" (0.txt がない場合) "[1-3].txt" "1.txt", "2.txt", "3.txt" "[!1].txt" "2.txt", "3.txt" (1.txt 以外の ?.txt) "[!12].txt" "3.txt" (1.txt, 2.txt 以外の ?.txt) ソース → ToolsLib.vbs テスト → T_Wildcard.vbs T_glob_1 関連 → ArrayFromWildcard *********************************************************************** <<< PathDictionaryClass >>> *********************************************************************** PathDictionaryClass PathDictionaryClass は、辞書のアイテムを設定するときのキーにフォルダーのパスを指定したら、 キーにフォルダーの中のファイルのパスも指定しても、同じアイテムを取得できる辞書です。 Set paths = new PathDictionaryClass paths.BasePath = "C:\BaseFolder" Set paths( "Folder" ) = a_object Assert paths( "Folder\File.txt" ) is a_object "Folder" "Folder\File.txt" 存在するフォルダーやファイルのパスをキーに指定してください。 キーには、 サブ フォルダー記号 が使えます。 例: "folder\*\back_up.txt", "folder\.\*.txt" アイテムには、任意のオブジェクトを指定できます (ただし、オブジェクト型のみ)。 new_PathDictionaryClass_fromXML を使えば、XML ファイルの中からパスの指定を取得できます。 Variable name value File path Folder path Except path Except path Except タグは、AddRemove メソッドに相当します。 参考 → new_PathDictionaryClass_fromXML サブ フォルダーのキーも設定されているときに、サブ フォルダーの中のファイルやフォルダーのパス を指定したときは、サブ フォルダーに設定されたアイテムが優先して取得されます。 Set paths = new PathDictionaryClass Set paths( "Folder" ) = a_object Set paths( "Folder\Sub" ) = b_object Assert paths( "Folder\File.txt" ) is a_object Assert paths( "Folder\Sub\File.txt" ) is b_object ファイルのパス、フォルダーのパス、ワイルドカードの間の優先順位を下記に示します。 上にあるほど優先度が高いです。 たとえば、あるファイルが、キーに指定したワイルドカードにマッチ しつつ、別のキーに指定したフォルダーの中にあるとき、キーにそのファイルのパスを指定すると、 優先順位の高いワイルドカードをキーに指定して代入したアイテムが返ります。 ・ファイルのパス(長い) ・ファイルのパス(短い) ・ワイルドカードがあるパス(\ 記号を含み、長い) ・ワイルドカードがあるパス(\ 記号を含み、短い) ・ワイルドカードがあるパス(\ 記号を含まず、長い) ・ワイルドカードがあるパス(\ 記号を含まず、短い) ・フォルダーのパス(長い) ・フォルダーのパス(短い) ファイル名のワイルドカードがあるパスより、フォルダーのパスを優先したいときは、Folder\* のように指定してください。 FilePaths プロパティは、フォルダーの中にある複数のファイルのパスの配列です。 FilePaths プロパティなどに含まれるか含まれないかが期待と異なるときは、PathDictionaryClass の オブジェクトを生成した直後に、IsDebugLog プロパティを True にして実行して、キーとファイル パスの関連を一覧表示してください。 スクリプト Set paths = new PathDictionaryClass paths.IsDebugLog = True paths.FilePaths IsDebugLog 一覧表示 *\Debug\ => Debug\a.obj *\Debug\ => Debug\b.obj . => a.c . => b.c ただし、 AddRemove メソッド が呼び出してあったら、そのファイルやフォルダーは FilePaths の対象外に なります。 Set paths = new PathDictionaryClass paths.BasePath = "C:\Folder" Set paths( "Folder" ) = a_object paths.AddRemove "*.bak" Assert IsSameArray( paths.FilePaths, Array( "Files\1\A.txt", "Files\1\B.txt" ) ) FilePaths FilePaths プロパティは、 PathNameCompare でソートされた配列を取得します。 ファイルを一覧するプロパティにアクセスすると、フォルダーの中を探索するため時間がかかります。 PathDictionaryClass のオブジェクトの内容を変更しなければ、キャッシュを使って高速に探索します。 Dic_addFilePaths_fromPathDirectory で、特定のオブジェクトをアイテムに持つパスを列挙できます。 ArrayFromWildcard でも、PathDictionaryClass のオブジェクトが得られます。 ArrayFromWildcard には、パスの文字列だけでなく PathDictionaryClass のオブジェクトでも、どちらでも指定できます。 GetBasePath に対しても、どちらでも指定できます。 Set paths = ArrayFromWildcard( "Folder" ) Assert paths( "Folder\File.txt" ) Is Nothing Set paths0 = new PathDictionaryClass Set paths( "Folder" ) = a_object Set paths = ArrayFromWildcard( paths0 ) Assert paths is paths0 Assert paths( "Folder\File.txt" ) Is a_object メンバー .BasePath キーに相対パスを指定した時の基準パス。 初期値は生成時のカレントフォルダー。 変更したら、FilePaths などの数が変わることがあります。 .Item Set ファイル、または、フォルダーのパスをキーに指定します。 サブ フォルダーも含むワイルド カードも指定可能です。 .Item Get .Item Set に指定したフォルダーの中にあるファイルやフォルダーも指定可能。 ただし、.Item Set に指定したキーが相対パスなら、絶対パスとはマッチしません。 .AddRemove で除外したパスが指定されたときは、.RemovedObject が返ります。 .Keys 辞書に登録したキー(パス)を列挙します。 .AddRemove で除外したパスも列挙します。 .KeysEx( Opt ) 辞書に登録したキー(パス)を列挙します。 ただし、Opt = Me.ExceptRemoved を 指定したときは、.AddRemove で除外したパスを列挙しないようになります。 .FilePaths 辞書のキーに登録したファイルと、辞書のキーに登録したフォルダーに含まれる ファイルの相対パスを列挙します。 キーが相対パスなら、相対パスの配列が返ります。 キーの末尾が \ のときは、フォルダーにマッチします。 .IsNotFoundError = False にすると、キーが指すパスにファイルまたはフォルダーが ないときでもエラーになりません。 → サブ フォルダー記号 関連 → Dic_addFilePaths_fromPathDirectory .FullPaths フル パスの配列が返る FilePaths。 .LeafPaths .FullPaths に空のフォルダーも追加したフル パスの配列。 空のフォルダーを指すパスの末尾には \ が付きます。 関連 → LeafPathDictionary .FolderPaths ファイルがあるフォルダーの相対パスを列挙します。 親フォルダーの親フォルダーも列挙します。 .DeleteFolderPaths ファイルを削除したときに削除の候補となるフォルダーの相対パスを 列挙します。 削除の候補となるフォルダーは、AddRemove に指定した パスを含まない親フォルダーです。 フォルダーを削除するときは、候補 となるフォルダーのサブフォルダーも削除してください。 .AddRemove( Path ) 対象外にするフォルダーのパスや、拡張子を設定します .RemovedObject .AddRemove で除外したパスをキーに指定したときの Item .Exists( Path ) 辞書に登録したキー(パス)であるかどうかを返します。 .AddRemove で除外したパスも列挙します。 .FileExists( Path ) キーに指定したファイルパスが辞書にあるなら True。 キーに指定したフォルダーの中(のサブフォルダー)にあるファイルの パスが指定されたときも、True。 引数に絶対パスを指定可能。 .FolderExists( Path ) FileExists に列挙されるファイルを含むフォルダーがあるかどうか。 Path がファイルにマッチするときは、False。 .DeleteFolderExists( Path ) 削除の候補となるフォルダーかどうか。 削除の候補となるサブフォルダーにマッチするときは、True .SearchParent 指定したパスの親フォルダーのパスを検索します。 → Dic_searchParent .IsDebugLog キーとファイル パスの関連を一覧表示するかどうか .IsNotFoundError .FilePaths で .Key に設定したパスが見つからないエラーを発生するかどうか .IsScaned .FilePaths, .FullPaths, .FolderPaths に必要なデータを集めるために、フォルダー を探索したかどうか。 辞書を変更すると False になり、再度探索します。 .Add( Key, Item ), .Count, .Items, .CompareMode, .Remove(), .RemoveAll() Scripting.Dictionary と同じ 標準の辞書との互換性 .Count, .Keys, .Items などのメソッドやプロパティは、Scripting.Dictionary と互換性があります。 Dic_add などの、辞書を使った関数を使うこともできます。 サンプル Set paths = new PathDictionaryClass Set paths( "Folder\Sub" ) = a_object paths.AddRemove "*.bak" Assert IsSameArray( paths.FilePaths, Array( "Files\1\A.txt", "Files\1\B.txt" ) ) For Each key In paths.FilePaths Assert paths( key ) Is a_object Next ソース → vbslib.vbs テスト → T_Wildcard.vbs T_PathDictionary_1, T_PathDictionary_Wildcard, T_PathDictionary_OverSub 関連 → Dictionary クラス (ハッシュ、辞書、Scripting.Dictionary) → new_PathDictionaryClass_fromXML XML からファイルの集合を指定する → ArrayFromWildcard PathDictionaryClass を取得する別の方法 → EnumFolderObjectDic → Folder::SubFolders フォルダーを一覧する → EnumFileObjectDic → Folder::Files ファイルを一覧する → FilePathClass ファイルのパスか、ファイルの内容に相当する文字列の抽象 *********************************************************************** <<< new_PathDictionaryClass_fromXML >>> *********************************************************************** new_PathDictionaryClass_fromXML Function new_PathDictionaryClass_fromXML( path_XML_Elements as IXMLDOMNodeList, AttributeName as string, BasePath as string ) as PathDictionaryClass of IXMLDOMElement FF-path 属性対応の XML から PathDictionaryClass のオブジェクトを生成します。 【引数】 path_XML_Elements パスが書かれた XML 要素(タグ)のオブジェクトの集合 AttributeName 通常 "path"。 パスが書かれた XML 属性の名前 BasePath XML に書かれた相対パスの基準パス 返り値 PathDictionaryClass のオブジェクト → PathDictionaryClass path_XML_Elements 引数には、XML の path 属性がある XML 要素(タグ)の集合を指定します。 返り値の辞書のアイテムは、XML 要素(タグ)オブジェクト( IXMLDOMElement 型 )になります。 サンプル 下記 Sample.xml の path 属性と Except タグをリードします。 path_of_XML = "Files\Files1.xml" base_path = GetParentFullPath( path_of_XML ) Set root = LoadXML( path_of_XML, Empty ) Set dic = new_PathDictionaryClass_fromXML( root.selectNodes( "Folder | File" ), "path", _ base_path ) Assert IsSameArray( dic.FilePaths, Array( _ "Sample.txt", "SubFolder\A.c", "SubFolder\Sub\A.c" ) ) For Each key In dic.FilePaths Assert dic( key ).getAttribute( "attr" ) = "ABC" Next new_PathDictionaryClass_fromXML selectNodes FF-path 属性対応の XML、path 属性と、Except タグ FF-path 属性 (File or Folder as files Path attribute) は、ファイルのパスを指定する XML の path 属性です。 vbslib のワイルドカード が使えます。 C:\FolderA\Sample.xml Variable name value File path File, Folder, Except タグに 書かれた相対パスの基準は すべて同じです。 Folder path Except path Except path 緑色の文字の名前は、FF-path 属性、または Variable タグによって定義された名前です。 赤色の文字の名前は、XML ファイルの種類によって異なります。 (new_PathDictionaryClass_fromXML 関数に指定します。) 上記は、Sample.txt ファイルと、SubFolder フォルダーとそのサブフォルダーの中にあるすべての ファイルのうち、拡張子が obj と bak のファイルと、SubFolder\Debug フォルダーの中のファイルを 除いたファイルを、指定したことになります。 上記の XML は、下記のコードでできる PathDictionary ができます。 Set paths = new PathDictionaryClass paths.BasePath = "C:\FolderA" Set paths( "Sample.txt" ) = file_tag Set paths( "SubFolder" ) = folder_tag paths.AddRemove "*.obj" paths.AddRemove "*.bak" paths.AddRemove "SubFolder\Debug" フォルダーの中の一部のファイルやフォルダーに対して、特別な設定を XML に記述することが できます。 記述する順番には依存しません。 子ノードの記述が優先されます。 attr="target" の設定は、Folder フォルダーとそのサブ フォルダーが対象ですが、 Folder\back_up フォルダーは対象外です。 ファイルのパス、フォルダーのパス、ワイルドカードの間の優先順位を下記に示します。 上にあるほど優先度が高いです。 たとえば、あるファイルが、指定したワイルドカードにマッチ しつつ、指定したフォルダーの中にあるときは、優先順位の高いワイルドカードを指定した XML の設定がそのファイルに対して使われます。 ・ファイルのパス(長い) ・ファイルのパス(短い) ・ワイルドカードがあるパス(\ 記号を含み、長い) ・ワイルドカードがあるパス(\ 記号を含み、短い) ・ワイルドカードがあるパス(\ 記号を含まず、長い) ・ワイルドカードがあるパス(\ 記号を含まず、短い) ・フォルダーのパス(長い) ・フォルダーのパス(短い) ファイル名のワイルドカードがあるパスより、フォルダーのパスを優先したいときは、Folder\* のように指定してください。 フォルダーの中にあるファイルが、指定されたか指定されなかったかが期待と異なるときは、 XML に下記の Debug タグを追加して、キーとファイル パスの関連を一覧表示してください。 XML path_dictionary_scan_log 一覧表示 *\Debug\ => Debug\a.obj *\Debug\ => Debug\b.obj . => a.c . => b.c Except タグを使えば、サブフォルダーの中にあるファイルのうち、指定したファイルやフォルダーを 対象外にすることができます。 Except タグは、FF-path 属性に対応したタグの子ノードとして配置 してください。 ワイルドカードを使って拡張子を指定することができます。 複数指定するときは、 コンマで区切ってください。 相対パスの基準は、XML ファイルがあるフォルダーです。 Except タグで対象外にしたフォルダーの中のサブフォルダーやファイルを対象にするときは、 Except タグの親ノードの兄弟ノードに指定してください。 A 対象 A\1 対象 A\B 対象外 A\B\1 対象外 A\B\C 対象 A\B\C\1 対象 path 属性を持つタグの名前は、"Folder" や "File" 以外の可能性があります。 ファイルを指定する属性が、path 属性でない可能性もあります。 それぞれの名前は、設定する XML ファイルの仕様を参照してください。 path 属性を持つタグの名前に関係なく、空のフォルダーを指定するときは、パスの末尾に \ を付けてください。 \ 空のフォルダー C FF-path 属性が使える XML ファイルには、Variable タグを指定することができます。 そして、 path 属性に、Variable タグの参照を指定することができます。 (例:下記の ${ExceptExts}) Except タグの path 属性にも、Variable タグの参照を指定することができます。 → Variable タグ XML ファイルの仕様によっては、path 属性を持つタグに path 属性以外の属性を指定することが できます。 (例:下記の Folder タグの attr 属性) ソース → vbslib.vbs テスト → T_Wildcard.vbs T_PathDictionary_XML 関連 → GetPathDictionariesFromXML → SyncFilesX *********************************************************************** <<< GetPathDictionariesFromXML >>> *********************************************************************** GetPathDictionariesFromXML Function GetPathDictionariesFromXML( path_XML_Elements as IXMLDOMNodeList, AttributeName as string, BasePath as string, MapAttributeName as string ) as dictionary of PathDictionaryClass of IXMLDOMElement 複数の map からなる FF-path 属性対応の XML から PathDictionaryClass のオブジェクトを生成します。 【引数】 path_XML_Elements パスが書かれた XML 要素(タグ)のオブジェクトの集合 AttributeName 通常 "path"。 パスが書かれた XML 属性の名前 MapAttributeName 通常 "map"。 map 属性が書かれた XML 属性の名前 BasePath XML に書かれた相対パスの基準パス 返り値 PathDictionaryClass のオブジェクトの辞書。キーは、map 属性の値 複数の map に対応した new_PathDictionaryClass_fromXML です。 map の設定があると、map ごとに XML ファイルを分けたようになります。 map="B" path attr map = "" "Folder" "target" "Folder\A.txt" "target" "Folder\back_up\A.txt" "not_target" map = "B" path attr "Folder" "targetB" "Folder\A.txt" "targetB" "Folder\back_up\A.txt" "targetB" map は、XML の map 属性に設定し、返り値(辞書型)のキーに入ります。 map 属性がないXML タグの設定値は、返り値(辞書型)のキーが "" のアイテムに入ります。 単一の map の場合、フォルダー(A) にだけ設定があるとき、そのサブ フォルダーまたはファイル(B) の設定は、(A) から継承されますが(同じ設定になりますが)、(A) と (B) で異なる map を指定した場合、 (B) の設定は、(A) から継承されません。 XML の map 属性は、パスを指定する要素の親要素や、さらにその親要素…、に設定することもできます。 map 属性を指定しなかったときは、GetPathDictionariesFromXML の返り値の辞書のキーは "" になります。 ソース → vbslib.vbs テスト → T_Wildcard.vbs T_PathDictionaries_XML *********************************************************************** <<< new_PathDictionaryClass >>> *********************************************************************** new_PathDictionaryClass Function new_PathDictionaryClass( in_Path as variant ) as PathDictionaryClass 典型的な PathDictionaryClass のオブジェクトを生成します。 【引数】 in_Path ファイルやフォルダーのパス 返り値 PathDictionaryClass のオブジェクト → PathDictionaryClass in_Path 引数には、文字列、文字列の配列、PathDictionaryClass のいずれかを指定できます。 サンプル Set paths = new_PathDictionaryClass( "Folder" ) Set paths = new_PathDictionaryClass( Array( "FolderA", "FolderB" ) ) Set paths = new_PathDictionaryClass( "Folder" ) Set paths2 = new_PathDictionaryClass( paths ) Assert paths is paths2 ソース → vbslib.vbs *********************************************************************** <<< new_PathDictionaryClass_withRemove >>> *********************************************************************** new_PathDictionaryClass_withRemove Function new_PathDictionaryClass_withRemove( in_BasePath as string, in_RemovePathArray as array of string, in_DictionaryItem as Object ) as PathDictionaryClass 除外するファイルやフォルダーがある、1つのフォルダーの PathDictionaryClass のオブジェクトを生成します。 【引数】 in_BasePath ベースとなる1つのフォルダー in_RemovePathArray 除外するファイルやフォルダーの相対パスの配列、または Empty in_DictionaryItem 生成する辞書のすべての Item に設定するオブジェクト 返り値 PathDictionaryClass のオブジェクト → PathDictionaryClass in_RemovePathArray 引数に指定する相対パスの基準フォルダーは、in_BasePath です。 サンプル Set dic = new_PathDictionaryClass_withRemove( "Folder", Array( "*.bak" ), Nothing ) Assert dic.BasePath = "C:\Folder" Assert IsSameArray( dic.Keys, Array( "." ) ) ソース → vbslib.vbs *********************************************************************** <<< GetBasePath >>> *********************************************************************** GetBasePath Function GetBasePath( in_StringOrObject as variant ) as string ベースのパスを返します。 【引数】 in_StringOrObject 文字列、または、 PathDictionaryClass 返り値 ベースのパス in_StringOrObject 引数が文字列のときは、その文字列を返します。 PathDictionaryClass 型のときは、BasePath プロパティを返します。 サンプル Assert GetBasePath( "C:\Folder" ) = "C:\Folder" GetBasePath Assert GetFullPath( GetBasePath( paths ), Empty ) = "C:\Folder\sub" GetBasePath Set paths = new PathDictionaryClass paths.BasePath = "C:\BaseFolder" Assert GetBasePath( paths ) = "C:\Folder" GetBasePath ソース → vbslib.vbs 関連 → ArrayFromWildcard *********************************************************************** <<< LeafPathDictionary >>> *********************************************************************** LeafPathDictionary LeafPathDictionary は、キーを「ファイル、または、空のフォルダーのパス」とした辞書です。 型は、標準で用意されている辞書と同じです。 キーに設定したパスは、ファイルまたはフォルダーが存在しない可能性があります。 LeafPathDictionary のアイテム(NameOnlyClass などのオブジェクト)の Name プロパティは、 キーと同じパス、または、存在するファイルまたはフォルダーへのパスです。 キーに関連付けられたアイテムの Name プロパティ以外は、ユーザーが自由に設定できます。 Name プロパティ以外のプロパティは、LeafPathDictionary からアクセスしません。 LeafPathDictionary を参照する処理によっては、キーしか参照しません。 また、キーをコピー先、アイテムの Name プロパティをコピー元として処理することがあります。 Const NotCaseSensitive = 1 Set dic = CreateObject( "Scripting.Dictionary" ) dic.CompareMode = NotCaseSensitive Set dic( "To.txt" ) = new_NameOnlyClass( "From.txt", Empty ) new_NameOnlyClass アイテムにあるパスから、キーにあるパスに、ファイルをコピーすることで、多くのファイルを集める処理に 使えます。 ファイルを置き換えるパッチをあてるときにも使えます。 → PatchAndBackUpDictionaryClass 2つのフォルダーを比較するときに、比較するファイルの名前や場所が異なるときは、関連するパスを キー、ファイルの内容をアイテムにすることで、比較ができます。 マージするときは、マージした後の パスに相対パスを合わせたパスをキーにするとよいでしょう。 辞書のアイテムを変更することで、コピー元を変更することができます。 Set dic( "To.txt" ) = new_NameOnlyClass( "From2.txt", Empty ) 辞書のキーを変更することで、コピー先を変更することができます。 Set dic( "To2.txt" ) = dic( "To.txt" ) Set dic.Remove "To.txt" 関連 → ChangeKeyOfLeafPathDictionary ExpandWildcard_Sort 変数 を True に設定すると、辞書のキーをABC順にソートします。 False に設定しても、下記のコードを実行すればソートできます。 QuickSortDicByKey dic QuickSortDicByKey LeafPathDictionary のアイテムの Name プロパティが Empty のときは、削除する予定である ことを示します。 LeafPathDictionary のアイテムの Name プロパティが文字列の配列のときは、 ThreeWayMerge した内容にする予定であることを示します。 (0) = Base, (1) = Left, (2) = Right です。 関連 → EnumerateToLeafPathDictionary フォルダーから、 LeafPathDictionary を生成します → PathDictionaryClass .LeafPaths と Dic_addNewObject → ExpandWildcard の c.EmptyFolder → NewDiffFilePaths → ChangeKeyOfLeafPathDictionary キーに書かれたパスを変更します → CopyFilesToLeafPathDictionary ファイルまたはフォルダーをコピーします → PatchAndBackUpDictionaryClass パッチ テスト → T_LeafPath.vbs T_LeafPath *********************************************************************** <<< EnumerateToLeafPathDictionary >>> *********************************************************************** EnumerateToLeafPathDictionary << LeafPathDictionary Function EnumerateToLeafPathDictionary( in_FolderPath as string ) as dictionary of NameOnlyClass フォルダーから、LeafPathDictionary を生成します。 【引数】 in_FolderPath 調べるフォルダーのパス 返り値 LeafPathDictionary 返り値の要素のキーと、アイテムの .Name には、フル パスが格納されます。 そのフル パスが空のフォルダーを指していても、キーの末尾は \ ではありません。 ExpandWildcard_Sort 変数 でソートできます。 ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_LeafPath *********************************************************************** <<< EnumerateToLeafPathDictionaryByFullSetFile >>> *********************************************************************** EnumerateToLeafPathDictionaryByFullSetFile << LeafPathDictionary Function EnumerateToLeafPathDictionaryByFullSetFile( in_FolderPath as string, in_MD5ListFilePath as string, in_EmptyOption as Empty ) as dictionary of MD5ListLeafClass _FullSet.txt ファイル 、または、フォルダーから、LeafPathDictionary を生成します。 【引数】 in_FolderPath 調べるフォルダーのパス in_MD5ListFilePath 存在するファイルの MD5 リストのファイル パスなど(下記) in_EmptyOption Empty を指定してください 返り値 LeafPathDictionary of MD5ListLeafClass 参照する _FullSet.txt ファイルは、in_FolderPath 引数のフォルダーの直下にある _FullSet.txt ファイルです。 _FullSet.txt ファイルが無ければ、 EnumerateToLeafPathDictionary と同じ動きをします。 ファイルが存在するときは、_FullSet.txt ファイルの中にそのファイルのパスがあってもなくても、存在する ファイルに関する情報が返り値に含まれます。 ただし、ハッシュ値が同じときは、タイムスタンプに関して のみ _FullSet.txt ファイルに書かれたタイムスタンプが返り値に含まれ、ファイルのタイムスタンプは無視 されます。 _FullSet.txt ファイルの中にあるパスにファイルが存在しないときは、_FullSet.txt ファイルに書かれた 情報が返り値に含まれます。 返り値のキーが空のフォルダーを指していても、キーの末尾は \ ではありません。 返り値のキーとアイテムは、 ExpandWildcard_Sort 変数 でソートできます。 in_MD5ListFilePath 引数 MD5ListLeafClass ::Name が指すパスにファイルまたはフォルダーがないときに MD5ListLeafClass:: BodyFullPathを設定するために参照される MD5 リスト のパス、または、 OpenForDefragment の返り値。 Empty を指定したときは、MD5ListLeafClass::BodyFullPath が Empty になる可能性が高まります。 MD5ListLeafClass EnumerateToLeafPathDictionaryByFullSetFile 関数の返り値のアイテムの型。 string .Name ファイル、または、フォルダーの相対パス。 Empty になることはありません。 string .HashValue ファイルのハッシュ値 → MD5 ファイルが存在しないなら、 _FullSet.txt ファイルに書かれたハッシュ値が入り ます。 ファイルが存在するなら、 EnumerateToLeafPathDictionaryByFullSetFile 関数 の中で計算したハッシュ値が入ります。 このハッシュ値は、_FullSet.txt ファイルに書かれたハッシュ値と異なることがあります。 Empty になることはありません。 _FullSet.txt の中 ファイルシステム 返り値 あり なし _FullSet.txt の中のハッシュ値 なし あり ファイルのハッシュ値 あり(*1) あり ファイルのハッシュ値 (*1) _FullSet.txt に書かれたハッシュ値と、ファイルのハッシュ値が異なること があります 参考 → 空のフォルダーの MD5 string .TimeStamp ファイルのタイムスタンプ。 形式は、 W3CDTF。 空のフォルダーなら get_ToolsLibConsts()EmptyFolderTimeStamp。 ファイルが存在するなら、 EnumerateToLeafPathDictionaryByFullSetFile 関数 を呼び出したときのファイルのタイムスタンプが入ります。 ただし、ファイルの ハッシュ値が _FullSet.txt に書かれたハッシュ値と同じときは、_FullSet.txt ファイルに書かれたタイムスタンプが入ります。 このハッシュ値は、ファイルの タイムスタンプと異なることがあります。 ファイルが存在せず、_FullSet.txt ファイルの中にタイムスタンプの記録が なければ、Empty になります。 _FullSet.txt の中 ファイルシステム 返り値 あり なし _FullSet.txt の中の日時 なし あり ファイルのタイムスタンプ あり(*1) あり(同じハッシュ値) _FullSet.txt の中の日時 あり(*1) あり(違うハッシュ値) ファイルのタイムスタンプ EmptyFolderTimeStamp なし EmptyFolderTimeStamp なし 空のフォルダー EmptyFolderTimeStamp EmptyFolderTimeStamp 空のフォルダー EmptyFolderTimeStamp なし なし Empty (*1) _FullSet.txt に書かれた日時と、ファイルのタイムスタンプが異なること があります string .BodyFullPath 存在するファイルやフォルダーのパス。 存在しないときは Empty。 ただし、 _FullSet.txt ファイルがあり、in_MD5ListFilePath に同じハッシュ値があったら、 in_MD5ListFilePath に記録されたパスのフル パス。 ただし、そのパスに ファイルやフォルダーがあることがチェックされていないことがあります。 ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_LeafPathWithFullSet *********************************************************************** <<< IsSameHashValuesOfLeafPathDictionary >>> *********************************************************************** IsSameHashValuesOfLeafPathDictionary Function IsSameHashValuesOfLeafPathDictionary( _ in_1stLeafPathDictionary as dictionary, in_1stBasePath as string, _ in_2ndLeafPathDictionary as dictionary, in_2ndBasePath as string ) LeafPathDictionary が指すすべてのファイルを、もう1つの LeafPathDictionary と比較します。 【引数】 in_1stLeafPathDictionary 1つ目の LeafPathDictionary 、または、Empty in_1stBasePath 比較するベースとする1つ目のフォルダーのパス in_2ndLeafPathDictionary 2つ目の LeafPathDictionary 、または、Empty in_2ndBasePath in_1stBasePath 引数に対応する2つ目のフォルダーのパス 返り値 すべてのファイルの内容が同じかどうか ファイルが同じ内容かどうかを調べるのに、 g_FileHashCache を使っています。 in_1stLeafPathDictionary 引数、または、in_2ndLeafPathDictionary 引数に、値が Empty の変数を 指定すると、その変数に LeafPathDictionary が格納されます。 ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_LeafPath_IsSameHash *********************************************************************** <<< IsSameFileNamesOfLeafPathDictionary >>> *********************************************************************** IsSameFileNamesOfLeafPathDictionary Function IsSameFileNamesOfLeafPathDictionary( _ in_1stLeafPathDictionary as dictionary, in_1stBasePath as string, _ in_2ndLeafPathDictionary as dictionary, in_2ndBasePath as string ) LeafPathDictionary が指すすべてのファイル名を、もう1つの LeafPathDictionary と比較します。 【引数】 in_1stLeafPathDictionary 1つ目の LeafPathDictionary 、または、Empty in_1stBasePath 比較するベースとする1つ目のフォルダーのパス in_2ndLeafPathDictionary 2つ目の LeafPathDictionary 、または、Empty in_2ndBasePath in_1stBasePath 引数に対応する2つ目のフォルダーのパス 返り値 すべてのファイルの内容が同じかどうか ファイルの内容は比較しません。 in_1stLeafPathDictionary 引数、または、in_2ndLeafPathDictionary 引数に、値が Empty の変数を 指定すると、その変数に LeafPathDictionary が格納されます。 ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_LeafPath_IsSameName *********************************************************************** <<< GetNotSameFileKeysAsItemsOfLeafPathDictionary >>> *********************************************************************** GetNotSameFileKeysAsItemsOfLeafPathDictionary Function GetNotSameFileKeysAsItemsOfLeafPathDictionary( in_LeafPathDictionary as dictionary ) as array of string LeafPathDictionary のキーとアイテムでファイルの内容が異なるキーを配列にまとめて返します。 【引数】 in_LeafPathDictionary LeafPathDictionary 返り値 キーとアイテムでファイルの内容が異なる要素のキーの配列 in_LeafPathDictionary 引数のキーとアイテムには、フル パスを格納しておいてください。 ファイルが同じ内容かどうかを調べるのに、 g_FileHashCache を使っています。 ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_LeafPath_GetNotSameFiles *********************************************************************** <<< ChangeKeyOfLeafPathDictionary >>> *********************************************************************** ChangeKeyOfLeafPathDictionary << LeafPathDictionary Sub ChangeKeyOfLeafPathDictionary( in_out_LeafPathDictionary as dictionary of NameOnlyClass, in_SourcePath as string, in_DestinationPath as string ) コピー先のファイルやフォルダーを移動するように、キーに書かれたパスを変更します。 【引数】 in_out_LeafPathDictionary LeafPathDictionary in_SourcePath コピー先を変更する前のファイルやフォルダーのパス in_DestinationPath コピー先を変更した後のファイルやフォルダーのパス ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_LeafPath *********************************************************************** <<< CopyFilesToLeafPathDictionary >>> *********************************************************************** CopyFilesToLeafPathDictionary << LeafPathDictionary Sub CopyFilesToLeafPathDictionary( in_LeafPathDictionary as dictionary of NameOnlyClass or PatchAndBackUpDictionaryClass, in_IsSetItemDestination as boolean ) アイテムの Name 属性に書かれたパスから、キーに書かれたパスに、ファイルまたはフォルダーをコピーします。 【引数】 in_LeafPathDictionary LeafPathDictionary in_IsSetItemDestination 辞書のアイテムをキーと同じ値にするかどうか AttachPatchAndBackUpDictionary でアタッチしたパッチを実際のファイルに反映するときにも使います。 in_LeafPathDictionary 引数のキーとアイテムには、フル パスを格納しておいてください。 in_LeafPathDictionary 引数のアイテムの Name プロパティが Empty のときは、削除します。 LeafPathDictionary のアイテムの Name プロパティが文字列の配列のときは、 ThreeWayMerge します。 Name(0) = Base (real), Name(1) = Left (real), Name(2) = Right (real), Name(3) = ThreeWayMergeOptionClass または、Empty です。 PatchAndBackUpDictionaryClass でいえば、Name(0)〜Name(2) は、 Name(0) = back_up (real), Name(1) = target (real), Name(2) = patch (real) です。 コンフリクトが発生しても E_Conflict エラーにしないようにするには、AttachPatchAndBackUpDictionary の in_out_Options 引数に、ThreeWayMergeOptionClass::IsEnableToRaiseConflictError = False を指定 します。 ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_LeafPath → T_Diff.vbs T_ThreeWayMerge_Cached *********************************************************************** <<< RemoveKeyOfEmptyItemInLeafPathDictionary >>> *********************************************************************** RemoveKeyOfEmptyItemInLeafPathDictionary << LeafPathDictionary Sub RemoveKeyOfEmptyItemInLeafPathDictionary( in_out_LeafPathDictionary as dictionary of NameOnlyClass, in_IsDeleteFile as boolean ) アイテムの Name プロパティが Empty の辞書の要素をすべて除外します。 【引数】 in_out_LeafPathDictionary LeafPathDictionary in_IsDeleteFile 除外したキーに書かれたパスのファイルを削除するかどうか サンプル Set dic = Dict(Array( "C:\FolderA\a.txt", new_NameOnlyClass( Empty, Empty ) )) RemoveKeyOfEmptyItemInLeafPathDictionary dic, True Assert not dic.Exists( "C:\FolderA\a.txt" ) Assert not exist( "C:\FolderA\a.txt" ) ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_LeafPath_RemoveEmpty *********************************************************************** <<< NormalizeLeafPathDictionary >>> *********************************************************************** NormalizeLeafPathDictionary Sub NormalizeLeafPathDictionary( in_out_LeafPathDictionary as dictionary of NameOnlyClass ) フォルダーのパスと、その中のファイルのパスがあるとき、フォルダーのパスを除外します。 【引数】 in_out_LeafPathDictionary LeafPathDictionary LeafPathDictionary は、キーを「ファイル、または、空のフォルダーのパス」とした辞書であることが、 正規の状態です。 正規の状態にしなければ、一部の関数が正しく動作しません。 サンプル Const NotCaseSensitive = 1 Set dic = CreateObject( "Scripting.Dictionary" ) dic.CompareMode = NotCaseSensitive Set dic( "C:\Folder" ) = new_NameOnlyClass( "C:\Folder", Empty ) Set dic( "C:\Folder\File.txt" ) = new_NameOnlyClass( "C:\Folder\File.txt", Empty ) NormalizeLeafPathDictionary dic '// キーが "C:\Folder" のアイテムが除外されます。 ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_LeafPath_Normalize *********************************************************************** <<< NewDiffFilePaths >>> *********************************************************************** NewDiffFilePaths Function NewDiffFilePaths( in_PathArray as array of string, in_RemovePathArray as array of string ) as dictionary of PathDictionaryClass 複数のフォルダーを比較するための、ファイルの相対パスをキーとした辞書を生成します。 【引数】 in_PathArray フォルダーのパス(フル パス、または、相対パス)の配列 in_RemovePathArray 除外するファイル名のパターンの配列、または、Empty 返り値 辞書、キーは相対パス、アイテムは空の PathDictionaryClass in_RemovePathArray 引数は、 new_PathDictionaryClass_withRemove 関数 の in_RemovePathArray 引数と 同じ意味です。 空のフォルダーは返り値のキーに含まれません。 → LeafPathDictionary サンプル Set diff_paths = NewDiffFilePaths( Array( _ "C:\Attached", "C:\Base" ), Empty ) For Each step_path In diff_paths.Keys Set files = diff_paths( step_path ) If files( 0 ) Is Nothing Then echo "A>" Else echo "A>"+ GetFullPath( step_path, files( 0 ).BasePath ) End If If files( 1 ) Is Nothing Then echo "B>" Else echo "B>"+ GetFullPath( step_path, files( 1 ).BasePath ) End If Next 上記サンプルの出力例: A>C:\Attached\Add.txt B> A>C:\Attached\Both.txt B>C:\Base\Both.txt A> B>C:\Base\Delete.txt ソース → vbslib.vbs 関連 → PathDictionaryClass .LeafPaths と Dic_addNewObject *********************************************************************** <<< Dic_addFilePaths_fromPathDirectory >>> *********************************************************************** Dic_addFilePaths_fromPathDirectory Function Dic_addFilePaths_fromPathDirectory( in_out_Dictionary as Dictionary or Empty, in_SetIndex as integer, in_MaxIndex as integer, in_BasePath as string, in_PathDictionary as PathDictionaryClass, in_Item as Object ) ファイルの相対パスをキーとした辞書の配列に、PathDictionary型の辞書にあるアイテムを追加します。 【引数】 in_out_Dictionary 辞書、キーは相対パス、Empty 可能、アイテムは ArrayClass 配列 in_SetIndex in_Item を設定する in_out_Dictionary 引数のアイテムの配列の番号 in_MaxIndex アイテムの配列の最大番号 in_BasePath in_PathDictionary 辞書のキーを相対パスにするときの基準フォルダーのパス in_PathDictionary → PathDictionaryClass in_Item Empty、または、in_PathDictionary のアイテムと比較するキー オブジェクト 返り値 in_out_Dictionary、または、生成した辞書 複数のフォルダーを比較するときなど、同じ相対パスのファイルに対して何らかの処理をするときに使い ます。 サンプル Set dic_A = new PathDictionaryClass : Set dic_A( "C:\FolderA" ) = obj_A Set dic_B = new PathDictionaryClass : Set dic_B( "C:\FolderB" ) = obj_B Set dic_A_B = CreateObject( "Scripting.Dictionary" ) Dic_addFilePaths_fromPathDirectory dic_A_B, 0, 1, "C:\FolderA", dic_A, obj_A Dic_addFilePaths_fromPathDirectory dic_A_B, 1, 1, "C:\FolderB", dic_B, obj_B For Each step_path In dic_A_B.Keys Set files = dic_A_B( step_path ) If not files( 0 ) Is Nothing and not files( 1 ) Is Nothing Then If not IsSameBinaryFile( _ GetFullPath( step_path, obj_A.BasePath ), _ GetFullPath( step_path, obj_B.BasePath , Empty ) Then .... PathDictionaryClass Dic_addFilePaths_fromPathDirectory Dic_addFilePaths_fromPathDirectory 関数を、それぞれのフォルダーに対して呼び出し、できた in_out_Dictionary 引数の辞書を使って、それぞれのフォルダーにある、同じ相対パスのファイル に対する処理ができるようになります。 Dic_addFilePaths_fromPathDirectory 関数の処理内容は、おおよそ下記の擬似コードのようになります。 For Each file_path In in_PathDictionary.FullPaths If in_PathDictionary( file_path ) is in_Item Then file_step_path = GetStepPath( file_path, in_BasePath ) Set in_out_Dictionary( file_step_path )( in_SetIndex ) = in_Item in_PathDictionary 引数から、以下の条件に合うキー(パス)とアイテム(オブジェクト)のセットを抽出します。 ・in_PathDictionary 引数に指定した PathDictionaryClass 型の辞書のアイテムが in_Item 引数に  指定したオブジェクトになっている(in_Item が Empty ではないとき) in_PathDictionary 引数の辞書 (PathDictionaryClass 型) ファイルのパス in_Item 引数と同じアイテム in_BasePath 引数に指定したフォルダーの中のファイルに対応する、in_PathDictionary 引数の辞書の アイテムに、in_Item 引数のオブジェクト以外が入っている可能性があります。 また、in_BasePath 引数に指定したフォルダーの外のファイルでも、in_PathDictionary 引数の辞書の アイテムに、in_Item 引数のオブジェクトが抽出される可能性があります。 抽出したキーとアイテムは、in_out_Dictionary 引数に指定した辞書のアイテム(ArrayClass 型の配列)の 配列要素に格納されます。 抽出したキーは、in_BasePath 引数に指定したパスを基準とした相対パスに 変換後、抽出したアイテムを追加する先の配列を特定するための辞書のキーとして使われます。 in_SetIndex 引数に指定した値が配列番号となる配列要素に、in_PathDictionary 引数の辞書のアイテム が格納されます。 ファイルの 相対パス in_SetIndex 引数 in_out_Dictionary 引数の辞書 配列 配列要素 in_PathDictionary 引数の 辞書のアイテム in_out_Dictionary 引数に Empty を指定すると、辞書を新規作成され、その辞書が返り値になります。 in_out_Dictionary 引数に辞書を指定すると、その辞書に要素が追加され、その辞書が返り値になります。 in_out_Dictionary 引数に指定した辞書のアイテムの配列の全要素は、Nothing で初期化されます。 ソース → vbslib.vbs テスト → T_Wildcard.vbs T_Dic_addFilePaths 関連 → EnumFileObjectDic *********************************************************************** <<< Dic_addFilePaths_fromOtherPathDirectory >>> *********************************************************************** Dic_addFilePaths_fromOtherPathDirectory Function Dic_addFilePaths_fromOtherPathDirectory( in_out_Dictionary as Dictionary or Empty, in_SetIndex as integer, in_MaxIndex as integer, in_BasePath as string, in_NewItem as Object, in_OtherBasePath as string, in_OtherPathDictionary as PathDictionaryClass, in_OtherItem as Object ) ファイルの相対パスをキーとした辞書の配列に、PathDictionary型の辞書にあるアイテムを追加します。 【引数】 in_out_Dictionary 辞書、キーは相対パス、Empty 可能、アイテムは ArrayClass 配列 in_SetIndex in_Item を設定する in_out_Dictionary 引数のアイテムの配列の番号 in_MaxIndex アイテムの配列の最大番号 in_BasePath in_out_Dictionary 辞書のキーを相対パスにするときの基準フォルダーのパス in_NewItem in_out_Dictionary 辞書に追加するオブジェクト in_OtherBasePath in_OtherPathDictionary 辞書のキーを相対パスにするときの基準フォルダーのパス in_OtherPathDictionary → PathDictionaryClass in_OtherItem Empty、または、in_OtherPathDictionary のアイテムと比較するキー オブジェクト 返り値 in_out_Dictionary、または、生成した辞書 in_BasePath 引数の値を基準のパスとした、in_OtherPathDictionary のキー(と in_OtherBasePath からできる) 相対パスに、ファイルまたはフォルダーがあれば、その相対パスを in_out_Dictionary 辞書のキーとし、in_NewItem を in_out_Dictionary 辞書のアイテムとなるように登録します。 参考 → SyncFilesMenuLib.vbs *********************************************************************** <<< GetInputOutputFilePaths >>> *********************************************************************** GetInputOutputFilePaths Function GetInputOutputFilePaths( InputPath as string or PathDictionaryClass, OutputPath as string, TemporaryBaseName as string ) as array of InputOutputFilePathClass ファイルを変換するときの、入力ファイルと出力ファイルのパスの配列を返します。 【引数】 InputPath 入力ファイルのパス、または、 PathDictionaryClass OutputPath 出力ファイルのパス、Empty = 入力ファイルに上書き TemporaryBaseName OutputPath = Empty のときに使う、一時ファイルの名前 → GetTempPath 返り値 入力ファイルと出力ファイルのパスの配列 → InputOutputFilePathClass InputPath に PathDictionaryClass のオブジェクトを指定できることが特徴です。 OutputPath = Empty が指定されると、返り値の配列要素のメンバー IsOutputPathTemporary は True になり、 返り値の配列要素のメンバー OutputPath は、TemporaryBaseName 引数に基づいた一時ファイルのパスに なります。 これは、下記のサンプルのように出力ファイルを入力ファイルに上書きするときに使います。 InputPath 引数と OutputPath 引数が同じパスのときも、OutputPath = Empty が指定されたときと同じ返り値 になります。 サンプル 入力ファイルに上書きすることに対応したコード For Each a_pair In GetInputOutputFilePaths( InputPath, Empty, "Temporary_*.txt" ) copy_ren a_pair.InputPath, a_pair.OutputPath '// メインとなる変換処理に相当 If a_pair.IsOutputPathTemporary Then _ move_ren a_pair.OutputPath, a_pair.InputPath Next サンプル 引数のバリエーション For Each a_pair In GetInputOutputFilePaths( "a.txt", "b.txt", "Temporary_*.txt" ) For Each a_pair In GetInputOutputFilePaths( "a.txt", Empty, "Temporary_*.txt" ) For Each a_pair In GetInputOutputFilePaths( "FolderA", "FolderB", "Temporary_*.txt" ) Set paths = new PathDictionaryClass Set paths( "Files\*.c" ) = Nothing Set paths( "Files\*.h" ) = Nothing For Each a_pair In GetInputOutputFilePaths( paths, Empty, "Temporary_*.txt" ) ソース → vbslib.vbs テスト → T_Wildcard.vbs T_GetInputOutputFilePaths 関連 → ReplaceRootPath *********************************************************************** <<< InputOutputFilePathClass >>> *********************************************************************** InputOutputFilePathClass GetInputOutputFilePaths の返り値(配列)の要素。 .InputPath 入力ファイルのパス .OutputPath 出力ファイルのパス .IsOutputPathTemporary OutputPath メンバーは、入力ファイルに上書きする前の一時ファイルのパスかどうか ソース → vbslib.vbs *********************************************************************** <<< ArrayFromWildcard2 >>> *********************************************************************** ArrayFromWildcard2 Function ArrayFromWildcard2( WildcardPath as string ) as PathDictionaryClass of Nothing ワイルドカードを展開します。 サブ フォルダーも検索します。 【引数】 WildcardPath フォルダーパス。 ワイルドカードも可。 返り値 PathDictionaryClass of Nothing ArrayFromWildcard との違いは、返り値の BasePath プロパティが、WildcardPath 引数に指定した フォルダーになることです。 ArrayFromWildcard では、カレント・フォルダーが BasePath のプロパ ティになります。 ワイルドカードがあると、ファイル名でフィルターします。 BasePath プロパティを明示的に指定したいときは、 PathDictionaryClass を生成してください。 一般に、相対パスのベースとなるフォルダーのパスを WildcardPath 引数に指定します。 サンプル Set paths = ArrayFromWildcard2( "Folder" ) Assert paths.BasePath = GetFullPath( "Folder", Empty ) Assert IsSameArray( paths.FilePaths, Array( "A.txt", "B.ini", "Sub\A.txt" ) ) ワイルドカードがないときは、ファイル または フォルダーのパスとして展開します。 指定したパスが指す場所にファイルかフォルダーのどちらがあるかによって変わります。 どちらも存在しないときは、エラーになります。 サンプル ワイルドカードがあるときは、ファイル名でフィルターします。 Set paths = ArrayFromWildcard2( "Folder\*.txt" ) Assert paths.BasePath = GetFullPath( "Folder", Empty ) Assert IsSameArray( paths.FilePaths, Array( "A.txt", "Sub\A.txt" ) ) ソース → vbslib.vbs テスト → T_Wildcard.vbs T_ArrayFromWildcard2 *********************************************************************** <<< IsWildcard >>> *********************************************************************** IsWildcard (src) Function IsWildcard( path as string ) as boolean 文字列の中にワイルドカードを含むかどうかを返します。 【引数】 path 調べる文字列 返り値 path の中にワイルドカードを含むかどうか 関連 → ReplaceFileNameWildcard *********************************************************************** <<< IsMatchedWithWildcard >>> *********************************************************************** IsMatchedWithWildcard (src) Function IsMatchedWithWildcard( Path, WildCard ) as boolean ワイルドカードにマッチするかどうかを返します。 【引数】 Path 検査する文字列 WildCard ワイルドカード 返り値 Path がワイルドカードにマッチしたかどうか WildCard で指定できるワイルドカードは、先頭に * だけです。 WildCard に * が無い文字列も指定できます。 サンプル Assert IsMatchedWithWildcard( "a.bmp", "*.bmp" ) = True Assert IsMatchedWithWildcard( "a.bmp", "*.jpg" ) = False テスト → T_Wildcard.vbs 関連 → ExpandWildcard *********************************************************************** <<< RemoveWildcardMatchedArrayItems >>> *********************************************************************** RemoveWildcardMatchedArrayItems (src) Sub RemoveWildcardMatchedArrayItems( in_out_PathArray as array of string, WildCard as string ) ワイルドカードにマッチしたパスを配列から除きます。 【引数】 in_out_PathArray (入出力) パスが入った文字列の配列 WildCard ワイルドカードを含むファイルまたはフォルダの名前 WildCard で指定できるワイルドカードは、先頭に * だけです。 WildCard に * が無い文字列も指定できます。 サンプル arr = Array( "a.jpg", "b.bmp", "c.jpg" ) RemoveWildcardMatchedArrayItems arr, "*.jpg" Assert IsSameArray( arr, Array( "b.bmp" ) ) *********************************************************************** <<< RemoveWildcard >>> *********************************************************************** RemoveWildcard (src) Sub RemoveWildcard( WildCard as string, fnames as array of string ) 廃止予定です 代わり → RemoveWildcardMatchedArrayItems *********************************************************************** <<< ReplaceFileNameWildcard >>> *********************************************************************** ReplaceFileNameWildcard (src) Function ReplaceFileNameWildcard( Path as string, FromStr as string, ToStr as string ) ワイルドカードを使って、ファイルパスを変更します。 【引数】 Path ファイルパス(ワイルドカードは使えません) FromStr 変更前の文字列。ワイルドカード可能。 ToStr 変更後の文字列。ワイルドカード可能。 "" 可能。 返り値 変更後のファイルパス。 Empty=Path が FromStr にマッチしなかった ファイル: vbslib.lib Path が、FromStr にマッチしなかったときは、Empty が返ります。 サンプル Assert ReplaceFileNameWildcard( "Fo\File.txt", "Fo\*.txt", "Fo\*.ini" ) = "Fo\File.ini" Path に親フォルダー名が含まれるときは、FromStr, ToStr にも親フォルダー名を含めてください。 s= ReplaceFileNameWildcard( Fo\File.txt", "Fo\*.txt", "Fo\*.xml" '// OK s= ReplaceFileNameWildcard( Fo\File.txt", "*.txt", "*.xml" '// NG テスト → T_Wildcard.vbs # [T_ReplaceFileNameWildcard] 関連 → StrMatchKey クラス ワイルドカードにマッチするかどうか → RemoveWildcard → IsWildcard *********************************************************************** <<< GetReadOnlyList >>> *********************************************************************** GetReadOnlyList Function GetReadOnlyList( TargetPath as string, out_ReadOnlyDictionary as dictionary of boolean, Opt as Empty ) as integer フォルダーにあるすべてのファイルの読み取り属性と、読み取り属性がオンの数を取得します。 【引数】 TargetPath 調べるフォルダー、またはファイルのパス out_ReadOnlyDictionary (出力) 読み取り専用かどうかの辞書、キーは相対パス、Empty可 Opt Empty を指定してください 返り値 読み取り属性がオンであるファイルの数 フォルダー自体の 読み取り属性は取得できません。 out_ReadOnlyDictionary 引数には、読み取り属性がオンのファイルとオフのファイルの両方が含まれます。 サンプル 読み取り属性がオンであるファイルがないことをチェックする Assert GetReadOnlyList( "C:\Folder\FileA.txt", Empty, Empty ) = 0 read_onlys.Keys から、読み取り属性がオンであるファイルのパスが分かります。 サンプル すべてのファイルの読み取り属性がオンであることをチェックする read_only_count = GetReadOnlyList( "C:\Folder\FileA.txt", read_onlys, Empty ) Assert read_only_count = read_onlys.Count サンプル TargetPath 引数にフォルダーを指定した場合 count = GetReadOnlyList( "C:\Folder", read_onlys, Empty ) For Each step_path In read_onlys.Keys is_read_only = read_onlys( step_path ) '// step_path="FileA.txt", ... Next サンプル TargetPath 引数にファイルを指定した場合 count = GetReadOnlyList( "C:\Folder\FileA.txt", read_onlys, Empty ) For Each step_path In read_onlys.Keys is_read_only = read_onlys( step_path ) '// step_path="." Next ソース → ToolsLib.vbs テスト → T_File.vbs T_GetReadOnlyList 関連 → SetReadOnlyAttribute *********************************************************************** <<< EnumFolderObjectDic >>> *********************************************************************** EnumFolderObjectDic Sub EnumFolderObjectDic( in_FolderPath as string, in_EmptyOption as Empty, out_Folders as dictinoary of Folder ) Folder サブ・フォルダー・オブジェクトを高速に辞書に列挙します。 サブフォルダのサブフォルダも列挙します。 【引数】 in_FolderPath 調べるフォルダのパス。 このフォルダの中から列挙します in_EmptyOption Empty を指定してください out_Folders (出力) サブフォルダを含む Folder オブジェクトの辞書 out_Folders は辞書型です。 キーは、フォルダーへの相対パスです。 その基準フォルダーは、 in_FolderPath です。 アイテムは、Folder オブジェクトです。 → Folder オブジェクト (VBS) out_Folders には、in_FolderPath の Folder オブジェクトと、in_FolderPath のサブフォルダーの Folder オブジェクトの両方が含まれます。 in_FolderPath に相当するキーの値は "." です。 サンプル EnumFolderObjectDic "C:\FolderA", Empty, folders1 '// Set "folders1" EnumFolderObjectDic "C:\FolderB", Empty, folders2 '// Set "folders2" For Each step_path In folders1.Keys If not folders2.Exists( step_path ) Then mkdir "C:\FolderB\"+ step_path For Each file In folders1.Item( step_path ).Files copy "C:\FolderA\"+ step_path + file.Name, "C:\FolderB\"+ step_path Next End If Next EnumFolderObjectDic EnumFolderObjectDic 出力例 "." "fe" "fo1" "fo1\fo1" "fo1\fo11.ex" "fo1\t1" "fo2" ソース → vbslib.vbs テスト → T_Wildcard.vbs T_EnumFolderObjectDic 関連 → EnumFolderObject → ExpandWildcard → ファイルを一覧するときの速度 → EnumFileObjectDic → LeafPathDictionary *********************************************************************** <<< EnumFileObjectDic >>> *********************************************************************** EnumFileObjectDic (src) Sub EnumFileObjectDic( FolderOrPath as string or Folder, out_Files as dictinoary of File File フォルダの中のファイル・オブジェクトを高速に辞書に列挙します。 【引数】 FolderOrPath 調べるフォルダのパス。 または、Folder オブジェクト(高速) out_Files (出力) ファイルのオブジェクトの辞書 out_Files は辞書型です。 キーは、ファイル名です。 アイテムは、File オブジェクトです。 サブ・フォルダーにあるファイルは列挙しません。 サンプル Dim files1, files2, file_name EnumFileObjectDic "C:\FolderA", files1 '// [out] files1 EnumFileObjectDic "C:\FolderB", files2 '// [out] files2 For Each file_name In files1.Keys If not files2.Exists( file_name ) Then copy "C:\FolderA\"+ file_name, "C:\FolderB" End If Next EnumFileObjectDic EnumFileObjectDic 関連 → EnumFolderObjectDic → Dic_addFilePaths_fromPathDirectory → LeafPathDictionary *********************************************************************** <<< EnumFolderObject >>> *********************************************************************** EnumFolderObject (src) Sub EnumFolderObject( FolderPath as string, out_Folders as array of Folder ) Folder サブ フォルダーのオブジェクトを高速に列挙します。 サブ フォルダーのサブ フォルダーも列挙します。 【引数】 FolderPath 調べるフォルダのパス。 このフォルダの中から列挙します out_Folders (出力) サブフォルダのオブジェクトの配列 out_Folders には、FolderPath の Folder オブジェクトと、FolderPath のサブ フォルダーの Folder オブジェクトの両方が含まれます。 サンプル EnumFolderObject "C:\FolderA", folders '// Set "folders" For Each folder In folders '// folder as Folder Object For Each file In folder.Files '// file as File Object echo file.Path Next Next EnumFolderObject → Folder オブジェクト → File オブジェクト サンプル Set fname_key = new StrMatchKey fname_key.Keyword = LCase( "*.txt" ) EnumFolderObject "C:\FolderA", folders '// Set "folders" For Each fo In folders '// fo as Folder For Each fi In fo.Files '// fo as File If fname_key.IsMatch( fi.Name ) Then echo fi.DateLastModified End If Next Next EnumFolderObject 性能 → ファイルを一覧するときの速度 関連 → ExpandWildcard → ファイルを一覧するときの速度 → Folder::SubFolders サブ・フォルダーを列挙しない場合 → EnumFolderObjectDic → EnumFileObjectDic *********************************************************************** <<< GetSubFolders >>> *********************************************************************** GetSubFolders (src) Sub GetSubFolders( folders as array of string, path as string ) サブ フォルダーのパスを列挙します。 サブ フォルダーのサブ フォルダーも列挙します。 【引数】 folders (出力) サブ フォルダーのパスの配列 path 調べるフォルダーのパス。 このフォルダーの中から列挙します 関連 → ExpandWildcard *********************************************************************** <<< その他 >>> *********************************************************************** その他 → Dic_searchChildren フォルダーに入っているファイルを一覧することに近い処理を辞書で行います。 → ExpandWildcard_Sort 変数 一覧するときに名前で並べ替えるかどうか → QuickSortDicByKey 辞書を名前で並べ替える *********************************************************************** <<< MD5 リスト >>> *********************************************************************** MD5 リスト フォルダーの中にあるすべてのファイルの MD5 (ハッシュ値の一種) を一覧したテキストファイル。 圧縮ファイルを展開したフォルダーやパッチをあてたフォルダーが正しく復元できたことを保証できます。 作成したフォルダー(A)の内容が、以前固定したフォルダー(B)の内容と同じであるかどうかを チェックするとき、フォルダー(B)に対応する MD5 リストと呼ばれるテキストファイルがあれば、 フォルダー(B) がなくてもチェックができます。 復元したフォルダー FileA.txt FileB.txt チェック MD5 リスト fadc3390060b1ba5ef3bef593b7c930d FileA.txt 60631deb298f23dc7e3a4ada23d8372c FileB.txt MD5 ファイル名 (相対パス) MD5 リスト、タイムスタンプ付き 2015-12-28T11:13:34+09:00 fadc3390060b1ba5ef3bef593b7c930d FileA.txt 2016-02-20T11:01:04+09:00 60631deb298f23dc7e3a4ada23d8372c FileB.txt タイムスタンプ MD5 ファイル名 (相対パス) W3C-DTF 形式 空のフォルダーの MD5 空のフォルダーも MD5 リストに含めます。 その MD5 値は、0が32文字です(vbslib の仕様)。 また、その値は、get_ToolsLibConsts().EmptyFolderMD5 から参照できます。 タイムスタンプ は、常に2001-01-01T00:00:00+00:00 (vbslib の仕様)で、 get_ToolsLibConsts().EmptyFolderTimeStamp から参照できます。 ただし、 NotExistFileMD5 (g_VBS_Lib_System) も 0が32文字です(vbslib の仕様)。 MD5 リスト の1行 2001-01-01T00:00:00+00:00 00000000000000000000000000000000 EmptyFolder VBScript Set tc = get_ToolsLibConsts() If hash_value = tc.EmptyFolderMD5 Then _ : If time_stamp = tc.EmptyFolderTimeStamp Then _ : EmptyFolderMD5 EmptyFolderTimeStamp 関連 → MakeFolderMD5List 関数 → CheckFolderMD5List 関数 → OpenForDefragment 関数 → MD5List コマンド 他にもあります。 _FullSet.txt ファイル、ExistingFiles.txt ファイル _FullSet.txt ファイルが存在するフォルダーは、その中の一部のファイルが存在しない可能性が ありますが、修復することがおそらく可能です。 _FullSet.txt ファイルの内容は MD5リストです。 存在するファイルに関する MD5リスト(ファイル名の例: ExistingFiles.txt)から同じハッシュ値(MD5) のファイルを探し、存在すればコピーして修復できます。 参考 → MD5List コマンド の Fragment と Defragment。 _FullSet.txt ファイルが存在するフォルダーから、別のフォルダーにコピーするとき、コピー元を修復 しなくても、コピー先を完全なフォルダーにすることができます。 参考 → CopyFolder (OpenForDefragmentClass) 参考 → ハッシュ値を利用してファイルの同一性をチェックする − @IT (Web) → 窓の杜 - CRCMD5リストを一括作成や連続比較して結果をタブで切り替え表示するソフト (Web) 関連 → MD5List コマンド → 空のフォルダーの MD5 → NotExistFileMD5 ファイルが存在しないとき → OpenForDefragment *********************************************************************** <<< MakeFolderMD5List >>> *********************************************************************** << MD5 リスト MakeFolderMD5List Sub MakeFolderMD5List( in_FolderPath as string, in_MD5ListFilePath as string, in_Option ) 後でフォルダーが正しく復元できたかどうかをチェックできるように、MD5 リストを作成します。 【引数】 in_FolderPath 対象のフォルダーのパス、またはその辞書 in_MD5ListFilePath 作成する MD5 リストのファイルパス in_Option → in_Option 引数 ファイル名が Ascii 文字だけのときは、Ascii 形式テキストファイルができます。 Ascii 文字以外が含まれるときは、Unicode 形式テキストファイルができます。 空のフォルダーも列挙します。 その MD5 値は、0が32文字です(vbslib 新仕様)。 サンプル MakeFolderMD5List "C:\Target", "MD5List.txt", Empty '// Write to "MD5List.txt" in_Option 引数 Empty または、下記の論理和を指定します。 Empty パスでソートします。 MD5 リストの中の相対パスの基準フォルダーは、in_FolderPath 引数の値です。 tc.BasePathIsList MD5 リストの中の相対パスの基準フォルダーは、in_MD5ListFilePath 引数の値の 親フォルダーです。 指定しなかったときの基準フォルダーは、in_FolderPath 引数の値です。 tc.FasterButNotSorted ソートしません。 やや高速に処理します。 CheckFolderMD5List に使えなくなります。 SortFolderMD5List で使えるようになります。 OpenForDefragment には使えます。 tc.IncludeFullSet _FullSet.txt があるフォルダーは、ファイルを列挙せず _FullSet.txt の内容を読みます。 tc.FasterButNotSorted と or で同時に指定してください。 CheckFolderMD5List OpenForDefragment とも使えなくなります。 tc.TimeStamp MD5 リストにファイルの更新日時も含めます。 tc は、get_ToolsLibConsts() です。 in_FolderPath 引数 - 複数の対象フォルダー 複数の対象のフォルダーに対する MD5リストを1つのファイルに出力するときは、 in_FolderPath 引数に辞書型を指定します。 ・Key: MD5リストに含まれるパスの左に付ける文字列 ・Item: 対象のフォルダーのパス サンプル MakeFolderMD5List Dict(Array( "%A%\", "C:\TargetA", "%B%\", "C:\TargetB" )), _ "MD5List.txt", Empty MD5List.txt: 202cb962ac59075b964b07152d234b70 %A%\example.txt fd758aae4cede6a4d6e44ef59b18e799 %B%\example.txt 対象フォルダーに含まれる MD5リスト 対象フォルダーの中に MD5リストを作成することはできますが、 そのMD5リストの中に作成しようとしている MD5リストを含めることはできません。 なぜなら、MD5リストのMD5が作成する前のMD5になってしまうからです。 ソース → ToolsLib.vbs テスト → T_fc.vbs T_MD5List 関連 → CheckFolderMD5List → Save (MD5CacheClass) → UpdateFolderMD5List *********************************************************************** <<< CheckFolderMD5List >>> *********************************************************************** << MD5 リスト CheckFolderMD5List Sub CheckFolderMD5List( in_TargetFolderPath as string, in_CorrectMD5ListFilePath as string, in_Option as Empty or variant ) MD5 リストを使って、フォルダーが正しく復元できたかどうかをチェックします。 【引数】 in_TargetFolderPath チェック対象の(復元した)フォルダーのパス、またはその辞書 in_CorrectMD5ListFilePath MD5 リストのファイルパス in_Option Empty または get_ToolsLibConsts().BasePathIsList 正しく復元できていれば、そのまま関数から返ります。 正しく復元できていなければ、Diff ツールで差分が表示され、エラーになります。 これは、 AssertFC と同じ動きです。 Diff ツールの左側がファイルにある(過去の)MD5リスト、右側が現在のフォルダーの MD5リストです。 in_TargetFolderPath 引数は、 MakeFolderMD5List と同様に辞書(複数の対象フォルダー)を指定できます。 in_CorrectMD5ListFilePath 引数にタイムスタンプ付き MD5 リストを指定したとき、タイムスタンプが 異なっていてもエラーにはなりません。 in_Option 引数 Empty パスでソートします。 ソートするのは内部でチェック対象のフォルダーから一時的に作成する MD5リストです。 in_CorrectMD5ListFilePath 引数に指定した MD5リストは、ソートされます。 MD5 リストの中の相対パスの基準フォルダーは、in_FolderPath 引数です。 tc.BasePathIsList MD5 リストの中の相対パスの基準フォルダーは、in_MD5ListFilePath 引数の 親フォルダーです。 c.TimeStamp 正しく復元できていたら、ファイルのタイムスタンプを MD5リストに書かれた日時に変更します。 c は、g_VBS_Lib です。 tc は、get_ToolsLibConsts() です。 対象フォルダーに含まれる MD5リスト 対象のフォルダーの中に MD5リストがあるときは、そのMD5リストの中にはそのMD5リスト ファイルの MD5が含まれていません。 なぜなら、MD5リストのファイルの MD5 を含んだ MD5リストができないからです。 → MakeFolderMD5List CheckFolderMD5List 関数は、MD5リストの有無と、MD5リスト自身のハッシュ値の正しさに ついては、チェックしません。 ソース → ToolsLib.vbs テスト → T_fc.vbs T_MD5List 関連 → MakeFolderMD5List → IsSameHashValueOfLeafPathDictionary (MD5CacheClass) *********************************************************************** <<< IsSameMD5List >>> *********************************************************************** << MD5 リスト IsSameMD5List Function IsSameMD5List( in_MD5ListFilePathA as string, in_MD5ListFilePathB as string, in_Option as Empty or variant) 2つの MD5 リストの中のハッシュ値だけを比較して同じかどうかを返します。 【引数】 in_MD5ListFilePathA MD5 リストのファイルパス in_MD5ListFilePathB 比較するもう1つの MD5 リストのファイルパス in_Option Empty または g_VBS_Lib.EchoV_NotSame 返り値 ハッシュ値が等しいかどうか MD5 リストの中に記録されたタイムスタンプは、比較に使われません。 MD5リストの行の順番だけが違うときは、等しいと判定します。 in_Option = g_VBS_Lib.EchoV_NotSame を設定すると、違った行を表示します。 ソース → ToolsLib.vbs テスト → CheckFolderMD5List *********************************************************************** <<< SortFolderMD5List >>> *********************************************************************** << MD5 リスト SortFolderMD5List Sub SortFolderMD5List( in_InputMD5ListFilePath as string, in_OutputMD5ListFilePath as string, in_Option as Empty ) MD5 リストを、相対パスでソートします。 【引数】 in_InputMD5ListFilePath ソートする前の MD5 リストのファイルパス in_OutputMD5ListFilePath ソートした後の MD5 リストのファイルパス in_Option Empty を指定してください 重要なファイルを上書き更新するときは、SortFolderMD5List の in_OutputMD5ListFilePath 引数に 一時的に出力するパスを指定し、その一時ファイルを作成した後(ファイルを閉じた後)で、 SafeFileUpdateEx を呼び出してください。 in_InputMD5ListFilePath 引数と in_OutputMD5ListFilePath 引数に、同じファイルを指定できます。 改行文字は、CR+LF に統一されます。 ソートするときに使う比較関数は、 PathNameCompare です。 ソース → ToolsLib.vbs テスト → T_fc.vbs T_SortFolderMD5List 関連 → ExpandWildcard_Sort 変数 *********************************************************************** <<< CopyDiffByMD5List >>> *********************************************************************** << MD5 リスト CopyDiffByMD5List Sub CopyDiffByMD5List( in_SourceFolderPath as string, in_DestinationFolderPath as string, in_SourceMD5ListFilePath as string, in_DestinationMD5ListFilePath as string, in_Option as Empty or integer ) コピー元とコピー先の MD5リストを使って、ファイルやフォルダーの差分をコピーします。 【引数】 in_SourceFolderPath コピー元のフォルダーのパス in_DestinationFolderPath コピー先のフォルダーのパス in_SourceMD5ListFilePath コピー元の MD5リストのパス in_DestinationMD5ListFilePath コピー先の MD5リストのパス in_Option Empty または g_VBS_Lib.AfterDelete in_Option 引数にg_VBS_Lib.AfterDelete を指定すると、コピー元にないファイルをコピー先のフォルダー から削除します。 in_Option 引数に Empty を指定すると、その削除を行いません。 空フォルダーの作成や、ファイルの削除による空フォルダーの削除も正しく処理します。 コピー先(in_DestinationFolderPath 引数)にフォルダーがないときや、空のフォルダーのパスを指定した ときは、差分を抽出するような動きになります。 コピー元の(in_SourceMD5ListFilePath 引数が指す) MD5リストがないときは、コピー元のフォルダー を調べるように UpdateFolderMD5List を呼び出して、コピー元の MD5リストを作ります。 サンプル MD5リストを使うことで、パッチのように USBメモリーやファイル サーバーを経由して PC 間の差分 コピーをすることができます。 また、下記のステップ1をする PC には、コピー先のフォルダーは、 必要ありません。 ステップ1: PC1 で、USBメモリーに、Revision-02 で追加されたファイルをコピーします。 Set c = g_VBS_Lib CopyDiffByMD5List "C:\FolderA", "E:\USB", _ "E:\Revision-02.txt", "E:\Revision-01.txt", c.AfterDelete ステップ2: PC2 で、USBメモリーから、Revision-02 で追加されたファイルをコピーします。 Set c = g_VBS_Lib CopyDiffByMD5List "E:\USB", "C:\BackUp\FolderA", _ "E:\Revision-02.txt", "E:\Revision-01.txt", c.AfterDelete 参考 → MD5List >> CopyDiff コマンド ソース → ToolsLib.vbs テスト → T_fc.vbs T_MD5List_CopyDiff 関連 → CopyDiffByMD5Lists 複数のコピー *********************************************************************** <<< CopyDiffByMD5Lists >>> *********************************************************************** << MD5 リスト CopyDiffByMD5Lists Sub CopyDiffByMD5Lists( in_SettingFilePath as string ) コピー元とコピー先の MD5リストを使って、ファイルやフォルダーの差分を複数コピーします。 【引数】 in_SettingFilePath 設定ファイル(下記)のパス 参考 → CopyDiffByMD5List サンプル 設定ファイル ソース → ToolsLib.vbs テスト → T_fc.vbs T_MD5List_CopyDiffByMD5Lists *********************************************************************** <<< UpdateFolderMD5List >>> *********************************************************************** UpdateFolderMD5List Sub UpdateFolderMD5List( in_TargetFolderPath as string, in_InputMD5ListFilePath as string, in_OutputMD5ListFilePath as string, in_Empty as Empty ) MD5 リストを更新します。 【引数】 in_TargetFolderPath 対象のフォルダーのパス in_InputMD5ListFilePath 入力する(古い)MD5 リストのファイルパス in_OutputMD5ListFilePath 出力する MD5 リストのファイルパス in_Empty Empty を指定してください 入力する MD5 リストに書かれたタイムスタンプと変わらないファイルは、MD5リストを再計算しません。 その分、高速に動作します。 in_OutputMD5ListFilePath のファイルは、in_TargetFolderPath のフォルダーに対して MakeFolderMD5List したときと同じ結果になります。 ソース → ToolsLib.vbs テスト → T_fc.vbs T_UpdateFolderMD5List 関連 → MakeFolderMD5List *********************************************************************** <<< IsThereTimeStampInFolderMD5List >>> *********************************************************************** IsThereTimeStampInFolderMD5List Function IsThereTimeStampInFolderMD5List( in_MD5ListFilePath as string ) as boolean MD5 リストにタイムスタンプが含まれているかどうかを返します。 【引数】 in_MD5ListFilePath MD5 リストのファイルパス 返り値 MD5 リストにタイムスタンプが含まれているかどうか ソース → ToolsLib.vbs *********************************************************************** <<< GetColumnOfPathInFolderMD5List >>> *********************************************************************** << MD5 リスト GetColumnOfPathInFolderMD5List Function GetColumnOfPathInFolderMD5List( in_MD5ListFilePath as string ) as integer MD5 リストの行を調べて、ファイルのパスがあるカラム番号(1以上)を返します。 【引数】 in_MD5ListFilePath MD5 リストのファイルパス 返り値 ファイルのパスがあるカラム番号(1以上) MD5 リストの中にタイムスタンプがあるときは、60 を返します。 MD5 リストの中にタイムスタンプがないときは、34 を返します。 指定した MD5 リストのファイルの内容がないときは、0 を返します。 指定した MD5 リストのファイルがないときは、エラーになります。 ソース → ToolsLib.vbs テスト → T_fc.vbs T_GetColumnOfPathInFolderMD5List *********************************************************************** <<< ReadPathsInMD5List >>> *********************************************************************** << MD5 リスト ReadPathsInMD5List Function ReadPathsInMD5List( in_MD5ListFilePath as string, in_ColumnOfPath as integer ) MD5 リストから、キーが相対パスの 辞書 を作成します。 【引数】 in_MD5ListFilePath MD5 リストのファイルパス in_ColumnOfPath ファイルのパスがあるカラム番号(1以上) 返り値 MD5 リストから作成した、キーが相対パスの辞書 返り値の要素のアイテムは、MD5 リストの1行です。 タイムスタンプが入ることもあります。 末尾に改行はありません。 サンプル C:\MD5List.txt fadc3390060b1ba5ef3bef593b7c930d FileA.txt 60631deb298f23dc7e3a4ada23d8372c FileB.txt スクリプト path = "C:\MD5List.txt" Set files = ReadPathsInMD5List( path, _ GetColumnOfPathInFolderMD5List( path ) ) Assert files( "FileA.txt" ) = "fadc3390060b1ba5ef3bef593b7c930d FileA.txt" Assert files( "FileB.txt" ) = "60631deb298f23dc7e3a4ada23d8372c FileB.txt" ReadPathsInMD5List GetColumnOfPathInFolderMD5List ソース → ToolsLib.vbs 関連 → OpenForDefragment *********************************************************************** <<< OpenForDefragment >>> *********************************************************************** << MD5 リスト OpenForDefragment Function OpenForDefragment( in_MD5ListFilePath as string, in_OptionFlag ) MD5 ハッシュ値が同じファイルを探して、コピーする処理を開始します。 【引数】 in_MD5ListFilePath 存在するファイルの MD5 リストのファイル パス in_OptionFlag Empty または get_ToolsLibConsts().TimeStamp 返り値 → OpenForDefragmentClass 内部でハッシュ値の 辞書 を作ります。 返り値のオブジェクトを使って、_FullSet.txt があるフォルダーに対して、 フラグメント(同じ内容のファイルを削除する)や デフラグメント(完全形に復帰する)ができます。 in_OptionFlag 引数に get_ToolsLibConsts().TimeStamp を指定すると、MD5リストが 空のファイルのときに、 Append すると、タイムスタンプ付きの MD5リストになります。 返り値のオブジェクトが削除されるまで、in_MD5ListFilePath 引数に指定したファイルを 読み取りモードで開いています。 参考 → OpenForDefragmentClass ソース → ToolsLib.vbs テスト → T_fc.vbs T_OpenForDefragment 関連 → ReadPathsInMD5List キーが相対パスの辞書 *********************************************************************** <<< OpenForDefragmentClass >>> *********************************************************************** OpenForDefragmentClass << OpenForDefragment (子ノードを参照してください。) *********************************************************************** <<< FileFullPath (OpenForDefragmentClass) >>> *********************************************************************** FileFullPath (OpenForDefragmentClass) Dim OpenForDefragmentClass::FileFullPath as string MD5 リスト のフル パス。 *********************************************************************** <<< GetRelativePath (OpenForDefragmentClass) >>> *********************************************************************** GetRelativePath (OpenForDefragmentClass) << OpenForDefragmentClass GetStepPath (OpenForDefragmentClass) Function OpenForDefragmentClass::GetRelativePath( in_HashValueOfMD5 as string, in_BaseFullPathInMD5List as string ) as string or Empty 初期化時に指定した MD5 リストから指定のハッシュ値を探して、相対パス(relative path)を返します。 【引数】 in_HashValueOfMD5 探すハッシュ値(MD5) in_BaseFullPathInMD5List Empty またはMD5 リストの中にある相対パスの基準パス 返り値 相対パス または Empty in_BaseFullPathInMD5List 引数が Empty ではないときは、ファイルが存在するパスを返します。 ファイルが存在しなければ、Empty を返します。 in_BaseFullPathInMD5List 引数が Empty のときは、ファイルが存在するかどうかをチェックしません。 ファイルが存在しないときも相対パスを返します。 ハッシュ値が一致するファイルがないときは、Empty を返します。 ハッシュ値の検索に辞書を使っています。 サンプル Set defrag = OpenForDefragment( "Folder\MD5List.txt", Empty ) step_path = defrag.GetRelativePath( "a5e064892e90bdbc0f85d8fe14f6828a", Empty ) Assert step_path = "Sub\File.txt" ソース → ToolsLib.vbs テスト → T_fc.vbs T_OpenForDefragment_1 *********************************************************************** <<< CopyFolder (OpenForDefragmentClass) >>> *********************************************************************** CopyFolder (OpenForDefragmentClass) << OpenForDefragmentClass Sub OpenForDefragmentClass::CopyFolder( in_BasePathInMD5List as string, in_SourceFolderPath as string, in_DestinationFolderPath as string, in_out_Options ) _FullSet.txt という名前のファイルに書かれたすべてのファイルを指定のフォルダーにコピーします。 【引数】 in_BasePathInMD5List Me の MD5 リストの中にある相対パスの基準パス in_SourceFolderPath コピー元 または _FullSet.txt ファイルがあるフォルダーのパス in_DestinationFolderPath コピー先のフォルダーのパス in_out_Options Empty または 各種フラグの論理和 → in_out_Options 引数 _FullSet.txt ファイルがある断片化(Fragment)されたフォルダーを、デフラグ(Defragment)した 完全なフォルダーに復帰、または別のフォルダーに完全なフォルダーをコピーします。 前者(復帰) をするときは、in_SourceFolderPath 引数 = in_DestinationFolderPath 引数を指定してください。 _FullSet.txt ファイルが in_SourceFolderPath のフォルダーになければ、MD5 は無視され、 in_SourceFolderPath のフォルダーから in_DestinationFolderPath のフォルダーにコピーするだけ になります。 (in_out_Options 引数に、c.SubFolder を指定しなかったとき) 参考 → ハッシュ値が見つからないエラーの対処方法 サンプル Set defrag = OpenForDefragment( "MD5List.txt", Empty ) defrag.CopyFolder "in_BasePathInMD5List", _ "in_SourceFolderPath", "in_DestinationFolderPath", Empty in_SourceFolderPath in_DestinationFolderPath FileC.txt FileA.txt FileC.txt (_FullSet.txt) fadc3390060b1ba5ef3bef593b7c930d FileA.txt 202cb962ac59075b964b07152d234b70 FileC.txt 同じハッシュ値(MD5)のファイルをコピー in_BasePathInMD5List MD5List.txt Me FileA.txt fadc3390060b1ba5ef3bef593b7c930d FileA.txt 60631deb298f23dc7e3a4ada23d8372c FileB.txt FileB.txt サンプル コピー元が圧縮されているとき in_SourceFolderPath と in_BasePathInMD5List の引数に指定したフォルダーに、コピー元となる ファイルが入った _Fragment.7z という名前の圧縮ファイル(7z形式)があったときは、自動的に 解凍も行い、コピーした結果は同じファイルになります。 解凍は、 DownloadAndExtractFileIn7zClass で行います。 DownloadStart をすべてのファイルに対して呼び出した後で、CopyFolder すると速くなります。 in_SourceFolderPath in_DestinationFolderPath FileC.txt _Fragment.7z FileA.txt FileC.txt _FullSet.txt fadc3390060b1ba5ef3bef593b7c930d FileA.txt 202cb962ac59075b964b07152d234b70 FileC.txt FileA.txt 同じハッシュ値(MD5)のファイルを圧縮ファイルの中からコピー in_BasePathInMD5List MD5List.txt Me _Fragment.7z fadc3390060b1ba5ef3bef593b7c930d FileA.txt 60631deb298f23dc7e3a4ada23d8372c FileB.txt in_out_Options 引数 in_out_Options 引数には、Empty、下記の定数の論理和、または、OpenForDefragmentOptionClass を指定できます。 c.NotExistOnly コピー先にすでにファイルが存在するときはコピーしません。 結果、_FullSet.txt に書かれたハッシュ値と内容が異なる可能性が あります。 指定しなかったときは、コピー先にすでにファイルが存在する ときでも、上書きコピーを行います。 c.ExistOnly コピー元となるファイル(MD5リストが指すパスのファイル)が存在しない ときは、エラーにせず無視します。 コピー先のフォルダーを完全に復帰 するには、別の MD5リストからも c.NotExistOnly を指定して CopyFolder します。 ただし、最後の MD5リストから CopyFolder するときは、 c.ExistOnly を指定せずに CopyFolder します。 c.SubFolder in_SourceFolderPath 引数に指定したパスとそのサブ フォルダーにある すべての _FullSet.txt があるフォルダーを処理対象とします。 c.ToNotReadOnly コピー先のファイルを読み取り専用ではないようにします。 c は、g_VBS_Lib です。 OpenForDefragmentOptionClass を指定する場合、Delegate メンバーはユーザー定義です。 in_out_Options 引数の出力は、 ParseOptionArguments 関数 の出力です。 ソース → ToolsLib.vbs テスト → T_fc.vbs T_OpenForDefragment_CopyFolder T_OpenForDefragment_Unzip *********************************************************************** <<< DownloadStart (OpenForDefragmentClass) >>> *********************************************************************** DownloadStart (OpenForDefragmentClass) << OpenForDefragmentClass Sub OpenForDefragmentClass::DownloadStart( in_BasePathInMD5List as string, in_SourceFolderPath as string, in_DestinationFolderPath as string, in_out_Options ) CopyFolder のコピー元のファイルを並列して テンポラリ フォルダー \Fragments にコピーします。 【引数】 in_BasePathInMD5List Me の MD5 リストの中にある相対パスの基準パス in_SourceFolderPath コピー元 または _FullSet.txt ファイルがあるフォルダーのパス in_DestinationFolderPath コピー先のフォルダーのパス in_out_Options Empty または 各種フラグの論理和 並列にコピーする分、速くコピーが終わります。 DownloadAndExtractFileIn7zClass の DownloadStart を内部で呼び出しています。 ソース → ToolsLib.vbs テスト → T_fc.vbs T_OpenForDefragment_Unzip_True *********************************************************************** <<< Append (OpenForDefragmentClass) >>> *********************************************************************** Append (OpenForDefragmentClass) << OpenForDefragmentClass Sub OpenForDefragmentClass::Append( in_OutputMD5ListFilePath as string, in_BasePathInMD5List as string, in_FragmentFolderPath as string, in_Empty ) 指定のフォルダーの中にあるファイルと同じハッシュ値のファイルが、Me の MD5 リストになければ追加します。 【引数】 in_OutputMD5ListFilePath Empty または 更新した MD5 リストを保存するパス in_BasePathInMD5List Me の MD5 リストの中にある相対パスの基準パス in_FragmentFolderPath MD5 リストに追加するファイルがあるフォルダーのパス in_Empty Empty を指定してください in_OutputMD5ListFilePath 引数に指定したファイルに、MD5 リストの複数行をライトします。 OpenForDefragment に指定したパスと異なるときは、名前を付けて保存したときのように、 開く前のリストも含んだリストを出力します。 in_OutputMD5ListFilePath 引数に Empty を指定すると、MD5 リストをファイルにライトしません。 ただし、 Save すると、そのタイミングで、本関数で追加された MD5 リストの複数行も保存されます。 in_FragmentFolderPath 引数に指定したフォルダーの直下に _FullSet.txt ファイル があるときは、 _FullSet.txt ファイルに書かれたハッシュ値が Me の MD5 リストになければ、MD5 リストに追加します。 フォルダーの中のファイルの列挙やハッシュ値の計算は行いません。 in_FragmentFolderPath 引数に指定したフォルダー A の中にあるファイルと同じハッシュ値(=同じ内容) の行が Me の MD5 リストにすでにある場合は、その行に書かれたパスがフォルダー A の外であっても、 MD5 リストに追加しません。 サンプル Set defrag = OpenForDefragment( "Folder\MD5List.txt", Empty ) defrag.Append "Folder\MD5List.txt", "Folder", "Folder\NewFragment", Empty ソース → ToolsLib.vbs テスト → T_fc.vbs T_OpenForDefragment_Append_* *********************************************************************** <<< Save (OpenForDefragmentClass) >>> *********************************************************************** Save (OpenForDefragmentClass) << OpenForDefragmentClass Sub OpenForDefragmentClass::Save( in_OutputMD5ListFilePath as string ) Append した MD5 リストをファイルに保存します。 【引数】 in_OutputMD5ListFilePath 出力する MD5 リストのファイル パス 1つも Append してなかったら、ファイルにアクセスしません。 内部で SafeFileUpdateEx を呼んでいます。 サンプル Set defrag = OpenForDefragment( "Folder\MD5List.txt", Empty ) defrag.Append Empty, "Folder", "Folder\NewFragmentA", Empty defrag.Append Empty, "Folder", "Folder\NewFragmentB", Empty defrag.Save "Folder\MD5List.txt" Append ソース → ToolsLib.vbs テスト → T_fc.vbs T_OpenForDefragment_Append_* *********************************************************************** <<< Fragment (OpenForDefragmentClass) >>> *********************************************************************** Fragment (OpenForDefragmentClass) << OpenForDefragmentClass Sub OpenForDefragmentClass::Fragment( in_BasePathInMD5List as string, in_FragmentingFolderPath as string, in_Flags ) 指定の _FullSet.txt の中にあるファイルのうち、Me の MD5 リストにある ファイルを削除します。 【引数】 in_BasePathInMD5List Me の MD5 リストの中にある相対パスの基準パス in_FragmentingFolderPath 削除しようとするファイルを含む _FullSet.txt ファイル があるフォルダーのパス in_Flags Empty または g_VBS_Lib.SubFolder Me の MD5 リストにあるファイルは、削除しません。 in_Flags 引数に g_VBS_Lib.SubFolder を指定したときは、in_FragmentingFolderPath 引数に 指定したパスとそのサブ フォルダーにある すべての _FullSet.txt があるフォルダーを 処理対象とします。 未対応 サンプル Set defrag = OpenForDefragment( "Folder\MD5List.txt", Empty ) defrag.Fragment "Folder", "Folder\NewFragment", Empty ソース → ToolsLib.vbs テスト → T_fc.vbs T_OpenForDefragment_Fragment *********************************************************************** <<< ExistenceCache (OpenForDefragmentClass) >>> *********************************************************************** ExistenceCache (OpenForDefragmentClass) Dim OpenForDefragmentClass::ExistenceCache as ExistenceCacheClass ExistenceCacheClass ファイルやフォルダーが存在するかどうかを高速に調べるためのキャッシュ。 OpenForDefragmentClass では、キャッシュの対象(ExistenceCacheClass:: TargetRootPath)の初期値が "\\" です。 つまり、共有フォルダー(UNC)が対象になります。 対象かどうかは、 StrCompHeadOf の c.AsPath で判定しています。 *********************************************************************** <<< OpenForDefragmentOptionClass >>> *********************************************************************** OpenForDefragmentOptionClass OpenForDefragment に関連するオプション。 integer .Flags CopyFolder の in_out_Options 引数に指定できる定数 CopyFunction .CopyOneFileFunction CopyFolder の中からコールバックされる関数。 ファイルのパスと、OpenForDefragmentOptionClass が渡されます。 variant .Delegate ユーザー定義、または、コール元定義 string .CurrentTimeStampInFullSetFile CopyFolder の中からコールバックされたとき、 _FullSet.txt ファイルに書かれたタイムスタンプ。 W3CDTF 型。 ソース → ToolsLib.vbs *********************************************************************** <<< ハッシュ値が見つからないエラーの対処方法。 Not found hash value in a list >>> *********************************************************************** ハッシュ値が見つからないエラーの対処方法。 Not found hash value in a list OpenForDefragment の CopyFolder で、ハッシュ値が見つからないエラー(例:下記)になったときの 状況と対処方法について説明します。 サンプル (下の図の左上) (下の図の右下) (下の図の左下) → 状況 → 対処方法 ソース → ToolsLib.vbs → CopyFolder (OpenForDefragmentClass) 状況 エラーメッセージの XML の中にある defragmenting_path 属性の値が、復元(Defragment)しようと しているファイルのパスです。 not_found_in 属性の値は、復元の元となる内容のハッシュ値 (コピー元となるファイルの内容のハッシュ値)が書かれているはずのハッシュ リストのファイルの パスです。 このハッシュ値は、found_in 属性の値に書かれたパス(_FullSet.txt)にあるファイルから 調べた値です。 下記の図は、正常動作する場合を表しています。 defragmenting_path A_Copy.txt A.txt コピー found_in not_found_in _FullSet.txt MD5List.txt : c678... A_Copy.txt : : c678... A.txt : c678... は、 c678ba46bc07e2062f66b188b0f520cf の省略です。 c678... A.txt not_found_in 属性の値に書かれたパスにあるハッシュ リスト ファイル(MD5List.txt)の中に、 ハッシュ値(c678ba46bc07e2062f66b188b0f520cf) が存在しないと、ハッシュ値が見つからない エラーになります。 A_Copy.txt ? _FullSet.txt MD5List.txt : c678... A_Copy.txt : : ???? : 対処方法 まず、復元するファイル(defragmenting_path 属性の値、例: A_Copy.txt)の正しい内容を決めます。 そして、そのハッシュ値を GetHash などで調べてください。 (A) 正しい内容のハッシュ値が、エラー メッセージに含まれるハッシュ値(c678...)と同じであれば、 MD5List.txt ファイルにそのハッシュ値を作り、コピー元となるファイルを作成します。 A.txt _FullSet.txt MD5List.txt : c678... A_Copy.txt : : c678... A.txt : 正しい内容→ c678... A.txt (B) 正しい内容のハッシュ値が、エラー メッセージに含まれるハッシュ値(c678...)と異なるのであれば、 _FullSet.txt ファイルに書かれたハッシュ値を修正します。 (B-X) また、コピー元とコピー先で同じ内容になるのであれば、MD5List.txt の内容と、コピー元の ファイルの内容を修正します。 A.txt _FullSet.txt MD5List.txt : 0db2... A_Copy.txt : : 0db2... A.txt : 正しい内容→ 0db2... 0db2... A.txt (B-Y) 正しい内容がコピー元と異なるのであれば、コピー先だったパスにファイルを追加します。 A_Copy.txt (追加) _FullSet.txt MD5List.txt : 0db2... A_Copy.txt : : c678... A.txt : 正しい内容→ 0db2... 0db2... *********************************************************************** <<< MD5CacheClass >>> *********************************************************************** MD5CacheClass ファイルのパスと、 MD5 のハッシュ値の関連を表現する辞書。 注意 MD5CacheClass を改良した OpenForDefragment をお使いください。 辞書の内容はファイルに保存(Save)・ファイルから復帰(Load)することができます。 ハッシュ値を計算(Scan)するときは、前回計算したときのタイムスタンプと異なるファイルだけ再計算する ことで、高速に MD5 の辞書を更新します。 MD5 リストのファイルを作成しておけば、フォルダーのサイズを削減するため同じハッシュ値のファイルを 一時的に削除(Fragment)したり、必要な時にファイルを復帰(Defragment)したりすることができます。 タイムスタンプ付きの MD5リストも扱えます。 タイムスタンプが違ったファイルだけ再計算することも できます。 復元したフォルダー FileA.txt FileB.txt ハッシュ値のみチェック、タイムスタンプが違ったファイルだけ再計算 MD5 リスト 2015-12-28T11:13:34+09:00 fadc3390060b1ba5ef3bef593b7c930d FileA.txt 2016-02-20T11:01:04+09:00 60631deb298f23dc7e3a4ada23d8372c FileB.txt タイムスタンプ MD5 ファイル名 (相対パス) サンプル Set hashes = new_MD5CacheClass( get_MD5CacheConst().TimeStamp ) hashes.Initialize hashes.c.TimeStamp hashes.TargetPaths = "C:\Folder" hashes.Scan Empty, Empty, False hashes.Save "_HashCache.txt" ソース → ToolsLib.vbs テスト → T_fc.vbs T_MD5Cache *********************************************************************** <<< TargetPaths >>> *********************************************************************** TargetPaths Dim MD5CacheClass::TargetPaths as string or PathDictionaryClass PathDictionaryClass MD5リストの中の相対パスの基準となるパス、または、MD5リストを構成するファイルのリスト。 1つのファイルパスを文字列型で指定することはできません。 *********************************************************************** <<< DefaultHashFileName >>> *********************************************************************** DefaultHashFileName Dim MD5CacheClass::DefaultHashFileName as string 保存するときのデフォルトのファイル名。 Scan するときにデフォルトでスキップするファイル名。 *********************************************************************** <<< GetHashFromStepPath >>> *********************************************************************** GetHashFromStepPath Function MD5CacheClass::GetHashFromStepPath( in_StepPath as string ) as string ファイルの相対パスから、ファイル固有のハッシュ値を返します。 ハッシュ値が登録されていなければ、Empty を返します。 相対パスの基準パス Load メソッド または Scan メソッド の in_TargetPaths 引数に指定したフォルダーのパス(文字列)が、 相対パスの基準パスになります。 in_TargetPaths 引数に PathDictionaryClass のオブジェクトを指定 したときは、その BasePath プロパティが基準パスになります。 参考 → GetBasePath ソース → ToolsLib.vbs *********************************************************************** <<< GetFirstStepPathFromHash >>> *********************************************************************** GetFirstStepPathFromHash Function MD5CacheClass::GetFirstStepPathFromHash( in_HashValue as string ) as string ファイル固有のハッシュ値から、存在する1つのファイルの相対パスを返します。 参考 → 相対パスの基準パス ソース → ToolsLib.vbs *********************************************************************** <<< SetHashValue >>> *********************************************************************** SetHashValue Sub MD5CacheClass::SetHashValue( in_StepPath as string, in_HashValue as string ) ファイルのパスに、計算済みのファイル固有のハッシュ値を設定します。 【引数】 in_StepPath ファイルの相対パス。 基準は → 相対パスの基準パス in_HashValue (出力) in_StepPath に指定したファイルのハッシュ値 ハッシュ値を計算するよりも早く処理します。 in_HashValue 引数に Empty を指定すると、リストから除外されます。 すでに除外されているときは何もせず、エラーにもなりません。 ソース → ToolsLib.vbs *********************************************************************** <<< Load >>> *********************************************************************** Load Sub MD5CacheClass::Load( in_HashCachePath as string, in_TargetPaths as string or PathDictionaryClass ) 計算済みのファイル固有のハッシュ値がたくさん記録されたファイルをロードします。 【引数】 in_HashCachePath ハッシュ値がたくさん記録されたファイルのパス in_TargetPaths Empty、または、スキャンする対象のパス in_TargetPaths に指定したフル パスを Me.TargetPaths に設定します。 in_TargetPaths に Empty を指定したら、in_HashCachePath の親フォルダーのパスを in_TargetPaths に 指定したときと同じ動きをします。 PathDictionaryClass のオブジェクトを指定することもできます。 in_HashCachePath の基準パスは、カレント フォルダーです。 ソース → ToolsLib.vbs テスト → T_fc.vbs T_MD5Cache *********************************************************************** <<< Save >>> *********************************************************************** Save Sub MD5CacheClass::Save( in_OutHashCachePath as string or Empty ) ファイル固有のハッシュ値をファイルに保存します。 【引数】 in_OutHashCachePath ハッシュ値をたくさん記録するファイルのパス Scan などで登録されたハッシュ値とタイム スタンプを出力します。 in_OutHashCachePath が Empty のときは、Me.DefaultHashFileName に保存します。 サンプル フォルダーに入っているファイルのハッシュ値を計算して保存します g_FileHashCache.RemoveAll Set cache = new MD5CacheClass cache.Scan "Folder", Empty, False cache.Save "_HashCache.txt" サンプル 保存されたファイルの内容の例 2999-12-31T00:00:00Z af7da95e0ba5ff3c49b5c11d3645db85 t10.txt 2999-12-31T00:00:00Z 4787fe8ae24c12988db6b8dbaf686b20 t11.txt 2999-12-31T00:00:00Z a461d688d013e47c4010387e7922940d t12.txt ↑W3C-DTF ↑MD5 ↑相対パス 基準は Scan 時のパス ソース → ToolsLib.vbs テスト → T_fc.vbs T_MD5Cache *********************************************************************** <<< Scan >>> *********************************************************************** Scan Sub MD5CacheClass::Scan( in_TargetPaths as Empty or string or PathDictionaryClass, in_ScanFilterPaths as Empty or string or PathDictionaryClass, in_IsCompareTimeStamp as boolean ) フォルダーに入っているファイルのハッシュ値を計算して登録します。 【引数】 in_TargetPaths スキャンする対象のパス in_ScanFilterPaths 調べるフォルダーのフィルター in_IsCompareTimeStamp タイム スタンプが変更されたときだけ再計算するかどうか in_TargetPaths が Empty のときは、Me.TargetPaths を使います。 Empty でなければ、 Me.TargetPaths を上書きします。 Me.TargetPaths と in_ScanFilterPaths の両方で指定されたファイルを、登録します。 in_ScanFilterPaths が Empty のときは、Me.TargetPaths だけを使います。 存在しないファイルは、ハッシュのリストから除外されます。 Fragment したフォルダーに対して Scan するときは、注意してください。 ソース → ToolsLib.vbs テスト → T_fc.vbs T_MD5Cache *********************************************************************** <<< Fragment >>> *********************************************************************** Fragment Sub MD5CacheClass::Fragment( in_ScanFilterPaths as Empty or string or PathDictionaryClass, ref_CopiedCache as MD5CacheClass, in_IsCheckFileHash as boolean ) 登録されているハッシュ値と同じファイルがあれば、1つを除いて削除します。 【引数】 in_ScanFilterPaths 調べるフォルダーのフィルター ref_CopiedCache ハッシュ値が登録されている別のキャッシュ in_IsCheckFileHash 削除するときにハッシュ値を再計算してチェックするかどうか "Me.Defragment" で復帰できる限り、同じ内容のファイルを削除します。 "Me" に入っているパスが指すファイルと同じ内容(同じハッシュ値)の ファイルが、"in_CopiedCache" に入っているパスが指すファイル にあるとき、"Me" に入っているパスのファイルを削除します。 "Me" に同じ内容のファイルが複数あるときも、1つを除いてファイルを削除 します。 削除されたファイルは、 Defragment で、復帰できます。 "ref_CopiedCache.DictionaryFromHash( hash )( 0 )" が指すパスにファイルが 存在するように "ref_CopiedCache.DictionaryFromHash( hash )" 配列の要素の 順番が入れ替わります。 削除する前のファイルのコピーが入ったフォルダーが ゴミ箱に入ります。 Me と in_ScanFilterPaths の両方で指定されたファイルが、削除される候補です。 in_ScanFilterPaths が Empty のときは、Me だけを使います。 ソース → ToolsLib.vbs テスト → T_fc.vbs T_MD5Cache_Fragment *********************************************************************** <<< Defragment >>> *********************************************************************** Defragment Sub MD5CacheClass::Defragment( in_ScanFilterPaths as Empty or string or PathDictionaryClass, in_CopiedCache as MD5CacheClass ) ハッシュ値が登録されているファイルがなければ、同じハッシュ値のファイルからコピーします。 【引数】 in_ScanFilterPaths 調べるフォルダーのフィルター ref_CopiedCache ハッシュ値が登録されている別のキャッシュ Me の中のハッシュ値と同じハッシュ値を持つ ref_CopiedCache の中の "in_CopiedCache.DictionaryFromHash( hash )( 0 )" が指すファイルを、 Me.TargetPaths の中にコピーすることによって、 Fragment で削除されたファイルを復帰します。 コピー先のフォルダーを指定するときは、Me.TargetPaths をコピー先のフォルダーに設定して から Defragment するか、 Load の in_TargetPaths 引数にコピー先のフォルダーを指定してから Defragment してください。 Me と in_ScanFilterPaths の両方で指定されたファイルが、コピーされる候補です。 in_ScanFilterPaths が Empty のときは、Me だけを使います。 サンプル Set cache = new MD5CacheClass cache.Load "_work\Folders_1_PartHash.txt", "_work\defragmented" Set copied_cache = new MD5CacheClass copied_cache.Load "_work\Folders_1_Hash.txt", "_work\copy" cache.Defragment Empty, copied_cache ソース → ToolsLib.vbs テスト → T_fc.vbs T_MD5Cache_Fragment *********************************************************************** <<< Delete >>> *********************************************************************** Delete Sub MD5CacheClass::Delete( in_DeletingFolderPath as string, in_MoveTargets as array of MD5CacheClass ) フォルダーを削除します。 【引数】 in_DeletingFolderPath 削除するフォルダーのパス in_MoveTargets 参照しているフラグメントがある可能性があるハッシュの辞書の配列 Fragment で削除されたファイルと同じハッシュ値のファイルが、削除しようとしているフォルダーの中 だけ(Me の中で唯一)あるときは、in_MoveTargets に指定したリストの中にある同じハッシュ値のパス に、ファイルを移動します。 in_MoveTargets に指定したリストの中にないファイルは、そのファイルと Me の中のハッシュ値を削除します。もし、in_MoveTargets に指定したリストが不足していると、 Defragment できなくなるので、注意してください。 *********************************************************************** <<< Verify >>> *********************************************************************** Verify Sub MD5CacheClass::Verify( in_ScanFilterPaths as Empty or string or PathDictionaryClass ) 存在するファイルのハッシュ値が正しいかどうかを再計算してチェックします。 【引数】 in_ScanFilterPaths 調べるフォルダーのフィルター Me に登録されているファイルのうち、存在するファイルについて、ハッシュ値が正しいかどうかを 再計算して、Me に登録されているハッシュ値と等しいことをチェックします。 等しくないファイルがあったら、そこでエラーになります。 ファイルの存在についてチェックするときは、 → CheckFileExistsAnywhereInFileList ソース → ToolsLib.vbs テスト → T_fc.vbs T_MD5Cache_Fragment *********************************************************************** <<< CheckFileExistsAnywhereInFileList >>> *********************************************************************** CheckFileExistsAnywhereInFileList Sub MD5CacheClass::CheckFileExistsAnywhereInFileList( _ in_HashFilePath as string or PathDictionaryClass of Nothing ) PathDictionaryClass 一覧ファイルに書かれたハッシュ値と、同じ内容のファイルが別に存在するかどうかをチェックします。 【引数】 in_HashFilePath ハッシュ値が書かれた一覧ファイルのパス → Save in_HashFilePath が指すパス以外に、Me が指すパスにファイルがあれば、それをコピーして復活 (Defragment)できるので、その場合はエラーにはなりません。 該当するハッシュ値を持つファイルの内容はチェックしません。 ファイルの内容をチェックするときは、 → Verify 内部では、"Me.DictionaryFromHash( hash )( 0 )" が指すパスに、ファイルが存在するように "Me.DictionaryFromHash( hash )" 配列の要素の順番が入れ替わります。 ソース → ToolsLib.vbs テスト → T_fc.vbs T_MD5Cache_Fragment *********************************************************************** <<< IsSameHashValuesOfLeafPathDictionary >>> *********************************************************************** IsSameHashValuesOfLeafPathDictionary 未確認 Sub MD5CacheClass::IsSameHashValuesOfLeafPathDictionary( arg_2ndLeafPathDictionary as string or LeafPathDictionary, in_2ndBasePath as MD5CacheClass ) LeafPathDictionary フォルダーに入っているファイルのハッシュ値のセットが、Me に登録されているものと同じか比較します。 【引数】 arg_2ndLeafPathDictionary 調べるフォルダー、または、ファイルの集合 in_2ndBasePath 調べるフォルダーのパス ソース → ToolsLib.vbs *********************************************************************** <<< MD5CacheFileClass >>> *********************************************************************** MD5CacheFileClass MD5CacheClass で管理するファイルの属性。 string .HashValue MD5 ハッシュ値 Date .TimeStamp タイムスタンプ *********************************************************************** <<< PatchAndBackUpDictionaryClass >>> *********************************************************************** PatchAndBackUpDictionaryClass PatchAndBackUpDictionaryClass は、ファイルを置き換えるパッチにおける、ファイルの一覧です。 back_up 置き換える前のファイルがある patch 置き換えた後のファイルがある あるファイル T に対する置き換える前後のファイル(B,P) は、次の相対パスP, B, T がすべて 同じという関係があります。 ・相対パスP = GetStepPath( patch.PatchPaths.Key, patch.PatchRootPath ) ・相対パスB = GetStepPath( patch.BackUpPaths.Key, patch.BackUpRootPath ) ・相対パスT = GetStepPath( full_path_T, base_path_T ) ただし、 ・patch は、PatchAndBackUpDictionaryClass のオブジェクト ・full_path_T は、パッチをあてる対象であるファイル T のフル パス ・base_path_T は、パッチをあてるときに指定する対象のベース フォルダーのパス GetStepPath メンバー .PatchRootPath パッチ フォルダーのフル パス。 置き換えた後のファイルがある。 作成する予定のパッチに入れる、パッチ フォルダーのルートのパス。 .BackUpRootPath バックアップ フォルダーのフル パス。 置き換える前のファイルがある。 作成する予定のパッチに入れる、バックアップ フォルダーのルートのパス。 .PatchPaths パッチ フォルダーにあるファイルの一覧。 → LeafPathDictionary キーは、コピー元のフル パス。 アイテムの Name は、その実体となる 存在するファイルのフル パス。 .BackUpPaths バックアップ フォルダーにあるファイルの一覧。 → LeafPathDictionary キーは、削除する前に比較するファイルのフル パス。 アイテムの Name は、その実体となる存在するファイルのフル パス。 .Copy() コピーしたオブジェクトを生成します。 関数 AttachPatchAndCheckBackUp パッチをあてます EnumerateToPatchAndBackUpDictionary フォルダーから、ファイルの一覧を生成します AttachPatchAndBackUpDictionary パッチをあてるように、ファイルの一覧を変更します MakePatchAndBackUpDictionary パッチに入れるファイルの一覧を作成します パッチが行う更新内容の確認方法 Diff ツール を使って、patch フォルダーと back_up フォルダーの差分を確認することで、 パッチが行う更新内容を確認することができます。 パッチ自体の更新内容の確認方法 SyncFilesX コマンド で、古いパッチと、新しいパッチの違いを確認することができます。 ただし、SyncFilesX では、以下のように読み替えをしてください。 ・patch フォルダー = SyncFilesX のワーク ・back_up フォルダー = SyncFilesX のベース 参考 → SyncFilesX を内部で使うツールとの比較 ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_LeafPath *********************************************************************** <<< AttachPatchAndCheckBackUp >>> *********************************************************************** AttachPatchAndCheckBackUp Sub AttachPatchAndCheckBackUp( in_PatchTargetPath as string, in_BackUpTargetPath as string, in_PatchPath as string, in_BackUpPath as string ) パッチをあてます。 【引数】 in_PatchTargetPath in_PatchPath 引数が対象とするルートのフォルダーのパス in_BackUpTargetPath in_BackUpPath 引数が対象とするルートのフォルダーのパス in_PatchPath コピー元ファイルが入った patch フォルダーのパス in_BackUpPath 削除または上書きされる前の内容が入った back_up フォルダーのパス バックアップ ファイルが同じ内容かどうかを調べるのに、 g_FileHashCache を使っています。 内部で PatchAndBackUpDictionaryClass を使っています。 ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_PatchAndBackUp_1 T_PatchAndBackUp_Moved *********************************************************************** <<< EnumerateToPatchAndBackUpDictionary >>> *********************************************************************** EnumerateToPatchAndBackUpDictionary << PatchAndBackUpDictionaryClass Function EnumerateToPatchAndBackUpDictionary( in_Path as string ) as PatchAndBackUpDictionaryClass フォルダーから、PatchAndBackUpDictionaryClass のオブジェクトを生成します。 【引数】 in_Path フォルダーのパス 返り値 パッチ ファイルの一覧 → PatchAndBackUpDictionaryClass in_Path 引数には、patch フォルダーと back_up フォルダーの両方が入っているフォルダーのパスを指定します。 返り値のキーとアイテムには、フル パスが格納されます。 patch フォルダーと back_up フォルダーのパスをそれぞれ指定するとき → MakePatchAndBackUpDictionary サンプル "target" フォルダーに、パッチ( "patch\patch" & "patch\back_up" フォルダー )をあてます。 files = Empty g_FileHashCache.RemoveAll Set patch = EnumerateToPatchAndBackUpDictionary( "patch" ) AttachPatchAndBackUpDictionary files, "target", patch, False '//(out)files CopyFilesToLeafPathDictionary files, True g_FileHashCache EnumerateToPatchAndBackUpDictionary AttachPatchAndBackUpDictionary CopyFilesToLeafPathDictionary ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_LeafPath T_PatchAndBackUp *********************************************************************** <<< MakePatchAndBackUpDictionary >>> *********************************************************************** MakePatchAndBackUpDictionary Function MakePatchAndBackUpDictionary( _ in_AttachedLeafPathDictionary as dictionary, in_RootPathInAttachedLeafPath as string, _ in_BaseLeafPathDictionary as dictionary, in_RootPathInBaseLeafPath as string, _ in_PathOfPatchAndBackUp as string ) as PatchAndBackUpDictionaryClass ファイルの一覧から、PatchAndBackUpDictionaryClass のオブジェクトを生成します。 【引数】 in_AttachedLeafPathDictionary パッチをあてた後のファイルの一覧、または、Empty in_RootPathInAttachedLeafPath パッチのルートにする、パッチをあてた後のフォルダーのパス in_BaseLeafPathDictionary パッチをあてる前のファイルの一覧、または、Empty in_RootPathInBaseLeafPath パッチのルートにする、パッチをあてる前のフォルダーのパス in_PathOfPatchAndBackUp 作成する予定の、パッチのルートのパス、または、Empty 返り値 → PatchAndBackUpDictionaryClass パッチ自体(フォルダー)は作成しません。 作成するときは、本関数を呼び出した後で、 CopyFilesToLeafPathDictionary を呼び出してください。 in_AttachedLeafPathDictionary 引数、または、in_BaseLeafPathDictionary 引数に、値が Empty の変数を 指定すると、その変数に LeafPathDictionary が格納されます。 そのキーとアイテムには、フル パスが 格納されます。 サンプル "01" フォルダーから "02" フォルダーができるパッチを "_work\Patch" フォルダーに作成します。 Set patch = MakePatchAndBackUpDictionary( _ Empty, "02", Empty, "01", _ "_work\Patch" ) CopyFilesToLeafPathDictionary patch, False '// "_work\Patch" に、パッチのフォルダーができます。 MakePatchAndBackUpDictionary CopyFilesToLeafPathDictionary サンプル "target" フォルダーに、パッチ( "patch" & "back_up" フォルダー )をあてます。 files = Empty g_FileHashCache.RemoveAll Set patch = MakePatchAndBackUpDictionary( _ Empty, "patch", Empty, "back_up", Empty ) AttachPatchAndBackUpDictionary files, "target", patch, False CopyFilesToLeafPathDictionary files, True g_FileHashCache MakePatchAndBackUpDictionary AttachPatchAndBackUpDictionary CopyFilesToLeafPathDictionary ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_LeafPath_MakePatch T_PatchAndBackUp *********************************************************************** <<< ChangeKeyOfPatchAndBackUpDictionaryToTarget >>> *********************************************************************** ChangeKeyOfPatchAndBackUpDictionaryToTarget Sub ChangeKeyOfPatchAndBackUpDictionaryToTarget( _ arg_PatchAndBackUpDictionary as PatchAndBackUpDictionaryClass, _ in_TargetPath as string or array of string ) パッチのパス .BackUpRootPath, .PatchRootPath, .BackUpPaths, .PatchPaths をあてる対象に移動します。 【引数】 arg_PatchAndBackUpDictionary パスを変更するパッチ → PatchAndBackUpDictionaryClass in_TargetPath パッチをあてる対象のフォルダーのパス 本関数は、複数のパッチをそれぞれ異なる対象フォルダーにあてることができるようにするために、主に MergePatchAndBackUpDictionary の内部から呼び出されます。 in_TargetPath に指定したフォルダーのパスに、patch.BackUpRootPath と patch.PatchRootPath が変更され ます。 ただし、patch は、arg_PatchAndBackUpDictionary 引数とします。 また、それに合わせて、 patch.BackUpPaths と patch.PatchPaths のキーを変更します。 patch.BackUpPaths と patch.PatchPaths の アイテムの Name プロパティは、パッチとバックアップのファイルを指したままであり、本関数を呼び出した 後でもパッチをあてることができます。 in_TargetPath に配列を指定すると、パッチとバックアップで、パッチをあてる対象のフォルダーが異なるとき の処理ができます。 in_TargetPath( 0 ) にはパッチに対する対象のフォルダーのパスを、in_TargetPath( 1 ) にはバックアップに対する対象のフォルダーのパスを指定します。 関数から返ると、patch.PatchRootPath と patch.BackUpRootPath は in_TargetPath( 0 ) と in_TargetPath( 1 ) の 共通するパッチをあてる対象 のフォルダーになります。 ただし、patch は、arg_PatchAndBackUpDictionary 引数とします。 サンプル パッチとバックアップで、パッチをあてる対象のフォルダーが同じとき Set patch = new PatchAndBackUpDictionaryClass patch.PatchRootPath = "C:\A\patch" Set patch.PatchPaths = EnumerateToLeafPathDictionary( patch.PatchRootPath ) patch.BackUpRootPath = "C:\A\back_up" Set patch.BackUpPaths = EnumerateToLeafPathDictionary( patch.BackUpRootPath ) ChangeKeyOfPatchAndBackUpDictionaryToTarget patch, "Target" AttachPatchAndBackUpDictionary files, patch, "Target", False CopyFilesToLeafPathDictionary patch, False PatchAndBackUpDictionaryClass EnumerateToLeafPathDictionary ChangeKeyOfPatchAndBackUpDictionaryToTarget ChangeKeyOfPatchAndBackUpDictionaryToTarget を呼び出す前後の値の例: 呼び出す前 呼び出した後 patch.PatchRootPath "C:\A\patch" "C:\Target" patch.BackUpRootPath "C:\A\back_up" "C:\Target" patch.PatchPaths.Key(0) "C:\A\patch\1.txt" "C:\Target\1.txt" patch.BackUpPaths.Key(0) "C:\A\back_up\1.txt" "C:\Target\1.txt" patch.PatchPaths.Item(0).Name "C:\A\patch\1.txt" "C:\A\patch\1.txt" patch.BackUpPaths.Item(0).Name "C:\A\back_up\1.txt" "C:\A\back_up\1.txt" サンプル パッチとバックアップで、パッチをあてる対象のフォルダーが異なるとき Set patch = new PatchAndBackUpDictionaryClass patch.PatchRootPath = "C:\A\patch" patch.PatchPaths = EnumerateToLeafPathDictionary( patch.PatchRootPath ) patch.BackUpRootPath = "C:\AA\back_up" patch.BackUpPaths = EnumerateToLeafPathDictionary( patch.BackUpRootPath ) ChangeKeyOfPatchAndBackUpDictionaryToTarget patch, Array( "Target\P", "Target\B" ) target_path = patch.PatchRootPath AttachPatchAndBackUpDictionary files, patch, target_path, False CopyFilesToLeafPathDictionary patch, False ChangeKeyOfPatchAndBackUpDictionaryToTarget ChangeKeyOfPatchAndBackUpDictionaryToTarget を呼び出す前後の値の例: 呼び出す前 呼び出した後 patch.PatchRootPath "C:\A\patch" "C:\Target" patch.BackUpRootPath "C:\AA\back_up" "C:\Target" patch.PatchPaths.Key(0) "C:\A\patch\1.txt" "C:\Target\P\1.txt" patch.BackUpPaths.Key(0) "C:\AA\back_up\1.txt" "C:\Target\B\1.txt" patch.PatchPaths.Item(0).Name "C:\A\patch\1.txt" "C:\A\patch\1.txt" patch.BackUpPaths.Item(0).Name "C:\AA\back_up\1.txt" "C:\AA\back_up\1.txt" ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_LeafPath の ChangePatchToTarget *********************************************************************** <<< MergePatchAndBackUpDictionary >>> *********************************************************************** MergePatchAndBackUpDictionary Sub MergePatchAndBackUpDictionary( _ arg_Destination as PatchAndBackUpDictionaryClass, in_TargetRootPathOfDestination as string, _ in_Source as PatchAndBackUpDictionaryClass, in_TargetRootPathOfSource as string ) PatchAndBackUpDictionaryClass のパッチをマージします。 【引数】 arg_Destination (入力) マージする前A、(出力) マージした後 → PatchAndBackUpDictionaryClass in_TargetRootPathOfDestination Empty または、arg_Destination パッチをあてる対象フォルダーのパス in_Source マージする前B → PatchAndBackUpDictionaryClass in_TargetRootPathOfSource Empty または、in_Source パッチをあてる対象フォルダーのパス arg_Destination の BackUp になくて Patch にファイルがあり、in_Source の BackUp にあって Patch にない場合は、 arg_Destination と in_Source の順にパッチをあてるとエラーになります(削除→追加と逆順なため)。 更に、arg_Destination の BackUp にあって Patch になく、in_Source の BackUp になくて Patch でもある場合は、 マージしなければ両方のパッチをアタッチできません。 arg_Destination と in_Source の両方に同じファイルに対するパッチがあり、内容が異なれば、どのようにしても、 エラーになります。 参考 → CanAttachFriendPatchAndBackUpDictionary 内部で ChangeKeyOfPatchAndBackUpDictionaryToTarget を呼び出しています。 マージした後の arg_Destination.BackUpRootPath と arg_Destination.PatchRootPath は、in_TargetRootPathOfDestination と in_TargetRootPathOfSource に 共通するパッチをあてる対象のフォルダー のパスになります。 in_TargetRootPathOfDestination と in_TargetRootPathOfSource に配列を指定することもできます。 参考 → ChangeKeyOfPatchAndBackUpDictionaryToTarget in_TargetRootPathOfDestination と in_TargetRootPathOfSource の両方が Empty にできるのは、arg_Destination と in_Source のパッチが同じフォルダーに対するパッチであるときだけです。 そのときは、マージした後の arg_Destination.BackUpRootPath と arg_Destination.PatchRootPath は、パッチをあてる対象のフォルダーでは なくなります。 片方だけ Empty にはできません。 サンプル patch_A と patch_B をマージした patch を作成し、パッチをあてます files = Empty g_FileHashCache.RemoveAll Set patch_A = EnumerateToPatchAndBackUpDictionary( "PatchA" ) Set patch_B = EnumerateToPatchAndBackUpDictionary( "PatchB" ) Set patch = patch_A.Copy() MergePatchAndBackUpDictionary patch, "Target\A", patch_B, "Target\B" target_path = patch.PatchRootPath AttachPatchAndBackUpDictionary files, patch, target_path, True '//(out)files CopyFilesToLeafPathDictionary files, True g_FileHashCache EnumerateToPatchAndBackUpDictionary MergePatchAndBackUpDictionary AttachPatchAndBackUpDictionary CopyFilesToLeafPathDictionary サンプル in_TargetRootPathOfDestination と in_TargetRootPathOfSource に配列を指定することもできます。 MergePatchAndBackUpDictionary patch_A, Array( "Target\P", "Target\B" ), _ patch_B, ( "Target\P", "Target\B" ) MergePatchAndBackUpDictionary Set patch = patch_A.Copy() ChangeKeyOfPatchAndBackUpDictionaryToTarget patch, Array( "Target\P", "Target\B" ) MergePatchAndBackUpDictionary patch, patch.PatchRootPath, patch_B, ( "Target\P", "Target\B" ) MergePatchAndBackUpDictionary patch, patch.PatchRootPath, patch_C, ( "Target\P", "Target\B" ) ChangeKeyOfPatchAndBackUpDictionaryToTarget MergePatchAndBackUpDictionary ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_PatchAndBackUp_Merge T_PatchAndBackUp_Merge_CheckToTest T_PatchAndBackUp_TwistedMerge *********************************************************************** <<< CanAttachFriendPatchAndBackUpDictionary >>> *********************************************************************** CanAttachFriendPatchAndBackUpDictionary Function CanAttachFriendPatchAndBackUpDictionary( _ in_AttachingPatch as PatchAndBackUpDictionaryClass, in_TargetRootPathOfAttaching as string, _ in_FriendPatch as PatchAndBackUpDictionaryClass, in_TargetRootPathOfFriend as string ) as integer 複数のパッチをあてるときに MergePatchAndBackUpDictionary しなければならないかどうかを調べます。 【引数】 in_AttachingPatch 先にアタッチするパッチA in_TargetRootPathOfAttaching Empty または、in_AttachingPatch パッチをあてる対象フォルダーのパス in_FriendPatch 後でアタッチするパッチF in_TargetRootPathOfFriend Empty または、in_FriendPatch パッチをあてる対象フォルダーのパス 返り値 調べた結果(下記) in_TargetRootPathOfAttaching, in_TargetRootPathOfFriend 引数について 参考 → MergePatchAndBackUpDictionary の in_TargetRootPathOfDestination 引数の説明 in_TargetRootPathOfAttaching と in_TargetRootPathOfFriend に配列を指定することもできます。 返り値について 下記のいずれかが返ります。 なお、c = get_ToolsLibConsts() です。 c.Attachable パッチA とパッチF の両方をアタッチすることができます c.CannotAttachBoth パッチA とパッチF の両方をアタッチすることはできません c.MustAttachAfterFriend パッチA とパッチF の両方をアタッチするには、先にパッチF をあてるか、 MergePatchAndBackUpDictionary する必要があります c.MustMergeWithFriend パッチA とパッチF の両方をアタッチするには、 MergePatchAndBackUpDictionary する必要があります サンプル Set patch_A = EnumerateToPatchAndBackUpDictionary( "PatchA" ) Set patch_B = EnumerateToPatchAndBackUpDictionary( "PatchB" ) state = CanAttachFriendPatchAndBackUpDictionary( patch_A, "Target\A", patch_B, "Target\B" ) If state = c.MustAttachAfterFriend or state = c.MustMergeWithFriend Then Set patch = patch_A.Copy() MergePatchAndBackUpDictionary patch, "Target\A", patch_B, "Target\B" End If CanAttachFriendPatchAndBackUpDictionary ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_PatchAndBackUp_Merge *********************************************************************** <<< AttachPatchAndBackUpDictionary >>> *********************************************************************** AttachPatchAndBackUpDictionary << PatchAndBackUpDictionaryClass Sub AttachPatchAndBackUpDictionary( in_out_LeafPathDictionary as dictionary of NameOnlyClass, in_PatchAndBackUpDictionary as PatchAndBackUpDictionaryClass or string, in_RootPathInLeafPath as string, _ in_out_Options as boolean or ThreeWayMergeOptionClass ) パッチをあてるように、ファイルの一覧を変更します 【引数】 in_out_LeafPathDictionary 変更されるファイル パスの一覧 → LeafPathDictionary in_PatchAndBackUpDictionary パッチ(パッチ ファイルの一覧) → PatchAndBackUpDictionaryClass in_RootPathInLeafPath パッチを当てる対象のルートのパス in_out_Options オプション(下記)、通常 True ファイルのコピーを実際にするときは、AttachPatchAndBackUpDictionary で変更した後(変数の中でパッチを あてた後) CopyFilesToLeafPathDictionary を呼び出します。 その関数の中で、 ThreeWayMerge を行います。 in_out_LeafPathDictionary 引数と in_PatchAndBackUpDictionary 引数のキーとアイテムには、フル パスを 格納しておいてください。 in_PatchAndBackUpDictionary 引数に文字列型の値を指定すると、内部で EnumerateToPatchAndBackUpDictionary を呼び出します。 in_out_Options に boolean 型を指定したときは、バックアップ ファイルが同じ内容でなければエラーにするか どうかを指定したことになります。 True を指定すると、バックアップにあるファイルが対象のフォルダーに ないときでもエラーになります。 ThreeWayMergeOptionClass を指定することもできます。 手動でパッチをあてるときは、 UpdateModule コマンド を使います。 バックアップ ファイルが同じ内容かどうかを調べるのに、 g_FileHashCache を使っています。 バックアップ ファイルがあるフォルダーに対応するプロジェクト内のフォルダーと、パッチ ファイルがある フォルダーに対応するプロジェクト内のフォルダーが異なるときは、 ChangeKeyOfPatchAndBackUpDictionaryToTarget の in_TargetPath 引数に配列を指定することで、 プロジェクト内のフォルダーをそろえてください。 in_out_LeafPathDictionary 引数に値が Empty の変数を指定すると、その変数に LeafPathDictionary が格納されます。 in_RootPathInLeafPath が指すフォルダーに、in_PatchAndBackUpDictionary のパッチを あてたファイルの一覧が格納されます。 そのキーとアイテムには、フル パスが格納されます。 サンプル → EnumerateToPatchAndBackUpDictionary のサンプル 参考 → SyncFilesX を内部で使うツールとの比較 ソース → ToolsLib.vbs テスト → T_LeafPath.vbs T_LeafPath T_LeafPath_CheckBackUp T_PatchAndBackUp → T_ModuleAssort.vbs T_LeafPathMerge → CopyFilesToLeafPathDictionary のテスト *********************************************************************** <<< タブ文字 >>> *********************************************************************** タブ文字 ChangeHeadSpaceToTab 行頭の空白文字をタブ文字に変換します ChangeHeadTabToSpace 行頭のタブ文字を空白文字に変換します ChangeMiddleSpaceToTab 行頭以外の空白文字をタブ文字に変換します ChangeMiddleTabToSpace 行頭以外のタブ文字を空白文字に変換します テスト → T_ChangeTabSpace フォルダ *********************************************************************** <<< ChangeHeadSpaceToTab >>> *********************************************************************** ChangeHeadSpaceToTab ToolsLib.vbs (src) Sub ChangeHeadSpaceToTab( ReadStream as TextStream, WriteStream as TextStream, TabSize as integer ) 行頭の空白文字をタブ文字に変換します。 【引数】 ReadStream 変換前のテキスト・ファイル・ストリーム → StartReplaceObj::r WriteStream 変換後のテキスト・ファイル・ストリーム → StartReplaceObj::w TabSize 1つのタブ文字あたりの空白文字の数 *********************************************************************** <<< ChangeHeadTabToSpace >>> *********************************************************************** ChangeHeadTabToSpace ToolsLib.vbs (src) Sub ChangeHeadTabToSpace( ReadStream as TextStream, WriteStream as TextStream, TabSize as integer ) 行頭のタブ文字を空白文字に変換します。 【引数】 ReadStream 変換前のテキスト・ファイル・ストリーム → StartReplaceObj::r WriteStream 変換後のテキスト・ファイル・ストリーム → StartReplaceObj::w TabSize 1つのタブ文字あたりの空白文字の数 サンプル Set rep = StartReplace( "in\sample.c", "out\sample.c", True ) ChangeHeadTabToSpace rep.r, rep.w, 4 rep.Finish *********************************************************************** <<< ChangeMiddleSpaceToTab >>> *********************************************************************** ChangeMiddleSpaceToTab ToolsLib.vbs (src) Sub ChangeMiddleSpaceToTab( ReadStream as TextStream, WriteStream as TextStream, TabSize as integer ) 行頭以外の空白文字をタブ文字に変換します。 【引数】 ReadStream 変換前のテキスト・ファイル・ストリーム → StartReplaceObj::r WriteStream 変換後のテキスト・ファイル・ストリーム → StartReplaceObj::w TabSize 1つのタブ文字あたりの空白文字の数 *********************************************************************** <<< ChangeMiddleTabToSpace >>> *********************************************************************** ChangeMiddleTabToSpace ToolsLib.vbs (src) Sub ChangeMiddleTabToSpace( ReadStream as TextStream, WriteStream as TextStream, TabSize as integer ) 行頭以外のタブ文字を空白文字に変換します。 【引数】 ReadStream 変換前のテキスト・ファイル・ストリーム → StartReplaceObj::r WriteStream 変換後のテキスト・ファイル・ストリーム → StartReplaceObj::w TabSize 1つのタブ文字あたりの空白文字の数 *********************************************************************** <<< SetBreakByPath (デバッグ) >>> *********************************************************************** SetBreakByPath (デバッグ) SetBreakByFName (デバッグ) Sub SetBreakByPath( in_Path as string, in_Count as integer ) Sub SetBreakByFName( in_Path as string ) 指定した名前のファイルをライトするときにブレークさせます。 【引数】 in_Path ブレークするファイル名 in_Count 何回目のライトでブレークするか。 Empty = 毎回 g_debug ≧ 1 のときだけブレークします。 vbslib の関数(copy、del、OpenForWrite など)ではない(g_fs.CopyFile など)関数によって ライトしたときはブレークしません。 サンプル SetBreakByFName "Out.txt" '// TODO: ソース → vbslib.vbs テスト → T_Debug フォルダ 関連 → SetupDebugTools *********************************************************************** <<< IsWriteAccessDenied >>> *********************************************************************** IsWriteAccessDenied (src) Function IsWriteAccessDenied( ErrNumber as integer, Path as string, FolderOrFile as bitfield, in_out_nRetry as integer ) 負荷が高いときに発生する書き込み拒否エラーに対処します。 【引数】 ErrNumber チェックするエラーコード Path アクセスしたパス FolderOrFile F_File または F_Folder または F_File or F_Folder in_out_nRetry (入出力) 再試行回数 返り値 書き込み拒否エラーが発生したかどうか VBScript (Windows) では、ファイルがロックされたときだけでなく、ディスク・アクセスの負荷が 高くなると、書き込み拒否エラー(エラーコード 70)が発生します。 このエラーに対処しないと、 スクリプトによる自動実行が中断されてしまいます。 IsWriteAccessDenied は、書き込み拒否 エラーによってスクリプトが中断されないように、再試行するスクリプトの記述を補助します。 vbslib が提供するファイル操作機能は、書き込み拒否エラーが発生しないように対処されて いるため、IsWriteAccessDenied を呼び出す必要はありません。 参考 → E_WriteAccessDenied → ファイルの負荷が高いとスクリプトが中断してしまう Windows (Web) サンプル: 高負荷状態でも使える CreateTextFile Dim f, path, n_retry, en, ed n_retry = 0 Do On Error Resume Next Set f = g_fs.CreateTextFile( path ) en = Err.Number : ed = Err.Description : On Error GoTo 0 If not IsWriteAccessDenied( en, path, F_File, n_retry ) Then Exit Do Loop If en <> 0 Then Err.Raise en,,ed path path 書き込み拒否エラー(エラーコード 70)が発生する可能性があるものの例 g_fs.CopyFile, g_fs.CopyFolder, g_fs.MoveFile, g_fs.MoveFolder g_fs.DeleteFolder, g_fs.CreateFolder g_fs.CreateTextFile, g_fs.OpenTextFile File::Name への代入による改名, ADODBStream::SaveToFile キーワード: g_FileSystemRetryMSec 再試行ユーザーインターフェース g_FileSystemMaxRetryMSec コマンドプロンプト(cscript.exe)で動く vbslib で、書き込み拒否エラーが発生したら、 次の警告を表示して、グローバル変数 g_FileSystemRetryMSec に指定した時間(ミリ秒) (通常4秒)だけ Sleep します。 グローバル変数 g_FileSystemMaxRetryMSec に指定した 時間(ミリ秒)(通常60秒)だけ再試行したら、書き込み拒否エラーを発生させます。 再試行は、IsWriteAccessDenied の内部では行いません。 参考:下記サンプル。 ウィンドウ(wscript.exe)で動く vbslib で、書き込み拒否エラーが発生したら、次の警告を 表示して [ 再試行 ] か [ キャンセル ] を選ぶメッセージボックスが表示されます。 ユーザーが入力するまで自動実行は一時停止します。 書き込みできません。 [再試行] [キャンセル] テスト → T_File_c_Manually.vbs → T_File_w_Manually.vbs → T_Replace_target.vbs # T_FromLock → T_Copy.vbs # T_CopyLocked → T_File.vbs # T_OverwriteFolderFile *********************************************************************** <<< SetReadOnlyAttribute >>> *********************************************************************** SetReadOnlyAttribute Sub SetReadOnlyAttribute( in_Path as string or Folder or File, in_IsReadOnly ) 指定のファイル、または、指定のフォルダーの中にあるすべてのファイルの、読み取り専用属性を変更します。 【引数】 in_Path 読み取り専用属性を変更するファイルのパス 読み取り専用属性を変更するファイルが入ったフォルダーのパス 読み取り専用属性を変更する File オブジェクト 読み取り専用属性を変更するファイルが入ったフォルダーの Folder オブジェクト サンプル SetReadOnlyAttribute "C:\Folder", False ソース → vbslib.vbs テスト → T_File.vbs T_GetReadOnlyList 関連 → GetReadOnlyList → File::Attributes *********************************************************************** <<< SetFilesToReadOnly >>> *********************************************************************** SetFilesToReadOnly 注意 この仕様は削除される予定です。 代わり → SetReadOnlyAttribute Sub SetFilesToReadOnly( in_Folder as string or Folder ) フォルダーの中にあるすべてのファイルを、読み取り専用にします。 【引数】 in_Folder 読み取り専用に設定するファイルが入ったフォルダーの Folder オブジェクト サンプル SetFilesToReadOnly "C:\Folder" ソース → vbslib.vbs 関連 → SetFilesToNotReadOnly → SetFileToReadOnly → SetFileToNotReadOnly → File::Attributes → GetReadOnlyList *********************************************************************** <<< SetFilesToNotReadOnly >>> *********************************************************************** SetFilesToNotReadOnly 注意 この仕様は削除される予定です。 代わり → SetReadOnlyAttribute Sub SetFilesToNotReadOnly( in_Folder as string or Folder ) フォルダーの中にあるすべてのファイルを、読み取り専用ではなくします。 【引数】 in_Folder 読み取り専用を解除するファイルが入ったフォルダーの Folder オブジェクト サンプル SetFilesToNotReadOnly "C:\Folder" ソース → vbslib.vbs 関連 → SetFilesToReadOnly *********************************************************************** <<< SetFileToReadOnly >>> *********************************************************************** SetFileToReadOnly 注意 この仕様は削除される予定です。 代わり → SetReadOnlyAttribute Sub SetFileToReadOnly( in_File as string or File ) ファイルを読み取り専用にします。 【引数】 in_File 読み取り専用に設定する File オブジェクト サンプル SetFileToReadOnly "C:\Folder\File.txt" ソース → vbslib.vbs 関連 → SetFileToNotReadOnly → SetFilesToReadOnly *********************************************************************** <<< SetFileToNotReadOnly >>> *********************************************************************** SetFileToNotReadOnly 注意 この仕様は削除される予定です。 代わり → SetReadOnlyAttribute Sub SetFileToNotReadOnly( in_File as string or File ) ファイルを読み取り専用ではなくします。 【引数】 in_File 読み取り専用を解除する File オブジェクト サンプル SetFileToNotReadOnly "C:\Folder\File.txt" ソース → vbslib.vbs 関連 → SetFileToReadOnly → SetFilesToReadOnly *********************************************************************** <<< BinaryArray クラス、バイナリーファイル >>> *********************************************************************** BinaryArray クラス、バイナリーファイル (src) バイナリー・ファイルのデータを扱いやすくするクラスです。 ファイルを配列のように扱うことができます。 ファイル: System.vbs 関連 → Byte 配列 (VBScript) サンプル バイナリーファイルからリード。Unicode 形式のテキストファイルかどうか判定する Set bin = ReadBinaryFile( "unicode_sample.txt" ) If bin(0) = &hFF and bin(1) = &hFE Then echo "This is unicode file." End If ReadBinaryFile バイナリーファイルへライト。 Unicode 形式のテキストファイル 「む(=0x3080)」 を作る Set bin = new BinaryArray bin.Size = 4 bin(0) = &hFF '// low byte of BOM bin(1) = &hFE '// high byte of BOM bin(2) = &h80 '// low byte of hiragana mu bin(3) = &h30 '// high byte of hiragana mu bin.Save "unicode_sample.txt" .Size .Save バイナリーファイルの変更。 Unicode テキスト・ファイルの先頭に 「は(=0x306F)」 を追加する Set bin = new BinaryArray bin.Load "unicode_sample.txt" strbin = bin.Read( Empty, Empty ) strbin = LeftB( strbin, 2 ) + ChrB( &h6F ) + ChrB( &h30 ) + MidB( strbin, 3 ) bin.Write strbin, 0, Empty bin.Save "unicode_sample.txt" .Load .Read .Write .Save LeftB, MidB, RightB, LenB, AscB, ChrB は、文字列操作関数のバイナリ版です。 バイナリーファイルを構造化してリードする Dim bin, out, size bin.Write &h10, Empty, Array( &h12, &h34, &h56, &h78, &h9A, &hBC, &hDE ) size = bin.ReadStruct( &h10, out, Array( "a", vbByte, "b", vbInteger+vbArray, 3 ) ) '// out("a") = &h12 '// out("b")(0) = &h5634 '// out("b")(1) = &h9A78 '// out("b")(2) = &hDEBC .Write .ReadStruct バイナリーデータを作成する Set bin = new_BinaryArray( Array( &h42, &h4D ) ) バイナリーデータをダンプ表示する echo_v new_BinaryArrayAsText( "漢字", Empty ).xml メンバー .Item 配列の要素。 配列番号。 (デフォルト・プロパティ) .Size 配列の要素数。 バイト・サイズ .Length 配列の要素数。 バイト・サイズ .Count 配列の要素数。 バイト・サイズ .ReDim_ 配列の要素数を変更します。 ReDim Preserve と同じです。 .Load ファイルの内容を、配列に入力します。 .Save 配列の内容を、ファイルに出力します。 .Read 配列の内容の一部を、Byte 配列にして返します。 .Write 配列の内容の一部を、変更します。 .ReadStruct 配列の内容の一部を、構造化した辞書を取得します。 .WriteStruct 構造化した配列を使って、バイナリ配列の内容の一部にライトします。 .WriteFromBinaryArray 配列の内容の一部をコピーします。 .WriteFromDump .ToEmpty 配列を空にします。 配列要素数は 0 になります。 .UBound_ 配列の最大要素番号を返します。 .xml 配列のすべての要素を文字列にします。 ダンプします。 テスト → T_Binary フォルダ 関連 → ADODB.Stream → OpenForReadRIFF → OpenForWriteRIFF *********************************************************************** <<< new_BinaryArray >>> *********************************************************************** new_BinaryArray Function new_BinaryArray( IntegerArray as array of integer ) as BinaryArray バイナリ配列を生成します。 【引数】 IntegerArray バイナリーの内容に相当する配列。 数値型または Byte 配列 返り値 生成されたバイナリ配列 ソース → System.vbs サンプル Set bin = new_BinaryArray( Array( &h42, &h4D ) ) binary = bin_1.Read( &h10, &h28 ) echo_v GetEchoStr( new_BinaryArray( binary ) ) 関連 → ReadBinaryFile *********************************************************************** <<< new_BinaryArrayFromFile >>> *********************************************************************** new_BinaryArrayFromFile Function new_BinaryArrayFromFile( Path as string ) as BinaryArray バイナリ・ファイルからバイナリ配列を生成します。 【引数】 Path バイナリ・ファイルのパス 返り値 生成されたバイナリ配列 ソース → System.vbs 関連 → Load (BinaryArray) → ReadBinaryFile *********************************************************************** <<< new_BinaryArrayFromBase64 >>> *********************************************************************** new_BinaryArrayFromBase64 Function new_BinaryArrayFromBase64( Base64_Text as string ) as BinaryArray Base64 でエンコードされた文字列からバイナリ配列を生成します。 【引数】 Base64_Text Base64 でエンコードされた文字列 返り値 生成されたバイナリ配列 ソース → System.vbs テスト → T_Binary.vbs Test_of_Base64 サンプル Set bin = new_BinaryArrayFromBase64( "EjRWeA==" ) 関連 → Base64 (BinaryArray) *********************************************************************** <<< new_BinaryArrayAsText >>> *********************************************************************** new_BinaryArrayAsText Function new_BinaryArrayAsText( Text as string, CharacterSet as string ) as BinaryArray 文字列から指定した文字コードセットのバイナリ・データを持つバイナリ配列を生成します。 【引数】 Text 文字列 CharacterSet 文字コードセット、Empty を指定すると "Unicode" 返り値 生成されたバイナリ配列 Unicode の場合、バイナリ配列の先頭に BOM (FF FE) が入ります。 EUC-JP 形式の文字列が格納されたバイナリ配列を生成します。 サンプル Set bin = new_BinaryArrayAsText( "漢字", "EUC-JP" ) サンプル 文字列の中のすべての文字コード(Unicode)を表示します。 echo_v new_BinaryArrayAsText( "漢字", Empty ).xml ソース → System.vbs テスト → T_Binary.vbs T_Binary_TextCharacterSet 関連 → Text (BinaryArray) → new_TextFileCharSetStack 文字コードセット一覧 → AssertString 文字列が異なっていたら Diff ツールを開きます *********************************************************************** <<< Item、配列番号 (BinaryArray) >>> *********************************************************************** Item、配列番号 (BinaryArray) (src) Default Property BinaryArray::Item( i as integer ) as integer 配列番号を使って、バイナリ配列の要素を参照します。 (デフォルト・プロパティ) 【引数】 i 配列の要素の番号。 先頭は 0 1バイトずつアクセスします。 サンプル Dim bin : Set bin = new BinaryArray bin.Load "a.bin" echo bin(0) '// bin.Item(0) と同じ bin(0) = &h30 bin(0) bin(0) *********************************************************************** <<< Size, Length, Count (BinaryArray) >>> *********************************************************************** Size, Length, Count (BinaryArray) Property BinaryArray::Size as integer Property BinaryArray::Length as integer Property BinaryArray::Count as integer バイナリ配列の要素数。 バイト・サイズ 値を設定すると、配列のサイズが変化します。 大きくなった部分の値は、0x00 になります。 小さくなった部分は削除されます。 サンプル Dim bin : Set bin = new BinaryArray bin.Load "a.bin" bin.Size = bin.Size + 1 bin.Save "a_plus1.bin" Size Size *********************************************************************** <<< ReDim_ (BinaryArray) >>> *********************************************************************** ReDim_ (BinaryArray) (src) Sub BinaryArray::ReDim_( UBound as integer ) バイナリ配列の要素数(=バイトサイズ)を変更します。 ReDim Preserve と同じです。 【引数】 UBound 新しい配列の最大要素番号 ReDim の末尾にアンダースコアが付いています。 (ReDim は予約語であるため。) *********************************************************************** <<< Load (BinaryArray) >>> *********************************************************************** Load (BinaryArray) Sub BinaryArray::Load( Path as string ) ファイルの内容を、バイナリ配列に入力します。 【引数】 Path ファイルのパス バイナリ配列に元々入っていた内容は無くなります。 関連 → ReadBinaryFile → new_BinaryArrayFromFile *********************************************************************** <<< Save (BinaryArray) >>> *********************************************************************** Save (BinaryArray) Sub BinaryArray::Save( Path as string ) バイナリ配列の内容を、ファイルに出力します。 【引数】 Path ファイルのパス サンプル Dim i Dim bin : Set bin = new BinaryArray bin.ReDim_ &hFF For i=0 To &hFF : bin(i) = i : Next bin.Save "a.bin" *********************************************************************** <<< Read (BinaryArray) >>> *********************************************************************** Read (BinaryArray) (src) Function BinaryArray::Read( Offset as integer, Length as integer ) as array of Byte array of Byte バイナリ配列の内容の一部を、Byte 配列にして返します。 【引数】 Offset 配列の中で抽出する部分の先頭の位置。 配列の先頭から = 0 Length 配列の中で抽出する部分の長さ(バイト)。 -1 = 最後まで 返り値 配列の内容の一部を抽出した Byte 配列 → Byte 配列 Offset = 0 または Empty にすると、配列の先頭からになります。 Length = -1 または Empty にすると、配列の最後までになります。 返り値に、文字列関数 LeftB, MidB, RightB, LenB, AscB, ChrB を使うことができます。 返り値に対して + 演算子は使えませんが、MidB( ByteArray, 1 ) などで String 型に変換 すれば、+ 演算子が使えます。 サンプル binary = bin.Read( &h10, &h28 ) echo AscB( MidB( binary, 3, 1 ) ) サンプル → バイナリ・ファイルの変更 関連 → ReadStruct (BinaryArray) → Write (BinaryArray) → Read (ADODB.Stream) *********************************************************************** <<< Write (BinaryArray) >>> *********************************************************************** Write (BinaryArray) (src) Sub BinaryArray::Write( Offset as integer, Length as integer, ByteArray as variant ) バイナリ配列の内容の一部を、変更します。 【引数】 Offset 配列の中で変更する部分の先頭の位置。 配列の先頭から = 0 Length 配列の中で変更する部分の長さ(バイト)。 -1 = ByteArray 引数の全体 ByteArray 変更内容が格納された文字列(UTF-16)、または配列、または数値 Offset = 0 または Empty にすると、配列の先頭からになります。 Length = -1 または Empty にすると、配列の最後までになります。 サンプル bin.Write 0, Empty, Array( &h42, &h4D ) bin.Write 0, 2, ChrB( &h42 ) + ChrB( &h4D ) bin.Write 1, 1, &h4D サンプル → バイナリ・ファイルの変更 関連 → Read (BinaryArray) → WriteStruct (BinaryArray) → ConvertToByteArray (ADODBConsts) *********************************************************************** <<< ReadStruct (BinaryArray) >>> *********************************************************************** ReadStruct (BinaryArray) (src) Function BinaryArray::ReadStruct( Offset as integer, out_Dic as dictionary, FormatArray as integer ) as integer バイナリ配列の内容の一部をリードした内容を、構造化した辞書を取得します。 【引数】 Offset 配列の中で抽出する部分の先頭の位置。 配列の先頭から = 0 out_Dic (出力) 数値の辞書。 キーは FormatArray に指定したもの。 FormatArray バイナリ配列から抽出する部分の型の集合 (下記) 返り値 抽出した部分のバイナリの大きさ(バイト) サンプル Dim bin, out, size bin.Write &h10, Empty, Array( &h12, &h34, &h56, &h78, &h9A, &hBC, &hDE ) size = bin.ReadStruct( &h10, out, Array( "a", vbByte, "b", vbInteger+vbArray, 3 ) ) '// out("a") = &h12 '// out("b")(0) = &h5634 '// out("b")(1) = &h9A78 '// out("b")(2) = &hDEBC &h10 out "a", vbByte, "b", vbInteger+vbArray, 3 FormatArray 引数 out_Dic (辞書型) に格納するキーの名前と、値の型を、順番に並べた配列を指定します。 vbInteger などの型に +vbArray したときは、配列をリードします。 このとき、更に配列の 要素数を指定してください。 要素数を -1 にすると、ファイルの最後までリードします。 下記の c は、ADODBConsts です。 vbByte 1バイト、符号なし、0〜255 vbInteger 2バイト、符号あり、-32768〜32767, &h0000〜&hFFFF vbInteger + c.Unsigned 2バイト、符号なし、Long型、0〜65535 vbLong 4バイト、符号あり、-2147483648〜2147483647、&h10000〜&hFFFFFFFF * + vbArray 配列。 vbByte などの型に vbArray をプラスしてください。 FormatArray には、配列の要素数も指定してください。 要素数を -1 にすると、ファイルの最後までリードします。 関連 → WriteStruct (BinaryArray) → Read (BinaryArray) *********************************************************************** <<< WriteStruct (BinaryArray) >>> *********************************************************************** WriteStruct (BinaryArray) (src) Sub BinaryArray::WriteStruct( Offset as integer, FormatAndDataArray as array ) 構造化した配列を使って、バイナリ配列の内容の一部に、バイナリーデータをライトします。 【引数】 Offset バイナリ配列の中で変更する範囲の先頭位置。 配列の先頭から = 0 FormatAndDataArray バイナリ配列へライトする部分の型とライトする値の集合 (下記) サンプル bin.WriteStruct 0, Array( vbByte, Array( &h12, &h34, &h56, &h78 ) ) '// bin = 0x0000 : 12 34 56 78 バイナリ配列 bin の 0 の位置に、vbByte型(8ビット整数型)の 0x12、0x34、0x56、0x78 を格納します。 bin.WriteStruct &h40, Array( vbByte, &h12, vbInteger, Array( &h5634, &h9A78, &hDEBC ) ) '// bin = 0x0040 : 12 34 56 78 9A BC DE バイナリ配列 bin の 0x40 の位置に、vbByte型(8ビット整数型)の 0x12 と、vbInteger型(16ビット 整数型)の 0x5634, 0x9A78, 0xDEBC を格納します。 FormatAndDataArray 引数 「値の型」 要素と、「値、または、値を並べた配列」 要素を繰り返す配列を指定します。 vbByte 1バイト、符号なし、0〜255 vbInteger 2バイト、符号あり、-32768〜32767, &h0000〜&hFFFF vbInteger + c.Unsigned 2バイト、符号なし、Long型、0〜65535 vbLong 4バイト、符号あり、-2147483648〜2147483647、&h10000〜&hFFFFFFFF 関連 → Write (BinaryArray) → new_BinaryArray → ReadStruct (BinaryArray) → ConvertToStructuredByteArray (ADODBConsts) *********************************************************************** <<< WriteFromBinaryArray (BinaryArray) >>> *********************************************************************** WriteFromBinaryArray (BinaryArray) (src) Sub BinaryArray::WriteFromBinaryArray( WriteOffset as integer, ReadBinaryArray as BinaryArray, ReadOffset as integer, Size as integer ) バイナリ配列の一部を別のバイナリ配列に、高速にコピーします。 【引数】 Me コピー先となるバイナリ配列 WriteOffset Me の中で変更する範囲の先頭位置。 配列の先頭から = 0 ReadBinaryArray コピー元となるバイナリ配列 ReadOffset ReadBinaryArray の中の範囲の先頭位置。 配列の先頭から = 0 Size コピーするサイズ(バイト), -1=最後まで ReadBinaryArray のサイズより大きな値を Size 引数に指定したときは、最後までコピーします。 *********************************************************************** <<< WriteFromDump (BinaryArray) >>> *********************************************************************** WriteFromDump (BinaryArray) Sub BinaryArray::WriteFromDump( in_Offset as integer, in_Dump as string ) 文字列にダンプされたバイナリーデータを、バイナリ配列の内容の一部に、ライトします。 【引数】 in_Offset バイナリ配列の中で変更する範囲の先頭位置。 配列の先頭から = 0 in_Dump バイナリーデータをダンプした文字列 in_Dump 引数の中の、16進数と | 演算子以外は無視されます。 16進数は、接頭辞 0x を付けるか、 接頭辞を付けないでください。 | 演算子は、論理和です。 無視される文字を除き、16進数が連続すると次のデータであるとして処理します。 16進数の桁数がに応じて、整数のビット数が異なります。 2, 4, 8 桁なら、リトル エンディアンの 8, 16, 32 ビット整数になります。 サンプル bin.WriteFromDump 0, "12 34 56 78" '// bin = 0x0000 : 12 34 56 78 バイナリ配列 bin の 0 の位置に、vbByte型(8ビット整数型)の 0x12、0x34、0x56、0x78 を、格納します。 bin.WriteFromDump %h10, "0x05 | 0x14, 0x1234, 0x98765432" '// bin = 0x0010 : 15 34 12 32 54 76 98 ソース → System.vbs テスト → T_Binary.vbs T_Binary_FromDump *********************************************************************** <<< Compare (BinaryArray) >>> *********************************************************************** Compare (BinaryArray) Function BinaryArray::Compare( ThanBinary as BinaryArray ) バイナリ配列を比較します。 【引数】 ThanBinary 比較対象のバイナリ配列 返り値 一致=0、StrComp と同じ ソース → System.vbs テスト → T_Binary.vbs 関連 → Byte 配列(バイナリ)の内容を比較する *********************************************************************** <<< SwapEndian (BinaryArray) >>> *********************************************************************** SwapEndian (BinaryArray) Sub BinaryArray::SwapEndian( Offset as integer, Size as integer, SwapUnitSize as integer ) バイナリ配列の一部のエンディアンを逆にします。 【引数】 Offset エンディアンを逆にする範囲の先頭オフセット Size エンディアンを逆にする範囲のサイズ(バイト) SwapUnitSize 逆にする単位 サンプル '// bin = 12 34 56 78 9A BC DE bin.SwapEndian &h2, &h4, 2 '// bin = 12 56 34 9A 78 BC DE バイナリ配列 bin の 0x2 の位置から始まる 4バイトの範囲を、2バイト単位(2バイト整数)で逆にします。 ソース → System.vbs テスト → T_Binary.vbs *********************************************************************** <<< ToEmpty (BinaryArray) >>> *********************************************************************** ToEmpty (BinaryArray) Sub BinaryArray::ToEmpty() 配列を空にします。 配列要素数は 0 になります。 *********************************************************************** <<< UBound_ (BinaryArray) >>> *********************************************************************** UBound_ (BinaryArray) (src) Property Get BinaryArray::UBound_() as integer 配列の最大要素番号を返します。 UBound の末尾にアンダースコアが付いています。 (UBound をオーバーライドすると、BinaryArray が実装できなくなるため。) *********************************************************************** <<< xml (BinaryArray) >>> *********************************************************************** xml (BinaryArray) (src) Property Get BinaryArray::xml() as string 配列のすべての要素を文字列にします。 出力例: FF FE 6F 30 80 30 *********************************************************************** <<< MD5 (BinaryArray) >>> *********************************************************************** MD5 (BinaryArray) Property Get BinaryArray::MD5() as string Property Get BinaryArray::SHA1() as string Property Get BinaryArray::SHA256() as string Property Get BinaryArray::SHA384() as string Property Get BinaryArray::SHA512() as string Property Get BinaryArray::RIPEMD160() as string バイナリー・データ(配列の全体)に対する ハッシュ値。 なお、ファイルのハッシュ値は、 GetHash コマンド でも確認できます。 ファイルの内容が異なれば、ハッシュ値も異なります。 内容が異なるのにハッシュ値が 同じになる(衝突する)確率はわずかにありますが、実用的には問題ありません。 ファイルの内容のごく一部だけ変えたときは、衝突しません。 なぜなら、衝突させるには、 ハッシュ アルゴリズムによって決まる法則で、ファイルの内容の全体を合わせる必要が あるからです。 MD5 ハッシュ値は、0〜9, a〜f の文字が32文字の文字列になります。 SHA-1 ハッシュ値は、0〜9, a〜f の文字が40文字の文字列になります。 SHA-256 ハッシュ値は、0〜9, a〜f の文字が64文字の文字列になります。 SHA-384 ハッシュ値は、0〜9, a〜f の文字が96文字の文字列になります。 SHA-512 ハッシュ値は、0〜9, a〜f の文字が128文字の文字列になります。 RIPEMD-160 ハッシュ値は、0〜9, a〜f の文字が40文字の文字列になります。 SHA-256, SHA-384, SHA-512, RIPEMD-160 は、Windows Vista 以降で使えます。 サンプル echo ReadBinaryFile( "Sample.zip" ).MD5 5c1d447971bc0c49f09b2e965ac4ed37 … 表示例 注意 バイナリ ファイルのハッシュ値を計算するときは、 GetHashOfFile をお使い ください。 ReadBinaryFile は、データをすべてリードしてからハッシュ値を計算 するため、メモリー不足が発生する可能性があります。 ソース → System.vbs テスト → T_Binary.vbs 関連 → MD5 → ハッシュ値 → GetHash コマンド → GetHashOfFile → MD5 リスト → 空のフォルダーの MD5 → new_BinaryArrayAsText 文字列からハッシュ値を得る場合 → PowerShell - MD5を計算する → g_FileHashCache キーワード: SHA1, SHA-1, SHA256, SHA-256, SHA384, SHA-384, SHA512, SHA-512, RIPEMD160, RIPEMD-160 *********************************************************************** <<< GetVersionString サンプル >>> *********************************************************************** GetVersionString サンプル zip などのパッケージ・ファイルのバージョンを MD5 から判定するソース・コードのサンプル を示します。 Sub Main() Set c = g_VBS_Lib path = InputPath( "zipファイルのパス >", c.CheckFileExists ) echo GetVersionString( path ) End Sub Dim g_VersionDataBase : g_VersionDataBase = Array(_ "c28bae2972d4e9c9f90ed1861f0b8002", "vbslib, 4.00, 2012-07-02",_ "700af264a9f00733b4d26f0407625d5b", "vbslib, 4.01, 2013-02-14" ) Function GetVersionString( Path ) If IsArray( g_VersionDataBase ) Then _ Set g_VersionDataBase = Dict( g_VersionDataBase ) value_of_MD5 = ReadBinaryFile( Path ).MD5 If g_VersionDataBase.Exists( value_of_MD5 ) Then GetVersionString = g_VersionDataBase( value_of_MD5 ) Else GetVersionString = "Unknown" End If End Function 関連 → MD5 (BinaryArray) → GetHash *********************************************************************** <<< Base64 (BinaryArray) >>> *********************************************************************** Base64 (BinaryArray) Property Get BinaryArray::Base64() as string バイナリー・データ(配列の全体)に対する Base64 でエンコードされた文字列。 ソース → System.vbs テスト → T_Binary.vbs Test_of_Base64 サンプル Set bin = new_BinaryArrayFromBase64( "EjRWeA==" ) echo bin.Base64 参考 → Base64 関連 → new_BinaryArrayFromBase64 → Base64 コマンド *********************************************************************** <<< Text (BinaryArray) >>> *********************************************************************** Text (BinaryArray) Function BinaryArray::Text( CharacterSet as string ) as string バイナリー・データを指定した文字コードセットの文字列とし、VBScript の文字列を返します。 サンプル Set shift_JIS_bin = new_BinaryArray( Array( &h8A, &hBF, &h8E, &h9A ) ) Assert shift_JIS_bin.Text( "Shift-JIS" ) = "漢字" ソース → System.vbs テスト → T_Binary.vbs T_Binary_TextCharacterSet 関連 → new_BinaryArrayAsText VBScript の文字列を指定した文字コードセットに変える → new_TextFileCharSetStack 文字コードセット一覧 *********************************************************************** <<< GetHashOfFile >>> *********************************************************************** GetHashOfFile Function GetHashOfFile( in_Path as string, in_HashType as string ) as string ファイルのハッシュ値を計算します。 内部で ADODB か Power Shell を使います。 【引数】 in_Path ハッシュ値を計算するファイルのパス in_HashType ハッシュ値の種類 返り値 ファイルのハッシュ値 in_HashType 引数に指定できる値は、"MD5", "SHA1", "SHA256", "SHA384", "SHA512", "RIPEMD160" です。 内部の ADODB でメモリー不足が発生したら、Power Shell を使用します。 サンプル echo GetHashOfFile( "A.bin", "MD5" ) ソース → System.vbs 関連 → GetHashPS 関数 → GetHash コマンド *********************************************************************** <<< GetHashPS >>> *********************************************************************** GetHashPS Function GetHashPS( in_Path as string, in_HashType as string ) as string ファイルのハッシュ値。 内部で Power Shell 使用。 【引数】 in_Path ハッシュ値を計算するファイルのパス in_HashType ハッシュ値の種類 返り値 ファイルのハッシュ値 in_HashType 引数に指定できる値は、"MD5", "SHA1", "SHA256", "SHA384", "SHA512", "RIPEMD160" です。 サンプル echo GetHashPS( "A.bin", "MD5" ) ソース → System.vbs *********************************************************************** <<< OpenForReadRIFF >>> *********************************************************************** OpenForReadRIFF Function OpenForReadRIFF( in_Path as string ) as RIFF_Reader RIFF 形式バイナリーファイルのリードを開始します。 【引数】 in_Path 入力ファイルのパス 返り値 内容をリードするときに使うオブジェクト WAV, AVI などの形式の一部にあたる、ツリー構造を持ったチャンクによって構成される バイナリーデータ形式をリードします。 参考 → RIFF 形式 サンプル Set bin = OpenForReadRIFF( "riff.bin" ) Set chunk = bin.ReadFirstChild() '// chunk as RIFF_ChunkClass Assert chunk.FourCC = "Set " Assert bin.Stack( 0 ).FourCC = "Root" Assert bin.Stack( 1 ).FourCC = "Set " Set chunk = bin.ReadFirstChild() Assert chunk.FourCC = "Elem" Assert chunk.Size = 5 Assert not chunk.IsExistChild Assert not chunk.IsExistNextSibling bin.ReadStruct data, Array( _ "a", vbByte+vbArray, 3, "b", vbInteger ) ) Assert data("a")(0) = &h41 Assert data("a")(1) = &h42 Assert data("a")(2) = &h43 Assert data("b") = &h4544 '// リトルエンディアン bin.ReturnToParent Set chunk = bin.ReadNextSibling() Assert chunk.FourCC = "Elm2" ReadFirstChild RIFF_ChunkClass ReadStruct ReturnToParent ReadNextSibling 上記のスクリプトは、下記のツリー構造をたどっています。 RIFF( 'Root' LIST( 'Set ' 'Elem'( &h41, &h42, &h43, &h44, &h45 ) ) 'Elm2'( &h58, &h59, &h5A ) ) ソース → System.vbs テスト → T_Binary.vbs *********************************************************************** <<< SeekChunkByIndexes (RIFF_Reader) >>> *********************************************************************** SeekChunkByIndexes (RIFF_Reader) Function RIFF_Reader::SeekChunkByIndexes( in_Empty as Empty, in_Indexes0_Array as array of integer ) as RIFF_ChunkClass インデックス番号で指定したチャンクにジャンプして、リードします。 【引数】 in_Empty Empty = ルート チャンクからたどる in_Indexes0_Array インデックス番号の配列 返り値 リードしたチャンクに関する情報 サンプル Set chunk = a_RIFF.SeekChunkByIndexes( Empty, Array( 2, 0 ) ) in_Indexes0_Array 引数の位置関係: RIFF チャンク Array( ) 要素チャンク Array( 0 ) 要素チャンク Array( 1 ) LIST チャンク Array( 2 ) 要素チャンク Array( 2, 0 ) 要素チャンク Array( 2, 1 ) ソース → System.vbs テスト → T_Binary.vbs T_RIFF_SeekChunkByIndexes *********************************************************************** <<< ReadFirstChild (RIFF_Reader) >>> *********************************************************************** ReadFirstChild (RIFF_Reader) Function RIFF_Reader::ReadFirstChild() as RIFF_ChunkClass 現在位置にあるリスト チャンクの、子チャンクのヘッダーをリードします。 【引数】 返り値 リードした子チャンクに関する情報 RIFF_ChunkClass ::IsExistChild = False のときに呼び出すとエラーになります。 *********************************************************************** <<< ReadNextSibling (RIFF_Reader) >>> *********************************************************************** ReadNextSibling (RIFF_Reader) Function RIFF_Reader::ReadNextSibling() as RIFF_ChunkClass 現在位置の次の兄弟チャンクのヘッダーをリードします。 【引数】 返り値 リードした兄弟チャンクに関する情報 RIFF_ChunkClass ::IsExistNextSibling = False のときに呼び出すとエラーになります。 *********************************************************************** <<< ReadStruct (RIFF_Reader) >>> *********************************************************************** ReadStruct (RIFF_Reader) Function RIFF_Reader::ReadStruct( out_Dic as dictionary, FormatArray as integer ) as integer 現在位置のチャンクの内容をリードし、辞書に格納します。 【引数】 out_Dic (出力) チャンクの内容が入った辞書 FormatArray バイナリ配列から抽出する部分の型の集合 返り値 抽出した部分のバイナリの大きさ(バイト) 参考 → ReadStruct (BinaryArray) *********************************************************************** <<< ReturnToParent (RIFF_Reader) >>> *********************************************************************** ReturnToParent (RIFF_Reader) Function RIFF_Reader::ReturnToParent() as RIFF_ChunkClass 現在位置を親チャンクに移動します。 【引数】 返り値 親チャンクに関する情報 *********************************************************************** <<< RIFF_ChunkClass >>> *********************************************************************** RIFF_ChunkClass チャンクのヘッダーをリードして得られたチャンクに関する情報。 .Offset チャンクの先頭の位置。 0 が先頭 .FourCC チャンクの名前に相当する FourCC (4文字の文字列) .Size チャンクに入っているデータのサイズ(バイト) .IsExistChild 子チャンクがあるかどうか .IsExistNextSibling 次の兄弟チャンクがあるかどうか *********************************************************************** <<< OpenForWriteRIFF >>> *********************************************************************** OpenForWriteRIFF Function OpenForWriteRIFF( in_Path as string, in_RootFourCC as string ) as RIFF_Writer RIFF 形式バイナリーファイルのライトを開始します。 【引数】 in_Path 出力ファイルのパス in_RootFourCC ルートチャンクの名前に相当する FourCC (4文字の文字列) 返り値 内容をライトするときに使うオブジェクト WAV, AVI などの形式の一部にあたる、ツリー構造を持ったチャンクによって構成される バイナリーデータ形式を作成します。 参考 → RIFF 形式 サンプル Set w_=AppKey.NewWritable( "." ).Enable() Set bin = OpenForWriteRIFF( "riff.bin", "Root" ) bin.WriteLIST "Set " bin.WriteChunk "Elem" bin.WriteStruct Array( vbByte, Array( &h41, &h42, &h43 ) ) bin.WriteStruct Array( vbInteger, Array( &h4544 ) ) bin.WriteEnd '// End of "Elem" chunk bin.WriteEnd '// End of "Set " chunk bin.WriteChunk "Elm2" bin.WriteStruct Array( vbByte, Array( &h58, &h59, &h5A ) ) bin = Empty WriteLIST WriteChunk WriteStruct WriteEnd 上記のスクリプトは、以下のバイナリーファイルを作ります。 52 49 46 46 2A 00 00 00 52 6F 6F 74 4C 49 53 54 12 00 00 00 53 65 74 20 45 6C 65 6D 05 00 00 00 41 42 43 44 45 00 45 6C 6D 32 03 00 00 00 58 59 5A 00 RIFF 0x0000002A Root LIST 0x00000012 Set Elem 0x00000005 0x41 0x42 0x43 0x44 0x45 Elm2 0x00000003 0x58, 0x59, 0x5A RIFF( 'Root' LIST( 'Set ' 'Elem'( &h41, &h42, &h43, &h44, &h45 ) ) 'Elm2'( &h58, &h59, &h5A ) ) ソース → System.vbs テスト → T_Binary.vbs *********************************************************************** <<< WriteLIST (RIFF_Writer) >>> *********************************************************************** WriteLIST (RIFF_Writer) << OpenForWriteRIFF Sub RIFF_Writer::WriteLIST( in_FourCC as string ) リスト チャンクのヘッダーを出力します。 【引数】 in_FourCC 出力するリスト チャンクの名前に相当する FourCC (4文字の文字列) 次は、 WriteLIST か WriteChunk のどちらかのチャンクのヘッダーをライトします。 リストを終了するときは、 WriteEnd を呼び出してください。 *********************************************************************** <<< WriteChunk (RIFF_Writer) >>> *********************************************************************** WriteChunk (RIFF_Writer) Sub RIFF_Writer::WriteLIST( in_FourCC as string ) リスト以外のチャンクのヘッダーを出力します。 【引数】 in_FourCC 出力するチャンクの名前に相当する FourCC (4文字の文字列) 次は、 WriteStruct でライトします。 *********************************************************************** <<< WriteStruct (RIFF_Writer) >>> *********************************************************************** WriteStruct (RIFF_Writer) Sub RIFF_Writer::WriteStruct( FormatAndDataArray as array ) 構造化した配列を使って、現在のチャンクに、バイナリーデータをライトします。 【引数】 FormatAndDataArray バイナリ配列へライトする部分の型とライトする値の集合 参考 → WriteStruct (BinaryArray) 連続して WriteStruct を呼び出すと、同じチャンクの中の続きをライトします。 WriteEnd でチャンク(のサイズ)を確定します。 *********************************************************************** <<< WriteEnd (RIFF_Writer) >>> *********************************************************************** WriteEnd (RIFF_Writer) Sub RIFF_Writer::WriteEnd() チャンクのサイズを確定します。 現在のチャンクのライトを終了したときに呼び出します。 本関数は、 WriteChunk または WriteLIST でライトしたチャンクのヘッダーの一部にある サイズ情報の部分に、適切な値をライトします。 本関数を呼び出した後で、 WriteLIST か WriteChunk のどちらかを呼び出したときは、 WriteEnd を呼び出す前のチャンクの親の兄弟のチャンクがライトされます。 ルートのチャンクになるまで、WriteEnd を呼び出す必要はありません。 RIFF_Writer クラス のオブジェクトが削除されるタイミングで、足りなかった WriteEnd 呼び出しを内部で自動 的に行い、OpenForWriteRIFF 関数の引数に指定したファイルに出力します。 *********************************************************************** <<< WritePadding (RIFF_Writer) >>> *********************************************************************** WritePadding (RIFF_Writer) Sub RIFF_Writer::WritePadding( in_FourCC as string, in_Alignment as integer ) 次のバイナリーデータのアラインメントを揃えるために、パディングするチャンクをライトします。 【引数】 in_FourCC パディングをするチャンクの FourCC in_Alignment アラインメント 下記の data のアラインメントを揃えるために、下記の 'Pad ' チャンクをライトします。 : 'Pad ' FourCC ... ライトする範囲の最初 padding_size padding ... ライトする範囲の最後 'Data' FourCC ... WritaStruct 関数でライト data_size data ... アラインメントが揃う位置 参考 → チャンクの中のデータの先頭をアラインメントするには *********************************************************************** <<< g_FileHashCache >>> *********************************************************************** g_FileHashCache ファイルのハッシュ値(MD5)のキャッシュ。 キーはフル パス、アイテムはハッシュ値(リード オンリー)である辞書。 プロセス起動後、初めて指定されたファイルのときだけ、ハッシュ値を計算します。 大量のファイルを何度も比較するときに使うと、高速になります。 Assert g_FileHashCache( "C:\A.txt" ) = "9060587edeb01a63e3d3edc959678d1e" g_FileHashCache に入るオブジェクトは、ToolsLib.vbs を include するときに作成されます。 キーがフォルダーのパスのときのアイテムは、"Folder" です。 ただし、フォルダーが空のときは、"EmptyFolder" です。 キーがファイルやフォルダーのパスではないときのアイテムは、"" です。 ファイルの変更があったときは、Remove メソッド、RemoveAll メソッドでキャッシュを破棄してください。 g_FileHashCache.RemoveAll g_FileHashCache.Remove "File.txt" ハッシュ値の計算と、ファイルのコピーを同時にするときは、CopyRenFile を呼び出します。 g_FileHashCache.CopyRenFile "Source.txt", "Destination.txt" ファイルの削除と同時に、キャッシュを更新するときは、DeleteFile を呼び出します。 g_FileHashCache.DeleteFile "File.txt" 参考 → MD5 (BinaryArray) ソース → ToolsLib.vbs FileHashCacheClass テスト → T_LeafPath.vbs T_FileHashCache *********************************************************************** <<< バイナリ混在テキスト生成 (txt2bintxt.exe) >>> *********************************************************************** バイナリ混在テキスト生成 (txt2bintxt.exe) txt2bintxt.exe は、VBScript で、一部がバイナリになっているテキストファイルを 作成できるようにする変換ツールです。 ダウンロード → txt2bintxt.zip バイナリになっている行は、行頭に Chr(&hFF) を出力してください。 f.WriteLine "123" f.WriteLine Chr(&hFF)+"EF BB BF 0D 0A" f.WriteLine "123" EF BB BF 0D 0A EF BB BF は、UTF-8 の BOM です。 こうして出力したファイルを、in.txt として、 txt2bintxt.exe in.txt out.txt を実行すると、out.txt は次のようになります。 123 ・ソ 123 31 32 33 0D 0A EF BB BF 0D 0A 31 32 33 0D 0A ・ソ EF BB BF 0D 0A out.txt (テキスト表現) out.txt (バイナリ表現) 不要になった入力ファイル(in.txt) は、別途削除してください。 関連 → new_TextFileCharSetStack BOM 付きテキストファイル → BinaryArray クラス バイナリ・ファイル・アクセス *********************************************************************** <<< Txt2BinTxt >>> *********************************************************************** Txt2BinTxt (src) Sub Txt2BinTxt( SrcPath as string, DstPath as string ) 参考 → バイナリ混在テキスト生成 (txt2bintxt.exe) *********************************************************************** <<< get_ADODBConsts >>> *********************************************************************** get_ADODBConsts (src) Function get_ADODBConsts() as ADODBConsts ADODB モジュールの定数をメンバーに持つオブジェクトを返します。 ファイル: System.vbs サンプル Dim c : Set c = get_ADODBConsts() t = f.Read( c.adReadAll ) ADODBConsts が定義する定数 adReadAll, adReadLine, adTypeBinary, adTypeText adModeRead, adModeWrite, adModeReadWrite adSaveCreateOverWrite adCRLF, adLF, Keep バイト配列を作成する関数 ConvertToByteArray ConvertToStructuredByteArray バイト配列と整数の間で変換する関数 BytesToShortInt BytesToUShortIntToLongInt BytesToLongInt ShortIntToBytes LongIntToUShortIntToBytes LongIntToBytes 関連 → ADODB.Stream *********************************************************************** <<< ConvertToByteArray (ADODBConsts) >>> *********************************************************************** ConvertToByteArray (ADODBConsts) (src) Function ADODBConsts::ConvertToByteArray( ByteArray as variant, Offset as integer, Size as integer ) as array of Byte 文字列や配列や数値を、バイト配列に変換します。 【引数】 ByteArray 文字列、または配列、または数値 Offset 返り値の先頭となる ByteArray の中の位置。先頭=0 Size ByteArray の中から返り値にするサイズ(バイト)。最後まで=-1 返り値 Write (ADODB.Stream) に渡せる Byte 配列 ファイル: System.vbs サンプル Dim binary, stream Dim c : Set c = get_ADODBConsts() binary = c.ConvertToByteArray( ChrB( &h42 ) + ChrB( &h4D ), 0, Empty ) stream.Write binary binary = c.ConvertToByteArray( &h4D, 1, Empty ) 参考 → Write (BinaryArray) テスト → T_Binary フォルダ *********************************************************************** <<< ConvertToStructuredByteArray (ADODBConsts) >>> *********************************************************************** ConvertToStructuredByteArray (ADODBConsts) (src) Function ADODBConsts::ConvertToStructuredByteArray( FormatAndDataArray as array ) as array of Byte 構造化した配列を、バイト配列に変換します。 【引数】 FormatAndDataArray バイナリ配列へライトする部分の型とライトする値の集合 返り値 Write (ADODB.Stream) に渡せる Byte 配列 参考 → WriteStruct (BinaryArray) 構造化した配列、FormatAndDataArray 引数の説明 テスト → T_Binary フォルダ *********************************************************************** <<< BytesToShortInt >>> *********************************************************************** BytesToShortInt (src) Function ADODBConsts::BytesToShortInt( b0, b1, b2, b3 as integer ) as integer 2バイトのバイナリ・データを、-32768(&h8000)〜32767(&h7FFF) の整数に変換します。 サンプル c.BytesToShortInt( &hFE, &hFF ) = &hFFFE *********************************************************************** <<< BytesToUShortIntToLongInt >>> *********************************************************************** BytesToUShortIntToLongInt (src) Function ADODBConsts::BytesToUShortIntToLongInt( b0, b1, b2, b3 as integer ) as integer 2バイトのバイナリ・データを、0〜65535 の整数に変換します。 サンプル c.BytesToUShortIntToLongInt( &hFE, &hFF ) = 65534 *********************************************************************** <<< BytesToLongInt >>> *********************************************************************** BytesToLongInt (src) Function ADODBConsts::BytesToLongInt( b0, b1, b2, b3 as integer ) as integer 4バイトのバイナリ・データを、Long 型整数に変換します。 サンプル c.BytesToLongInt( &h78, &h56, &h34, &h12 ) = &h12345678 c.BytesToLongInt( AscB( b ), AscB( MidB( b, 2, 1 ) ), _ AscB( MidB( b, 3, 1 ) ), AscB( RightB( b, 1 ) ) ) *********************************************************************** <<< ShortIntToBytes >>> *********************************************************************** ShortIntToBytes (src) Function ADODBConsts::ShortIntToBytes( Value as integer ) as array of integer -32768(&h8000)〜32767(&h7FFF) の整数を、2バイトの配列に変換します。 &h0000〜&h7FFF(Integer型)、&h10000〜 &h7FFFFFFF(Long型) は、正の整数です。 &h8000〜&hFFFF(Integer型)、&h80000000〜(Long型) は、負の整数です。 サンプル c.ShortIntToBytes( &hFEFF ) = Array( &hFF, &hFE ) *********************************************************************** <<< LongIntToUShortIntToBytes >>> *********************************************************************** LongIntToUShortIntToBytes (src) Function ADODBConsts::LongIntToUShortIntToBytes( Value as integer ) as array of integer 0〜65535 の整数を、2バイトの配列に変換します。 サンプル c.LongIntToUShortIntToBytes( 65534 ) = Array( &hFE, &hFF ) *********************************************************************** <<< LongIntToBytes >>> *********************************************************************** LongIntToBytes (src) Function ADODBConsts::LongIntToBytes( Value as integer ) as array of integer 整数を、4バイトの配列に変換します。 サンプル c.LongIntToBytes( &h12345678 ) = Array( &h78, &h56, &h34, &h12 ) *********************************************************************** <<< ADODB.Stream 関連 >>> *********************************************************************** ADODB.Stream 関連 *********************************************************************** <<< ADODB_Stream_loadFromFile >>> *********************************************************************** ADODB_Stream_loadFromFile Sub ADODB_Stream_loadFromFile( Stream as ADODB.Stream, Path as string ) エラーメッセージを適切にした ADODB.Stream.LoadFromFile 。 参考 → LoadFromFile (ADODB.Stream) ソース → vbslib.vbs テスト → T_fc.vbs T_IsSameBinaryFile_ReadWriteLock *********************************************************************** <<< (複数行) ArrayFromLines >>> *********************************************************************** (複数行) ArrayFromLines Function ArrayFromLines( lines as string ) as Array of string 複数行からなる文字列のうち、それぞれの行を要素とした配列を返します。 【引数】 lines 複数行からなる文字列 返り値 それぞれの行を要素とした配列 改行文字は、CR+LF でも LF でもどちらでも構いません。 サンプル For Each line In ArrayFromLines( "ABC"+ vbCRLF +"DEF" ) Next "ABC"+ vbCRLF +"DEF" 上記 ArrayFromLines の返り値は、Array( "ABC", "DEF" ) サンプル VBScript a_array = ArrayFromLines( Trim2( root.selectSingleNode( _ "./Lines/text()" ).nodeValue ) ) Trim2 selectSingleNode Lines nodeValue a_array は、Array( "Line (1)", "Line (2)" ) になります。 XML Line (1) Line (2) ソース → vbslib.vbs テスト → T_Lines.vbs 関連 → StringStream クラス → FindStringLines → SortStringLines *********************************************************************** <<< セクション化されたテキスト >>> *********************************************************************** セクション化されたテキスト 複数のセクションに分けたテキストファイルを扱います。 CreateFromTextSections セクション化されたテキストを集めてファイルを作成します ReadTextSections セクション化されたテキストを集めた文字列を返します OpenForWriteTextSection セクション化されたテキストを編集します 関連 → 構造化テキストフォーマット → セクション化されたソースファイル (Module Mixer) → MultiTextXML_Class *********************************************************************** <<< CreateFromTextSections >>> *********************************************************************** CreateFromTextSections Sub CreateFromTextSections( in_XML_Path as string, in_XML_Root as IXMLDOMElement, in_CreateFilePath as string, in_MixedTextXPath as string, in_Empty as Empty ) セクション化されたテキストを集めてファイルを作成します。 【引数】 in_XML_Path TextSection タグがある XML ファイルのパス in_XML_Root Empty、または、in_XML_Path の XML の要素オブジェクト in_CreateFilePath 作成するファイルのパス in_MixedTextXPath 下記の MixedText タグがある XML 要素の XPath、基準は in_XML_Root in_Empty Empty、または、オプション(下記) 返り値 セクション化されたテキストを集めたテキスト in_XML_Root に Empty を指定すると、内部で LoadXML ( in_XML_Path, Empty ) を呼び出します。 その分、 処理時間がかかります。 in_XML_Root の中にある Variable タグの変数 は、TextSection タグの path 属性に指定できます。 in_Empty に get_ToolsLibConsts().DeleteIfNoSection を指定すると、MixedText タグの中の TextSection タグ が1つも無いときに、in_CreateFilePath のファイルが削除されます。 参考 → CreateFromTextSections コマンド テキスト、MixedText タグのサンプル CreateFile タグに指定されたすべてのファイルを作成する。 サンプル CreateFromTextSections "SettingA.xml", Empty, Empty, Empty, Empty CreateFile タグに指定されたすべてのファイルを作成する。 サンプル CreateFromTextSections "SettingA.xml", Empty, "_out.txt", "#C_Type", Empty CreateFromTextSections "SettingA.xml", Empty, "_out.txt", "/MixedText[@id='C_Type']", Empty ソース → ToolsLib.vbs テスト → T_TextSection.vbs T_CreateFromTextSections 関連 → CreateFromTextSections コマンド → ReadTextSections 関数 *********************************************************************** <<< ReadTextSections >>> *********************************************************************** ReadTextSections Function ReadTextSections( in_XML_Root as IXMLDOMElement, in_MixedTextXPath as string, in_VariablesForPath as string, in_Variables as LazyDictionaryClass, in_Empty as Empty ) セクション化されたテキストを集めた文字列を返します。 【引数】 in_XML_Root in_MixedSettingXPath の基準となる XML要素(タグ) in_MixedTextXPath 下記の MixedText タグがある XML 要素の XPath、基準は in_XML_Root in_XML_FilePath アドレスの基準となる XML ファイルのパス in_VariablesForPath Empty または path 属性に評価するときに使う辞書 → LazyDictionaryClass in_Empty Empty を指定してください 返り値 セクション化されたテキストを集めたテキスト in_XML_Root の中にある Variable タグの変数 と、in_VariablesForPath 引数の変数は、TextSection タグの path 属性に指定できます。 参考 → CreateFromTextSections コマンド テキストのサンプル SettingB.xml の XML 属性から参照する MixedText タグからセクションを集める。 サンプル SettingB.xml mixed_text SettingA.xml VBScript xml_path = "SettingB.xml" Set xml_root = LoadXML( xml_path, Empty ) text = ReadTextSections( xml_root, "/MixedText[@id='mixed_1']", xml_path, Empty, Empty ) ReadTextSections VBScript Set linker = new LinkedXMLs linker.XmlTagNamesHavingIdName = Array( "MixedText" ) xml_path = "SettingB.xml" Set xml_root = LoadXML( xml_path, Empty ) linker.StartNavigation xml_path, xml_root Set mixed_text_tag = linker.GetLinkTargetNode( xml_root.getAttribute( "mixed_text" ) ) text = ReadTextSections( mixed_text_tag, ".", linker.TargetXmlPath, Empty, Empty ) linker.EndNavigation LinkedXMLs "SettingB.xml" "mixed_text" ReadTextSections ソース → ToolsLib.vbs テスト → T_TextSection.vbs T_ReadTextSections 関連 → CreateFromTextSections コマンド → CreateFromTextSections 関数 *********************************************************************** <<< MakeCrossedOldSections >>> *********************************************************************** MakeCrossedOldSections Sub MakeCrossedOldSections( in_OutFolderPath as string, _ in_NewFolderPath as string or PathDictionaryClass, in_OldFolderPath as string, _ in_NewTxscPath as string, in_OldTxscPath as string, in_Option as Empty ) 新しいセクションの構成に合わせるように、古い内容のセクションを集めます。 【引数】 in_OutFolderPath 出力ファイルを格納するフォルダーのパス in_NewFolderPath 新しいセクションの構成を持つファイルが入ったフォルダーのパス in_OldFolderPath 古い内容のセクションを持つファイルが入ったフォルダーのパス in_NewTxscPath in_NewFolderPath の中間ファイルを格納するフォルダーのパス in_OldTxscPath in_OldFolderPath の中間ファイルを格納するフォルダーのパス in_Option Empty を指定してください in_NewFolderPath 引数に PathDictionaryClass のオブジェクトを指定できます。 in_NewFolderPath 引数に指定したファイルに対応する出力ファイルが in_OutFolderPath 引数に指定 したフォルダーに格納されます。 中間ファイルは、 MakeTextSectionIndexFile が出力するセクション インデックス ファイルです。 サンプル Out New Old A.txt A.txt X.txt /* Title: Section_A_1 */ This is old Section-A-1. /* Title: Section_A_1 */ New A-1. New A-2. /* Title: Section_A_1 */ This is old Section-A-1. /* Title: Section_B_2 */ This is old Section-B-2. /* Title: Section_A_2 */ This is old Section-A-2. /* Title: Section_A_2 */ B.txt B.txt Y.txt /* Title: Section_B_1 */ This is old Section-B-1. /* Title: Section_B_2 */ This is old Section-B-2. /* Title: Section_B_1 */ New B-1. /* Title: Section_B_2 */ New B-2. /* Title: Section_B_1 */ This is old Section-B-1. /* Title: Section_A_2 */ This is old Section-A-2. New フォルダーにある A.txt と同じ名前のファイルを、Out フォルダーに作成します。 その内容は、 New フォルダーにある A.txt のセクションの構成(順序)、すなわち、Section_A_1、Section_A_2 の 順になります。 セクションの名前は、 MakeTextSectionIndexFile が入力する形式で記述します。 現在は、 Natural Docs 形式のみ対応しています。 それぞれセクションの内容は、Old フォルダーに ある、すべてのファイルの中から検索して見つかったセクションをコピーした内容になります。 ソース → ToolsLib.vbs テスト → T_TextSection.vbs T_MakeCrossedOldSections → T_CrossedOld フォルダー 関連 → DoTextShrink → NaturalDocs → ModuleAssort *********************************************************************** <<< MakeTextSectionIndexFile >>> *********************************************************************** MakeTextSectionIndexFile Sub MakeTextSectionIndexFile( Path as string or PathDictionaryClass, TagTypeName as string, BeforeRootFullPath as string, AfterRootFullPath as string ) タグが付いたファイルから、セクション インデックス ファイルを更新します。 【引数】 Path セクション化されたテキスト ファイルのパス、または、 PathDictionaryClass TagTypeName タグのタイプ、"NaturalDocs" を指定してください → Natural Docs SectionTypeName 出力ファイルの中の type 属性に入れる文字列 BeforeRootFullPath セクション化されたテキストのルート・フォルダーのパス AfterRootFullPath セクション インデックス ファイル(.txsc) のルート・フォルダーのパス .txsc ファイルのタイムスタンプの方が新しいときは、更新をせず、高速に処理します。 BeforeRootFullPath 引数と AfterRootFullPath 引数に、テキスト ファイルとインデックス ファイルのある場所 の関係を指定します。 BeforeRootFullPath 引数、AfterRootFullPath 引数に Empty を指定すると、カレント フォルダーを指定した ときと同じ処理をします。 BeforeRootFullPath 引数、AfterRootFullPath 引数の詳細は、 → ReplaceRootPath サンプル *.txsc ファイルを作成する MakeTextSectionIndexFile "*.c", "NaturalDocs", "C_Type", Empty, Empty サンプル _txsc\(ファイル名.拡張子).txsc の例 TagTypeName = "NaturalDocs" の場合の Sample.c の例 /*********************************************************************** * Function: StartA ************************************************************************/ void StartA() { } /*********************************************************************** * Function: StartB ************************************************************************/ void StartB() { } 参考 → TextStream::Line ソース → ToolsLib.vbs コールツリー MakeTextSectionIndexFile (.vbs) MakeTextSectionIndexFile (.c) 内部で vbslib_helper.exe を呼び出しています。 End of File MakeNaturalComments_C_Language → NaturalDocs 関連の構文解析 g_NaturalDocsKeywords (src) config->AdditionalKeywords テスト → T_TextSection.vbs T_MakeTxScFile *********************************************************************** <<< ConnectInTextSectionIndexFile >>> *********************************************************************** ConnectInTextSectionIndexFile Sub ConnectInTextSectionIndexFile( in_IndexFilePath as string, in_KeywordAndName as array of array of string, in_Empty as Empty ) セクション インデックス ファイルの中の指定したセクションを前のセクションとつなげる。 【引数】 in_IndexFilePath セクション インデックス ファイルのパス in_KeywordAndName 前のセクションとつなげるセクションのキーワードと名前の配列 in_Empty Empty を指定してください サンプル _txsc\(ファイル名.拡張子).txsc の例 上記 TextSection タグをつなげるスクリプト: ConnectInTextSectionIndexFile "Sample.c", Array( Array( "Function", "StartB" ) ) つなげた後の.txsc ファイルの例: *********************************************************************** <<< OpenForWriteTextSection >>> *********************************************************************** OpenForWriteTextSection Function OpenForWriteTextSection( SourcePath as string, DestinationPath as string, Option_ as Empty ) as WriteTextSectionClass セクション化されたテキストの編集を開始します。 【引数】 SourcePath 編集前のセクション化されたテキスト・ファイルのパス DestinationPath 編集した結果を出力するファイルのパス、または、Empty Option_ Empty を指定してください 返り値 → WriteTextSectionClass 返り値のオブジェクトの参照カウンターが 0 になったら、ファイルに出力されます。 サンプル file.txt ファイルの中の、"Section1" を含むセクションを削除します。 Set file = OpenForWriteTextSection( "file.txt", Empty, Empty ) file.Cut "Section1" file = Empty WriteTextSectionClass → Cut (WriteTextSectionClass) セクションを削除します。 → PickUp (WriteTextSectionClass) 残すセクションを選択します。 ソース → ToolsLib.vbs テスト → T_TextSection.vbs 関連 → 構造化テキストフォーマット (Module Mixer) セクション化されたテキスト → UsesSection (Mxp_Symbol) *********************************************************************** <<< Cut (WriteTextSectionClass) >>> *********************************************************************** Cut (WriteTextSectionClass) Sub WriteTextSectionClass::Cut( Key as string ) セクションを削除します。 【引数】 Key セクションの中に含まれる文字列 ソース → ToolsLib.vbs *********************************************************************** <<< PickUp (WriteTextSectionClass) >>> *********************************************************************** PickUp (WriteTextSectionClass) Sub WriteTextSectionClass::PickUp( Key as string ) 残すセクションを選択します。 【引数】 Key セクションの中に含まれる文字列 本関数を1度でも呼び出すと、WriteTextSectionClass のオブジェクトの参照カウンターが 0 になったとき、選択されなかったセクションはすべて削除されます。 本関数を1度も呼び出さなかったときは、すべてのセクションが残ります。 ソース → ToolsLib.vbs *********************************************************************** <<< .ini ファイル >>> *********************************************************************** .ini ファイル 下記の形式のテキストファイルで記述された設定値を扱います。 [SectionX] SettingA = abc SettingB = 12 ; comment [SectionY] SettingA = BC セクション名は省略可能 空行も可能 行末までのコメント記号は、行頭のみ対応 → ParseIniFileLine → GetIniFileTextValue → SetIniFileTextValue → RenumberIniFileData 関連 → OpenForRegFile *********************************************************************** <<< ParseIniFileLine >>> *********************************************************************** ParseIniFileLine Function ParseIniFileLine( Line as string ) as ParsedIniFileLineClass .ini ファイルに書かれた行を解析します。 【引数】 Line .ini ファイルの中の1行 返り値 解析結果 [ ] で囲まれた行は、セクション名として解析します。 = がない行は、コメント行として解析します。 ParsedIniFileLineClass .Section セクション名 .Name 左辺 .Value 右辺 サンプル Set line = ParseIniFileLine( "[Section1]" ) '// line.Section = "Section1" '// line.Name = Empty '// line.Value = Empty Set line = ParseIniFileLine( "Name = Value" ) '// line.Section = Empty '// line.Name = "Name" '// line.Value = "Value" Set line = ParseIniFileLine( "Name =" ) '// line.Section = Empty '// line.Name = "Name" '// line.Value = "" Set line = ParseIniFileLine( "comment" ) '// line.Section = Empty '// line.Name = Empty '// line.Value = Empty ソース → vbslib.vbs テスト → T_IniFile.vbs T_GetIniFileTextValue *********************************************************************** <<< GetIniFileTextValue >>> *********************************************************************** GetIniFileTextValue [ 親: .ini ファイル ] Function GetIniFileTextValue( IniText as string, SectionName as string, VariableName as string, Option_ as Empty ) as string .ini ファイルに書かれた設定値を参照します。 【引数】 IniText .ini ファイルの内容 SectionName セクション名、セクションがないファイルでは=Empty VariableName 変数名 Option_ Empty を指定してください 返り値 変数の設定値 該当する変数が存在しないときは、Empty が返ります。 サンプル Assert GetIniFileTextValue( text, Empty, "NameA", Empty ) = "Value" Assert GetIniFileTextValue( text, "SectionB", "NameA", Empty ) = "Value" ソース → vbslib.vbs テスト → T_IniFile.vbs T_GetIniFileTextValue 関連 → SetIniFileTextValue → GetIniFileTextValues *********************************************************************** <<< GetIniFileTextValues >>> *********************************************************************** GetIniFileTextValues Function GetIniFileTextValues( IniText as string, SectionName as string, VariableName as string, Option_ as Empty ) as array of string .ini ファイルに書かれた設定値を複数参照します。 【引数】 IniText .ini ファイルの内容 SectionName セクション名、セクションがないファイルでは=Empty VariableName 変数名 Option_ Empty を指定してください 返り値 変数の設定値の配列 該当する変数が存在しないときは、空の配列が返ります。 サンプル Assert IsSameArray( GetIniFileTextValues( text, "Section", "NameA", Empty ), _ Array( "Value1", "Value2" ) ソース → vbslib.vbs テスト → T_IniFile.vbs T_GetIniFileTextValue *********************************************************************** <<< SetIniFileTextValue >>> *********************************************************************** SetIniFileTextValue [ 親: .ini ファイル ] Function SetIniFileTextValue( IniText as string, SectionName as string, VariableName as string, Value as Variant, Option_ as Empty ) as string .ini ファイルに書かれた設定値を変更します。 【引数】 IniText 変更前の .ini ファイルの内容 SectionName セクション名、セクションがないファイルでは=Empty VariableName 変数名 Value 変更後の変数の設定値 Option_ Empty を指定してください 返り値 変更後の .ini ファイルの内容 該当する変数が存在しないときは、エラーになります。 サンプル after_text = SetIniFileTextValue( before_text, Empty, "NameA", "Value", Empty ) ソース → vbslib.vbs テスト → T_IniFile.vbs T_SetIniFileTextValue 関連 → GetIniFileTextValue *********************************************************************** <<< RenumberIniFileData >>> *********************************************************************** RenumberIniFileData [ 親: .ini ファイル ] Sub RenumberIniFileData( ReadStream as TextStream, WriteStream as TextStream, StartNumber as integer, IsPlusSpaceLineOnly as boolean ) .ini ファイルの内容のうち、= より左にある ( ) の中の番号を振り直します。 【引数】 ReadStream 入力ストリーム → StringStream クラス WriteStream 出力ストリーム → StringStream クラス StartNumber 開始番号 IsPlusSpaceLineOnly 空行があるときだけ番号を+1するかどうか サンプル・データ Data(2) = ABC Data(5) = DEF Data(6) = DEF 入力 出力 Data(1) = ABC Data(2) = DEF Data(3) = DEF ソース → vbslib.vbs 関連 → RenumberIniFileData コマンド *********************************************************************** <<< ParseJSON >>> *********************************************************************** ParseJSON (src) Function ParseJSON( JSON_String as string ) as JS_Object JSON をパース(構文解析)します。 【引数】 JSON_String JSON 形式の文字列データ 返り値 JSON のデータにアクセスできるオブジェクト サンプル Set json = ParseJSON( "{'attribute_1':'One', 'attr2':'Two'}" ) echo json.attribute_1 '// "One" 省略された属性に対して、返り値から参照しようとすると、エラー 438 になります。 参考 → JSON (JavaScript Object Notation) *********************************************************************** <<< C言語 >>> *********************************************************************** C言語 関連 → 開発環境操作 *********************************************************************** <<< CutSharpIf >>> *********************************************************************** CutSharpIf Sub CutSharpIf( InputPath as string, OutputPath as string, Symbol as string, IsCutTrue as boolean ) #ifdef 〜 #endif をカットします。 【引数】 InputPath 入力ファイルやフォルダーのパス → GetInputOutputFilePaths OutputPath 出力ファイルやフォルダーのパス → GetInputOutputFilePaths Symbol #define シンボル、または、#if の条件文 IsCutTrue #if が真の部分をカットする(True)か、偽の部分をカットする(False)か サンプル CutSharpIf "sample.c", Empty, "SAMPLE", True CutSharpIf "FolderA", "FolderB", "SAMPLE_A || SAMPLE_B", False ソース → ToolsLib.vbs → vbslib_helper.c → ParsedRanges_getCut_by_PP_Directive テスト → T_CutSharpIf.vbs T_CutSharpIf 関連 → CutSharpIf コマンド *********************************************************************** <<< CutCommentC >>> *********************************************************************** CutCommentC Sub CutCommentC( in_Path as string, in_Empty as Empty ) C/C++言語のソース ファイルからコメントを削除します。 【引数】 in_Path コメントを削除するソース ファイルのパス in_Empty Empty を指定してください(予約) コメントを削除する前の内容は上書きされて無くなるので、バックアップを取ってから実行して ください。 in_Path 引数には、 ArrayFromWildcard の引数のように ワイルドカードなどを指定できます。 参考 → CutComment コマンド サンプル Set w_=AppKey.NewWritable( "Folder" ).Enable() CutCommentC "Folder\Source.c", Empty NewWritable "Folder\Source.c" ソース → ToolsLib.vbs → vbslib_helper.c → clib - CutCommentC_1 テスト → T_CutCommentC.vbs T_CutCommentC *********************************************************************** <<< MakeDocumentByNaturalDocs >>> *********************************************************************** MakeDocumentByNaturalDocs Sub MakeDocumentByNaturalDocs( SourceRootPath as string, DocumentRootPath as string, Options as Empty ) Natural Docs を実行して、ソースファイルからHTML形式のドキュメントを生成します。 【引数】 SourceRootPath ソースファイルがあるフォルダーのパス DocumentRootPath HTML形式のドキュメントを生成するフォルダーのパス Options Empty を指定してください ソースファイルは、現在のコードページ(日本なら Shift-JIS)、または Unicode(UTF-16) に してください。 参考 → Natural Docs サンプル MakeDocumentByNaturalDocs "src", "HTML", Empty 補足 Natural Docs や ActivePerl がインストールされていないと、インストールを即す警告が表示 されます。 参考 → Setting_getNaturalDocsPerlPath → GetPerlVersion DocumentRootPath に指定したパスにフォルダーを消すと、Natural Docs のプロジェクト フォルダー(キャッシュ)を作り直します。 プロジェクトフォルダーは、 テンポラリ・フォルダー の中に作られ、日付が変わると作り直します。 g_Vers("NaturalDocsExtension") を設定すると、Natural Docs に入力する拡張子を 変更できます。 ソース → ToolsLib.vbs テスト → T_NaturalDocs.vbs 関連 → NaturalDocs コマンド → MakeDocumentBy_doxygen *********************************************************************** <<< MakeDocumentBy_doxygen >>> *********************************************************************** MakeDocumentBy_doxygen Sub MakeDocumentBy_doxygen( SourceRootPath as string, DocumentRootPath as string, Options as Empty ) doxygen を実行して、ソースファイルからHTML形式のドキュメントを生成します。 【引数】 SourceRootPath ソースファイルがあるフォルダーのパス DocumentRootPath HTML形式のドキュメントを生成するフォルダーのパス Options Empty を指定してください ソースファイルは、現在のコードページ(日本なら Shift-JIS)、または Unicode(UTF-16) に してください。 参考 → doxygen サンプル MakeDocumentBy_doxygen "src", "HTML", Empty 補足 doxygen がインストールされていないと、インストールを即す警告が表示されます。 参考 → Setting_getDoxygenPath DocumentRootPath に指定したパスにフォルダーを消すと、Natural Docs のプロジェクト フォルダー(キャッシュ)を作り直します。 プロジェクトフォルダーは、 テンポラリ・フォルダー の中に作られ、日付が変わると作り直します。 g_Vers("NaturalDocsExtension") を設定すると、Natural Docs に入力する拡張子を 変更できます。 ソース → ToolsLib.vbs テスト → T_doxygen.vbs 関連 → doxygen コマンド → MakeDocumentByNaturalDocs *********************************************************************** <<< ConvertDocumetCommentFormat >>> *********************************************************************** ConvertDocumetCommentFormat Sub ConvertDocumetCommentFormat( InputPath as string, OutputPath as string, InputFormat as string, OutputFormatFilePath as string ) プログラムのソースファイルの中にある、ドキュメントに変換できるコメントの形式を変換します。 【引数】 InputPath 入力ファイルやフォルダーのパス → GetInputOutputFilePaths OutputPath 出力ファイルやフォルダーのパス → GetInputOutputFilePaths InputFormat 現在、"NaturalDocs" のみ指定できます OutputFormatFilePath 出力するコメントのテンプレートが書かれたファイルのパス 現在、C言語の NaturalDocs 形式コメントから、doygen (Javadoc)形式コメントへの変換の 一部のみ可能です。 サンプル → T_ConvertDCF フォルダー ソース → ToolsLib.vbs テスト → T_TextSection.vbs T_ConvertDCF コールツリー ConvertDocumetCommentFormat (src) vbslib_helper.exe ConvertDocumentCommentFormat ConvertDCF_onXML_Element (src) if ( _tcsicmp( in_Status->TagName, _T("Text") ) == 0 ) { ConvertDCF_Class::Comments.ID (src) ConvertDCF_Class_convert (src) MakeNaturalComments_C_Language NaturalDocs 形式コメントをパースする NaturalCommentClass_printXML NaturalCommentClass (src) NaturalDocsHeaderClass (src) ConvertDCF_CommentClass_getReplaced (src) 1つのコメントを置き換える /* Set "descriptions" : Replaced from "${Descriptions}" */ 関連 → ConvertDocumetCommentFormat コマンド *********************************************************************** <<< DoTextShrink >>> *********************************************************************** DoTextShrink Sub DoTextShrink( TxMxFilePath as string, Option as Empty ) セクション(NaturalDocs で区切ったソース ファイル)のうち、使用していないセクションを削除します。 【引数】 TxMxFilePath 編集するファイルなどが記述された .txmx ファイルのパス(下記) Option Empty を指定してください ソース → ToolsLib.vbs テスト → T_TextSection.vbs T_TextShrink T_MakeTxScFile → T_TextShrink フォルダー コールツリー DoTextShrink (src) TxMxClass (src) MakeTextSectionIndexFile vbs(src) MakeTextSectionIndexFile c(src) ListUpUsingTxMxKeywords vbs(src) ListUpUsingTxMxKeywords c(src) MakeNaturalComments_C_Language NaturalCommentClass TxMxListUp_readSetting TxMxListUp_listUpUsedNames c(src) MakeShrinkedSectionsFile (src) CreateFromTextSections DoTextMix ListUpTextShrinkKeywords 関連 → DoTextShrink コマンド *********************************************************************** <<< (CSV) ArrayFromCSV, ArrayFromCSV_Int >>> *********************************************************************** (CSV) ArrayFromCSV, ArrayFromCSV_Int (src) Function ArrayFromCSV( a_CSV as string ) as Array of string Function ArrayFromCSV_Int( a_CSV as string ) as Array of integer CSV 形式の1行を解析して、それぞれの項目を配列に格納します。 【引数】 a_CSV CSV 形式の1行 返り値 (出力)CSV の項目が入った配列 サンプル For Each column In ArrayFromCSV( "ABC , DEF" ) Next ABC , DEF 上記 ArrayFromCSV の返り値は、Array( "ABC", "DEF" ) 各項目の両端の空白が削除されたものが戻ります。 項目の端に空白文字がある場合と、項目の中にコンマやダブルクォーテーション(")が あるときは、" " で囲んでください。 ただし、ダブルクォーテーション1文字あたり、 ダブルクォーテーションを2つ並べてください。 CSV: A, " ""ABC,"" " 各項目: A "ABC," VBS: ArrayFromCSV( "A, "" """"ABC,"""" """ ) CSV とは別に、VBS も同様に " 文字は " を2つ並べる "A, ,C" の真ん中の要素のように、何も無いときは、配列の要素が Empty になります。 "A, " のように最後がコンマのときは、配列の最後の要素が Empty になります ArrayFromCSV( "A,,C" ) = Array( "A", Empty, "C" ) ArrayFromCSV( "A," ) = Array( "A", Empty ) 要素に "" (ダブルクオーテーション2つだけ)が指定されたときは、空文字列になります。 ArrayFromCSV( "A, """"" ) = Array( "A", "" ) " " のように、空白文字や空文字列のときは、配列要素数が 0 になります。 ArrayFromCSV( " " ) = Array( ) 複数行の文字列を指定するときは、最後の行以外の行末を "," にしてください。 ArrayFromCSV( "A, B," +vbCRLF+ "C, D," +vbCRLF+ "E, F" ) = Array( "A","B","C","D","E","F" ) つまり A, B, C, D, E, F = A, B, C, D, E, F サンプル 複数行の文字列から、各行を配列にする paths = ArrayFromCSV( Replace( Trim2( multi_line_string ), vbCRLF, "," ) ) 性能について 本関数は処理が遅いです。 CSV ファイルのデータは、1行に対応するクラスの配列にキャッシュしておくと速くなります。 テスト → T_CSV.vbs # ArrayFromCSV 関連 → CSV (ArrayClass) → Split → ArrayFromCmdLine → MeltCSV → AddCSV (ArrayClass) *********************************************************************** <<< ArrayFromOrPipe >>> *********************************************************************** ArrayFromOrPipe Function ArrayFromOrPipe( in_OrPipedString as string or array of string ) as Array of string | で区切られた文字列を解析して、それぞれの項目を配列に格納します。 【引数】 in_OrPipedString | または , で区切られた文字列、または、その配列 返り値 (出力) 文字列の配列 ArrayFromCSV とほぼ同じですが、コンマだけでなく | も区切り記号として処理します。 サンプル For Each column In ArrayFromOrPipe( "ABC | DEF" ) Next ABC | DEF 上記 ArrayFromOrPipe の返り値は、Array( "ABC", "DEF" ) サンプル For Each column In ArrayFromOrPipe( Array( "*.txt | ""A *.log""", "*.xml" ) ) Next "*.txt | ""A *.log""", "*.xml" 上記 ArrayFromOrPipe の返り値は、Array( "*.txt", "A *.log", "*.xml" ) ソース → vbslib.vbs テスト → T_Wildcard.vbs T_ArrayFromWildcard1 T_ArrayFromWildcard2 *********************************************************************** <<< CSVFrom >>> *********************************************************************** CSVFrom Function CSVFrom( a_Array as array ) as string 配列を CSV 形式に変換します。 【引数】 a_Array 配列 返り値 CSV 形式文字列 ソース → vbslib.vbs テスト → T_CSV.vbs *********************************************************************** <<< CSVText >>> *********************************************************************** CSVText Function CSVText( s as string ) as string CSV の1項目に変換します。 サンプル s = CSVText( "a,b" ) s は、"""a,b""" という1つの値になります。 a と b という2つの値ではありません。 サンプル CSV の1行を作成します s = "" For Each t In Array( "a", "b" ) If s <> "" Then s = s + ", " s = s + CSVText( t ) Next ソース → vbslib.vbs テスト → T_CSV.vbs *********************************************************************** <<< MeltCSV >>> *********************************************************************** MeltCSV (src) Function MeltCSV( Line as string, in_out_Start as integer ) as string CSV 形式の1項目を取り出し、通常の文字列に戻す。 【引数】 Line CSV 形式の1行 in_out_Start (入力) 取り出しを開始する文字の位置、(出力)次に取り出す〜 返り値 取り出した CSV 形式の1項目。Empty=項目に値が無い 各項目の両端の空白が削除されたものが戻ります。 次の項目が無いときは、i=0 になります。 i=0 を渡すと、Empty を返します。 サンプル i = 1 Do s = MeltCSV( line, i ) If not IsEmpty( s ) Then (s を使った処理) If i = 0 Then Exit Do Loop 関連 → ArrayFromCSV テスト → T_CSV.vbs # main *********************************************************************** <<< CSV_insert >>> *********************************************************************** CSV_insert Function CSV_insert( CSV_Line as string, RightColumnNum0 as integer, Element as variant ) as string CSV 形式の1行に、要素を挿入します。 【引数】 CSV_Line CSV 形式の1行 RightColumnNum0 挿入する位置の右の要素の番号(0以上) Element 挿入する要素 返り値 挿入した後の CSV 形式の1行 サンプル Assert CSV_insert( "A,B,C", 1, "x" ) = "A,x,B,C" Assert CSV_insert( "A,B,C", 4, "x" ) = "A,B,C,,x" ソース → vbslib.vbs テスト → T_CSV.vbs *********************************************************************** <<< CSV_set >>> *********************************************************************** CSV_set Function CSV_set( CSV_Line as string, ColumnNum0 as integer, Element as variant ) as string CSV 形式の1つの要素を上書きします。 【引数】 CSV_Line CSV 形式の1行 ColumnNum0 上書きする要素の番号(0以上) Element 上書きする要素 返り値 上書きした後の CSV 形式の1行 サンプル Assert CSV_set( "A,B,C", 1, "x" ) = "A,x,C" Assert CSV_set( "A,B,C", 4, "x" ) = "A,B,C,,x" ソース → vbslib.vbs テスト → T_CSV.vbs *********************************************************************** <<< CSV_remove >>> *********************************************************************** CSV_remove Function CSV_remove( CSV_Line as string, ColumnNum0 as integer ) as string CSV 形式の1つの要素を削除します。 【引数】 CSV_Line CSV 形式の1行 ColumnNum0 削除する要素の番号(0以上) 返り値 削除した後の CSV 形式の1行 サンプル Assert CSV_remove( "A,B,C", 1 ) = "A,C" Assert CSV_remove( "A,B,C", 4 ) = "A,B,C," 削除する要素より前の要素が無いときは、前に空の要素が追加されます Assert CSV_remove( "A,B,C,", 3 ) = "A,B,C" ソース → vbslib.vbs テスト → T_CSV.vbs *********************************************************************** <<< (XML) LoadXML >>> *********************************************************************** (XML) LoadXML (src) Function LoadXML( PathOrStr as string, Opt as variant ) as IXMLDOMElement IXMLDOMElement XML ファイル、または XML 形式の文字列を読み込みます。 【引数】 PathOrStr XML ファイルのパス、または XML 形式文字列や FilePathClass Opt オプション(下記) → Opt 引数 返り値 XML のルート要素 日本語があるときは、Unicode にするか、XML宣言で Shift-JIS を指定してください。 参考 → DOM サンプル → XML → XmlFilter ツール (.zip) → xml_sub 関数 サンプル : sample.xml ファイルをロードする Dim root, elem, attr Set root = LoadXML( "sample.xml", Empty ) '//=== read 1 attribute value WScript.Echo root.selectSingleNode( "./Tests/Test" ).getAttribute( "result" ) '//=== read 1 text value WScript.Echo root.selectSingleNode( "./Tests" ).text Set node = root.selectSingleNode( "./Tests/text()" ) If not node is Nothing Then WScript.Echo node.nodeValue '//=== loop each tags For Each element In root.selectNodes( "./Tests/Test" ) WScript.Echo "result, "+ element.getAttribute( "result" ) Next Set nodes = root.selectNodes( "./Tests" ) ReDim values( nodes.length - 1 ) For i=0 To UBound( values ) values(i) = nodes(i).text Next '//=== loop each attributes For Each element In root.selectNodes( ".//Test" ) WScript.Echo "<" + element.tagName + ">" For Each attribute In element.attributes WScript.Echo attribute.name + "=" + attribute.value Next Next LoadXML "sample.xml" → XmlRead selectSingleNode "./Tests/Test" getAttribute "result" → XmlRead ./Tests/text() selectNodes "./Tests/Test" result "result" ".//Test" サンプル: XML 形式文字列を展開する Dim s : s = "ABC 123" Dim root : Set root = LoadXML( s, F_NoRoot or F_Str ) Dim value : value = root.selectSingleNode( "./TAG1" ).getAttribute( "attr" ) '// value = "value1" LoadXML 関連 → XML 要素へアクセスするその他のサンプル サンプル: XML を結合する Dim f, root, elem, attr Set f = OpenForWrite( "FileAB.xml", Empty ) f.WriteLine "" Set root = LoadXML( "FileA.xml", Empty ) f.WriteLine XmlTags( root.selectSingleNode( "./TagB" ).xml, 1 ) Set root = LoadXML( "FileB.xml", Empty ) f.WriteLine XmlTags( root.selectSingleNode( "./TagB" ).xml, 1 ) f.WriteLine "" Opt 引数 F_NoRoot フラグ、g_VBS_Lib.NoRootXML XML のルート要素が無い XML を読み込みます。 返り値は、内部で自動的に 加えられたルート要素 になります。 先頭が < でないときは、自動的にルート要素が加えられます。 F_Str フラグ、g_VBS_Lib.StringData PathOrStr 引数を XML 形式文字列として処理します g_VBS_Lib.InheritSuperClass (SuperClassタグ) SuperClass タグの属性を子タグにコピーして、id 属性を持たない SuperClass タグを 削除した XML データを返します。 super_class 属性を持つタグは、super_class 属性が 指す id 属性を持つ SuperClass タグの属性をコピーします。 参考: T_InheritSuperClassXML テスト FileA.xml ファイル LoadXML の返り値の XML テスト → T_XML フォルダー 関連 → XmlRead → MultiTextXML_Class → LoadXML_Cached *********************************************************************** <<< LoadXML_Cached >>> *********************************************************************** LoadXML_Cached Function LoadXML_Cached( PathOrStr as string, Opt as variant ) as IXMLDOMElement IXMLDOMElement XML を解析してできた DOM オブジェクトをキャッシュする LoadXML 。 2回目以降の XML ファイルは、キャッシュによって XML を解析する処理がなくなり、高速に処理 します。 返り値がどの変数から参照されなくなっても、キャッシュのために、DOM オブジェクトはメモリー上に 残ります。 vbslib の内部に絶対パスをキー、DOM オブジェクトをアイテムとした辞書型のキャッシュ があります。 ソース → vbslib.vbs キャッシュは、以下の変数です。 g_VBS_Lib.XML_DOM_ReadCache as dictionary key=path, item=IXMLDOMElement class 関連 → XML_ReadCacheClass *********************************************************************** <<< XML_ReadCacheClass >>> *********************************************************************** XML_ReadCacheClass XML ファイルの内容を内部でキャッシュします。 → Item (XML_ReadCacheClass) 関連 → LoadXML_Cached *********************************************************************** <<< Item (XML_ReadCacheClass) >>> *********************************************************************** Item (XML_ReadCacheClass) << XML_ReadCacheClass Default Property Get XML_ReadCacheClass::Item( URL as string ) as string XML のテキスト、または、属性値を返します。 【引数】 URL XML ファイルのパス +"#"+ XPath 返り値 XML のテキスト、または、属性値 ソース → vbslib.vbs テスト → T_XML.vbs # [T_XML_ReadCacheClass] サンプル VBScript Set files = new XML_ReadCacheClass tag_text = files( "Sample.xml#/Root/Tag" ) '// tag_text = "The text" Sample.xml#/Root/Tag Sample.xml The text *********************************************************************** <<< OpenForReplaceXML >>> *********************************************************************** OpenForReplaceXML Function OpenForReplaceXML( SrcPath as string, DstPath as string ) as ReplaceXmlFile1 XMLファイルの内容の変更を開始します。 【引数】 SrcPath 変更前のテキストファイルのパス DstPath 変更後のテキストファイルのパス。 SrcPath と同じ、または Empty 可。 返り値 → ReplaceXmlFile1 クラス サンプル Set xml = OpenForReplaceXML( "file1.xml", Empty ) xml.Write "/Root/Elem/@attr1", 11 xml.IsUserConfirm = True xml = Empty '// デストラクタでユーザーの確認およびファイルの更新をする file1.xml Write /Root/Elem/@attr1 11 IsUserConfirm ReplaceXmlFile1 クラス .Write タグの間のテキスト、または XML 属性の値を変更します。 .IsUserConfirm XML ファイルを変更する前に、ユーザーに確認をとるかどうか。 ソース → vbslib.vbs テスト → T_XML.vbs # [T_OpenForReplaceXML] → T_XML_Manually.vbs # [T_OpenForReplaceXML_Manually] 関連 → SetXmlAttribute → OpenForReplace → ReplaceRange (ReplaceTextFile1) → PositionOfXML_Class *********************************************************************** <<< Write (ReplaceXmlFile1) >>> *********************************************************************** Write (ReplaceXmlFile1) → OpenForReplaceXML Sub ReplaceXmlFile1::Write( XPath as string, Value as string ) XML のタグの間のテキスト、または XML の属性の値を変更します。 【引数】 XPath タグの間のテキスト、または XML の属性の位置を表す XPath Value 変更後のテキストまたは XML 属性の値、""=値なし、Empty=削除する 返り値 変化があったかどうか 参考 → XmlWrite → サンプル *********************************************************************** <<< SetXmlAttribute (ReplaceXmlFile1) >>> *********************************************************************** SetXmlAttribute (ReplaceXmlFile1) → OpenForReplaceXML 廃止されました。 → Write (ReplaceXmlFile1) Sub ReplaceXmlFile1::SetXmlAttribute( XPathForXmlElement as string, AttrName as string, AttrValue as string ); XML 属性の値を変更します。 【引数】 XPathForXmlElement 属性を変更する XML 要素(タグ) への XPath。 フル・パス AttrName XML 属性の名前 AttrValue 変更後の XML 属性の値 → サンプル *********************************************************************** <<< IsUserConfirm (ReplaceXmlFile1) >>> *********************************************************************** IsUserConfirm (ReplaceXmlFile1) → OpenForReplaceXML Dim ReplaceXmlFile1::IsUserConfirm as boolean XML ファイルを変更する前に、ユーザーに確認をとるかどうかの設定値。 デフォルトは、False です。 XML ファイルを更新する直前で、値が変わる属性とその値を表示します。 表示中に、ユーザーの確認入力があるまで待ちます。 → サンプル 確認画面の例: /Root/Tests/Test1@attr1="1" /Root/Tests/Test3@attr1="3" 更新ファイル:out.xml XML ファイルの上記属性を変更します。 続行するには Enter キーを押してください . . . *********************************************************************** <<< OpenForAppendXml >>> *********************************************************************** OpenForAppendXml (src) Function OpenForAppendXml( SrcPath as string, DstPath as string ) as AppendXmlFile XMLファイルの内容の追加を開始します。 【引数】 SrcPath 変更前のテキストファイルのパス DstPath 変更後のテキストファイルのパス。 SrcPath と同じ、または Empty 可。 返り値 TextStream + α のオブジェクト 追加する内容は、OpenForWrite と同様に WriteLine などのメソッドに XML の文字列を 指定します。 XPath ではありません。 クローズするときに、ルートの XML タグ(XML要素)を閉じるタグを出力します。 よって、追加する内容は、ルートの XML タグの直下の末尾に限定されます。 返り値を使って呼び出せるメソッドは、FileSystemObject::OpenTextFile と同じですが、 WriteXml メソッドが追加されています。 → WriteXml サンプル Set file = OpenForAppendXml( "Modify.xml", Empty ) file.WriteLine " " file.WriteXml ReadFile( "Add.xml" ) file = Empty Modify.xml (処理前) Modify.xml (処理後) Add.xml テスト → T_XML.vbs # [T_OpenForAppendXml] *********************************************************************** <<< WriteXml (AppendXmlFile) >>> *********************************************************************** WriteXml (AppendXmlFile) (src) Sub AppendXmlFile::WriteXml( Xml as string ) 指定した XML 文字列から、ルート XML タグを除いて追加します。 【引数】 Xml 追加する XML 文字列 サンプル を追加します file.WriteXml "" サンプル Modify.xml に Add.xml を追加します。 OpenForAppendXml( "Modify.xml", Empty ).WriteXml ReadFile( "Add.xml" ) Modify.xml (処理前) Modify.xml (処理後) Add.xml *********************************************************************** <<< PositionOfXML_Class >>> *********************************************************************** PositionOfXML_Class 文字列の中にある XML要素の文字位置を調べます。 内部で DOM は使っていません。 XML要素を追加・変更・削除しても、空白の数や属性の順番が変わって、 XML 文書が崩れてしまうという XML規格の問題を回避することができます。 サンプル Set xml = new PositionOfXML_Class xml.Load "Data.xml" Set test_tag = xml.SelectSingleNode( "//Tag[1]" ) current_pos = test_tag.PositionOfLeftOfStartTag next_pos = test_tag.PositionOfNextOfEndTag Set file = OpenForReplace( "Data.xml", Empty ) text_0 = Left( file.Text, current_pos - 1 ) text_1 = Mid( file.Text, current_pos, next_pos - current_pos ) text_2 = Mid( file.Text, next_pos ) file.Text = text_0 + _ vbTab +""+ vbCRLF + _ text_1 + _ vbTab +""+ _ text_2 file = Empty Load SelectSingleNode OpenForReplace 上記スクリプトは、たとえば以下の編集を行います。 Data.xml MS-XML の DOM では、以下のように整形された XML しか保存できません。 ソース → vbslib.vbs テスト → T_XML.vbs T_PositionOfXML T_PositionOfXML_TryUI 関連 → OpenForReplaceXML *********************************************************************** <<< Load (PositionOfXML_Class) >>> *********************************************************************** Load (PositionOfXML_Class) << PositionOfXML_Class Sub PositionOfXML_Class::Load( in_FilePath as string ) XML ファイルをロードします。 【引数】 in_FilePath ロードする XML ファイルのパス ソース → vbslib.vbs *********************************************************************** <<< SelectSingleNode (PositionOfXML_Class) >>> *********************************************************************** SelectSingleNode (PositionOfXML_Class) << PositionOfXML_Class Function PositionOfXML_Class::SelectSingleNode( in_XPath as string ) as PositionOfXML_ElementClass PositionOfXML_ElementClass 指定した XML 要素を探して、その位置情報にアクセスするオブジェクトを返します。 【引数】 in_XPath XML 要素を指す XPath。 ただし一部の形式のみ 返り値 XML の位置情報にアクセスするオブジェクト または Nothing in_XPath 引数に指定できる XPath は、以下の形式のみです。 //Tag[1] //Tag[last()] 該当する XML 要素がなければ、Nothing を返します。 [ ] の中は、1以上の整数です。 要素数(=last()) より大きいときは、Nothing を返します。 PositionOfXML_ElementClass 以下のプロパティから、XML タグの前後などの文字の位置を取得できます。 文字の位置は、VB の InStr 関数などで扱う位置と同じで、先頭が 1 で、文字単位で +1 した整数値です。 ファイルのバイナリの位置とは異なります。 integer .PositionOfLeftOfStartTag 開始タグまたは空要素タグの行頭または前のタグの直後の文字の位置 integer .PositionOfNextOfEndTag 終了タグまたは空要素タグの次の行の先頭または終了タグの直後の文字の位置 同じ行に別のタグがないとき: * + * * = PositionOfLeftOfStartTag が指す文字 + + = PositionOfNextOfEndTag が指す文字 同じ行に別のタグがあるとき: * + * + * = PositionOfLeftOfStartTag が指す文字 + = PositionOfNextOfEndTag が指す文字 厳密にいえば、同じ行に別のタグがあるかどうかではなく、 タグの左の位置のプロパティは、同じ行の左側に別のタグがるかどうか、 タグの次の位置のプロパティは、同じ行の右側に別のタグがるかどうかです。 同じ行の右側に別のタグがあっても、タグの左の位置のプロパティは、 上記の「同じ行に別のタグがないとき」に該当します。 以下は、まだ開発されていません。 integer .PositionOfNextOfStartTag 開始タグの次の行の先頭または開始タグの直後の文字の位置 integer .PositionOfLeftOfFirstAttribute 最初の属性の行頭またはタグ名の直後の文字の位置 integer .PositionOfNextOfLastAttribute 最後の属性の次の行の先頭または最後の属性の直後の文字の位置 参考 → XML 1.1 - 3.1 Start-Tags, End-Tags, and Empty-Element Tags (Web) ソース → vbslib.vbs *********************************************************************** <<< XmlRead >>> *********************************************************************** XmlRead Function XmlRead( in_BaseXmlElement as IXMLDOMElement, in_XPath as string ) as string XML のタグの間のテキスト、または XML の属性の値を取得します。 【引数】 in_BaseXmlElement in_XPath の基準となる XML要素(タグ) in_XPath タグの間のテキスト、または XML の属性の位置を表す in_XPath 返り値 テキストまたは XML 属性の値。文字列型 タグの間のテキストは、厳密には in_XPath = "/Root/Elem/text()" ですが、in_XPath = "/Root/Elem" を指定してください。 in_XPath に指定したタグ(XML要素)やXML属性が存在しないときは、Empty を返します。 in_XPath が相対パスのときは、in_BaseXmlElement のタグが基準になります。 in_XPath にフル・パスを指定することもできます。 サンプル Set root = LoadXML( "in.xml", Empty ) '// as IXMLDOMElement value = XmlRead( root, "./Tag1/@attr1" ) XmlRead Tag1/@attr1 参考 → getAttribute (IXMLDOMElement) → RegRead ソース → vbslib.vbs テスト → T_XML.vbs T_XmlRead 関連 → CutIndentOfMultiLineText XML のタグの間の複数行のテキスト → XmlReadBoolean → LinkedXMLs クラス #付き RUL、name 属性、id 属性 *********************************************************************** <<< XmlReadOrError >>> *********************************************************************** XmlReadOrError Function XmlReadOrError( in_BaseXmlElement as IXMLDOMElement, in_XPath as string, in_FilePath as string ) as string XML にデータが記述されていなければエラーになる XmlRead です。 【引数】 in_BaseXmlElement in_XPath の基準となる XML要素(タグ) in_XPath タグの間のテキスト、または XML の属性の位置を表す in_XPath in_FilePath Empty または エラーメッセージに表示する XML ファイルの名前 返り値 テキストまたは XML 属性の値。文字列型 サンプル Set root = LoadXML( "Setting.xml", Empty ) '// as IXMLDOMElement value = XmlReadOrError( root, "./Tag1/@attr1", "Setting.xml" ) XmlReadOrError Tag1/@attr1 エラーメッセージは、下記のようになります。 in_FilePath = Empty のときのエラーメッセージは、下記のようになります。 ソース → vbslib.vbs テスト → T_XML.vbs # [T_XmlRead] 関連 → XmlRead *********************************************************************** <<< Read_XML_Encoding >>> *********************************************************************** Read_XML_Encoding Function Read_XML_Encoding( in_Path as string ) as string XML ファイルから、?xml タグの encoding 属性を読みます。 【引数】 in_Path XML ファイルのパス 返り値 encoding 属性の値、文字コード セット名 ?xml タグ(XML宣言)の encoding 属性が設定されてなく、UTF-16 の BOM があるときは、 "UTF-16" が返ります。 encoding 属性が設定されてなく、BOM がないときは、"UTF-8" が返ります。 encoding 属性が設定されてないときに "UTF-8" であるのは、HTML5 の 仕様です。 ソース → vbslib.vbs テスト → T_XML.vbs T_LoadXML 関連 → ReadUnicodeFileBOM *********************************************************************** <<< XmlReadBoolean >>> *********************************************************************** XmlReadBoolean Function XmlRead( in_BaseXmlElement as IXMLDOMElement, in_XPath as string, in_DefaultValue as boolean, in_FilePath as string or Empty ) as string XML のタグの間のテキスト、または XML の属性の値を、論理型で取得します。 【引数】 in_BaseXmlElement in_XPath の基準となる XML要素(タグ) in_XPath タグの間のテキスト、または XML の属性の位置を表す in_XPath in_DefaultValue in_Path が指す XML ノードがないときの返り値 in_FilePath エラーが発生したときに表示するファイルのパス、または Empty 返り値 タグの間の値、または XML 属性の値。 論理型 XML に記述する値は、Yes, No, True, False のいずれかです。 大文字小文字は区別しません。 タグの間のテキストは、厳密には in_XPath = "/Root/Elem/text()" ですが、in_XPath = "/Root/Elem" を指定してください。 in_XPath が相対パスのときは、in_BaseXmlElement のタグが基準になります。 in_XPath にフル・パスを指定することもできます。 in_DefaultValue には、Empty など、オブジェクト型以外を指定できます。 サンプル Set root = LoadXML( "in.xml", Empty ) '// as IXMLDOMElement value = XmlReadBoolean( root, "./Tag1/@attr1", False, "a.xml" ) XmlReadBoolean XML の例: ソース → vbslib.vbs テスト → T_XML.vbs # [T_XmlReadBoolean] 参考 → XmlRead *********************************************************************** <<< XmlSelect >>> *********************************************************************** XmlSelect Function XmlSelect( BaseXmlElement as IXMLDOMElement, XPath as string ) as IXMLDOMElement XML のタグのオブジェクトを返します。 もし、該当する XML のタグが無ければ生成して返します。 【引数】 BaseXmlElement XPathForXmlElement の基準となる XML要素(タグ) XPath XML 要素(タグ)の位置を表す XPath 返り値 XML 要素(タグ)のオブジェクト ソース → vbslib.vbs テスト → T_XML.vbs # T_XmlSelect *********************************************************************** <<< XmlAttrDic >>> *********************************************************************** XmlAttrDic Function XmlAttrDic( XmlElem as IXMLDOMElement ) as dictionary of string XML 要素(タグ)の属性を、辞書にします。 【引数】 XmlElem XML 要素 返り値 キーが属性名、アイテムが属性値の辞書 ソース → vbslib.vbs テスト → T_XML.vbs # [T_XmlAttrDic] *********************************************************************** <<< GetHRefBase >>> *********************************************************************** GetHRefBase (src) Function GetHRefBase( BasePath as string, TargetTagNames as array of string ) as HRefBase HTML の A href のようなリンクを取得するためのオブジェクトを返します。 【引数】 BasePath 基準となる XML ファイルのパス TargetTagNames リンク先となる id, name 属性を持つタグの名前の配列 返り値 リンクを取得するためのオブジェクト サンプル Dim base, x Set base = GetHRefBase( "sample.xml", Array("X") ) Set x = base.href( "target.xml#name1" ) Assert x.getAttribute( "name" ) = "name1" "sample.xml" "X" href "target.xml#name1" sample.xml target.xml Link "target.xml#name1" テスト → T_XML.vbs # [T_HRefBase] 関連 → href (HRefBase) → LinkedXMLs クラス 循環参照検出あり → GetTagJumpParams *********************************************************************** <<< href (HRefBase) >>> *********************************************************************** href (HRefBase) (src) << GetHRefBase Function HRefBase::href( URL as string ) as IXMLDOMElement IXMLDOMElement HTML の A href のようなリンクのリンク先となる XML タグを取得します。 【引数】 URL リンク先のURL 返り値 リンク先の XML タグ 他の XML ファイルへのリンクがあるときは、内部で自動的に LoadXML が呼ばれます。 パスにピリオドを3つ並べる こともできます。 リンク先が見つからないときはエラーになります。 参考 → GetHRefBase HRefBase オブジェクトの取得 → GetLinkTargetNode (LinkedXMLs) 関連 → getElementById (HTMLDocument) *********************************************************************** <<< LinkedXMLs クラス >>> *********************************************************************** LinkedXMLs クラス (src) HTML の A href のようなリンクの、リンク先となる XML タグを取得します。 リンク先の名前は、name 属性か id 属性に指定します。 両者に違いはありません。 他の XML ファイルへのリンクがあるときは、内部で自動的に LoadXML が呼ばれます。 リンク先のリンク先が、循環参照しているかどうかを検出することもできます。 関連 → GetHRefBase sample.xml target.xml Link スクリプト Dim root, a, x, linker Set root = LoadXML( "sample.xml", Empty ) Set a = root.selectSingleNode( "./A" ) '// A タグ Set linker = new LinkedXMLs linker.XmlTagNamesHavingIdName = Array( "X" ) linker.StartNavigation "sample.xml", root Set x = linker.GetLinkTargetNode( "target.xml#name1" ) '// X タグ linker.EndNavigation "sample.xml" XmlTagNamesHavingIdName "X" StartNavigation "sample.xml" GetLinkTargetNode "target.xml#name1" EndNavigation 他の XML ファイルへのリンクがあるときは、内部で LoadXML が呼ばれ、返される XML ルートタグは、内部にキャッシュされます。 最新の情報に更新するとき(キャッシュを クリアするとき)は、LinkedXMLs オブジェクトを再生成してください。 データ構造 .XmlTagNamesHavingIdName as array of string リンク先になれるタグ名の配列 .SourceXmlPath as string リンク元の XML ファイルのパス .SourceXmlRootElem as IXMLDOMElement SourceXmlPath のルート XML タグ .TargetLocation as string 直前のリンク先のパス、# を含む場合もある .TargetXmlPath as string リンク先の XML ファイルのパス .TargetXmlRootElem as IXMLDOMElement TargetXmlPath のルート XML タグ テスト → GetHRefBase 関連 → GetTagJumpParams → XPath - [@name='value'] (属性の値でフィルターする述語) *********************************************************************** <<< XmlTagNamesHavingIdName (LinkedXMLs) >>> *********************************************************************** XmlTagNamesHavingIdName (LinkedXMLs) Dim LinkedXMLs::XmlTagNamesHavingIdName as string getLinkTargetNode メソッドでリンク先にできる XML のid 属性や name 属性を持つ XML タグ名の配列。 サンプル Set linker = new LinkedXMLs linker.XmlTagNamesHavingIdName = Array( "TestCases", "TestCase", "SubCase" ) "TestCases", "TestCase", "SubCase" XmlTagNamesHavingIdName に指定した名前を持つタグにリンクすることができます。 下記の A href のうち、name1, name2 はリンク先が見つかりますが、name3 は見つかりません。 1 2 3 *********************************************************************** <<< StartNavigation (LinkedXMLs) >>> *********************************************************************** StartNavigation (LinkedXMLs) (src) Sub LinkedXMLs::StartNavigation( SourceLocation as string, SourceXmlRootElem as IXMLDOMElement ) 現在の XML ファイル(リンク元)の情報を指定します。 【引数】 SourceLocation 現在の XML ファイルのパス。相対パスでも可能。 # があれば付けること SourceXmlRootElem SourceXmlPath のファイルのルート XML タグ (下記) SourceXmlRootElem 引数 初めてリンク先を探すときは、LoadXML の返り値を指定します。 リンク先の更にリンク先を探すときは、LinkedXMLs::TargetXmlRootElem を指定します。 *********************************************************************** <<< EndNavigation (LinkedXMLs) >>> *********************************************************************** EndNavigation (LinkedXMLs) (src) Sub LinkedXMLs::EndNavigation() StartNavigation で指定した現在の XML ファイルの終了を指定します。 *********************************************************************** <<< GetLinkTargetNode (LinkedXMLs) >>> *********************************************************************** GetLinkTargetNode (LinkedXMLs) (src) Function LinkedXMLs::GetLinkTargetNode( TargetLocation as string ) as IXMLDOMElement IXMLDOMElement リンク先となる XML タグを取得します。 【引数】 TargetLocation リンク先のパス。 target.xml#name 形式 返り値 リンク先のタグ サンプル linker.StartNavigation "sample.xml", root Set x = linker.GetLinkTargetNode( "target.xml#name1" ) linker.EndNavigation "target.xml#name1" 本関数が成功すると、Me.TargetXmlPath(リンク先の XML ファイルのパス)と、 Me.TargetXmlRootElem (TargetXmlPath のルート XML タグ)も更新されます。 参考 → href (HRefBase) 循環参照エラーの検出 StartNavigation をネストしていくと、GetLinkTargetNode で、循環参照エラーを検出できます。 linker.StartNavigation "sample.xml", root Set a = linker.GetLinkTargetNode( "#a" ) linker.StartNavigation linker.TargetLocation, linker.TargetXmlRootElem Set b = linker.GetLinkTargetNode( "#b" ) linker.StartNavigation linker.TargetLocation, linker.TargetXmlRootElem Set a2 = linker.GetLinkTargetNode( "#a" ) '// 循環参照エラー linker.EndNavigation linker.EndNavigation linker.EndNavigation linker.StartNavigation "sample.xml", root Set b = linker.GetLinkTargetNode( "#b" ) '// 循環参照エラーにならない linker.EndNavigation *********************************************************************** <<< ParseAttributesInXML >>> *********************************************************************** ParseAttributesInXML Function ParseAttributesInXML( in_AttributesString as string, in_AttributeNames as array of string ) as dictionary of string 文字列の中にある XML のタグの属性の部分を解析します。 【引数】 in_AttributesString XML のタグの属性の部分。 文字列型 in_AttributeNames 解析する XML 属性の名前の配列 返り値 XML 属性の名前をキーとした、属性値の辞書 XML タグの属性の形式は、名="値" または 名='値' です。 文字列に = 文字を含む場合、XML タグの属性の可能性がありますが、= の左が解析対象の属性名 ではないときや、= の右が " または ' ではないときは、一般の文字列として扱われます。 XML の文法 としては認められていませんが、エラーにはなりません。 また、 実体参照や文字参照(例:&) で記述すれば、XML タグの属性の形式と同じ形式の値も出力することができます(エスケープ)。 in_AttributeNames 引数に指定した配列に空の文字列 "" が含まれるときは、XML タグの属性を 削除した残りの文字列を出力することができます。 XML 属性が削除した部分の空白の文字数は、XML 属性の両隣にある空白の文字数の小さいほう になります。 ただし、前(左)の XML 属性が抜かれたときに右隣の空白が少なくなったら、次(右)の XML 属性の左隣の空白はその少なくなった文字数が使われます。 サンプル Set attrs = ParseAttributesInXML( "a=""Apple"" b=""Banana""", Array( "a", "b" ) ) Assert attrs( "a" ) = "Apple" Assert attrs( "b" ) = "Banana" "a=""Apple"" b=""Banana""" サンプル Set attrs = ParseAttributesInXML( "Text1 a=""Apple"" c=""Cherry""", Array( "a", "b", "" ) ) Assert attrs( "a" ) = "Apple" Assert not attrs.Exists( "b" ) Assert not attrs.Exists( "c" ) Assert attrs( "" ) = "Text1 c=""Cherry""" "Text1 a=""Apple"" c=""Cherry""" "Text1 c=""Cherry""" 補足 " " で囲まれた属性値に " を含めるときは、" に置き換えてください。 ' ' で囲まれた属性値に ' を含めるときは、' に置き換えてください。 属性値は " " で囲んでも ' ' で囲んでも上記以外の違いはありません。 ただし、" " または ' ' で囲む必要があります。 = の隣には空白があってもなくても構いません。 本関数の in_AttributesString 引数に指定できる「vbslib の XML 属性」 の文字列は、XML の文法と しては認められていないもの(例: <, >, & が含まれている文字列)でも、ほぼ問題なく解析できます。 入力: "If ( c < d && e > f ) { a = ""Apple < > &"" }" 出力: a="Apple < > &" 属性値に 実体参照や文字参照(例:&) を含めることができます。 しかし、設定値には、<, >, & をそのまま記述できます。 XML の文法としては認められていませんが、実体参照に変換して記述 する必要はありません。 ただし、属性値に実体参照や文字参照(例:&)と同じ形式(& から 始まり、英数字があり、; で終わる形式)の文字列を設定したいときだけは、 & を & に置き換えてください。 入力: "a=' < > " &quot;'" &quot; 出力: a= " < > " "" " 同じ属性名の属性が in_AttributesString 引数に複数あったときは、それぞれの属性値の間に 改行 vbCRLF が入る形でまとめられます。 XML の文法では同じ属性名の属性は、認められて いません。 入力: "a=""1"" a=""2""" 出力: a= "1"+ vbCRLF +"2" 属性値以外のテキストに、解析対象の属性を設定するような形式(名="値")を設定するとき (例: 属性 a を解析するときに attrs( "" ) に "a=""A""" を残すとき)は、 = を = に置き換えてください。 例: "a=""A"""。 入力: "a=""A""" 出力: attrs("")= "a=""A""" 参考 → XML - 実体参照、文字参照 ソース → vbslib.vbs テスト → T_XML.vbs T_ParseAttributesInXML *********************************************************************** <<< DecodeCharacterReferencesOfXML >>> *********************************************************************** DecodeCharacterReferencesOfXML Function DecodeCharacterReferencesOfXML( in_String as string ) as string XML の実体参照や文字参照(例:&) をデコードします。 【引数】 in_String 実体参照や文字参照を含む文字列 返り値 実体参照や文字参照を対応する文字に変換した文字列 本関数の in_String 引数に指定できる「vbslib の XML 属性」 の文字列は、XML の文法と しては認められていないもの(例: <, >, & が含まれている文字列)でも、ほぼ問題なく 解析できます。 参考 → ParseAttributesInXML サンプル a_string = DecodeCharacterReferencesOfXML( "& < > " & < >" ) Assert a_string = "& < > "" & < >" "& < > " & < >" "& < > "" & < >" ソース → vbslib.vbs テスト → T_XML.vbs T_ParseAttributesInXML *********************************************************************** <<< CutIndentOfMultiLineText >>> *********************************************************************** CutIndentOfMultiLineText Function CutIndentOfMultiLineText( in_Text as string, in_Indent as string or Empty, in_NewLine as string, in_Option as boolean or Empty ) as string インデントをカットします。 また、XML で改行コードが混在したテキストを扱います。 【引数】 in_Text インデントをカットする前の文字列。改行コードは、LF in_Indent Empty か、代わりに追加する文字数*インデントの文字、例:"1*"+ vbTab in_NewLine 返り値の改行コード、Empty(CR+LF), vbCRLF, vbLF, "CR+LF", "LF" in_Option Empty または 下記 → in_Option 引数について 返り値 カットした後の文字列 本関数を呼び出すアプリケーションが入出力する XML ファイルは、複数行のテキスト(タグの間) が記述しやすくなります。 ただし、cut_indent="yes" 属性(名前はアプリケーションの仕様による) を付ける必要があります。 → サンプル → in_Option 引数について → インデントと、上下の端の空行について → 改行コードについて サンプル XML ファイル: XML パーサーの出力: CutIndentOfMultiLineText の返り値: Line1 Line2 cut_indent Line1 Line2 Line1 Line2 または → CDATA セクション サンプル CutIndentOfMultiLineText の返り値: XML ファイル: Line1 Line2 cut_indent indent ^ Line1 ^ Line2 ^ は、タブ文字 スクリプト: If set_item.getAttribute( "cut_indent" ) = "yes" Then text = CutIndentOfMultiLineText( text, set_item.getAttribute( "indent" ), _ Empty, g_VBS_Lib.CutLastLineSeparator ) End If cut_indent indent in_Option 引数について Empty または、下記の定数の論理和 (or) を指定できます。 g_VBS_Lib.CutLineSeparators 末尾が改行文字ならその改行を1つカットして返します。 g_VBS_Lib.KeepLineSeparators → 改行コードについて インデントと、上下の端の空行について すべての行がインデントしてから(タブ文字や空白文字から)始まる場合、そのインデントを カットします。 XML パーサーは、 先頭行が空行のときは、その先頭行をカットします(XML パーサーは、HTML パーサーと 異なり、先頭の空行をカットしません)。 最終行がインデントしかなく、末尾に改行文字がないときは、その最終行をカットします(XML パーサーは、HTML パーサーと異なり、末尾の空行はカットしません)。 参考 → XMLを学ぼう(10):落とし穴になる空白文字と改行文字 - @IT (Web) サンプル XML ファイル: Line1 Line2 Line3 cut_indent="yes" は、(対応アプリケーション では)、インデントをカットすることを示しています。 アプリケーションの内部では、このオプションがある ときだけ、CutIndentOfMultiLineText を呼び出します。 XML パーサーの出力: (改行) ^ ^ Line1(改行) ^ ^ ^ Line2(改行) ^ Line3(改行) ^ ^ は、タブ文字 CutIndentOfMultiLineText の返り値: ^ Line1(改行) ^ ^ Line2(改行) Line3(改行) スクリプト: text_template = _ vbCRLF +_ vbTab + vbTab +"Line1"+ vbCRLF +_ vbTab + vbTab + vbTab +"Line2"+ vbCRLF +_ vbTab + "Line3"+ vbCRLF +_ vbTab + vbTab output = CutIndentOfMultiLineText( text ) Assert output = _ vbTab +"Line1"+ vbCRLF +_ vbTab + vbTab +"Line2"+ vbCRLF +_ "Line3"+ vbCRLF 改行コードについて XML パーサーは、改行コードを LF に統一してしまいます。 そのため、本関数では、改行コードが 混在したテキストも読み込む(アプリケーションが扱う)ことができるように、in_Text 引数(XML テキスト)の行末に改行コードを指定します。   ・行末の "\r"+ LF は CR の改行   ・行末の "\n"+ LF は LF の改行   ・行末の "\r\n"+ LF は CR+LF の改行   ・行末の その他の文字+ LF は、in_NewLine 引数に指定した改行 なお、この拡張(行末の改行コード指定)は、標準的な XML との互換性を考慮して、特定の XML 属性に指定するオプション(例: cut_indent="yes")があるときだけ有効にするようなアプリケー ションにすべきです。 CutIndentOfMultiLineText 関数の in_Option 引数に g_VBS_Lib.KeepLineSeparators を指定したときも、行末の その他の文字+ LF は、LF の改行に なります。 参考 → XML の改行文字の正規化による副作用 サンプル XML ファイル: cut_indent="yes" は、(対応アプリケーション では)、改行文字の種類によって区別します。 アプリケーションの内部では、このオプションがある ときだけ、CutIndentOfMultiLineText を呼び出します。 Line1 Line2\n Line3\r Line4\r\n XML パーサーの出力: (LF) ^ ^ Line1(LF) ^ ^ ^ Line2\n(LF) ^ Line3\r(LF) ^ Line4\r\n(LF) ^ ^ は、タブ文字 CutIndentOfMultiLineText の返り値: ^ Line1(CR+LF) ^ ^ Line2(LF) Line3(CR) Line4(CR+LF) ソース → vbslib.vbs テスト → T_XML.vbs T_XmlText 関連 → Translate コマンド >> サンプル : 複数行のテキストを翻訳する → MultiTextXML_Class → GetTab → XmlText *********************************************************************** <<< MultiTextXML_Class >>> *********************************************************************** MultiTextXML_Class マルチ・パート・テキストXML ファイルの内容を内部でキャッシュします。 → GetText (MultiTextXML_Class) → IsExist (MultiTextXML_Class) マルチ・パート・テキストXML 複数のテキスト・ファイルを1つにまとめた XML ファイル。 Sample.xml タグ名は、上記と異なるタグ名でも構いませんが、id 属性は必須です。 encoding 属性の設定値は、ファイルの文字コードの設定に合わせてください。 例: UTF-8、UTF-16、Shift_JIS など 参考 → XML ファイルのパス(アドレス)に "Sample.xml#1" を指定すると、下記の文字列が取得できます。 最後に改行が入りますが、アプリケーションによっては最後の改行を1つ削除します。 abc def ファイルのパス(アドレス)に "Sample.xml#second" を指定すると、下記の文字列が取得できます。 最後に改行が入りますが、アプリケーションによっては最後の改行を1つ削除します。 abc def ファイルのパス(アドレス)に "Sample.xml" を指定すると、ファイルの全体の内容が取得できます。 ファイルに同じ id 属性が存在すると、上の方にある部分のみ有効になります。 CutIndentOfMultiLineText 関数 を内部で呼び出しており、id 属性と供に cut_indent 属性が あれば、indent 属性や改行コードも指定することができます。 LF\n CR+LF 先頭文字 (>> *********************************************************************** GetText (MultiTextXML_Class) Function MultiTextXML_Class::GetText( URL as string ) as string マルチ・パート・テキストXML ファイルを、リードします。 【引数】 URL ファイルパス +"#"+ ID属性の値、または、ファイルパス 返り値 テキスト・ブロックの内容 サンプル Set files = new MultiTextXML_Class text = files.GetText( "Files\T_MultiTextXML_1.xml#1" ) ソース → vbslib.vbs テスト → T_XML.vbs T_MultiTextXML *********************************************************************** <<< IsExist (MultiTextXML_Class) >>> *********************************************************************** IsExist (MultiTextXML_Class) Function MultiTextXML_Class::IsExist( URL as string ) as boolean マルチ・パート・テキストXML ファイルに、指定の id があるかどうかを返します。 【引数】 URL ファイルパス +"#"+ ID属性の値、または、ファイルパス 返り値 指定の id があるかどうか サンプル Set files = new MultiTextXML_Class If files.IsExist( "Files\T_MultiTextXML_1.xml#1" ) Then ... ソース → vbslib.vbs テスト → T_XML.vbs T_MultiTextXML_IsExist *********************************************************************** <<< GetXPath >>> *********************************************************************** GetXPath (src) Function GetXPath( DOMObject as IXMLDOMElement, ShowAttrs as string ) as string 指定した XML の DOM オブジェクトがある場所を表す XPath を返します。 【引数】 DOMObject IXMLDOMElement または IXMLDOMAttribute ShowAttrs Empty、または、XPath に含める XML 属性名、またはその配列 返り値 XPath DOMObject 引数が IXMLDOMElement クラスのときは、ルート XML 要素からのパスは含まれます。 DOMObject 引数が IXMLDOMAttribute クラスのときは、ルート XML 要素からのパスは含まれません。 その理由は、標準の DOM の仕様書では、IXMLDOMAttribute クラスから、所属する XML 要素が 取得できないからです。 ShowAttrs 引数に指定した、返り値に含める XML 属性は、XPath に含まれるすべて XML 要素、 つまり、親ノードの XML 要素に対しても、XML 属性を含めます。 サンプル Dim node Dim root : Set root = LoadXML( "sample.xml", Empty ) ' as IXMLDOMElement '// GetXPath( root, Empty ) = "/Root" node = root.selectNodes( "/Root/Test1" ) '// GetXPath( node(0), Empty ) = "/Root/Test1" node = root.selectNodes( "/Root/Test2/@id" ) '// GetXPath( node(0), Empty ) = "@id" node = root.selectNodes( "/Root/Test2[@id='1']/Sub" ) '// GetXPath( node(0), Array("id","attr") ) = _ '// "/Root/Test2[@id='1' and @attr='a']/Sub" 参考 → XPath テスト → T_XML.vbs # [T_XPath] *********************************************************************** <<< GetXmlAttribute >>> *********************************************************************** GetXmlAttribute (src) 廃止されました。 → XmlRead Function GetXmlAttribute( BaseXmlElement, XPathForXmlElement, AttrName ) XML 属性の値を返します。 【引数】 BaseXmlElement XPathForXmlElement の基準となる XML要素(タグ) XPathForXmlElement 属性を変更する XML 要素(タグ) への XPath または Empty AttrName XML 属性の名前 返り値 XML 属性の値、文字列型のみ、Empty=属性なし サンプル: Dim root : Set root = LoadXML( "in.xml", Empty ) ' as IXMLDOMElement value = GetXmlAttribute( root, "./Tag1", "attr1" ) GetXmlAttribute Tag1 attr1 参考 → getAttribute (IXMLDOMElement) → RegRead テスト → T_XML.vbs # [T_GetXmlAttribute] *********************************************************************** <<< XmlWrite >>> *********************************************************************** XmlWrite (src) Function XmlWrite( BaseXmlElement as IXMLDOMElement, XPath as string, Value as string ) as boolean XML のタグの間のテキスト、または XML の属性の値を変更します。 【引数】 BaseXmlElement XPath の基準となる XML要素(タグ) XPath タグの間のテキスト、または XML の属性の位置を表す XPath Value 変更後のテキストまたは XML 属性の値、""=値なし、Empty=削除する 返り値 変化があったかどうか タグの間のテキストは、厳密には XPath = "/Root/Elem/text()" ですが、XPath = "/Root/Elem" を指定 してください。 XPath に指定したタグ(XML要素)が存在しないときは、作成します。 このとき、自動的に改行文字と タブ文字が入ります。 ただし、ルートのXMLタグに xml:space="preserve" があるとき、かつ、タグの開始から 終了までが1行の中にある部分の中に、新規タグを作成するときは、改行文字もタブ文字も入りません。 XPath = "/Root/Elem" (XML要素へのパス)のとき、Value = "" なら、 となります。 XPath = "/Root/Elem" (XML要素へのパス)のとき、Value = Empty なら、 を削除します。 XPath = "/Root/Elem/@attr" (XML属性へのパス)のとき、Value = "" なら、 となります。 XPath = "/Root/Elem/@attr" (XML属性へのパス)のとき、Value = Empty なら、 となります。 サンプル Dim b, is_change, root Set root = LoadXML( "in.xml", Empty ) '// as IXMLDOMElement b= XmlWrite( root, "./Tag1/@attr1", 123 ) is_change = is_change or b If is_change Then root.ownerDocument.save "out.xml" XmlWrite Tag1/@attr1 123 参考 → setAttribute (IXMLDOMElement) → RegWrite テスト → T_XML.vbs # T_XmlWrite 関連 → OpenForReplaceXML → Write (ReplaceXmlFile1) *********************************************************************** <<< XmlWriteEncoding >>> *********************************************************************** XmlWriteEncoding (src) Sub XmlWriteEncoding( RootXmlElement as IXMLDOMElement, CharSet as string ) XML ファイルの文字コードを指定します。 【引数】 BaseXmlElement ルートの XML要素(タグ) CharSet 文字コード → new_TextFileCharSetStack テスト → T_XML.vbs # T_XmlWrite *********************************************************************** <<< XmlInsertAfter >>> *********************************************************************** XmlInsertAfter Sub XmlInsertAfter( in_out_ReferenceNode as IXMLDOMElement, in_NewNode as IXMLDOMElement ) 兄弟関係の次になるように、XML 要素を追加します。 【引数】 in_out_ReferenceNode XPath の基準となる XML要素(タグ) in_NewNode タグの間のテキスト、または XML の属性の位置を表す XPath 返り値 テキストまたは XML 属性の値。文字列型 ソース → vbslib.vbs 関連 → insertBefore (IXMLDOMElement) *********************************************************************** <<< XmlAttr >>> *********************************************************************** XmlAttr (src) Function XmlAttr( s as string ) as string " " で囲む XML の属性値に( 実体参照 に)変換します。 サンプル: s = XmlAttr( "<""'" ) s は、"<"'" になります ' ' で囲むとき → XmlAttrA テスト → T_XML.vbs # [T_XmlText] 関連 → xml プロパティ (vbsool) → StrT_changeToXmlAttr (clib) → ParseAttributesInXML → XPath のエスケープ文字、バックスラッシュ \ *********************************************************************** <<< XmlAttrA >>> *********************************************************************** XmlAttrA (src) Function XmlAttrA( s as string ) as string ' ' で囲む XML の属性値に(実体参照に)変換します。 サンプル: s = XmlAttrA( "<""'" ) s は、"<""'" になります *********************************************************************** <<< XmlText >>> *********************************************************************** XmlText Function XmlText( s as string ) as string XML のテキスト(タグの外)に( 実体参照 に)変換します。 サンプル Assert XmlText( "<""" ) = "<""" ソース → vbslib.vbs テスト → T_XML.vbs T_XmlText 関連 → xml プロパティ (vbsool) → XmlText コマンド → MultiTextXML_Class *********************************************************************** <<< XmlSort >>> *********************************************************************** XmlSort Sub XmlSort( BaseXmlElement as IXMLDOMElement, XPath as string, CompareFunc as function, CompareFuncParam as variant ) XML のタグを並べ替えします。 【引数】 BaseXmlElement XPath の基準となる XML要素(タグ) XPath 並べ替えするタグの位置を表す XPath CompareFunc 比較関数 CompareFuncParam CompareFunc の第3引数 サンプル T タグをソートする。 ソートキーは、T/EN。 Sub Main() Set root = LoadXML( "Sample.xml", Empty ) XmlSort root, "T", GetRef( "SampleCompare" ), Empty End Sub Function SampleCompare( in_LeftTag, in_RightTag, in_Parameter ) left_text = in_LeftTag.selectSingleNode( "./EN/text()" ).nodeValue right_text = in_RightTag.selectSingleNode( "./EN/text()" ).nodeValue SampleCompare = StrComp( left_text, right_text, 1 ) End Function 日本語2.Japanese 英語3.English 仏語1.French 仏語1.French 日本語2.Japanese 英語3.English ソース → vbslib.vbs テスト → T_XML.vbs T_XmlSort *********************************************************************** <<< ObjToXML >>> *********************************************************************** ObjToXML (src) Function ObjToXML( TagName as string, Objs as object or array, Opt as variant ) as string オブジェクトの基本的なデータを XML 文字列に変換します。 【引数】 TagName ルート・タグ名、Empty にすると、ルートタグを追加しません。 Objs XML データの内容にするオブジェクト、またはその配列 Opt Empty を指定してください 返り値 XML 文字列 サンプル: s = ObjToXML( Empty, obj, Empty ) オブジェクトのクラス名と、Name プロパティ、DefinePath プロパティから XML データを作成します。 他のプロパティも含んだ XML データは、xml プロパティを作成してください。 関連 → xml プロパティ (vbsool) → SetDefinePath → GetTab *********************************************************************** <<< ChangeToXml >>> *********************************************************************** ChangeToXml (src) Function ChangeToXml( XML as string or object ) as IXMLDOMElement IXMLDOMElement XML 文字列などを、XML 要素オブジェクトに変換します。 参考 → loadXML メソッド (vbsool) 引数に指定できるものは、次のものがあります。 ・XML が記述された文字列 ・ XML ファイルをロードする LoadXML などで取得した IXMLDOMElement ・ParentProcess や ChildProcess → /ChildProcess オプション *********************************************************************** <<< SetXmlAttribute >>> *********************************************************************** SetXmlAttribute (src) 廃止されました。 → XmlWrite Function SetXmlAttribute( BaseXmlElement as IXMLDOMElement, XPathForXmlElement as string, AttrName as string, AttrValue as string ) as boolean XML 属性の値を変更します。 【引数】 BaseXmlElement XPathForXmlElement の基準となる XML要素(タグ) XPathForXmlElement 属性を変更する XML 要素(タグ) への XPath または Empty AttrName XML 属性の名前 AttrValue 変更後の XML 属性の値、""=値なし、Empty=属性を削除する 返り値 変化があったかどうか XPathForXmlElement に該当する XML 要素が複数あったときは、すべての XML 要素の属性を変更 します。 XPathForXmlElement に該当する XML 要素が無かったときは、XML 要素を追加します。 サンプル: Dim b, is_change Dim root : Set root = LoadXML( "in.xml", Empty ) '// as IXMLDOMElement b= SetXmlAttribute( root, "./Tag1", "attr1", "1234" ) is_change = is_change or b If is_change Then root.ownerDocument.save "out.xml" SetXmlAttribute Tag1 attr1 1234 参考 → setAttribute (IXMLDOMElement) → RegWrite テスト → T_XML.vbs # T_SetXmlAttribute *********************************************************************** <<< UpdateLineAttributeInXML >>> *********************************************************************** UpdateLineAttributeInXML キーワード: line_num Sub UpdateLineAttributeInXML( in_Path as string, in_AttributeName as string ) XML ファイルの中の行番号を値に持つ XML属性の値を、実際の行番号に合わせます。 【引数】 in_Path 内容を置き換える XML ファイルのパス in_AttributeName "@"+ XML属性の名前 内部で XML の構文解析は行いません。 単純に置き換えているだけです。 サンプル スクリプト: UpdateLineAttributeInXML "Sample.xml", "@line_num" Sample.xml ファイルを処理する前: Sample.xml ファイルを処理した後: line_num="999" line_num="4" ソース → vbslib.vbs テスト → T_XML.vbs T_UpdateLineAttributeInXML *********************************************************************** <<< 関連 >>> *********************************************************************** 関連 → new_LazyDictionaryClass XML の Variable タグ → ToRegularXML XML ファイルを整形します *********************************************************************** <<< 関連 >>> *********************************************************************** 関連 バイナリ ファイル → BinaryArray クラス レジストリ ファイル → OpenForRegFile 文字列 TextStream → StringStream クラス メイク ファイル → MakeFileClass (メイクファイル) *********************************************************************** <<< プロセス制御と include >>> *********************************************************************** [ テスト ] プロセス制御と include 新プロセス → start 指定したコマンドラインを新プロセスで実行します。 終了を待ちません。 → RunProg 指定したコマンドラインを新プロセスで実行します。 終了を待ちます。 → sudo 管理者権限を持った新プロセスで実行します。 終了を待ちます。 → env 環境変数を展開します → ArgumentExist コマンドライン・オプションが指定されているかどうかを返します。 → GetWScriptArgumentsUnnamed コマンドラインの引数を返します。 (改良版) 現在のプロセスのまま → call_vbs 指定した VBScript ファイルの中の関数を呼び出し、終了するまで待ちます。 → include クラス定義や関数定義が入った VBSファイルをインクルードします。 → IsDefined 指定したシンボルの関数が定義されているかどうかを返します。 待ち → Sleep 指定した時間だけ待ちます。 → WaitForFile 指定したファイルが作られるまで待ちます。 他にもあります。左のツリーから選択してください。 関連 → 正常終了時の動作 → エラー発生時の動作 → プログラム起動 (VBS) → バージョン判定、環境変数 → g_debug_params *********************************************************************** <<< start >>> *********************************************************************** start (src) Sub start( cmdline as string ) 指定したコマンドラインを新プロセスで実行します。 終了を待ちません。 CPU がマルチコアであれば、複数のプロセスによる並列処理になり高速になります。 サンプル: start """%ProgramFiles%\Movie Maker\moviemk.exe""" コマンドラインでは、パスをダブルクォーテーションで囲むこと サンプル: Dim cmd cmd = Setting_getEditorCmdLine( 1 ) cmd = Replace( cmd, "%1", "C:\file.txt" ) start cmd Setting_getEditorCmdLine cmdline 引数にフォルダやデータファイルのパスを指定すると、そのフォルダや ファイルをダブルクリックしたときと同じように開きます。 start の後にすぐに終了すると、開けないことがあります。 Sleep で、すぐに終了しないようにしてください。 cmdline 引数に環境変数を含めることができます。 (%var% 形式) ファイルが見つからないと、E_WIN32_FILE_NOT_FOUND エラーになります ホームページを開く start "http://www.example.com/" start """C:\Program Files\Internet Explorer\iexplore.exe"" "+ a_URL start で実行した内容のログを取る start "cmd.exe /C cscript //nologo sample.vbs | "+ g_vbslib_ver_folder +_ "safetee\safetee.exe -o Sample_out.txt & exit" safetee cmd.exe /C を経由して実行してください。 > でリダイレクトすると内容が表示されない ので、パイプを経由して safetee(または tee)を実行してください。 また、パイプを 使う場合、実行後にウィンドウが残らないように、exit してください。 start 関数から別の関数を呼び出すとき cmdline 引数に、\?InCurrentProcessFunc\(関数名) を指定すると、指定した関数を 呼び出します。 呼び出した関数から返ると、start 関数から戻ります。 キーワード: InCurrentProcessFunc start するプロセスにパラメーターを渡す → g_InputCommand_Args テスト → T_Start_Manually.vbs # [T_StartErr] 関連 → IShellDispatch2::ShellExecute → GetCScriptGUI_CommandLine *********************************************************************** <<< RunProg >>> *********************************************************************** RunProg (src) Function RunProg( cmdline as string, stdout_stderr_redirect as string ) as integer 指定したコマンドラインを新プロセスで実行します。 終了を待ちます。 【引数】 cmdline コマンドライン(実行ファイルパス+パラメータ) stdout_stderr_redirect 出力先のファイルパス(下記) 返り値 エラーレベル(main 関数の返り値) プロセスが終了するまで、関数内部で待ちます。 新プロセスのカレントフォルダは、RunProg を呼び出す直前のカレントフォルダーになります。 cmdline 引数に指定した実行ファイルやスクリプトファイルがあるフォルダーではありません。 → g_start_in_path コマンドプロンプトから標準入力するプログラムは、停止してしまいます。 下記のいずれかの回避策を行ってください。 対策 → Shell::Exec (VBS) 実証コード → T_Call\TryExec.vbs → Run (Shell) 新しいウィンドウが開き、標準入力ができます → input (vbslib) → RunBat 入力が要求されていないのに止まるとき 関連 → 正常終了時の動作 → エラー発生時の動作 → CheckTestErrLevel → sudo (管理者として起動) stdout_stderr_redirect 引数 一般的なシェルと異なり、リダイレクトしても標準出力へも出力されます。 Empty や "" のときは、標準出力へ出力し、ファイルに保存しません。 "nul" のときは、標準出力へ出力せず、出力内容を破棄します。 EchoOff オブジェクト を使っても出力しなくなりますが、ファイルに保存できます。 g_VBS_Lib.NotEchoStartCommand を指定したときは、RunProg 自体の echo 出力は しなくなりますが、RunProg から実行するプログラムは、echo 出力されます。 表示されるはずの echo 出力が表示されないときは、 → Run (Shell) ただし、新しいウィンドウが開きます。 表示内容をテストするときは、 → AssertFC → ログ 補足 VBScript を実行するときは、cscript を経由してください。 vbslib の input などを使っているときは、/GUI_input:1 または /set_input を指定してください。 RunProg "cscript //nologo sample.vbs /GUI_input:1", "" VBScript をデバッガに接続するときは、下記のように //x を付けてください。 RunProg "cscript //x sample.vbs", "" コマンド・プロンプトで使えるコマンドを実行するときは、次のようにしてください。 RunProg "cmd /c (dir > files.txt)", "" 複数のコマンドを実行するときは、& をつけてください。 RunProg "cmd /c (cd sub & dir > ..\files.txt)", "" ダブル クォーテーションを指定するときは、\' を指定してください。 RunProg "cscript sample.vbs \'/Option\'", "" sample.vbs に、名前なし引数(オプション以外)である、/Option という文字列が 渡ります。 → GetWScriptArgumentsUnnamed 複数のコマンドをバッチファイルのように記述するときは → RunBat バッチファイルを実行するときは、次のようにしてください。 (pause など、標準入力するコマンドを使わないようにしてください) カレント・ディレクトリを調整してから RunProg を呼び出してください。 RunProg "batch1.bat", "" RunProg "batch1.bat /close", "" 閉じないバッチファイルは、閉じるようにする start "cmd.exe /C ""batch1.bat""" 参考 → コマンドプロンプトを自動的に閉じないバッチファイル RunProg したプロセスAが、子プロセスBを生成したとき、プロセスAが終了しても、プロセスB が終了していなければ、RunProg から戻りません。 SysWOW64\cscript.exe から cscript (cscript のフォルダー指定なし)を RunProg したときは、 SysWOW64\cscript.exe が起動します。 Run (Shell) から cscript を起動したときは、system32\cscript.exe (64bit版) が起動します。 g_ChildHead Dim g_ChildHead as string 新プロセスが標準出力へ出力する内容を表示するときに、行頭に追加する文字列。 デフォルトは、何も追加しません。 グローバル変数です。 関連 → Run (Shell) → Exec (Shell) → CheckTestErrLevel → 子プロセスへの受け渡し (/ChildProcess オプション) → RunProg (clib) → TempParams.txt - C言語のプログラムにデータを渡す → ArgsLog テスト → T_RunProg.vbs → T_DebugVBS_Manual.vbs *********************************************************************** <<< RunBat >>> *********************************************************************** RunBat Function RunBat( CommandLines as string, Redirect as string ) as integer 指定したバッチを新プロセスで実行します。 終了を待ちます。 【引数】 CommandLines バッチファイルに記述する内容 Redirect 出力先のファイルパス, "" または Empty で標準出力のみ 返り値 エラーレベル バッチを終了するときは、goto :eof を使わずに、最後の行に到達するようにしてください。 ソース → vbslib.vbs サンプル r= RunBat( _ "nmake -f makefile" +vbCRLF+_ "@if errorlevel 1 goto fin" +vbCRLF+_ "del *.obj" +vbCRLF+_ ":fin", _ Empty ) If r <> 0 Then Raise 1, "" If not exist( "sample.dll" ) Then Fail 関連 → バッチファイルを実行するとき → RunBatAsync *********************************************************************** <<< RunBatAsync >>> *********************************************************************** RunBatAsync Function RunBatAsync( CommandLines as string ) as RunBatAsyncClass 指定したバッチを新プロセスで実行します。 終了を待ちません。 【引数】 CommandLines バッチファイルに記述する内容 返り値 実行状況を確認するためのオブジェクト 返り値の .Status と .ExitCode は、 Exec (Shell) の返り値と同じです。 バッチを終了するときは、goto :eof を使わずに、最後の行に到達するようにしてください。 RunBatAsync は、echo 出力されません。 デバッグ用に echo 出力を確認したいときは、一時的に RnuBat を使用してください。 ソース → vbslib.vbs サンプル Set exec = RunBatAsync( _ "copy a.txt b.txt" +vbCRLF+_ "goto :fin" +vbCRLF+_ ":fin" +vbCRLF+_ "" ) Do If exec.Status = g_VBS_Lib.WshFinished Then echo exec.ExitCode Exit Do End If Loop テスト → T_Download.vbs T_SetVirtualFileServer_Files VirtualServerAtLocal::DownloadAsyncExec の中で使用 *********************************************************************** <<< CompileCSharp >>> *********************************************************************** CompileCSharp Function CompileCSharp( in_SourceFilePath as string ) as CompileCSharpClass C#言語のソース ファイルをコンパイルします。 【引数】 in_SourceFilePath C#言語のソース ファイルのパス 返り値 → CompileCSharpClass サンプル → CompileCSharpClass ソース → System.vbs テスト → T_CS_Script.vbs *********************************************************************** <<< CompileCSharpClass >>> *********************************************************************** CompileCSharpClass CompileCSharp 関数 の返り値。 C#言語をコンパイルした実行ファイル。 サンプル *********************************************************************** <<< sudo >>> *********************************************************************** sudo (src) Function sudo( CmdLine as string, OperationName as string, StdoutStderrRedirect as string ) as integer 指定したコマンドラインを管理者権限を持った新プロセスで実行します。 終了を待ちます。 【引数】 CmdLine コマンドライン(実行ファイルパス+パラメータ) OperationName ユーザーが行おうとしている処理の名前 StdoutStderrRedirect "" を指定してください 返り値 エラーレベル(main 関数の返り値) Windows Vista/7 の場合 Windows Vista/7 では、起動する直前に、下記のメッセージを出力します。 更にユーザー アクセス制御(UAC)による管理者への昇格の許可も求められます。 ユーザーが心配 しないよう、OperationName 引数に、行おうとする処理の名前を的確に指定してください。 サンプルコード: sudo "cscript CopyProgram.vbs", _ "Sample アプリケーションのインストール", "" sudo が出すメッセージ (実行前) ------------------------------------------------------------------------------- [ UAC(ユーザーアカウント制御)予告(詳細) ] 詳細情報1: "C:\home\InstallSample.vbs" 詳細情報2: C:\home> cscript CopyProgram.vbs ------------------------------------------------------------------------------- [ UAC(ユーザーアカウント制御)予告 ] 『Sample アプリケーションのインストール』という処理の続きを "管理者権限ランチャー (sudo.exe)"から実行します。 これが、あなたがしようとしている処理と異なるときや、あいまいな処理名のときは、 終了してください。 続行するには Enter キーを押してください . . . ↓ Enter キーを押すと ↓ 「はい」 をクリックすると sudo に指定したプログラム、cscript CopyProgram.vbs を、新規プロセスで起動 ↓ プログラムが終了したら sudo が出すメッセージ (実行後) 管理者権限で行う処理が完了し、管理者権限は失効しました。 2秒間表示されます。 Windows XP の場合 Windows XP では、管理者へログインする設定にすると、起動時に管理者のパスワードを 入力するようになります。 自分が管理者であるときは、入力を求められません。 未対応 デバッガに接続するには sudo で起動する .vbs スクリプトのプロセスをデバッグするときは、CmdLine 引数に、 cscript のオプション //x 、または /g_debug オプションを付けてください。 sudo "cscript //x CopyProgram.vbs", _ "Sample アプリケーションのインストール", "" sudo "cscript CopyProgram.vbs /g_debug:1", _ "Sample アプリケーションのインストール", "" 内部コールツリー 通常時 T_sudo_c_Manual.vbs 親プロセス、一般ユーザー sudo (vbs) "cscript T_sudo_c_target.vbs" sudo.exe cmd /C "temporary.bat" 子プロセス、管理者 cmd /C "temporary.bat" 孫プロセス、管理者 wscript T_sudo_c_target.vbs ひ孫プロセス、管理者 cscript T_sudo_c_target.vbs 玄孫プロセス、管理者 if not ""%errorlevel%""==""21"" pause エラー時に pause する echo %errorlevel% > errorlevel.txt デバッガ使用時 T_sudo_c_Manual.vbs 親プロセス、一般ユーザー sudo (vbs) "cscript //x T_sudo_c_target.vbs" sudo.exe cmd /C "cscript //x ***.vbs" /debug:1 子プロセス、管理者 cscript ***.vbs 孫プロセス、管理者、デバッガ接続 テスト → T_sudo フォルダ If GetOSVersion() >= 6.0 Then 未対応 関連 → g_admin *********************************************************************** <<< sudo_del_copy >>> *********************************************************************** sudo_del_copy (src) Sub sudo_del_copy( in_SudoScriptPath as string, in_OperationName as string, in_SourceFullPath as string, in_DestinationFullPath as string, Option_ as Empty ) 管理者権限が必要なら、権限を取得して、フォルダーを置き換えます。 【引数】 in_SudoScriptPath 一時的に作成する管理者権限で実行するスクリプトのパス in_OperationName ユーザーが行おうとしている処理の名前 in_SourceFullPath 置き換えた後の内容が入ったフォルダーのフル パス in_DestinationFullPath 置き換える対象のフォルダーのフル パス Option_ Empty、または、除外する相対パスの配列 管理者権限が必要かどうかは、in_DestinationFullPath が Program Files または Program Files (x86) フォルダーの中にあるかどうかを内部で判定します。 Option_ 引数に文字列の配列を指定すると、その文字列が相対パスとして、そのパスにある ファイルやフォルダーを削除しません。 in_SourceFullPath 引数が指すフォルダーにあるときの 動作は未定義です。 *********************************************************************** <<< env >>> *********************************************************************** env (src) Function env( s as string ) as string %〜% で囲まれた環境変数の名前を環境変数の値に展開します。 SetVar で設定した環境変数も展開します。 サンプル: path = env( "%windir%" ) 環境変数 windir を展開する サンプル: path = env( "%windir%\system32" ) 環境変数以外も指定できます。 引数に Empty が指定されると Empty を返します。 指定した環境変数が定義されていないときは、エラー E_NotFoundSymbol = &h80041006 になり ます。 %% は、% に置き換わります。 %0〜%9 は展開しません。 また、閉じる % も不要です。 引数に配列を指定すると、それぞれの配列要素にある環境変数を展開します。 paths = env( Array( "%windir%", "%windir%\system32" ) ) Assert IsSameArray( paths, Array( "C:\Windows", "C:\Windows\system32" ) ) ローカル環境変数の値が配列のとき、配列要素に環境変数があれば、それも展開します。 SetVar "VarA", 1 SetVar "VarB", 2 SetVar "VarC", Array( "X%VarA%X", "X%VarB%X" ) Assert IsSameArray( env("%VarC%"), Array( "X1X", "X2X" ) ) 関連 → SetVar → GetVar → SetVarBreak → LoadEnvVars → SaveEnvVars → VarStack → 環境変数を取得する (ExpandEnvironmentStrings) → Environment (Shell) (VBScript) → 環境変数を参照する (Excel) テスト → T_Var.vbs # [T_Var1] *********************************************************************** <<< ArrayFromCmdLine >>> *********************************************************************** ArrayFromCmdLine (src) Function ArrayFromCmdLine( CmdLine as string ) as array of string コマンドラインの1行を解析して、それぞれの項目を配列に格納する。 【引数】 CmdLine コマンドラインの1行 返り値 (出力)それぞれの項目が入った配列 サンプル For Each column In ArrayFromCmdLine( "Sample.exe ""file (1).txt"" /opt1:2" ) echo column Next 上記 ArrayFromCmdLine の返り値は、Array( "Sample.exe", "file (1).txt", "/opt1:2" ) それぞれの項目は、空白文字によって分割されます。 abc def abc def タブルクォートの中にある空白文字は、項目の分割になりません。 両端のダブルクォートは、項目に含まれません。 ダブルクォートは閉じてなくても構いません。 abc "def ghi" "j k abc def ghi j k タブルクォートで囲まれている部分の前または後が空白文字ではないときは、それらも 1つの項目の中に含まれます。 その際、ダブルクォート文字は含まれません。 abc"def" ab"c d"ef abcdef abc def ダブルクォート文字を項目に含めるときは、\" と記述します。 " " で囲まれた中でも外でも同じです。 ab\"cd "12\"34" ab"cd 12"34 \ の直後が " ではないときは、\ が連続していても、そのまま項目に入ります。 \\pc\n \\pc\n \ が n 文字あって直後に " があるときは、n が偶数なら、\ 文字が n/2 文字と " " の 囲みの開始になります。 n が奇数なら、\ 文字 (n-1)/2 文字と " 文字になります。 " " で囲まれた中でも外でも同じです。 \" \\\" \\\\\" \\"a b" \\\\"c d" " \" \\" \a b \\c d "\" \\\" \\\\\" \\"a b" \\\\"c d" " \" \\" \a b \\c d 参考 → cmd.exe のコマンドラインの仕様を解析してみた - 永遠に未完成 (Web) → コマンドラインの引数とエスケープ テスト → T_CmdLine.vbs # [T_ArrayFromCmdLine] 関連 → ArrayFromCSV → ParseCmdLine → Split その他の形式から配列 → ArgsLog パラメーターを記録する → ArrayFromBashCmdLine → パラメータ (コマンドライン), Arguments, args → CmdLineFromStr *********************************************************************** <<< ArrayFromCmdLineWithoutOpt >>> *********************************************************************** ArrayFromCmdLineWithoutOpt Function ArrayFromCmdLineWithoutOpt( CmdLine as string, OptionSigns as variant ) as array of string コマンドラインの1行を解析して、オプション以外の項目を配列に格納する。 【引数】 CmdLine コマンドラインの1行 OptionSigns オプション記号の配列、または Empty(= "/", "-") 返り値 (出力)それぞれの項目が入った配列 サンプル arr = ArrayFromCmdLineWithoutOpt( "Sample.exe ""file (1).txt"" /opt1:2 param2", Empty ) 上記 ArrayFromCmdLineWithoutOpt の返り値は、Array( "Sample.exe", "file (1).txt", "param2" ) *********************************************************************** <<< DicFromCmdLineOpt >>> *********************************************************************** DicFromCmdLineOpt (src) Function DicFromCmdLineOpt( CmdLine as string, OptionNames as array of string ) as dictionary of string or True コマンドラインの1行を解析して、オプション名をキーとした辞書を返します。 【引数】 CmdLine コマンドラインの1行 OptionNames オプション名の配列 返り値 (出力)オプション名をキーとした辞書 オプションではないパラメーターは、キー "no name" の、配列型の値に格納されます。 オプションは、キーがオプション名、値が文字列型、True、Empty のいずれかになります。 サンプル Dim params : Set params = DicFromCmdLineOpt( _ "Sample.exe /opt1:2 -flag param", Array( "/opt1", "-flag", "/no_opt" ) ) Assert IsSameArray( params( "no name" ), Array( "Sample.exe", "param" ) Assert params( "/opt1" ) = "2" Assert params( "-flag" ) = True Assert params( "-flag" ) Assert not params( "/no_opt" ) Assert IsEmpty( params( "/no_opt" ) ) オプション名と値の間に空白文字が含まれる場合は、OptionNames に指定する オプション名の後に ":" (コロン)を付けてください。 Dim params : Set params = DicFromCmdLineOpt( _ "-o value1 value2", Array( "-o:" ) ) Assert params( "-o" ) = "value1" Assert IsSameArray( params( "no name" ), Array( "value2" ) 複数指定ができるオプションは、OptionNames に指定するオプション名の後に "::" (コロン×2)を付けてください。 このとき、辞書の値は配列になります。 Dim params : Set params = DicFromCmdLineOpt( _ "-o value1 -ovalue2", Array( "-o::" ) ) Assert IsSameArray( params( "-o::" ), Array( "value1", "value2" ) ) テスト → T_CmdLine.vbs # [T_DicFromCmdLineOpt] 関連 → GetCommandLineOptionValue *********************************************************************** <<< MeltCmdLine >>> *********************************************************************** MeltCmdLine (src) Function MeltCmdLine( Line as string, in_out_Start as integer ) as string コマンドラインの1項目を取り出し、通常の文字列に戻す。 【引数】 CmdLine コマンドラインの内容 in_out_Start (入力) 取り出しを開始する文字の位置、(出力)次に取り出す〜 返り値 取り出したコマンドラインの1項目 次の項目が無いときは、in_out_Start=0 になります。 サンプル サンプルデータ i = 1 Do s = MeltCmdLine( cmdline, i ) If i = 0 Then Exit Do Loop sample.exe param1 "param 2" 次の順番で返ります sample.exe param1 param 2 サンプル Assert MeltCmdLine( """double_quotation""", 1 ) = "double_quotation" テスト → T_CmdLine.vbs # [T_MeltCmdLine] 関連 → ArrayFromCSV → MeltQuot → Split → CmdLineFromStr *********************************************************************** <<< ParseCmdLine >>> *********************************************************************** ParseCmdLine 未対応 Function ParseCmdLine( CmdLine as string ) as CmdLineArgs コマンドラインが入った文字列を解析して、それぞれの引数を配列などに格納する。 【引数】 CmdLine コマンドライン 返り値 引数にアクセスするオブジェクト → CmdLineArgs クラス 現在のスクリプトを起動したときのコマンドラインではない、コマンドラインの内容に アクセスしやすくします。 サンプル Set args = ParseCmdLine( line ) サンプルデータ sample.exe param1 "param 2" 次のように分割されます sample.exe param1 param 2 関連 → WScript.Arguments → GetCmdLine → MeltCmdLine → Split → ArrayFromCSV *********************************************************************** <<< CmdLineArgs クラス >>> *********************************************************************** CmdLineArgs クラス 未対応 取得 → ParseCmdLine メンバー WScript.Arguments に準拠 *********************************************************************** <<< GetWScriptArgumentsUnnamed >>> *********************************************************************** GetWScriptArgumentsUnnamed Function GetWScriptArgumentsUnnamed() as array of string コマンドラインの引数 WScript.Arguments.Unnamed を返します。 (改良版) コマンドラインに特殊な書き方をすることで、/ から始まる POSIX 形式のパスや、名前付き引数 (オプション)を、名前なし引数として(オプションと分けて)受け取ることができます。 VBScript WSH を起動するコマンドラインの引数にダブルクォーテーションを含めることはできませんが、 本関数によるエスケープ文字の処理をすることで引数にダブルクォーテーションを含めることができ、 また、/ から始まる引数の両端のダブルクォーテーションは削除されます。 詳細は下記。 参考 → WSH の WScript.Arguments の引数の区切り、ダブルクォーテーションの指定 → コマンドラインの引数とエスケープ (DOS) サンプル コマンドライン: cscript sample.vbs \'quoted\' \'/directory\' /option "http://www.example.com" VBScript : Set args = GetWScriptArgumentsUnnamed() Assert args.Count = 3 Assert args(0) = """quoted""" Assert args(1) = "/directory" Assert args(2) = "http://www.example.com" \' → " の変換の詳細 (ダブル クォーテーションへの変換) コマンドライン(vbslib を使うスクリプトを呼び出すコマンドライン)の中に、1文字以上の \ 文字と それに続く ' 文字(シングルクォーテーション)があると、" に変換された引数が返ります。 コマンドラインから vbslib が受け取るパラメーターに " や \' を含めたいときは、\' や \\' のように 下記の逆変換をした文字列をコマンドラインに指定します。 変換のサンプルを以下に示します。 vbslib 独自の書き方ですが、コマンドラインの \ 文字とそれに 続く " 文字による処理とほぼ同じで、\ に続く文字だけが異なります。 基本的な変換例: \' → " 詳細な変換例: 逆変換の仕方 \' → " \\' → \' \\\' → \" \\\\' → \\' \ → \ \\ → \\ \\\ → \\\ \others → \others \\others → \\others \\\others → \\\others … " を \' に置き換える … ' の前の \ を2倍の数の \ に置き換える … " の前の \ を2倍の数の \ に、" を \' に置き換える … ' の前の \ を2倍の数の \ に置き換える \'\\'\' → "\'" → "'" \'/ や、\'\\ から始まるときは、"/a" → /a の変換を参照 "/a" → /a の変換の詳細 (ダブル クォーテーションの削除) \' → " の変換をした後が、"/ から始まると、両端の " がなくなった引数が返ります。 また、 "\ から始まる引数は、" から始まるようになります。 "\ の変換は、"/ から始まっても両端の " を なくさない引数を返せるようにするためです。 変換のサンプルを以下に示します。 基本的な変換例: 左記の A → B → C は、 A. コマンドラインの引数 B. \' → " の変換後(内部) C. GetWScriptArgumentsUnnamed 関数の返り値 \'/a\' → "/a" → /a 詳細な変換例: \'/a\' → "/a" → /a \'a\' → "a" → "a" \'\/a\' → "\/a" → "/a" \'\\a\' → "\\a" → "\a" \'\\\a\' → "\\\a" → "\\a" \'\\\\a\' → "\\\\a" → "\\\a" \'\xa\' → "\xa" → "xa" \'\\'\' → "\'" → "'" \'\\\'\' → "\"" → """ \'\\\\'\' → "\\'" → "\'" \'\\\\\'\'→ "\\"" → "\"" \'\\/a\' → "\\/a" → "\/a" t\'/a\' → t"/a" → t"/a" t/a → t/a → t/a \'/a → "/a → /a \a → \a → \a /a → (返らない) ソース → vbslib.vbs テスト → T_CmdLine.vbs T_GetWScriptArgumentsUnnamed *********************************************************************** <<< GetWScriptArgumentsNamed >>> *********************************************************************** GetWScriptArgumentsNamed Function GetWScriptArgumentsNamed( OptionName as string ) as string コマンドラインのオプション引数 WScript.Arguments.Named を返します。 【引数】 OptionName コマンドラインに指定するオプションの名前 返り値 オプションの値 VBScript WSH を起動するコマンドラインの引数にダブルクォーテーションを含めることはできませんが、 本関数によるエスケープ文字の処理をすることで引数にダブルクォーテーションを含めることができます。 参考 → GetWScriptArgumentsUnnamed ダブルクォーテーションの指定方法 ソース → vbslib.vbs テスト → T_CmdLine.vbs T_GetWScriptArgumentsUnnamed *********************************************************************** <<< ParseWScriptArgumentQuotation >>> *********************************************************************** ParseWScriptArgumentQuotation Function ParseWScriptArgumentQuotation( Value as string ) as string WScript.Arguments に入っている値に、エスケープ文字の処理をしたものを返します。 【引数】 Value WScript.Arguments に入っている値 返り値 エスケープ文字の処理をした Value VBScript WSH を起動するコマンドラインの引数にダブルクォーテーションを含めることはできませんが、 本関数によるエスケープ文字の処理をすることで引数にダブルクォーテーションを含めることができます。 参考 → GetWScriptArgumentsUnnamed ダブルクォーテーションの指定方法 ソース → vbslib.vbs テスト → T_CmdLine.vbs T_ParseWScriptArgumentQuotation *********************************************************************** <<< ArrayFromBashCmdLine >>> *********************************************************************** ArrayFromBashCmdLine (src) Function ArrayFromBashCmdLine( CmdLine as string ) as array of string bash シェルのコマンドラインの1行を解析して、それぞれの項目を配列に格納する。 ArrayFromCmdLine の bash 版です。 テスト → T_CmdLine.vbs # [T_ArrayFromBashCmdLine] *********************************************************************** <<< MeltBashCmdLine >>> *********************************************************************** MeltBashCmdLine (src) Function MeltBashCmdLine( Line as string, in_out_Start as integer ) as string bash シェルのコマンドラインの1項目を取り出し、通常の文字列に戻す。 MeltCmdLine の bash 版です。 テスト → T_CmdLine.vbs # [T_ArrayFromBashCmdLine] *********************************************************************** <<< CmdLineFromStr >>> *********************************************************************** CmdLineFromStr Function CmdLineFromStr( Str as string or array ) as string 文字列、または文字列の配列から、コマンドラインを作成します。 【引数】 Str 文字列、または文字列の配列 返り値 コマンドライン ファイル: vbslib.vbs ・ ・ それぞれの配列要素は、空白で区切ります。 文字列に空白や >, <, ^, | 記号を含むときは、" " で囲みます。 文字列にダブル・クォーテーションや \ 記号があるときは、それらの文字が、これから 起動するプログラムに渡るように \ を追加します。 → \' → " の変換の詳細 (ダブル クォーテーションへの変換) サンプル cmd = CmdLineFromStr( Array( "findstr", "/C:""quot and space""", "*" ) ) Assert cmd = "findstr ""/C:\""quot and space\"""" *" ソース → vbslib.vbs テスト → T_CmdLine.vbs # [T_CmdLineFromStr] 関連 → ArgsLog → ArrayFromCmdLine → MeltCmdLine *********************************************************************** <<< GetCmdLine >>> *********************************************************************** GetCmdLine (src) Function GetCmdLine() as string 現在のスクリプトを起動したときのコマンドラインを返します。 実行ファイル名と、パラメーターの両方を含みます。 関連 → WScript.Arguments → ParseCmdLine → g_debug_params *********************************************************************** <<< ArgumentExist >>> *********************************************************************** ArgumentExist (src) Function ArgumentExist( Name as string ) as boolean 指定した名前のコマンドライン・オプションが指定されているかどうかを返します。 【引数】 Name コマンドライン・オプション名 返り値 オプションが指定されているかどうか サンプル: If ArgumentExist( "Opt1" ) Then ... パラメーターが必須のオプションには、ArgumentExist を呼ぶ必要はありません。 /Opt1:1 ではなく /Opt1 では、WScript.Arguments.Named.Item("Opt1") は Empty を返し、/Opt1 を指定しなかったときと、区別ができません。 ArgumentExist は、区別ができます。 Name の大文字小文字は区別します。 関連 → パラメータを取得する (VBS) WScript.Arguments.Unnamed(0) WScript.Arguments.Named.Item( "Opt1" ) WScript.Arguments.Named( "Opt1" ) → GetCommandLineExist (clib) → GetArgvNamed (clib) → g_debug_params *********************************************************************** <<< GetCommandLineOptionName >>> *********************************************************************** GetCommandLineOptionName (src) Function GetCommandLineOptionName( OneParameter as string ) as string オプション名+値から、オプション名を返します。 【引数】 OneParameter オプション名+値 返り値 オプション名 サンプル: name = GetCommandLineOptionName( "/OptionA:12" ) '// name = "OptionA" テスト → T_CmdLine.vbs # [T_CommandLineOption] *********************************************************************** <<< GetCommandLineOptionValue >>> *********************************************************************** GetCommandLineOptionValue (src) Function GetCommandLineOptionValue( OneParameter as string ) as string オプション名+値から、値を返します。 【引数】 OneParameter オプション名+値 返り値 値 サンプル: value = GetCommandLineOptionValue( "/OptionA:12" ) '// value = "12" value = GetCommandLineOptionValue( "/OptionA:""C:\Program Files""" ) '// value = "C:\Program Files" テスト → T_CmdLine.vbs # [T_CommandLineOption] *********************************************************************** <<< ModifyCmdLineOpt >>> *********************************************************************** ModifyCmdLineOpt (src) Function ModifyCmdLineOpt( CmdLine as string, OptionName as string, NewOptionNameAndParam as string ) as string コマンドラインの1行にある、オプションの値を変更します。 【引数】 CmdLine コマンドラインの1行 OptionName オプション名 NewOptionNameAndParam オプション名と、変更後の値。 削除=Empty 返り値 (出力) 変更後のコマンドラインの1行 サンプル -Opt2 オプションの値を変更する new_cmdline = ModifyCmdLineOpt( "-Opt1 -Opt2:ValueA Value1", "-Opt2", "-Opt2:ValueB" ) Assert new_cmdline = "-Opt1 -Opt2:ValueB Value1" -Opt2 オプションを無くす new_cmdline = ModifyCmdLineOpt( "-Opt1 -Opt2:ValueA Value1", "-Opt2", Empty ) Assert new_cmdline = "-Opt1 Value1" -Opt2 オプションがなければ追加する new_cmdline = ModifyCmdLineOpt( "-Opt1 Value1", "-Opt2", "-Opt2:ValueB" ) Assert new_cmdline = "-Opt1 -Opt2:ValueB Value1" -Opt2 オプションと、その値の間が空白のときは、OptionNmae 引数の末尾に ":"(コロン)を付ける new_cmdline = ModifyCmdLineOpt( "-Opt1 -Opt2 ValueA Value1", "-Opt2:", "-Opt2 ValueB" ) Assert new_cmdline = "-Opt1 -Opt2 ValueB Value1" 複数指定できる -o オプションを追加するときは、OptionNmae 引数の末尾に "::"(コロン×2)を付ける new_cmdline = ModifyCmdLineOpt( "-o ValueA -o ValueB Value1", "-o::", "-o NewValue" ) Assert new_cmdline="-o NewValue -o ValueA -o ValueB Value1" 複数指定できる -o オプションを修正/削除するときは、OptionNmae 引数の末尾に "::"(コロン×2) と値を付ける new_cmdline = ModifyCmdLineOpt( "-o ValueA -o ValueB Value1", "-o::ValueB", "-o NewValue" ) Assert new_cmdline = "-o ValueA -o NewValue Value1" new_cmdline = ModifyCmdLineOpt( "-o ValueA -o ValueB Value1", "-o::ValueB", Empty ) Assert new_cmdline = "-o ValueA Value1" テスト → T_CmdLine.vbs # [T_ModifyCmdLineOpt] *********************************************************************** <<< オプション引数、ビットフラグ >>> *********************************************************************** オプション引数、ビットフラグ 移植性を持たせつつ将来のバージョンで関数の引数を追加できるようにしたいときは、 下記の引数を検討するとよいでしょう。 ビットフラグ引数 → IsBitSet オプション引数(配列) → ParseOptionArguments 移植性を持たせつつ引数の数を変更したいときは、 新しく関数名を "<従来の関数名>Ex" にするか、 古い関数名を "<従来の関数名>_Old" にするとよいでしょう。 *********************************************************************** <<< IsBitSet >>> *********************************************************************** IsBitSet IsAnyBitsSet IsAllBitsSet IsBitNotSet IsAnyBitsNotSet IsAllBitsNotSet Function IsBitSet( Variable as integer, ConstValue as integer ) as integer 1つのビットが立っているかどうかを判定します。 Function IsAnyBitsSet( Variable as integer, OrConstValue as integer ) as integer 複数のビットのうち1つ以上が立っているかどうかを判定します。 Function IsAllBitsSet( Variable as integer, OrConstValue as integer ) as integer 複数のビットのすべてが立っているかどうかを判定します。 Function IsBitNotSet( Variable as integer, ConstValue as integer ) as integer 1つのビットが立っていないかどうかを判定します。 Function IsAnyBitsNotSet( Variable as integer, OrConstValue as integer ) as integer 複数のビットのうち1つ以上が立っていないかどうかを判定します。 Function IsAllBitsNotSet( Variable as integer, OrConstValue as integer ) as integer 複数のビットのすべてが立っていないかどうかを判定します。 【引数】 Variable 調べる対象のビット・フィールド値 ConstValue 調べる位置のビットを1にしたビット・フィールド値 OrConstValue 調べる位置の複数のビットを1にしたビット・フィールド値 返り値 判定結果 (0以外=True、0=False)、論理型ではありません 参考 → ビット演算 ソース → vbslib.vbs テスト → T_Var.vbs T_IsBitSet サンプル Sub Main() Set c = get_SampleConsts() echo FuncA( c.Bit0 ) echo FuncA( c.Bit1 ) echo FuncA( c.Bit0 or c.Bit1 ) echo FuncA( 0 ) echo FuncA( Empty ) End Sub Function FuncA( BitFlags ) Set c = get_SampleConsts() s = "" If IsBitSet( BitFlags, c.Bit0 ) Then s = s + "A" If IsAnyBitsSet( BitFlags, c.Bit0 or c.Bit1 ) Then s = s + "B" If IsAllBitsSet( BitFlags, c.Bit0 or c.Bit1 ) Then s = s + "C" If IsBitNotSet( BitFlags, c.Bit0 ) Then s = s + "a" If IsAnyBitsNotSet( BitFlags, c.Bit0 or c.Bit1 ) Then s = s + "b" If IsAllBitsNotSet( BitFlags, c.Bit0 or c.Bit1 ) Then s = s + "c" FuncA = s End Function '************************************************************************* ' <<< [get_SampleConsts] >>> '************************************************************************* Dim g_SampleConsts Function get_SampleConsts() If IsEmpty( g_SampleConsts ) Then _ Set g_SampleConsts = new SampleConsts Set get_SampleConsts = g_SampleConsts End Function Class SampleConsts Public Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7, Bit8, Bit9 Public Bit10, Bit11, Bit12, Bit13, Bit14, Bit15, Bit16, Bit17, Bit18, Bit19 Public Bit20, Bit21, Bit22, Bit23, Bit24, Bit25, Bit26, Bit27, Bit28, Bit29 Public Bit30, Bit31 Private Sub Class_Initialize() Bit0 = &h0001 Bit1 = &h0002 Bit2 = &h0004 Bit3 = &h0008 Bit4 = &h0010 Bit5 = &h0020 Bit6 = &h0040 Bit7 = &h0080 Bit8 = &h0100 Bit9 = &h0200 Bit10 = &h0400 Bit11 = &h0800 Bit12 = &h1000 Bit13 = &h2000 Bit14 = &h4000 Bit15 = CLng("&h8000") Bit16 = &h00010000 Bit17 = &h00020000 Bit18 = &h00040000 Bit19 = &h00080000 Bit20 = &h00100000 Bit21 = &h00200000 Bit22 = &h00400000 Bit23 = &h00800000 Bit24 = &h01000000 Bit25 = &h02000000 Bit26 = &h04000000 Bit27 = &h08000000 Bit28 = &h10000000 Bit29 = &h20000000 Bit30 = &h40000000 Bit31 = &h80000000 End Sub Public Function ToStr( Number ) Select Case Number Case Bit0 : ToStr = "Bit0" Case Bit1 : ToStr = "Bit1" '// ... End Select End Function End Class 関連 → Hex *********************************************************************** <<< ParseOptionArguments >>> *********************************************************************** ParseOptionArguments Sub ParseOptionArguments( in_out_Options as variant ) 引数に指定した配列型のオプション引数を辞書型に変換します。 キーは要素の型名です。 【引数】 in_out_Options (入力) 任意の型の変数や配列や辞書やEmpty、(出力) 辞書 ParseOptionArguments は、オプション引数(オプション的な引数)を扱いやすくします。 ユーザーは、オプションを指定しないときは Empty を渡します。 オプションを1つ以上指定するときは、配列型にまとめて渡します。 オプションを1つ指定するときは、配列に入れなくても構いません。 処理が開始されると、本関数によって、オプション引数は型をキーとした辞書に変換されます。 in_out_Options 引数に辞書を指定したときは、何もしません。 キーは、大文字小文字を区別しません。 整数型(integer, byte, long)のアイテムに対応するキーは、"integer" です。 浮動小数型(single, double)のアイテムに対応するキーは、"float" です。 その他の型は、 TypeName の返り値がキーになります。 例: NameOnlyClass 入力した配列に含まれない型をキーに指定した場合、アイテムは Empty になります。 ArrayClass 型のアイテムに対応するキーは、"ArrayClass" ですが、配列型のアイテムに 対応するキーはできません。 配列は、上記のとおり複数のオプションをまとめるものとして 処理します。 オプション引数を直接 TypeName 関数などで判定しないでください。 オプション引数をそのまま関数呼び出しに渡しているときは、辞書型に置き換わって返ってくる 可能性があります。 そして、その変数が再びオプション引数に渡される可能性があります。 ですので、必ず ParseOptionArguments を呼び出した後で、辞書のキーの有無からオプション の有無を判定してください。 サンプル Set object = new SampleClass FuncA Array( &h0001 or &h0002, "ABC", object ) Sub FuncA( in_out_Options ) ParseOptionArguments in_out_Options Assert in_out_Options("integer") = &h0001 or &h0002 Assert in_out_Options("string") = "ABC" Assert in_out_Options("SampleClass") Is object Assert not in_out_Options.Exists("NotPassedType") option_flags = in_out_Options("integer") If in_out_Options.Exists("SampleClass") Then Set options = in_out_Options("SampleClass") Else Set options = new SampleClass End If End Sub サンプル FuncA 123 Sub FuncA( in_out_Options ) ParseOptionArguments in_out_Options Assert in_out_Options("integer") = 123 End Sub ソース → vbslib.vbs テスト → T_Var.vbs T_ParseOptionArguments キーワード: in_out_Config *********************************************************************** <<< include >>> *********************************************************************** include Sub include( path as string ) 関数定義やクラス定義が入った VBSファイルをインクルードします。 include は、 vbs_inc の内部からも呼ばれます。 path に環境変数を含めることができます。 (%var% 形式) クラス定義や関数定義が入った VBS ファイルのパスを指定します。 VBS ファイルで定義されたグローバル変数や関数は、include を呼び出した 関数の外から参照することはできません。 path に相対パスを指定するときは注意が必要です。 → g_start_in_path 呼び出し先に関数を実行するときのカレントフォルダは、そのスクリプト ファイルがあるフォルダになります。 サンプル include "%ProgramFiles%\Movie Maker\moviemk.vbs" フォルダのパスを指定したり、ワイルドカードを指定すると、サブフォルダも 含めて include します。 ただし、フォルダのパスだけを指定した場合は、 *_obj.vbs ファイルだけ include します。 サンプル objs フォルダのサブフォルダも含めて、*_obj.vbs を include します include "objs" 二重定義エラーが出るときの対策 インクルードする vbs ファイルに、すでに定義されているクラスの 定義があると、エラーになります。クラスは、インスタンスに影響する ため上書きできません。 (関数は上書きできます) 二重にインクルードしないようにするか、クラス定義だけ1回だけ インクルードするファイルに分割してください。 サンプル: 1回だけインクルードする Dim g_TestClass : If IsEmpty( g_TestClass ) Then _ include "TestClass.vbs" : g_TestClass = True ソース → vbs_inc_sub.vbs → vbslib_mini.vbs テスト → T_Include.vbs # [main2] 関連 → include_objs → vbs_inc → g_SrcPath → FuncRedir_add *********************************************************************** <<< SectionTree クラス >>> *********************************************************************** SectionTree クラス (src) SectionTree オブジェクトを使って、全体の処理を複数のセクションに分割すると、途中のセクション から実行することができるようになります。 たとえば、1つの関数の中で、複数のテストを連続して行っているとき、1つ1つのテストをセクションに 分けておくと、失敗したテストから実行させることができるようになります。 セクションの開始と終了で、現在のセクションの位置(親のツリーノードのセクション名から現在まで) を表示します(下記、サンプル画面)。 サンプル Sub Test_start( tests ) Set section = new SectionTree '//SetStartSectionTree "T_Sample2" '// 一部のセクションだけ実行するときは有効にする '//=========================================================== If section.Start( "T_Sample1" ) Then '// ここは実行されません End If : section.End_ '// section.Start 〜 End_ の外は、常に実行する If section.Start( "T_Sample2" ) Then '// ここから実行されます End If : section.End_ '// ここで、「終了しました」と確認メッセージが表示される If section.Start( "T_Sample2" ) Then '// ここも実行されます End If : section.End_ Pass End Sub SetStartSectionTree T_Sample2 Start End_ サンプル画面 Section> T_Sample2

:
サンプル ネストしているとき Sub Test_start( tests ) SetStartSectionTree "Sec1, SubSec2" Dim section : Set section = new SectionTree If section.Start( "Sec1" ) Then If section.Start( "SubSec2" ) Then '// ここは実行されます End If : section.End_ End If : section.End_ Pass End Sub サンプル画面 Section> Sec1
Section> Sec1 > SubSec2
:
テスト (各メソッドを参照) 関連 → ログ *********************************************************************** <<< Start (SectionTree) >>> *********************************************************************** [ 親: SectionTree クラス ] Start (SectionTree) (src) Function SectionTree::Start( SectionName as string ) as boolean セクションの開始を指定します。 【引数】 SectionName セクション名 返り値 セクションを実行するかどうか ファイル: vbslib.vbs デバッグ用に、本関数の中から呼び出すコールバック関数を登録できます。 → OnStart (SkipSectionGlobal) テスト → T_SectionTree.vbs # [T_SectionTree_1] → T_SectionTree.vbs # [T_SectionTree_2] → T_SectionTree.vbs # [T_SectionTree_0] → T_SectionTree.vbs # [T_SectionTree_Err] *********************************************************************** <<< End_ (SectionTree) >>> *********************************************************************** [ 親: SectionTree クラス ] End_ (SectionTree) (src) Sub SectionTree::End_() セクションの終了を指定します。 ファイル: vbslib.vbs テスト → Start (SectionTree) *********************************************************************** <<< xml (SectionTree) >>> *********************************************************************** [ 親: SectionTree クラス ] xml (SectionTree) (src) Function SectionTree::xml() as string 現在のセクションを返します。 ファイル: vbslib.vbs サンプル 現在のセクションを表示します。 なお、echo に指定するときは xml を省略できます。 Dim section : Set section = new SectionTree If section.Start( "Sec1" ) Then echo section End If : section.End_ 出力例: テスト → T_SectionTree.vbs # [T_SectionTree_1] → T_SectionTree.vbs # [T_SectionTree_2] *********************************************************************** <<< 旧仕様 >>> *********************************************************************** 旧仕様 *********************************************************************** <<< EchoTestStart >>> *********************************************************************** EchoTestStart (src) 廃止予定です。 代用 → SectionTree クラス Sub EchoTestStart( TestSymbol as string ) テストシンボルをエコー出力します。 サンプル1 EchoTestStart "T_Samp1" サンプルの出力 ((( [T_Samp1] ))) サンプル2 EchoTestStart tests.Symbol Test.vbs や InputCommand を実行するときは、EchoTestStart 関数を呼ばなくても、自動 的にシンボルがエコー出力されます。 Test_start 関数の中で複数のテストをするときに、EchoTestStart 関数を使うと、テストのログ が見やすくなります。 *********************************************************************** <<< SkipToSection >>> *********************************************************************** SkipToSection (src) Sub SkipToSection( Num as integer ) 指定した番号のセクションより前のセクションをスキップするように設定します。 【引数】 Num 次に実行するセクション番号 通常、メイン関数から呼び出します。 はじめは 0 を指定して、セクション番号を echo 出力させます。 次に、スキップしたいセクションを調べて、次に実行したいセクション番号を指定します。 サンプル: セクション番号 5 から実行する( 5 より前は実行をスキップする。) SkipToSection 5 サンプル: セクション番号 5,2 から実行する( 5,1 より前は実行をスキップする。) SkipToSection Array( 5, 2 ) サンプル: セクション番号を表示させない、かつ、実行のスキップをしない。 SkipToSection Empty セクション番号は、下記のように echo 出力されます。 SkipToSection を一度も呼んで いないときや、スキップ中は出力されません。
一度も SkipToSection が呼ばれていないときは、グローバル変数 g_SkipSection が Empty になっています。 NotSkipSection にブレークポイントを張ると、セクションごとにブレークします。 関連 → SetBreakAtSection → SkipSection::Start → SkipSection::End_ テスト → T_SkipToSection フォルダ *********************************************************************** <<< SkipSection::Start >>> *********************************************************************** SkipSection::Start (src) Function SkipSection::Start() as boolean 本関数を呼び出した場所をセクションの開始場所とします。 サンプル: Dim section : Set section = new SkipSection If section.Start() Then '// section 1 : section.End_ End If If section.Start() Then '// section 2 If exist( "out.txt" ) Then '// 条件によって、しないことがある処理は、section の中へ : End If section.End_ End If テスト → T_SkipToSection フォルダ *********************************************************************** <<< SkipSection::End_ >>> *********************************************************************** SkipSection::End_ Sub SkipSection::End_() 参考 → SkipSection::Start *********************************************************************** <<< NotSkipSection >>> *********************************************************************** NotSkipSection (src) Function NotSkipSection() as boolean 廃止予定です。 SkipSection::Start 〜 End_ を使ってください → SkipSection::Start 本関数を呼び出した場所をセクションの開始場所とします。 【引数】 返り値 SkipToSection で設定されたセクション以降かどうか 本関数を呼び出すとセクション番号を+1します。 SkipToSection が呼ばれていたら、セクション番号を echo 出力します。 サンプル: For Each i As arr If NotSkipSection() Then DoTest End If Next echo 出力の例:
*********************************************************************** <<< SetBreakAtSection >>> *********************************************************************** SetBreakAtSection (src) Sub SetBreakAtSection( Num ) 指定のセクションでブレークするようにします。 *********************************************************************** <<< GetSkipSectionGlobal >>> *********************************************************************** GetSkipSectionGlobal Function GetSkipSectionGlobal() as SkipSectionGlobal セクションを管理するオブジェクトを返します。 【引数】 返り値 セクションを管理するオブジェクト ソース → vbslib.vbs GetSkipSectionGlobal 関数 → vbslib.vbs SkipSectionGlobal クラス SkipSectionGlobal クラス → OnStart セクションを開始する直前でコールバックする関数。 *********************************************************************** <<< OnStart (SkipSectionGlobal) >>> *********************************************************************** OnStart (SkipSectionGlobal) Sub SkipSectionGlobal::OnStart( CallbackObject as variant ) セクションを開始する直前でコールバックする関数。 【引数】 CallbackObject GetSkipSectionGlobal().CallbackObject サンプル Sub Main( Opt, AppKey ) Set ss = GetSkipSectionGlobal() Set ss.OnStart = GetRef("CheckOnCallback") Set ss.CallbackObject = Nothing RunTestPrompt AppKey.NewWritable( "." ) End Sub Sub CheckOnCallback( Argument1 ) echo "CheckOnCallback" End Sub 関連 → Start (SectionTree) セクションの開始を指定します。 *********************************************************************** <<< call_vbs >>> *********************************************************************** call_vbs (src) (src) Function call_vbs( path as string, func as string, param as variant ) 指定した VBScript ファイルの中の関数を呼び出し、終了するまで待ちます。 【引数】 path VBScript ファイルのパス func 呼び出す関数の名前 param 関数に渡すパラメータ 返り値 関数の返り値 現在のプロセスのまま、別の .vbs ファイルを呼び出します。 サンプル: call_vbs "%ProgramFiles%\Movie Maker\moviemk.vbs", "FuncA", "" 呼び出し先の関数は、次の型にしてください。 Function FuncA( Param ) path に環境変数を含めることができます。 (%var% 形式) path に相対パスを指定するときは注意が必要です。 → g_start_in_path 呼び出し先に関数を実行するときのカレントフォルダは、そのスクリプト ファイルがあるフォルダになります。 グローバル変数は、呼び出し先で宣言したものが、使えるようになります。 g_SrcPath は、で、グローバル領域を実行しているときだけでなく、呼び出す 関数を実行しているときも、path 引数に指定したパスのフル・パスが入ります。 *********************************************************************** <<< FuncRedir_add >>> *********************************************************************** FuncRedir_add (src) Sub FuncRedir_add( out_Redir as FuncRedir, Name as string ) 関数コールをリダイレクト(横取り)します。 【引数】 out_Redir (出力) FuncRedir オブジェクト Name リダイレクトされる関数の名前 上書きする前の関数を呼び出さないときは、FuncRedir_add を呼び出す必要はありません。 FuncRedir_add の第1引数に指定して取得したオブジェクト使って、上書きする前の関数を 呼び出します。 リダイレクト先の関数が定義してあるスクリプト・ファイルと、別のファイルから FuncRedir_add を呼び出してください。 たとえば、下記の ModuleC.vbs と ModuleC_pre.vbs のように分けてください。 そうしないと、リダイレクトする前の関数が上書きされた後で、FuncRedir_add が呼ばれる ことになり、終わりのない再帰呼び出しになり、メモリ不足(スタック不足)のエラーになる でしょう。 サンプル FuncA 関数の定義をリダイレクトし、環境変数 FuncA_Redir の値によって、リダイレクト元か リダイレクト先かのどちらかの FuncA 関数を呼び出すかを選べるようにします。 Main.vbs include "ModuleC_pre.vbs" include "ModuleC.vbs" ModuleC_pre.vbs FuncRedir_add を呼び出すためのファイル Dim g_FuncA : FuncRedir_add g_FuncA, "FuncA" FuncA FuncA FuncA ModuleC.vbs リダイレクト先 ModuleX.vbs FuncA の呼び出し元 Sub FuncA( Param1 ) If GetVar( "FuncA_Redir" ) = "Over" Then echo "overrided" Else g_FuncA.CallSub1 Param1 End If End Sub FuncA Sub FuncX() Dim v_:Set v_= new VarStack SetVar "FuncA_Redir", "Over" FuncA End Sub FuncA 参考 → T_NameAdd_vbslib フォルダ → バージョン判定、環境変数 FuncRedir オブジェクトのメソッド一覧 上書きする前の関数を呼び出します。 Sub FuncRedir::CallSub0() Sub FuncRedir::CallSub1( Param1 ) Sub FuncRedir::CallSub2( Param1, Param2 ) Sub FuncRedir::CallSub3( Param1, Param2, Param3 ) Sub FuncRedir::CallSub4( Param1, Param2, Param3, Param4 ) Function FuncRedir::CallFunction0() Function FuncRedir::CallFunction1( Param1 ) Function FuncRedir::CallFunction2( Param1, Param2 ) Function FuncRedir::CallFunction3( Param1, Param2, Param3 ) Function FuncRedir::CallFunction4( Param1, Param2, Param3, Param4 ) テスト → T_FuncRedir.vbs 関連 → バージョン判定、環境変数 → マクロ・リダイレクト *********************************************************************** <<< CallForEach >>> *********************************************************************** CallForEach (src) Function CallForEach0( Func as Function, Collection as array or variant ) Function CallForEach1( Func, Collection, Param1 as variant ) Function CallForEach2( Func, Collection, Param1 as variant, Param2 as variant ) Collection のそれぞれの要素を引数に渡して、関数 Func を複数回呼び出します。 【引数】 Func 呼び出す関数(GetRef使用) Collection 配列、または単純変数、または Empty Param1 関数に渡すパラメータ 返り値 関数 Func の返り値(Collection が単純変数のときのみ) なるべく、CallForEach を使わずに、For ループを使って、それぞれの要素に対して 処理してください。 サンプル: CallForEach2 GetRef("CallForEach_copy"), Array( "a.txt", "b.txt" ), "src", "dst" 上記コードは下記コードと同じ処理内容です。 CallForEach_copy "a.txt", "src", "dst" CallForEach_copy "b.txt", "src", "dst" キーワード: CallForEach0, CallForEach1, CallForEach2, CallForEach3, CallForEach4 関連 → EventResponders : イベント応答 (vbsool) *********************************************************************** <<< CallForEach_copy >>> *********************************************************************** CallForEach_copy (src) Sub CallForEach_copy( StepPath as string, FromFolderPath as string, ToFolderPath as string ) CallForEach に使えるファイルコピーです。 【引数】 StepPath ファイルへの相対パス。 基準は FromFolderPath と ToFolderPath FromFolderPath コピー元のフォルダ ToFolderPath コピー先のフォルダ サンプル CallForEach2 GetRef("CallForEach_copy"), Array( "a.txt", "folder\*" ), "src", "dst" 上記コードは下記コードと同じ処理内容です。 copy "src\a.txt", "dst" copy "src\folder\*", "dst\folder" '// copy "src\folder", "dst" と同じ フォルダーをコピーするとき、パスの末尾に "\*" があってもなくても構いません。 ワイルドカードを使っても、サブ・フォルダーはコピーしません。 ExpandWildcard と組み合わせて ください。 Set c = g_VBS_Lib ExpandWildcard "src\*.doc", c.File or c.SubFolder, folder, step_paths CallForEach2 GetRef("CallForEach_copy"), step_paths, "src", "dst" テスト → T_EachCopy.vbs # [T_EachCopy1] 関連 → CopyFunction 型、コピー関数型 *********************************************************************** <<< CallForEach_move >>> *********************************************************************** CallForEach_move (src) Sub CallForEach_move( FilePath, FromFolderPath, ToFolderPath ) CallForEach に使えるファイルの移動です。 参考 → CallForEach_copy *********************************************************************** <<< CallForEach_del >>> *********************************************************************** CallForEach_del (src) Sub CallForEach_del( FilePath, FolderPath ) CallForEach に使えるファイルまたはフォルダの削除です。 サンプル CallForEach1 GetRef("CallForEach_del"), Array( "a.txt", "folder\*" ), "folder" 上記コードは下記コードと同じ処理内容です。 del "folder\a.txt" del "folder\folder\*" *********************************************************************** <<< Transpose >>> *********************************************************************** Transpose 文を実行する順番を入れ替えます。 たとえば、関数の引数の代入(詳細)を後で書くほうが可読性が上がるときに使います。 Transpose は、順番の入れ替えを示すだけで、何もしません。 サンプル Transpose : For i=0 To 1 : If i=1 Then Else ' Transpose Transpose : End If : Next copy t_source, t_destination t_source = "C:\From.txt" t_destination = "C:\To.txt" 前半と後半(Transpose : Else の前後)をつなぐ変数の名前の先頭は、 t_ から始めるコーディング ルールを推奨します。 上記のコードは、説明のために後半が短いため、変数を介さないほうが読みやすいですが、 一般に後半が長いときは読みやすくなります。 上記のコードは、下記のコードと同じ処理を行います。 source = "C:\From.txt" destination = "C:\To.txt" copy source, destination ソース → vbslib.vbs *********************************************************************** <<< SetTaskStartTime >>> *********************************************************************** SetTaskStartTime (src) Sub SetTaskStartTime( TaskName as string, StartTime as string ) タスク・スケジューラーに登録済みの、指定のタスクを開始する時刻を変更します。 StartTime の先頭を + にすると、現在の時刻からの差分を指定できます。 例) +1:30 … 1時間半後 サンプル → samples/TaskScheduler フォルダ echo "タスクの開始時間を再設定します。" Dim name : name = input( "タスク名>" ) echo "例: 13:00 ... 今が午前10時なら、今日の午後1時に実行する" echo "例: 1:00 ... 今が午前10時なら、明日の午前1時に実行する" echo "例: +1:00 ... 今から1時間後に実行する" Dim after : after = input( "いつ実行を開始しますか>" ) SetTaskStartTime name, after SetTaskStartTime 関連 → GetTaskList → schtasks /Create *********************************************************************** <<< GetTaskList >>> *********************************************************************** GetTaskList (src) Function GetTaskList( EmptyParam as Empty ) タスク・スケジューラーに登録済みの、タスクを一覧します。 返り値は、タスクの集合である辞書型です。 タスクの集合の Key は タスク名、Item は1つのタスクを表す辞書型です。 1つのタスクを表す辞書型の Key は タスクの属性名、Item は属性の値です。 サンプル Set tasks = GetTaskList( Empty ) Set task = tasks.Item( "\Task1" ) start task.Item( "実行するタスク" ) 参考 → schtasks /Query *********************************************************************** <<< MakeFileClass (メイクファイル) >>> *********************************************************************** MakeFileClass (メイクファイル) make コマンドのように、ファイルのタイムスタンプを比較して、必要ならコマンドを実行します。 一般的なメイクファイルと、MakeFileClass との対応関係を示します。 一般的なメイクファイル (vbslibではない) Target.txt : Source1.txt Source2.txt command Target.txt が無いときか、Source1.txt または Source2.txt より古いときに、 command を実行します。 ただし、Source1.txt および Source2.txt に対する ルールのコマンドを実行した後で実行します。 参考 → Makefile → ロールバック MakeFileClass では、次のように記述します。 Sub Main() Set mk = new MakeFileClass mk.AddRule new_Target_txt_Rule() mk.Make End Sub Function new_Target_txt_Rule() Set o = new MakeRule o.Sources = Array( "Source1.txt", "Source2.txt" ) o.Target = "Target.txt" Set o.Command = GetRef("Target_txt_Command") Set new_Target_txt_Rule = o End Function Sub Target_txt_Command( Param, Rule ) copy_ren Rule.Sources(0), Rule.Target End Sub MakeFileClass Target_txt Target_txt MakeRule Source1.txt Source2.txt Target.txt Target_txt Target_txt Target_txt Command ワイルドカードを指定 すれば、 暗黙ルール を作ることができます。 うまく動作しないときは、 DebugMode を設定して詳細な情報を確認してください。 メイクファイルの図の記法例 (参考) ここでは、メイクファイルで指定された「構成」を図に表すときの記法を示します。 サンプル Target.txt Source.txt 生成する by new_Target_txt_Rule 凡例 MakeRule を返す関数名 MakeRule の source と target の関係 MakeRule で実行するコマンド 最初に更新するファイル File ソース → vbslib.vbs → データ構造 (MakeFileClass) テスト → T_MakeRule フォルダ 関連 → OpenForMakeRuleOfRevisionFolder → CheckEnglishOnly_src\Test.vbs ソースに更新があったときだけコピーする *********************************************************************** <<< MakeFileClass >>> *********************************************************************** MakeFileClass (src) << MakeFileClass (メイクファイル) サンプル → メイクファイル .AddRule メイクファイルのルールを登録します。 .Make メイクを実行します。 .Name メイクファイルの名前。 .Variables ユーザー定義変数の集まり。 .Delegate ユーザー定義の委譲先オブジェクト。 .DebugMode デバッグモード .DebugMode_Param1 デバッグモードのパラメーター .c 定数の集まり *********************************************************************** <<< AddRule (MakeFileClass) >>> *********************************************************************** AddRule (MakeFileClass) Sub MakeFileClass::AddRule( a_MakeRule as MakeRule ) MakeRule メイクファイルのルールを登録します。 a_MakeRule 引数に配列を指定することもできます。 *********************************************************************** <<< Make (MakeFileClass) >>> *********************************************************************** Make (MakeFileClass) Sub MakeFileClass::Make() 登録されているメイクファイルのルールに従って、メイクを実行します。 *********************************************************************** <<< Name (MakeFileClass) >>> *********************************************************************** Name (MakeFileClass) Dim MakeFileClass::Name as string メイクファイルの名前。 MakeFileClass::DebugMode に MakeFileClass::c.OutDebugXML を設定するときに 表示されます。 *********************************************************************** <<< Variables (MakeFileClass) >>> *********************************************************************** Variables (MakeFileClass) Dim MakeFileClass::Variables as LazyDictionaryClass LazyDictionaryClass ユーザー定義変数の集まり。 MakeFileClass を生成した時点で、LazyDictionaryClass のオブジェクトは生成されています。 Variables が指しているオブジェクトは、 MakeRule::Variables でも参照できます。 MakeRule::Variables で自動的に設定される変数と同じ名前の変数をユーザーが定義すると 上書きされてしまうので注意してください。 *********************************************************************** <<< Delegate (MakeFileClass) >>> *********************************************************************** Delegate (MakeFileClass) Dim MakeFileClass::Delegate as variant 委譲先となるユーザー定義オブジェクト。 MakeFileClass クラスのオブジェクトを生成するときにユーザ定義オブジェクトを Delegate に格納しておくと、 MakeRule::Command で呼ばれる関数の中で、第1引数である MakeFileClass オブジェクトの Delegate からユーザ定義オブジェクトを、参照することができるようになります。 Sub main() Dim mk : Set mk = new MakeFileClass mk.AddRule new_Target_txt_Rule() mk.Delegate = "ABC" mk.Make End Sub Sub Target_txt_Command( a_MakeFile, a_MakeRule ) echo a_MakeFile.Delegate End Sub Delegate Delegate *********************************************************************** <<< DebugMode (MakeFileClass) >>> *********************************************************************** DebugMode (MakeFileClass) Dim MakeFileClass::DebugMode as integer Dim MakeFileClass::DebugMode_Param1 as variant メイクファイルのデバッグモード DebugMode = MakeFileClass::c.OutDebugXML のとき メイクを実行する直前に、どのコマンドがあって、どのコマンドを実行するのかを XML で表示します。 スクリプトは、pause によって一時停止します。 DebugMode = MakeFileClass::c.BreakBeforeCommand のとき 指定の MakeRule のコマンドを実行する直前で Stop します。 DebugMode_Param1 as string ブレークする MakeRule::Target の一部 Empty = すべて Stop する DebugMode = MakeFileClass::c.Watch のとき それぞれの MakeRule のコマンドを実行する前と後で、指定の関数を呼び出します。 DebugMode_Param1 as Sub 呼び出す関数。GetRef を使ってください 呼び出す関数のパラメーターは、MakeRule::Command と同じです。 Sub ( Delegate as variant, Rule as MakeRule ) c は、MakeFileClass::c で参照できる MakeFileClassConst オブジェクトです。 *********************************************************************** <<< MakeRule >>> *********************************************************************** MakeRule (src) << MakeFileClass (メイクファイル) サンプル → メイクファイル 新規作成するときは、少なくとも Target、Sources、Command を初期化してください。 .Target .Command によって作られるファイルのパス。 .Sources .Command を実行するのに必要となるファイルのパスの配列。 .Command Target のタイムスタンプが、Sources より新しいときに実行する関数。 .Variables ユーザー定義変数と、MakeFile の自動変数の集まり。 (Read Only) .CurrentDirectory MakeRule オブジェクトを生成したときのカレント・フォルダ。 (Read Only) .Delegate 委譲先となるユーザー定義オブジェクト。 .Type_ メイクルールの種類。 .c 定数の集まり (Read Only) .Priority 優先度。 大きいほど優先する。 .NewestSource 最もタイムスタンプが新しい Sources のファイルパス。 .AllNewSource ターゲットよりタイムスタンプが新しいファイルパスの配列。 *********************************************************************** <<< Target (MakeRule) >>> *********************************************************************** Target (MakeRule) (src) Dim MakeRule::Target as string .Command によって作られるファイルのパス。 または、Command が最後まで完了したら更新するファイルのパス。 相対パスを指定するとき、基準フォルダは .CurrentDirectory。 ワイルドカードを指定したとき (暗黙ルール) ( Target : Sources ) が ( A.obj : A.c ), ( B.obj : B.c ) のルールがあるとき、 MakeRule::Target と MakeRule::Sources(0) にワイルドカードがあるかどうかによって、 動作がどのように違うかを示します。 MakeRule::Target MakeRule::Sources(0) 動作 A.obj A.c A.c が更新されたらコマンドを実行 *.obj A.c エラー(未対応) A.obj *.c エラー(未対応) *.obj *.c A.c が更新されたら A.c に対するコマンドを実行、 B.c が更新されたら B.c に対するコマンドを実行 サンプル Source フォルダーにある *.txt ファイルが更新されたら、Target フォルダーにコピーする Function new_Target_txt_Rule() Set o = new MakeRule o.Sources = Array( "Source\*.txt" ) o.Target = "Target\*.txt" Set o.Command = GetRef("Target_txt_Command") Set new_Target_txt_Rule = o End Function Sub Target_txt_Command( Param, Rule ) copy_ren Rule.Sources(0), Rule.Target End Sub *********************************************************************** <<< Sources (MakeRule) >>> *********************************************************************** Sources (MakeRule) (src) Dim MakeRule::Sources as Array of string .Command を実行するのに必要となるファイルのパスの配列。 または、Command を起動するときに更新するファイルのパス。 相対パスをしていするとき、基準フォルダは .CurrentDirectory。 参考 → ワイルドカードを指定したとき *********************************************************************** <<< Command (MakeRule) >>> *********************************************************************** Command (MakeRule) (src) Dim MakeRule::Command as Sub( Delegate as variant, Rule as MakeRule ) Target のタイムスタンプが、Sources より新しいときに実行する関数。 GetRef で代入してください。 Delegate 引数は、MakeFileClass::Delegate *********************************************************************** <<< Variables (MakeRule) >>> *********************************************************************** Variables (MakeRule) Dim MakeRule::Variables as LazyDictionaryClass LazyDictionaryClass ユーザー定義変数と、MakeFile の自動変数の集まり。 MakeRule::Command に指定した関数がコールバックされている間は、 MakeFile の自動変数 に相当する下記の変数が定義されます。 また、 MakeFileClass::Variable と同じオブジェクトを参照しており、そこに設定した変数を 参照または変更することができます。 下記の凡例: Variables にある変数名 MakeFile の自動変数名 ${Target} $@ target (:の左) a.o : a.c $(CC) -c -o ${Target} ${Sources} a.o : a.c $(CC) -c -o a.o a.c MakeRule::Target と同じ値です。 相対パスのフォルダー部分も含みます。 source (:の右) の1つ目 ${Sources[0]} $< a.o : a.c b.h @echo ${Sources[0]} a.o : a.c b.h @echo a.c MakeRule::Sources 配列 の1つ目の要素と同じ値です。 相対パスのフォルダー部分も含みます。 ${Sources} $? source (:の右) の全体 a.o : a.c b.h @echo ${Sources} a.o : a.c b.h @echo a.c b.h MakeRule::Sources配列 を CmdLineFromStr に渡した出力です。 ただし、\ は \\ に変換されません。 相対パスのフォルダー部分も含みます。 ${TargetNoExt} $* target の拡張子を除いたもの a.o : a.c $(CC) -c -o ${Target} ${TargetNoExt}.c a.o : a.c $(CC) -c -o a.o a.c MakeRule::Target の拡張子を除いたものです。 相対パスのフォルダー部分も含みます。 *********************************************************************** <<< CurrentDirectory (MakeRule) >>> *********************************************************************** CurrentDirectory (MakeRule) (src) Dim MakeRule::CurrentDirectory as string MakeRule オブジェクトを生成したときのカレント・フォルダ。 MakeRule::Target や MakeRule::Sources に格納されている相対パスの基準パス。 MakeRule::Command の関数が呼ばれる直前で、カレント・フォルダがこの値になります。 *********************************************************************** <<< Delegate (MakeRule) >>> *********************************************************************** Delegate (MakeRule) (src) Dim MakeRule::Delegate as variant 委譲先となるユーザー定義オブジェクト。 MakeRule クラスのオブジェクトを生成するときにユーザー定義オブジェクトを Delegate に格納しておくと、 MakeRule::Command で呼ばれる関数の中で、第2引数である MakeRule オブジェクトの Delegate からユーザー定義オブジェクトを、参照することができるようになります。 Function new_Target_txt_Rule() Set new_Target_txt_Rule = new MakeRule : With new_Target_txt_Rule .Sources = Array( "Source1.txt", "Source2.txt" ) .Target = "Target.txt" .Delegate = "ABC" Set .Command = GetRef("Target_txt_Command") End With End Function Sub Target_txt_Command( a_MakeFile, a_MakeRule ) echo a_MakeRule.Delegate End Sub Delegate Delegate *********************************************************************** <<< Type_ (MakeRule) >>> *********************************************************************** Type_ (MakeRule) (src) Dim MakeRule::Type_ as integer メイクルールの種類。 Empty 普通のメイクルール c.Splitter ターゲットが存在しないときでも、コマンドを実行しないメイクルール 参考 → オーダー調整用更新分離パス c は、MakeRule::c で参照できる MakeFileClassConst オブジェクトです。 *********************************************************************** <<< Priority (MakeRule) >>> *********************************************************************** Priority (MakeRule) (src) Dim MakeRule::Priority as integer 優先度。 大きいほど優先する。 同じ MakeRule::Target の値を持つ MakeRule が複数あるときは、その複数の中で、 MakeRule::Priority が最も大きい MakeRule::Command の関数だけが呼ばれます。 *********************************************************************** <<< NewestSource (MakeRule) >>> *********************************************************************** NewestSource (MakeRule) (src) Property Get MakeRule::NewestSource() as string 最もタイムスタンプが新しい MakeRule::Sources 配列の要素。ファイルパス。 タイムスタンプを比較するタイミングは、この NewestSource プロパティを参照したときです。 *********************************************************************** <<< AllNewSource (MakeRule) >>> *********************************************************************** AllNewSource (MakeRule) (src) Property Get MakeRule::AllNewSource() as Array of string MakeRule::Sources の中で、ターゲットよりタイムスタンプが新しいファイルパスの配列。 タイムスタンプを比較するタイミングは、この AllNewSource プロパティを参照したときです。 *********************************************************************** <<< MakeRule_compare >>> *********************************************************************** MakeRule_compare (src) Function MakeRule_compare( TargetPath, SourcePath ) as boolean タイムスタンプを比較して、メイク・コマンドを実行する状況かどうかを返す。 【引数】 TargetPath ターゲット・ファイルのパス。 メイクルールの : より左側 SourcePath ソース・ファイルのパス。 メイクルールの : より右側 返り値 メイク・コマンドを実行する状況かどうか サンプル If MakeRule_compare( "dst.txt", "src.txt" ) Then copy_ren "src.txt", "dst.txt" End If 参考 → タイムスタンプのテストの注意 関連 → File::DateLastModified → FileSystemObject::FileExists → DateAddStr *********************************************************************** <<< MakeFileClassConst >>> *********************************************************************** MakeFileClassConst メイクファイルに関する定数 get_MakeFileClassConst 関数、MakeFileClass::c、MakeRule::c 取得 メンバー .Splitter (=1) → Type_ (MakeRule) .OutDebugXML (=1) .BreakBeforeCommand (=2) → DebugMode (MakeFileClass) .Watch (=4) *********************************************************************** <<< データ構造 (MakeFileClass) >>> *********************************************************************** データ構造 (MakeFileClass) MakeFileClass (src) dictionary< target_path, MakeRuleGroup > (src) .RuleGroups string .TargetPath // 辞書のキー、Target と Sources の両方 ArrayClass< MakeRuleSpec > (src) .Rules MakeRule (src) .Rule .Target string .Sources array< string > ArrayClass< MakeRuleSpec > .UserFiles *********************************************************************** <<< OpenForMakeRuleOfRevisionFolder >>> *********************************************************************** OpenForMakeRuleOfRevisionFolder Function OpenForMakeRuleOfRevisionFolder( in_RuleFilePath as string ) as MakeRuleSetOfRevisionFolderClass make コマンドのような実行を、リビジョンのフォルダーに対して行ったことの記録を開きます。 【引数】 in_RuleFilePath メイク ルール ファイルのパス、または、Empty 返り値 → MakeRuleSetOfRevisionFolderClass 新しいリビジョンに対して make コマンドのような実行をするときは、記録(メイク ルールの ファイル)にある (CSV形式)の要素、または、 を増やします。 サンプル スクリプト: Set maker = OpenForMakeRuleOfRevisionFolder( "C:\Masters\MakeRule.xml" ) echo maker.GetMakeTreeString( "C:\Masters\Module\01" ) OpenForMakeRuleOfRevisionFolder GetMakeTreeString 表示: ${Files}\Step1\01 ${Files}\Step2\01 ${Files}\Step3A\03A ${Files}\Step3B\03B Step1\01 を出力するために、Step3A\03A と Step3B\03B を入力して、Step2\01 を出力 する Command 2 を実行してから、Step2\01 を入力して、Step1\01 を出力する Command 1 を実行したことの記録は、以下のようになります。 Step1 Step2 Step3A 01 01 03A Step3B Command 1 Command 2 03B メイク ルール ファイル MakeRule.xml Command 1 コマンド プロンプトに渡すコマンド 01 Output と Input_ の path の最後の * Command 2 01, 03A, 03B Variable 下記の新しいリビジョンを追加したとき、 の要素と を追加します。 ただし、ツリーが決定するまで、暫定的にそれぞれのリビジョン名の末尾に _Tmp を入れた ほうがよいでしょう。 Step1 Step2 Step3A 02_Tmp 02_Tmp 04A_Tmp Step3B Command 1 Command 2 04B_Tmp メイク ルール ファイルの変更後 : 02_Tmp, 01 : 02_Tmp, 04A_Tmp, 04B_Tmp 01, 03A, 03B : 02_Tmp, 02_Tmp, 04A_Tmp, 04B_Tmp MakeRule XML リファレンス → サンプル MakeRule/Output 複数可能 コマンドを実行したら出力されるフォルダーのパス。 MakeRule/Input 複数可能 MakeRule/Input_ 複数可能 コマンドを実行するときに入力するフォルダーのパス。 Input タグと Input_ タグに違いはありません。、 MakeRule/Command 複数可能 実行する コマンドライン 。 Command タグには、以下の変数を記述できます。 ${Revision[n]} 対象となるリビジョンの名前。 例:"02" n は、0 から始まる Output タグと Input タグの順番の番号です。 ${Output[n]} メイクしてできるフォルダーのフル パス。 フォルダー名は、Work 固定です。 n は、${Revision[n]} の n と同じです。 1つの n に対して ${Output[n]} か ${Input[n]} のどちらかだけ参照 できます。 ${Input[n]} 入力するフォルダーのフル パス。 フォルダー名は、Work 固定です。 n は、${Revision[n]} の n と同じです。 1つの n に対して ${Output[n]} か ${Input[n]} のどちらかだけ参照 できます。 MakeRule/Revisions 複数可能 Input タグや Output タグに指定した * と置き換えるリビジョン名の集合。 CSV形式。 同じ親を持つすべての Input タグや Output タグに共通のリビジョン名に置き換えます。 複数のリビジョン名は、CSV 形式で指定します。 1つのリビジョン名は、1つの RevisionSet タグに対応します。 MakeRule/RevisionSet 複数可能 Input タグや Output タグに指定した * と置き換えるリビジョン名の集合。 CSV形式。 CSV の要素の順番は、同じ親を持つ Input タグまたは Output タグの順番に対応 します。 ソース → ToolsLib.vbs テスト → T_MakeRuleR.vbs 関連 → ModuleAssort2 → MakeFileClass (メイクファイル) *********************************************************************** <<< MakeRuleSetOfRevisionFolderClass >>> *********************************************************************** MakeRuleSetOfRevisionFolderClass << OpenForMakeRuleOfRevisionFolder OpenForMakeRuleOfRevisionFolder の返り値。 LazyDictionaryClass .Variables ArrayClass of MakeRule_OfRevisionFolder_Class .MakeRules *********************************************************************** <<< GetMakeTreeString >>> *********************************************************************** GetMakeTreeString << OpenForMakeRuleOfRevisionFolder Function MakeRuleSetOfRevisionFolderClass::GetMakeTreeString( in_RootFolderPath as string ) as string メイク ルールのツリーを文字列で返します。 【引数】 in_RootFolderPath 最終出力フォルダーのパス 返り値 メイク ルールのツリーの文字列 ソース → ToolsLib.vbs *********************************************************************** <<< GetMakeRelations >>> *********************************************************************** GetMakeRelations << OpenForMakeRuleOfRevisionFolder Function MakeRuleSetOfRevisionFolderClass::GetMakeRelations( in_RootFolderPath as string ) as ArrayClass of MakeRule_OfRevisionFolder_Class メイク ルールのツリー返します。 【引数】 in_RootFolderPath 最終出力フォルダーのパス 返り値 メイク ルールのツリー ソース → ToolsLib.vbs *********************************************************************** <<< LoadAdditionally >>> *********************************************************************** LoadAdditionally << OpenForMakeRuleOfRevisionFolder Sub MakeRuleSetOfRevisionFolderClass::LoadAdditionally( in_RootFolderPath as string ) メイク ルールを追加します。 【引数】 in_RuleFilePath 追加するメイク ルール ファイルのパス、または、Empty ソース → ToolsLib.vbs *********************************************************************** <<< 子プロセスへの受け渡し (/ChildProcess オプション) >>> *********************************************************************** 子プロセスへの受け渡し (/ChildProcess オプション) (src) メイン・プロセスから、任意のデータ(例: Err2::ErrID )を渡し、子プロセスが終了したら メイン・プロセスに更新された データを返す、といったようなことができます。 このような データの受け渡しができるようにするのが、/ChildProcess オプションによる子プロセス の機能です。 OS が定義している子プロセスとは異なります。 XMLファイル メイン・プロセス vbslib (WSH) 子プロセス vbslib (WSH) XMLファイル → 処理フロー → メイン・プロセス側が使う ParentProcess オブジェクト、new_ParentProcess → 子プロセス側が使う ChildProcess オブジェクト、get_ChildProcess → InterProcessData インターフェース(ライブラリ用) → 困ったときは (/ChildProcess) vbslib の RunProg 関数で、vbs ファイルを起動すると、自動的に VBScript を起動するときの コマンドライン・パラメーター に、/ChildProcess オプションを付け、XML ファイルによるデータ の送受信ができるようになっています。 Shell::Run などで起動すると、/ChildProcess オプション が自動的に付かないので、明示的に指定しない限り送受信できません。 cscript sample.vbs → cscript sample.vbs /ChildProcess:090401,1 /ChildProcess の右の値は、テンポラリ・フォルダにできるフォルダ名の数値の部分です。 テンポラリ・ファイル名は、下記のとおりです。 %Temp% は、C:\Document 〜 に変わります。 %Temp%\Report\090401\ChildProcess_1\In.xml %Temp%\Report\090401\ChildProcess_1\Out.xml vbslib では、エラー処理やデバッグ用に Err2 オブジェクトの送受信を自動的に必ず行います。 /ChildProcess オプションが(自動的にでも)付くと、エラーレベル(プロセスの返り値)の値が 21 でないとエラーとみなし、メイン・プロセス側でもエラーを発生させます。 参考 → 正常終了時の動作 VBScript でエラーを発生させるテストをするときに、/ChildProcess オプションが付くと、 Err2::ErrID (エラーが発生した番号) などの値がメイン・プロセスから継承された値となり、 Err2::ErrID の値が正しいかどうかのチェックができなくなってしまいます。 それを回避するには、 エラーを発生させるテスト・スクリプトでは、/ChildProcess:0 オプションを付けてください。(下記) 自動的に /ChildProcess オプションを付けないようにするには、/ChildProcess:0 を明示的に 指定します。 r= RunProg( "cscript sample.vbs /ChildProcess:0", "" ) 参考 → テンポラリ・フォルダ → テスト情報 I/F テスト → [T_ChildProcess] → T_ChildProcess1.vbs 関連 → TempParams.txt - C言語のプログラムにデータを渡す *********************************************************************** <<< 処理フロー (/ChildProcess オプション) >>> *********************************************************************** 処理フロー (/ChildProcess オプション) メイン・プロセス起動 InitializeModule (vbslib.vbs) Set g_InterProcess = new InterProcess InitializeModule (vbslib.vbs または 任意の.vbs) g_InterProcess.InterProcessDataArray.Add LibData プロセスが変わるときにコールバック するように登録する main new_ParentProcess アプリケーションがやり取りするときのみ呼び出す ParentChildProcess.m_OutFile.WriteLine AppData.xml アプリケーションからの出力 ParentProcess (src) RunProg If TypeName( ParentProcess ) <> "ParentChildProcess" Then new_ParentProcess ParentChildProcess::OnCallInParent (src) g_InterProcess.OnCallInParent g_InterProcess (src) InterProcessData InterProcessData.OnCallInParent Err2::OnCallInParent (src) ParentChildProcess.m_OutFile.WriteLine LibData ライブラリからの出力 InterProcessData.ProcessCallID + 1 ProcessCallID を+1する ParentProcess.m_OutFile.WriteLine g_InterProcessからの出力 cmdline = cmdline +" /ChildProcess:"+ step_path +","+ pr.m_FileID (.vbs) Shell::Exec 子プロセス起動 (VBScript global code) 参考 → 処理フロー (vbs_inc/setting) InitializeModule (vbslib.vbs) new_ChildProcess_ifChildProcess (src) If WScript.Arguments.Named.Item("ChildProcess") Then Set g_ChildProcess = m m.m_TempPath = env( "%TEMP%\Report\" ) + m.m_DateID +"\ChildProcess_"+ m.m_FileID Set m_InXML = LoadXML( "In.xml" ) InterProcess.OnCallInSub g_InterProcessへの入力 InitializeModule (vbslib または 任意の.vbs) new_ObjectFromStream ライブラリへの入力 g_InterProcess.m_Data.Add LibData プロセスが変わるときにコールバックするように登録する main get_ChildProcess (.vbs) new_ObjectFromStream AppData, ChildProcess アプリケーションへの入力 : 子プロセスのメイン処理 : ParentChildProcess.m_OutFile.WriteLine AppData アプリケーションからの出力 ResumePop or FinalizeInModulesCaller::Class_Terminate CallFinalizeInModules FinalizeModule [vbslib.vbs] Err2.OnSuccessFinish エラー関係の調整 ParentChildProcess::Finish (src) If m_OutFile_LastLine = "" (src) InterProcess.OnReturnInChild ParentChildProcess.m_OutFile.WriteLine g_InterProcessからの出力 InterProcessData::OnReturnInChild InterProcessData Err2::OnReturnInChild (src) ParentChildProcess.m_OutFile.WriteLine ライブラリからの出力 子プロセス終了 Out.xml ParentChildProcess::OnReturnInParent (src) Set m_InXML = LoadXML( "Out.xml" ) InterProcess::OnReturnInParent (src) InterProcess.loadXML g_InterProcessへの入力 InterProcessData.OnReturnInParent InterProcessData new_ObjectFromStream ライブラリへの入力 '// サブ・プロセスで発生したエラーを、メイン・プロセスでも投げる If g_Err2.Num <> 0 Then g_Err2.Raise AppData.loadXML アプリケーションへの入力 ParentChildProcess::Class_Terminate (src) 受け渡しに使った XML ファイルを削除する ParentChildProcess::Finish (src) If m_OutFile_LastLine = "" Then *********************************************************************** <<< メイン・プロセス側が使う ParentProcess オブジェクト、new_ParentProcess >>> *********************************************************************** メイン・プロセス側が使う ParentProcess オブジェクト、new_ParentProcess (src) 子プロセスに、データを受け渡しするときは、new_ParentProcess_Object で生成した ParentProcess オブジェクトを RunProg に渡します。 new_ParentProcess で生成した ParentProcess オブジェクトには、他の子プロセスと受け渡し するファイルの名前が重複しない番号が m_FileID に入っています。 複数の子プロセスを 平行して同時に動かすときは、ParentProcess オブジェクトをもう1つ生成してください。 前の子プロセスが終わってから次の子プロセスを動かすときは、同じ ParentProcess オブジェクトが使えます。 使用サンプル: sample.Name = "A" : sample.Value = 1 '// 子プロセス起動前に、送るオブジェクトをXMLファイルに変換する Dim pr : new_ParentProcess_Object pr, Empty '//[out] pr as ParentChildProcess pr.m_OutFile.WriteLine sample.xml '// 子プロセスを起動する Dim r : r= RunProg( "cscript.exe T_ChildProcess1_Sub.vbs", pr ) CheckTestErrLevel r '// 子プロセス終了後に、戻されたXMLファイルをオブジェクトに戻す sample.loadXML pr.m_InXML.selectSingleNode( _ TypeName( sample ) +"[@name='"+ sample.Name +"']" ) xml pr ParentProcess オブジェクトのメンバー Class ParentChildProcess Public m_OutFile 'as TextStream (Write) ... 子プロセスへ渡す XML ファイル Public m_InXML 'as IXMLDOMElement ... メイン・プロセスに戻される ルートXML要素 Public m_TempPath ' as string. 送受信ファイルができるフォルダのパス Public m_DateID ' as string. 例:"090401". /ChildProcess オプションに渡す値 Public m_FileID ' as string. 例:"1". /ChildProcess オプションに渡す値 End Class *********************************************************************** <<< 子プロセス側が使う ChildProcess オブジェクト、get_ChildProcess >>> *********************************************************************** 子プロセス側が使う ChildProcess オブジェクト、get_ChildProcess (src) vbs_inc モジュールは、vbslib をインクルードする前に自動的に /ChildProcess オプションがあるかどうかを 判定し、あれば ChildProcess オブジェクトを生成します。 ChildProcess オブジェクトは、get_ChildProcess 関数で取得できる 静的オブジェクト であり、メインプロセスからの情報を m_InXML から入力し、 メインプロセスへ戻す情報を、m_OutFile に出力することができます。 /ChildProcess オプションがないときは、get_ChildProcess 関数が、Nothing オブジェクトを返します。 使用サンプル: Dim pr, sample '// プログラム開始時に、送られてきたXMLファイルをオブジェクトに戻す Set pr = get_ChildProcess() ' as ParentChildProcess new_ObjectFromStream sample, "SampleClass", pr '// main If not IsEmpty( sample ) Then sample.Value = 2 End If '// プログラム終了時に、戻すオブジェクトをXMLファイルに変換する If not pr is Nothing Then If not IsEmpty( sample ) Then pr.m_OutFile.WriteLine sample.xml End If xml ChildProcess オブジェクトのメンバー Class ParentChildProcess Public m_InXML 'as IXMLDOMElement ... メイン・プロセスから渡される ルートXML要素 Public m_OutFile 'as TextStream (Write) ... メイン・プロセスへ戻す XML ファイル Public m_TempPath ' as string. 送受信ファイルができるフォルダのパス Public m_DateID ' as string. 例:"090401". ファイル名の一部 Public m_FileID ' as string. 例:"1". ファイル名の一部 End Class 参考 → XPath → xml プロパティ *********************************************************************** <<< InterProcessData インターフェース(ライブラリ用) >>> *********************************************************************** InterProcessData インターフェース(ライブラリ用) ライブラリが自動的に子プロセスに受け渡しをするオブジェクトに必要なインターフェースです。 Err2 は、このインターフェースを持っています。 Class InterProcessData '// defined_as_interface Public Sub OnCallInParent( a_ParentProcess as ParentChildProcess ) : End Sub Public Sub loadXML( XmlObject as IXMLDOMElement ) : End Sub Public Sub OnReturnInChild( a_ChildProcess as ParentChildProcess ) : End Sub Public Sub OnReturnInParent( a_ParentProcess as ParentChildProcess ) : End Sub End Class Function new_InterProcessData() Set new_InterProcessData = new InterProcessData End Function 参考 → T_ChildProcess2_include.vbs 子プロセスに渡すオブジェクトは、g_InterProcess.m_Data as ArrayClass に登録してください。 '// 子プロセスと送受信するオブジェクトを登録する Dim sample : Set sample = new SampleClass '// has_interface_of InterProcessData g_InterProcess.m_Data.Add sample 参考 → T_ChildProcess2.vbs 子プロセスのライブラリの初期化(vbslib モジュールのグローバル・初期化関数)で、 get_ChildProcess as ParentChildProcess から、new_ObjectFromStream などを使って、 オブジェクトを受け取ってください。 メイン・プロセスに渡すオブジェクトは、 g_InterProcess.m_Data as ArrayClass に登録してください。 Dim g_Sample Sub InitializeModule_Sample '// vbslib モジュールのグローバル・初期化関数 '// NewChildProcessOnStart の後で new_ObjectFromStream g_Sample, "SampleClass", get_ChildProcess() If not IsEmpty( g_Sample ) Then g_InterProcess.m_Data.Add g_Sample End Sub 参考 → T_ChildProcess2_Sub.vbs → グローバル変数の初期化、後始末、g_InitializeModule、g_FinalizeModule テスト → T_ChildProcess2.vbs *********************************************************************** <<< g_InterProcess オブジェクト >>> *********************************************************************** g_InterProcess オブジェクト (src) メイン・プロセスと子プロセスで共有する変数です。 Dim g_InterProcess ' as InterProcess Class InterProcess Public Property Get ProcessCallID '// as ArrayClass of integer Public InterProcessUserData '// as string End Class .ProcessCallID ' as ArrayClass of integer ProcessCallID(0) = メイン・プロセスが子プロセスを起動した回数。 ProcessCallID(1) = 子プロセスが孫プロセスを起動した回数。 ライブラリのデータを格納後、g_InterProcess のデータを格納直前に、 +1されます。 → 処理フロー (/ChildProcess オプション) .InterProcessUserData as string アプリケーション・ユーザーがデバッグ用に使えます テスト → [T_ChildProcessID] ProcessCallID や InterProcessUserData *********************************************************************** <<< 困ったときは (/ChildProcess) >>> *********************************************************************** 困ったときは (/ChildProcess) 受け渡しの内容を確認するには 下記の XML ファイルを確認してください。 ただし、ParentProcess オブジェクトが削除されたら、XML ファイルも削除されるので注意してください。 %Temp%\Report\090401\ChildProcess_1\In.xml %Temp%\Report\090401\ChildProcess_1\Out.xml 参考 → 子プロセスへの受け渡し (/ChildProcess オプション) アプリケーションからデータが送れない RunProg の第2引数に、ParentProcess オブジェクトを指定しているか確認してください。 *********************************************************************** <<< GetCScriptGUI_CommandLine >>> *********************************************************************** GetCScriptGUI_CommandLine (src) Function GetCScriptGUI_CommandLine( Parameters as string ) as string ダブルクリックしたときに、vbslib のコマンド・プロンプトを開くコマンドラインを返します。 【引数】 Parameters cscript.exe に渡すパラメーター 返り値 コマンドライン Windows のバージョンによって、返り値の内容は変わります。 サンプル command_line = GetCScriptGUI_CommandLine( "sample.vbs" ) Assert command_line = _ """%windir%\System32\cmd.exe"" /K (""%windir%\SysWOW64\cscript.exe"" sample.vbs)" 環境変数を展開するときは、 → env *********************************************************************** <<< OpenFolder >>> *********************************************************************** OpenFolder Sub OpenFolder( in_FolderOrFilePath ) フォルダーを開きます。 フォルダーがなければユーザーに処理を選ばせます。 【引数】 in_FolderOrFilePath フォルダー、またはファイルのパス フォルダーを開く処理は、OpenFolder 関数の内部から Setting_openFolder 関数 を呼び出すことで行います。 in_FolderOrFilePath 引数の親フォルダーがあれば、そのフォルダーを開きます。 親フォルダーがなければ、以下のメニューを開きます。 "C:\Folder\Sub\File.txt" が見つかりません。 1. フォルダーを作る C:\Folder\Sub\File.txt 2. フォルダーを作る C:\Folder\Sub 3. フォルダーを開く C:\Folder 9. 続きを実行する 番号> ソース → vbslib.vbs テスト → T_OpenFolder_Manually.vbs 関連 → Setting_openFolder *********************************************************************** <<< GetEditorCmdLine >>> *********************************************************************** GetEditorCmdLine GetSearchOpenCmdLine (廃止予定) Function GetEditorCmdLine( PathAndFragment as string ) as string Function GetSearchOpenCmdLine( PathAndFragment as string ) as string (廃止予定) テキスト・エディターを起動するコマンドラインを返します。 【引数】 PathAndFragment テキストファイルへのパスと行番号またはキーワード 返り値 コマンドライン Setting_getEditorCmdLine の設定が反映されます。 PathAndFragment には、タグジャンプ形式の文字列(パス+行番号、または、パス+行内容) を指定できます。 形式については下記のサンプルを参照してください。 返り値に含まれるファイル・パスは、フル・パスになります。 拡張子が pdf で a.pdf#page=2 のように path を指定すると、Internet Explorer で指定した ページが開きます。(Internet Explorer の設定変更や仕様変更により使えなくなる可能性が あります。) サンプル: File1.txt を開きます start GetEditorCmdLine( "File1.txt" ) サンプル: File1.txt の10行目を開きます start GetEditorCmdLine( "File1.txt(10)" ) #number start GetEditorCmdLine( "File1.txt:10" ) :number サンプル: File1.txt を開いて "[Func1]" を含む行にジャンプします start GetEditorCmdLine( "File1.txt#[Func1]" ) #string start GetEditorCmdLine( "File1.txt:[Func1]" ) :string キーワードの直前の文字がコロン ( : ) のときは、数字のみのキーワードを指定できません。 サンプル: File1.txt を開いて "Func1" を行末に含む行にジャンプします start GetEditorCmdLine( "File1.txt#Func1${\n}" ) ${\n} \n は、C言語の改行の表現と同じです。 ${ } は、 ${ } 変数 の表現と同じです。 サンプル: File1.txt を開いて "Func1" を2番目に含む行にジャンプします start GetEditorCmdLine( "File1.txt#Func1${+2}" ) ${+number} テキストファイルを開くエディタは、 Setting_getEditorCmdLine 関数を定義することで変更でき ます。 Setting_getEditorCmdLine の i=2、i=3 のどちらかに対応すれば、指定の行へジャンプ できます。 i=0、i=1 のどちらかに対応していれば、ファイルを開くことだけはできます。 GetSearchOpenCmdLine は廃止予定です。 GetEditorCmdLine を使ってください。 参考 → タグジャンプ - テキストエディタ Apsaly (Web) ソース → vbslib.vbs テスト → T_Path.vbs T_GetEditorCmdLine 関連 → GetTagJumpParams タグジャンプ形式のパスの解析 → Setting_openFolder フォルダーを開く *********************************************************************** <<< GetDiffCmdLine, GetDiffCmdLine3, GetDiffCmdLine3Ex >>> *********************************************************************** GetDiffCmdLine, GetDiffCmdLine3, GetDiffCmdLine3Ex (src) Function GetDiffCmdLine( PathA as string, PathB as string ) as string Function GetDiffCmdLine3( PathA as string, PathB as string, PathC as string ) as string Function GetDiffCmdLine3Ex( PathA as string, PathB as string, PathC as string, in_Option as Empty or DiffCmdLineOptionClass ) as string DiffCmdLineOptionClass Diff ツール(比較するプログラム)を起動するコマンドラインを返します。 ファイルのパスが指定されたときに起動するツールは、 Setting_getDiffCmdLine の設定によって 変わります。 フォルダーのパスが指定されたときに起動するツールは、 Setting_getFolderDiffCmdLine の設定によって変わります。 サンプル テキスト ファイルを比較するツールを起動する。 start GetDiffCmdLine( "file1.txt", "file2.txt" ) サンプル フォルダーを比較するツールを起動する。 start GetDiffCmdLine( "folder1", "folder2" ) サンプル file1.txt、file2.txt、file3.txt を表示する start GetDiffCmdLine3( "file1.txt", "file2.txt", "file3.txt" ) 設定されている Diff ツールが3つのファイルを同時に比較することができないときは、 3つのファイルのうち、比較する2つのファイルを選択するスクリプト diff3to2.vbs を 起動するコマンドラインを返します。 サンプル file1.txt の 5行目と、それに対応する file2.txt を表示する start GetDiffCmdLine( "file1.txt(5)", "file2.txt" ) 設定されている Diff ツールが行番号指定に対応していないときは、5行目ではなく先頭の 行を表示します。 返り値の例: "C:\Program Files\Diff.exe" "C:\FileA.txt" "C:\FileB.txt" サンプル 相対パスを1つ入力して、Diff を開くプロンプト Dim folder_a, folder_b, step_path folder_a = "C:\folder_a\" folder_b = "C:\folder_b\" Do echo "" echo "2つのフォルダーの中にあるテキストファイルを Diff で表示します" echo folder_a echo folder_b echo "" echo "Enter のみ : 終了" step_path = input( "共通の相対パス >" ) If step_path = "" Then Exit Do start GetDiffCmdLine( GetFullPath( step_path, folder_a ), _ GetFullPath( step_path, folder_b ) ) Loop DiffCmdLineOptionClass GetDiffCmdLine3Ex 関数 に指定するオプション。 boolean .IsComparing(i) (i+1) 番目のフォルダーを比較するかどうか。 初期値は True。 3つのパスは指定するけど、そのうち一部だけ比較する ときは、比較しないフォルダーについて False にします。 参考 → DiffCUI *********************************************************************** <<< GetDiffStringCmdLine, GetDiffStringCmdLine3 >>> *********************************************************************** GetDiffStringCmdLine, GetDiffStringCmdLine3 Function GetDiffStringCmdLine( StringA as string, StringB as string ) as DiffCmdLineClass Function GetDiffStringCmdLine3( StringA as string, StringB as string, StringC as string ) as DiffCmdLineClass Diff ツールを起動して、文字列を比較するコマンドラインを返します。 【引数】 StringA 比較する文字列 A StringB 比較する文字列 B StringC 比較する文字列 C 返り値 コマンドラインの文字列、または、 DiffCmdLineClass GetDiffCmdLine, GetDiffCmdLine3 との違いは、引数が比較する内容の文字列であることです。 サンプル start GetDiffStringCmdLine( "ABC", "AxC" ) サンプル Diff ツールを開き、Diff ツールを閉じたら一時的に作成されるファイルを削除する Set diff_ = GetDiffStringCmdLine( "ABC", "AxC" ) RunProg diff_, "" Pause diff_.Remove ソース → TestScript.vbs 関連 → AssertString *********************************************************************** <<< DiffCmdLineClass >>> *********************************************************************** DiffCmdLineClass Dim DiffCmdLineClass::PathA as string 比較する文字列 A が入ったファイルのパス。 Dim DiffCmdLineClass::PathB as string 比較する文字列 B が入ったファイルのパス。 Dim DiffCmdLineClass::PathC as string Empty または、比較する文字列 C が入ったファイルのパス。 Default Property Get DiffCmdLineClass::CmdLine() as string Diff ツールを起動して、文字列を比較するコマンドライン。 Sub DiffCmdLineClass::Remove() 比較する文字列が入ったファイルを削除します。 参考 → GetDiffStringCmdLine ソース → TestScript.vbs *********************************************************************** <<< GetDiffOneLineCmdLine >>> *********************************************************************** GetDiffOneLineCmdLine Function GetDiffOneLineCmdLine( in_PathAndLineNumA as string, in_PathAndLineNumB as string ) as DiffCmdLineClass Diff ツールを起動して、指定した行を 1文字ずつ比較するコマンドラインを返します。 【引数】 in_PathAndLineNumA 比較するファイルのパスと行番号、または、比較する文字列 in_PathAndLineNumB 比較するファイルのパスと行番号、または、比較する文字列 返り値 コマンドラインの文字列、または、 DiffCmdLineClass サンプル start GetDiffOneLineCmdLine( "FileA.txt(3)", "FileB.txt(4)" ) サンプル Diff ツールを開き、Diff ツールを閉じたら一時的に作成されるファイルを削除する Set diff_ = GetDiffOneLineCmdLine( "FileA.txt(3)", "FileB.txt(4)" ) RunProg diff_, "" Pause diff_.Remove サンプル ファイルの比較ではなく、文字列を比較するときは、要素数1の配列を渡します。 start GetDiffOneLineCmdLine( Array( "Yes, it is." ), Array( "Yes, it was." ) ) ソース → TestScript.vbs テスト → T_fc.vbs T_GetDiffOneLineCmdLine 関連 → Diff1 コマンド *********************************************************************** <<< DiffCUI >>> *********************************************************************** DiffCUI Sub DiffCUI( FilePaths as array of string, FileLabels as array of string ) Diff ツールがないときに、コマンドラインだけで使える比較ツール。 【引数】 FilePaths 比較するファイル パスの配列 FileLabels 比較するファイルの役割名の配列 本関数を呼び出すと、以下のように表示されます。 1. 差分を調べて、結果をテキスト・エディターで開く 4. 01 のファイルを開く 5. 02 のファイルを開く *. 03 のファイルは、存在しません **. コピーする(コピー元(4以上)×10+コピー先(4以上) 例:45 = 01 → 02 99. 戻る 操作の番号を入力してください > Diff ツールで開くファイルのパスをテストでチェックするとき DiffCUI は、比較しているそれぞれのファイルを開くメニューがあり、 テキストエディターで開くファイルのパスをテストでチェックする 方法と組み合わせれば、Diff ツールで開くファイルのパスをチェックできます。 参考 → DiffCUI_InCurrentProcess → _src\Test\tools\T_SyncFiles\SettingForTest.vbs ソース → vbslib.vbs テスト → T_SyncFiles.vbs 関連 → GetDiffCmdLine, GetDiffCmdLine3 *********************************************************************** <<< DiffCUI_InCurrentProcess >>> *********************************************************************** DiffCUI_InCurrentProcess Function DiffCUI_InCurrentProcess( CommandLine as string ) start に InCurrentProcessFunc を指定して、 DiffCUI を呼び出すために経由する関数。 start に本関数の返り値を指定すると、以下のように表示されます。 >start \?InCurrentProcessFunc\DiffCUI_InCurrentProcess -i=33 "C:\Folder\01" "C :\Folder\02" "C:\Folder\03" ------------------------------------------------------------------------------- 1. 差分を調べて、結果をテキスト・エディターで開く 4. 01 のファイルを開く 5. 02 のファイルを開く *. 03 のファイルは、存在しません **. コピーする(コピー元(4以上)×10+コピー先(4以上) 例:45 = 01 → 02 99. 戻る 操作の番号を入力してください > ソース → PC_setting_default.vbs *********************************************************************** <<< Sleep >>> *********************************************************************** Sleep (src) Sub Sleep( msec as integer ) 指定した時間だけ待ちます。 【引数】 msec 待つ時間(ミリ秒) サンプル: Sleep 1000 サンプル: Dim n : For n = 5 To 1 Step -1 : echo n : Sleep 1000 : Next : echo 0 5秒のカウントダウン 関連 → timeout (バッチファイル) *********************************************************************** <<< WaitForFile >>> *********************************************************************** WaitForFile (src) Function WaitForFile( Path as string ) as string 指定したファイルが作られるまで待ちます。 【引数】 Path 待つファイルのパス 返り値 ファイルの1行目の内容(末尾に改行文字なし) サンプル: WaitForFile "Result.txt" 何かの処理(前処理)が終わってから行う処理があるときに使います。 前処理が終わるときに、終わったことを示すファイルを作るようにすれば、 本関数が使えるようになります。 本関数から抜ける直前で、対象のファイルを削除します。 エラーを発生させるファイルを作る WaitForFile で待っているファイルが、XML 形式のテキストで、ルートのタグが のときは、WaitForFile の内部からエラーを発生させます。 作成するファイルの例 上記の場合、Err オブジェクトの内容は、次のようになります。 Assert Err.Number = 3 Assert Err.Description = "" 通信の注意 同期に使うファイルは、2つのスレッド(クライアントとサーバー)で別のファイル名にしてください。 そうしないと、自分が作成(送信)したファイルを待つ(受信する)形になり、待たないことに なってしまうからです。 送信ファイルを作成する前に、受信したファイルを削除してください。 そうしないと、相手が次の受信ファイルを先に作ってしまい、そのファイルを削除してしまう からです。 また、前の通信の残りがあるときでも正しく動くように、クライアントは、前の受信 ファイルを削除してから、送信ファイルを作成してください。 複数のプロセスで通信をするときは、同期に使用するファイルを最終的に 削除する責任を持つ 形にしてください。 そうしないと、同期に使用するファイルを相手に通知する 前に削除してしまう可能性が生まれて、サブ・スレッドが永遠に待ち続ける ことになってしまいます。 ホスト側が WaitForFile で待って通信を終える メイン・スレッド (クライアント) サブ・スレッド (サーバー) 起動 WaitForFile CreateFile CreateFile で終えると (busy) delete 終了 WaitForFile 待ち続ける... テスト → T_Call_Target.vbs # [T_WaitForFile] 関連 → CreateFile → FileT_wait (clib) → OnTime (Excel) *********************************************************************** <<< WaitForProcess >>> *********************************************************************** WaitForProcess (src) Sub WaitForProcess( ProcessName as string ) 指定したプロセスが終了するまで待ちます。 【引数】 ProcessName 実行ファイル名 ファイル: System.vbs サンプル WaitForProcess "notepad.exe" テスト → T_Process.vbs # [T_WaitForProcess] *********************************************************************** <<< EnumProcesses >>> *********************************************************************** EnumProcesses (src) Function EnumProcesses() as dictionary of ArrayClass of integer プロセスを一覧します。 【引数】 返り値 プロセスの一覧。 実行ファイル名をキーとする PID の配列の辞書 ファイル: System.vbs サンプル Dim ps : Set ps = EnumProcesses() echo ps.Item( "notepad.exe" ) '// ArrayClass of PID If not ps.Exists( "notepad.exe" ) Then '// ps.Item( "notepad.exe" ).Count = 0 は不可 start "notepad.exe" ElseIf ps.Item( "notepad.exe" ).Count >= 2 Then echo "There are 2 processes." End If 参考 → tasklist (バッチファイル) テスト → T_Process.vbs # [T_Processes] *********************************************************************** <<< KillProcess >>> *********************************************************************** KillProcess (src) Sub KillProcess( Process as integer or string ) プロセスを強制終了します。 【引数】 Process プロセスの PID、または、実行ファイル名 ファイル: System.vbs 実行ファイル名を指定した場合、その実行ファイルから作られたすべての インスタンスが強制終了します。 サンプル KillProcess "notepad.exe" 参考 → taskkill (バッチファイル) テスト → T_Process.vbs # [T_Processes] *********************************************************************** <<< その他 >>> *********************************************************************** その他 → IsDefined 指定したシンボルの関数が定義されているかどうかを返します。 *********************************************************************** <<< 自動テスト、開発環境 >>> *********************************************************************** 自動テスト、開発環境 プログラムが大きくなるほど、テスト(回帰テスト)の自動化が重要になります。 → テスト・プロンプト (Test.vbs) → テスト支援機能 (関数) → 開発環境操作 vbslib の開発では、機能を追加/修正するごとに以下のものを更新しています。 機能: コード × テストプログラム × ドキュメント × ○ 参考 → チェックリスト 関連 → エラー処理 (Err2) → FCBat テストツール → 標準出力への出力内容をチェックするテスト → ログ → 自動化のヒント → テストツール → テストツールの接続場所 → テスト駆動開発(TDD)を学ぶ (Web) → vbslib のテスト仕様 *********************************************************************** <<< テスト・プロンプト (Test.vbs) >>> *********************************************************************** テスト・プロンプト (Test.vbs) (src: TestPrompt) (src: Tests) Test.vbs ファイルに記述されたコールバック関数(Test_build, Test_setup, Test_start, Test_check, Test_clean)を呼び出すプロンプトです。 サブ・フォルダーにある Test.vbs ファイルに記述されたコールバック関数も呼び出します。 Test.vbs をダブルクリックして起動します。 Test Prompt [ALL] test vbs = Test.vbs base folder = C:\home\vbslib 1. Select the Test (current test = ALL) 2. Do ALL Test 3. | call each "Test_build" in sub folders 4. | call each "Test_setup" in sub folders 5. | call each "Test_start" in sub folders 6. | call each "Test_check" in sub folders 7. | call each "Test_clean" in sub folders 8. Change the Debug Mode (debug script=False, target=False) 88.Open Fail Folder 89.Next Fail 9. Quit → メニュー項目 Change the Debug Mode テスト・プロンプトのトップメニュー Test.vbs → メニュー項目の動作 → テスト・フォルダーの構成 → Test.vbs 単体のテスト・スクリプト → TestCommon.vbs → TestCommon_Data.xml → Test.vbs のコマンドライン・オプション → Fail したとき → サブフォルダの関数の呼び出し順序 → 処理フロー → データ構造 → TestPrompt_Setting.vbs プロンプトの設定 テスト → テスト・プロンプトのテスト 関連 → 処理フロー (Test.vbs) → データ構造 (Test.vbs) → テスト・スクリプト ver2 *********************************************************************** <<< メニュー項目の動作 >>> *********************************************************************** メニュー項目の動作 [ 親: テスト・プロンプト Test.vbs ] テストプロンプトのメニューから選んだときのデフォルトの動作を説明します。 1. Select the Test 実行するテスト項目( Test.vbs 、または、Test.vbs があるフォルダー)を選択します。 ALL を選択すると、すべてのテスト項目(すべてのサブ・フォルダー)を実行します。 「order」 と入力すると、 サブフォルダの関数の呼び出し順序 と CurrentTestPriority が表示されます。 2. Do ALL Test Test.vbs の Test_build, Test_setup, Test_start, Test_check, Test_clean を呼び出します。 Test_current は、Test_build などそれぞれを呼び出す前に呼び出します。 → サブフォルダの関数の呼び出し順序 → Tests::DoAllTest 3. call each "Test_build" in sub folders Test.vbs の Test_current と Test_build を呼び出します。 → Tests::DoTest 4. call each "Test_setup" in sub folders Test.vbs の Test_current と Test_setup を呼び出します。 5. call each "Test_start" in sub folders Test.vbs の Test_current と Test_start を呼び出します。 6. call each "Test_check" in sub folders Test.vbs の Test_current と Test_check を呼び出します。 7. call each "Test_clean" in sub folders Test.vbs の Test_current と Test_clean を呼び出します。 8. Change the Debug Mode → デバッグモード 88. Open Fail Folder エラーがあった Test.vbs があるフォルダーを開きます 89. Next Fail 次にエラーがあった Test.vbs があるフォルダーを開きます *********************************************************************** <<< デバッグモード >>> *********************************************************************** [ マップ ] デバッグモード テスト・プロンプトのトップメニューで、Change the Debug Mode を選ぶと次のメニューが出ます。 1) Reload Test Script 2) ChgDebugMode Test Script 3) ChgDebugMode Test Target 4) Echo On/Off (current=on) 5) AutoDiff (current=on) Reload Test Script ChgDebugMode Test Script ChgDebugMode Test Target Echo On/Off AutoDiff 1) Reload Test Script Reload Test Script は、TestPrompt.vbs や、TestPrompt_Setting.vbs を変更したときに 選択します。 選択すると再読み込みします。 Test.vbs は、トップメニューから Test.vbs を呼び出すときに、毎回再読み込みするので、 Test.vbs を変更したときは、このメニュー(Reload Test Script)を選ぶ必要はありません。 2) ChgDebugMode Test Script ChgDebugMode Test Script は、TestPrompt.vbs と Test.vbs をデバッガに接続します。 Test.vbs の先頭で下記のように記述すると、このメニューを選ばなくても、自動的にこの モードで実行を開始し、5番のメニューを自動的に実行します。 '--- start of parameters for starting main script g_debug = 1 : Sub main2( Opt, AppKey ):set_input "5." .... 1 5. Test.vbs をデバッグするときは、更に Test.vbs の中に Stop 文を入れてください。 Sub Test_start( tests ) Stop If ... Then Fail Pass End Sub Stop 3) ChgDebugMode Test Target ChgDebugMode Test Target は、テスト対象をデバッガに接続します。 Test.vbs の先頭で次のように記述すると、自動的にこのモードで実行を開始し、 5番のメニューを自動的に実行します。 '--- start of parameters for starting main script g_option = "/target_debug:1 /set_input:5." ただし、Test.vbs の関数の引数 tests の bTargetDebug メンバ変数が True に 変わるだけなので、Test.vbs の中で対応する必要があります。 If tests.bTargetDebug Then '// デバッガに接続するコマンド Else '// 通常のコマンド End If VBScript の呼び出しを、デバッガ接続に対応した例: If tests.bTargetDebug Then dbg = "//x " Else dbg = "" r = RunProg( "cscript "+dbg+target+" /Test:"+tname, "" ) 4) エラー・ブレークを有効にする テスト・スクリプトでも通常の方法でエラーが発生した場所でブレークできます。 参考 → エラーが発生した瞬間のスクリプト内部の様子を調べる エラーが発生する場所が安定しないときは、エラー・ブレークを有効にしてください。 エラーが発生してもテストの続きを実行しなくなりますが、エラーが発生したところで ブレークします。 注意: Pass 関数を呼び出したときもブレークしてしまいます。 5) AutoDiff → AutoDiff モード 関連 → g_debug 変数 → input … /set_input オプションが使われる関数 *********************************************************************** <<< テスト・フォルダーの構成 >>> *********************************************************************** テスト・フォルダーの構成 [ 親: テスト・プロンプト Test.vbs ] テスト・スクリプトは、scriptlib フォルダを含むルートフォルダのサブフォルダなら、 どのフォルダにでも置くことができます。 テスト・スクリプトのファイル名は、Test.vbs にしてください。 Test.vbs をダブルクリックすると、テスト・プロンプトが開きます。 → Test.vbs Test Test.vbs … ユニット・テスト 全体 TestCommon.vbs … 全ユニット・テストに共通のスクリプト TestCommon_Data.xml … 全ユニット・テストに共通の設定データ T_UnitTest1 … テストシンボル名と同じ名前のフォルダ Test.vbs … "T_UnitTest1" のユニット・テスト scriptlib vbslib TestPrompt.vbs … テスト・プロンプト・モジュール TestScript.vbs … テスト・スクリプト・モジュール setting_default TestPrompt_Setting.vbs … テスト・プロンプトの設定 Test.vbs をダブルクリックすると、サブフォルダの Test.vbs も、テスト・プロンプトに 登録されます。 カレント・テストが ALL なら、サブフォルダも含めて Test_setup などが 呼ばれます。 デバッグ・モードのときは、デバッグ・モードになっている Test.vbs を サブフォルダも含めて呼ばれます。 → サブフォルダの関数の呼び出し順序 *********************************************************************** <<< Test.vbs >>> *********************************************************************** [ マップ ] [ 親: テスト・プロンプト Test.vbs ] Test.vbs (src) 単体テストを実行するスクリプトです。 ダブルクリックすると、 テスト・プロンプト が開きます。 用意された関数 の内容を記述することで作成します。 テスト・プロンプトから、サブ・フォルダーにある大量の Test.vbs を自動的に実行することが できます。 ファイル名を TestSample.vbs に変えたら、サブ・フォルダーにある TestSample.vbs を自動的に実行します。 RunTestPromptConfigClass ::ExpectedPassConutに予想される Pass の数を設定しておくと よいでしょう。 Test.vbs のテンプレート vbslib_pack\sample\TestPrompt T_Run 汎用のサンプル T_RunFCVbs FCVbs を経由するテストのサンプル T_RunPrompt テストプロンプトをテストするサンプル T_RunVBS VBS をテストするサンプル Test.vbs に記述する関数 Main RunTestPrompt を呼び出してください。 Test_current Test_build などをコールバックする前にコールバックされる関数。 Test_build テスト対象をビルドします。 Test_setup テストデータを作成します。 Test_start テストを実行します。 複数の項目を実行するときはチェックもします。 Test_check Test_start がすべて完了後、テストの出力が正しいかチェックします。 エラー処理のテストは、Test_start で行います。 Test_clean テストで出力されたファイルを削除します。 引数は、 Tests クラス です。(上記の関数はどれも引数は同じ) Sub Test_start( tests as Tests ) 上記の関数は、 TestScript::Do_ から呼ばれます。 Fail したときの動きは、 Do_ の仕様に従います。 Test.vbs の Test_current には、デバッグを行う1つのサブテストケースを tests.SetCur で指定します。 Test.vbs サンプル → Test.vbs Option Explicit Sub Main( Opt, AppKey ):RunTestPrompt AppKey.NewWritable( "." ):End Sub Sub Test_current( tests ) tests.SetCur "Sub1" End Sub Sub Test_build( tests ) If tests.IsCur("Sub1") Then echo tests.Symbol+" - Test_build Sub1" If tests.IsCur("Sub2") Then echo tests.Symbol+" - Test_build Sub2" Pass End Sub Sub Test_setup( tests ) Pass End Sub Sub Test_start( tests ) RunProg "target.exe", "Sample_log.txt" Pass End Sub Sub Test_check( tests ) Fail End Sub Sub Test_clean( tests ) Skip "test skip" End Sub テスト → T_TestScName フォルダ Test.vbs から改名するテスト 関連 → GetMainSetting 関数 (vbsool) → アプリケーション (vbslib付属) *********************************************************************** <<< Test_current >>> *********************************************************************** Test_current Sub Test_current( tests as Tests ) Test_build などをコールバックする前にコールバックされる関数。 下記のようなことができます。 ・Tests.vbs のグローバル変数(の代わり)を初期化します。 Set g = tests.CurrentTest.Delegate g("ExeName") = "Sample" → UnitTest::Delegate 関連 → GetMainSetting 関数 ・他の Tests.vbs と、コールバックされる順番を調整します。 Sub Test_current( tests ) tests.CurrentTestPriority = 500 End Sub CurrentTestPriority ・テスト・シンボルを設定します。 Sub Test_current( tests ) tests.Symbol = "T_SubTest" End Sub Symbol "Already defined test symbol" エラー が出るときは、 上記のように Symbol 変数の値を変更してください。 ・デバッグするサブテストケースを選択します。 Sub Test_current( tests ) tests.SetCur "Sub1" End Sub SetCur *********************************************************************** <<< UnitTest::Delegate >>> *********************************************************************** UnitTest::Delegate Dim UnitTest::Delegate as variant UnitTest ユーザ向けの、任意の値やオブジェクトを格納する変数。 Tests.vbs のグローバル変数の代わりです。 (Tests.vbs は、ExecuteGlobal を何度も行われるため、グローバル変数を置くことができません。) サンプル in Test.vbs: RunTestPrompt を実行する場合は、Delegate を使う Sub Main( Opt, AppKey ) '// Set g = GetTemporaryTestsObject().CurrentTest.Delegate RunTestPrompt AppKey.NewWritable( "." ) End Sub Sub Test_current( tests ) If IsEmpty( tests.CurrentTest.Delegate ) Then Set g = CreateObject( "Scripting.Dictionary" ) : Set tests.CurrentTest.Delegate = g '// call_vbs SearchParent("TestCommon.vbs"), "TestCommon_setVariables", g '[Setting] '============================================================================== g("ExeName") = "Sample" '============================================================================== x = WScript.Arguments.Named( "Config" ) : If not IsEmpty( x ) Then g("Config") = x End If End Sub Sub Test_build( tests ) Set g = tests.CurrentTest.Delegate devenv_rebuild g("ExeName")+".sln", g("Config") End Sub Delegate TestCommon.vbs TestCommon_setVariables ExeName Sample Delegate ExeName サンプル in TestTarget.vbs: RunTestPrompt を実行しない場合は、Delegate を使わない Dim g_g : Sub GetMainSetting( g ) : If not IsEmpty(g_g) Then Set g=g_g : Exit Sub Set g=CreateObject("Scripting.Dictionary") : Set g_g=g call_vbs SearchParent("TestCommon.vbs"), "TestCommon_setVariables", g '[Setting] '============================================================================== g("ExeName") = "Sample" '============================================================================== End Sub Sub Main() GetMainSetting g devenv_rebuild g("ExeName")+".sln", g("Config") End Sub TestCommon.vbs TestCommon_setVariables ExeName Sample ExeName 参考 → GetMainSetting 関数 (vbsool) TestCommon.vbs の中の TestCommon_setVariables 関数 のサンプル: '******************************************************************************** ' <<< [TestCommon_setVariables] >>> '******************************************************************************** Dim g_TestCommon_ConfigInited Sub TestCommon_setVariables( in_out_SharedConfig ) AssertExist env("%SAMPLEROOT%") '// 環境変数をチェックする If IsEmpty( g_TestCommon_ConfigInited ) Then '// プロセスごとの設定 Set test_common_data = ReadTestCase( SearchParent(_ "TestCommon_Data.xml" ), Empty ) '// test_common_data as If IsEmpty( in_out_SharedConfig ) Then _ Set in_out_SharedConfig = CreateObject( "Scripting.Dictionary" ) Dic_add in_out_SharedConfig, test_common_data g_TestCommon_ConfigInited = True End If End Sub AssertExist ReadTestCase TestCommon_Data.xml コールツリー (Test.vbs) RunTestPrompt Tests::DoAllTest Test_current // テストごとに異なる UnitTest::Delegate TestCommon_setVariables // 全テストに共通の UnitTest::Delegate など コールツリー (一般スクリプト) main GetMainSetting // スクリプト・ファイルごとに異なる UnitTest::Delegate TestCommon_setVariables // 全スクリプト共通の UnitTest::Delegate など テスト → Test_template1.vbs # Delegate 関連 → GetMainSetting 関数 (vbsool) → TestCommon.vbs *********************************************************************** <<< TestCommon.vbs >>> *********************************************************************** [ 親: テスト・プロンプト Test.vbs ] TestCommon.vbs サブ・フォルダーにある Test.vbs に共通するスクリプトを記述します。 ライブラリにするほど汎用的ではないが、複数のテストで使われる関数などを記述します。 Test.vbs Sub main2( Opt, AppKey ) RunTestPrompt AppKey.NewWritable( "." ) End Sub Sub Test_current( tests ) If IsEmpty( tests.CurrentTest.Delegate ) Then Dim g : Set g = CreateObject( "Scripting.Dictionary" ) : Set tests.CurrentTest.Delegate = g call_vbs SearchParent("TestCommon.vbs"), "TestCommon_setVariables", g End If End Sub Sub Test_start( tests ) : TestCommon_test_start tests : Pass : End Sub TestCommon.vbs Sub TestCommon_setVariables( g ) Set g("GlobalTestObject") = new SampleTest End Sub Sub TestCommon_test_start( tests ) '// 複数のテストで行う処理 End Sub TestCommon_setVariables 関連 → GetMainSetting 関数 (vbsool) *********************************************************************** <<< グローバル・テスト・オブジェクト, SampleTest >>> *********************************************************************** グローバル・テスト・オブジェクト, SampleTest TestCommon.vbs で定義する TestCommon_setVariables 関数で、グローバル・テスト・ オブジェクトを生成し、 UnitTest::Delegate から参照します。 Sub Test_build( tests ) Dim g : Set g = tests.CurrentTest.Delegate RunProg """"+ g("GlobalTestObject").ExePath +"""", "" End Sub Sub TestCommon_setVariables( g ) Set g("GlobalTestObject") = new SampleTest End Sub *********************************************************************** <<< TestCommon_Data.xml >>> *********************************************************************** [ 親: テスト・プロンプト Test.vbs ] TestCommon_Data.xml テストに関する情報をまとめたデータ・ファイルです。 ダブルクリックする Test.vbs と同じフォルダーに TestCommon_Data.xml を作成してください。 TestSymbols 属性 Test.vbs の 2. Do ALL Test を選んだときに実施するテストを選択します。 実施するテストのシンボルを CSV 形式で指定してください。 Test.vbs の シンボルが多いときは、改行を入れることができます。 1. Select the Test を選ぶと、シンボルを一覧できます。 この属性が無いときは、サブ・フォルダーにある全てのテストを実施します。 参考 → Tests::LoadTestSet TestScriptFileName 属性 TestScriptFileName 属性に、Test.vbs のファイル名を指定すると、そのファイル名から 起動した場合のみ、有効になります。 TestScriptFileNameExcepted 属性 TestScriptFileNameExcepted 属性に、Test.vbs のファイル名を指定すると、その ファイル名「以外」から起動した場合のみ、有効になります。 その他、オリジナル属性 テスト固有のオリジナル属性を、TestCommon_Data.xml に含めることができます。 参考 → TestCommon.vbs の中の TestCommon_setVariables 関数 のサンプル *********************************************************************** <<< Test.vbs のコマンドライン・オプション >>> *********************************************************************** Test.vbs のコマンドライン・オプション コマンドライン・オプションを指定して起動すると、メニューから選択することなく、自動的に テストの実施などを行うことができます。 サンプル: BuildTest.bat @echo off echo テストのビルド・ステップを実行します。 pause cscript Test.vbs /Build 次のオプションがあります。 /Case:TestSymbol TestSymbol に指定したテスト・シンボルの Test.vbs を選択します。 /Case オプションが無いときは、すべての Test.vbs を選択します。 /All Test.vbs の Test_build, Test_setup, Test_start, Test_check, Test_clean を 呼び出します。 呼び出したら、プロセスを終了します。 /Build Test_build 関数を呼び出します。 呼び出したら、プロセスを終了します。 /Setup Test_setup 関数を呼び出します。 呼び出したら、プロセスを終了します。 /Start Test_start 関数を呼び出します。 呼び出したら、プロセスを終了します。 /Check Test_check 関数を呼び出します。 呼び出したら、プロセスを終了します。 /Clean Test_clean 関数を呼び出します。 呼び出したら、プロセスを終了します。 /log テストのログのファイル名。 デフォルトは、"Test_logs.txt" テスト → T_Prpt フォルダ 関連 → テスト・スクリプト ver2 VBS から Test.vbs を呼び出す *********************************************************************** <<< Fail したとき >>> *********************************************************************** Fail したとき [ 親: テスト・プロンプト ] テストに Fail したときの対応のヒントを説明します。 関連 FCBat を使っているときは、 → Fail したテスト項目を特定する (FCBat) 1.エラー状況を確認する Test_start などでエラーが発生しても、エラーがあったことを表示して、Test_logs.txt に記録 するだけで、次のテスト関数を呼び出しに行きます。 Test_logs.txt, Test_log.txt Test_logs.txt には、エラーが発生した Test.vbs のフル・パスと、テスト関数が記録されて います。 RunTestPrompt で、テストを1つだけ指定したときは、Test_log.txt に記録されます。 [FAIL] Fail the Test in "Test_start" function in "C:\home\vbslib_pack\_src\T_Priority\Test.vbs" Test_logs.txt を「書き込みできない」とき、テスト・プロンプトが二重に起動して同じファイルを 開こうとしているときがあります。 そのときは、下記の /log オプションを指定して Test.vbs を 起動するか、Main 関数の先頭で、m_DefLogFName にログ・ファイルの名前を設定してください。 cscript Test.vbs /log:TestTarget_logs.txt Sub Main( Opt, AppKey ) g_Test.m_DefLogFName = "TestTarget_logs.txt" RunTestPrompt AppKey.NewWritable( "." ) End Sub 旧 AutoDiff モード 廃止されました。 AssertFC を使ってください。 ver4 では、m_bAutoDiff_ に変えると動きますが、今後は無くなります。 AutoDiff モードを有効にすると、テストが失敗したとき、テスト・ログの中にコマンドプロンプトの fc コマンド の出力(テキストの差分表示)があれば、Diff ツールを起動します。 Sub Main( Opt, AppKey ) g_Test.m_bAutoDiff = True RunTestPrompt AppKey.NewWritable( "." ) End Sub m_bAutoDiff Diff ツールの設定 → Setting_getDiffCmdLine テスト → [T_AutoDiff] 自動的に Diff ツールを開く 2.繰り返し実行する環境を作る テスト・プロンプトへの入力を自動化することで、繰り返しテストを実行することを簡単にします。 Tests.vbs Sub main2( Opt, AppKey ):set_input "5." :RunTestPrompt AppKey.NewWritable( "." ):End Sub 5. 3.デバッガに接続して、問題のある場所で止める → エラーが発生した瞬間のスクリプト内部の様子を調べる → エラー・ブレークを有効にする (旧版) Test_logs.txt に記録されている Test.vbs を デバッグモード(Script) で実行すると、問題がある 場所でブレークします。 多くの場合、テスト対象のプログラムの出力値チェックでエラーになっているので、Test.vbs を デバッグモード(Target) で実行します。 テスト・プロンプト自体をデバッグするときは、デバッグモード(Script) で実行してブレークする 場所に、Stop 命令を記述し、cscript.exe //x で、Test.vbs を実行してください。 *********************************************************************** <<< サブフォルダの関数の呼び出し順序 >>> *********************************************************************** サブフォルダの関数の呼び出し順序 テスト・プロンプトは、サブフォルダにある Test.vbs (起動時のファイル名と同じ名前の ファイル)も呼び出します。 (TestCommon_Data.xml の によって実施するテストは制限できます。) その呼び出す順序を説明します。 /TestCases/@TestSymbols AddTestScriptAuto 追加順序 Test_current Test_start Test_build Test_check Test_setup Test_clean T_SomeTests Test.vbs 1 1 4 7 10 15 18 T_UnitTest1 Test.vbs 2 2 5 8 11 14 17 T_UnitTest2 Test.vbs 3 3 6 9 12 13 16 数字に書いてある順番に Test_current 関数などがコールバックされます。 ただし、同じ深さの T_UnitTest1 と T_UnitTest2 の順番は変わることがあります。 ALL テストを行うと、すべての Test.vbs ファイル(起動時のファイル名と同じ名前の ファイル)の Test_current を読んだ後に、すべての Test.vbsファイルの Test_build を 呼び出す…、と繰り返していきます。 Test_current, Test_build, Test_setup, Test_start は、Tests::AddTestScript した順に、 Test_check, Test_clean は、Tests::AddTestScript した順と逆に呼ばれます。 Tests::AddTestScriptAuto は、親フォルダから追加していくので、 Test_current, Test_build, Test_setup, Test_start は、親フォルダから、 Test_check, Test_clean は、子フォルダから呼ばれます。 Tests::CurrentTestPriority を設定することで、テストの順番を変えることができます。 (ver4) テストに失敗したら、そのテストの続きの関数はコールバックされません。 たとえば、T_UnitTest1 の Test_start 関数内でエラーが発生したら、T_UnitTest1 の Test_check, Test_clean 関数はコールバックされません。 (ver4) テストをスキップしたら、そのテストの続きの関数はコールバックされませんが、 Test_clean 関数はコールバックされます。 たとえば、T_UnitTest1 の Test_start 関数 内で Skip 関数を呼び出したら、T_UnitTest1 の Test_check 関数はコールバックされ ませんが、T_UnitTest1 の Test_clean 関数はコールバックされます。 (ver4) Test_build 関数と Test_setup 関数と Test_start 関数は、親フォルダーの テストに失敗があれば、子フォルダーの同じ名前の関数はコールバックされません。 Test_check 関数と Test_clean 関数は、子フォルダーのテストに失敗があれば、 親フォルダーの関数はコールバックされません。 テスト → [T_SomeTests] 複数のテストスクリプト 関連 → Tests::CurrentTestPriority → Tests::SetCur → Select the Test メニュー 呼び出し順序を確認する *********************************************************************** <<< テストプログラム作成のヒント >>> *********************************************************************** テストプログラム作成のヒント → 手動テストは、ユーザーをガイドするスクリプトを作成すること → テストケースの組み合わせ → ファイルを生成したり、更新したりするテスト → 他のプログラムを起動する機能のテスト → エラーメッセージをチェックするテスト → echo 出力して、その内容が正しいことをチェックするテスト 手動テストは、ユーザーをガイドするスクリプトを作成すること 実際にテストを実行する前に、スクリプトで、自動的に行われる動作の説明と、手動で操作する内容と 確認する内容を表示して、pause 関数を呼び出してください。 echo_line EchoTestStart "T_Sample" echo "〜されるので、〜してください。" echo "〜であること。" pause echo_line (手動テストの自動部分の処理) 参考 → samples/Test/T_TestByManual フォルダ 手動テストが存在することを知らせるために、Test_start 関数で、ManualTest 関数を呼び出してください。 テストケースの組み合わせ テストケースの組み合わせは多重ループで記述します。 ただし、組み合わせは必要最低限にして ください。 テストのパラメーターは、 記述しやすくなります。 実際にテストを行うコードは、ループの最後の方にあります。 DicTable 関数 JoinDicTable 関数 Dic_add 関数 を使うと Dim t, t2 For Each t In DicTable(Array( _ "Case", "SrcPath", "AnsPath", Empty, _ "Default", "sample1.xml", "sample1_replaced.xml", _ "UTF8_BOM", "sample6_utf8bom.xml", "sample6_utf8bom_replaced.xml", _ "Unicode", "sample3_unicode.xml", "sample3_unicode_replaced.xml" )) For Each t2 In DicTable(Array( _ "Case2", "DstPath", "OutPath", Empty, _ "DstNormal", "out.xml", "out.xml", _ "DstEmpty", Empty, "out.xml", _ "DstOverWrite", "out.xml", "out.xml" )) Dic_add t, t2 : t2.RemoveAll '// cross join '//=== setup files ... '//=== Do test '//##################################### Test Point Assert Convert( t("SrcPath"), t("DstPath") ) = t("AnsPath") Next Next DicTable DicTable Dic_add 関連 → TestNums → SQL JOIN ファイルを生成したり、更新したりするテスト 各テスト項目の最初で、存在する可能性のあるすべてのファイルを削除する関数を呼ぶ。 よくある、すでに存在するファイルがあるときは、そのテンプレートからコピーする 他のプログラムを起動する機能のテスト Setting_getEditorCmdLine などを、プログラムを起動しないようにする WaitForFile で待つ エラーメッセージをチェックするテスト Dim e, e2 ' as Err2 '// Error Handling Test echo vbCRLF+"Next is Error Test" If TryStart(e) Then On Error Resume Next ... If TryEnd Then On Error GoTo 0 e.CopyAndClear e2 '// Set "e2" echo e2.desc Assert InStr( e2.desc, "SomeError" ) >= 1 Assert e2.num <> 0 CopyAndClear エラーの情報を Err2::CopyAndClear でコピーしてから、チェックしてください。 g_debug を設定したときに、Fail したところで正しくブレークするようになります。 チェックするところではなく、エラーが発生した場所でブレークするには、次のように e.Raise を記述して、一旦 /g_debug オプション を無効にし、/g_debug オプションに設定する値を 変更します。 ... If TryEnd Then On Error GoTo 0 e.Raise e.CopyAndClear e2 '// Set "e2" echo 出力して、その内容が正しいことをチェックするテスト RunProg で子プロセスを起動し、その出力をファイルにリダイレクトします。 子プロセスで実行するスクリプトは、直接起動することもできます。 たとえば、下記のスクリプト では、T_Example_Main を起動します。 Sub T_Example( Opt, AppKey ) Set w_= AppKey.NewWritable( "_log.txt" ).Enable() RunProg "cscript //nologo T_Wildcard.vbs T_Example_Main", "_log.txt" AssertFC "_log.txt", "T_Example_ans.txt" del "_log.txt" Pass End Sub Sub T_Example_Main( Opt, AppKey ) echo GetTestResult() Pass End Sub 関連 → % を使った文字列変換関数 *********************************************************************** <<< 処理フロー (Test.vbs) >>> *********************************************************************** 処理フロー (Test.vbs) [ 親: テスト・プロンプト ] テストスクリプトを起動すると、テストプロンプトが起動します。 ユーザがメニューから選択すると、テスト・プロンプトからコールバック されるので、テストの実施などを行います。 インクルード テスト プロンプト (TestPrompt.vbs) コールバック テスト スクリプト (Test.vbs) テスト実施 テスト対象 プロセス チェック 出力データ 出力 各テスト項目 テスト・プロンプト・エンジン Test.vbs TestPrompt.vbs ターゲットプログラム RunTestPrompt (src) TestPrompt_Setting.vbs をロード&SetTest をコール → Setting_buildTestPrompt メニューを表示 (src) (UnitTest).vbs を再ロード Tests::DoAllTest Test_start などをコールバック → 呼び出し順序 起動 テストを実行 結果を報告 (src) TestScript::Finish メニューを表示 同一プロセス内 *********************************************************************** <<< データ構造 (Test.vbs) >>> *********************************************************************** データ構造 (Test.vbs) TestPrompt in RunTestPrompt() (src) MenuItem .m_Menu() Tests (src) .m_Tests Dic< UnitTest > .Sets UnitTest .CurrentTest TestScript g_Test Tests::DoAllTest (src) SectionTree section *********************************************************************** <<< テスト・スクリプト ver2 >>> *********************************************************************** テスト・スクリプト ver2 別の VBS ファイルを呼び出したり、ログをとったりします。 全テストのとき、ユニットテストのとき、デバッグのとき、という状況に応じて、 テストスケジューラは、臨機応変にテストスクリプトを呼び出します。 テスト処理が失敗したら、テストスクリプトからテストスケジューラに return 的に戻り、 テストスケジューラは、次のテストスクリプトを実行します。 cscript.exe など テスト スケジューラ テスト スクリプト Do_ プロセス起動 → TestPrompt クラス Tests クラスをユーザから使うためのコマンドプロンプトです。 → Tests クラス テストをスケジューリングするクラスです。 → TestScript クラス テストスクリプトを呼び出すクラスです。 → その他の関数 サンプル Dim ts : Set ts = new Tests ts.AddTestScriptAuto ".", "Test.vbs" ts.DoAllTest 参考 → テストツールの接続場所 テスト → TestsClass フォルダ *********************************************************************** <<< 設定ファイル TestPrompt_Setting.vbs >>> *********************************************************************** 設定ファイル TestPrompt_Setting.vbs テスト・プロンプトに関する設定を記述したファイルです。 通常、編集しなくてもそのまま使えます。 Setting_buildTestPrompt 関数 に設定を記述してください。 テスト・プロンプトのメニュー項目を記述します。 prompt.m_Menu(1).m_Caption = "1. Do ALL Test" prompt.m_Menu(1).m_OpType = prompt.Op_AllTest テストシンボルと、ユニット・テスト・プロンプトの VBS ファイルのあるパスの 対応関係を記述します。 tests.AddTestScriptAuto tests.BaseFolderPath, "Test.vbs" または fo = "test\" Set t= tests.AddTestScript( "T_Fold1", fo+"T_Fold1.vbs" ) サンプル → TestPrompt_Setting_default.vbs # Setting_buildTestPrompt *********************************************************************** <<< RunTestPrompt >>> *********************************************************************** RunTestPrompt (src) Sub RunTestPrompt( Opt ) テスト・プロンプトを開きます。 【引数】 Opt Empty または、Test.vbs のパス、または Writables オブジェクト サンプル Sub main2( Opt, AppKey ) RunTestPrompt AppKey.NewWritable( "." ) End Sub テスト・プロンプトで選択したメニュー項目によって、 Test.vbs に記述する関数 (Test_build など) を呼び出します。 Opt に Writables オブジェクトを指定すると、その設定を使い、、サブフォルダに ある Test.vbs もテストします。 Opt に Empty を指定すると、サブフォルダにある Test.vbs もテストします。 Opt に Test.vbs のパスを指定すると、そのテストだけをテストします。 Opt に Test.vbs のパスを指定しなかったときのログのファイル名は、Test_logs.txt、 指定したときのログのファイル名は、Test_log.txt になります。 Opt に RunTestPromptConfigClass のオブジェクトを指定できます。 コールツリー main2 RunTestPrompt TestPrompt::DoPrompt TestPrompt::DoTest 関連 → GetTemporaryTestsObject *********************************************************************** <<< RunTestPromptConfigClass >>> *********************************************************************** RunTestPromptConfigClass RunTestPrompt の設定。 RunTestPrompt に指定します。 Writables .Writable → NewWritable (AppKeyClass) integer .ExpectedPassConut → ExpectedPassConut (TestScript) string .TestTargetVBS_Path テスト対象の Test.vbs のパス ソース → TestPrompt.vbs *********************************************************************** <<< TestPrompt クラス >>> *********************************************************************** TestPrompt クラス (src) Tests クラス をユーザから使うためのコマンドプロンプトです。 .DoPrompt (src) *********************************************************************** <<< Tests クラス >>> *********************************************************************** Tests クラス (src) テストをスケジューリングするクラスです。 Test.vbs に記述するコールバック関数 の引数です。 .AddTestScriptAuto フォルダに含まれるすべての Test.vbs をロードします。 .BaseFolderPath as string テストツリーのベース(ルート)フォルダのパス .LoadTestSet 実施を行うテスト・シンボルを読み込む テスト → [T_LoadTestSet] → T_TestSet フォルダ .CurrentSymbol as string 現在設定されているテストシンボル、 "T_ALL"など .Symbol as string 現在実行しているテストのテストシンボル .CurrentTest as UnitTest 現在実行しているテストの情報、 Delegate はココ .CurrentTestPriority テストの優先度 AutoDiff モード を有効にするかどうか .m_bAutoDiff *********************************************************************** <<< AddTestScriptAuto (Tests) >>> *********************************************************************** AddTestScriptAuto (Tests) (src) Function Tests::AddTestScriptAuto( BasePath, FName ) フォルダに含まれるすべてのテスト項目スクリプト(Test.vbs)が呼び出せるようにします。 【引数】 BasePath 検索するフォルダ FName テスト項目スクリプトのファイル名(通常 Test.vbs) 返り値 なし テスト → ○ [T_AddAuto] テスト項目の自動追加 *********************************************************************** <<< AddTestScript (Tests) >>> *********************************************************************** AddTestScript (Tests) (src) Function Tests::AddTestScript( Symbol, FileName ) テスト項目スクリプト(Test.vbs)が呼び出せるようにします。 【引数】 Symbol テストシンボル FileName テスト項目スクリプトのファイル名(通常 Test.vbs) 返り値 なし *********************************************************************** <<< CurrentTestPriority (Tests) >>> *********************************************************************** CurrentTestPriority (Tests) (src) Dim Tests::CurrentTestPriority as integer 呼び出し順序を決めるための、現在のテストの優先度 デフォルトは 1000 です。 サンプル Sub Test_current( tests ) tests.CurrentTestPriority = 850 End Sub 値の例: ・ソースをビルドする = 700番台 ・テスト・ライブラリをビルドする = 800番台 ・テスト・プログラムをビルド&実行する = 900番台 ・サンプル・プログラムをビルド&実行する = 1000番台 参考 → Test_current → サブフォルダの関数の呼び出し順序 *********************************************************************** <<< Symbol (Tests) >>> *********************************************************************** Symbol (Tests) Dim Tests::Symbol as string 現在のテストの識別子(テスト・シンボル) デフォルトは、Test.vbs があるフォルダーの名前です。 参考 → Test_current *********************************************************************** <<< SetCurrentSymbol (Tests) >>> *********************************************************************** SetCurrentSymbol (Tests) Function Tests::SetCurrentSymbol( Symbol as string ) as integer 現在のテストの識別子(テスト・シンボル)を選択します。 全てのテストを選択するときは、"ALL" を指定してください。 返り値は、0=成功、1=失敗 *********************************************************************** <<< GetCallingOrder (Tests) >>> *********************************************************************** GetCallingOrder (Tests) (src) Sub Tests::GetCallingOrder( out_UnitTests as UnitTest ) サブフォルダの関数の呼び出し順序 を取得します。 *********************************************************************** <<< DoAllTest (Tests) >>> *********************************************************************** DoAllTest (Tests) Sub Tests::DoAllTest() すべてのテストを実施します。 参考 → 2. Do ALL Test コールツリー TestPrompt::DoPrompt Tests::DoAllTest (src) ShakerSort_fromDic テストする順番を整列する TestScript::Start TestScript::m_nPass = 0 テストの集計をリセットする For Each CurrentTest '// as UnitTest テストのループ Tests::OnTestFunctionSetup m_Symbol = Me.CurrentTest.Symbol TestScript::Do_ (src) ( CurrentTest.ScriptPath, "Test_current", Me as Tests ) TestScript::Do_ ( CurrentTest.ScriptPath, "Test_start", Me as Tests ) echo '//=== Echo the Test title call_vbs_t (src) g_fs.OpenTextFile ExecuteGlobal Test_start など テスト・スクリプトへコールバックする If en <> 0 Then Err.Raise en,, ed If en = E_TestPass Then TestScript::m_nPass = m_nPass + 1 テストの結果をまとめる Tests::OnTestFunctionFinish m_Symbol = Me.CurrentTest.Symbol TestScript::Finish 参考 → 処理フロー (テスト・プロンプト) 関連 → Tests::DoTest *********************************************************************** <<< DoTest (Tests) >>> *********************************************************************** DoTest (Tests) (src) Sub Tests::DoTest( Func as string, bReverse as Boolean ) 3. call each "Test_build" in sub folders など、テスト関数の1つを実行します。 【引数】 Func 呼び出す関数の名前 bReverse 複数の Test.vbs の関数を逆順に呼び出します。(*1) (*1) True にすると、Test_clean と同じ順序に呼び出します。 → サブフォルダの関数の呼び出し順序 サブフォルダーにあるテスト・スクリプトで定義されている、Func に指定した名前の 関数もコールバックされます。 関連 → Tests::DoAllTest *********************************************************************** <<< SetCur (Tests) >>> *********************************************************************** SetCur (Tests) (src) Sub Tests::SetCur( SubSymbol ) デバッグを行うサブテストシンボルを設定します。 Test_current の中から呼び出してください。 指定したサブテストシンボルのテスト項目だけ実施するようになります。 デバッグが済んだら、"" を設定してください。 → Tests::IsCur Sub Test_current( tests ) tests.SetCur "SubTestA" End Sub Sub Test_start( tests ) If tests.IsCur( "SubTestA" ) Then '// Do SubTestA End If If tests.IsCur( "SubTestB" ) Then '// Do SubTestB End If Pass End Sub テスト → T_SubTest\Test_target.vbs#SetCur *********************************************************************** <<< IsCur (Tests) >>> *********************************************************************** IsCur (Tests) (src) Function Tests::IsCur( SubSymbol ) 指定のサブテストシンボル、または "" が設定されているか判定します。 Test_start など(Test_current 以外)の中から呼び出します。 テスト → T_SubTest\Test_target.vbs#IsCur 関連 → Tests::SetCur *********************************************************************** <<< SaveTestResultHtml (Tests) >>> *********************************************************************** 未対応 SaveTestResultHtml (Tests) (src) Sub Tests::SaveTestResultHtml( SavePath as string ) テストの結果を HTML 形式で出力します。 【引数】 SavePath 出力ファイルパス。 Empty のとき "TestResult.html" ファイル: TestScript.vbs 出力サンプル: 書きかけ テスト → T_SomeTests.vbs # T_TestReport *********************************************************************** <<< SaveTestResultCSV (Tests) >>> *********************************************************************** SaveTestResultCSV (Tests) (src) Sub Tests::SaveTestResultCSV( SavePath as string ) テストの結果を CSV 形式で出力します。 【引数】 SavePath 出力ファイルパス。 Empty のとき "TestResult.csv" ファイル: TestScript.vbs 出力サンプル: Test symbol,result,step,path,priority T_SomeTests,Pass,,TestOfTest2.vbs,1000 T_SampA,Pass,,T_SampA\TestOfTest2.vbs,1000 T_SampB,Fail,Test_check,T_SampB\TestOfTest2.vbs,1000 T_SampC,Skip,Test_setup,T_SampC\TestOfTest2.vbs,1000 テスト → T_SomeTests.vbs # T_TestReport *********************************************************************** <<< LoadTestResultCSV (Tests) >>> *********************************************************************** LoadTestResultCSV (Tests) (src) Sub Tests::LoadTestResultCSV( LoadPath as string ) テストの結果を CSV 形式で出力します。 【引数】 LoadPath 出力ファイルパス。 Empty のとき "TestResult.csv" ファイル: TestScript.vbs *********************************************************************** <<< TestScript クラス、g_Test 変数 >>> *********************************************************************** TestScript クラス、g_Test 変数 (src) テストスクリプトを呼び出すクラスです。 グローバル変数 g_Test は、TestScript クラスのオブジェクトを参照しています。 → TestScript::Start テストを開始します。 ログ取りを開始します。 → TestScript::Do_ テスト関数を呼び出します。(同じプロセス) → TestScript::Finish テストを終了します。 ログ取りを終了して集計します。 → テスト・スクリプトのテスト *********************************************************************** <<< Start (TestScript) >>> *********************************************************************** Start (TestScript) (src) Sub TestScript::Start テストを開始します。 ログ取りを開始します。 カレントテストのスクリプトがあるフォルダに、TestScript_log.txt ができます。 *********************************************************************** <<< Do_ (TestScript) >>> *********************************************************************** Do_ (TestScript) (src) Sub TestScript::Do_( vbs_path as string, func as string, param as variant ) テスト関数を呼び出します。(同じプロセス) 【引数】 vbs_path テスト・スクリプトが書かれた VBScript ファイルのパス func 呼び出す関数の名前(文字列) param 関数に渡すパラメータ Do の後に、アンダーラインがあるので注意してください。(無いとエラーになるため) *********************************************************************** <<< Finish (TestScript) >>> *********************************************************************** Finish (TestScript) (src) Sub TestScript::Finish テストを終了します。 ログ取りを終了して集計します。 TestScript クラスのデストラクタによってテストが終了しますが、 明示的にこの Finish を呼び出して終了させることもできます。 *********************************************************************** <<< ExpectedPassConut (TestScript) >>> *********************************************************************** ExpectedPassConut (TestScript) Dim TestScript::ExpectedPassConut as integer 予想される Pass の数。 サンプル 一致した時の表示例 ========================================================== Test Finish (Pass=155, Manual=6, Skip=0, Fail=0) ExpectedPassConut = 155 [OK] 一致しなかったら、[FAIL] と表示されます。 ExpectedPassConut が設定されていないときは、ExpectedPassConut の行を表示しません。 ソース → TestScript.vbs テスト → T_Prpt フォルダー 関連 → RunTestPromptConfigClass ::ExpectedPassConut Test.vbs を使うとき *********************************************************************** <<< UnitTest クラス >>> *********************************************************************** UnitTest クラス (src) Class UnitTest Public Symbol ' as string Public ScriptPath ' as string Public Priority ' as integer Public Delegate ' as variant End Class Delegate *********************************************************************** <<< その他の関数 >>> *********************************************************************** その他の関数 *********************************************************************** <<< GetTemporaryTestsObject >>> *********************************************************************** GetTemporaryTestsObject Function GetTemporaryTestsObject() as Tests 一時的な Tests オブジェクトを生成し、Test_current を呼び出します。 【引数】 返り値 テスト・オブジェクト ファイル: TestScript.vbs 主に、Test_current で取得できるデータを、RunTestPrompt を呼び出す前に参照するときに使います。 GetTemporaryTestsObject().CurrentTest は、同じファイルの中にある Test_current 関数などの引数 に渡るオブジェクトを指しています。 サンプル Sub Main( Opt, AppKey ) Dim g : Set g = GetTemporaryTestsObject().CurrentTest.Delegate RunTestPrompt AppKey.NewWritable( Array( ".", g("PublicFolder") ) ) End Sub Sub Test_current( tests ) If IsEmpty( tests.CurrentTest.Delegate ) Then Dim g : Set g = CreateObject( "Scripting.Dictionary" ) : Set tests.CurrentTest.Delegate = g '[Setting] '============================================================================== g("PublicFolder") = "..\Public\FromPackage" '============================================================================== End If End Sub テスト → T_TempTests フォルダ *********************************************************************** <<< CheckTestErrLevel >>> *********************************************************************** CheckTestErrLevel (src) Sub CheckTestErrLevel( errorlevel as integer ) VBS プログラムの終了コード(エラーレベル)に問題があったらエラーを発生させる。 【引数】 errorlevel エラーレベル(WScript.Quit の引数) 内部で、Pass, Fail, Skip のいずれかを呼び出します。 VBS プログラムは、wscript ではなく cscript で呼び出さないと、正しいエラーレベル を取得できません。 RunProg から VBScript のスクリプトを呼び出して、子プロセスでエラーが発生すると、 親プロセスの RunProg の中からエラーが発生してしまうため、終了コードを取得できません。 Run (Shell) を使ってください。 サンプル r = g_sh.Run( "cscript sample.vbs",, True ) CheckTestErrLevel r 参考 → エラー発生時の動作 → 正常終了時の動作 関連 → RunProg *********************************************************************** <<< g_IsAutoTest >>> *********************************************************************** g_IsAutoTest Dim g_IsAutoTest as boolean 自動テストを実行中かどうか。 g_IsAutoTest = True にすると、 Pause しなくなることがあります。 *********************************************************************** <<< テスト支援機能 (関数) >>> *********************************************************************** テスト支援機能 (関数) テスト対象となるスクリプトが使うもの *********************************************************************** <<< ReadTestCase >>> *********************************************************************** ReadTestCase (src) Function ReadTestCase( XmlPath as string, TestCaseID as string ) as ArrayClass of Dictionary ArrayClass Dictionary Function ReadTestCase( XmlPath as string, Empty ) as Dictionary Dictionary → 複数ケースで共通のデータ テストケースが書かれた XML ファイルのデータにアクセスするオブジェクトを返します。 【引数】 XmlPath テストケースが書かれた XML ファイルのパス TestCaseID XML ファイルの中の タグの id 属性の値、または Empty 返り値 テストケースのデータの辞書、または、その配列 ファイル: TestScript.vbs サンプル・コード: Sub T_Test1( Opt, AppKey ) Dim x Dim cases : Set cases = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1" ) For Each x In cases.Items T_Test1_main Opt, AppKey, x '// Test.vbs の中では、パラメーターは ( tests, x ) Next Pass End Sub '// ループが増えてもインデントを深くさせなくて済むように、テストの実施は *_main 関数にする Sub T_Test1_main( Opt, AppKey, x ) Dim w_:Set w_=AppKey.NewWritable( "out" ).Enable() EchoTestStart "T_Test1" echo x '// 全てのデータを表示する FuncA CInt( x("InputData") ) FuncB Replace( x("Answer"), "%Num%", CStr( 12 ) ) End Sub T_Test1 ReadTestCase T_Test1_Data.xml TestCase_for_T_Test1 T_Test1 T_Test1 InputData Answer 属性値の扱い方 返り値は、辞書型を要素に持つ配列(ArrayClass)です。 辞書のキーは、XML 属性の名前です。 データの具体的な値は、下記のサンプル XML ファイルを参照してください。 ・得られるデータはすべて文字列型です。 ・数値を使うときは、CInt 関数などを使います。 ・辞書のキーに指定した名前に対応する XML 属性が存在しないときは、Empty を返します。 ・複数のデータをコンマで区切って記述したときは、 ・動的に変化するデータを XML ファイルに記述するときは、%Num% のように変数を記述します。  ただし、テスト・スクリプトで Replace 関数や ・#name (HTML の href 属性)のリンク先を得るには、 ArrayFromCSV などを使います。 DicItemOfItem などを使って値を設定してください。 GetHRefBase を使ってください。 テストケースが書かれた XML ファイルの書式 テストケースのデータの多くは構造体の配列であるため、XML ファイルの書式は、それを想定 して、ある程度決めています。 この標準化により、XML ファイルを見たときにテストケースが 把握しやすくなりますし、テスト・スクリプトのコードも DOM より簡単になります。 書式の詳細は、 下記の DTD を参照してください。 もし、複雑なデータを記述したいときは、一般的な XML ファイルをアクセスする DOM を使って ください。 参考 → LoadXML サンプル XML ファイル: T_Test1_Data.xml TestCases TestCase TestCase_for_T_Test1 #common SubCase InputData Answer SubCase TestCase TestCase TestCase_for_T_Test1_sub SubCase SubCase TestCase TestCases TestCases、TestCase、SubCase のタグ名を変えることはできません。 XML タグの中(例:SubCase タグの中) に 形式のコメントは入れたいときは、 XMLの仕様上できないので、ダミーとなる _comment1 などの属性を使って、コメントを 記述します。 テスト → T_TestCaseData.vbs # T_TestCaseData 関連 → 複数のケースで共通のデータ → 特殊な XML 属性 (ReadTestCase) → クロス・ケース → テスト・ケースの選択 → スクリプトからテストケースを指定する → SetReadTestCase デバッグ用に、テストケースを指定します → GetMainSetting 関数 (vbsool) スクリプト・ファイル内のデータ → DicTable 辞書を使ったテストデータ → TestNums (clib) C言語のテスト番号 *********************************************************************** <<< 複数のケースで共通のデータ >>> *********************************************************************** 複数のケースで共通のデータ [ 親: ReadTestCase ] 複数のテストケースで共通のデータは、 特殊な XML 属性 を指定するか、 TestCase タグの属性に記述できます。 サンプル XML ファイル: T_Test1_Data.xml ExeName common CommonData1 #common 上のファイルと下のファイルは、同じテスト・データになります。 CommonData1 ExeName CommonData1 ExeName タグの内容をリードするときは、下記のようにします。 Dim test_common_data : Set test_common_data = ReadTestCase( SearchParent(_ "TestCommon_Data.xml" ), Empty ) '// test_common_data as start test_common_data( "ExeName" ) *********************************************************************** <<< (旧版) 複数のケースで共通のデータ >>> *********************************************************************** (旧版) 複数のケースで共通のデータ [ 親: ReadTestCase ] 複数のテストケースで共通のデータを、XML ファイルの TestCases タグの属性からリードするときは、 ReadTestCase の第2引数を Empty に指定してください。 Sub T_Test1( Opt, AppKey ) Dim x Dim xx : Set xx = ReadTestCase( "T_Test1_Data.xml", Empty ) '// xx as Dim cases : Set cases = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1" ) For Each x In cases.Items Dic_add x, xx T_Test1_main Opt, AppKey, x Next Pass End Sub '// ループが増えてもインデントを深くさせないため、テストの実施は *_main 関数にする Sub T_Test1_main( Opt, AppKey, x ) echo x FuncA CInt( x("InputData") ) FuncB x("CommonData1") End Sub T_Test1 T_Test1_Data.xml Empty T_Test1 T_Test1 CommonData1 サンプル XML ファイル: T_Test1_Data.xml TestCases CommonData1 複数のテスト・プログラムで共通のデータは、親フォルダーにある共通の XML ファイルからリードして ください。 Set xx = ReadTestCase( SearchParent("TestCommon_Data.xml"), Empty ) '// xx as SearchParent *********************************************************************** <<< 特殊な XML 属性 (ReadTestCase) >>> *********************************************************************** 特殊な XML 属性 (ReadTestCase) [ 親: ReadTestCase ] ReadTestCase がリードする XML ファイルは、データの記述が冗長にならないように、データの継承や集約 ができる特殊な XML が使えます。 → base_data 属性 XML 属性を継承します → plus_attr 属性 継承した XML 属性は CSV 形式で追加します → aggregate 属性 子の XML 要素を集約します テストデータを記述する XML ファイルの DTD *********************************************************************** <<< base_data 属性 >>> *********************************************************************** base_data 属性 [ 親: ReadTestCase ] データの多くは共通で、一部のデータだけ変えるときは、base_data 属性を使って属性を継承することが できます。 base_data 属性は、A タグの href 属性と同じ記述形式です。 別のファイルから継承する こともできます。 ファイルパスに、ピリオドを3つ並べると、親フォルダー、親の親フォルダー … と探していきます。 参考 → パスにピリオドを3つ並べた場合 サンプル XML ファイル: T_Test1_Data.xml T_Test1_Common T_Test1_Common T_Test1_Common 上のファイルと下のファイルは、同じデータになります。 Answer="ans1.txt" Answer="ans1.txt" テスト → T_TestCaseData.vbs # [T_BaseTestCaseData] → T_TestCaseData.xml # T_BaseTestCaseData_1 など *********************************************************************** <<< plus_attr 属性 >>> *********************************************************************** plus_attr 属性 [ 親: ReadTestCase ] CSV 形式のデータを、別のタグから追加するときは、plus_attr 属性を使います。 plus_attr 属性の値は、属性の値を CSV 形式で並べます。 サンプル XML ファイル: T_Test1_Data.xml InputDataA InputDataA 上のファイルと下のファイルは、同じデータになります。 InputDataA テスト → T_TestCaseData.vbs # [T_BaseTestCaseData] → T_TestCaseData2.xml # T_BaseTestCaseData_22 など *********************************************************************** <<< aggregate 属性 >>> *********************************************************************** aggregate 属性 [ 親: ReadTestCase ] TestCase タグの子の SubCase タグに、別の TestCase タグの子を追加するときは、 aggregate 属性を使います。 サンプル XML ファイル: T_Test1_Data.xml TestCase_Common TestCase_Common TestCase_Common SubCase 上のファイルと下のファイルは、同じデータになります。 SubCase SubCase テスト → T_TestCaseData.vbs # [T_BaseTestCaseData] → T_TestCaseData.xml # T_AggregateTestCaseData_1 など *********************************************************************** <<< クロス・ケース >>> *********************************************************************** クロス・ケース [ 親: ReadTestCase ] テストケースの値が、表の縦軸と横軸にあり、表の全てをテストする場合は、下記のように二重ループに して、Dic_add を使ってテストデータを結合します。 Sub T_Test1( Opt, AppKey ) Dim x, y, mix Dim cases_x : Set cases_x = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1_x" ) Dim cases_y : Set cases_y = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1_y" ) Set mix = CreateObject( "Scripting.Dictionary" ) For Each y In cases_y.Items For Each x In cases_x.Items mix.RemoveAll : Dic_add mix, x : Dic_add mix, y T_Test1_main Opt, AppKey, mix Next Next Pass End Sub '// ループが増えてもインデントを深くさせないため、テストの実施は *_main 関数にする Sub T_Test1_main( Opt, AppKey, x ) echo x FuncA x("InputData"), ReadFile( x("CurrentFolder") +"\file.txt" ) End Sub T_Test1 T_Test1 T_Test1 InputData CurrentFolder サンプル XML ファイル: T_Test1_Data.xml XML ファイルを使わない、クロス・ケースのサンプル Sub T_Test1( Opt, AppKey ) Set t = CreateObject( "Scripting.Dictionary" ) For Each endian In Array( "LittleEndian", "BigEndian" ) For Each language In Array( "VBScript", "C" ) t("Endian") = endian t("Language") = language T_Test1_Main t Next Next Pass End Sub '// ループが増えてもインデントを深くさせないため、テストの実施は *_Main 関数にする Sub T_Test1_Main( Opt, AppKey, x ) echo x FuncA x("Endian"), x("Language") End Sub *********************************************************************** <<< テスト・ケースの選択 >>> *********************************************************************** テスト・ケースの選択 [ 親: ReadTestCase ] SubCase タグの中から、特定のタグだけ選択するときは、ArrayClass の LookUpDic を使ってください。 Sub T_Test1( Opt, AppKey ) Dim x Dim cases : Set cases = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1" ) Set x = cases.LookUpDic( "name", "Alphabet" ) T_Test1_main Opt, AppKey, x Pass End Sub "name", "Alphabet" サンプル XML ファイル: T_Test1_Data.xml *********************************************************************** <<< スクリプトからテストケースを指定する >>> *********************************************************************** スクリプトからテストケースを指定する [ 親: ReadTestCase ] テストケースの値を XML ファイルではなく、スクリプトに埋め込む場合は、下記のように代入します。 Sub T_Test1( Opt, AppKey ) Dim x, y Dim cases : Set cases_x = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1" ) For Each x In cases_x.Items For Each y In Array( 2, 3 ) x("y") = y T_Test1_main Opt, AppKey, x x.Remove "y" Next Next Pass End Sub '// ループが増えてもインデントを深くさせないため、テストの実施は *_main 関数にする Sub T_Test1_main( Opt, AppKey, x ) echo x FuncA x("InputData"), ReadFile( x("y") +"\file.txt" ) End Sub T_Test1 ( 2, 3 ) x("y") = y T_Test1 x.Remove "y" T_Test1 x("y") *********************************************************************** <<< TempParams.txt - C言語のプログラムにデータを渡す >>> *********************************************************************** TempParams.txt - C言語のプログラムにデータを渡す C言語の標準ライブラリだけを使うときは、fgets を使った1行ずつ読み込むような単純なファイル・リード しかできませんが、VBScript で XML などのデータを整理することで、C言語のプログラムに複雑な 動きをさせることができるようになります。 T_Test1.xml Test.vbs TempParams.txt C言語のプログラム vbs スクリプトのサンプル (Test.vbs) Sub T_Test1_main( tests, x ) // x is from ReadTestCase Dim f : Set f = OpenForWrite( "TempParams.txt", Empty ) f.WriteLine x("Param1") & " // Param1" f = Empty r= RunProg( "CLangProg.exe /TempParams:TempParams.txt", "" ) del "TempParams.txt" ReadTestCase C言語のテスト・プログラムのサンプル (CLangProg.exe) int Params_read( Params* m, FILE* f ); int T_Sample() { int e; errno_t et; FILE* f = NULL; TCHAR s[256]; TCHAR path[256]; //=== ReadTestCase e= GetCommandLineNamed( _T("TempParams"), false, s, sizeof(s) ); IF(e)goto fin; e= StrT_getFullPath( path, sizeof(path), s, NULL ); et= _tfopen_s( &f, path, _T("rt") ); IF(et)goto err_no; e= Params_read( ¶ms, f ); IF(e)goto fin; //=== Test Main // Write here ... e=0; fin: if(f!=NULL){ee= fclose( f ); IF(ee&&!e)e=E_Errno;} } int Params_read( Params* m, FILE* f ) { int e; int i; TCHAR line[256]; line[0] = '\0'; _fgetts( line, _countof(line), f ); e= StrT_cutLineComment( line, sizeof(line), line, _T("//") ); IF(e)goto fin; m->BufferSize = _ttoi( line ); _fgetts( line, _countof(line), f ); // skip space line e=0; fin: return e; } StrT_cutLineComment TempParams.txt ファイルの基本形 多くの場合、テスト・データを単純に並べていくだけで、テストを実施することはできるでしょう。 テスト・ケースが複数あるときは、空行で区切るとよいでしょう。 clib の StrT_cutLineComment 関数を使えば、コメントを入れることができます。 下記は、struct { int a; int b; } TestData[2]; という構造になります。 TempParams.txt 100 // 1つ目のテスト・ケースの1つ目のデータ 200 // 1つ目のテスト・ケースの2つ目のデータ 110 // 2つ目のテスト・ケースの1つ目のデータ 210 // 2つ目のテスト・ケースの2つ目のデータ TempParams.txt ファイルの フラグド構造体パラメーター 1つのテスト・ケースにおいて、それぞれのデータを使うかどうかを表すには、1つ目のデータを ビットフィールドの数値として使い、ビットが1であれば対応するデータが記述されているように します。 TempParams.txt 0x07 // ビットフィールド。 ビット0、1、2が1 100 // 1つ目のデータ 200 // 2つ目のデータ 300 // 3つ目のデータ 0x02 // ビットフィールド。 ビット1のみが1 200 // 2つ目のデータ 参考 → フラグド構造体パラメーター TempParams.txt ファイルの データ型の名前 テスト・データが複数のデータ構造を持つときは、データ構造を識別するシンボルを TempParams.txt ファイルに記述する必要があります。 TempParams.txt DataTypeA // データ型の名前 100 // DataTypeA の1つ目のデータ 200 // DataTypeA の2つ目のデータ DataTypeB // データ型の名前 100 // DataTypeB の1つ目のデータ 200 // DataTypeB の2つ目のデータ 300 // DataTypeB の3つ目のデータ *********************************************************************** <<< ReadTestCase 内部のデバッグ >>> *********************************************************************** ReadTestCase 内部のデバッグ 下記のように IsVerbose を True にすると、XML をリードする処理のステップを表示します。 If IsEmpty( g_ReadTestCase ) Then Set g_ReadTestCase = new XmlObjReader g_ReadTestCase.IsVerbose = True Skipped *********************************************************************** <<< SetReadTestCase >>> *********************************************************************** SetReadTestCase (src) Sub SetReadTestCase( XmlPath as string, TestCaseID as string, Condition as string ) デバッグ用に、テストケースを指定します。 【引数】 XmlPath テストケースが書かれた XML ファイルのパス TestCaseID XML ファイルの中の タグの id 属性の値 Condition テストケースを指定する条件文 ファイル: TestScript.vbs ReadTestCase を呼び出す前に、SetReadTestCase を呼び出すコードを追加すると、 ReadTestCase の返り値が、SetReadTestCase で指定した1つのケースだけになります。 サンプル・コード: Sub T_Test1( Opt, AppKey ) Dim testcases, x SetReadTestCase "T_Test1_Data.xml", "TestCase_for_T_Test1", "name='Alphabet'" : Skipped Set x = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1" ) For Each x In testcases.Items '// x は、InputData="ABC" の1回ループのみになる T_Test1_main Opt, AppKey, x Next Pass End Sub SetReadTestCase Skipped サンプル XML ファイル: T_Test1_Data.xml テスト → T_TestCaseData.vbs # [T_SetReadTestCase] *********************************************************************** <<< SetStartSectionTree >>> *********************************************************************** [ 親: SectionTree クラス ] SetStartSectionTree (src) Sub SetStartSectionTree( SectionNames as string ) 実行するセクションを設定します。 【引数】 SectionNames セクション名。 CSV形式 ファイル: vbslib.vbs サンプル Sec1 セクションから実行します。 SetStartSectionTree "Sec1" サンプル Sec1 セクションの中の SubSec2 セクションから実行します。 SetStartSectionTree "Sec1, SubSec2" テスト → T_SectionTree.vbs # [T_SectionTree_SetStart] → T_SectionTree.vbs # [T_SectionTree_SetStart2] → T_SectionTree.vbs # [T_SectionTree_SetStart3] → T_SectionTree.vbs # [T_SectionTree_SetStartMiss] 関連 → SectionTree クラス *********************************************************************** <<< Pass >>> *********************************************************************** Pass (src) Sub Pass テストがパスしたことを、テストスクリプトに知らせて、プログラムを終了します。 内部的には、エラー 21 が発生します。 参考 → 正常終了時の動作 テスト → T_SomeTests.vbs # T_TestReport の T_SampA *********************************************************************** <<< Fail >>> *********************************************************************** Fail (src) Sub Fail テストが失敗したことを、ユーザーやテストスクリプトに知らせて、プログラムを終了します。 エラーが発生したときと同じ動きをします。つまり、Fail の後は実行しません。 テスト → T_SomeTests.vbs # T_TestReport の T_SampB *********************************************************************** <<< Skip >>> *********************************************************************** Skip (src) Sub Skip() テストが実行できる状況ではないことを、テストスクリプトに知らせて、プログラムを終了します。 エラーが発生したときと同じ動きをします。つまり、Skip の後は実行しないで、次のテストを実行します。 テスト → T_SomeTests.vbs # T_TestReport の T_SampC *********************************************************************** <<< Skipped >>> *********************************************************************** Skipped (src) Sub Skipped デバッグなどの理由で、テストの一部を一時的にスキップしたことを、テストスクリプトに 知らせます。 Skipped を呼んだテスト項目は、Pass を呼び出しても Fail します。 このときのエラーメッセージは、次のようになります。 Pass But Skipped. Cut calling "Skipped" function. テスト → [T_Skip] テストをスキップする *********************************************************************** <<< ManualTest >>> *********************************************************************** ManualTest (src) Sub ManualTest( TestSymbol as string ) テストが手動テストであることを、テストスクリプトに知らせます。 手動テストは最低限にしてください。 サンプル ManualTest "T_Sample1" ManualTest tests.Symbol 参考 → Tests クラス 参考 → テストプログラム作成のヒント *********************************************************************** <<< Assert >>> *********************************************************************** Assert (src) Sub Assert( Condition as boolean ) 条件が満たされているかをチェックします。 満たされていなければ、Fail を呼び出します。 If not Condition Then Fail とほぼ同じですが(違いは下記)、正しい条件文を記述する ことになるので、ソースの可読性があがります。 また、If 文を使わないので、マルチステートメント(1行に複数の文)が記述できます。 g_debug の設定にかかわらず常にチェックします。 If Condition と If not Condition は、完全に反対の関係ではありません。 たとえば、If 4 と If not 4 は、どちらも真です。 完全に反対の関係は次のように複数行になります。 If Condition Then Else *** End If よって、正しい条件文を記述することは If Then Fail より Assert の方が簡単になります。 サンプル Public Property Let VarA(x) : Assert x >= 0 : VarA = x : End Property x >= 0 トラブルシューティング 左辺全体を括弧で囲むと、エラーになります。 Assert ( a + 2 ) = 0 '// エラー: 型が一致しません。: 'Assert' 上記は、( a + 2 ) = 0 の評価を行ってから Assert を呼び出すのではなく、 a + 2 を配列番号とした Assert 配列に 0 を代入するように解釈されます。 以下のように括弧を削除するか、括弧を追加してください。 Assert a + 2 = 0 Assert ( ( a + 2 ) = 0 ) 関連 → Fail テストが失敗したことを、ユーザーやテストスクリプトに知らせます。 → Raise 新規にエラーを発生させます。 *********************************************************************** <<< AssertExist >>> *********************************************************************** AssertExist Sub AssertExist( in_Path as string ) ファイルまたはフォルダが存在するかどうかをチェックします。 存在しなければ、エラーメッセージの中にパスが含まれます。 このため、デバッガを起動しなくてもユーザーが対応できる可能性が高まります。 エラーコードは、E_PathNotFound になります。 逆に、AssertExist では、存在するときにエラーにすることはできません。 大文字小文字が異なると、echo_v 関数で警告を表示しますが、継続します。 サンプル: AssertExist "settings.txt" "settings.txt" エラーメッセージのサンプル: 参考 → TestCommon_setVariables Test.vbs で共通のファイルの存在チェック ソース → vbslib.vbs → vbslib_mini.vbs テスト → T_File.vbs T_AssertExist → T_FileMutex_Manually.vbs T_AssertExist_UNC 関連 → exist → Assert2Exist → 大文字小文字に統一することの副作用 *********************************************************************** <<< Assert2Exist >>> *********************************************************************** Assert2Exist Sub Assert2Exist( in_PathA as string, in_PathB as string ) ファイルまたはフォルダが2つとも存在するかどうかをチェックします。 1つでも存在しなければ、エラーメッセージの中に2つのパスが含まれます。 2つを比較するときに使うとよいでしょう。 このため、デバッガを起動しなくてもユーザーが対応できる可能性が高まります。 エラーコードは、E_PathNotFound になります。 大文字小文字が異なると、echo_v 関数で警告を表示しますが、継続します。 サンプル: Assert2Exist "FileA.txt", "FileB.txt" "FileA.txt", "FileB.txt" エラーメッセージのサンプル: ソース → vbslib.vbs テスト → T_File.vbs T_Assert2Exist 関連 → AssertExist *********************************************************************** <<< AssertFullPath >>> *********************************************************************** AssertFullPath Sub AssertFullPath( in_Path as string, in_NameOfPath as string ) 指定したパスがフル パスでなければ、エラーにします。 【引数】 in_Path 調べるパス in_NameOfPath in_Path に指定したパスを設定する場所(表示用) フル パスでなければ、次のエラーメッセージを表示します。 " XML ファイルに タグ が指定できるなら、 type="FullPathType" や OS の環境変数を指定する ことで、${ } 変数にフル パスを設定することができます。 たとえば、XML ファイルの一部を次のように記述します。 ... file 属性はフル パス ${Base}\File.txt 変数 ${Base} の値は、XML ファイルがあるフォルダーの親フォルダーのフル パスです。 ソース → vbslib.vbs *********************************************************************** <<< AssertFC >>> *********************************************************************** AssertFC Sub AssertFC( Path1 as string, Path2 as string ) 2つのテキストファイルを比較して、異なれば diff ツールを開きます。 テキストファイルの文字コードが自動判定できるなら、文字コードが異なっても テキストが同じであれば、同じと判定します。 文字コードが異なれば必ず異なると判定するときは、 IsSameBinaryFile を使ってください。 テキスト ファイルの内容の大文字と小文字を区別しません。 Path2 のファイルの内容に、% を使った文字列変換関数を使うことができます。 % 文字を使うとき(文字列変換関数からエスケープするとき)は、%% と記述します。 参考 → % を使った文字列変換関数 異なっていたら、E_TestFail エラーになります。 サンプル 標準出力への出力内容をチェックするテスト Sub T_Sample( Opt, AppKey ) Set w_= AppKey.NewWritable( Array( "_out.txt" ) ).Enable() RunProg "cscript //nologo "+ WScript.ScriptName +" T_Sample_Sub", "_out.txt" AssertFC "_out.txt", "T_Sample_ans.txt" del "_out.txt" Pass End Sub Sub T_Sample_Sub( Opt, AppKey ) '// 標準出力へ出力する処理 End Sub AssertFC 下記のコードを書いた後は、diff ツールが開かなくなります。 下記のコードがあってもなくても、例外は発生します。 g_Vers("AssertFC_Diff") = False 比較の詳細を調べたいときは、IsSameTextFile 関数 (vbslib.vbs) の中で is_debugging を検索して見つかるソース コードを参照してください。 ソース → TestScript.vbs AssertFC → vbslib.vbs IsSameTextFile テスト → T_fc_Manually.vbs T_AssertFC → AssertFC フォルダー → IsSameTextFile のテスト c.RightHasPercentFunction or c.ErrorIfNotSame のケース 関連 → ログ *********************************************************************** <<< AssertValue >>> *********************************************************************** AssertValue Sub AssertValue( Name as string, TestValue as variant, PassValue as variant, CompareOption as interger ) 値が範囲内であるかどうかをチェックし、範囲外なら詳細なメッセージを付けてエラーにします。 【引数】 Name 値の名前、エラーメッセージ用 TestValue チェック対象の値 PassValue 範囲 CompareOption 比較オプション サンプル AssertValue "EqualNumber", a, 1, Empty a = 1 であるかチェックします。 AssertValue "RangeNumber", a, Array( 1, 3 ), c.Range 1 ≦ a ≦ 3 であるかチェックします。 AssertValue "Str", a, Array( "A", "ABC" ), c.CaseSensitive a = "A" または a = "ABC" であるかチェックします。 ソース → vbslib.vbs テスト → T_Value.vbs # [T_AssertValue] *********************************************************************** <<< AssertString >>> *********************************************************************** AssertString Sub AssertString( TestString as string, AnswerString as string, Option_ as integer ) 文字列が等しいことをチェックし、異なっていたら文字列を比較する Diff ツールを開きます。 【引数】 TestString テストする文字列 AnswerString 答の文字列 Option_ Empty または c.CaseSensitive 文字列に含まれるすべての文字の文字コードも Diff ツールで比較します。 サンプル AssertString "ABC", "AxC" ソース → TestScript.vbs 関連 → GetDiffStringCmdLine, GetDiffStringCmdLine3 → new_BinaryArrayAsText *********************************************************************** <<< AssertD_TypeName >>> *********************************************************************** AssertD_TypeName Sub AssertD_TypeName( in_Value as variant, in_TypeName as string ) 値の型の名前をチェックします。 (デバッグ時のみ) 【引数】 in_Value チェックする値 in_TypeName 型やクラスの名前 型名をソースのコメントに書くときよりは信頼できるようになります。 g_is_debug が 0 のときは、何もしません。 高速化のため。 サンプル AssertD_TypeName self, "SampleClass" ソース → vbslib.vbs *********************************************************************** <<< ErrorValue >>> *********************************************************************** ErrorValue Sub ErrorValue( Name as string, Value as Variant ) 問題がある値をメッセージに含めたエラーを発生させます。 【引数】 Name 値の名前 Value 問題がある値 サンプル スクリプトの例 ErrorValue "Sample", 1 上記スクリプトを実行した時のエラーメッセージ ソース → vbslib.vbs *********************************************************************** <<< その他 >>> *********************************************************************** その他 → ConvertToFullPath テキストファイルの中の相対パスをフル・パスに変換します。 *********************************************************************** <<< 性能計測 >>> *********************************************************************** 性能計測 参考 → BenchStart *********************************************************************** <<< 開発環境操作 >>> *********************************************************************** 開発環境操作 Visual Studio 2005〜2010 を操作します。 → devenv_rebuild Visual Studio のソリューションをリビルドします → devenv_build Visual Studio のソリューションをビルドします → devenv_clean Visual Studio のソリューションをクリーンします → devenv_ver_name 環境変数 ファイル: VisualStudio.vbs テスト → T_devenv フォルダ 関連 → MSBuild → Module Mixer 3 *********************************************************************** <<< devenv_rebuild >>> *********************************************************************** devenv_rebuild (src) Sub devenv_rebuild( SlnPath as string, ConfigName as string ) Visual Studio のソリューションをリビルドします。 【引数】 SlnPath ソリューション・ファイルのパス(.sln) ConfigName 設定名("Release"など) ソリューション・ファイルに書かれたバージョン情報を元に、 コンパイラのバージョンを自動的に選択します。 ビルドに失敗したら、E_BuildFail エラーになります。 ソース → VisualStudio.vbs サンプル Dim ds_:Set ds_= new CurDirStack pushd "src" devenv_rebuild "sample.sln", "Release" popd devenv_rebuild "src\sample_%devenv_ver_name%.sln", "Debug" devenv_rebuild "sample.sln", "Release|x64" Release|x64 が使えるかどうかは、.sln ファイルをテキストファイル で開いて、そのコンフィグがあるかどうかで判断してください。 参考 → Devenv コマンド ライン スイッチ (Web) → コマンドライン・コンパイル → devenv_ver_name 環境変数 テスト → T_devenv.vbs # [T_devenv_build] → T_devenv.vbs # [T_devenv_build_MultiFolder] *********************************************************************** <<< devenv_build >>> *********************************************************************** devenv_build (src) Sub devenv_build( SlnPath as string, ConfigName as string ) Visual Studio のソリューションをビルドします。 参考 → devenv_rebuild *********************************************************************** <<< devenv_clean >>> *********************************************************************** devenv_clean (src) Sub devenv_clean( SlnPath as string ) Visual Studio のソリューションをクリーンします。 【引数】 SlnPath ソリューション・ファイルのパス(.sln) サンプル: Dim ds_:Set ds_= new CurDirStack pushd "src" devenv_clean "sample.sln" popd 参考 → devenv_ver_name 環境変数 テスト → T_devenv.vbs # [T_devenv_build_MultiFolder] *********************************************************************** <<< devenv_upgrade >>> *********************************************************************** devenv_upgrade (src) Sub devenv_upgrade( SlnPath as string, Opt as Empty ) Visual Studio のソリューション・ファイルを新しい Visual Studio 用に変換します。 【引数】 SlnPath 古い Visual Studio のソリューション・ファイルのパス(.sln) Opt Empty または、c.MakeBackup 新しいバージョンとは、現在の PC にインストールされている Visual Studio のうち、 最も新しいバージョンのことです。 Opt に、c.MakeBackup を指定すると、変換前のファイルのバックアップを作成します。 ただし、c は、get_VisualStudioConsts の返り値です。 サンプル: Dim ds_:Set ds_= new CurDirStack pushd "src" devenv_upgrade "sample.sln", Empty popd 参考 → devenv_ver_name 環境変数 → /Upgrade (devenv.exe) (Web) → To the command line enthusiasts Some quick know-hows for Upgrading to VS 2010 (Web) *********************************************************************** <<< get_VisualStudioConsts >>> *********************************************************************** get_VisualStudioConsts (src) Function get_VisualStudioConsts() as Object VisualStudio.vbs で使う定数の集合。 サンプル: Dim c : Set c = get_VisualStudioConsts() '// c.MakeBackup *********************************************************************** <<< devenv_ver_name 環境変数 >>> *********************************************************************** devenv_ver_name 環境変数 (src) devenv_rebuild, devenv_clean などに指定する .sln ファイルのパスには、 %devenv_ver_name% を指定することができます。 devenv_rebuild "src\sample_%devenv_ver_name%.sln", "Release" インストールされている Visual Studio に応じて、次の文字列に変換されます。 Visual Studio 2015 … "vs2015" Visual Studio 2013 … "vs2013" Visual Studio 2012 … "vs2012" Visual Studio 2010 … "vs2010" Visual Studio 2008 … "vs2008" Visual Studio 2005 … "vs2005" 複数の Visual Studio がインストールされているときは、デフォルトでは最新のものが設定されますが、 PC の環境変数や、SetVar で devenv_ver_name を設定することで、バージョンを選択できます。 GetVar や env で、devenv_ver_name 環境変数の値を取得するときは、その前に get_DevEnvObj を実行してください。 get_DevEnvObj get_DevEnvObj echo "Default: " + GetVar( "%devenv_ver_name%" ) devenv_ver_name テスト → [T_devenv] 関連 → devenv_ver_name 環境変数 *********************************************************************** <<< devenv_platform 環境変数 >>> *********************************************************************** devenv_platform 環境変数 devenv_platform 環境変数の値は、"" (Win32 or x86) または "x64\" です。 初期値は、"" です。 "" 以外のときは、末尾に \ を付けてください。 64bit アプリケーションをビルドするときは、"x64\" を設定してからビルドしてください。 サンプル set_ "devenv_platform", "x64\" devenv_build "Example.sln", "Release" Assert exist(env("sample sln\%devenv_platform%Release\Example.exe")) %devenv_platform% *********************************************************************** <<< IsVisualStudioInstalled >>> *********************************************************************** IsVisualStudioInstalled (src) Function IsVisualStudioInstalled( VersionNum as integer, IsExpress as boolean ) as boolean 指定したバージョンの Visual Studio がインストールされているかどうかを返します。 【引数】 VersionNum バージョン番号 IsExpress Express 版かどうか 返り値 インストールされているかどうか *********************************************************************** <<< GetVisualStudioVersionNum >>> *********************************************************************** GetVisualStudioVersionNum (src) Function GetVisualStudioVersionNum( VersionString as string ) as integer Visual Studio のバージョン文字列(例:"vs2008")を数値(例:2008)に変換します。 *********************************************************************** <<< GetSlnFileVersion >>> *********************************************************************** GetSlnFileVersion (src) Sub GetSlnFileVersion( SlnPath as string, out_VersionNum as integer, out_IsExpress as boolean ) 指定のソリューション・ファイルが使える Visual Studio のバージョンを返します。 【引数】 SlnPath Visual Studio のソリューション・ファイルのパス(.sln) out_VersionNum (出力) バージョン番号。 2012, 2010, 2008, 2005 out_IsExpress (出力) Express 版かどうか *********************************************************************** <<< VisualStudioSlnClass >>> *********************************************************************** VisualStudioSlnClass (src) Visual Studio の *.sln ファイルを読み込みます。 Load してから Projects や ConfigurationPlatforms にアクセスしてください。 テスト → T_devenv.vbs # [T_devenv_SlnLoad] *********************************************************************** <<< Load (VisualStudioSlnClass) >>> *********************************************************************** Load (VisualStudioSlnClass) (src) Sub VisualStudioSlnClass::Load( SlnFilePath as string ) Visual Studio の *.sln ファイルを読み込みます。 【引数】 SlnFilePath *.sln ファイルのパス *********************************************************************** <<< Projects (VisualStudioSlnClass) >>> *********************************************************************** Projects (VisualStudioSlnClass) Dim VisualStudioSlnClass::Projects as ArrayClass of VisualStudioSlnProjectClass VisualStudioSlnProjectClass ソリューションの中にあるプロジェクトの一覧。 Load してからアクセスしてください。 *********************************************************************** <<< VisualStudioSlnProjectClass >>> *********************************************************************** VisualStudioSlnProjectClass (src) Class VisualStudioSlnProjectClass Public ProjectName '// as string Public RelativePath '// as string Public ProjectGuid '// as string End Class 参考 → VisualStudioSlnClass *********************************************************************** <<< ConfigurationPlatforms (VisualStudioSlnClass) >>> *********************************************************************** ConfigurationPlatforms (VisualStudioSlnClass) Dim VisualStudioSlnClass::ConfigurationPlatforms as ArrayClass of VisualStudioSlnConfigurationPlatformClass VisualStudioSlnConfigurationPlatformClass ソリューションの中にあるコンフィギュレーションとプラットフォームの一覧。 Load してからアクセスしてください。 *********************************************************************** <<< VisualStudioSlnConfigurationPlatformClass >>> *********************************************************************** VisualStudioSlnConfigurationPlatformClass Class VisualStudioSlnConfigurationPlatformClass Public Configuration '// as string. "Debug", "Release" Public Platform '// as string. "Win32", "x86", "x64" End Class 参考 → VisualStudioSlnClass *********************************************************************** <<< DeleteProjectInVisualStudioSln >>> *********************************************************************** DeleteProjectInVisualStudioSln (src) Sub DeleteProjectInVisualStudioSln( SlnFilePath as string, ProjectNameh as string ) Visual Studio の *.sln ファイルの中にある1つのプロジェクトを削除します。 【引数】 SlnFilePath *.sln ファイルのパス ProjectNameh 削除するプロジェクトの名前 プロジェクトの名前は、 VisualStudioSlnProjectClass::ProjectName から参照できます。 テスト → T_devenv.vbs # [T_devenv_DeleteProjectsInSln] *********************************************************************** <<< その他 >>> *********************************************************************** その他 → C言語 *********************************************************************** <<< インストール、レジストリ、OS >>> *********************************************************************** インストール、レジストリ、OS → Shutdown PC の電源を切ります。 → RegEnumKeys レジストリのサブキーを列挙します。 → RegEnumValues 指定のレジストリ・キーに入っている値を列挙します。 → RegExists 指定のレジストリ・キーか値が存在するかどうかを判定します。 → RegExport レジストリ・キーの値を .reg ファイルに出力します。 → RegRead レジストリからリードします。 → RegWrite レジストリにライトします。 → InstallRegistryFileOpen ファイルをダブルクリックしたときに開くプログラムを設定します。 → InstallRegistryFileVerb ファイルの右クリック・メニューの1つの項目を追加します。 他にもあります。左のツリーから選択してください。 関連 → レジストリ (VBS) → バージョン判定、環境変数 *********************************************************************** <<< Shutdown >>> *********************************************************************** Shutdown [ 親: システム、OS、レジストリ ] (src) Sub Shutdown( Operation as string, CountDownTimeSec as integer ) PC の電源を切ります。 【引数】 Operation 電源の切り方(下記) CountDownTimeSec 電源を切るまでの時間(秒) ソース → vbslib.vbs → SetSuspendState フォルダー サンプル main_child が終了したらデフォルト設定で電源を切る。 RunProg "cscript main_child.vbs", "" Shutdown Empty, Empty 通常 60秒後にシャットダウンします。 エラーが発生しても、電源を切るには、 RunProg などで、メイン処理を行う子プロセス を起動して、子プロセスが終了する(RunProg から戻る)まで待ってから、Shutdown を実行してください。 こうすれば、Ctrl-C や閉じるボタンが押されても電源が切れます。 サンプル 30秒後にスリープする Shutdown "Sleep", 30 Operation 引数 次のいずれかの文字列を指定できます。 "PowerOff", "Reboot", "Hibernate", "Sleep", "Standby" スリープするときは、scriptlib\vbslib_XXX\SetSuspendState フォルダが必要です。 Sleep と Standby は同じです。 Windows 8 タブレットのコネクテッド・スタンバイ には対応していません。 補足 Shutdown 関数を呼び出すと、カウントダウンを始め、下記のウィンドウが開きます。 ただし、CountDownTimeSec = 0 のときは開きません。 [OK] を押せば、すぐに電源を切ります。 [キャンセル]を押すか、VBScript の コンソールを閉じると、電源を切らなく なります。 デフォルト設定は、 setting フォルダ に下記の関数の定義によって設定します。 関数定義がないときは、"PowerOff", 60 になります。 Function Setting_getShutdownOperation() Setting_getShutdownOperation = "PowerOff" End Function Function Setting_getShutdownCountDownTimeSec() Setting_getShutdownCountDownTimeSec = 60 End Function サンプル 音楽を鳴らしながら、60秒待ち、スリープする g_CommandPrompt = 1 '// この行だけ SetupVbslibParameters に記述 Sub main() Play "******.mp3" Dim e ' as Err2 If TryStart(e) Then On Error Resume Next Shutdown "Sleep", 60 If TryEnd Then On Error GoTo 0 e.Clear '// ユーザ・キャンセルしてもウィンドウを閉じるため End Sub このスクリプトを、Windows のタスクに登録しておくと、1時間ごとにスリープに入ることを 試みるようなことができます。 参考 → タスク (Windows でのスケジュール実行) Windows 7 では、地デジの予約録画などによる、 「半スリープ状態」 から、 Shutdown "Sleep" してもスリープ状態になりません。 wakeonlan : 無停電 Linux サーバーから別の PC の電源を入れる まず、電源を入れる PC の準備をします。 Windows XP の場合、 [ スタート > マイコンピューター ] を右クリック [ プロパティ > ハードウェア > デバイス マネージャ ] から、ネットワーク アダプタの子ノードの中から該当するアダプタを 右クリック [ プロパティ ]、[ 詳細設定 > Wake Up Capabilities ] を [ Magic Packet ]、 [ 電源の管理 > このデバイスで、コンピュータのスタンバイ状態を解除できるように する ] にチェックします。 PC の電源を切ってから、再度電源を入れてすぐに BIOS の設定画面を開き(機種 依存です。例:F2を押す)、Wake On LAN を有効にします(例:Power > Automatic Power On > Wake on LAN = Primary) 『無停電の Linux サーバー』 にログインして、wakeonlan コマンドを実行します。 なお、MAC アドレスは、コマンドプロンプトから ipconfig /all を実行すると分かります。 wakeonlan <電源を入れるPCのMACアドレス> 例: ./wakeonlan 11:22:33:44:55:66 電源を落とすには、リモート・デスクトップ経由で、コマンドプロンプトから shutdown /s /f を実行するか、 vbslib Prompt.vbs の Shutdown を実行するか、無停電 Linux サーバー から下記のコマンドを入力してください。 /usr/bin/net rpc -S <マシン名> -U <アカウント名>%<パスワード> shutdown -t 10 <アカウント名> は、<ユーザ名> または <ドメイン名>\\<ユーザ名> テスト → T_Shutdown_Manually.vbs それぞれの OS のバージョンで行うこと *********************************************************************** <<< IsScreenSaverRunning >>> *********************************************************************** IsScreenSaverRunning [ 親: システム、OS、レジストリ ] (src) Function IsScreenSaverRunning() as boolean スクリーンセーバーが動いているかどうかを返します。 テスト → T_ScreenSaver_Manually.vbs # [T_IsScreenSaverRunning] *********************************************************************** <<< RegEnumKeys >>> *********************************************************************** RegEnumKeys [ 親: システム、OS、レジストリ ] (src) Sub RegEnumKeys( Path as string, out_Keys as array of string, Opt as integer ) レジストリのサブキーを列挙します。 【引数】 Path レジストリのキーのパス out_Keys (出力) サブキーのフルパスの配列。 末尾に \ は無い Opt オプション。 Empty か F_SubFolder ファイル: System.vbs サブキーが無いときは、UBound( out_Keys ) = -1 になります。 Path の末尾に \ があってもなくても、キー(フォルダーのようなもの)を指定したことに なります。 サンプル: Dim keys RegEnumKeys "HKEY_CURRENT_USER\Software\_Test", keys, Empty '// keys(0) = "HKEY_CURRENT_USER\Software\_Test\Sub" '// keys(1) = "HKEY_CURRENT_USER\Software\_Test\Sub2" テスト → T_Reg.vbs T_Reg1 *********************************************************************** <<< RegEnumValues >>> *********************************************************************** RegEnumValues [ 親: システム、OS、レジストリ ] (src) Sub RegEnumValues( Path as string, out_Values as array of RegValueName ) RegValueName 指定のレジストリ・キーに入っている値を列挙します。 【引数】 Path レジストリのキーのパス out_Values (出力) 値と型名の配列 → RegValueName クラス ファイル: System.vbs サンプル: Dim values RegEnumValues "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\" + _ "CurrentVersion\Setup", values '// Set "values" Path の末尾に \ があってもなくても、キー(フォルダーのようなもの)を指定した ことになります。 RegValueName クラス Class RegValueName Public Name as string Public Type_ as string End Class テスト → T_Reg.vbs T_Reg1 *********************************************************************** <<< RegExists >>> *********************************************************************** RegExists (src) [ 親: システム、OS、レジストリ ] Sub RegExists( RegPath as string ) 指定のレジストリ・キーか値が存在するかどうかを判定します。 【引数】 RegPath レジストリのキーのパス Path の末尾が \ のときは、キーがあるかどうかを判定します。 Path の末尾が \ ではないときは、値があるかどうかを判定します。 ファイル: System.vbs サンプル: If RegExists( "HKEY_CURRENT_USER\Software\_Test\" ) Then Fail *********************************************************************** <<< IsRegEmptyKey >>> *********************************************************************** IsRegEmptyKey Sub IsRegEmptyKey( RegPath as string ) 指定のレジストリ キーに、値もサブのキーもないかどうかを返します。 指定のレジストリ キーがないときは、False を返します。 ソース → vbslib.vbs テスト → T_Reg.vbs T_Reg1 *********************************************************************** <<< RegRead >>> *********************************************************************** RegRead [ 親: システム、OS、レジストリ ] (src) Function RegRead( Path as string ) as variant レジストリからリードします。 【引数】 Path リードする場所。 キーへのパス+値の名前 返り値 値、または Empty RegRead (Shell) との違いは、キーが見つからないときにエラーになるのではなく、 Empty を返すところです。 Path の最後に \ があると、キーの (規定) をリードします。 関連 → RegReadEx *********************************************************************** <<< RegReadEx >>> *********************************************************************** RegReadEx [ 親: システム、OS、レジストリ ] (src) Function RegReadEx( Path as string, RegistryType as integer ) as variant レジストリからリードします。 32/64 ビット用レジストリ対応。 【引数】 Path リードする場所。 キーへのパス+値の名前 RegistryType 64=64ビット用レジストリ、32=32ビット用レジストリ 返り値 値、または Empty サンプル echo RegReadEx( "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"+_ "doxygen_is1\InstallLocation", 64 ) *********************************************************************** <<< RegExport >>> *********************************************************************** RegExport [ 親: システム、OS、レジストリ ] (src) Sub RegExport( RegPath as string, OutFilePath as string, Opt as variant ) 指定のレジストリ・キーに入っている値を .reg ファイルに出力します。 【引数】 RegPath レジストリのキーのパス OutFilePath 出力ファイルパス Opt オプション。 Empty か F_SubFolder ファイル: System.vbs 対応しているキーの型は、REG_SZ のみです。 サンプル: RegExport "HKEY_CURRENT_USER\Control Panel\Keyboard", _ "keyboard.reg", F_SubFolder テスト → T_Reg.vbs # T_RegExport *********************************************************************** <<< RegWrite >>> *********************************************************************** RegWrite [ 親: システム、OS、レジストリ ] (src) Sub RegWrite( Path as string, Value as string or integer, Type as string or Empty ) レジストリにライトします。 【引数】 Path ライトする場所。 キーへのパス+値の名前 Value 値、または Empty(=値を消す) Type 値のタイプ, "REG_SZ", "REG_DWORD" など、または Empty(*1) ファイル: System.vbs Path によっては管理者権限が必要です RegWrite (Shell) との違いは、エラーメッセージの内容です。 Path の最後に \ があると、キーの (規定) に設定します。 (*1) Type = Empty のときは、 Value の型によって自動的に型を判定します。 サンプル: RegWrite "HKEY_CLASSES_ROOT\.ext\", "ExtSample", Empty *********************************************************************** <<< RegDelete >>> *********************************************************************** RegDelete [ 親: システム、OS、レジストリ ] (src) Sub RegDelete( Path as string ) レジストリの値、またはキーを削除します。 Path の末尾が "\" のときは、キー(フォルダーのようなもの)を削除します。 サブ・キーや値があるときでも、削除できます。 値の名前に "\" を含むときは、 ただし、RegDelete でキーを削除するときは、そのキー(またはサブ・キー)が 持つ値の名前に "\" を含んでいても正しく処理します。 StdRegProv::DeleteValue を使ってください。 サンプル: RegDelete "HKEY_CLASSES_ROOT\.svg\" テスト → T_Reg.vbs T_Reg1 → T_Reg_Manually.vbs # T_RegWriteRead → T_Reg_Manually.vbs # T_FileAssocOpen 最後の T_FileAssocProg2.exe アンインストールで、値の名前に "\" を含む 値を持つキーを削除しています。 *********************************************************************** <<< OpenForRegFile >>> *********************************************************************** OpenForRegFile (src) Function OpenForRegFile( RegFilePath as string ) as EditRegFile レジストリファイル(*.reg)を編集します。 【引数】 RegFilePath レジストリファイルのパス 返り値 EditRegFile オブジェクト サンプル: Dim f : Set f = OpenForRegFile( "Sample.reg" ) If IsEmpty( f.RegRead( "HKEY_CLASSES_ROOT\.ext\" ) ) Then _ f.RegWrite "HKEY_CLASSES_ROOT\.ext\", "ExtSample", "REG_SZ" f = Empty '// Write Sample.reg HKEY_CLASSES_ROOT\.ext\ ExtSample ランダムアクセスに対応しています。 OpenForRead や OpenForWrite のように シーケンシャル(ファイルの先頭から順番)にアクセスする必要はありませんし、 変更しないキーまで Write する必要はありません。 存在しないキーを新規に Write したときは、シーケンシャル(RegWriteした順番) にファイルに記述されます。 Empty の値を Write すると、そのキーは削除されます。 元々書かれていたコメントは保持されます。 テスト → T_Reg.vbs # T_RegFile 関連 → OpenForEnvVarsFile → .ini ファイル *********************************************************************** <<< EditRegFile クラス >>> *********************************************************************** EditRegFile クラス (src) レジストリファイル(*.reg)を編集します。 OpenForRegFile から取得できます。 メソッド .RegRead レジストリファイルからリードします。 .RegWrite レジストリファイルにライトします。 .Close レジストリファイルを閉じます。 アクセスを終了します。 *********************************************************************** <<< Close (EditRegFile) >>> *********************************************************************** Close (EditRegFile) (src) Sub EditRegFile::Close() レジストリファイルを閉じます。 アクセスを終了します。 デストラクタによっても自動的にファイルを閉じます。 閉じる前にエラーが発生してデストラクタが呼ばれたら、Write した内容は反映されません。 *********************************************************************** <<< InstallRegistryFileOpen >>> *********************************************************************** [ 親: システム、OS、レジストリ ] (src) InstallRegistryFileOpen Sub InstallRegistryFileOpen( Extension as string, ExePath as string, IsDefault as boolean ) ファイルをダブルクリックしたときに開くプログラムを設定します。(現在のユーザーのみ) 【引数】 Extension 拡張子 ExePath プログラムの exe ファイルのパス。相対パス可。 IsDefault True = ダブルクリックしたときに開く、 False = プログラムの選択に登録する ファイル: System.vbs サンプル: InstallRegistryFileOpen ".svg", "Snap Note.exe", True Windows8 では、関連する設定に矛盾があると、「この種類のファイル (.<拡張子>) を開くには、どのアプリを使いますか?」が常に表示されます。 下記 Hash キーがあるときは、レジストリーの設定を直接設定しただけでは、「この種類の ファイル (.<拡張子>)を開くには、どのアプリを使いますか?」が常に表示されるようになります。 セキュリティーの機能の可能性があります。 少なくとも、マクロソフト製品が使う拡張子は、 Hash キーができます。 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ FileExts\.<拡張子>\UserChoice\Hash ダブルクリックしたときに開くプログラムを変更できるように戻すには、 UninstallRegistryFileOpen などで、レジストリーの設定を元に戻してから、ファイルを右クリック [ プログラムから開く > 既定のプログラムの選択 ] を選んでください。 マクロソフト製品(または、Windows インストーラーでインストールしたプログラム?)が使わない 拡張子には Hash キーができず、レジストリーの設定だけで関連付けすることができます。 参考 → ファイルをダブルクリックしたときのコマンド → 既定のプログラムの選択、プログラムから開く テスト → T_Reg_Manually.vbs # [T_FileAssocOpen] 関連 → UninstallRegistryFileOpen ダブルクリックしたときの設定解除 → InstallRegistryFileVerb ファイルの右クリック・メニュー → InstallRegistryFileOpenCommand コマンドラインを指定して開くプログラムを設定する *********************************************************************** <<< UninstallRegistryFileOpen >>> *********************************************************************** [ 親: システム、OS、レジストリ ] (src) UninstallRegistryFileOpen Sub UninstallRegistryFileOpen( Extension as string, ExePath as string ) ファイルをダブルクリックしたときに開くプログラムを設定解除します。(現在のユーザーのみ) 【引数】 Extension 拡張子 ExePath プログラムの exe ファイルのパス。相対パス可。 ファイル: System.vbs サンプル: UninstallRegistryFileOpen ".svg", "Snap Note.exe" テスト → T_Reg_Manually.vbs # [T_FileAssocOpen] 関連 → InstallRegistryFileOpen ダブルクリックしたときの設定 *********************************************************************** <<< InstallRegistryFileOpenCommand >>> *********************************************************************** [ 親: システム、OS、レジストリ ] (src) InstallRegistryFileOpenCommand Sub InstallRegistryFileOpenCommand( Extension as string, ProgID as string, CommandLine as string, IsDefault as boolean ) ファイルをダブルクリックしたときに開くプログラムを設定します。(現在のユーザーのみ) 【引数】 Extension 拡張子 ProgID プログラムの識別子 CommandLine コマンドライン IsDefault True = ダブルクリックしたときに開く、 False = プログラムの選択に登録する ファイル: System.vbs サンプル InstallRegistryFileOpenCommand ".svg", "Snap Note.exe", """Snap Note.exe"" ""%1""", True サンプル prompt_vbs = SearchParent( "vbslib Prompt.vbs" ) command_line = """%windir%\System32\cmd.exe"" /K (""%windir%\System32\cscript.exe"" //nologo """+_ prompt_vbs +""" TranslateTest ""%1"" """")" InstallRegistryFileOpenCommand "trans", "TranslateTest", command_line, True 参考 → ファイルをダブルクリックしたときのコマンド テスト → T_Reg_Manually.vbs # T_FileAssocOpen_OS_Exe 関連 → UninstallRegistryFileOpenCommand → GetCScriptGUI_CommandLine *********************************************************************** <<< UninstallRegistryFileOpenCommand >>> *********************************************************************** UninstallRegistryFileOpenCommand Sub UninstallRegistryFileOpenCommand( Extension as string, ProgID as string ) ファイルをダブルクリックしたときに開くプログラムを設定解除します。(現在のユーザーのみ) 【引数】 Extension 拡張子 ProgID プログラムの識別子 ファイル: System.vbs サンプル: UninstallRegistryFileOpenCommand ".svg", "Snap Note.exe" テスト → T_Reg_Manually.vbs # T_FileAssocOpen_OS_Exe 関連 → InstallRegistryFileOpenCommand *********************************************************************** <<< RegWriteOpenExt >>> *********************************************************************** [ 親: システム、OS、レジストリ ] (src) RegWriteOpenExt 廃止されました。 代わりは…… → InstallRegistryOfFileOpen Sub RegWriteOpenExt( Ext, KeyName, Explain, Command, Opt ) 指定の拡張子の [開く(&O)] メニューのコマンドを登録します。 【引数】 Ext 拡張子。先頭はピリオド。例:.ext KeyName レジストリのキーの名前(英語) Explain タイプの説明に表示される内容 Command 実行するコマンドライン Opt 通常 Empty サンプル: .c ファイルをメモ帳で開くようにします。 RegWriteOpenExt ".c", "cfile", "C Language source", _ "C:\Windows\Notepad.exe ""%1""", Empty ファイル: System.vbs 管理者権限が必要です 今まで関連付けられていた情報は失われます。 *********************************************************************** <<< InstallRegistryFileVerb >>> *********************************************************************** [ 親: システム、OS、レジストリ ] (src) InstallRegistryFileVerb Sub InstallRegistryFileVerb( ProgID as string, Verb as string, Caption as string, CommandLine as string ) ファイルの右クリック・メニューの1つの項目を追加します。(現在のユーザーのみ) 【引数】 ProgID "*"、または RegReadExtProgID の返り値 (*1) Verb メニュー項目の識別子(英語) Caption 右クリック・メニューに表示する文字列。(*2) CommandLine コマンドライン。 %1 は、ファイルのパスに置き換わります。 ファイル: System.vbs サンプル: InstallRegistryFileVerb RegReadExtProgID( "svg" ), "edit", "Snap Note (&Z)", _ """"+ GetFullPath( "Snap Note.exe", Empty ) +""" ""%1""" (*1) RegReadExtProgID で、拡張子と現在関連付けられている ProgID を取得できます。 フォルダーに対する設定をするときは、ProgID="Folder" を指定してください。 すべてのファイルやフォルダーに対する設定をするときは、ProgID="*" を指定してください。 (*2) & の次の文字は、右クリック・メニューを表示している状態で押すと選択できるキーボード のキーになります。 参考 → 右クリックして表示されるメニュー (特定の拡張子のファイル) テスト → T_Reg_Manually.vbs # [T_FileAssocVerb] 関連 → UninstallRegistryFileVerb 右クリック・メニューの削除 → InstallRegistryFileOpen ダブルクリックしたときの設定 → RegReadExtProgID 拡張子と関連付けられている ProgID の取得 *********************************************************************** <<< UninstallRegistryFileVerb >>> *********************************************************************** [ 親: システム、OS、レジストリ ] (src) UninstallRegistryFileVerb Sub UninstallRegistryFileVerb( ProgID as string, Verb as string ) ファイルの右クリック・メニューの1つの項目を削除します。(現在のユーザーのみ) 【引数】 ProgID "*"、または RegReadExtProgID の返り値 (*1) Verb メニュー項目の識別子(英語) ファイル: System.vbs サンプル: InstallRegistryFileVerb RegReadExtProgID( "svg" ), "edit" (*1) RegReadExtProgID で、拡張子と現在関連付けられている ProgID を取得できます。 関連 → InstallRegistryFileVerb 右クリック・メニューの追加 *********************************************************************** <<< RegWriteAsterExt >>> *********************************************************************** [ 親: システム、OS、レジストリ ] (src) RegWriteAsterExt 廃止されました。 代わりは…… → InstallRegistryFileVerb Sub RegWriteAsterExt( KeyName, Caption, Command, Opt ) すべてのファイルに対するコンテキストメニューを追加登録します。 【引数】 KeyName レジストリのキーの名前(英語) Caption コンテキストメニューに表示される内容 Command 実行するコマンドライン Opt 通常 Empty ファイル: System.vbs 管理者権限が必要です サンプル: '--- start of parameters for vbslib include ------------------------------- g_admin = 1 : '--- end of parameters for vbslib include --------------------------------- Sub main() Dim prog : prog = GetFullPath( "bz", Empty ) RegWriteAsterExt "bz", "bz (binary editor)", prog + "\bz.exe ""%1""", Empty End Sub *********************************************************************** <<< RegReadExtProgID >>> *********************************************************************** [ 親: システム、OS、レジストリ ] (src) RegReadExtProgID Function RegReadExtProgID( Extension as string ) as string 拡張子と現在関連付けられている ProgID を取得します。(現在のユーザー) フォルダーに対応する ProgID は、"Folder" です。 関連 → InstallRegistryFileVerb 右クリック・メニューの追加 *********************************************************************** <<< MsiModify >>> *********************************************************************** MsiModify (src) Sub MsiModify( MsiPath as string, TableName as string, KeyColumnName as string, ValueColumnNum as integer, Key as string, NewValue as string ) Windows 用のインストール・パッケージ(.msi)のデータベースを修正します。 【引数】 MsiPath インストール・パッケージ(.msi)のファイルのパス TableName データベースのテーブル名 KeyColumnName キーがある列の名前 ValueColumnNum 値がある列の番号(最初=1) Key キーの名前 NewValue 新しい値 サンプル Sub Main( Opt, AppKey ) Dim msi_path : msi_path = "sample.msi" Dim new_values : Set new_values = Dict(Array( "Utilities", "INSTALLDIR" )) Dim key For Each key In new_values.Keys MsiModify msi_path, "Directory", "Directory", 2, key, new_values.Item( key ) Next End Sub 参考 → Orca ツール、msi ファイルのデータベースの修正 *********************************************************************** <<< get_WMI >>> *********************************************************************** [ 親: システム、OS、レジストリ ] (src) get_WMI Function get_WMI( ComputerName as string, ClassName as string ) as Object WMI オブジェクトを返します。 【引数】 ComputerName コンピューター名。 Empty = ログオンしているコンピューター ClassName WMI のクラス名 返り値 エラーコード、正常=0 参考 → WMI (Windows Management Instrumentation) *********************************************************************** <<< GetPythonInstallPath >>> *********************************************************************** GetPythonInstallPath Function GetPythonInstallPath() as string Python がインストールされているフォルダーのパスを返します。 レジストリーの情報と、 SetTargetPythonVersion の設定を元にしています。 ソース → vbslib.vbs サンプル python_exe = GetPythonInstallPath() +"\python.exe" script_path = "C:\sample.py" RunProg """"+ python_exe +""" """+ script_path +"""", "" *********************************************************************** <<< SetTargetPythonVersion >>> *********************************************************************** SetTargetPythonVersion Sub SetTargetPythonVersion( MinVer as integer, MaxVer as integer ) Python に関する機能の対象となるバージョンの範囲を設定します。 【引数】 MinVer 最小バージョン、または、Empty MaxVer 最大バージョン、または、Empty 本関数を呼び出すと、 GetPythonInstallPath や IsInstallPython の動きが 変わります。 ソース → vbslib.vbs *********************************************************************** <<< IsInstallPython >>> *********************************************************************** IsInstallPython Function IsInstallPython() as boolean Python がインストールされているかどうかを返します。 ソース → vbslib.vbs *********************************************************************** <<< GetPerlVersion >>> *********************************************************************** GetPerlVersion Function GetPerlVersion( Options as Empty ) as string Perl がインストールされているか確認し、ActivePerl のバージョンを返します。 【引数】 Options Empty を指定してください 返り値 スクリプト・エンジン名と、バージョン番号。 例:"5.16.3" 内部で Setting_getPerlPath によって Perl スクリプトのホスト(.exe) のパスを検索します。 また、本関数の内部で、現在実行中のプロセスの環境変数 PATH に、Perl の exe ファイルがある フォルダーを追加します。 Perl がインストールされていないと、下記のようなエラーになります。 参考 → Strawberry Perl → ActivePerl サンプル Perl が使えるかどうかをチェックする GetPerlVersion Empty ソース → vbslib.vbs *********************************************************************** <<< その他 >>> *********************************************************************** その他 → GetOSVersion → SetTaskStartTime タスクに登録する → 送る、に登録する *********************************************************************** <<< ネットワーク >>> *********************************************************************** ネットワーク → DownloadByHttp インターネットからダウンロードします。 → SetVirtualFileServer 仮想ファイル・サーバーを設定します。 → GetPercentURL % 文字を使った正規の URL に変換します。 → CheckWSHNetwork ファイアウォールをチェックします。 → start ホームページを開きます。 他にもあります。左のツリーから選択してください。 *********************************************************************** <<< DownloadByHttp >>> *********************************************************************** キーワード: sage_p_downloader.exe DownloadByHttp Sub DownloadByHttp( DownloadURL as string, OutLocalPath as string ) インターネットからダウンロードします。 【引数】 DownloadURL ダウンロードする URL、または、その配列 OutLocalPath ダウンロードしたファイルの保存先パス DownloadURL 引数が配列のときは、OutLocalPath はフォルダーのパスになります。 DownloadURL 引数が配列のときは、実行後は、DownloadURL 配列の内容が、 保存先のファイルのパスに置き換わります。 サンプル DownloadByHttp "http://www.sage-p.com/index.html", "index.html" DownloadURL には、URL に含むことができない文字も含むことができます。 内部で、GetPercentURL を呼び出しています。 ダウンロードを含む処理をするときは、SetVirtualFileServer を使えば、実際に ネットワークにアクセスする前に、ローカル PC だけで動作確認ができます。 参考 → SetVirtualFileServer デフォルトでは、Sage Plaisir 21 のホームページからダウンロードするときのみ、 ユーザーの許可を確認することなくダウンロードできます。 他のホームページ からダウンロードするときは、ユーザーの許可を求められます。 他のホームページからダウンロードする処理を含むスクリプトを使って自動化する ときは、ユーザーの許可を求めない exe を作成する必要があります。 デフォルト では、ダウンロードを実際に行うのは、scriptlib\vbslibXXX\sage_p_downloader に 入っている sage_p_downloader.exe ですが、_src\Test\vbslib_test\scriptlib\ vbslib\sage_p_downloader\src にソースが含まれているので、 修正は簡単です。 ソースに記述されたダウンロードできるドメインを 変更し、再コンパイルし、exe 名を変更して、Netword.vbs にある DownloadByHttp の定義を編集してください。 exe 名を変更することで、ウィルス対策ソフトが ネットワークアクセスの許可を再度行います。 ソース → Network.vbs → src フォルダー sage_p_downloader.exe のソース テスト → T_Download.vbs T_SetVirtualFileServer T_SetVirtualFileServer_Files T_SetVirtualFileServer_Files_Manually 関連 → SetVirtualFileServer → GetPercentURL *********************************************************************** <<< SetVirtualFileServer_byXML >>> *********************************************************************** SetVirtualFileServer_byXML Sub SetVirtualFileServer_byXML( SettingXML_Path as string ) SetVirtualFileServer による仮想ファイル・サーバーの設定を XML ファイルで行います。 【引数】 SettingXML_Path 仮想ファイル・サーバーの設定がある XML ファイル、または、Empty SettingXML_Path = Empty のときは、仮想ファイル・サーバーを使わないようになります。 既に仮想ファイル・サーバーが登録されていたときも、その登録は解除されます。 これまで登録されていた仮想ファイル・サーバーの設定は登録解除されます。 参考 → SetVirtualFileServer サンプル SetVirtualFileServer_byXML GetVar("%VirtualServer%") GetVar 環境変数 VirtualServer が定義されていれば、その値を XML ファイルのパスとして設定します。 定義されていなければ、仮想ファイル・サーバーを使いません。 XML ファイルの例 Replace/@from SetVirtualFileServer の VirtualURL 引数に渡す値 Replace/@to SetVirtualFileServer の LocalOrOtherPath 引数に渡す値。 省略時は、Empty を渡します。 ソース → Network.vbs テスト → T_Download.vbs T_SetVirtualFileServer_byXML キーワード: VirtualServer, TestServer *********************************************************************** <<< SetVirtualFileServer >>> *********************************************************************** SetVirtualFileServer Sub SetVirtualFileServer( VirtualURL as string, LocalOrOtherPath as string ) ネットワーク・サーバーの代わり(仮想ファイル・サーバー)を設定します。 【引数】 VirtualURL 仮想ファイル・サーバーが応答するベース URL LocalOrOtherPath VirtualURL に対応するローカルのパス、または URL 通常、VirtualURL の最後が、/ なら、LocalPath の最後は \ または / にしてください。 SetVirtualFileServer を使うと、 DownloadByHttp を呼び出しても、インターネットからダウン ロードせず、設定したローカル・フォルダからコピーするか、別の URL からダウンロードします。 この機能により、一般公開されているサーバーを変更しないでテストができます。 LocalOrOtherPath は、ローカル PC にあるフォルダーのパス、または、別の URL を指定します。 LocalOrOtherPath に "://" があると、別の URL が指定されたとして、ダウンロードします。 既に仮想ファイル・サーバーが登録されているときに呼び出すと、追加登録されます。 LocalOrOtherPath = Empty を指定すると、VirtualURL の URL に対して、仮想ファイル・サーバーを 使わないようになります。 VirtualURL = Empty を指定すると、すべての仮想ファイル・サーバーを使わないようになります。 サンプル SetVirtualFileServer "http://www.sage-p.com/", "C:\www_sage-p_com\" DownloadByHttp "http://www.sage-p.com/index_test.html", "index.html" ソース → Network.vbs テスト → DownloadByHttp のテスト 関連 → SetVirtualFileServer_byXML *********************************************************************** <<< GetPercentURL >>> *********************************************************************** GetPercentURL Function GetPercentURL( UnicodeURL as string ) as string 基本的な URL の区切り文字(:/?#)以外の予約文字を、% 文字を使った URL にエンコードします。 【引数】 UnicodeURL 基本的な URL の区切り文字だけを考慮した URL 返り値 実際に URL に使える文字だけを使った URL % 文字を使うようにエンコードした文字列は、% とそれに続く 2 文字(UTF-8 の16進数)を、 対応する 1 文字に変換するだけでデコードできます(戻ります)。 ただし、エンコード時に、 % も %25 に変換しておかなければ、デコードしても戻らなくなります。 % は1バイトしか変換できないので、文字コード セットの情報が別に無ければ、Ascii 以外の文字を デコードしても戻らなくなります。 一般にUTF-8 が使われますが、Ascii 以外の文字に対して UTF-16 より効率が悪い UTF-8 を使うのは、よく考えていないのでしょう。 2バイト文字は、 9バイト(UTF-8)、6バイト(UTF-16、Shift-JIS)になります。 つまり、4.5倍と3倍です。 未対応 国際化ドメイン名(Punycode) は、2〜3倍に収まります。(本関数ではこの変換はしません) サンプル url = GetPercentURL( "http://www.sage-p.com/download file.zip" ) url は、 "http://www.sage-p.com/download%20file.zip" になります。 詳細 本関数は、基本的な URL の予約文字 : / ? # はそのまま残し、それ以外の(特殊な)予約文字は % 文字を使った文字列にエスケープします。 URL の ?query の部分の = と & は、クエリー文字列 のため、エスケープしません。 それ以外の部分の = と & は、エスケープします。 特殊な予約文字を返り値に含める(予約文字として使う)ときは、"${>" と "}" の間に埋め込んで ください。 "${>" と、それに続く "}" は無くなります。 未対応 ${ } 変数 は展開しません。 文字 $, {, } がエスケープされます。 ${> } 変数の定義は不要です。 基本的な予約文字で区切られた、それぞれの部分文字列(ファイル名、フォルダー名、URL の後の ほうにある ?query の各変数の値や #fragment の部分) は、基本的な予約文字も含めてすべて エスケープする必要があるので、本関数とは別の関数を使うとよいでしょう。 未対応 query の中にある sub-delims の文字は、クエリー文字列として有効にするため、エスケープしま せん。 query の中の : / ? @ は、gen-delims ではありません。 fragment の中にある sub-delims の文字は、RFC 3986 では区切り文字ではないため、エスケープ しません。 また、fragment の中の : / ? @ は、gen-delims ではありません。 \ 文字は、URL のフォルダー区切り記号 / に変換します。 戻すときに \ か / のどちらであるか は分からなくなります。 Windows のパス (UNC) に使うなどの状況で判断してください。 空白は + ではなく %20 に置き換えます。 Google でも正常に動きます。 + は、Google の検索 キーワードに入れるため %2B に置き換えます。 参考 → 検索キーワードの空白は + エンコードの詳細 上記の補足を踏まえて、文字ごとにまとめると、以下のようになります。 次の文字(基本的な予約文字)は、区切り文字として、エスケープしません。   ・: / ? # // RFC3986 の ABNF のトップの定義にある gen-delims   ただし、最初の # より後の # はエスケープします。 次の文字(特殊な予約文字)は、区切り文字や予約文字ではなくすために、% にエスケープします。   ・[ ] @ // RFC3986 の gen-delims     ・ただし、query と fragment の @ は、エスケープしません。   ・! $ & ' ( ) * + , ; = // RFC3986 の sub-delims。     ・ただし、query と fragment の sub-delims は、エスケープしません。   ・% < > // RFC3986 にはあるが、reserved になっていない予約文字 次の文字は、RFC 3986 では明確にされていないため、% にエスケープします。   ・Ascii 以外の文字 (漢字、Unicode 文字)   ・" ^ { | } // \ 以外の RFC3986 で定義されていない文字、空白と制御文字 "${>" と "}" の間の文字は、どんな文字でもエスケープせず、"${>" とそれに続く "}" が 無くなります。 その後、$\ は $ に変換されます。 (最優先) \ 文字は、URL のフォルダー区切り記号 / に変換します。 RFC 3986 では明確にされていません。   ・\ 次の文字(英語の一般の文字)は、URL でも使えるので、エスケープしません。   ・アルファベット、数字 URLに使える文字 RFC 3986 RFC1738-ja, RFC 2396 RFC 3986 に基づいて URL (URI) に使える/使えない文字は、以下の通りです。 国際化ドメイン名 は、% と文字コードではなく、Punycode に変換します。 Windows のフォルダー区切り文字 \(バックスラッシュ) は、通常、URL にするときに / に 置き換えますが、URL では定義されていません。 0 1 2 3 4 5 6 7 URL の仕様に出てこない文字(使えない文字 "^\{|}) 0 spc 0 @ P ` p URL が使う一般的な予約文字 (gen-delims :/?#[]@) 1 ! 1 A Q a q 特殊な URL の予約文字 (sub-delims !$&'()*+,;=) 2 " 2 B R b r URL で定義がない予約文字(使えない文字 %<>) 3 # 3 C S c s URL が文字として使う文字 (unreserved A0-._~) 4 $ 4 D T d t 5 % 5 E U e u GetPercentURL 関数 (vbsliib) 6 & 6 F V f v scheme, hier-part, query, fragment でエスケープ 7 ' 7 G W g w scheme, hier-part でエスケープ 8 ( 8 H X h x → 詳細 9 ) 9 I Y i y A LF * : J Z j z B + ; K [ k { C , < L \ l | D CR - = M ] m } E . > N ^ n ~ F / ? O _ o 0 1 2 3 4 5 6 7 以下に RFC 3986 の一部を示す。 参考 → RFC 3986 - Appendix A. Collected ABNF for URI (Web) → 情報セキュリティ技術動向調査(2009 年下期):IPA (Web) 9 URI のエスケープ - RFC 3986 は、unreserved が減っていて読みにくくなる (予約文字を踏まえずに多くの標準ができている身勝手な標準化委員への愚痴?) fooooooo://example.com:8042/over/there?name=ferret#nose (scheme) ( authority )( path ) ( query ) ( fragment ) → RFC 3986 - 3. Syntax Components (Web) URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty authority = [ userinfo "@" ] host [ ":" port ] host = IP-literal / IPv4address / reg-name reg-name = *( unreserved / pct-encoded / sub-delims ) path-abempty = *( "/" segment ) path-absolute = "/" [ segment-nz *( "/" segment ) ] path-rootless = segment-nz *( "/" segment ) segment = *pchar segment-nz = 1*pchar query = *( pchar / "/" / "?" ) fragment = *( pchar / "/" / "?" ) → ABNF 記法 pchar = unreserved / pct-encoded / sub-delims / ":" / "@" unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" pct-encoded = "%" HEXDIG HEXDIG reserved = gen-delims / sub-delims gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" ALPHA = アルファベット DIGIT = 数字 HEXDIG = 16進数の数字。 (Hex Digit) RFC 3986 では、unreserved と sub-delims が常に選択できる。 pct = percent, gen = general, delims = delimiters % は、pct-encoded の定義内で使われています。 < と > は、URL を囲む文字として使うことが推奨されています。 つまり、URL では使えません。 Using <> angle brackets around each URI is especially recommended as a delimiting style for a reference that contains embedded whitespace. IDN、国際化ドメイン名、日本語ドメイン名 → 国際化ドメイン名 - Wikipedia (Web) ドメイン名の区切り(ピリオド)ごとに、Punycode 変換を行う。 → Punycode → Punycode - Wikipedia (Web) 参考 → URLエンコード (% 表記) → CGIのパラーメータつきURL (?), query → Uniform Resource Identifier (URI): Generic Syntax (Web) → URIに使ってよい文字の話 - 本当は怖い情報科学 (Web) ソース → Network.vbs テスト → T_Download.vbs T_GetPercentURL 関連 → DecodePercentURL → ConvertCharCodeInHref → ECMAScript - encodeURIComponent → Punycode *********************************************************************** <<< DecodePercentURL >>> *********************************************************************** DecodePercentURL Function DecodePercentURL( in_URL as string ) as string % 文字を使った URL から、Unicode 文字を使った URL にデコードします。 【引数】 in_URL % 文字を使った URL 返り値 Unicode 文字を使った URL ソース → vbslib.vbs テスト → T_Download.vbs T_GetPercentURL 関連 → GetPercentURL *********************************************************************** <<< LockByFileMutex >>> *********************************************************************** LockByFileMutex Function LockByFileMutex( UNC_FilePath as string, TimeOut_msec as integer ) as FileMutexClass ファイル・サーバーに対する排他制御を開始します。 【引数】 UNC_FilePath 排他制御を管理するファイルのパス TimeOut_msec タイムアウト(ミリ秒)、または、c.Forever 返り値 ロック状態を保持しているオブジェクト → FileMutexClass UNC_FilePath に、ファイル・サーバー、または、ローカルのファイルのパスを指定 してください。 指定したファイルには、ロックしているユーザー名 %USERDOMAIN%\%USERNAME% (例:PC01\User1)が上書きされ、書き込み禁止、読み込み許可状態になります。 ロック状態を解除したら、ファイルを削除します。 FileMutexClass LockByFileMutex 関数の返り値です。 FileMutexClass のオブジェクトが削除されると、ロック状態を解除します。 Close メソッド(引数なし)を呼び出しても解除できます。 サンプル Set c = g_VBS_Lib Set mutex = LockByFileMutex( "\\PC01\Folder\_Mutex.txt", c.Forever ) '// ロック開始 ... mutex = Empty '// ロック終了 ソース → Network.vbs テスト → T_FileMutex_Manually.vbs *********************************************************************** <<< CheckWSHNetwork >>> *********************************************************************** CheckWSHNetwork → CheckWSHNetwork フォルダ WSH (wscript.exe, cscript.exe) に、ファイアウォールがネットワークアクセスを許可しているか どうかをチェックするスクリプトです。 CheckWSHNetwork.vbs をダブルクリックすると起動します。 cscript.exe または wscript.exe に、ネットワークアクセスを許可すると危険かもしれませんが、 Windows7 のファイアウォールは、WSH によるネットワークアクセスをブロックしないで 実行できます。 (ダウンロードサーバーのドメインで識別するのかもしれません?) *********************************************************************** <<< vbs_inc, vbslib include (vbslib のコア・システム) >>> *********************************************************************** [ テスト ] vbs_inc, vbslib include (vbslib のコア・システム) 複数の VBScript ファイルをインクルードするライブラリです。 scriptlib フォルダの中の vbs_inc.vbs ファイルの中にあり、内部的に使われます。 Main 関数 があるスクリプト・ファイルに、vbs_inc をインクルードするコード(vbslib include )が必要です。 そのコードは、 Short Hand Prompt を使って新規作成できるスクリプトなど に入っているので参考にしてください。 vbslib include は、scriptlib\setting フォルダーの中にある .vbs ファイル(通常、 vbs_inc_setting.vbs) に書かれた Setting_getIncludePathes 関数 に書かれた .vbs ファ イルをロードします。 main sample メイン・スクリプト (vbslib includeを含む) → Main 関数 scriptlib vbslib vbs_inc.vbs vbs_inc ライブラリ本体 → vbs_inc.vbs setting 設定フォルダ vbs_inc_setting.vbs vbs_inc の設定 → Setting_getIncludePathes sample_lib インクルードするライブラリのサンプル → ライブラリ.vbs のルール は、インクルードの方向 参考 → vbs_inc/setting の処理フロー、終了時の動作 vbs_inc は、次のグローバル変数を定義しています。 → g_debug デバッガに接続しているかどうか(するかどうか) → g_debug_params デバッガに接続するときのコマンドライン・パラメータ → g_vbslib_path vbs_inc.vbs のフル・パス → g_vbslib_folder scriptlib フォルダのフル・パス。末尾に \ が付く → g_vbslib_ver_folder vbs_inc.vbs があるフォルダのフル・パス。末尾に \ が付く → g_IncludePathes インクルードする VBS ファイルのパスの配列 → g_CommandPrompt コマンドプロンプトで実行するかどうか → g_Vers バージョン番号の集合です。 → g_cut_old 古い関数でブレークするようにします。 → g_is_cscript_exe コマンドライン(cscript.exe)で実行しているかどうか → g_admin 起動時に管理者へログインするのかしないのか → g_fs g_fs = CreateObject( "Scripting.FileSystemObject" ) → g_sh g_sh = WScript.CreateObject("WScript.Shell") 関連 → グローバル変数の初期化、g_InitializeModule → WriteVBSLibFooter *********************************************************************** <<< vbs_inc.vbs >>> *********************************************************************** vbs_inc.vbs vbs_inc.vbs には、インクルードする vbslib のバージョンや、vbslib が入っているフォルダーを 選択して、vbslib をインクルードするスクリプトが書かれています。 vbs_inc.vbs は、 メイン.vbs からインクルードされます。 インクルードする前に、次の変数に値を代入しておいてください。 g_vbslib_path 変数 g_Vers.Item("vbslib") vbs_inc.vbs の中で次の変数を設定(再設定)してください。 g_vbslib_folder 変数 g_Vers.Item("vbslib") vbslib が入っているフォルダーを変更するときは、上記の変数の設定(再設定)だけでなく、 g_vbslib_path 変数 も再設定してください。 サンプル g_vbslib_folder = g_fs.GetParentFolderName( g_vbslib_folder ) g_vbslib_folder = g_vbslib_folder + "\src\samples\scriptlib\" g_vbslib_path = g_vbslib_folder +"vbs_inc.vbs" *********************************************************************** <<< メイン.vbs のグローバル変数 >>> *********************************************************************** メイン.vbs のグローバル変数 メイン・スクリプトのグローバル変数は、start of lib include 〜 end of lib include の間にある、設定値を格納する場所で Dim/New してください。 '--- start of vbslib include ----------------------------- : '--- start of parameters for vbslib include ------- : g_CommandPrompt = 1 Dim g_ObjectA : Set g_ObjectA = New ObjectA '--- end of parameters for vbslib include -------------- : '--- end of vbslib include ------------------------------- '--- start of vbslib include ----------------------------- : '--- start of parameters for vbslib include ------- '--- end of parameters for vbslib include -------------- : '--- end of vbslib include ------------------------------- ライブラリ・スクリプトのグローバル変数は、グローバル領域で Dim して、 InitializeModule 関数の中で初期化します。 g_InitializeModule に InitializeModule 関数のリファレンスを設定します。 Dim g_Test Function InitializeModule Set g_Test = New TestScript End Function Dim g_InitializeModule Set g_InitializeModule = GetRef( "InitializeModule" ) → グローバル変数の初期化、後始末、g_InitializeModule、g_FinalizeModule *********************************************************************** <<< vbslib_updater - vbslib をバージョンアップする >>> *********************************************************************** vbslib_updater - vbslib をバージョンアップする vbslib_updater ツール バージョンアップを補助する vbslib_updater というツールを提供しています。 下記の作業を自動的に行います。 ただし、手動で修正が必要な場合もあります。 vbslib ヘッダ にあるファイルをベースに vbslib フォルダを vbslib ヘッダに作成する。 vbslib ヘッダがある *.vbs ファイルに g_Vers を追加し vbslib のバージョンを 3.0 に設定する。 main 関数を main2 に置き換える。 元の main 関数は、コメントアウトする。 g_IncludeType を、コメントアウトする。 アプリケーション・スクリプトの修正 一部の関数は、廃止されても移植性のために残してあるものがあります。 True に設定して、廃止される関数を呼び出すとブレークするので、見つけやすくなります。 g_cut_old を [WARNING] Out of Writable の警告が大量に出るときは、main2 の最初に次を記述してください。 AppKey.SetWritableMode F_IgnoreIfWarn SetWritableMode scriptlib フォルダの ver2 と ver3 の共存 ver2 の scriptlib フォルダの vbs_inc.vbs を vbs_inc_200.vbs に改名し、 ver3 の scriptlib フォルダを ver2 の scriptlib フォルダにコピーすると、 上書きすることなく、ver2 と ver3 を共存できます。 *********************************************************************** <<< Main (メイン.vbs) >>> *********************************************************************** Main (メイン.vbs) << vbs_inc Sub Main() Sub Main( Opt as dictionary, AppKey as AppKeyClass ) vbslib を使うスクリプトは、Main から内容を記述します。 Main 関数を定義しているスクリプト・ファイルの中に、 (vbslib をインクルードして Main を呼び出すコード)が必要です。 その内容は、既存のメイン・スクリプト(vbslib Prompt.vbs など)を参照してください。 vbslib include のコード ユーザ定義関数です。 引数はあってもなくてもかまいませんが、ファイルに出力するスクリプトは、 AppKey 引数を使った NewWritable メソッド を呼ぶ必要があります。 Main 関数が呼ばれるときのカレント・フォルダーは、スクリプトがあるフォルダー になります。 WSH を起動したときのカレント・フォルダー(作業フォルダー)は、 g_start_in_path に入っています。 main2 関数が定義されているときは呼ばれません。 サンプル Sub Main() echo "Hello, world!" End Sub '--- start of vbslib include ------------------------------ : (vbslib をインクルードして main を呼び出すコード) : (既存のメイン・スクリプトを参照してください) vbslib include カレント・フォルダー にファイルを出力できるようにする サンプル ↓ Sub Main( Opt, AppKey ) Dim w_:Set w_=AppKey.NewWritable( "." ).Enable() echo "Hello, world!" End Sub '--- start of vbslib include ------------------------------ : (vbslib をインクルードして main を呼び出すコード) : (既存のメイン・スクリプトを参照してください) NewWritable vbslib include 参考 → 処理フロー (vbs_inc/setting) Main 関数の外側の動き テスト → T_NewMain1 フォルダ vbslib_inc のみの環境 → T_NewMain2 フォルダ vbslib がある環境 関連 → GetMainSetting 関数 (vbsool) → SetupVbslibParameters → WriteVBSLibFooter *********************************************************************** <<< main2 >>> *********************************************************************** main2 << vbs_inc Sub main2( Opt as dictionary, AppKey as AppKeyClass ) vbslib を使うスクリプトは、main2 から内容を記述します。 廃止予定です。 main を使ってください。 ユーザ定義関数です。 ファイルを出力するスクリプトは、出力するフォルダを、下記サンプルの NewWritable の引数に 指定することで、出力して良いかユーザに確認しなくなります。 ただし、Windows フォルダや Program Files フォルダなどは必ず確認します。 main 関数が呼ばれるときのカレント・フォルダーは、スクリプトがあるフォルダーになります。 WSH を起動したときのカレント・フォルダー(作業フォルダー)は、 g_start_in_path に入っています。 カレント・フォルダー にファイルを出力できるようにする サンプル: ↓ Sub main2( Opt, AppKey ) Dim w_:Set w_=AppKey.NewWritable( "." ).Enable() echo "Hello, world!" End Sub NewWritable *********************************************************************** <<< SetupVbslibParameters >>> *********************************************************************** SetupVbslibParameters << vbs_inc Sub SetupVbslibParameters() vbslib include の設定をします。 ユーザー定義関数です。 通常、メイン・スクリプト・ファイルの最後にあります。 次の変数を設定できます。 → g_debug → g_debug_tree → g_debug_process → g_vbslib_path → g_CommandPrompt サンプル Sub SetupVbslibParameters() '--- start of parameters for vbslib include ------------------------------- '// g_Vers("OldMain") = 1 g_vbslib_path = "scriptlib\vbs_inc.vbs" g_CommandPrompt = 2 g_debug = 0 '--- end of parameters for vbslib include --------------------------------- End Sub g_vbslib_path g_CommandPrompt g_debug *********************************************************************** <<< g_fs >>> *********************************************************************** g_fs (src) << vbs_inc Dim g_fs as Scripting.FileSystemObject FileSystemObject を参照するグローバル変数です。 実装コード: Dim g_fs : Set g_fs = CreateObject( "Scripting.FileSystemObject" ) *********************************************************************** <<< g_sh >>> *********************************************************************** g_sh (src) << vbs_inc Dim g_sh as WScript.Shell → WScript.Shell オブジェクト (WshShell オブジェクト) vbs_inc.vbs をインクルードした後に使えます。 Dim g_sh : Set g_sh = WScript.CreateObject( "WScript.Shell" ) *********************************************************************** <<< 動作モード、デバッグ >>> *********************************************************************** 動作モード、デバッグ *********************************************************************** <<< g_debug >>> *********************************************************************** g_debug (src) Dim g_debug as integer デバッガに接続しているかどうか(するかどうか)。 何番目のエラーでブレークするか。 g_debug は、 /g_debug オプション もしくは、 SetupVbslibParameters にユーザが記述します。 0 = デバッガに接続しない 1 = デバッガに接続する、BreakErrID = 1 1.5 = デバッガに接続する、BreakErrID = 1.5 2 = デバッガに接続する、BreakErrID = 2 : -1 = デバッガに接続しないが、 SetupDebugTools を呼び出す。 99 など大きい数 = デバッガに接続する(エラーが発生しないとき) 参考 → g_debug - デバッグを開始する → Err2::BreakErrID → エラーが発生した瞬間のスクリプト内部の様子を調べる → g_is_debug テスト → [T_ErrInfo] ユーザへのエラー通知とデバッガ接続 → [T_Err2] Err2 オブジェクトとデバッガーのテスト → [T_StartFromOther] スクリプトが無いフォルダーから起動したとき *********************************************************************** <<< g_debug_tree >>> *********************************************************************** g_debug_tree (src) Dim g_debug_tree as Array of integer エラーが発生した場所の詳細情報。 ブレークするために使われる情報です。 g_debug_tree は、 /g_debug オプション もしくは、 SetupVbslibParameters にユーザが記述します。 サンプル: Dim g_debug_tree = Array( 1, 2 ) プログラムを On Error Resume Next 〜 On Error Goto 0 のブロックのツリー構造として 見たときの情報になっています。 ユーザーは、エラーが発生したときに表示される g_debug_tree に設定する値をそのままお使いください。 表示されなかったときは、設定 する必要はありません。 参考 → g_debug - デバッグを開始する テスト → T_Err2_Tree フォルダ *********************************************************************** <<< g_debug_process >>> *********************************************************************** g_debug_process Dim g_debug_process as integer 何回目の子プロセスを起動したときにデバッガに接続するかどうか。 g_debug_process は、 /g_debug オプション もしくは、 SetupVbslibParameters にユーザが記述します。 0 = メイン・プロセスをデバッガに接続する(g_debug>0 のとき) 1 = 1回目にメイン・プロセスが起動した子プロセスをデバッガに接続する 2 = 2回目にメイン・プロセスが起動した子プロセスをデバッガに接続する : サンプル g_debug_process = 1 孫プロセスを起動したときにデバッガに接続することもできます。 g_debug_process = Array(3,1) 3回目に起動した子プロセスから1回目に呼び出す孫プロセス 現在は何回目のプロセス番号か g_InterProcess.ProcessCallID(0) + 1 参考 → g_debug - デバッグを開始する テスト → T_ChildProcessIDNest_Manually.vbs # Array → T_ChildProcessIDNest_Manually2.vbs コールツリー ChangeScriptMode '// g_debug_process (src) // "/g_debug" オプションを g_debug_process 変数へ InitializeModule (src) // g_Err2.Break_ChildProcess_CallID へ If IsNumeric( g_debug_process ) Then g_Err2.Break_ChildProcess_CallID.Add g_debug_process ElseIf IsArray( g_debug_process ) Then g_Err2.Break_ChildProcess_CallID.Copy g_debug_process RunProg (src) '// Break in ChildProcess by "g_debug_process" If g_InterProcess.ProcessCallID(i) + 1 = g_Err2.Break_ChildProcess_CallID(i) Then cmdline = "cscript //x "+ // デバッガーと接続して起動する CallFinalizeInModules (src) If g_debug_process > 0 Then // デバッグ モードから戻すように警告する WScript.Echo " 0 です。 *********************************************************************** <<< g_is_debug >>> *********************************************************************** g_is_debug False = 接続していない True = 接続している If g_is_debug Then *********************************************************************** <<< g_debug_params >>> *********************************************************************** g_debug_params (src) Dim g_debug_params as integer デバッガに接続するときのコマンドライン・パラメータ 通常、.vbs ファイルをダブルクリックすると、コマンドライン・パラメータは何も設定 されませんが、g_debug_param に代入すると設定されます。 g_debug = -1 または 1以上に設定しないと、g_debug_params は無効になります。 サンプル: '--- start of parameters for vbslib include --------- Dim g_debug_params : g_debug_params = "test.txt" テスト → T_DebugParam フォルダ *********************************************************************** <<< g_debug_or_test >>> *********************************************************************** g_debug_or_test (src) Dim g_debug_or_test as integer デバッグ時、またはデバッグ時のテストかどうか。 自動テストを行うことができるデバッグ機能は、g_debug ではなく g_debug_or_test 値が True のときに行います。 *********************************************************************** <<< g_CommandPrompt >>> *********************************************************************** g_CommandPrompt (src) Dim g_CommandPrompt as integer コマンドプロンプトを表示するかどうか 0= コマンドプロンプトなし。メッセージは標準ダイアログで表示。 1= コマンドプロンプトあり。終了するとすぐに閉じる。 エラーが発生したときは閉じない。 2= コマンドプロンプトあり。終了しても閉じない。 +4=コマンドプロンプトを最小化ウィンドウで表示。 +4 は、他のオプションと複合するオプションです。 g_CommandPrompt は、 にユーザが記述します。 SetupVbslibParameters 動作のしくみ コマンドプロンプトなし(=0)のときは、wscript.exe で実行します。 コマンドプロンプトありのときは、cscript.exe で実行します。 ただし、vbs ファイルをダブルクリックした瞬間はwscript.exe で実行しますが、wscript.exe が新しく コマンド・プロンプト(cmd.exe)のプロセスを作成し、そこで cscript.exe を実行します。 → ChangeScriptMode → 処理フロー (vbs_inc/setting) コマンドプロンプトから cscript.exe 経由でスクリプトを起動したときは、同じウィンドウで実行します。 ただし、64ビットのコマンドプロンプトから起動したとき、 g_is64bitWSH が False(デフォルト)なら、 32ビットのコマンド・プロンプト(cmd.exe)である、新しいウィンドウで実行します。 64ビットWindows 32ビットWindows 64ビット cmd.exe %windir%\System32\cmd.exe - 32ビット cmd.exe %windir%\SysWOW64\cmd.exe %windir%\System32\cmd.exe ウィンドウが開いてしまうとき g_CommandPrompt = 0 を設定していても、ウィンドウが開いてしまう原因は、他にもあります。 ・バッチファイルから実行したとき ・ショートカットから実行 するときのリンク先(コマンドライン)に cmd.exe /K を指定したとき ・コマンドライン用の exe を実行したとき (g_CommandPrompt = 5 で最小化はできます) テスト → [T_CommandPrompt] プロンプトを開く、閉じるテスト → [T_ErrInfo] ユーザへのエラー通知とデバッガ接続 関連 → /close オプション → g_is_cscript_exe → コマンドプロンプト、コンソール (cmd.exe) → 正常終了時の動作 *********************************************************************** <<< /close オプション >>> *********************************************************************** /close オプション (src) Sample.vbs /close:0 コマンドプロンプトを表示するかどうかの設定。 このオプションがあるときは、g_CommandPrompt の設定が無視されます。 関連 → g_CommandPrompt *********************************************************************** <<< ChangeScriptMode >>> *********************************************************************** ChangeScriptMode Sub ChangeScriptMode(); 必要に応じて、子プロセスでスクリプトを実行します。 子プロセスを起動する理由は、次のものがあります。 ・コマンドプロンプトのウィンドウを開くために、wscript.exe から cscript.exe を起動する → g_CommandPrompt ・デバッガーに接続するために、//x オプションをつけて cscript.exe または cscript.exe  を起動する ・管理者として実行するために、runas コマンド経由で wscript.exe または cscript.exe  を起動する ・64ビットのコマンドプロンプトから起動したときに、32ビットの wscript.exe または  cscript.exe を起動する。 この場合は、新しいウィンドウが開きます。 ChangeScriptMode 関数は、vbslib を使うときに、自動的に呼ばれます。 vbslib_mini.vbs ファイルを使うときは、明示的に呼び出してください。 ソース → vbs_inc_sub.vbs → vbslib_mini.vbs → sample without vbslib.vbs 関連 → VBScript - 常に cscript.exe で実行する (コマンドプロンプトを出す) *********************************************************************** <<< g_is_cscript_exe >>> *********************************************************************** g_is_cscript_exe (src) Dim g_is_cscript_exe as boolean コマンドライン(cscript.exe)で実行しているかどうか *********************************************************************** <<< g_admin >>> *********************************************************************** g_admin (src) Dim g_admin as integer 起動時に管理者へログインするのかしないのか 0 = 起動時に管理者へログインしない 1 = 起動時に管理者へログインする 通常、 sudo を使ってください。 に記述します。 g_admin の設定値は、メインの .vbs ファイルの中の SetupVbslibParameters Windows XP では、制限ユーザーから管理者へログインする設定にすると、起動時に管理者の パスワードを入力するようになります。 自分が管理者であるときは、入力を求められません。 Windows Vista/7 では、vbs ファイルをダブルクリックした直後に、昇格の確認が求められます。 Windows XP では、管理者のユーザ名を Setting_getAdminUserName に設定してください テスト → [T_Admin] 参考 → IShellDispatch2::ShellExecute の runas → アカウント 関連 → sudo *********************************************************************** <<< g_is_admin >>> *********************************************************************** g_is_admin (src) Dim g_is_admin as boolean 管理者のグループに入っているかどうか。 Windows Vista 以降では、UAC を確認した後で true になります。 *********************************************************************** <<< g_is64bitWindows >>> *********************************************************************** g_is64bitWindows (src) Dim g_is64bitWindows as boolean スクリプトが動いている OS が、64ビットWindows かどうか。 関連 → 64ビットWindows (WOW64) → g_is64bitWSH *********************************************************************** <<< g_is64bitWSH >>> *********************************************************************** g_is64bitWSH (src) Dim g_is64bitWSH as boolean スクリプトを動かすホスト、または、動いているホストが、64ビット WSH かどうか。 64ビット Windows では、vbslib を使うスクリプトは 64ビット版 WSH で起動され、起動直後に 32ビット WSH に切り替わりますが、SetupVbslibParameters 関数の中で、 g_is64bitWSH = True と設定すると、64ビット Windows では、64ビット WSH にのままなります。 ただし、メイン.vbs の最後にある vbslib include の中に Dim g_is64bitWSH が記述されている 必要があります。 参考: vbslib Prompt.vbs の内容 Main 関数を呼び出した後は、g_is64bitWSH の値は、実際に動いている WSH のバージョンに 従った値になります。 32ビット Windows では、g_is64bitWSH の値は無視されます。 g_is64bitWindows = True g_is64bitWindows = False g_is64bitWSH = True %windir%\System32\cscript.exe - g_is64bitWSH = False %windir%\SysWOW64\cscript.exe %windir%\System32\cscript.exe サンプル If g_is64bitWindows = g_is64bitWSH Then cscript_exe = env("%windir%\System32\cscript.exe") Else cscript_exe = env("%windir%\SysWOW64\cscript.exe") End If 関連 → 32ビットWindows と 64ビットWindows の WSH → g_is64bitWindows *********************************************************************** <<< ファイルまたはフォルダのパス >>> *********************************************************************** ファイルまたはフォルダのパス *********************************************************************** <<< g_start_in_path >>> *********************************************************************** g_start_in_path (src) Dim g_start_in_path as string プロセス起動時のカレント・フォルダーのフル・パス。 vbslib ver4 以降では、main 関数を呼ばれたときのカレント・フォルダーは、メイン.vbs ファイルが あるフォルダーになります。 そのため、プロセス起動時のカレント・フォルダーは、g_start_in_path から取得する必要があります。 このように変更した理由は、書かれたスクリプトが、汎用コマンドとして使われることより、 スクリプトがあるフォルダーに対して固有の処理を行うことが多いためです。 g_start_in_path を変更すると、InputPath の基準フォルダーを変更することができます。 サンプル: cd g_start_in_path サンプル: Sub main2( Opt, AppKey ) Dim ds_:Set ds_= new CurDirStack pushd g_start_in_path : popd End Sub カレント・ディレクトリとスクリプトがあるディレクトリ コマンド・プロンプトから、プログラムを実行するときのパラメーターに、ファイルのパスを指定 するときは、カレント・ディレクトリからの相対パスを指定します。 たとえば、cl a.c のように cl コマンドに指定した a.c は、カレント・ディレクトリにある a.c ファイルを指しています。 このとき、cl.exe の実行ファイルは、環境変数 PATH で指定されたディレクトリのどこかにあり、 a.c は、cl.exe があるディレクトリにある a.c ファイルではありません。 しかし、この法則は、スクリプトを記述するときに問題になります。cl.exe のように使えるスク リプト script.vbs を開発したとしましょう。スクリプトから、cl a.c を実行するように記述するときは、 素直にcl a.c とスクリプトに記述するでしょう。 このとき、a.c は、スクリプトがあるフォルダー からの相対パスを指定するはずです。 カレント・ディレクトリからの相対パスではありません。 どういうことかというと、通常、カレント・ディレクトリは、スクリプトがあるディレクトリではなく、 スクリプトを起動したときのディレクトリのままになるのですが、これでは、他のフォルダーから スクリプトを起動したとき、a.c というファイルは、起動したときのカレント・ディレクトリにある a.c というファイルになってしまうのです。 起動したときのカレント・ディレクトリにある a.c を 意図してスクリプトを記述することなど、ほとんど無いので、カレント・ディレクトリが、起動した ときのカレント・ディレクトリであるという仕様は、扱いにくいのです。 vbslib4 では、main 関数を実行するときのカレント・ディレクトリは、スクリプトがあるディレク トリになっています。これにより、多くのケースで、スクリプトに記述したファイル、たとえば a.c が、意図したとおりのファイルを指定することになります。 一方で、起動したときのディレクトリは、g_start_in_path グローバル変数を参照するようになっ ています。 起動時のパラメーターに指定した相対パスは、g_start_in_path を基準とした絶対 パスに変換する必要があります。 しかし、多くの場合、それに気をつける必要はありません。 ショートハンド・プロンプトに対応したスクリプト(InputCommand 関数を使ったスクリプト)は、 自動的にコマンド・プロンプトから起動することもできるようになるのですが、そのときに、 パラメーターに指定した相対パスは、InputPath 関数で取得でき、それは、g_start_in_path から の相対パスであるとして、フル・パスを返すからです。 カレント・ディレクトリは、スクリプトがあるディレクトリがいいか、起動時のカレント・ディレクトリ がいいか、という話ではなく、どちらの相対パスも自動的に適切に扱えるように工夫されて いるのです。 テスト → [T_StartFromOther] スクリプトが無いフォルダーから起動したとき 関連 → InputPath *********************************************************************** <<< g_vbslib_path >>> *********************************************************************** g_vbslib_path (src) Dim g_vbslib_path as string vbs_inc.vbs をインクルードする前 vbs_inc.vbs の相対パス。 相対パスの基準は、すべてのスクリプトのベースフォルダなど。 にユーザが記述します。 インクルードする前の g_vbslib_path は、 SetupVbslibParameters vbs_inc.vbs をインクルードした後 vbs_inc.vbs のフル・パス *********************************************************************** <<< g_vbslib_folder >>> *********************************************************************** g_vbslib_folder (src) Dim g_vbslib_folder as string scriptlib フォルダのフル・パス。末尾に \ が付きます。 g_Ver の設定に関わらず、最初の scriptlib フォルダの親になります。 サンプル copy Left( g_vbslib_folder, Len( g_vbslib_folder ) - 1 ), "C:\NewScriptFolder" 関連 → g_vbslib_ver_folder → scriptlib フォルダー → g_vbslib_parent_folder → WriteVBSLibFooter *********************************************************************** <<< g_vbslib_ver_folder >>> *********************************************************************** g_vbslib_ver_folder (src) Dim g_vbslib_ver_folder as string vbs_inc_XXX.vbs があるフォルダのフル・パス。末尾に \ が付きます。 g_Ver の設定によって、フォルダパスは変わります。 関連 → scriptlib フォルダー → g_vbslib_folder *********************************************************************** <<< g_SrcPath >>> *********************************************************************** g_SrcPath (src) Dim g_SrcPath as string インクルードしているスクリプトファイル(.vbs)のフル・パス。 include や call_vbs や g_IncludePathes で、グローバル領域を実行しているとき、 だけ定義されます。 参考 → get_DefineInfoObject g_SrcPath のサンプルがあります → デバッガで開いているソースのパスを知る g_SrcPath のサンプルがあります *********************************************************************** <<< g_MainPath >>> *********************************************************************** g_MainPath (src) Dim g_MainPath as string メイン.vbs のスクリプトファイル(.vbs)のフル・パス。 *********************************************************************** <<< グローバル変数の初期化、後始末、g_InitializeModule、g_FinalizeModule >>> *********************************************************************** グローバル変数の初期化、後始末、g_InitializeModule、g_FinalizeModule (src) vbs_inc.vbs でインクルードするモジュールの中にあるグローバル変数は、下記のように 初期化関数を g_InitializeModule に設定してください。後始末が必要なら、g_FinalizeModule と g_FinalizeLevel を設定してください。 g_FinalizeLevel が小さいモジュールほど先に呼ばれます。 これらによって、グローバル変数の初期化や後始末の順番を制御します。 同じモジュールの中のオブジェクトの Class_Terminate が呼ばれる順番は、グローバル変数に 格納した順番と同じです。 参考 → Class_Terminate が呼ばれる順序 初期化関数で依存するモジュールがなくても、(モジュール).vbs をダブルクリックして、 文法チェックができます。 Setting_getIncludePathes にモジュールを登録して、vbs_inc.vbs をダブルクリックすると、 初期化、後始末のテストができます。 サンプル (TestScript.vbs) ' Global Variable Dim g_Test Function InitializeModule( ThisPath ) Set g_Test = new TestScript : ErrCheck : Set g_TestScriptGlobals.Test = g_Test End Function Dim g_InitializeModule Set g_InitializeModule = GetRef( "InitializeModule" ) Function FinalizeModule( ThisPath, Reason ) g_Test.Finish End Function Dim g_FinalizeModule: Set g_FinalizeModule = GetRef( "FinalizeModule" ) Dim g_FinalizeLevel: g_FinalizeLevel = 100 ' If smaller, called early 配列のグローバル変数 main より後のグローバル領域に、配列を宣言すると、main 関数終了後にエラーになることが あります。そのときは、下記のように SetupVbslibParameters の中で宣言してください。 '--- start of parameters for vbslib include ------------------------------- Dim g_LineOfThreadSwitch() *********************************************************************** <<< g_Finalizing >>> *********************************************************************** g_Finalizing (src) Dim g_Finalizing as boolean グローバル変数の後始末処理を行っているときかどうか。 参考 → グローバル変数の初期化、後始末、g_InitializeModule、g_FinalizeModule *********************************************************************** <<< vbslib_helper.exe >>> *********************************************************************** vbslib_helper.exe VBScript だけではできないが、C言語ではできる機能を実行するプログラムです。 vbslib の内部から必要に応じて自動的に起動されます。 vbslib_helper.exe ファイルは、 g_vbslib_ver_folder に格納してください。 ソース → vbslib_helper_src フォルダー *********************************************************************** <<< 処理フロー (vbs_inc/setting) >>> *********************************************************************** [ 親: vbs_inc ] [ 親: setting フォルダ ] 処理フロー (vbs_inc/setting) VBScript global code [メイン.vbs] '// start of vbslib include Execute g_f.ReadAll [vbs_inc.vbs] VBScript global code Execute g_f.ReadAll [vbs_inc_sub.vbs] VBScript global code ChangeScriptMode (src) 場合によっては コマンドプロンプトを起動する '//=== Make command line → cmd.exe → g_CommandPrompt g_sh.Run cmd setting フォルダー '//=== Load setting script (src) 設定ファイルをロード(実行)する scriptlib フォルダー '//=== read and execute g_IncludePathes Setting_getIncludePathes モジュールをロード(実行)する CallInitializeInModules InitializeModule モジュールの初期化をする Setting_onAfterInclude あるフォルダの中あるすべてのスクリプトの既定の設定 ResumePush On Error Resume Next main / main2 メイン・スクリプト ResumePop → 詳細 → 正常終了時の動作 → エラー発生時の動作 CallFinalizeInModules (src) モジュールの後始末をする WScript.Echo Err.Description エラーメッセージを表示する If g_CommandPrompt = 1 Then WScript.Sleep 2000 関連 → エラーが発生して終了するとき → 処理フロー (Err2) *********************************************************************** <<< 正常終了時の動作 >>> *********************************************************************** 正常終了時の動作 main 関数からそのまま返ると、エラーレベルは 21 になります。 これは、wscipt.exe, cscript.exe は、スクリプトの内部でエラーが発生しても、 エラーレベルは 0 になっており、正常に終了したかどうかを区別するためです。 エラーレベルを指定するときは、WScript.Quit を呼び出すか、g_ExitCode に設定してください。 /SuccessRet - メイクファイルから vbslib を使ったスクリプトを呼び出すとき コンパイルするときに使われることがあるメイクファイルは、起動したコマンドのエラーレベルが 0 ではないときは、エラーが発生したものとみなしますが、vbslib を使ったスクリプトが正常終了した ときは、エラーレベルが 21 になるため、メイクファイルは処理を中断してしまいます。 正常終了したときに、エラーレベルが 0 になるようにするには、/SuccessRet:0 オプションを指定して vbs を起動してください。 ただし、ごくまれに vbslib がキャッチ できないエラーが発生することがありますが、そのときは、エラーレベルが 0 になるため、 正常終了と区別することはできません。 cscript sampe.vbs /SuccessRet:0 テスト → [T_SuccessRet] /SuccessRet オプションによるエラーレベル 内部フロー main ResumePop (src) CallFinalizeInModules If not IsEmpty( g_ExitCode ) Then WScript.Quit g_ExitCode WScript.Quit 21 関連 → g_CommandPrompt コマンドプロンプトを自動的に閉じるかどうか *********************************************************************** <<< エラー発生時の動作 >>> *********************************************************************** エラー発生時の動作 (src) main 関数の中でエラーが発生したら、標準化されたエラーメッセージを表示し、 適切なエラーレベルを、wscript.exe / cscript.exe を呼び出したプロセスへ返します。 → エラーメッセージ文字列の標準書式(XML版) wscipt.exe, cscript.exe は、スクリプトの内部でエラーが発生しても、エラーレベルは 0 になっています。 これではエラーが発生したかどうかがわからないので、vbs_inc がエラーをキャッチして、エラー番号をエラーレベルにします。 文法エラーが発生したときは、エラーレベルが 1 になります。 関連 → 正常終了時の動作 → 終了、返り値(エラーレベル)を指定する (VBScript) → 警告して終了するには → CheckTestErrLevel *********************************************************************** <<< バージョン判定、環境変数 >>> *********************************************************************** バージョン判定、環境変数 インスタンスを特定する必要が無い どの設定ファイルを使うか、などを選択するときに、環境変数を使います。 一般的な設定値は、環境変数ではなく、 XML 形式などの設定ファイルや、 演算器的なオブジェクト の、どのバージョンを使うか、 静的オブジェクト・スクリプト・ファイル を使ったほうが、階層化できたりして扱いやすいです。 設定値を指定するときは、main または デフォルト(自動判定など)の設定値を使うときは、SetVar を使いません。 優先度の高いものから並べると、main 関数の SetVar > setting の SetVar > OS の環境変数 > 自動選択、の順になります。 Setting_getIncludePathes で SetVar を使います。 関連 → set_ OS の環境変数の設定 → FuncRedir_add 関数コールのリダイレクト → LoadEnvVars ファイルに書かれた環境変数の集合を使う → TestCommon_setVariables Test.vbs で共通の環境変数とファイルのチェック → GetMainSetting 関数 (vbsool) スクリプト内で共通の設定値 処理フロー VBScript global code [メイン.vbs] 1つのスクリプトで使う InitializeModule で設定される内容の選択 g_Vers.Add "Disable", 1 環境変数 VBScript global code [vbs_inc_sub.vbs] Setting_getIncludePathes あるフォルダの中にある スクリプトの InitializeModule で 設定される内容の選択 g_Vers.Add "Disable", 1 InitializeModule → モジュールのグローバル変数の初期化 全スクリプト共通の既定の設定 (全 scriptlib フォルダ) SetVar Setting_onAfterInclude [vbs_inc_setting.vbs など] → setting フォルダ あるフォルダの中にあるスクリプトの 既定の設定(scriptlib フォルダごと) SetVar main / main2 SetVar 1つのスクリプトで使う設定 new ClassA Class_Initialize Me.Ver = CInt2( GetVar( "ClassA_Ver" ) ) If IsEmpty( Me.Value ) Then Me.Ver = 200 数値を自動的に 設定する ClassI_validate インスタンスを 自動的に 選択する If IsEmpty( g_ClassI ) Then Dim name : name = GetVar( "ClassI" ) If IsEmpty( name ) Then ... (自動判定ルーチン) name = "ClassA" End If Select Case name Case "ClassA" : Set g_ClassI = new ClassA Case "ClassB" : Set g_ClassI = new ClassB End Select Set ClassI_validate = g_ClassI End If デフォルト値の決定方法は、 次のものがあります。  ・固定値  ・設定ファイルからのリード  ・自動判定 環境変数の値を使った後は、SetVar をしても無効なので、SetVar は main 関数の 最初で呼び出してください。 関連 → 環境変数を取得する (VBScript) *********************************************************************** <<< IsDefined >>> *********************************************************************** [ 親: バージョン判定 ] IsDefined (src) Function IsDefined( Symbol as string ) as boolean 指定したシンボルの関数が定義されているかどうかを返します。 サンプル: If not IsDefined( "copy" ) Then ... ソース → vbs_inc_sub.vbs 参考 → GetRef 関連 → CheckSettingFunctionExists *********************************************************************** <<< g_Vers >>> *********************************************************************** [ テスト ] [ 親: バージョン判定 ] g_Vers (src) Dim g_Vers as Scripting.Dictionary 各種バージョン番号、または、設定に関する辞書です。 辞書のキーは、左にあるツリーの子ノードを参照してください。 例: → g_Vers("vbslib") → g_Vers("TextFileExtension") 値は文字列や数値やオブジェクトなどを格納できます。 SetVar で設定される変数と同じ変数の領域(Dictionary)です。 (vbslib ver4 より) VarStack を使うことができます。 関連 → VarStack *********************************************************************** <<< g_Vers("vbslib") >>> *********************************************************************** g_Vers("vbslib") Dim g_Vers("vbslib") as dictionary vbslib のバージョン番号です。 設定サンプル Sub SetupVbslibParameters() '--- start of parameters for vbslib include ------------------------------- g_Vers("vbslib_ver") = 99.99 : '--- end of parameters for vbslib include --------------------------------- End Sub 値の意味 0.0 … バージョン切り替えテスト用 2.0 … ver2.00 をそのまま使う (vbs_inc のデフォルト) 3.0 … ver3.00 を使う 4.0 … ver4.00 を使う 99.99 … 最新を使う vbs_inc.vbs から vbslib をインクルード開始する時点で、実際に使用するバージョン 番号に変わります。 それまでは、メイン.vbs が要求する番号です。 上記のように決めていますが、実際の動きは下記の vbs_inc.vbs の内容によります。 判定サンプル vbs_inc.vbs の一部 g_f = g_Vers.Item("vbslib") If g_f >= 4.9 Then g_Vers.Item("vbslib") = 4.9 g_vbslib_path = g_vbslib_folder + "vbslib\vbs_inc_sub.vbs" ElseIf g_f >= 4.0 Then g_vbslib_path = g_vbslib_folder + "vbslib400\vbs_inc_400.vbs" ElseIf g_f >= 3.0 Then g_vbslib_path = g_vbslib_folder + "vbslib300\vbs_inc_300.vbs" ElseIf g_f >= 2.0 Then g_vbslib_path = g_vbslib_folder + "vbs_inc_200.vbs" Else g_vbslib_path = g_vbslib_folder + "vbslib000\vbs_inc_000.vbs" End If バージョンの判定は、不等号を使ってください。 参考 → vbslib をバージョンアップする テスト → T_Var.vbs # T_g_Vers_Stack *********************************************************************** <<< TextFileExtension (g_Vers) >>> *********************************************************************** TextFileExtension (g_Vers) << g_Vers Dim g_Vers("TextFileExtension") as dictionary テキスト・ファイルの拡張子をキーとした辞書。 大文字と小文字を区別しません。 サンプル テキスト・ファイルの拡張子であるか判断する。 If g_Vers("TextFileExtension").Exists( "xml" ) Then extension = g_fs.GetExtensionName( path ) If g_Vers("TextFileExtension").Exists( extension ) Then サンプル 辞書を作成する Set g_Vers("TextFileExtension") = Dic_addFromArray( Empty, Array( _ "txt", _ "c", "h", "cpp", "hpp", "vbs", "js", "py", "rb", _ "ini", "log", _ "html", "htm", "xml", "svg" ), True ) Dic_addFromArray setting フォルダー の PC_setting_default.vbs などで設定します。 ソース → PC_setting_default.vbs テスト → T_Path.vbs T_TextFileExtension 関連 → IsSameBinaryFile → IsSameTextFile *********************************************************************** <<< NaturalDocsExtension (g_Vers) >>> *********************************************************************** NaturalDocsExtension (g_Vers) Dim g_Vers("NaturalDocsExtension") as dictionary NaturalDocs に入力できるファイルの拡張子をキーとした辞書。 MakeDocumentByNaturalDocs で使われます。 この辞書が setting フォルダー にないときは、デフォルトの設定を使って処理されます。 この辞書の使い方は、 g_Vers("TextFileExtension") と同じです。 *********************************************************************** <<< CutPropertyM (g_Vers) >>> *********************************************************************** CutPropertyM (g_Vers) キーワード: Name, m_Name << g_Vers Dim g_Vers("CutPropertyM") as string True なら Name プロパティを、False なら m_Name プロパティを使います。 ライブラリが提供するいくつかの関数の中で使われるオブジェクトに対して、Name プロパティを 参照するか、m_Name プロパティを参照するかを選べます。 デフォルトは、True です。 サンプル g_Vers("CutPropertyM") = False 関連 → Dic_addNewObject *********************************************************************** <<< g_is_vbslib_for_fast_user >>> *********************************************************************** g_is_vbslib_for_fast_user Dim g_is_vbslib_for_fast_user as boolean メジャー バージョンアップで採用される予定の暫定機能を使うかどうか。 暫定機能の仕様は変わる可能性があります。 この変数は、通常 PC全体の setting フォルダー で設定します。 サンプル → _src\Test\FastUser.vbs サンプル 暫定機能 Sub NewFunction() Confirm_VBS_Lib_ForFastUser '// Function End Sub Empty のときは、 Confirm_VBS_Lib_ForFastUser でユーザーに確認が求められます。 サンプル 暫定機能のテスト プログラムは、スキップします。 Sub T_NewFunction( Opt, AppKey ) If g_is_vbslib_for_fast_user Then '// Test End If Pass End Sub サンプル 内部の修正で暫定機能を使うようになったとき、一時的に有効にします。 is_fast_back_up = g_is_vbslib_for_fast_user g_is_vbslib_for_fast_user = True '// 暫定機能 g_is_vbslib_for_fast_user = is_fast_back_up *********************************************************************** <<< Confirm_VBS_Lib_ForFastUser >>> *********************************************************************** Confirm_VBS_Lib_ForFastUser Sub Confirm_VBS_Lib_ForFastUser() メジャー バージョンアップで採用される予定の暫定機能を使うことをユーザーに確認します。 暫定機能の仕様は変わる可能性があります。 OK を押すと g_is_vbslib_for_fast_user = True に設定して処理を継続します。 g_is_vbslib_for_fast_user = True のときは、ユーザーに確認しません。 ソース → vbslib.vbs *********************************************************************** <<< ThisIsOldSpec >>> *********************************************************************** ThisIsOldSpec (src) Sub ThisIsOldSpec() 現在実行している関数が、廃止されようとしている関数であることを警告します。 ファイル: vbs_inc_sub.vbs g_debug <> 0 のときは、初めて ThisIsOldSpec を呼び出したときにブレークします。 関連 → SetErrorOfOldSpec *********************************************************************** <<< g_cut_old >>> *********************************************************************** [ 親: バージョン判定 ] g_cut_old (src) g_cut_old は、廃止されました。 代わりに ThisIsOldSpec を使ってください。 → ThisIsOldSpec Dim g_cut_old as boolean vbslib の古い関数を呼び出したときに、デバッガでブレークするようにします。 vbslib のユーザーのサンプル: g_cut_old = True vbslib の作成者のサンプル: If g_cut_old Then Stop :If g_cut_old=I_CutOldErr Then Error デフォルトは True になります。 False にするには、 SetupVbslibParameters に次のように記述してください。 '--- start of parameters for vbslib include ------------------------------- Dim g_cut_old : g_cut_old = False 参考 → vbslib2 から vbslib3 へバージョンアップする *********************************************************************** <<< SetErrorOfOldSpec >>> *********************************************************************** SetErrorOfOldSpec (src) Sub SetErrorOfOldSpec() ThisIsOldSpec が呼ばれたら、エラーにするように設定します。 ファイル: vbs_inc_sub.h 関連 → ThisIsOldSpec *********************************************************************** <<< SetNotErrorOfOldSpec >>> *********************************************************************** SetNotErrorOfOldSpec (src) Sub SetNotErrorOfOldSpec() ThisIsOldSpec が呼ばれても、エラーにしないように設定します。 ファイル: vbs_inc_sub.h 関連 → ThisIsOldSpec *********************************************************************** <<< GetOSVersion >>> *********************************************************************** [ 親: バージョン判定 ] GetOSVersion (src) Function GetOSVersion() as double Windows の内部バージョンを返します。 5.0 = Windows 2000 5.1 = Windows XP 6.0 = Windows Vista 6.1 = Windows 7 6.2 = Windows 8 6.3 = Windows 8.1 10 = Windows 10 関連 → g_is64bitWindows → g_is64bitWSH *********************************************************************** <<< set_, SetVar >>> *********************************************************************** set_, SetVar (src) (src) [ 親: 環境変数 ] Sub set_( Symbol as string, Value as string ) Sub SetVar( Symbol as string, Value as variant ) vbslib の環境変数を設定します。 【引数】 Symbol 変数名 Value 設定する値、Empty = 変数を未定義にする サンプル: set_ "FooVar", "1" OS の環境変数 SetVar "FooVar", 1 ローカル環境変数 (vbslib が持つ辞書) set_ は、OS の環境変数には設定されます。 SetVar は、OS の環境変数には設定されません。そのため、RunProg などで 子プロセスを起動しても、伝達されません。 その代わり、文字列以外(数値や配列など)を設定することができます。 set_ も SetVar も、env を使って参照することができます。 set_ を実行すると、同じ名前のローカル環境の変数が削除されます。(2016-08-18より) 注意 環境変数はグローバル変数と同じなので、なるべく使わないでください。 下記のいずれかが使用できないか検討してください。 ・オブジェクトのメソッド、プロパティ ・設定関数 ・setting フォルダ, setting_default フォルダ テスト → T_Var フォルダ 関連 → GetVar → VarStack → SetVarBreak → env → RunBat → clib の環境変数 → Environment (Shell) → 条件ブレーク → SetDefaultEnvironmentVariables → AddIfNotExist PATH 環境変数の追加 → GetMainSetting 関数 (vbsool) テスト → [T_Var] vbslib の環境変数のテスト → T_Var フォルダ *********************************************************************** <<< GetVar >>> *********************************************************************** GetVar (src) [ 親: 環境変数 ] Function GetVar( Symbol as string ) as variant vbslib の環境変数の値を返します。 【引数】 Symbol 変数名 返り値 Symbol に指定した環境変数の値 サンプル: v = GetVar( "FooVar" ) 値を設定していない環境変数を指定したときは、エラーが発生するのではなく、Empty を返し ます。 OS の環境変数を指定することもできます。 変数名に % を付けたものを指定した場合、% が無い変数名の値が返ります。 GetVar( "FooVar" ) = GetVar( "%FooVar%" ) テスト → T_Var フォルダ T_Var1 T_Var2 関連 → SetVar → SetVarBreak → env → 条件ブレーク *********************************************************************** <<< SetVarBreak >>> *********************************************************************** SetVarBreak (src) [ 親: 環境変数 ] Sub SetVarBreak( Symbol as string, Opt as Empty ) vbslib の環境変数の値を設定、または参照しているところでブレークするように設定します。 【引数】 Symbol 変数名 Opt Empty を指定してください サンプル: SetVarBreak "FooVar", Empty 関連 → SetVar → GetVar → env *********************************************************************** <<< VarStack >>> *********************************************************************** VarStack (src) [ 親: 環境変数 ] オブジェクトが破棄されるタイミングで、環境変数の値を元に戻します。 下記の場合、関数から抜けると戻します。 Sub FuncA() Set v_= new VarStack set_ "Foo2", "2a" SetVar "Foo3", 3 g_Vers "Foo4", 1 End Sub '// 元の環境変数の値に戻る set_ SetVar g_Vers *********************************************************************** <<< LoadEnvVars >>> *********************************************************************** LoadEnvVars (src) [ 親: 環境変数 ] Sub LoadEnvVars( Path_ofSetCommandLog, Option_ ) ファイルを参照して、複数の環境変数を現在のプロセスに設定します。 【引数】 Path_ofSetCommandLog 環境変数の設定の一覧のファイルパス、または辞書 Option_ Empty または F_Append または辞書 今まで設定されていた環境変数のうち、Path_ofSetCommandLog のファイルに記述されて いない環境変数は、削除されます。 ただし、Option_ = F_Append にすると削除されません。 サンプル 環境変数全体を、ファイルに記述された値に設定します。 LoadEnvVars "settings.txt", Empty setting.txt VAR1=value1 VAR2=3 VAR3=cmd setting.txt は、コマンドプロンプトの set (Enter) で出力される内容と同じフォーマットです。 VBScript では、下記のように記述します。 g_sh.Run "cmd /C (set > ""C:\folder\settings.txt"")",, True サンプル 環境変数全体を、辞書に入っている内容に設定します。 Set dic = CreateObject( "Scripting.Dictionary" ) dic.Item( "VAR1" ) = "value1" dic.Item( "VAR2" ) = "3" LoadEnvVars( dic, Empty ) サンプル ファイルに入っている環境変数の設定を、辞書に格納する Set envs = CreateObject( "Scripting.Dictionary" ) LoadEnvVars "settings.txt", envs Option_ 引数に辞書オブジェクトを渡すと、その辞書オブジェクトの内容が変わるだけで、 環境変数の値は変わりません。 参考 → デフォルトの環境変数の設定タイミング テスト → T_Var.vbs # T_LoadEnvVars 関連 → SaveEnvVars → ClearEnvVars → Dic_add *********************************************************************** <<< SaveEnvVars >>> *********************************************************************** SaveEnvVars (src) [ 親: 環境変数 ] Sub SaveEnvVars( Path_ofSetCommandLog, Option_ ) 現在の環境変数をファイルに保存するか、辞書に格納します。 【引数】 Path_ofSetCommandLog ファイルパス、または辞書、または Empty Option_ Empty 固定 Path_ofSetCommandLog に、値が入っていない(Empty の)変数を指定したら、 内部で Dictionary オブジェクトを生成して、その中に環境変数の設定値を 格納します。 サンプル: Dim envs SaveEnvVars envs, Empty '//[out] envs echo envs LoadEnvVars envs, Empty テスト → T_Var.vbs # T_LoadEnvVars 関連 → VarStack *********************************************************************** <<< ClearEnvVars >>> *********************************************************************** ClearEnvVars (src) [ 親: 環境変数 ] Sub ClearEnvVars() 現在のプロセスの環境変数をほぼすべて削除します。 VBScript から削除できない環境変数は残ります。 テスト → T_Var.vbs # T_LoadEnvVars *********************************************************************** <<< OpenForEnvVarsFile >>> *********************************************************************** OpenForEnvVarsFile (src) Function OpenForEnvVarsFile( EnvVarsFilePath as string ) as EditEnvVarsFile 環境変数ファイルを編集します。 【引数】 EnvVarsFilePath 環境変数ファイルのパス 返り値 EditEnvVarsFile オブジェクト サンプル: Dim f : Set f = OpenForEnvVarsFile( "settings.txt" ) echo f.get_( "VAR_A" ) f.set_ "VAR_A", "1" f.select_ "VAR_A", "1", Array( "VAR_A", "VAR_B", "VAR_C" ), "0" f = Empty '// Write settings.txt VAR_A VAR_A 1 VAR_A 1 ランダムアクセスに対応しています。 OpenForRead や OpenForWrite のように シーケンシャル(ファイルの先頭から順番)にアクセスする必要はありませんし、 変更しないキーまで Write する必要はありません。 存在しない環境変数を新規に set_ したときは、ABC 順でファイルに記述されます。 Empty の値を set_ すると、その環境変数はファイルから削除されます。 関連 → OpenForRegFile テスト → T_VarFile.vbs # [T_VarFile1] *********************************************************************** <<< EditEnvVarsFile クラス >>> *********************************************************************** EditEnvVarsFile クラス 関連 → OpenForEnvVarsFile .Path Property .Path as string .set_ Sub .set_( Name as string, Value as string or Empty ) .get_ Function .get_( Name as string ) as string Name が定義されていないときは、Empty を返します .select_ Sub select_( Name as string, Value as string, OtherNames as array of string, OtherValue as string ) *********************************************************************** <<< SetVarInBatchFile >>> *********************************************************************** SetVarInBatchFile Sub SetVarInBatchFile( Path as string, Symbol as string, Value as variant ) バッチ・ファイルの中で、環境変数を設定している部分の値を変更します。 【引数】 Path バッチ・ファイルのパス Symbol 環境変数の名前 Value 環境変数の値 ソース → vbslib.vbs テスト → T_VarFile.vbs T_SetVarInBatchFile *********************************************************************** <<< Start_VBS_Lib_Settings >>> *********************************************************************** Start_VBS_Lib_Settings Sub Start_VBS_Lib_Settings() エディター等の設定を変更する Setting コマンド を起動します。 ソース → vbslib.vbs → SettingTemplate.xml *********************************************************************** <<< エラー処理 (Err2) >>> *********************************************************************** [ テスト ] エラー処理 (Err2) → Err2 のコーディング例 (TryStart, TryEnd) → エラーメッセージを表示して、エラー状態から復帰し、 続きを実行する → エラーの内容を変えて、再度エラーを発生させる → エラーメッセージをチェックするテスト → Err2 オブジェクト → エラーコード → Error 未知のエラーを発生させます。 → Raise 新規にエラーを発生させます。 → Warning 警告を表示してプロセスを終了します。 → FinObj クラス Finally ブロックに似た記述をする → エラーメッセージ文字列の標準書式 → エラー発生時の動作 → Err2 の処理フロー テスト → T_Err2 フォルダ → [T_Err2] Err2 オブジェクトのテスト 関連 → エラー処理 (Err 版) *********************************************************************** <<< Err2 のコーディング例 (TryStart, TryEnd) >>> *********************************************************************** Err2 のコーディング例 (TryStart, TryEnd) Try ブロックの中が、1行だけのとき Dim e ' as Err2 If TryStart(e) Then On Error Resume Next ... If TryEnd Then On Error GoTo 0 If e.num = E_FileNotExist Then ... : e.Clear If e.num <> 0 Then e.Raise Err2 TryStart TryEnd E_FileNotExist Clear Raise 関連 → エラーメッセージをチェックするテスト エラーをキューにためる → EnqueueAndClear (Err2) クリアしたエラーが発生した場所を調べるときは、クリアする代わりに Err2::Raise してください。 Try ブロックの中が、複数行のとき Dim e ' as Err2 If TryStart(e) Then On Error Resume Next If Trying Then ... If Trying Then ... If TryEnd Then On Error GoTo 0 If e.num = E_FileNotExist Then ... : e.Clear If e.num <> 0 Then e.Raise Err2 TryStart TryStart Trying Trying TryEnd E_FileNotExist Clear Raise Trying は、毎行記述する必要があります。 エラーが発生しても、TryStart〜TryEnd の間で続きを実行する場合は、 Trying は不要です。 Try ブロックの中で発生したエラーでブレークさせるとき If g_count_up(1)=0 Then Stop '// watch-> g_count [TODO] echo "g_count(1)=" & g_count(1) If g_count(1) < 99 Then If TryStart(e) Then On Error Resume Next End If 参考 → g_count, g_count_up TryStart を使うと、エラーが発生した場所で、ブレークさせることができます。 On Error Resume Next を呼び出したらブレークしなくなるので、TryStart が、 On Error Resume Next を呼び出すべきかどうかを判定します。 ブレークさせるときは、Err2::BreakErrID を設定してください。 → Err2::BreakErrID サンプル → _err2_test.lzh 関連 → メンバ変数 (Err2) → エラー処理 (Err 版) *********************************************************************** <<< Err2 オブジェクト >>> *********************************************************************** Err2 オブジェクト (src) 関連 → Err オブジェクト → Err2 のコーディング例 (TryStart, TryEnd) 取得, g_Err2 TryStart を呼び出すと、Err2 オブジェクトを取得できます。 また、g_Err2 グローバル変数からアクセスすることもできます。 Dim g_Err2 as Err2 メンバ変数 Public Number ' Err.Number Public num ' Err.Number Public Description ' Err.Description (Error Message) Public desc ' Err.Description (Error Message) Public Source ' Err.Source Public ErrID ' count of (num <> 0) in each first Copy after Clear Public RaiseID ' count of (num <> 0) in Copy Public BreakErrID ' as integer Public BreakRaiseID ' as integer メンバ関数 .Copy err オブジェクトの内容をコピーします。 .Raise 同じ内容のエラーを再度発生させる。 .OverRaise エラーの内容を変えて、再度エラーを発生させる。 .Clear エラーをクリアする。 他にもあります。 テスト → [T_Err2] Err2 オブジェクトのテスト → T_Err2 フォルダ *********************************************************************** <<< Number (Err2) >>> *********************************************************************** Number (Err2) → Err2 オブジェクト num (Err2) Property Get Err2::Number() as integer Property Get Err2::num() as integer エラーコード。 エラー状態でなければ、0 になります。 *********************************************************************** <<< Description (Err2) >>> *********************************************************************** Description (Err2) → Err2 オブジェクト desc (Err2) Property Get Err2::Description() as string Property Get Err2::desc() as string エラー・メッセージ。 サンプル エラーメッセージを表示して、エラー状態から復帰し、 続きを実行する Dim e ' as Err2 If TryStart(e) Then On Error Resume Next ... If TryEnd Then On Error GoTo 0 If e.num <> 0 Then echo_v "Error 0x"+ Hex( e.num ) +": "+ e.Description e.Clear End If Clear 復帰する前にエラーが発生した場所でブレークするには、Clear の前に Raise を追加してください。 echo_v "Error 0x"+ Hex( e.num ) +": "+ e.Description e.Raise e.Clear Raise *********************************************************************** <<< ErrStr (Err2) >>> *********************************************************************** ErrStr (Err2) → Err2 オブジェクト Property Get Err2::ErrStr() as string XML形式のエラーメッセージ。 エラーメッセージの例: 関連 → エラーメッセージ文字列のXML書式 *********************************************************************** <<< GetErrStr (Err2) >>> *********************************************************************** GetErrStr (Err2) (src) 廃止されました → ErrStr (Err2) Function Err2::GetErrStr() as string 標準形式のエラーメッセージを返す。 エラーメッセージの例: 関連 → エラーメッセージ文字列の標準書式(XML版) *********************************************************************** <<< DebugHint (Err2) >>> *********************************************************************** DebugHint (Err2) → Err2 オブジェクト Property Get Err2::DebugHint() as string エラーの内容とデバッグのヒント。 サンプル: If TryStart(e) Then On Error Resume Next ... If TryEnd Then On Error GoTo 0 If e.num <> 0 Then echo e.DebugHint : e.Clear エラーメッセージの例: 下記のファイルをテキストエディタで開いて次のように変数の値を修正すると、 デバッガに接続して問題がある場所で停止します。 "T_Err2_Clear.vbs" ------------------------------------------------------------------ g_debug = 2 ------------------------------------------------------------------ テスト → T_InputCommand.vbs # T_InputCommand_ForgetClear *********************************************************************** <<< Value (Err2) >>> *********************************************************************** Value (Err2) (src) 廃止されました → DebugHint (Err2) Function Err2::Value() as string エラーの内容を文字列型で返します。 *********************************************************************** <<< Copy (Err2) >>> *********************************************************************** Copy (Err2) (src) Sub Err2::Copy( err as Err ) err オブジェクトの内容をコピーします。 *********************************************************************** <<< Raise (Err2) >>> *********************************************************************** Raise (Err2) (src) Sub Err2::Raise() 同じ内容のエラーを再度発生させる。 *********************************************************************** <<< OverRaise (Err2) >>> *********************************************************************** OverRaise (Err2) (src) Sub Err2::OverRaise( e_num as integer, e_desc as string ) エラーの内容を変えて、再度エラーを発生させる。 サンプル Dim e ' as Err2 If TryStart(e) Then On Error Resume Next ... If TryEnd Then On Error GoTo 0 If e.num <> 0 Then If Right( e.Description, 2 ) = "/>" Then message = Left( e.Description, Len( e.Description ) - 2 ) + _ " msg2=""追加メッセージ。""/>" e.OverRaise e.Number, message Else e.Raise End If End If エラーが発生して、そのエラーメッセージが XML 形式なら、属性 msg2="追加メッセージ。" を追加します。 関連 → AppendErrorMessage *********************************************************************** <<< Clear (Err2) >>> *********************************************************************** Clear (Err2) (src) Sub Err2::Clear() エラーをクリアする。 エラー処理が終わったことを示すため、メンバ変数をリセットします。 num = 0 : Description = "" : RaiseID = 0 関連 → GetErrStr (Err2) エラーメッセージを取得する → CopyAndClear (Err2) エラーの情報コピーしてクリアする *********************************************************************** <<< CopyAndClear (Err2) >>> *********************************************************************** CopyAndClear (Err2) (src) Sub Err2::CopyAndClear( out_e2 as Err2 ) エラーの情報を out_e2 にコピーしてから Err2 のエラーをクリアします。 内部で Err2 オブジェクトが生成されて、out_e2 に格納されます。 CopyAndClear した後でエラーが発生した場合、テストによるエラーであると判断して、 次のようなメッセージが表示されます。 '//エラーが発生した場所を知るには、CopyAndClear する前に Raise してください。 次のように Raise するコードを追加してください。 また、 /g_debug オプション を設定していたら、設定を無効にしてください。 '//=== Error Handling Test echo vbCRLF+"Next is Error Test" If TryStart(e) Then On Error Resume Next Test '// ここでエラーが発生する If TryEnd Then On Error GoTo 0 e.Raise '// これを追加する e.CopyAndClear e2 '//[out] e2 Assert e2.num <> 0 '// テストによるエラーが発生した場所 e.Raise 参考 → エラーメッセージをチェックするテスト テスト → T_Err2_Main.vbs # T_Err2_CopyAndClear *********************************************************************** <<< EnqueueAndClear (Err2) >>> *********************************************************************** EnqueueAndClear (Err2) (src) Sub Err2::EnqueueAndClear() エラーの情報を Err2 の内部キューに入れてから Err2 のエラーをクリアします。 サンプル Dim e ' as Err2 If TryStart(e) Then On Error Resume Next Err.Raise 1,, "Error1" If TryEnd Then On Error GoTo 0 e.EnqueueAndClear If not IsEmpty(e) Then s = e.DequeueAll() : If s <> "" Then Raise 1, s EnqueueAndClear DequeueAll テスト → T_Err2_Main.vbs # T_Err2_EnqueueAndClear *********************************************************************** <<< DequeueAll (Err2) >>> *********************************************************************** DequeueAll (Err2) (src) Function Err2::DequeueAll() as string Err2 の内部キューの内容を返し、内部キューを空にします。 エラーがキューに入っていないときは、"" を返します。 XML 書式のエラーメッセージを取得したいときは、ルート要素(タグ)を追加する 必要があるか検討してください。 サンプル返り値 参考 → EnqueueAndClear (Err2) テスト → T_Err2_Main.vbs # T_Err2_EnqueueAndClear *********************************************************************** <<< ErrID (Err2) >>> *********************************************************************** ErrID (Err2) Dim Err2::ErrID as integer エラーの通し番号。 エラーが発生して初めての TryEnd を通ったとき +1 されます。 Err2::Clear した後で、次のエラーが発生すると +1 されます。 関連 → Err2::BreakErrID *********************************************************************** <<< RaiseID (Err2) >>> *********************************************************************** RaiseID (Err2) Dim Err2::RaiseID as integer エラーの通し番号。 エラーが発生して TryEnd を通るたびに +1 されます。 Err2::Clear で 0 に戻ります。 *********************************************************************** <<< BreakErrID (Err2) >>> *********************************************************************** BreakErrID (Err2) Dim Err2::BreakErrID as integer デバッガでブレークするエラーの通し番号。 通常、 vbslib.vbs をインクルードしたら、g_Err2::BreakErrID に設定されます。 g_debug に設定してください。 サンプル: '--- start of parameters for vbslib include ------------------- g_debug = 1.5 参考 → Err2 のコーディング例 (TryStart, TryEnd) エラーメッセージの前に g_debug を設定するように表示されます。 このメッセージに従って、 デバッガを起動すると、エラーが発生した場所でブレークします。 下記のファイルをテキストエディタで開いて次のように変数の値を修正すると、 デバッガに接続して問題がある場所で停止します。 "T_Err2_Clear.vbs" ------------------------------------------------------------------ g_debug = 2 ------------------------------------------------------------------ g_debug が小さすぎると、後で復帰するために問題の無いエラーでブレークします。 また、ブレークしたときはエラー復帰が行われなくなります。 とりあえずデバッガに接続したいときは、十分に大きい値を設定するか、0 に設定して エラーメッセージから必要な値を確認してください。 g_Err2.BreakErrID を 1.5 とすると、Err2::ErrID が 1 のときのエラーをキャッチする TryEnd または Trying でブレークします。 エラーが発生したら Err2::ErrID が+1されますが、Err2::ErrID = Err2::BreakErrID に なったら、エラーによってデバッガでブレークします。 次に Err2:ErrID が+1されるのは、 Err2::Clear した後にエラーが発生したときです。 それまでの Err.Raise では、Err2:ErrID ではなく、Err2:RaiseID が+1されます。 Pass (vbslib) は、エラーではありませんが、内部で Err.Raise を呼び出しているため、 Err2:ErrID が+1されます。 ただし、TryStart 〜 TryEnd の間ではないとき(On Error Next Resume を実行していない とき)にエラーが発生したときは、Err2::BreakErrID の値にかかわらず、エラーが発生したら 必ずエラーブレークします。 Visual Studio 2008 以降では、エラーが発生した場所からステップ実行することができます。 関連 → Err2::ErrID → 処理フロー (Err2) *********************************************************************** <<< エラーコード >>> *********************************************************************** エラーコード (src) 関連 → エラーメッセージ (VBS) → Windows エラーコード Dim E_Others : E_Others = 1 Dim E_TestPass : E_TestPass = 21 Dim E_TestSkip : E_TestSkip = 22 Dim E_TestFail : E_TestFail = 23 Dim E_BuildFail : E_BuildFail = &h80041004 Dim E_OutOfWritable : E_OutOfWritable = &h80041005 Dim E_NotFoundSymbol : E_NotFoundSymbol = &h80041006 Dim E_ProgRetNotZero : E_ProgRetNotZero = &h80041007 Dim E_Unexpected : E_Unexpected = &h80041008 Dim E_TimeOut : E_TimeOut = &h80041009 Dim E_WIN32_FILE_NOT_FOUND: E_WIN32_FILE_NOT_FOUND = &h80070002 Dim E_WIN32_DIRECTORY : E_WIN32_DIRECTORY = &h8007010B Dim E_ProgTerminated : E_ProgTerminated = &hC0000005 Dim E_BadType : E_BadType = 13 Dim E_FileNotExist : E_FileNotExist = 53 Dim E_EndOfFile : E_EndOfFile = 62 Dim E_WriteAccessDenied : E_WriteAccessDenied = 70 Dim E_ReadAccessDenied : E_ReadAccessDenied = 70 Dim E_PathNotFound : E_PathNotFound = 76 Dim E_AlreadyExist : E_AlreadyExist = 58 *********************************************************************** <<< [E_NotClear] エラー処理の途中で終了しました。Err2.Clear または再 Raise してください >>> *********************************************************************** [E_NotClear] エラー処理の途中で終了しました。Err2.Clear または再 Raise してください TryStart 〜 TryEnd でエラー処理するときの最後に必要な Err2::Clear または Err2::Raise が呼ばれないで、スクリプトが終了しました。 Err2::BreakErrID を設定して、エラーが発生した場所でブレークして、コールスタックを参照 して、TryStart 〜 TryEnd のエラー処理に、Err2::Clear または Err2::Raise を記述してください。 エラーメッセージ: 処理フロー VBScript global code (メインvbs の vbslib include) ResumePop CallFinalizeInModules 0 FinalizeModule (vbslib.vbs) (= g_FinalizeModules(i)) Err2.OnSuccessFinish echo GetErrStr( num, Description ) *********************************************************************** <<< エラーメッセージのXML書式 >>> *********************************************************************** エラーメッセージのXML書式 XML を使って、エラー情報を構造化します。 もしエラー情報の一部を取得したいときは、エラーメッセージ(Err2.Description) を LoadXML に渡してください。 参考 → Err2 オブジェクト >> *********************************************************************** Error (src) Sub Error() 簡易的にその他のエラーを発生させます。 コーディングが最も楽なエラー発生です。 その代わり、エラーの内容はユーザに 伝わりません。 cscript.exe のエラーレベルは 1 になります。 エラー値を返す API やライブラリは、少なくとも、正常に処理されたことを示す値 でなかったら、本関数を呼び出して、緊急停止させます。 想定済みのエラーであれば、ユーザがエラーに対応できるように、Raise などを 使ってエラー処理を実装してください。 想定外のエラーや開発者が発生させたことがないエラーは、本関数を呼び出して、 緊急停止させます。 関連 → Raise エラーを発生させる。 *********************************************************************** <<< OrError >>> *********************************************************************** OrError (src) Sub OrError() 子プロセスであっても、そのコードを実行したところでブレークできるようにします。 サンプル Stop:OrError 通常、上記のように Stop 命令と同時に使用します。 g_debug = 0 の状態で上記のコードを実行したときは、OnError 関数の中でエラーが発生します。 このエラーにより、このコードでブレークするために必要な設定が、エラーメッセージに表示され ます。 参考 → エラーが発生した瞬間のスクリプト内部の様子を調べる ブレークするために必要な設定を行って、スクリプトを再起動すると、Stop 命令によってブレーク します。 続いて実行される OnError 関数の中では何もしないので、続きをステップ実行できます。 *********************************************************************** <<< Raise >>> *********************************************************************** Raise (src) Sub Raise( ErrorNum as integer, Description as string ) 新規にエラーを発生させます。 【引数】 ErrorNum エラーコード Description エラーメッセージ サンプル Raise 1, "ファイルが見つかりません c:\a.txt" 参考 → エラーを発生させる(VBS) 関連 → Error 簡単に実装できるエラー発生 → GetErrStr 標準形式のエラーメッセージを返す。 → Assert 条件が満たされているかをチェックします。 → 警告して終了するには *********************************************************************** <<< Warning >>> *********************************************************************** Warning (src) Sub Warning( Description as string ) 警告を表示してプロセスを終了します。 【引数】 Description 警告メッセージ エラーコード E_TestPass(=21) のエラーが発生します。 サンプル スクリプト: Warning "アップデートのチェックはスキップしました。" 表示内容: → エラーメッセージのXML書式 テスト → T_Warning フォルダー *********************************************************************** <<< GetErrStr >>> *********************************************************************** GetErrStr (src) Function GetErrStr( e_num as integer, e_desc as string ) as string 標準形式のエラーメッセージを返す。 【引数】 e_num エラーコード e_desc エラーメッセージ サンプル: Dim e ' as Err2 echo_v GetErrStr( e.num, e.desc ) エラーメッセージの例: 関連 → エラーメッセージ文字列の標準書式(XML版) → GetErrStr (Err2) *********************************************************************** <<< AppendErrorMessage >>> *********************************************************************** AppendErrorMessage Function AppendErrorMessage( in_OldMessage as string, in_Appending_XML_Attributes as string ) as string エラーメッセージを追加します。 【引数】 in_OldMessage 今までのエラーメッセージ in_Appending_XML_Attributes 追加するエラーメッセージ、XML 属性の形式 返り値 新しいエラーメッセージ サンプル Dim e ' as Err2 If TryStart(e) Then On Error Resume Next ... If TryEnd Then On Error GoTo 0 If e.num <> 0 Then e.OverRaise e.Number, AppendErrorMessage( e.Description, _ "msg2=""追加メッセージ。""" ) End If OverRaise AppendErrorMessage エラーが発生して、そのエラーメッセージが XML 形式なら、属性 msg2="追加メッセージ。" を追加します。 参考 → OverRaise ソース → vbs_inc_sub.vbs *********************************************************************** <<< TryStart >>> *********************************************************************** TryStart (src) Function TryStart( e as Err2 ) as boolean Try ブロックの開始に記述します。 On Error Resume Next を呼び出すべきかどうかを判定します。 参考 → Err2 のコーディング例 (TryStart, TryEnd) → エラーをチェックするテストで期待と異なるエラーが発生するとき → "エラーが発生しているときに TryStart は呼べません。" エラーについて エラーをチェックするテストで期待と異なるエラーが発生するとき If TryStart(e) Then On Error Resume Next CreateFile fo + "\a.txt", "ABC" // 異なるエラーか発生 If TryEnd Then On Error GoTo 0 If e.num <> E_OutOfWritable Then Fail // ここのチェックで引っかかる "Test.vbs" /g_debug:5,1 ---------------------------------------------------------------------- 異なるエラーが発生した場所を知るには、チェックする前に Raise してください。 e.Raise If e.num <> E_OutOfWritable Then Fail それでも /g_debug オプションに設定すべき値の表示が変わらないときは、エラーが 発生していない可能性があります。 エラーが発生していないときの問題は、/g_debug オプションで自動的にエラーが発生した場所を表示することはできません。 "エラーが発生しているときに TryStart は呼べません。" エラーについて (もし、 /g_debug オプションを使っていたら、使わないで動かしてください。 エラーの状況 と、/g_debug の設定が合っていないと、誤って TryStart のエラーになることがあります。) 処理 TryStart エラーが発生(1) TryEnd ← Err2::Clear していない TryStart エラーが発生(2) ← このエラーが前のエラーの情報を消してしまう TryEnd エラーにしている理由 ほとんどの場合、1つ目のエラーを対処することで、2つ目のエラーは発生しなくなるため、 2つ目のエラーが発生したときに、1つ目のエラーの情報が上書きされて消えてしまうことが ないようにすることが重要です。 対処方法 1. エラーメッセージに表示されているように、g_debug 変数などの値を設定し、エラーが 発生している場所、つまり、TryStart の中の Stop 命令でブレークさせます。 2. Err.Number が 0 以外なら、Err.Description の値を、e.num が 0 以外なら e.desc の Err2::desc の値を表示させて、1つ前のエラーの内容を確認します。 3. コールスタックを上にたどっていき、On Error Resume Next が無いか探します。 あったら、おそらく、そこで1つ前のエラーが発生しているので、そのエラーを発生 させなくするか、クリアすることで対処してください。 なお、多くの場合、TryStart を使わない On Error Resume Next によって、そこで 発生したエラーでブレークすることができなくなっています。 VBScript の不具合に対する対処 Class_Initialize か Class_Terminate で発生したエラーは、VBScript は投げられま せん(エラーによる中断をしません)。 ErrCheck または ErrorCheckInTerminate を呼び出してください。 *********************************************************************** <<< TryEnd >>> *********************************************************************** TryEnd (src) Function TryEnd() as boolean Try ブロックの終了に記述します。 On Error GoTo 0 を呼び出すべきかどうかを判定します。 参考 → Err2 のコーディング例 (TryStart, TryEnd) *********************************************************************** <<< Trying >>> *********************************************************************** Trying (src) Function Trying() as boolean Try ブロックの中で記述します。 エラーが発生していたら False を返します。 参考 → Err2 のコーディング例 (TryStart, TryEnd) *********************************************************************** <<< ErrCheck >>> *********************************************************************** キーワード: new の注意点 ErrCheck (src) Sub ErrCheck() これまでの処理で、エラーがあったかどうかをチェックして、エラーがあったら発生させます。 クラスの Class_Initialize メソッドの中でエラーが発生しても、VBScript は、続きを実行してしまい、 エラーを見つけるのが困難になります。 new でオブジェクトを生成したら、本関数を呼び出して ください。 サンプル: Set obj = new ClassA : ErrCheck テスト → テスト [T_ErrOnNew] コンストラクタで発生したエラーを検出 関連 → ErrorCheckInTerminate *********************************************************************** <<< ErrorCheckInTerminate >>> *********************************************************************** ErrorCheckInTerminate (src) Sub ErrorCheckInTerminate( ErrNumAtStart as integer ) クラスの Class_Terminate の中で発生したエラーを表示します。 【引数】 ErrNumAtStart Class_Terminate に入った直後のエラーコード エラーが発生していたら、Err オブジェクトの内容を echo 出力して Stop または pause します。 エラーが発生していなかったら(Err.Number = 0 なら)、何もしません。 Class_Terminate の中でエラーを発生させることはできないので、ErrorCheckInTerminateも エラーを発生させません。 なるべく、Class_Terminate の中では、複雑な処理をしないで、 エラーが発生したことを示すフラグを立てて、後で処理してください。 参考 → Class_Terminate の中のエラー サンプル: Private Sub Class_Terminate() Dim en,ed : en = Err.Number : ed = Err.Description On Error Resume Next '// This clears error If en=0 or en=21 Then Else del Me.TmpDstPath End If ErrorCheckInTerminate en On Error GoTo 0 : If en <> 0 Then Err.Raise en,,ed '// This sets en again End Sub ErrorCheckInTerminate エラーが発生したときに対処法 Class_Terminate の中で発生したエラーでブレークさせる方法を説明します。 On Error Resume Next の後に、下記のコードを記述してください。 一度実行したら、最後の行の 99 を g_count(0) の値に変更して再度実行してください。 参考 → g_count, g_count_up On Error Resume Next '// This clears error If g_count_up(0)=0 Then Stop echo "g_count(0)=" & g_count(0) '// watch-> g_count [TODO] If g_count(0) = 99 Then On Error GoTo 0 0 0 0 0 99 テスト → T_Finish.vbs # ErrorCheckInTerminate *********************************************************************** <<< NotCallFinish >>> *********************************************************************** NotCallFinish (src) Sub NotCallFinish() Finish が呼ばれないで、クラスの Class_Terminate が呼ばれたときにエラー表示します。 関連 → Class_Terminate の中のエラー サンプル: Private Sub Class_Terminate() If en = 0 and not Me.IsFinished Then NotCallFinish End Sub *********************************************************************** <<< FinObj クラス (Finallyブロック) >>> *********************************************************************** FinObj クラス (Finallyブロック) (src) FinObj クラスを使うと、Finally ブロックに似た記述をすることができます。 FinObj のデストラクターから、Finally ブロックに相当する関数を呼び出します。 エラーが発生しても、続きを実行したり、キャッチしたりしませんが、Finally ブロックは実行します。 VBA の On ErroroGoto (Label) に相当する機能です。 WSH の VBScript では Goto は 0 しかできません。 関連 → エラー処理, On Error 記述例: 関数の場合 Sub FuncA( Path ) Set fin = new FinObj : fin.SetFunc "FuncA_Finally" ren Path, "a.txt" : fin.SetVar "Path", Path '// 戻すときのデータを記録 : fin.SetVar "Path", Empty '// 正常時は戻さないならデータを削除 End Sub Sub FuncA_Finally( Vars ) '// Finally ブロックに相当 en = Err.Number : ed = Err.Description : On Error Resume Next '// This clears error path = Vars.Item("Path") '// 戻すデータを取得 If not IsEmpty( path ) Then ren "a.txt", path '// 戻す処理 End If ErrorCheckInTerminate en : On Error GoTo 0 : If en <> 0 Then Err.Raise en,,ed '// This sets en again End Sub FuncA_Finally ren Path, "a.txt" Path FuncA_Finally Path ren "a.txt", path 記述例: メソッドの場合 Class ClassA Public Sub FuncA( Path ) Set fin = new FinObj : fin.SetFunc "FuncA_Finally" : End Sub : Public Sub FuncA_Finally( Vars ) '// Finally ブロックに相当 : End Sub End Class Sub ClassA_FuncA_Finally( Vars ) : Vars.Item("Me").FuncA_Finally( Vars ) : End Sub ローカル変数のデストラクタが動く順番に依存しないようにしてください。 たとえば、下記のように、デストラクタでカレント・フォルダが変わるとき、FuncA_Finally が 呼ばれるタイミングが、カレント・フォルダが変わる前か後かどうか不定なので、Finally ブロックで相対パスを指定することはできません。 Sub FuncA( Path ) Dim fin : Set fin = new FinObj : fin.SetFunc "FuncA_Finally" Dim ds_:Set ds_= New CurDirStack fin.SetVar "CurDir", g_fs.CurrentDirectory : End Sub : Sub FuncA_Finally( Vars ) del Vars.Item("CurDir") + "\_temporary_folder" End Sub 関連 → Class_Terminate (デストラクタ) → ErrorCheckInTerminate *********************************************************************** <<< 処理フロー (Err2) >>> *********************************************************************** 処理フロー (Err2) → 正常終了するとき → エラーが発生して終了するとき → エラーが Err2.Clear または再 Raise されないで終了したときの処理フロー 関連 → 処理フロー (vbs_inc/setting) 正常終了するとき VBScript global code (メインvbs の vbslib include) ResumePop CallFinalizeInModules 0 On Error Goto 0 していないときは 1 FinalizeModule (vbslib.vbs) (= g_FinalizeModules(i)) エラーが発生して終了するとき VBScript global code (メインvbs の vbslib include) : Err.Raise g_FinalizeInModulesCaller.Class_Terminate CallFinalizeInModules 1 FinalizeModule (vbslib.vbs) (= g_FinalizeModules(i)) WScript.Echo Err.Description If g_CommandPrompt = 1 Then WScript.Sleep 2000 *********************************************************************** <<< 困ったときは? (デバッグ) >>> *********************************************************************** 困ったときは? (デバッグ) エラーメッセージを見ても分からないときは、スクリプトの開発者に質問してください。 あなたが開発者であるときは、デバッグモードで動かしてみてください。 → デバッグを開始する → エラーメッセージの標準書式 → g_count, g_count_up … スルーカウンタ → g_debug_var → 条件ブレーク → ファイル出力を開始するタイミングでブレークする → SetupDebugTools … デバッグ機能の設定場所 → ウォッチ (WS, WD, WX) → 性能計測 → g_debug_params … 起動時のパラメーターを指定する → エラーコード → 長い文字を入力するときの注意 → vbslib2 から vbslib3 へ移植するには サポート ソフトウェアデザイン館 Sage Plaisir 21 http://www.sage-p.com/ ホームページにあるサポート掲示板かメールアドレスへ *********************************************************************** <<< g_debug - デバッグを開始する (vbslib) >>> *********************************************************************** g_debug - デバッグを開始する (vbslib) デバッガーとは、スクリプトの実行を一時的に止めて、変数の値を確認することなどができる ツールです。 正しい値で処理されているところと、誤った値で処理されているところを 挟み込んでいくようにして、問題がある場所を見つける作業を支援します。 関連 → デバッグ用一時コードのテンプレート インストール デバッガーは、Visual Studio Community 以上、または MS-Office 付属の Microsoft Script Editor に含まれています。 無料の scd10jp.exe も使えます。 → デバッガー (Visual Studio など) Visual Studio 2008 Professtional で、VBScript (WSH) をデバッグ デバッガーの起動の仕方 vbslib を使っているスクリプトの場合: → コマンドラインやショートカットからデバッガーに接続する vbslib を使わない場合: → デバッガー (Visual Studio など) Mircrosoft 製のデバッガーは、すべて同じ手順でデバッガーを起動できます。 その他の手順 → コマンドラインやショートカットからデバッガーに接続する → エラーが発生した瞬間のスクリプト内部の様子を調べる → ソース・ファイルの中の任意の場所でブレーク(一時停止)する → デバッガを終了する → デバッガで開いているソースの場所を知る → デバッガが無いときの g_debug → デバッグモードにしないでデバッガに接続 → vbslib include や、vbs_inc モジュールのデバッグ → コンパイルエラーが発生したときのデバッグ (g_is_compile_debug) → SetupDebugTools → 子プロセスでブレーク(Stop)する → ファイル出力を開始するタイミングでブレークする → 条件ブレーク → g_count, g_count_up → SkipToSection → メッセージボックス (VBScript) → 動作モード、デバッグ関係のグローバル変数 → エラー、デバッグ (VBScript) コマンドラインやショートカットからデバッガーに接続する (/g_debug) vbslib を使用しているスクリプトは、 WSH のデバッガー がインストールしてある環境では、 コマンドライン: cscript sample.vbs /g_debug:99 または、ショートカットを作成して、ショートカットを右クリック [ プロパティ ] の、 リンク先: "C:\Folder\sample.vbs" /g_debug:99 として起動するだけで、デバッガーに接続します。 /g_debug:1 にすると、1つ目のエラーでブレークします。 "C:\Folder\sample.vbs" /g_debug:2,1;1 のような複雑な記述もできます。 記述すべき値はエラーメッセージに表示されます。 → エラーが発生した瞬間のスクリプト内部の様子を調べる コロンの次は、 g_debug 、コンマの次は、 g_debug_tree 、セミコロンの次は、 g_debug_process に設定されます。 一時的にデバッガーの接続をしないときは、d_debug オプション全体を消さなくても、オプション の名前を少し変更するだけでできます。 こうすれば、再接続するときに、オプションのパラメー ターを入力し直す必要がなくなります。 (メモ) これができるのは、無効なオプションを VBScript がエラーにしないためです。 "C:\Folder\sample.vbs" /g_debug__:2,1;1 g_debug__ デバッガーに表示されているソース コードをテキスト エディターで開くときは、 OpenVBSLibSource コマンド を実行してください。 関連 → デバッグを開始する, g_debug (vbslib) テスト → T_Err2_Debug1_WithDebugger → T_Err2_Tree → T_ChildProcessIDNest_Manually2.vbs エラーが発生した瞬間のスクリプト内部の様子を調べる エラーが発生したら、エラーが発生した瞬間でブレーク(一時停止)するために必要な、 g_debug などに設定すべき値が自動的に表示されます。 表示されるエラーメッセージの例 WSH のデバッガーがインストールされていれば、スクリプト・ファイルへのショートカッ トを作成、プロパティ - リンク先に、下記の /g_debug オプションを追加、ショートカ ットから起動すると、問題がある場所で停止します。 ---------------------------------------------------------------------- "T_Sample.vbs" /g_debug:1 ---------------------------------------------------------------------- エラーが発生した瞬間でブレークさせるには、2つの方法があります。 1つは、*.vbs ファイルのショートカットを作成して、右クリック [ プロパティ ] の [ リンク先 ] に、/g_debug:1 オプションを設定してください。 リンク先: ...\sample.vbs /g_debug:1 1つ目のエラーでブレークする もう1つは、メイン・スクリプトの SetupVbslibParameters の中にある g_debug = 0 を編集して ください。 編集したら、スクリプトを再度実行してください。 Sample.vbs g_debug = 1 デバッガにアタッチして、1つ目のエラーでブレークする 多くの場合、vbslib の内部関数の中でブレークしてしまうので、自分が扱っているスクリプトが 見つかるまで、コールスタック(デバッグ | ウィンドウ | 呼び出し履歴)を開いて、探してください。 深い 浅い テスト → [T_ErrInfo] ユーザへのエラー通知とデバッガ接続 関連 → テストが Fail したとき → エラー処理のデバッグ ソース・ファイルの中の任意の場所でブレーク(一時停止)する g_debug ブレークしたいソースの場所に、Stop:OrError を記述して実行してください。 Stop:OrError g_debug などの変数に設定すべき値が書かれたコードが表示されます。 このコードを、 メイン.vbs の最後にある SetupVbslibParameters 関数の最後に記述してください。 下記のファイルをテキストエディタで開いて次のように変数の値を修正すると、デバッガ に接続して問題がある場所で停止します。 "sample.vbs" ---------------------------------------------------------------------- g_debug = 1 ---------------------------------------------------------------------- その状態で実行すると、Stop:OrError を記述した場所でブレークします。 関連 2回目以降でブレークする方法 → g_count, g_count_up → 条件ブレーク デバッガを終了する デバッグを中止するときは、コマンドプロンプトを閉じてください。 コマンドプロンプトが表示されていないときは、kill_wscript.bat を実行してください。 デバッガで開いているソースの場所を知る コールスタック(デバッグ | ウィンドウ | 呼び出し履歴)を見れば、全体から見てどの部分で 止まっているかが分かります。 開いているソースのフル・パスは、1行目に自動的に挿入されています。 ただし、Visual Studio 2010 以後は、インクルードしたすべてのスクリプトファイルの内容が 1つの [eval code] ウィンドウにまとめられてしまいますので、「'// g_SrcPath="」 で前方 検索してください。 一部のオブジェクト(静的オブジェクト)は、DefineInfo.FullPath プロパティに、クラスを定義 しているソースのフル・パスが入っています。DefineInfo プロパティが無くても、メソッドに ステップインしたときのソースの1行目から分かります。 メイン・スクリプトのパスは、WScript.ScriptFullName プロパティの値を見れば 分かりますが、インクルードしたスクリプトのパスは、通常分かりません。 しかし、g_debug=1 でデバッガに接続したときに表示される vbslib のソースは、 1行目にフル・パスが記述されたコメントが付きます。 (ただし、Visual Studio 2012 では、 すべてのファイルが1つのウィンドウにまとめられてしまうため、"g_SrcPath=" で上方向 に検索してください。) また、ソースの先頭に下記のような記述があり、 g_SrcPath の値を代入した g_〜_vbs.DefinePath 変数の値に、インクルードしたスクリプト のパスが入っています。 Visual Studio では、この変数を選択してウォッチ・ウィンドウへ ドロップし、値(パス、" "付きでも可)をコピーして、 ファイル・オープンで開けます。 .vbs ファイルの先頭 '// g_SrcPath="C:\Folder\vbslib\Sample.vbs" ... デバッグ時に自動的に付きます Dim g_SrcPath Class Sample_vbs : Public FullPath : End Class Dim g_Sample_vbs Set g_Sample_vbs =_ new Sample_vbs With g_Sample_vbs .FullPath = g_SrcPath End With Class ClassA Public Property Get DefineInfo() : Set DefineInfo = g_Sample_vbs End Property End Class g_SrcPath 簡易版 → get_DefineInfoObject もし、g_〜_vbs.DefinePath 変数が無くても、最後の call_vbs, call_vbs_d が呼び出している 関数を定義しているスクリプトのパスなら、g_SrcPath の値から知ることができます。 最後以外は、コールスタックを目的の call_vbs, call_vbs_d に切り替えて、 path 引数 の値を調べることで分かります。 また、下記の式の値が True なら、最後の call_vbs, call_vbs_d が、メイン・スクリプト の関数を呼び出していると判断できます。 g_SrcPath = WScript.ScriptFullName vbs ファイルが、main 関数を持ち、include もされる場合、上記の実装では、二重定義 エラーになります。 下記のように実装してください。 Dim g_Sample_vbs If IsEmpty( g_Sample_vbs ) Then Declare_g_Sample_vbs Sub Declare_g_Sample_vbs ExecuteGlobal "Class Sample_vbs : Public FullPath : End Class" Set g_Sample_vbs =_ new Sample_vbs With g_Sample_vbs .FullPath = g_SrcPath End With End Sub Sub main2( Opt, AppKey ) g_SrcPath = WScript.ScriptFullName : Declare_g_Sample_vbs : デバッガが無いときの g_debug デバッガが無くても、g_debug=1 にすれば、エラーメッセージが詳しくなることがあります。 g_debug=0 [ERROR](500) この変数は宣言されていません。 g_debug=1 C:\home\sample.vbs(34, 3) Microsoft VBScript 実行時エラー: この変数は宣言されていません。: 'e' ただし、行番号が出るのは、文法エラーのみです。 子プロセスでブレーク(Stop)する ブレークしたい場所に Stop 命令を記述してデバッガーに接続しても、RunProg 関数など で起動した子プロセスが Stop 命令を実行したときは、ブレークしません。 その代り、Stop:OrError と記述すると、ブレークするために必要な方法が表示されます。 参考 → OrError デバッグモードにしないでデバッガに接続 g_debug=1 にすると、詳しい動作内容が表示されたり、エラーが発生したらブレーク したりするなど、若干動きが異なります。 この動きをさせないで、デバッガに接続する には、g_debug=0 にして、下記のバッチファイルを実行してください。 debugger.bat Test.vbs ファイルをデバッガにアタッチします @cscript //x Test.vbs /g_debug:0 @pause wscript ではないことに注意 ただし、 g_CommandPrompt =0 なら wscript にしてください main.vbs g_debug=0 vbslib include や、vbs_inc モジュールのデバッグ 内部で、デバッガに接続するまでに、 vbs_inc モジュールの一部が動きますが、 そこをデバッグするときは、下記のバッチファイルを実行してください。 debugger.bat Test.vbs ファイルをデバッガにアタッチします wscript であることに注意 @wscript //x Test.vbs @pause デバッグを中止するときは、kill_wscript.bat を実行してください。 インクルードしたファイルにコンパイルエラーが発生したときのデバッグ (g_is_compile_debug) インクルードしたファイルがコンパイルエラーしたときは、g_is_compile_debug = 1 として 起動すると、コンパイルエラーがあった vbs ファイルがある行を開きます。 ただし、 Setting_getEditorCmdLine に、行番号を指定して開くことができるテキストエディタが すでに登録してある必要があります。 '--- start of parameters for vbslib include ------------------------------- g_debug = 0 '// release:0, debug:99, -1:call SetupDebugTools Dim g_is_compile_debug : g_is_compile_debug = 1 テスト → T_CompileDebug フォルダ *********************************************************************** <<< g_debug_var >>> *********************************************************************** g_debug_var (src) ReDim g_debug_var(10) デバッグ用グローバル配列変数 g_debug_var。 ブレークする条件を満たしたことを設定するときなどに使用できます。 すべてのモジュールからアクセスすることができ、スコープを超えて通知ができます。 デバッグするときに新しく一時的なグローバル変数を作成することがよくありますが、 その度にどこに配置したらよいかを考えなくて済みます。 デバッガーを使うときは、g_debug_var にウォッチする変数を持つオブジェクトを設定 しておくことで、変数の値を表示しながらステップ実行することができます。 デバッグが完了したら、g_debug_var を使っているコードを削除してください。 vbslib は、g_debug_var 変数を用意するだけで、アクセスしません。 サンプル 条件付きブレークをする テスト対象の中: If ... Then g_debug_var( 0 ) = True : If g_debug_var( 0 ) Then Stop Stop する条件を満たしたことを通知しています。 テスト対象の中の中: If ... Then g_debug_var( 1 ) = True : If g_debug_var( 1 ) Then Stop 2つ目の条件を満たしたことを通知しています。 補足 作成中の新機能を一時的に有効にするときは、g_debug_var を使わずに、 一時的なグローバル変数を作成してください。 新機能の外: gc_NewFunction = True '//[TODO] 一時的なグローバル変数 新機能の中: If gc_NewFunction Then NewFunction 関連 → g_DebugVar (clib) *********************************************************************** <<< g_count, g_count_up >>> *********************************************************************** g_count, g_count_up (src) Function g_count_up( i as integer ) as integer グローバル配列変数 g_count の1つの配列要素の値を+1します。 【引数】 i カウンタの種類の番号、配列要素番号(0以上) 返り値 新しい配列要素の値 デバッグ用です。 参考 → スルーカウンタ 問題が発生した場所の少し前でブレークさせたい場所で、まず下記のように記述します。 複数のカウンタを使うときは引数 0 を変えてください If g_count_up(0)=0 Then Stop '// watch-> g_count [TODO] echo_v "g_count(0)=" & g_count(0) 0 0 0 実行させてエラーが発生した場所でブレークしたら、g_count(0) の値をウォッチします。 0 は、g_count_up の ( ) の中と同じです。 ウォッチするのは、g_count_up ではないことに 注意してください。 g_count(0) ← ウォッチ g_count(0) の値がウォッチした値と一致したらブレークするように、記述を変更します。 If g_count_up(0)=2 Then Stop 2 ← g_count(0) をウォッチしたら 2 だった場合 再び最初から実行させると、上記の Stop で止まります。 関連 → 条件ブレーク → スルーカウンタ (C言語 - errors) *********************************************************************** <<< 条件ブレーク >>> *********************************************************************** 条件ブレーク 特定の条件を満たしたときだけブレークしたいときは、次のように記述します。 If ... Then SetVar "Stop1", 1 '// 条件の判定 [TODO] : If GetVar( "Stop1" ) Then Stop '// ブレークする場所 [TODO] *********************************************************************** <<< ファイル出力を開始するタイミングでブレークする >>> *********************************************************************** ファイル出力を開始するタイミングでブレークする 出力ファイルの内容に問題があるときは、ファイル名を指定するだけで、 ファイルの出力を開始するところでブレークさせることができます。 参考 → SetBreakByFName *********************************************************************** <<< FileWatcher >>> *********************************************************************** FileWatcher ファイルの内容をウォッチします。 ファイルの内容を、下記の順番で テンポラリ・フォルダー (下記 ${Tmp})にコピーします。 よって、ファイルの内容が変化する様子を確認したいときは、Before フォルダーと After_ フォルダーを比較すればよいことになります。 フォルダー ${Tmp}\ReplaceSteps\Before ${Tmp}\ReplaceSteps\After_ ファイル @ StepNum_001_to_002.txt A StepNum_001_to_002.txt A StepNum_002_to_003.txt B StepNum_002_to_003.txt B StepNum_003_to_004.txt C StepNum_003_to_004.txt 拡張子は、ウォッチしているファイルと同じ拡張子になります。 @〜C は、 FileWatcher_copyAFileToTheLog 関数 を呼び出した回数に対応します。 たとえば、A が付いている After_\StepNum_001_to_002.txt と Before\StepNum_002_to_003.txt の両方が、2回目に指定したファイルと同じ内容になります。 FileWatcher_copyAFileToTheLog 関数を呼び出すと、標準出力に下記のように出力 します。 ただし、1回目の呼び出しでは、比較する相手がいないので、出力しません。 FileWatcher >> C:\Users\user1\AppData\Local\Temp\Report\〜\ReplaceSteps FileWatcher >> StepNum_001_to_002.txt 初めて呼び出したときは、 Before\StepNum_001_to_002.txt にウォッチしているファイルのコピーが作られます。 2回目に呼び出したときは、 After_\StepNum_001_to_002.txt にウォッチしているファイルのコピーが作られます。 3回目に呼び出したときは、 Before\StepNum_002_to_003.txt に、After_\StepNum_001_to_002.txt のコピーと、 After_\StepNum_002_to_003.txt に、ウォッチしているファイルのコピーが作られます。 それ以降は、3回目に呼び出した ときと、同様に2つのコピーが作られていきます。 ウォッチするファイルを変更するときは、 FileWatcher_setNewFile 関数 を呼び出します。 その関数を呼び出す前後のファイルは、比較しないようになります。 たとえば、StepNum_003_to_004.txt のファイルが最後のコピーだったときに、 FileWatcher_setNewFile 関数を呼び出したら、次に作られるコピーは、 Before\StepNum_005_to_006.txt だけです。 StepNum_004_to_005.txt は、作られません。 関連 → ThreeWayMergeOptionClass .BreakStepNum *********************************************************************** <<< FileWatcher_copyAFileToTheLog >>> *********************************************************************** FileWatcher_copyAFileToTheLog << FileWatcher Sub FileWatcher_copyAFileToTheLog( in_WatchingPath as string ) 現在のファイルの内容を記録します。 【引数】 in_WatchingPath ウォッチしているファイルのパス ソース → vbslib.vbs *********************************************************************** <<< FileWatcher_setNewFile >>> *********************************************************************** FileWatcher_setNewFile << FileWatcher Sub FileWatcher_setNewFile() 次に記録するファイルを、比較を開始するファイルにします。 ソース → vbslib.vbs *********************************************************************** <<< Test.vbs のコールバック関数を呼び出すタイミングでコールバックする >>> *********************************************************************** Test.vbs のコールバック関数を呼び出すタイミングでコールバックする OnStart (SkipSectionGlobal) に、デバッグ用に作成したコールバック関数を登録してください。 参考 → テスト・プロンプト (Test.vbs) *********************************************************************** <<< 処理の詳細表示 (g_verbose)、トレース表示 >>> *********************************************************************** 処理の詳細表示 (g_verbose)、トレース表示 Dim g_verbose as boolean Verbose モードが有効かどうか。 ファイル: vbs_inc_sub.vbs Verbose モードが有効であるときは、内部処理の内容を詳しく表示しながら実行します。 Verbose モードで内部処理を表示する主な目的は、行われるはずの処理が行われて いない不具合を解決することです。 処理が行われなかった ことを中心に表示してください。 そうしないと、必要な情報が多くのノイズ(情報)に 隠れてしまいます。 とりあえず Verbose モードで動かし、そこからどの情報を詳しく 表示するようにすればいいか、どのオブジェクトを GetEchoStr で表示させるとよいか をガイドできればよいでしょう。 プログラムが処理内容に対してメタな処理になっているときに処理のステップを表示 したいときは、そのモジュールのメンバーに Verbose モードを追加してください。 サンプル (デバッグ時) g_verbose = 1 FuncA pause FuncA の処理内容を詳しく表示します。 サンプル (開発時) If g_verbose Then echo_v "処理は1つも行われませんでした。" テスト → T_Verbose.vbs # [T_Verbose] 関連 → echo_v *********************************************************************** <<< SetupDebugTools >>> *********************************************************************** SetupDebugTools (src) Sub SetupDebugTools() デバッグ時に main 関数を呼び出す直前で呼び出される関数。 通常、vbslib include に、SetupDebugTools 関数の定義を記述します。 デバッグ用に何らかの設定をしたり、ファイルを初期状態に戻すなどの処理を、この関数の 中に定義してください。 main 関数の最初に記述しても同じことができますが、vbslib を インクルードする前に、vbslib など vbs_inc でインクルードする関数が使え、g_debug の設定 の直後に処理を記述できるため、デバッグ用のコードを一般のコードと区別できます。 また、この関数の中では、利便性のために Out of Writable 警告 を発しません。 ただし、ファイルパスを指定するときは変数を使わないようにするなどして、予想外のファイル を壊さないように注意してください。 サンプル: '--- start of parameters for vbslib include --------- g_debug = 0 '// release:0, debug:99, -1:call SetupDebugTools Sub SetupDebugTools() : set_input "" : SetBreakByFName Empty : End Sub g_debug = 99 '// 上書きすることで、上記のデフォルトのコードを保護します。 Sub SetupDebugTools() '// 関数も前の定義を上書きできます。 del "C:\Users\user1\Desktop\TestData" set_input "1." SetBreakByFName "Out.xml" End Sub set_input SetBreakByFName テスト → [T_SetupDebugTools] デバッガ時の初期設定 *********************************************************************** <<< ウォッチ (WS, WD, WX) >>> *********************************************************************** ウォッチ (WS, WD, WX) (src) Sub MARK( Label as string, out_Count as variant ) スレッドの通過を表示します Function WS( Expression as string ) as string 文字列値を表示するコードを返します Function WD( Expression as string ) as string 数値を表示するコードを返します Function WX( Expression as string ) as string 数値を16進数で表示するコードを返します Sub WS2( Label as string, Value as variant ) 文字列値を表示します Sub WD2( Label as string, Value as variant ) 数値を表示します Sub WX2( Label as string, Value as variant ) 数値を16進数で表示します ブレークしないで、変数の値を標準出力へ表示します。 サンプル: Dim var1 : var1 = 123 Execute WD("var1") MARK "a", 0 Dim var1 : var1 = 123 WD2 "var1", var1 出力例: デバッガーを使うときは、 g_debug_var にウォッチする変数を持つオブジェクトを設定しておくことで、 変数の値を表示しながらステップ実行することができます。 関連 → Execute_Echo → バイナリーデータをダンプ表示する *********************************************************************** <<< エラー処理のデバッグ >>> *********************************************************************** エラー処理のデバッグ エラーが発生した後の処理を、デバッグする方法を示します。 1. まず、エラーが発生した瞬間を捕らえて、その場所に Stop 命令を記述します。 参考 → エラーが発生した瞬間のスクリプト内部の様子を調べる → ソース・ファイルの中の任意の場所でブレーク(一時停止)する … Stop 命令 2. g_debug を 99 など大きな数に設定して起動します。 3. Stop したら、ステップ実行します。 *********************************************************************** <<< データの元を探す >>> *********************************************************************** データの元を探す データを格納する場所(複数)は、変数名を単語単位で全文検索すれば分かることが多いです。 多くヒットしてしまうときは、クラス名で絞り込むか、データの値を print/echo して絞り込んでください。 データに関するデバッグは、そのデータを計算するときの入力データと、計算内容を確認することです。 入力データの入力データもあります。 最も元となる入力データからのツリー構造になります。 プログラムは、大量のデータのすべてに関して、元に近いほうから計算(処理)することです。 データA フロー データC フロー データD (NG) データB 確認する 確認する また、データをどこのコードでも参照できるように、下記のように、調べるデータをルートからたどるための インデックスを調べておくとよいでしょう。 データのインデックスを探す 1. この色の文字 で書かれたデバッグ用コードを入れて、データのインデックスを探す。 Set find_ = new CrossFindClass (.txt) Set element = find_.OutElements.Item( element_name ) as CrossFind_OutElementClass echo_v "333=> element_name = "+ GetEchoStr( element_name ) … 辞書のキー Set module = element.OutModuleTypes.Item(k) (.txt) echo_v "222=> k = "+ GetEchoStr( k ) … 配列番号 kk = 0 For Each one_element In module.Delegate.Elements array of string ↑CrossFind_ModuleClass (.txt) echo_v "111=> kk = "+ GetEchoStr( kk ) kk = kk + 1 … For Each から   配列番号 "" 上記は、VBScript のコードです。 2. インデックスを入れた、データ構造のルート(下記の find_ )からたどるコードを書く Set g_debug_var(9) = root_object echo_v "999=> "+ g_debug_var(9).OutElements( "1.c" ).OutModuleTypes(1).Delegate.Elements(2) ↑辞書のキー ↑配列番号 ↑ 配列番号 *********************************************************************** <<< デバッグ用一時コードのテンプレート >>> *********************************************************************** デバッグ用一時コードのテンプレート 下記のコードをすぐに開ける場所に置いておけば、デバッグ時にコピーするだけで デバッグに必要な情報を集めることができるようになります。 必要なら赤字の部分を変更してください。 変数の値を表示する。 特にループの中。 多くの変数値を見るときは、 → デバッガー → データの元を探す echo_v echo_v "111=> variable = "+ GetEchoStr( variable ) 111 variable GetEchoStr variable CPU がこの経路を通過したこと、処理が行われたことを表示する。 echo_v "111=>" 111 ブレークする。 Stop:OrError '// TODO:*********** OrError 現在編集中の場所を強調表示する。 未確定のコードであることを示す。 '//■ TODO: Coding of *********** 指定の条件を満たしたときに、ブレークする。 If InStr( Name, "value" ) >= 1 Then Stop:OrError '// TODO: InStr( Name, "value" ) >= 1 指定した回数を通過したときに、ブレークする。 If g_count_up(0)=0 Then Stop:OrError '// TODO: echo_v "g_count(0)=" & g_count(0) g_count_up 処理をスキップする。 主にテスト プログラム用。 Skipped : If False Then End If スキップする処理を If 〜 End If で挟みます。 配列形式のデータをスキップする。 Array _ 0 : Skipped スキップするデータを Array _ の行と 0 : Skipped の行の間に、 一時的に移動します。 このコードは、何も処理が行われません。 DicTable でよく使われます。 バイナリーをダンプする。 echo_v new_BinaryArrayAsText( "漢字", Empty ).xml "漢字"