長期実行バッチファイルを実行しています。バッチファイルの最後にいくつかのコマンドを追加する必要があることに気付きました(既存のコンテンツに変更を加えず、余分なコマンドを追加するだけです)。たいていのバッチファイルがインクリメンタルに読み込まれ、1つずつ実行されるので、これを行うことは可能ですか?または、システムがファイルの内容全体を読み取り、ジョブを実行しますか?実行中のバッチファイルの変更
答えて
私はちょうどそれを試みたが、私の直感に対して、それは(Windows XP上で)最後に新しいコマンドを拾っ
私は、ファイルを実行した
echo Hello
pause
echo world
を含むバッチファイルを作成し、それは一時停止しながら、
echo Salute
を追加ポーズcontineする入力し、それを保存し、押下、すべての3つのプロンプトがコンソールにエコーしました。
だから、それに行ってください!
コマンドインタープリタは、バッチファイル内の行位置を記憶しています。現在実行中の行位置の後でバッチファイルを変更する限り、大丈夫です。
これを変更すると、それは変なこと(コマンドの繰り返しなど)を開始します。
それはどこに書かれていますか、これはあなた自身の経験からですか? – Benoit
これは私の経験では真実です。 – UnhandledExcepSean
実際には、パーサーポインタはファイル内の同じインデックスにとどまるので、インデックスの前にテキストを追加/削除すると、命令ポインタの下にあるものが移動します。確かに奇妙なことが起こります。 – cat
ほとんどの場合、cmd.exeは現在のファイル位置(行位置だけでなく)を覚えており、呼び出しごとにファイル位置を非表示スタックにプッシュします。それは背後に実行していると、実際のファイル位置の前に、あなただけが何を必要とする一方で、あなたはあなたのファイルを編集することができることを意味し
...
自己修正バッチ
の小さなサンプルそれはラインを変更set value=1000
連続
@echo off
setlocal DisableDelayedExpansion
:loop
REM **** the next line will be changed
set value=1000
rem ***
echo ----------------------
echo The current value=%value%
<nul set /p ".=Press a key"
pause > nul
echo(
(
call :changeBatch
rem This should be here and it should be long
)
rem ** It is neccessary, that this is also here!
goto :loop
rem ...
:changeBatch
set /a n=0
set /a newValue=value+1
set /a toggle=value %% 2
set "theNewLine=set value=%newValue%"
if %toggle%==0 (
set "theNewLine=%theNewLine% & rem This adds 50 byte to the filesize.........."
)
del "%~f0.tmp" 2> nul
for /F "usebackq delims=" %%a in ("%~f0") DO (
set /a n+=1
set "line=%%a"
setlocal EnableDelayedExpansion
if !n!==5 (
(echo !theNewLine!)
) ELSE (
(echo !line!)
)
endlocal
) >> "%~f0.tmp"
(
rem the copy should be done in a parenthesis block
copy "%~f0.tmp" "%~f0" > nul
if Armageddon==TheEndOfDays (
echo This can't never be true, or is it?
)
)
echo The first line after the replace action....
echo The second line comes always after the first line?
echo The current filesize is now %~z0
goto :eof
+1それは可能なことの楽しい例です。 – dbenham
ジェブの例では、楽しみがたくさんあるが、それは追加または削除されたテキストの長さに大きく依存します。私は反直観的な結果は、 "あなたがそれを変更すると、それは奇妙なことをやり直す(コマンドを繰り返すなど)"と言いました。
jebのコードを変更して、実行中のバッチファイルの先頭でさまざまな長さの動的コードを自由に変更する方法を示しました。動的セクション全体が完全に各繰り返しに置き換えられます。それぞれのダイナミックラインの先頭には、非干渉の;
が付いています。これにより、暗黙的なEOL=;
オプションのため、FOR /F
が動的コードを削除することができます。
特定の行番号を検索する代わりに、動的コードの開始位置を特定するための特定のコメントを探します。これは維持しやすくなります。
私は等号の行を使用してコードを無害に埋め込み、伸縮を許しています。コンマ、セミコロン、等号、スペース、タブ、改行のいずれかの組み合わせを使用できます。 (もちろん、パディングはセミコロンで始めることはできません。)括弧内の等号はコード展開を可能にします。括弧の後の等号はコードの収縮を可能にします。
FOR /F
は空白行を削除します。この制限は、FINDSTRを使用して各行の先頭に行番号を付け、ループ内の接頭辞を取り除くことで解決できます。しかし、余分なコードは物事を遅くするので、コードが空白行に依存しない限り、それは価値がありません。
@echo off
setlocal DisableDelayedExpansion
echo The starting filesize is %~z0
:loop
echo ----------------------
::*** Start of dynamic code ***
;set value=1
::*** End of dynamic code ***
echo The current value=%value%
::
::The 2 lines of equal signs amount to 164 bytes, including end of line chars.
::Putting the lines both within and after the parentheses allows for expansion
::or contraction by up to 164 bytes within the dynamic section of code.
(
call :changeBatch
==============================================================================
==============================================================================
)
================================================================================
================================================================================
set /p "quit=Enter Q to quit, anything else to continue: "
if /i "%quit%"=="Q" exit /b
goto :loop
:changeBatch
(
for /f "usebackq delims=" %%a in ("%~f0") do (
echo %%a
if "%%a"=="::*** Start of dynamic code ***" (
setlocal enableDelayedExpansion
set /a newValue=value+1, extra=!random!%%9
echo ;set value=!newValue!
for /l %%n in (1 1 !extra!) do echo ;echo extra line %%n
endlocal
)
)
) >"%~f0.tmp"
::
::The 2 lines of equal signs amount to 164 bytes, including end of line chars.
::Putting the lines both within and after the parentheses allows for expansion
::or contraction by up to 164 bytes within the dynamic section of code.
(
move /y "%~f0.tmp" "%~f0" > nul
==============================================================================
==============================================================================
)
================================================================================
================================================================================
echo The new filesize is %~z0
exit /b
上記はうまくいきますが、動的コードをファイルの最後にあるサブルーチンに移動するとはるかに簡単です。このコードは、制限なしに、またパディングの必要なく、拡張および縮小できます。 FINDSTRは、動的部分を削除する際のFOR/Fよりもはるかに高速です。動的な行には、セミコロン(ラベルも含む)を接頭辞として安全に付けることができます。次に、FINDSTR/Vオプションを使用して、セミコロンで始まる行を除外し、新しい動的コードを単に追加することができます。
@echo off
setlocal DisableDelayedExpansion
echo The starting filesize is %~z0
:loop
echo ----------------------
call :dynamicCode1
call :dynamicCode2
echo The current value=%value%
call :changeBatch
set /p "quit=Enter Q to quit, anything else to continue: "
if /i "%quit%"=="Q" exit /b
goto :loop
:changeBatch
(
findstr /v "^;" "%~f0"
setlocal enableDelayedExpansion
set /a newValue=value+1, extra=!random!%%9
echo ;:dynamicCode1
echo ;set value=!newValue!
echo ;exit /b
echo ;
echo ;:dynamicCode2
for /l %%n in (1 1 !extra!) do echo ;echo extra line %%n
echo ;exit /b
endlocal
) >"%~f0.tmp"
move /y "%~f0.tmp" "%~f0" > nul
echo The new filesize is %~z0
exit /b
;:dynamicCode1
;set value=33
;exit /b
;
;:dynamicCode2
;echo extra line 1
;exit /b
EDIT - 偶数のラベルに接頭辞を付けることができることを示すために、最後のコードを変更して、簡単に動的コードに含めることができます。 – dbenham
短い回答:はい、バッチファイルは実行中に自分自身を変更することができます。すでに他の人が確認しているので。
私が働いていた場所は、Windows 3以前はMS-DOSの社内メニューシステムでした。実行方法は非常にエレガントでした。実際には、バッチファイルから実行して、スクリプトを実行するためにメインプログラム(C言語で書かれたもの)を修正しました。このトリックは、選択が実行されている間、メニュープログラム自体がメモリスペースを占有していないことを意味していました。これには、LAN Mailプログラムや3270端末プログラムなどが含まれていました。
しかし、自己修正バッチファイルから実行すると、TSRプログラムのロードなどのスクリプトも実行でき、実際にはバッチファイルに入れることのできるものはほとんどできます。それはそれを非常に強力にしました。作者が最終的にバッチファイルをコマンドごとに再起動させる方法を見つけだすまで、GOTO
コマンドだけが機能しませんでした。
コマンドインタープリタは、読み込んでいる各コマンドファイル内のバイトオフセットを記憶しているように見えますが、ファイル自体はロックされていないため、実行中はテキストエディタなどで変更することができます。
この記憶された場所の後にファイルが変更された場合、インタープリタは今変更されたスクリプトをうまく実行し続ける必要があります。しかし、そのポイントより前に変更が加えられ、その変更がそのポイントのテキストの長さを変更した場合(たとえば、テキストを挿入または削除した場合など)、その記憶されたロケーションはもはやその次のコマンドの開始を参照しなくなります。インタプリタが次の '行'を読み込もうとすると、代わりに、挿入または削除されたテキストの量に応じて、別の行または行の一部を選択します。あなたが運が良ければ、おそらくそれが起こった言葉を処理したり、エラーを出したり、次の行から実行し続けることはできませんが、あなたが望むものではないでしょう。
しかし、何が起こっているのかを理解することで、スクリプトを構築してリスクを軽減することができます。メニューを表示し、choice
コマンドを使用してユーザーからの入力を受け入れてから、選択を処理することによって、単純なメニューシステムを実装するスクリプトを用意しました。そのトリックは、スクリプトが入力を待っているポイントがファイルの最上部近くにあることを確認して、編集したいと思うような編集がそのポイントの後に起こり、厄介な影響を与えないようにすることです。
例:
:top
call :displayMenu
:prompt
REM The script will spend most of its time waiting here.
choice /C:1234 /N "Enter selection: "
if ERRORLEVEL == 4 goto DoOption4
if ERRORLEVEL == 3 goto DoOption3
if ERRORLEVEL == 2 goto DoOption2
goto DoOption1
:displayMenu
(many lines to display menu)
goto prompt
:DoOption1
(many lines to do Option 1)
goto top
:DoOption2
(many lines to do Option 2)
goto top
(etc)
- 1. 別のバッチファイル内でバッチファイルを実行中
- 2. 実行中のアイテムの変更
- 3. 実行中のRxJavaストリームの変更
- 4. バッチファイルの変更
- 5. クエリの実行中に変更する
- 6. 実行中のPHP変更スクリプト
- 7. 実行中のC#変更プロセスFileName
- 8. 実行中のアクティビティのデザインを変更中
- 9. バッチファイルで実行されるPHPコードを変更する
- 10. 実行バッチファイル
- 11. 実行中にコンテキストクラスローダーを変更する
- 12. 実行中のシステムでの変電所ポート転送の変更
- 13. Powershellで実行中のバッチファイルのPIDを特定する
- 14. バッチファイルの実行の返信
- 15. 実行中のプロセスの環境変数を変更する
- 16. バッチファイルの実行中にコマンドプロンプトにhideコマンドを表示
- 17. cygwinのネットワーク共有(VMWare共有フォルダ)からバッチファイルを実行中
- 18. バッチファイルの実行中にcmdウィンドウを隠すには?
- 19. バッチファイルの実行中にECHOがオフになりました
- 20. コマンドを実行中にvimのステータス行を変更する
- 21. Arduinoの実行中に変数を変更する
- 22. バッチファイルの名前変更
- 23. Chrome拡張機能の実行中の反応アプリケーションの変更
- 24. 複数の実行中のテーブルの変更
- 25. JRebelで実行中のMavenプロファイルの変更
- 26. トランザクションの実行中にデータベースの変更にアクセスする
- 27. 実行中のデータストリームの出力ファイルを変更しますか?
- 28. アプリの実行中にXMLシェイプの色を変更する
- 29. 実行中のビルドの通知を変更する
- 30. プログラムの実行中にenumの説明を変更する
あなた奨めの愛SO迅速な応答。すでにバッチを実行し始めました。>質問を投稿しました>答えを得ました>実行完了前にファイルを編集しました! –
また、バッチファイルを削除または名前を変更すると、現在の命令がエラーを終了した瞬間がスローされます。「バッチファイルが見つかりません」。 –