フォルダに続き、ファイル処理を行う命令・関数の紹介を行います。 以前にファイルの存在確認と変数への読み込みを行いましたが、 今回はエクスプローラ、言い換えるとPCを管理する上で行える処理をHSPでやってしまいます。
まず、ファイルを起動する命令から。
| exec 実行ファイル, モード, アクション | |||
| 実行ファイル | 起動するファイルパスを指定する。 | ||
| モード | 以下の方法で起動する。 0:ノーマル 2:最小化 16:関連付けたアプリケーションで開く 32:印刷 | ||
| アクション | レジストリに登録されたコンテキストメニュー文字列を指定する。 | ||
EXECuteの略であるexec命令は、エクスプローラ上の様々な操作開始に代わって実行するものです。 主にフォルダやファイルの実行、URLを開くことが出来るもので、 Windowsのスタートメニューにある「ファイル名を指定して実行」と同じ挙動をさせられます。 第1パラメータに起動させるファイルを指定しますが、 第2パラメータのモードをノーマル(省略)にする場合は、拡張子はexeのみ(拡張子の省略可能)が対象です。 指定できるモードは上記の通りで、テキストファイル等のドキュメントファイルを開く場合は、 モード16とすることで、指定したファイルの拡張子に関連付けられたアプリケーションで開けます。 例えばテキストファイルを開く場合に、通常はメモ帳等の特定エディタで編集しているが、 ココで起動させる場合だけはワードパッドで開かせたいと言う時は、モード16を使用するのではなく、 「exec "wordpad readme.txt"」のように実行パスの+半角スペース+ファイルパス指定することで、 先頭に書いたアプリケーションにコマンドラインとして送り、開くことが出来ます。 当然アプリケーション側がコマンドラインに対応してないと開けませんが、大半は対応させているようです。 尚、カレントフォルダは今までに紹介した他の命令でもフォルダパスを指定せずとも処理できましたが、 exec命令は他にもWindowsフォルダやSystemフォルダ、System32フォルダにある ファイルをフォルダパスなしに実行させることが出来るようです。 ですので、上記のwordpadは通常、Windowsフォルダですが、ファイル名だけで実行できます。 同一ファイル名の場合に、フォルダパスを指定しない場合の優先順位は次の通り。 「カレントディレクトリ」>「System32」>「System」>「Windows」 第3パラメータに書くのは、実行する動作を指定する文字列。 指定できる動作はファイルの種類によるが、大抵のものは次のコンテキストメニューを実行できるようです。
| コマンド | 内容 |
| edit | エディタで編集する。 |
| explore | 指定したフォルダをエクスプローラで開く。「explorer」で起動させるものと同じ。 |
| open | 関連付けたアプリケーションで開く。モード16と同じ。 |
| 関連付けたアプリケーションの印刷機能で印刷する。モード32と同じ。 | |
| properties | プロパティウィンドウを開く。 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
exe = "calc\nnotepad\nexplorer\nmspaint" name = "電卓\nメモ帳\nエクスプローラ\nペイント" screen 0, 300, 100 title "ランチャー" objsize 100, 20 pos 10, 10 : mes "実行ファイル" pos 150, 10 : combox index, 100, name pos 10, 40 : mes "起動" pos 150, 40 : button gosub "開始", *start notesel exe stop *start noteget proc, index exec proc // 指定プログラムを実行する return |
続いてファイル複製処理を行う命令を紹介します。
| bcopy コピー元ファイル, コピー先ファイル | |||
| コピー元ファイル | コピーする対象のファイルパスを指定する。 | ||
| コピー先ファイル | 作成するファイルパスを指定する。 | ||
bcopy命令はBinaryCOPYの略で、使い方は至って簡単。 第1パラメータのファイルを第2パラメータの位置・名称として複製するというものです。 既に指定フォルダに指定ファイルがパスが存在する場合、上書保存してしまいます。 気をつけなければ、重要なファイルでも上書きしてしまいかねません。 既に存在する場合は、作成する前にダイアログを表示して本当に上書きしてよいか確認するとよいでしょう。 作成先名と同一名のフォルダが存在する場合は上書きされませんが、HSPのエラーで終了してしまいます。 こうならないようにするには、コピーする前にチェックロジックを入れるようにしましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
sdim file, 512, 2 screen 0, 480, 70 objsize 60, 20 pos 10, 10 : mes "コピー元" pos 100, 10 : input file.0, 300, 20 pos 410, 10 : button gosub "参照", *ref pos 10, 40 : mes "コピー先" pos 100, 40 : input file.1, 300, 20 pos 410, 40 : button gosub "コピー", *copy stop *ref dialog "", 16, "コピー元ファイル" if stat : objprm 0, refstr return *copy dirlist check, file.1, 5 if stat { dialog "フォルダとして存在しているため、コピーできません。", 1 return } dirlist check, file.1, 1 if stat { dialog "既に存在しますが上書きコピーしますか?", 2 if stat = 7 : return } bcopy file.0, file.1 // ファイルコピーする dialog "作成しました。" return |
続いて、ファイル削除処理を行う命令を紹介します。
| delete 削除ファイル | |||
| 削除ファイル | 削除するファイルパスを指定する。 | ||
パラメータで指定したファイルを削除するdelete命令は、ゴミ箱に入れず、 元に戻すアンドゥ作業もありませんので、意図しないファイルを削除しないように注意してください。 また、指定できるのは1ファイルだけで、複数ファイル、またはフォルダごとの一括削除は行えませんので、 実現したい場合は他の方法で行ってください。 利用者に指定ファイルを削除させる場合、bcopy命令による上書きコピーの時と同様に、 削除前には確認メッセージを表示させると親切だと思いますよ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
sdim file, 512 screen 0, 480, 70 objsize 60, 20 pos 10, 10 : mes "削除ファイル" pos 110, 10 : input file, 300 pos 410, 10 : button gosub "参照", *ref pos 410, 40 : button gosub "削除", *del stop *ref dialog "", 16, "削除対象ファイル" if stat : objprm 0, refstr return *del exist file if strsize = -1 { if file ! "" : dialog "[" + file + "]はファイルとして存在しません。" } else { dialog "[" + file + "]を本当に削除してよろしいですか?", 3 if stat = 7 : return delete file // ファイルを削除する dialog "削除しました。" objprm 0, "" } return |
exec命令のように他ファイルを実行する命令を紹介します。 exec命令と異なる点は、実行できるファイルが中間オブジェクトファイルだけであること、 実行と同時に、実行させた側のプログラムは終了されてしまうこと、です。 中間オブジェクトファイルとは、スクリプトをコンパイルして中間コードにしたオブジェクトファイルのこと。 つまり、中間オブジェクトファイルを実行し、元の実行側を終了するということは、 HSPの実行を中間オブジェクトファイルに移すということです。
| run AXファイル, コマンドライン | |||
| AXファイル | コンパイル済みの中間オブジェクトファイルを指定する。 | ||
| コマンドライン | 中間オブジェクト実行時に取得できるコマンドラインを指定する。 | ||
第1パラメータにHSP実行の切替先AXオブジェクトを指定し、 第2パラメータに、AXオブジェクト起動時の「dir_cmdlineで取得できるコマンドライン」を指定します。 EXEを実行している時は内部で保持していた変数情報等がクリアされるので通常、 EXE1ファイルだけの実行で、外部の(またはパックした)AXファイルに処理を移しませんが、 例えば管理者も以前にやろうとしていた「機能毎にファイル自体を切り分ける」処理を施そうとした際に、 EXEを複数用意すると、ランタイムも各EXEに付加され重複してしまい無駄が出来てしまいます。 この場合にEXEを1つだけ用意しておき、そのEXEから機能毎のAXファイルを実行するようにすれば、 ランタイムはEXE1つだけで、機能毎に分けられたファイルにはランタイムが付かずサイズを抑えられます。 この説明ではイメージしにくいと思いますが、 run命令は複数のHSP実行ファイルを別プロセスで扱いたい場合に有効なのではないでしょうか? 例えば下記3つのスクリプトを、「runtest1.ax」「runtest2.ax」「runtest3.ax」で保存し、 4つ目のスクリプトを実行してみてください。
保存名【runtest1.ax】
1 2 3 4 5 6 7 8 9 10 11 12 |
title "1つ目のAX実行内容" mes "1つ目のAXファイルに制御が移りました。\n" wait 500 mes "ココではサンプルメッセージを表示させているだけですが、" wait 300 mes "実際に使う時は行わせたい処理を記述した上でAXを作成してください。" wait 300 mes "先ほどと同じ様にrun実行しますが、次からコマンドラインも使用します。" wait 300 mes "\n説明は後程としまして、2つ目のAXへ処理を移します。" wait 500 run "runtest2.ax", "from runtest1" // 不正起動用コマンドラインを付けて起動 |
保存名【runtest2.ax】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
if dir_cmdline ! "from runtest1" : end // 不正実行処理の制御 title "2つ目のAXファイル" mes "2つ目のAXファイルに制御が移りました。\n" wait 500 mes "もし、利用者がAXファイルの存在や扱い方を知っており、" wait 300 mes "1つ目のAXを実行せず、不正に2つ目以降から実行させようとしても、" wait 300 mes "このサンプルプログラムのように起動時チェックを設けていると、" wait 300 mes "トラップ用コマンドラインを知らない限りは実行を防ぐことが可能です。" wait 300 mes "\n次のAXへ処理を移します。" wait 500 run "runtest3.ax", "from runtest2" // 不正起動用コマンドラインを付けて起動 |
保存名【runtest3.ax】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
if dir_cmdline ! "from runtest2" : end // 不正実行処理の制御 title "3つ目のAXファイル" mes "3つ目のAXファイルに制御が移りました。\n" wait 500 mes "プログラムをAXファイルとして複数に分けるメリットを説明します。" wait 300 mes "例えば、追加パックや追加シナリオ機能の実現や、" wait 300 mes "最近はブロードバンドが主流なのでメリットは少ないですが" wait 300 mes "修正箇所のみを手直ししたフィックス版を公開する際に" wait 300 mes "肥大化したEXEを再度まるまるダウンロードしてもらうのではなく" wait 300 mes "数キロ〜数十キロバイトのAXのみを修正ファイルとして公開すると" wait 300 mes "ナローバンドの人には喜ばれるかもしれません" wait 300 mes "以上で「runテスト」を終了します。" wait 500 end |
初めに実行するメインプログラム【untitled (テストでは保存しなくても構いません) 】
1 2 3 4 5 6 7 8 9 10 |
title "HSPBC 複数AXファイルの実行テスト" mes "これから複数のAXファイルに切り分けたプログラムのテストを行います。" wait 300 mes "run命令でウィンドウ制御が別ウィンドウへ移る際にチラつきますが、" wait 300 mes "なんか良い対処法を考えてみてください。" wait 300 mes "それでは、始まり始まり〜。。。" wait 300 run "runtest1.ax" // 中間オブジェクトファイル起動 |
この章の最後として、パス文字列から一部を取得する関数を紹介します。
| 取得値 = getpath(対象文字列, モード) | |||
| 取得値 | 指定した対象文字列を指定モードで処理した結果文字列の受取先を指定する。 | ||
| 対象文字列 | ファイルパス形式の文字列または文字列型変数を指定する。 | ||
| モード | 取得モード(後述)を指定する。 | ||
第1パラメータの文字列から、第2パラメータに指定した下記のモードの形に変換した文字列を返します。
| モード | 処理内容 | 対象文字列例( A:\BC\DEF.GHI ) |
| 0 | 処理せずにそのまま渡す。 | A:\BC\DEF.GHI |
|---|---|---|
| 1 | ファイル名のみ(拡張子除く)渡す。 | A:\BC\DEF |
| 2 | 拡張子のみ渡す。 | .GHI |
| 8 | フォルダ名を除いて渡す。 | DEF.GHI |
| 16 | 小文字に変換して渡す。 | a:\bc\def.ghi |
| 32 | フォルダ名のみ渡す。 | A:\BC |
複数の処理を同時に行いたい時は、モード値の合計を指定してください。 但し、ファイル名のみ(=1)と拡張子のみ(=2)の合計値3を指定すると、0と同じ文字列コピー、 拡張子のみ(=2)とフォルダ名のみ(=32)の合計値34を指定すると、2と同じ拡張子のみ、 フォルダ名を除く(=8)とフォルダ名のみ(=32)の合計値40を指定すると、8と同じとなります。 getpath関数は単純に、文字列の最後尾から最も近いピリオドまでを拡張子として、 最後尾から最も近い¥マークまでをファイル名として判断しています。 第1パラメータに指定する文字列または文字列型変数には、必ずしもファイルのパスでなくとも構いません。 ファイルパスの一部取り出し以外にはあまり用途がないような関数ですが、 小文字に変換するモードはファイルパスに関係なく利用価値がありますよね? 但し、getpath関数は元々がファイルパス向けの文字列を指定するようになっていますので、 最大256バイトまでの文字列しか返しませんので気をつけましょう。 以下のサンプルは、読み込もうとしているファイルが画像かをチェックするプログラムです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
sdim list, 32 admit = "jpg", "gif", "bmp", "ico" foreach admit if cnt : list += ";*." list += admit.cnt loop dialog list, 16, "読み込める画像" if stat { ok = 0 foreach admit tmp = getpath(refstr, 2 + 16) // 選択ファイルの拡張子を小文字にして抽出 if strmid(tmp, 1, 256) = admit.cnt { ok = 1 break } loop if ok { picload refstr, 1 } else { dialog "読み込める画像を選択してください" } } |