2009-11-04 8 views
212

Jak uruchomić następujące polecenie w PowerShell?Jak uruchomić plik EXE w PowerShell z parametrami ze spacjami i cudzysłowami

C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe -verb:sync -source:dbfullsql="Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;" -dest:dbfullsql="Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;",computername=10.10.10.10,username=administrator,password=adminpass"

+0

Zobacz również http://stackoverflow.com/questions/6224638/powershell-call-msbuild-with-nested-quotation-marks/8468690#8468690 –

+0

Jeśli masz na myśli litteraly " w PowerShell "(co rozumiem jako" wewnątrz istniejącego monitu programu PowerShell), następnie następujący przykład może być łatwo dopasowany do twoich potrzeb. "Uwaga: nie ma potrzeby oddzielania polecenia od jego parametrów: ' # Pokaż wszystkie dostępne aktualizacje pakietów NPM zainstalowanych globalnie za pomocą narzędzia npm-check-updates [ciąg] $ cmd = 'ncu -g' Write-Verbose -Message $ cmd Invoke-Command -ScriptBlock ([ScriptBlock] :: Create ($ cmd)) ' – user3785010

+0

Nie mam pojęcia, jak użyć" mini-markdown ", aby edytować powyższy komentarz, aby każdy wiersz kodu pojawia się w osobnym wierszu, a wygasł 5-minutowy limit edycji oryginalnego komentarza. Jeśli ktokolwiek wie, aby użyć "mini-Markdown", aby rozwiązać problem, odeślę go w bardziej czytelnej formie. Pierwsza linia powinna być tylko następujące: narzędzie # Wyświetl dostępne aktualizacje do zainstalowanych na całym świecie pakietów NPM za pomocą NPM-sprawdź aktualizacje – user3785010

Odpowiedz

230

Kiedy PowerShell widzi polecenie zaczynające się ciągiem po prostu ocenia ciąg, to znaczy, że zwykle Echos go do ekranu, na przykład:

PS> "Hello World" 
Hello World 

Jeśli chcesz PowerShell do interpretowania ciąg jako nazwa polecenia, a następnie użyć operatora połączeń (&) tak:

PS> & 'C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe' 

Po że prawdopodobnie wystarczy zacytować pary parametr/argumentów, które conta w spacje i/lub znaki cudzysłowu. Gdy wywołasz taki plik EXE ze złożonymi argumentami wiersza poleceń, zazwyczaj bardzo pomocne jest narzędzie, które pokaże ci, jak PowerShell wysyła argumenty do pliku EXE. PowerShell Community Extensions ma takie narzędzie. Nazywa się to echoargs. Wystarczy zastąpić plik EXE z echoargs - pozostawiony wszystkie argumenty na miejscu, i pokaże ci, jak plik EXE otrzyma argumenty, na przykład:

PS> echoargs -verb:sync -source:dbfullsql="Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;" -dest:dbfullsql="Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;",computername=10.10.10.10,username=administrator,password=adminpass 

Arg 0 is <-verb:sync> 
Arg 1 is <-source:dbfullsql=Data> 
Arg 2 is <Source=mysource;Integrated> 
Arg 3 is <Security=false;User> 
Arg 4 is <ID=sa;Pwd=sapass!;Database=mydb;> 
Arg 5 is <-dest:dbfullsql=Data> 
Arg 6 is <Source=.\mydestsource;Integrated> 
Arg 7 is <Security=false;User> 
Arg 8 is <ID=sa;Pwd=sapass!;Database=mydb; computername=10.10.10.10 username=administrator password=adminpass> 

Korzystanie echoargs można eksperymentować, aż dojdziesz to dobrze , na przykład:

PS> echoargs -verb:sync "-source:dbfullsql=Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;" 
Arg 0 is <-verb:sync> 
Arg 1 is <-source:dbfullsql=Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;> 

Okazuje się, że starałem się zbyt mocno, aby utrzymać podwójne cudzysłowy wokół ciągu połączenia. Najwyraźniej nie jest to konieczne, ponieważ nawet cmd.exe usunie je.

BTW, czapki z głów dla zespołu PowerShell. Byli bardzo pomocni w pokazaniu mi konkretnej inkantacji pojedynczych & podwójnych cytatów, aby uzyskać pożądany wynik - jeśli zachodzi potrzeba utrzymania wewnętrznych podwójnych cytatów w miejscu. :-) Zdają sobie również sprawę z tego, że jest to obszar bólu, ale są one napędzane przez liczbę osób dotkniętych przez konkretny problem. Jeśli jest to dla ciebie obszar bólu, zagłosuj na to PowerShell bug submission.

Aby uzyskać więcej informacji na temat PowerShell analizuje, sprawdź mój Effective PowerShell blog series - konkretnie item 10 - "Understanding PowerShell Parsing Modes"

UPDATE 4/4/2012: Ta sytuacja staje się znacznie łatwiejsze w obsłudze w PowerShell V3. Zobacz ten blog post for details.

+1

jeśli używając jako drugi przykład, otrzymuję ten błąd: Error: Nierozpoznany argumentu „” -source: dbfullsql = "" "Data". Wszystkie argumenty muszą zaczynać się od "-". – Vans

+2

Przykro mi, nie rozumiem. Widzę, że obecnie 6 osób przegłosowało odpowiedź, więc brakuje mi czegoś oczywistego, ale jaka jest rzeczywista odpowiedź? Czy istnieje specjalna zasada, aby wiedzieć o parametrach ze spacjami z PowerShell, czy też sugerujesz, aby wziąć to z osobna, używając EchoArgs, aby pomóc? –

+0

Cytowanie argumentów jest zwykle wystarczające, ale nie zawsze. W tych przypadkach, w których to nie działa, użycie 'echoargs' wskazuje, w jaki sposób PowerShell interpretuje argumenty, zanim przekaże je do EXE. –

41

Wystarczy dodać operatora & przed nazwą .exe. Oto polecenie, aby zainstalować SQL Server Express w trybie ciszy:

$fileExe = "T:\SQLEXPRADV_x64_ENU.exe" 
$CONFIGURATIONFILE = "T:\ConfSetupSql2008Express.ini" 

& $fileExe /CONFIGURATIONFILE=$CONFIGURATIONFILE 
+16

Nie odpowiada to na pytanie, jak używać spacji i cudzysłowów w wierszu poleceń powershell. –

8

udało mi się dostać mój podobnego polecenia jest wykonywana przy użyciu następujące podejście:

msdeploy.exe -verb=sync "-source=dbFullSql=Server=THESERVER;Database=myDB;UID=sa;Pwd=saPwd" -dest=dbFullSql=c:\temp\test.sql 

Dla polecenia (nie, że to pomaga dużo teraz), wszystko będzie wyglądać mniej więcej tak:

msdeploy.exe -verb=sync "-source=dbfullsql=Server=mysource;Trusted_Connection=false;UID=sa;Pwd=sapass!;Database=mydb;" "-dest=dbfullsql=Server=mydestsource;Trusted_Connection=false;UID=sa;Pwd=sapass!;Database=mydb;",computername=10.10.10.10,username=administrator,password=adminpass 

kluczowe punkty to:

  • Użyj cytatów wokół argumentu źródłowego i usuń osadzone cudzysłowy wokół ciągu połączenia
  • Użyj alternatywnych nazw kluczy podczas budowania ciągu połączenia SQL, które nie zawiera spacji. Na przykład użyj "UID" zamiast "User Id", "Server" zamiast "Data Source", "Trusted_Connection" zamiast "Integrated Security", i tak dalej. Mogłem go uruchomić tylko wtedy, gdy usunąłem wszystkie spacje z ciągu połączenia.

Nie próbowałem dodawać części "computername" na końcu wiersza poleceń, ale mam nadzieję, że te informacje pomogą innym osobom odczytać to teraz, zbliżając się do pożądanego wyniku.

+1

Próbowałem wszystkich innych odpowiedzi, ale to była jedyna odpowiedź, która zadziałała dla mnie! Dziękuję za udostępnienie tej alternatywnej ścieżki. – Sentient

+0

+1 za wzmiankę o synonimach ciągów połączeń – meklarian

4

nowy ciąg ewakuacji w PowerShell V3, cytowany z New V3 Language Features:

Easier Reuse of Command Lines From Cmd.exe

web jest pełen linii poleceń napisanych dla Cmd.exe. Te wiersze komend działają dość często w PowerShellu, ale gdy zawierają pewne znaki, na przykład średnik (;), znak dolara ($) lub nawiasy klamrowe, musisz wprowadzić pewne zmiany, prawdopodobnie dodając kilka cytatów. To wydawało się źródłem wielu drobnych bólów głowy.

Aby pomóc w rozwiązaniu tego problemu, dodaliśmy nowy sposób "ucieczki" do analizowania wierszy poleceń. Jeśli użyjesz magicznego parametru -%, zatrzymamy nasze normalne analizowanie linii poleceń i przerzucimy się na coś znacznie prostszego. Nie pasujemy do ofert. Nie zatrzymujemy się na średniku. Nie rozwijamy zmiennych PowerShell. Rozszerzamy zmienne środowiskowe, jeśli używamy składni Cmd.exe (np.% TEMP%). Poza tym, argumenty aż do końca linii (lub potoku, jeśli jesteś rurociągiem) są przekazywane bez zmian. Oto przykład:

PS> echoargs.exe --% %USERNAME%,this=$something{weird} 
Arg 0 is <jason,this=$something{weird}> 
+0

Spróbuję tego później. Wydaje się fajne. –

9

Ten pracował dla mnie:

& 'D:\Server\PSTools\PsExec.exe' @('\\1.1.1.1', '-accepteula', '-d', '-i', $id, '-h', '-u', 'domain\user', '-p', 'password', '-w', 'C:\path\to\the\app', 'java', '-jar', 'app.jar') 

Wystarczy umieścić ścieżki czy ciągów połączenia w jednej pozycji tablicy i podzielić inne rzeczy w jednej pozycji tablicy każdego.

Istnieje wiele innych opcji tutaj: https://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx

Microsoft powinien uczynić ten sposób prostszy i zgodny ze składni wiersza poleceń.

23

miałem obowiązuje zarówno polecenia i parametry, a to, co pracował dla mnie:

$Command = "E:\X64\Xendesktop Setup\XenDesktopServerSetup.exe" 
$Parms = "/COMPONENTS CONTROLLER,DESKTOPSTUDIO,DESKTOPDIRECTOR,LICENSESERVER,STOREFRONT /PASSIVE /NOREBOOT /CONFIGURE_FIREWALL /NOSQL" 

$Prms = $Parms.Split(" ") 
& "$Command" $Prms 

Jest to w zasadzie taka sama jak odpowiedź Akiry, ale to działa, jeśli dynamicznie budować swoje parametry poleceń i umieścić je w zmienna.

+0

imho to jest najlepsze! nie ma base64, nie ma dziwnej - składni%, która przełącza podstawianie, normalne reguły zastępowania powłoki, nie ma zamieszania, jest bardzo czytelna. – AnneTheAgile

+0

To nie działa. Jeśli twój parametr ma nazwę ścieżki, nazwa ścieżki zostanie podzielona na wiele parametrów. – BrainSlugs83

+0

Dobra odpowiedź. Czy jednak będzie działać z cytatami w parametrach? –

3

Ten pracował dla mnie:

PowerShell.exe -Command "& ""C:\Some Script\Path With Spaces.ps1""" 

Kluczem wydaje się, że cała komenda jest w cudzysłowach zewnętrznych, w „&” ampersand jest używany do określenia innego pliku poleceń dziecko jest wykonywany, a następnie ostatecznie Escaped (double-double-) Cytaty wokół ścieżki/nazwy pliku z spacje w ciebie chciałeś wykonać w pierwszej kolejności.

Jest to również uzupełnienie jedynego obejścia problemu z połączeniem MS, że -File nie zwraca kodów zwrotnych niezerowych i -Komenda jest jedyną alternatywą. Ale do tej pory uważano, że jest to ograniczenie, ponieważ nie obsługuje przestrzeni. Zaktualizowałem też ten element opinii.

http://connect.microsoft.com/PowerShell/feedback/details/750653/powershell-exe-doesn-t-return-correct-exit-codes-when-using-the-file-option

+0

To nie jest związane z pytaniem o ops, specjalnie zapytał, jak uruchomić długie polecenie w swoim poście w grze powershell. Nie jest to, jak uruchamiać skrypt powłoki z spacjami w ścieżce pliku. – leinad13

+0

Przeczytaj tytuł pytania, przestrzenie są problemem, a nie długością. Jest to jedna poprawna odpowiedź na takie problemy, którymi warto się podzielić. Czy masz ten sam problem i faktycznie go wypróbujesz? Jeśli chcesz ją poprawić, prześlij poprawkę zawierającą faktyczne polecenie w pytaniu, a ja ją zaakceptuję. –

3

Alternatywnym rozwiązaniem jest użycie przełącznika Base64 zakodowane polecenia:

powershell -EncodedCommand "QwA6AFwAUAByAG8AZwByAGEAbQAgAEYAaQBsAGUAcwBcAEkASQBTAFwATQBpAGMAcgBvAHMAbwBmAHQAIABXAGUAYgAgAEQAZQBwAGwAbwB5AFwAbQBzAGQAZQBwAGwAbwB5AC4AZQB4AGUAIAAtAHYAZQByAGIAOgBzAHkAbgBjACAALQBzAG8AdQByAGMAZQA6AGQAYgBmAHUAbABsAHMAcQBsAD0AIgBEAGEAdABhACAAUwBvAHUAcgBjAGUAPQBtAHkAcwBvAHUAcgBjAGUAOwBJAG4AdABlAGcAcgBhAHQAZQBkACAAUwBlAGMAdQByAGkAdAB5AD0AZgBhAGwAcwBlADsAVQBzAGUAcgAgAEkARAA9AHMAYQA7AFAAdwBkAD0AcwBhAHAAYQBzAHMAIQA7AEQAYQB0AGEAYgBhAHMAZQA9AG0AeQBkAGIAOwAiACAALQBkAGUAcwB0ADoAZABiAGYAdQBsAGwAcwBxAGwAPQAiAEQAYQB0AGEAIABTAG8AdQByAGMAZQA9AC4AXABtAHkAZABlAHMAdABzAG8AdQByAGMAZQA7AEkAbgB0AGUAZwByAGEAdABlAGQAIABTAGUAYwB1AHIAaQB0AHkAPQBmAGEAbABzAGUAOwBVAHMAZQByACAASQBEAD0AcwBhADsAUAB3AGQAPQBzAGEAcABhAHMAcwAhADsARABhAHQAYQBiAGEAcwBlAD0AbQB5AGQAYgA7ACIALABjAG8AbQBwAHUAdABlAHIAbgBhAG0AZQA9ADEAMAAuADEAMAAuADEAMAAuADEAMAAsAHUAcwBlAHIAbgBhAG0AZQA9AGEAZABtAGkAbgBpAHMAdAByAGEAdABvAHIALABwAGEAcwBzAHcAbwByAGQAPQBhAGQAbQBpAG4AcABhAHMAcwAiAA==" 

Po zdekodowaniu, zobaczysz, że to oryginalny fragment PO za wszystkich argumentów i cudzysłowy zachowanych.

powershell.exe -EncodedCommand 

Accepts a base-64-encoded string version of a command. Use this parameter 
to submit commands to Windows PowerShell that require complex quotation 
marks or curly braces. 

Oryginalny polecenie:

C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe -verb:sync -source:dbfullsql="Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;" -dest:dbfullsql="Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;",computername=10.10.10.10,username=administrator,password=adminpass" 

Okazuje się to, gdy zakodowany jako base64:

QwA6AFwAUAByAG8AZwByAGEAbQAgAEYAaQBsAGUAcwBcAEkASQBTAFwATQBpAGMAcgBvAHMAbwBmAHQAIABXAGUAYgAgAEQAZQBwAGwAbwB5AFwAbQBzAGQAZQBwAGwAbwB5AC4AZQB4AGUAIAAtAHYAZQByAGIAOgBzAHkAbgBjACAALQBzAG8AdQByAGMAZQA6AGQAYgBmAHUAbABsAHMAcQBsAD0AIgBEAGEAdABhACAAUwBvAHUAcgBjAGUAPQBtAHkAcwBvAHUAcgBjAGUAOwBJAG4AdABlAGcAcgBhAHQAZQBkACAAUwBlAGMAdQByAGkAdAB5AD0AZgBhAGwAcwBlADsAVQBzAGUAcgAgAEkARAA9AHMAYQA7AFAAdwBkAD0AcwBhAHAAYQBzAHMAIQA7AEQAYQB0AGEAYgBhAHMAZQA9AG0AeQBkAGIAOwAiACAALQBkAGUAcwB0ADoAZABiAGYAdQBsAGwAcwBxAGwAPQAiAEQAYQB0AGEAIABTAG8AdQByAGMAZQA9AC4AXABtAHkAZABlAHMAdABzAG8AdQByAGMAZQA7AEkAbgB0AGUAZwByAGEAdABlAGQAIABTAGUAYwB1AHIAaQB0AHkAPQBmAGEAbABzAGUAOwBVAHMAZQByACAASQBEAD0AcwBhADsAUAB3AGQAPQBzAGEAcABhAHMAcwAhADsARABhAHQAYQBiAGEAcwBlAD0AbQB5AGQAYgA7ACIALABjAG8AbQBwAHUAdABlAHIAbgBhAG0AZQA9ADEAMAAuADEAMAAuADEAMAAuADEAMAAsAHUAcwBlAHIAbgBhAG0AZQA9AGEAZABtAGkAbgBpAHMAdAByAGEAdABvAHIALABwAGEAcwBzAHcAbwByAGQAPQBhAGQAbQBpAG4AcABhAHMAcwAiAA== 

i tutaj jest jak replikować w domu:

$command = 'C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe -verb:sync -source:dbfullsql="Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;" -dest:dbfullsql="Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;",computername=10.10.10.10,username=administrator,password=adminpass"' 
$bytes = [System.Text.Encoding]::Unicode.GetBytes($command) 
$encodedCommand = [Convert]::ToBase64String($bytes) 
$encodedCommand 

# The clip below copies the base64 string to your clipboard for right click and paste. 
$encodedCommand | Clip 
3

Wypróbowałem wszystkie sugestie, ale byłem sti Nie można uruchomić msiexec.exe z parametrami zawierającymi spacje. Więc moje rozwiązanie skończył przy użyciu System.Diagnostics.ProcessStartInfo:

# can have spaces here, no problems 
$settings = @{ 
    CONNECTION_STRING = "... ..." 
    ENTITY_CONTEXT = "... ..." 
    URL = "..." 
} 

$settingsJoined = ($settings.Keys | % { "$_=""$($settings[$_])""" }) -join " " 
$pinfo = New-Object System.Diagnostics.ProcessStartInfo 
$pinfo.WorkingDirectory = $ScriptDirectory 
$pinfo.FileName = "msiexec.exe" 
$pinfo.RedirectStandardError = $true 
$pinfo.RedirectStandardOutput = $true 
$pinfo.UseShellExecute = $false 
$pinfo.Arguments = "/l* install.log /i installer.msi $settingsJoined" 
$p = New-Object System.Diagnostics.Process 
$p.StartInfo = $pinfo 
$p.Start() | Out-Null 
$p.WaitForExit() 
$stdout = $p.StandardOutput.ReadToEnd() 
0

Więc wpadłem na podobny problem i zdecydował się go rozwiązać w ten sposób zamiast:

  1. Ucieczka swoje cytatów (") postacie z lewy apostrof (`)
  2. Otocz swój nowy wyraz z cytatów (")
  3. pomocą operatora połączeń (&), wydać polecenie invoke-expression na nowy ciąg

Przykład rozwiązania:

& { invoke-expression "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe -verb:sync -source:dbfullsql=`"Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;`" -dest:dbfullsql=`"Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;`",computername=10.10.10.10,username=administrator,password=adminpass`"" }

0

W przypadku ktoś zastanawia się, jak wystarczy uruchomić plik wykonywalny:

.....> \ plik..exe

lub

......> pełna \ ścieżka \ do \ file.exe

0

Istnieje sporo metod można użyć, aby to zrobić.

There are other methods like using the Call Operator (&), Invoke-Expression cmdlet etc. But they are considered unsafe. Microsoft recommends using Start-Process.

Metoda 1

prosty przykład

Start-Process -NoNewWindow -FilePath "C:\wamp64\bin\mysql\mysql5.7.19\bin\mysql" -ArgumentList "-u root","-proot","-h localhost" 

W twoim przypadku

Start-Process -NoNewWindow -FilePath "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" -ArgumentList "-verb:sync","-source:dbfullsql=`"Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;`"","-dest:dbfullsql=`"Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;`"","computername=10.10.10.10","username=administrator","password=adminpass" 

W ten sposób oddzielić każdy parametr w ArgumentList za pomocą przecinków.

Metoda 2

Prosty przykład

Start-Process -NoNewWindow -FilePath "C:\wamp64\bin\mysql\mysql5.7.19\bin\mysql" -ArgumentList "-u root -proot -h localhost" 

W twoim przypadku

Start-Process -NoNewWindow -FilePath "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" -ArgumentList "-verb:sync -source:dbfullsql=`"Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;`" -dest:dbfullsql=`"Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;`",computername=10.10.10.10,username=administrator,password=adminpass" 

Metoda ta jest łatwiejsza, gdyż pozwala wpisać parametry jednym zamachem.

Note that in powershell to represent the quotation mark (") in a string you should insert the grave accent (`) (This is the key above the Tab key in the US keyboard).

-NoNewWindow parameter is used to display the new process in the current console window. By default Windows PowerShell opens a new window.

Referencje: Powershell/Scripting/Start-Process

Powiązane problemy