web-dev-qa-db-ja.com

スペースと引用符を含むパラメーターを使用してPowerShellでEXEファイルを実行する方法

PowerShellで次のコマンドをどのように実行しますか?

C:¥Program Files¥IIS¥Microsoft Web Deploy¥msdeploy.exe -verb:sync -source:dbfullsql = "データソース= mysource;統合セキュリティ= false;ユーザーID = sa;パスワード= sapass!;データベース= mydb;" -dest:dbfullsql = "データソース=。\ mydestsource;統合セキュリティ= false;ユーザーID = sa;パスワード= sapass!;データベース= mydb;"、コンピュータ名= 10.10.10.10、ユーザー名= administrator、パスワード= adminpass "

278
Vans

PowerShellが文字列で始まるコマンドを検出した場合、その文字列を評価するだけです。つまり、通常は画面にエコー表示します。次に例を示します。

PS> "Hello World"
Hello World

PowerShellに文字列をコマンド名として解釈させたい場合は、次のように呼び出し演算子(&)を使用します。

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

その後は、おそらくスペースや引用符を含むパラメータと引数のペアだけを引用符で囲む必要があります。複雑なコマンドライン引数を使用してこのようなEXEファイルを呼び出す場合、PowerShellがどのようにしてEXEファイルに引数を送信するのかを示すツールがあると便利です。 PowerShellコミュニティ拡張 にはそのようなツールがあります。それはechoargsと呼ばれます。 EXEファイルをechoargsに置き換えるだけで、すべての引数がそのまま残り、EXEファイルが引数を受け取る方法がわかります。次に例を示します。

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>

Echoargsを使うと、正しくなるまで試してみることができます。例えば:

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;>

結局、接続文字列を二重引用符で囲むのは難しすぎました。 cmd.exeでもそれらが取り除かれるので、どうやらそれは必要ではありません。

ところで、PowerShellチームに敬意を表します。内部の二重引用符をそのままにしておく必要がある場合は、希望する結果を得るための一重引用符と二重引用符の具体的な意味を教えてください。 :-)彼らはまたこれが痛みの領域であることを認識していますが、彼らは特定の問題の影響を受ける人々の数によって動かされています。これがあなたにとって苦痛な分野であるならば、これを投票してください PowerShellバグ投稿

PowerShellの解析方法の詳細については、私の 効果的なPowerShellブログシリーズをチェックしてください - 特に item 10 - "PowerShellの解析モードについて"

UPDATE 4/4/2012:この状況はPowerShell V3では扱いやすくなりました。詳しくは ブログ記事を参照してください

294
Keith Hill

.exe名の前に演算子を追加するだけです。これは、SQL Server Expressをサイレントモードでインストールするためのコマンドです。

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

& $fileExe  /CONFIGURATIONFILE=$CONFIGURATIONFILE
50
nonolde1er

コマンドとパラメータの両方にスペースがありましたが、これが私にとって役に立ちました。

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

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

基本的にはAkiraの答えと同じですが、これはあなたが動的にあなたのコマンドパラメータを構築し変数にそれらを入れる場合にうまくいきます。

40
Microb

これは私のために働いた:

& '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')

パスまたは接続文字列を1つの配列項目に配置し、他のものをそれぞれ1つの配列項目に分割するだけです。

ここに他の多くのオプションがあります: https://social.technet.Microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx

Microsoftはこの方法をよりシンプルにし、コマンドプロンプト構文と互換性を持たせるべきです。

16
Akira Yamamoto

このページを参照してください。 https://slai.github.io/posts/powershell-and-external-commands-done-right/

外部実行可能ファイルとしてvshadowを使用した要約

$exe = "H:\backup\scripts\vshadow.exe"
&$exe -p -script=H:\backup\scripts\vss.cmd E: M: P:
12
Baodad

誰かが単に実行可能ファイルを実行する方法を考えていないのであれば:

.....>。\ file.exe

または

......> full\path\to\file.exe

11
darkgaze

私は私の似たようなコマンドを以下の方法でうまく動かすことができた。

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

あなたの命令のために(それが今大いに役立つというわけではない)、ものはこのようなものになるでしょう:

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

重要な点は次のとおりです。

  • Source引数を引用符で囲み、接続文字列を囲んでいる引用符を削除します。
  • スペースを含まないSQL接続文字列を作成する際には、代替キー名を使用してください。たとえば、「ユーザーID」の代わりに「UID」、「データソース」の代わりに「サーバー」、「統合セキュリティ」の代わりに「Trusted_Connection」などを使用します。接続文字列からすべてのスペースを削除すると、動作するようになりました。

私はコマンドラインの最後に "computername"の部分を追加しようとはしませんでしたが、うまくいけばこの情報を読んで他の人が彼らの望む結果に近づくのを助けるでしょう。

8
G-Mac

から引用したPowerShell V3の新しいエスケープ文字列 - 新しいV3言語の機能

Cmd.exeからのコマンドラインのより簡単な再利用

WebはCmd.exeのために書かれたコマンドラインでいっぱいです。これらのコマンドラインはPowerShellでは十分に機能しますが、セミコロン(;)、ドル記号($)、中括弧などの特定の文字が含まれている場合は、いくつかの変更を加える必要があります。これは多くのマイナーな頭痛の原因と思われました。

このシナリオに対処するために、コマンドラインの解析を「エスケープ」する新しい方法を追加しました。もしあなたが魔法のパラメータ - %を使うなら、私たちはあなたのコマンドラインの通常の解析をやめて、もっと簡単なものに切り替えます。見積もりは一致しません。セミコロンに留まらないでください。 PowerShellの変数は拡張しません。 Cmd.exe構文を使用している場合は、環境変数を拡張します(例:%TEMP%)。それ以外は、行の終わりまでの引数(またはパイプを使用している場合はパイプ)はそのまま渡されます。これが一例です。

PS> echoargs.exe --% %USERNAME%,this=$something{weird}
Arg 0 is <jason,this=$something{weird}>
6
Loïc MICHEL

あなたがそれをするのに使用できるかなり多くの方法があります。

呼び出し演算子()、 Invoke-Expression cmdletなどを使用する方法は他にもありますが、安全ではないと見なされます。 Microsoftでは、 Start-Process の使用を推奨しています。

方法1

簡単な例

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

あなたの場合

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"

このメソッドでは、ArgumentList内の各パラメーターをコンマで区切ります。

方法2

簡単な例

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

あなたの場合

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"

この方法は、パラメータを一度に入力できるので簡単です。

PowerShellでは、 引用符( ")を文字列 で表すには、 Graveアクセント(`) を挿入する必要があります(これはUSキーボードのTabキーの上にあるキーです)。 。

-NoNewWindow パラメータは、現在のコンソールウィンドウに新しいプロセスを表示するために使用されます。既定では、Windows PowerShellは新しいウィンドウを開きます。

参照先: Powershell /スクリプト/ Start-Process

6

私はすべての提案を試してみましたが、スペースを含むパラメータでmsiexec.exeを実行することはまだできませんでした。だから私の解決策は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()
4

別の答えは Base64 encodedコマンドスイッチを使用することです。

powershell -EncodedCommand "QwA6AFwAUAByAG8AZwByAGEAbQAgAEYAaQBsAGUAcwBcAEkASQBTAFwATQBpAGMAcgBvAHMAbwBmAHQAIABXAGUAYgAgAEQAZQBwAGwAbwB5AFwAbQBzAGQAZQBwAGwAbwB5AC4AZQB4AGUAIAAtAHYAZQByAGIAOgBzAHkAbgBjACAALQBzAG8AdQByAGMAZQA6AGQAYgBmAHUAbABsAHMAcQBsAD0AIgBEAGEAdABhACAAUwBvAHUAcgBjAGUAPQBtAHkAcwBvAHUAcgBjAGUAOwBJAG4AdABlAGcAcgBhAHQAZQBkACAAUwBlAGMAdQByAGkAdAB5AD0AZgBhAGwAcwBlADsAVQBzAGUAcgAgAEkARAA9AHMAYQA7AFAAdwBkAD0AcwBhAHAAYQBzAHMAIQA7AEQAYQB0AGEAYgBhAHMAZQA9AG0AeQBkAGIAOwAiACAALQBkAGUAcwB0ADoAZABiAGYAdQBsAGwAcwBxAGwAPQAiAEQAYQB0AGEAIABTAG8AdQByAGMAZQA9AC4AXABtAHkAZABlAHMAdABzAG8AdQByAGMAZQA7AEkAbgB0AGUAZwByAGEAdABlAGQAIABTAGUAYwB1AHIAaQB0AHkAPQBmAGEAbABzAGUAOwBVAHMAZQByACAASQBEAD0AcwBhADsAUAB3AGQAPQBzAGEAcABhAHMAcwAhADsARABhAHQAYQBiAGEAcwBlAD0AbQB5AGQAYgA7ACIALABjAG8AbQBwAHUAdABlAHIAbgBhAG0AZQA9ADEAMAAuADEAMAAuADEAMAAuADEAMAAsAHUAcwBlAHIAbgBhAG0AZQA9AGEAZABtAGkAbgBpAHMAdAByAGEAdABvAHIALABwAGEAcwBzAHcAbwByAGQAPQBhAGQAbQBpAG4AcABhAHMAcwAiAA=="

デコードすると、すべての引数と二重引用符が保持されたOPの元のスニペットになります。

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.

元のコマンド:

 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"

Base64としてエンコードされるとこれになります。

QwA6AFwAUAByAG8AZwByAGEAbQAgAEYAaQBsAGUAcwBcAEkASQBTAFwATQBpAGMAcgBvAHMAbwBmAHQAIABXAGUAYgAgAEQAZQBwAGwAbwB5AFwAbQBzAGQAZQBwAGwAbwB5AC4AZQB4AGUAIAAtAHYAZQByAGIAOgBzAHkAbgBjACAALQBzAG8AdQByAGMAZQA6AGQAYgBmAHUAbABsAHMAcQBsAD0AIgBEAGEAdABhACAAUwBvAHUAcgBjAGUAPQBtAHkAcwBvAHUAcgBjAGUAOwBJAG4AdABlAGcAcgBhAHQAZQBkACAAUwBlAGMAdQByAGkAdAB5AD0AZgBhAGwAcwBlADsAVQBzAGUAcgAgAEkARAA9AHMAYQA7AFAAdwBkAD0AcwBhAHAAYQBzAHMAIQA7AEQAYQB0AGEAYgBhAHMAZQA9AG0AeQBkAGIAOwAiACAALQBkAGUAcwB0ADoAZABiAGYAdQBsAGwAcwBxAGwAPQAiAEQAYQB0AGEAIABTAG8AdQByAGMAZQA9AC4AXABtAHkAZABlAHMAdABzAG8AdQByAGMAZQA7AEkAbgB0AGUAZwByAGEAdABlAGQAIABTAGUAYwB1AHIAaQB0AHkAPQBmAGEAbABzAGUAOwBVAHMAZQByACAASQBEAD0AcwBhADsAUAB3AGQAPQBzAGEAcABhAHMAcwAhADsARABhAHQAYQBiAGEAcwBlAD0AbQB5AGQAYgA7ACIALABjAG8AbQBwAHUAdABlAHIAbgBhAG0AZQA9ADEAMAAuADEAMAAuADEAMAAuADEAMAAsAHUAcwBlAHIAbgBhAG0AZQA9AGEAZABtAGkAbgBpAHMAdAByAGEAdABvAHIALABwAGEAcwBzAHcAbwByAGQAPQBhAGQAbQBpAG4AcABhAHMAcwAiAA==

これが自宅で複製する方法です。

$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
Knuckle-Dragger

ExeファイルをPowerShellのさまざまな方法で実行できます。たとえば、unrar.exeを実行して.rarファイルを抽出する場合は、単純に次のようにpowershellで記述できます。

$extract_path = "C:\Program Files\Containing folder";
$rar_to_extract = "C:\Path_to_Arch\file.rar"; #(or.exe if its a big file)  
C:\Path_here\Unrar.exe x -o+ -c- $rar_to_extract $extract_path;

しかし、時にはこれでうまくいかないので、上記のように&パラメータを使用する必要があります。たとえば、vboxmanage.exe(仮想ボックス仮想マシンを管理するツール)では、引用符なしでこのように文字列の外側でパラメータを呼び出す必要があります。

> $vmname = "misae_unrtes_1234123"; #(name too long, we want to change this)
> & 'C:\Program Files\Oracle\VirtualBox\VBoxManage.exe' modifyvm $vmname --name UBUNTU;

単純にwinrarアーカイブファイルを.exeファイルとして呼び出したい場合は、invoke-commandコマンドレットとSilentパラメータ/ S(圧縮されている場所と同じフォルダに自分自身を展開する予定)を使用して解凍することもできます。

> Invoke-Command -ScriptBlock { C:\Your-path\archivefile.exe /S };

そのため、powershellで引数を付けて.exeファイルを実行する方法はいくつかあります。

時々、それはきちんと動くようにするための回避策を見つけなければなりません、それは.exeがコンパイルされたか、またはその創作者にされた方法に依存して、いくらかのさらなる努力と苦痛を必要とします。

3
Andy McRae

これは私のために働いた:

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

重要なのは、コマンド全体を外側の引用符で囲み、 "&"のアンパサンドを使用して別の子コマンドファイルを実行することを指定し、最後にパスとファイル名をスペースで囲んでエスケープすることです。あなたはそもそも実行したかったのです。

これは、MS Connectの問題に対する-Fileがゼロ以外の戻りコードを返さず、-Commandが唯一の選択肢であるという唯一の回避策の完了でもあります。しかし今までのところ-Commandの限界はスペースをサポートしていないということでした。私はそのフィードバック項目も更新しました。

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

3
Tony Wall

私のラップトップでは次のようなコードが完璧に動作していました。

& $msdeploy `
-source:package="$publishFile" `
-dest:auto,computerName="$server",includeAcls="False",UserName="$username",Password="$password",AuthType="$auth" `
-allowUntrusted  `
-verb:sync  `
-enableRule:DoNotDeleteRule `
-disableLink:AppPoolExtension  `
-disableLink:ContentExtension  `
-disableLink:CertificateExtension  `
-skip:objectName=filePath,absolutePath="^(.*Web\.config|.*Environment\.config)$" `
-setParam:name=`"IIS Web Application Name`",value="$appName"

それから私は1つのサーバー上で直接それを実行しようとしたとき私はそれらのエラーを取得し始めました"Unrecognized argument ...etc.... All arguments must begin with "-". "

考えられるすべての回避策(成功しなかった)を試した後、私のラップトップは5.0を持っていますが、サーバー(Windows 2008 R2)上のPowershellはバージョン3.0であることがわかりました。 (あなたはバージョンを見るために "$ PSVersionTable"を使うことができます)。

Powershell を最新バージョンにアップグレードした後、再び動作し始めました。

1
drizin

だから、私は同様の問題に遭遇し、代わりにこの方法でそれを解決することを選びました:

  1. バッククォート( `)で引用符(")をエスケープする
  2. 新しい式を引用符( ")で囲みます
  3. 呼び出し演算子(&)を使用して、新しい文字列に対してコマンドinvoke-expressionを発行します。

解決策の例:

&{invoke-expression "C:¥Program Files¥IIS¥Microsoft Web Deploy¥msdeploy.exe -verb:sync - source:dbfullsql =` "データソース= mysource;統合セキュリティ= false;ユーザーID = sa;パスワード= sapass !; Database = mydb; `" -dest:dbfullsql = `"データソース=。\ mydestsource;統合セキュリティ= false;ユーザーID = sa;パスワード= sapass!;データベース= mydb; `"、computername = 10.10.10.10、 username = administrator、password = adminpass` ""}

0
Randall Borck

実行可能ファイル名には、new-aliascmdletを使用して、スペースを処理したり、実行可能ファイルを$ PATH環境に追加したりする必要がなくなります。

PS> new-alias msdeploy "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe"
PS> msdeploy ...

PSエイリアスを一覧表示または変更するには、も参照してください。

PS> get-alias
PS> set-alias

From Jeffery Hicks Aarticle

他の答えは議論に対処する。

0
crokusek

次を使用できます。

Start-Process -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"

ここで注意すべき重要な点は、ヘルプガイドによると、FilePathの位置は0でなければならないということです。コマンドレットのヘルプガイドを呼び出すには、Get-Help <Commandlet-name> -Detailedと入力するだけです。この場合、Get-Help Start-Process -Detailedです。

0
CyrilDex

私はこの簡単で、きれいでそして効果的な方法を使います。

引数を1行に1つずつ配列に入れます。これにより、読みやすく編集しやすくなります。次に、すべての引数を二重引用符で囲み、1つの単一パラメーターを持つ関数に渡すという簡単なトリックを使用します。それは配列を含むそれらを単一の文字列に平坦化し、それをPSの 'Invoke-Expression'を使って実行します。このディレクティブは、文字列を実行可能なコマンドに変換するように特別に設計されています。うまくいきます:

                    # function with one argument will flatten 
                    # all passed-in entries into 1 single string line
Function Execute($command) {
                    # execute:
    Invoke-Expression $command;
                    # if you have trouble try:
  # Invoke-Expression "& $command";
                    # or if you need also output to a variable
  # Invoke-Expression $command | Tee-Object -Variable cmdOutput;

}

#  ... your main code here ...

               # The name of your executable app
$app = 'my_app.exe';
               # List of arguments:
               #    Notice the type of quotes - important !
               #    Those in single quotes are normal strings, like 'Peter'
$args = 'arg1',
        'arg2',
        $some_variable,
        'arg4',
        "arg5='with quotes'",
        'arg6',
        "arg7 \ with \ $other_variable",
        'etc...';

               # pass all arguments inside double quotes
Execute "$app $args";
0
Felix