문자열에서 임의의 네이티브 명령을 어떻게 실행합니까?


208

다음 시나리오를 통해 내 필요를 표현할 수 있습니다 . 기본 명령으로 실행할 문자열을 허용하는 함수를 작성하십시오.

아이디어를 너무 많이 얻지 못했습니다. 회사의 다른 곳에서 다른 명령 줄 유틸리티와 인터페이스하여 명령을 제공하는 명령을 제공하는 경우. 명령을 제어하지 않으므로 유효한 명령을 input 으로 승인해야합니다 . 이것들은 내가 쉽게 극복 할 수 없었던 주요 딸꾹질입니다.

  1. 명령은 공백이있는 경로에있는 프로그램을 실행할 수 있습니다.

    $command = '"C:\Program Files\TheProg\Runit.exe" Hello';
  2. 이 명령에는 공백이있는 매개 변수가있을 수 있습니다.

    $command = 'echo "hello world!"';
  3. 이 명령에는 단일 눈금과 이중 눈금이 모두있을 수 있습니다.

    $command = "echo `"it`'s`"";

거기에 모든 이를 달성 깨끗한 방법은? 나는 화려하고 추악한 해결책을 고안 할 수 있었지만 스크립팅 언어의 경우 이것이 간단하게 죽어야한다고 생각합니다.

답변:


318

Invoke-Expression로 별칭이 지정됩니다 iex. 다음은 예제 # 2 및 # 3에서 작동합니다.

iex $command

exe가 따옴표 안에 있기 때문에 예제 # 1과 같은 일부 문자열은 그대로 실행되지 않습니다. 문자열의 내용이 Powershell 명령 프롬프트에서 바로 실행하는 방식이기 때문에 그대로 작동합니다.

$command = 'C:\somepath\someexe.exe somearg'
iex $command

그러나 exe가 따옴표로 묶인 &경우이 예제에서와 같이 명령 행에서 실행할 때 실행되도록 하는 데 도움이 필요합니다 .

>> &"C:\Program Files\Some Product\SomeExe.exe" "C:\some other path\file.ext"

그리고 스크립트에서 :

$command = '"C:\Program Files\Some Product\SomeExe.exe" "C:\some other path\file.ext"'
iex "& $command"

"이 순진한 구현 에서처럼 명령 문자열의 첫 문자가 인 경우를 감지하여 거의 모든 경우를 처리 할 수 ​​있습니다 .

function myeval($command) {
    if ($command[0] -eq '"') { iex "& $command" }
    else { iex $command }
}

그러나 다른 방식으로 호출해야하는 다른 경우가있을 수 있습니다. 이 경우 try{}catch{}특정 예외 유형 / 메시지에 대해을 사용하거나 명령 문자열을 검사해야합니다.

상대 경로 대신 항상 절대 경로를 수신하는 경우 위의 2 이외의 특별한 경우가 많지 않아야합니다.


3
앨리어싱이 훌륭합니다. 다른 컴퓨터로 이동하거나 해당 스크립트를 다른 사람에게 보내면 해당 별칭이 설정되지 않을 수 있습니다. PowerShell 함수의 전체 이름을 선호하십시오.
Doug Finke 2018 년

1
@ Doug : 대부분 그렇게하거나 내장 별칭을 사용합니다 (특히 명령 줄의 간결함을 위해). eval일 반 농담이다가 다른 많은 스크립트 언어에서 호출,이 사람에 대한 몰랐다 어디 내가 본 첫 번째 질문하지 않습니다 어떤이의 때문에 invoke-expression. 그리고 OP의 경우는 사내 스크립트로만 들립니다.
Joel B Fant 2016 년

나는 이것을 시도했지만 작동하지 않습니다 : $ command = ' "C : \ Program Files \ Windows Media Player \ mplayer2.exe" "H : \ Audio \ Music \ Stevie Wonder \ Stevie Wonder-Superstition.mp3" '
조니 카우프만

3
"&"또는 "."를 넣어야 할 수도 있습니다. 그것은 예를 들어, 파워 쉘 모국어가 아닌 경우 실제 명령 전에 서명Invoke-Expression "& $command"
토브 Bergstedt

Torbjörn Bergstedt이 승리합니다! 마법의 추가 "&"가 내 문제를 해결했습니다! 결과적으로, 나는 행복하고 혼란스러워합니다.
Johnny Kauffman

19

기본적으로 PowerShell을 사용하여 쉘 명령을 실행하는 것이 얼마나 어려운지에 대한이 Microsoft Connect 보고서를 참조하십시오 (아, 아이러니).

http://connect.microsoft.com/PowerShell/feedback/details/376207/

그들은 --%PowerShell이 ​​텍스트를 오른쪽으로 해석하는 것을 멈추게하는 방법으로 사용 하는 것이 좋습니다 .

예를 들면 다음과 같습니다.

MSBuild /t:Publish --% /p:TargetDatabaseName="MyDatabase";TargetConnectionString="Data Source=.\;Integrated Security=True" /p:SqlPublishProfilePath="Deploy.publish.xml" Database.sqlproj

1
아, 그리고 Microsoft는 인터넷을 끊었고 링크는 더 이상 유효하지 않습니다.
Johan Boulé

1
위의 링크에서 archive.org에 web.archive.org/web/20131122050220/http://...
mwfearnley

4

제거 문자열에 대한 레지스트리를 구문 분석하고 실행할 때 허용 된 답변이 작동하지 않았습니다. 결국 전화가 필요하지 않은 것으로 나타났습니다 Invoke-Expression.

마지막으로 제거 문자열을 실행하는 방법을 알기 위해이 멋진 템플릿 을 발견했습니다 .

$path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall'
$app = 'MyApp'
$apps= @{}
Get-ChildItem $path | 
    Where-Object -FilterScript {$_.getvalue('DisplayName') -like $app} | 
    ForEach-Object -process {$apps.Set_Item(
        $_.getvalue('UninstallString'),
        $_.getvalue('DisplayName'))
    }

foreach ($uninstall_string in $apps.GetEnumerator()) {
    $uninstall_app, $uninstall_arg = $uninstall_string.name.split(' ')
    & $uninstall_app $uninstall_arg
}

이것은 나를 위해 작동합니다. 즉, $app내가 알고있는 사내 응용 프로그램이 두 가지 주장 만 가질 것입니다. 보다 복잡한 설치 제거 문자열의 경우 결합 연산자 를 사용할 수 있습니다 . 또한 방금 해시 맵을 사용했지만 실제로 배열을 사용하고 싶을 것입니다.

또한 동일한 응용 프로그램의 여러 버전이 설치되어 있으면이 제거 프로그램이 한 번에 모두 순환하여 혼란 스럽 MsiExec.exe습니다.


1

호출 연산자를 사용하려는 경우 인수는 변수에 저장된 배열 일 수 있습니다.

$prog = 'c:\windows\system32\cmd.exe'
$myargs = '/c','dir','/x'
& $prog $myargs

호출 연산자는 ApplicationInfo 객체와도 작동합니다.

$prog = get-command cmd
$myargs = -split '/c dir /x'
& $prog $myargs
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.