batファイルを直接起動したときとタスクスケジューラから起動したときで挙動が違ったため、メモ
batファイルは設定ファイルの中身のデータを変数として外部ファイル(batと同階層に存在)から読み込むものとする。
このbatファイルを直接起動する場合、相対パス(ファイル名のみ)でも参照可能だったので以下の状態で設定
@echo off
@chcp 65001
@set SettingTxt=変数設定.txt
::設定ファイルはbatファイルと同階層にあること
@if not exist %SettingTxt% goto notFileEnd
::設定ファイルがない場合、最後まで飛ばす
@for /f "usebackq delims== tokens=1,2" %%i in (%SettingTxt%) do set %%i=%%j
::設定の各種情報を外部ファイルから変数に設定
::=の前を変数名、=の後を値として記憶させる(do set %%i=%%j)
@echo %TxtNames%%extendChild%
@goto finishedTask
:notFileEnd
set karyunagi="%SettingTxt%ファイル自体なかった"
:finishedTask
set /p karyunagi="操作完了"
TxtNames=拾うデータ
extendChild=.txt
本来は生成したファイル名があるかの判定とかあるが、そこは省略
しかし、タスクスケジューラから起動するとなにも実行せずに閉じる。
タスクスケジューラからbatファイルを開くところは起動しているので、bat内部でパスが指定できていないことになる。
調べたところ、タスクスケジューラから起動すると、パス位置がbatファイル位置を参照せずにファイル名をローカルディスク直下のパスとして探してしまうため、起きていたようだ。
タスクスケジューラでは・・・?
解決策を探していたら、以下のページを見つけた。
[Windows]タスクスケジューラで作業フォルダを指定する方法
タスクスケジューラ内の「開始(オプション)(I)」にbatファイルフォルダのパスを設定すると動くらしい。
実際試してみたら動いた。
・・・
いや、まぁ動いたけどこれ
batファイルの位置が固定で変化しない前提だよね・・・
普通は変更掛からないはずだけど、
事情があって変更みたいなことを考えると、絶対参照で書きたくはない
しかも、固定でない場合は変更がかかるたびに2か所もいちいち修正しなくてはならなくなるから、めんどい・・・
(ここ以外にも起動するbatファイルパスをタスクスケジューラの「プログラム/スクリプト(P):」も修正する必要がある)
bat側で指定する
よくよく考えてみたら、batのパスをbat内で指定すればいけるんじゃないかと思い、
@set pathes=%~d0
@set SettingTxt=変数設定.txt
::設定ファイルはbatファイルと同階層にあること
@set SettingTxt="%pathes%%SettingTxt%"
のように一部追加変更した。
最後の SettingTxt の "" は、
パス内に半角空白が入っていた時の対策のために入れている。半角空白があるとその先はコマンドが区切られているとして解釈し、ファイル名として読み取れなくなってしまう。
が・・・変わらない。
と思ったら、ドライブしか拾えてなかった。
@set pathes=%~d0
上記の指定だと、ドライブしか指定していないため、ドライブしか参照できていない。
ファイル名を除いたパスを指定する場合、「p」も指定する必要がある。
ということで、設定ファイルのパス取得に追加
@set pathes=%~dp0
@set SettingTxt=変数設定.txt
::設定ファイルはbatファイルと同階層にあること
@set SettingTxt="%pathes%%SettingTxt%"
実行できた。
バッチ内で自パスを拾うので、疑似相対パス参照はできた。
もっとも自パスの1つ上階層内の別フォルダ指定は試してみたが、できなかった(というかできない?)ので、batのみで同一階層下以外の相対パス参照は無理っぽい?
20/08/03 追記
コメントいただいたものでpushd
を用いてみたところ、相対参照もできた。
@set pathes=%~dp0
pushd %pathes%..\test\
@set pathes=%cd%
@set SettingTxt=変数設定.txt
::設定ファイルはbatファイルの1つ上階層のtestフォルダ内にあること
@set SettingTxt="%pathes%\%SettingTxt%"
ただし、%~dp0
から遡る都合か、
%~dp0
時にあった最後の/
は存在しなくなってしまうので、
変数結合時(最後のSettingTxt
)に追加している。
##参考
パス名の文字列を自在に切り取る - 知識ゼロからのwindowsバッチファイル超入門
バッチファイルでの「スペース」を含んだ文字列の取り扱い - 知識ゼロからのwindowsバッチファイル超入門
.bat(バッチファイル)のforコマンド解説。 - Qiita