장기 실행 파일을 실행하고 있습니다. 이제 배치 파일의 끝 부분에 몇 가지 명령을 추가해야한다는 것을 알았습니다 (기존의 내용은 변경하지 않고 일부 추가 명령 만 변경). 대부분의 배치 파일을 점진적으로 읽고 하나씩 실행한다는 점을 고려하면이 작업을 수행 할 수 있습니까? 또는 시스템이 파일의 전체 내용을 읽은 다음 작업을 실행합니까? ,실행중인 배치 파일 변경
답변
난 그냥 그것을 시도, 나의 직관에 대해, 그것은
가 나는 파일을 실행
echo Hello
pause
echo world
포함하는 배치 파일을 생성 (Windows XP에서) 마지막에 새 명령을 집어 이 일시 중지 된 동안, 세 가지 메시지는 콘솔에 반향되었다
echo Salute
그것을 저장을 누르면 일시 정지를 contine에 입력했다.
그래서 가십시오!
명령 인터프리터는 배치 파일의 줄 위치를 기억합니다. 현재 실행중인 행 위치 다음에 배치 파일을 수정하는만큼 괜찮을 것입니다.
그 전에 수정하면 이상한 일을 시작합니다 (반복 명령 등).
어디서든 문서화 되었습니까, 아니면 자신의 경험에서 나온 것입니까? – Benoit
내 경험에 사실입니다. – UnhandledExcepSean
실제로, 파서 포인터가 파일의 동일한 인덱스에 머물러 있기 때문에 인덱스 앞에 텍스트를 추가/제거하면 명령 포인터 아래에있는 내용이 바뀝니다. 이상한 일들이 일어납니다. – cat
거의 비슷하게 rein처럼, cmd.exe는 현재 파일 위치 (줄 위치뿐 아니라)를 기억하고 각 호출마다 파일 위치를 invisible 스택에 저장합니다. 당신이 그것을 뒤에 실행의 실제 파일 위치하기 전에, 당신은 단지 당신이 무엇을 필요로하는 동안 파일을 편집 할 수 있습니다 의미
... 자기 수정 배치의
작은 샘플
그것은 라인을 변경 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을 사용하여 각 행 앞에 줄 x 호를 붙인 다음 루프 내의 접 두부를 제거하여 극복 할 수 있습니다. 그러나 여분의 코드는 작업 속도를 늦추므로 코드가 빈 줄에 의존하지 않는 한 할 가치가 없습니다. 동적 코드가 파일의 끝에 서브 루틴으로 이동하는 경우
@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 메일 프로그램 및 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. 배치 파일 (.bat)의 경로 변경
- 2. 단일 인스턴스 배치 파일?
- 3. PsExec 시작된 후 원격 컴퓨터에서 C# 실행중인 배치 파일
- 4. 배치 파일
- 5. Powershell에서 실행중인 배치 파일의 PID를 확인하십시오.
- 6. 배치/BAT - 배치/BAT 파일로 프록시 설정 변경
- 7. 대체 파일 이름과 배치 파일
- 8. Windows 배치 파일 : 입력 파일 (대상 파일 이름)을 기반으로 파일 이름 변경 (복수 폴더 가능)
- 9. 배치 파일에서 여러 배치 파일 실행
- 10. Windows 배치 파일 디버거?
- 11. 공백 인수를 배치 파일
- 12. Windows 배치 파일 && 연산자
- 13. 배치 파일 디렉토리 확장
- 14. MySQL 배치 파일 업데이트
- 15. 대화 형 배치 파일
- 16. 배치 파일, $ : 및 ~
- 17. 배치 찾기 파일 확장자
- 18. 배치 파일 의심
- 19. 배치 파일 실행 C#
- 20. 배치 : 제거 파일 확장자
- 21. 배치 파일 XCopy 명령
- 22. 배치 파일 실행
- 23. 배치 파일 명령
- 24. 폴더 삭제를위한 배치 파일
- 25. 배치 파일 용 도구
- 26. 일부 배치 파일 질문
- 27. 터보 C & 배치 파일
- 28. 배치 파일 스크립팅
- 29. 프로그래밍 배치 파일
- 30. Process.Start를, 배치 파일 및
당신 꼭 사랑 SO 빠른 응답. 이미 배치를 실행하기 시작했습니다> 질문 게시> 답변 있음> 실행 완료 전에 파일을 편집했습니다! –
또한 배치 파일을 제거하거나 이름을 변경하면 현재 명령어의 오류가 완료된 순간 "배치 파일을 찾을 수 없습니다."라는 점에 유의하십시오. –