윈도우즈 배치 파일 내에서 PowerShell 스크립트를 실행하는 방법
Windows 배치 스크립트와 동일한 파일에 PowerShell 스크립트가 내장되어 있는 방법은 무엇입니까?
저는 다른 시나리오에서도 이러한 일이 가능하다는 것을 알고 있습니다.
- 다을사용여배포스에치함트 SQL을 내장
sqlcmd
goto와 했습니다. - 첫를 들어 *nix 환경트의첫립줄있에스가는이경실다, 를들설니합명같이다과예와 같이 됩니다.
#!/usr/local/bin/python
.
이를 수행할 방법이 없을 수도 있습니다. 이 경우 시작 스크립트와 별도의 PowerShell 스크립트를 호출해야 합니다.
제가 생각한 한 가지 가능한 해결책은 PowerShell 스크립트를 에코아웃한 다음 실행하는 것입니다.이렇게 하지 않는 좋은 이유는 이러한 시도를 하는 이유의 일부는 예를 들어 이스케이프 문자의 고통 없이 PowerShell 환경의 이점을 사용하기 위한 것이기 때문입니다.
저는 몇 가지 특이한 제약이 있어서 우아한 해결책을 찾고 싶습니다.저는 이 질문이 다양한 사람들의 반응을 미끼로 하는 것일 수도 있다고 생각합니다: "대신 이 다른 문제를 해결하려고 노력하는 것이 어때요?"이것들이 저의 제약이라고만 하면 됩니다, 죄송합니다.
아이디어 있어요?이를 달성할 수 있는 현명한 의견과 탈출 캐릭터의 적절한 조합이 있습니까?
이를 달성하는 방법에 대한 몇 가지 생각:
- 럿캐.
^
Visual Basic ▁an▁in▁like▁의 밑줄과 같은 연속이 있습니다. Visual Basic의 밑줄과 같은 것입니다. - ▁an.
&
을 구분할 때 합니다.echo Hello & echo World
으로 두 개의 에 발생합니다. - %0은 현재 실행 중인 스크립트를 제공합니다.
그래서 (제가 그것을 작동시킬 수 있다면) 다음과 같은 것이 좋을 것입니다.
# & call powershell -psconsolefile %0
# & goto :EOF
/* From here on in we're running nice juicy powershell code */
Write-Output "Hello World"
제외하고는...
- 효과가 없어요...왜냐면
- 가 PowerShell의 PowerShell의 경우에는 다음과 같습니다.
Windows PowerShell console file "insideout.bat" extension is not psc1. Windows PowerShell console file extension must be psc1.
- 이 . CMD에 가 있기는 말입니다. 하지만 우연히 발견되기는 합니다.
'#', it is not recognized as an internal or external command, operable program or batch file.
이 제품은 PowerShell에 올바른 라인만 전달합니다.
dosps2.cmd
:
@findstr/v "^@f.*&" "%~f0"|powershell -&goto:eof
Write-Output "Hello World"
Write-Output "Hello some@com & again"
정규식은 다음으로 시작하는 행을 제외합니다.@f
그고포함서해리▁an서▁including를 포함합니다.&
다른 모든 것을 PowerShell에 전달합니다.
C:\tmp>dosps2
Hello World
Hello some@com & again
때때로 "다중 언어 스크립트"라고 불리는 것을 찾는 것처럼 들립니다.CMD -> PowerShell의 경우
@@:: This prolog allows a PowerShell script to be embedded in a .CMD file.
@@:: Any non-PowerShell content must be preceeded by "@@"
@@setlocal
@@set POWERSHELL_BAT_ARGS=%*
@@if defined POWERSHELL_BAT_ARGS set POWERSHELL_BAT_ARGS=%POWERSHELL_BAT_ARGS:"=\"%
@@PowerShell -Command Invoke-Expression $('$args=@(^&{$args} %POWERSHELL_BAT_ARGS%);'+[String]::Join([char]10,$((Get-Content '%~f0') -notmatch '^^@@'))) & goto :EOF
인용된 인수를 지원할 필요가 없는 경우에는 한 줄로 묶을 수도 있습니다.
@PowerShell -Command Invoke-Expression $('$args=@(^&{$args} %*);'+[String]::Join([char]10,(Get-Content '%~f0') -notmatch '^^@PowerShell.*EOF$')) & goto :EOF
http://blogs.msdn.com/jaybaz_ms/archive/2007/04/26/powershell-polyglot.aspx 에서 가져온 것입니다.이것이 PowerShell v1입니다. v2에서는 더 간단할 수 있지만, 저는 찾아보지 않았습니다.
여기에서는 이 주제에 대해 논의했습니다.주요 목표는 느린 I/O 작업을 줄이고 중복 출력 없이 스크립트를 실행하기 위해 임시 파일을 사용하지 않는 것이었습니다.
그리고 저에 따르면 최고의 해결책은 다음과 같습니다.
<# :
@echo off
setlocal
set "POWERSHELL_BAT_ARGS=%*"
if defined POWERSHELL_BAT_ARGS set "POWERSHELL_BAT_ARGS=%POWERSHELL_BAT_ARGS:"=\"%"
endlocal & powershell -NoLogo -NoProfile -Command "$input | &{ [ScriptBlock]::Create( ( Get-Content \"%~f0\" ) -join [char]10 ).Invoke( @( &{ $args } %POWERSHELL_BAT_ARGS% ) ) }"
goto :EOF
#>
param(
[string]$str
);
$VAR = "Hello, world!";
function F1() {
$str;
$script:VAR;
}
F1;
훨씬 더 나은 방법(여기 참조):
<# : batch portion (begins PowerShell multi-line comment block)
@echo off & setlocal
set "POWERSHELL_BAT_ARGS=%*"
echo ---- FROM BATCH
powershell -noprofile -NoLogo "iex (${%~f0} | out-string)"
exit /b %errorlevel%
: end batch / begin PowerShell chimera #>
$VAR = "---- FROM POWERSHELL";
$VAR;
$POWERSHELL_BAT_ARGS=$env:POWERSHELL_BAT_ARGS
$POWERSHELL_BAT_ARGS
POWERSHELL_BAT_ARGS
명령행 인수는 배치 부분에서 변수로 처음 설정됩니다.
우선 . - 이 줄은 "" "" " " " " " " 입니다.<# :
석될것다니입처다것처럼 구문 됩니다.:<#
리디렉션이 다른 명령보다 우선 순위가 높기 때문입니다.
하만시작대로 :
배치 파일은 레이블로 사용됩니다. 즉, 실행되지 않습니다.여전히 PowerShell에 대한 설명은 유효합니다.
이 제대로 할 수 것만 남았습니다.%~f0
이 경로는 cmd.exe에 의해 실행되는 스크립트의 전체 경로입니다.
처음에 PowerShell에서 한 가지 오류가 발생하는 것을 개의치 않는다면 이 방법이 효과적인 것 같습니다.
dosps.cmd
:
@powershell -<%~f0&goto:eof
Write-Output "Hello World"
Write-Output "Hello World again"
저는 장 프랑수아 라부아르의 솔루션을 매우 좋아하는데, 특히 그가 Arguments를 처리하고 powershell-script에 과감하게 전달했기 때문입니다(+1 추가).
하지만 한 가지 결점이 있습니다.제가 언급할 명성이 없기 때문에, 저는 새로운 해결책으로 수정 사항을 게시합니다.
된 경우 .$
파일 내용을 로드하기 전에 평가할 문자입니다.가장 간단한 해결책은 큰따옴표를 바꾸는 것입니다.
PowerShell -c ^"Invoke-Expression ('^& {' + [io.file]::ReadAllText('%~f0') + '} %ARGS%')"
개인적으로, 저는 오히려 사용하는 것을 선호합니다.get-content
-raw
나에게 있어 이것은 더 강력한 것입니다.
PowerShell -c ^"Invoke-Expression ('^& {' + (get-content -raw '%~f0') + '} %ARGS%')"
하지만 그건 물론 제 개인적인 생각입니다.ReadAllText works
아주 완벽하게
완전성을 위해 수정된 스크립트:
<# :# PowerShell comment protecting the Batch section
@echo off
:# Disabling argument expansion avoids issues with ! in arguments.
setlocal EnableExtensions DisableDelayedExpansion
:# Prepare the batch arguments, so that PowerShell parses them correctly
set ARGS=%*
if defined ARGS set ARGS=%ARGS:"=\"%
if defined ARGS set ARGS=%ARGS:'=''%
:# The ^ before the first " ensures that the Batch parser does not enter quoted mode
:# there, but that it enters and exits quoted mode for every subsequent pair of ".
:# This in turn protects the possible special chars & | < > within quoted arguments.
:# Then the \ before each pair of " ensures that PowerShell's C command line parser
:# considers these pairs as part of the first and only argument following -c.
:# Cherry on the cake, it's possible to pass a " to PS by entering two "" in the bat args.
echo In Batch
PowerShell -c ^"Invoke-Expression ('^& {' + (get-content -raw '%~f0') + '} %ARGS%')"
echo Back in Batch. PowerShell exit code = %ERRORLEVEL%
exit /b
###############################################################################
End of the PS comment around the Batch section; Begin the PowerShell section #>
echo "In PowerShell"
$Args | % { "PowerShell Args[{0}] = '$_'" -f $i++ }
exit 0
또한 내장된 PowerShell 및/또는 VBScript/JScript 코드를 지원하는 이 "polyglot" 래퍼 스크립트를 고려해 보십시오. 이 스크립트는 2013년에 작성자 자신인 flabdablet가 게시한 독창적인 원본에서 수정되었지만 링크 전용 답변이었기 때문에 2015년에 삭제되었습니다.
파일 배파을만예다니듭일치)을합니다.sample.cmd
)는과 같은내용을 있습니다
<# ::
@echo off & setlocal
copy /y "%~f0" "%TEMP%\%~n0.ps1" >NUL && powershell -NoProfile -ExecutionPolicy Bypass -File "%TEMP%\%~n0.ps1" %*
set ec=%ERRORLEVEL% & del "%TEMP%\%~n0.ps1"
exit /b %ec%
#>
# Paste arbitrary PowerShell code here.
# In this example, all arguments are echoed.
'Args:'
$Args | % { 'arg #{0}: [{1}]' -f ++$i, $_ }
참고:
- 될 때 로 사용되는 파일입니다.
*.ps1
은 파이생정경에 됩니다.%TEMP%
폴더; 그렇게 함으로써 단순히 사용함으로써 (합리적으로) 강력하게 인수를 전달하는 것을 크게 단순화합니다.%*
- 위의 명령은 Windows PowerShell을 호출합니다.크로스 플랫폼 PowerShell(Core) v7+ 에디션을 호출하려면 다음과 같이 대체합니다.
powershell
와 함께pwsh
위의 암호로
기술 설명:
선
<# ::
블록의 이지만 PowerShell의 경우는 다음과 같습니다.cmd.exe
무시, npocmaka의 대답에서 차용한 기술입니다.시어음작으로
@
PowerShell에서는되지만 PowerShell에서는 됩니다.cmd.exe
회전이@
- 접미사가 없는 행은 다음으로 끝납니다.exit /b
거기서 종료하는, 바로 파종료을하고일배치서거기▁which▁right,고▁the하.cmd.exe
는 나머지 파일을 무시하므로 배치되지 않은 파일 코드, 즉 PowerShell 코드를 자유롭게 포함할 수 있습니다.그
#>
코드를 합니다. line은 PowerShell 주석 블록을 포함합니다.파일이기 형식의 PowerShell 파일입니다.
findstr
코드를 은 파일 확장자가 입니다. 그러나 PowerShell은 파일 이름 확장자가 있는 스크립트만 실행하기 때문입니다..ps1
배치 파일의 (임의의) 사본을 작성해야 합니다.%TEMP%\%~n0.ps1
을 임시복생다에 만듭니다.%TEMP%
배치 파일에 대해 이름이 지정된 폴더(%~n0
), 확장자가 경우), 이 파일은 삭제됩니다..ps1
작업이 완료되면 임시 파일이 자동으로 제거됩니다.다음의 3개의 개별 라인에 주의하십시오.
cmd.exe
명령문은 PowerShell 명령의 종료 코드를 전달하는 데 필요합니다.
(사用)setlocal enabledelayedexpansion
가정적으로 그것을 한 줄로 하는 것을 허용하지만, 그것은 원치 않는 해석을 초래할 수 있습니다.!
chars. 인수에서.)
인수 전달의 견고성을 입증하기 위해:
가 의위코다음같과이저로 저장되었다고 합니다.sample.cmd
호출:
sample.cmd "val. w/ spaces & special chars. (\|<>'), on %OS%" 666 "Lisa \"Left Eye\" Lopez"
다음과 같은 결과를 제공합니다.
Args:
arg #1: [val. w/ spaces & special chars. (\|<>'), on Windows_NT]
arg #2: [666]
arg #3: [Lisa "Left Eye" Lopez]
포함된 문자가 로 전달된 방식을 기록합니다.
그러나 포함된 문자와 관련된 에지 사례가 있습니다.:
:: # BREAKS, due to the `&` inside \"...\"
sample.cmd "A \"rock & roll\" life style"
:: # Doesn't break, but DOESN'T PRESERVE ARGUMENT BOUNDARIES.
sample.cmd "A \""rock & roll\"" life style"
이러한 어려움은 의 결함 있는 주장 구문 분석에 기인하며, 궁극적으로 flabdablet가 그의 훌륭한 답변에서 지적한 것처럼 이러한 결함을 시도하는 것은 무의미합니다.
그가 설명했듯이, 시퀀스 안에 (sic)이 있는 다음 메타 문자를 이스케이프하면 문제가 해결됩니다.
& | < >
위의 예를 사용합니다.
:: # OK: cmd.exe metachars. inside \"...\" are ^^^-escaped.
sample.cmd "A \"rock ^^^& roll\" life style"
한 솔루션과 를 지원하며 줄 param
제이가 올린 해결책처럼.유일한 단점은 이 솔루션이 임시 파일을 만든다는 것입니다.저의 사용 사례에 적합합니다.
@@echo off
@@findstr/v "^@@.*" "%~f0" > "%~f0.ps1" & powershell -ExecutionPolicy ByPass "%~f0.ps1" %* & del "%~f0.ps1" & goto:eof
이 작업에 대한 현재 선호도는 mklement0의 첫 번째 솔루션과 거의 동일한 방식으로 작동하는 폴리글롯 헤더입니다.
<# :cmd header for PowerShell script
@ set dir=%~dp0
@ set ps1="%TMP%\%~n0-%RANDOM%-%RANDOM%-%RANDOM%-%RANDOM%.ps1"
@ copy /b /y "%~f0" %ps1% >nul
@ powershell -NoProfile -ExecutionPolicy Bypass -File %ps1% %*
@ del /f %ps1%
@ goto :eof
#>
# Paste arbitrary PowerShell code here.
# In this example, all arguments are echoed.
$Args | % { 'arg #{0}: [{1}]' -f ++$i, $_ }
여러 가지 이유로 cmd 헤더를 각각 하나의 명령어로 여러 줄로 배치하는 것을 선호합니다.먼저, 무슨 일이 일어나고 있는지를 보는 것이 더 쉽다고 생각합니다. 명령줄은 편집 창 오른쪽에서 떨어지지 않을 정도로 짧습니다. 왼쪽에 있는 구두점 열은 첫 번째 줄에 있는 끔찍하게 남용된 레이블이 말하는 머리글 블록으로 시각적으로 표시합니다. 째둘,,del
그리고.goto
명령은 고유한 줄에 있으므로, 정말 펑키한 것이 스크립트 인수로 전달되더라도 계속 실행됩니다.
임시적인 솔루션을 선호하게 되었습니다..ps1
존하는사람대다줄을게에에 을 제출합니다.Invoke-Expression
PowerShell의 이해할 수 없는 오류 메시지에는 최소한 의미 있는 라인 번호가 포함되기 때문입니다.
데 까지 완전히 의 PowerShell은 PowerShell과 128비트를 사용합니다.%RANDOM%
임시 파일 이름에 포함되어 있기 때문에 여러 개의 동시 스크립트가 서로의 임시 파일을 중지하지 않습니다.은 원래 스크립트가가 손실될 수 입니다. 는 cmd 파일 접근 방식에 입니다. 이는 다음과 같은 이유입니다.dir
환경 변수가 두 번째 줄에 생성되었습니다.
PowerShell이 스크립트 파일에서 허용할 파일 이름 확장자에 대해 그렇게 신경 쓰지 않는 것은 훨씬 덜 성가실 것입니다. 하지만 당신은 당신이 갖고 싶은 셸이 아니라 당신이 가지고 있는 셸과 전쟁을 합니다.
말이 나온 김에: mklement0이 관찰하듯이,
# BREAKS, due to the `&` inside \"...\"
sample.cmd "A \"rock & roll\" life style"
은 실은제깨다집면니, 왜하냐로 .cmd.exe
전혀 가치 없는 인수 구문 분석입니다.저는 일반적으로 cmd의 많은 제한 사항을 숨기려고 노력하는 작업이 적을수록 예상치 못한 버그가 줄어든다는 것을 발견했습니다(예를 들어, mkemle0의 흠잡을 데 없는 앰퍼와 논리 탈출을 깨는 괄호가 포함된 인수를 생각해 낼 수 있을 것이라고 확신합니다).제가 보기에, 총알을 깨물고 비슷한 것을 사용하는 것이 덜 고통스럽습니다.
sample.cmd "A \"rock ^^^& roll\" life style"
와 세 번째 첫와째세째번번.^
분석될 때, 두은 이스케이프를 합니다.&
으로 powershell.exe
못생겼어요.", 이못겼요어생네거요▁yes어못겼생.네, 그렇게 행동하는 것이 더 어렵습니다.cmd.exe
대본에서 가장 먼저 시작하는 것이 아닙니다.걱정 말아요.중요한 경우 문서화합니다.
의 실제 대분의실이션서에케애는&
어쨌든 이슈는 미결입니다.이와 같은 스크립트에 대한 인수로 전달될 대부분은 드래그 앤 드롭을 통해 도착하는 경로 이름이 될 것입니다.Windows에서는 공간과 앰퍼샌드를 보호하기에 충분한 따옴표를 따옴표 이외의 값을 따옴표로 묶습니다. 이 값은 Windows 경로 이름에서는 사용할 수 없습니다.
도 못 Vinyl LP's, 12"
CSV 파일에 표시됩니다.
다른 샘플 배치+검정력셸 스크립트...이 솔루션은 다른 제안 솔루션보다 간단하며 다음과 같은 특징을 가지고 있습니다.
- 임시 파일 생성 없음 => 성능이 향상되고 덮어쓸 위험이 없습니다.
- 배치 코드의 특별한 접두사는 없습니다.이것은 그냥 일반적인 배치입니다.PowerShell 코드도 마찬가지입니다.
- ! % < > ' $와 같은 까다로운 문자가 있는 따옴표로 묶인 문자열을 포함하여 모든 배치 인수를 PowerShell에 올바르게 전달합니다.
- 큰따옴표는 큰따옴표를 두 배로 하여 전달할 수 있습니다.
- 표준 입력은 PowerShell에서 사용할 수 있습니다. (Batch 자체를 PowerShell로 파이프로 연결하는 모든 버전과는 대조적입니다.)
이 샘플은 언어 전환을 표시하고 PowerShell 측은 배치 측에서 받은 인수 목록을 표시합니다.
<# :# PowerShell comment protecting the Batch section
@echo off
:# Disabling argument expansion avoids issues with ! in arguments.
setlocal EnableExtensions DisableDelayedExpansion
:# Prepare the batch arguments, so that PowerShell parses them correctly
set ARGS=%*
if defined ARGS set ARGS=%ARGS:"=\"%
if defined ARGS set ARGS=%ARGS:'=''%
:# The ^ before the first " ensures that the Batch parser does not enter quoted mode
:# there, but that it enters and exits quoted mode for every subsequent pair of ".
:# This in turn protects the possible special chars & | < > within quoted arguments.
:# Then the \ before each pair of " ensures that PowerShell's C command line parser
:# considers these pairs as part of the first and only argument following -c.
:# Cherry on the cake, it's possible to pass a " to PS by entering two "" in the bat args.
echo In Batch
PowerShell -c ^"Invoke-Expression ('^& {' + [io.file]::ReadAllText(\"%~f0\") + '} %ARGS%')"
echo Back in Batch. PowerShell exit code = %ERRORLEVEL%
exit /b
###############################################################################
End of the PS comment around the Batch section; Begin the PowerShell section #>
echo "In PowerShell"
$Args | % { "PowerShell Args[{0}] = '$_'" -f $i++ }
exit 0
다른 대부분의 사람들이 실제로 PowerShell 주석처럼 보이듯이 배치 주석에는 :: 대신 :#을 사용합니다. (또는 다른 대부분의 스크립트 언어 주석처럼 보입니다.)
사용하다Invoke-Command
(icm
한 cmd로 만들 수 있습니다: " 여서줄", "다음 4헤를 ps1파일여유한효하배추다가치있니로습만들수줄에더1▁for줄),▁we다▁cmd▁4▁prep▁can니다▁line▁to▁batch배있한음습),줄:▁header▁short,치▁make▁it수.
<# : batch portion
@powershell -noprofile "& {icm -ScriptBlock ([Scriptblock]::Create((cat -Raw '%~f0'))) -NoNewScope -ArgumentList $args}" %*
@exit /b %errorlevel%
: end batch / begin powershell #>
"Result:"
$args | %{ "`$args[{0}]: $_" -f $i++ }
가 스크립트 [0]를 변경합니다.%*
"'%~f0'" %*
당신의 질문을 완전히 이해하지 못한다면, 제 제안은 다음과 같습니다.
@echo off
set MYSCRIPT="some cool powershell code"
powershell -c %MYSCRIPT%
아니면 더 나은.
@echo off
set MYSCRIPTPATH=c:\work\bin\powershellscript.ps1
powershell %MYSCRIPTPATH%
Powershell 스크립트 앞에 세 줄을 추가하고, 블록 주석만 사용한 다음 배치 파일로 저장할 수 있습니다.그런 다음 Powershell 스크립트를 실행할 배치 파일을 가질 수 있습니다.예:
psscript.bat
@echo off
@powershell -command "(Get-Content -Encoding UTF8 '%0' | select-string -pattern '^[^@]')" | @powershell -NoProfile -ExecutionPolicy ByPass
@goto:eof
<# Must use block comment; Powershell script starts below #>
while($True) {
Write-Host "wait for 3s"
Start-Sleep -Seconds 3
}
몇 가지 아이디어를 모으기
<# :
@powershell -<%~f0&goto:eof
#>
Write-Output "Hello World"
Write-Output "Hello World again"
@powershell -noninteractive "& ([Scriptblock]::Create((gc '%~df0' | select -Skip 1 | Out-String))) %*" & goto :eof
제가 드리는 제물은 다음과 같습니다.
- 확실한 것을 사용합니다.exe 입력 파일을 해시하여 임시로 파일 이름을 형성합니다.
- more.exe를 사용하여 헤더를 제거하고 임시로 파일을 만듭니다.
- all -arg xxx 스타일 인수를 powershell에 전달합니다.
- 에서는 ps1 파일을 볼 수 있도록 임시로 보관합니다.
용법의 예
.\runner.bat
.\runner.bat -scope town
.\runner.bat -scope "whole universe"
주자.배트
@echo off & (For /F Delims^= %%a In ('CertUtil -HashFile %0 SHA1^|FindStr /VRC:"[^a-f 0-9]"') Do Set "PS1=%TEMP%\%%a.ps1" )
(if not exist %PS1% more +3 %0 > %PS1%) & (PowerShell.exe -ExecutionPolicy bypass -file %PS1% %* & goto :EOF)
@@@@@@[ PowerShell Starts Here ]@@@@@@
Param(
[String]$scope = "world"
)
write-host "hello $scope"
레드 라이딩 후드의 답변을 수정한 스타일입니다.[ 스택 오버플로 편집 대기열이 가득 찼기 때문에 :D ]
완성도를 위해:
- 누락된 유용한 PowerShell 인수가 추가되었습니다.
- 오류 처리를 개선하기 위해 오류 수준을 반환합니다.
- 단일 및 이중 따옴표로 묶인 인수 지원
- 이 불쾌한 버그를 제거합니다.
- Batch 및 PowerShell 구문 강조 표시와의 호환성을 보장하여 구문 오류를 방지합니다.
코드 조각:
<# :
@PowerShell -ExecutionPolicy Bypass -NoLogo -NoProfile "& ([Scriptblock]::Create((Get-Content '%~df0' | Select-Object -Skip 4 | Out-String))) %*" & goto :eof
exit /b %errorlevel%
#>
전체 데모 스크립트:
<# :
@PowerShell -ExecutionPolicy Bypass -NoLogo -NoProfile "& ([Scriptblock]::Create((Get-Content '%~df0' | Select-Object -Skip 4 | Out-String))) %*" & goto :eof
exit /b %errorlevel%
#>
Write-Output $PSVersionTable
Write-Output $args
$host.ui.RawUI.WindowTitle = "PowerShell Chimera"
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
Start-Sleep -Seconds 5
Exit 0x539
사용 예:
# demo.bat var1="1" var2='2' & echo %errorlevel%
# demo.bat "var1=1" 'var2=2' & echo %errorlevel%
출력:
Name Value
---- -----
PSVersion 5.1.19041.868
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.19041.868
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
var1=1
var2=2
WINDOWS-PC\User
1337
참고 사항:만약 당신이 그것에 대해 확신하지 못한다면.-NonInteractive
레드 라이딩 후드의 원래 답변에 사용된 주장, 아래 설명을 인용했습니다.
당신이 사용하는 것을 오해하고 있는 것 같습니다.-NonInteractive
스위치; 당신은 여전히 powershell-non-interactive를 실행할 수 있고 대화형 프롬프트를 받을 수 있습니다.NonInteractive
스위치는 자동화된 스크립팅 시나리오를 위해 고안되었으며, 파워셸이 사용자에게 프롬프트를 보내고 응답을 기다리지 않도록 할 수 있습니다.들어 이 아닌 에서 PowerShell을 하는 Get-Credential
매개 변수가 없으면 사용자 이름과 암호를 묻는 대신 즉시 실패합니다.비대화형은 보안 메커니즘으로 작동하지 않습니다.더 나은 방법은 사용자가 액세스하는 데 사용할 수 있는 도구가 아니라 보호하려는 내용을 보호하는 것입니다.
출처: "PowerShell이 대화형 명령 창을 허용하지 않도록 강제하는 방법" 질문에 대한 jbsmith의 답변
PS: PowerShell 해킹대회로 변신한 주제 :D
1위를 차지하는 답변에는 당사 솔루션의 다음과 같은 기능이 없습니다.
Read-Host
/pause
이제 작동합니다.- 인수 패스스루(따옴표로 묶은 인수 포함)
- 반환 코드 패스스루
<# :
@set batch_args=%*
@powershell "iex ('$args = @(iex \"^& {`$args} $env:batch_args\");' + (cat -Raw '%~f0'))"
@exit /b %ERRORLEVEL%
#>
Write-Host Your PowerShell code goes here. First arg: $args[0] -fore Green
Read-Host Waiting for user to press Enter
Exit 42
인수가 필요하지 않으면 다음과 같이 하면 됩니다.@powershell "iex (cat -Raw '%~f0')"
설명:
<# ... #>
. PowerShell은 다음과 같습니다.<# :
배치에서 null 리디렉션으로 해석되므로 주석은 배치 코드로만 실행됩니다.exit /b %ERRORLEVEL%
종료 코드 PowerShell 종료반록도합니다하를 .
- 은 PowerShell 가 있는 만 실행합니다.
.ps1
을 직접 실행하는 "PowerShell", "PowerShell"이라고 .Invoke-Expression
/iex
대신 그것을 실행하기 위해.%~f0
는 Batch의 코드 입니다.$args
인수를 이지만, 하여 수동으로합니다. PowerShell은 이 변수를 PowerShell과 동일하게 설정합니다.
@
.%*
일괄 처리에서 스크립트에 전달된 모든 인수를 참조합니다.- 그
& {$args} %*
일부 볼 수 인수를 합니다. - PowerShell이 의심되므로 인용된 인수가 해당 스니펫에서 작동하지 않습니다.
- 내가 하면,
$args = (echo %*)
echo는 가 전달되지 경우 의 상호 작용을 echo echo 는수달인전을않지되우다경상기 :/ - 따라서 env 변수를 설정하고 Invoke-Expression으로 두 번 구문 분석하는 나의 초특급 해결 방법은 잘못된 인용 문제를 해결하고 인수 없음 문제를 방지합니다!
@
0개의 인수가 있더라도 항상 배열을 얻을 수 있습니다.
- 그
그ScriptBlock
기반 답변은 다음과 같은 문제를 가지고 있습니다.Write-Host
은 "문"과 함께 됩니다.Write-Output
/echo
- 기반 답변은 블록이 완료될 때만 표시되며, 이는 내 사용 사례에 치명적입니다(사용).Read-Host
할 경우 둡니다).
언급URL : https://stackoverflow.com/questions/2609985/how-to-run-a-powershell-script-within-a-windows-batch-file
'programing' 카테고리의 다른 글
부울 모드에서 마리아DB 전체 텍스트 검색에서 사용할 수 있는 문자는 무엇입니까? (0) | 2023.08.29 |
---|---|
확장 및 축소 방법확장 및 축소 방법Javascript를 사용하시겠습니까? (0) | 2023.08.29 |
콘다가 차지하는 디스크 공간을 어떻게 확보합니까? (0) | 2023.08.29 |
node.js 스트림을 사용한 오류 처리 (0) | 2023.08.09 |
c 코드를 c++ 코드에 연결할 때 g++ 연결 순서 종속성 (0) | 2023.08.09 |