วิธีเรียกใช้ไฟล์ EXE ใน PowerShell ด้วยพารามิเตอร์ที่มีช่องว่างและเครื่องหมายคำพูด


333

คุณรันคำสั่งต่อไปนี้ใน PowerShell ได้อย่างไร

C: \ Program Deploy \ msdeploy.exe Web \ Files \ IIS \ Microsoft เว็บ - แหล่งข้อมูล: ซิงค์: dbfullsql = "แหล่งข้อมูล = mysource; Integrated Security = false ID ผู้ใช้ = sa; Pwd = sapass!; ฐานข้อมูล = mydb;" -dest: dbfullsql = "Data Source =. \ mydestsource; Integrated Security = false; ID ผู้ใช้ = sa; Pwd = sapass!; ฐานข้อมูล = mydb;", computername = 10.10.10.10, ชื่อผู้ใช้ = ผู้ดูแลระบบ, รหัสผ่าน = adminpass "



หากคุณหมายถึง litteraly "ใน PowerShell" (ซึ่งฉันตีความหมายถึง "ภายในพรอมต์ PowerShell ที่มีอยู่แล้ว) ตัวอย่างต่อไปนี้สามารถ adpated ได้อย่างง่ายดายเพื่อให้ตรงกับความต้องการของคุณสังเกตเห็นว่าไม่จำเป็นต้องแยกคำสั่งจากพารามิเตอร์: # Show any available updates to globally installed npm packages using the npm-check-updates tool [string] $cmd = 'ncu -g' Write-Verbose -Message $cmd Invoke-Command -ScriptBlock ([ScriptBlock]::Create($cmd))
user3785010

ฉันไม่รู้ว่าจะใช้ "mini-markdown" เพื่อแก้ไขความคิดเห็นข้างต้นเพื่อให้แต่ละบรรทัดของรหัสปรากฏในบรรทัดที่แยกกันและการ จำกัด เวลา 5 นาทีในการแก้ไขความคิดเห็นเดิมหมดอายุแล้ว หากใครรู้ตอนนี้ใช้ "mini-Markdown" เพื่อแก้ไขปัญหาฉันจะโพสต์ในรูปแบบที่อ่านได้ง่ายขึ้น บรรทัดแรกควรเป็นดังต่อไปนี้: # แสดงการอัปเดตใด ๆ ที่มีให้กับแพ็กเกจ npm ที่ติดตั้งทั่วโลกโดยใช้เครื่องมือตรวจสอบการอัปเดต
npm

คำตอบ:


347

เมื่อ 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 จะกำจัดสิ่งเหล่านั้นออก

BTW สวมหมวกให้กับทีม PowerShell พวกเขาค่อนข้างมีประโยชน์ในการแสดงให้ฉันเห็นคาถาที่เฉพาะเจาะจงของคำพูดเดี่ยวและสองเพื่อให้ได้ผลลัพธ์ที่ต้องการ - ถ้าคุณต้องการที่จะให้คำพูดคู่ภายในอยู่ในสถานที่ :-) พวกเขายังตระหนักว่านี่เป็นพื้นที่แห่งความเจ็บปวด แต่พวกเขาได้รับผลกระทบจากจำนวนคนที่ได้รับผลกระทบจากปัญหาเฉพาะ หากนี่เป็นเรื่องที่เจ็บปวดสำหรับคุณโปรดลงคะแนนการส่งบั๊ก PowerShellนี้

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการแยกวิเคราะห์ PowerShell ให้ดูซีรี่ส์บล็อก PowerShell ที่มีประสิทธิภาพของฉัน- รายการเฉพาะ10 - "การทำความเข้าใจโหมด PowerShell ในการแยกวิเคราะห์"

UPDATE 4/4/2012: สถานการณ์นี้ง่ายต่อการจัดการใน PowerShell V3 เห็นนี้โพสต์บล็อกสำหรับรายละเอียด


1
หากใช้เป็นตัวอย่างที่สองฉันได้รับข้อผิดพลาดนี้: ข้อผิดพลาด: อาร์กิวเมนต์ที่ไม่รู้จัก '"-source: dbfullsql =" "" Data " อาร์กิวเมนต์ทั้งหมดจะต้องเริ่มต้นด้วย "-"
รถตู้

2
ฉันขอโทษฉันไม่เข้าใจ ฉันเห็นว่าในปัจจุบันมี 6 คนยกคำตอบขึ้นมาดังนั้นฉันจึงขาดสิ่งที่เห็นได้ชัด แต่คำตอบที่แท้จริงคืออะไร มีกฎพิเศษที่ต้องรู้เกี่ยวกับพารามิเตอร์ที่มีช่องว่างด้วย PowerShell หรือคุณเพียงแค่แนะนำให้ใช้เป็นกรณี ๆ ไปโดยใช้ EchoArgs เพื่อช่วย?
Tyler Collier

การอ้างถึงข้อโต้แย้งมักจะเพียงพอ แต่ไม่เสมอไป ในกรณีที่ไม่สามารถใช้งานได้echoargsจะมีตัวบ่งชี้ว่า PowerShell ตีความการขัดแย้งก่อนที่มันจะส่งผ่านไปยัง EXE ได้อย่างไร
Keith Hill

1
คุณรู้หรือไม่ว่าฉันจะทำสิ่งนี้ในไฟล์. bat? ฉันพยายาม& 'C:\Program Files\Sublime Text 3\sublime_text.exe'โดยตรงในคอนโซลและมันใช้งานได้ แต่ในแบทช์ไฟล์ฉันได้รับข้อผิดพลาดว่า "& ไม่คาดคิดในเวลานี้"
Joe Zim

ไม่เป็นไร. พบมัน:START C:\"Program Files"\"Sublime Text 3"\sublime_text.exe
Joe Zim

61

เพียงเพิ่มตัวดำเนินการ&ก่อนชื่อ. exe นี่คือคำสั่งในการติดตั้ง SQL Server Express ในโหมดเงียบ:

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

& $fileExe  /CONFIGURATIONFILE=$CONFIGURATIONFILE

53

ฉันมีช่องว่างทั้งในคำสั่งและพารามิเตอร์และนี่คือสิ่งที่ใช้ได้กับฉัน:

$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 แต่วิธีนี้ใช้ได้ผลถ้าคุณสร้างพารามิเตอร์คำสั่งของคุณแบบไดนามิกและวางไว้ในตัวแปร


2
อิมโฮนี่ดีที่สุด! ไม่มี base64, ไม่แปลก -% ไวยากรณ์ที่สลับการทดแทน, กฎการทดแทน PowerShell ปกติ, ไม่มีความสับสนอ่านง่ายมาก
AnneTheAgile

1
มันใช้งานไม่ได้ หากพารามิเตอร์ของคุณมีชื่อเส้นทางในนั้นชื่อเส้นทางจะถูกแบ่งออกเป็นหลายพารามิเตอร์
BrainSlugs83

1
คำตอบที่ดี อย่างไรก็ตามมันจะทำงานกับเครื่องหมายคำพูดในพารามิเตอร์ได้หรือไม่
Akira Yamamoto

โปรดลองสิ่งนี้หลังจากทุกอย่างใช้งานได้จริง และยังใช้ส่วนขยาย PowershellEchoArgs
Jeremy Thompson

34

สิ่งนี้ใช้ได้กับฉัน:

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

เพียงแค่ใส่พา ธ หรือสตริงการเชื่อมต่อในรายการอาร์เรย์หนึ่งและแยกสิ่งอื่น ๆ ในรายการอาร์เรย์หนึ่งรายการ

มีตัวเลือกอื่น ๆ อีกมากมายที่นี่: https://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx

Microsoft ควรทำให้วิธีนี้ง่ายขึ้นและเข้ากันได้กับไวยากรณ์ของพรอมต์คำสั่ง


2
Array เป็นตัวเลือกที่ดีที่สุดแน่นอน - ใช้งานได้ดีสำหรับฉัน ยกเว้นฉันผ่านตัวแปรอาเรย์เพราะข้อโต้แย้งของฉันเป็นแบบไดนามิก ขอบคุณ
Jon Barker

ทางออกที่ดีที่สุด IMHO
Vasin Yuriy

25

มีวิธีการค่อนข้างน้อยที่คุณสามารถใช้เพื่อทำมัน

มีวิธีการอื่นเช่นการใช้ Call Operator ( & ), Invoke-Expression cmdlet เป็นต้น แต่ก็ถือว่าไม่ปลอดภัย ไมโครซอฟท์แนะนำให้ใช้การเริ่มต้นกระบวนการ

วิธีที่ 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 เพื่อแสดงเครื่องหมายคำพูด (") ในสตริงคุณควรแทรกเครื่องหมายเน้นเสียง (`) (นี่คือกุญแจเหนือปุ่ม Tab ในแป้นพิมพ์ US)

-NoNewWindow พารามิเตอร์ใช้เพื่อแสดงกระบวนการใหม่ในหน้าต่างคอนโซลปัจจุบัน ตามค่าเริ่มต้น Windows PowerShell จะเปิดหน้าต่างใหม่

ข้อมูลอ้างอิง: Powershell / Scripting / Start-Process


ง่าย ๆ ชนะเสมอ! ขอบคุณ
Mike Casas

ขอบคุณสำหรับบันทึกสุดท้ายในการหลีกเลี่ยงเครื่องหมายคำพูด!
เปาโล


13

ในกรณีที่มีคนสงสัยว่าจะเรียกใช้ไฟล์ที่ปฏิบัติการได้อย่างไร:

..... >. \ \ file.exe

หรือ

...... > เต็ม \ path \ to \ file.exe


2
นี่ควรเป็นคำตอบสำหรับคำถามนั้นมันเป็นสิ่งที่เรากำลังมองหาเมื่อเราค้นหาด้วยคำหลัก "เริ่ม EXE จาก PowerShell" ขอบคุณ !
Jean-Daniel Gasser

2
วิธีการเกี่ยวกับการทำงานกับข้อโต้แย้ง?
SereneWizard

1
@SereneWizard ดีเพิ่มพวกเขาหลังจาก. exe มีช่องว่างในระหว่าง ตัวอย่าง:. \ file.exe param1 param2 param3
darkgaze

9

ฉันสามารถทำให้คำสั่งที่คล้ายกันทำงานโดยใช้วิธีการต่อไปนี้:

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

ประเด็นสำคัญคือ:

  • ใช้อัญประกาศรอบ ๆ อาร์กิวเมนต์แหล่งที่มาและเอาอัญประกาศที่ฝังอยู่รอบ ๆ สายอักขระการเชื่อมต่อ
  • ใช้ชื่อคีย์ทางเลือกในการสร้างสตริงการเชื่อมต่อ SQL ที่ไม่มีช่องว่าง ตัวอย่างเช่นใช้ "UID" แทน "รหัสผู้ใช้", "เซิร์ฟเวอร์" แทน "แหล่งข้อมูล", "Trusted_Connection" แทน "ความปลอดภัยแบบรวม" และอื่น ๆ ฉันสามารถใช้งานได้ก็ต่อเมื่อฉันลบช่องว่างทั้งหมดออกจากสตริงการเชื่อมต่อ

ฉันไม่ได้ลองเพิ่มส่วน "ชื่อคอมพิวเตอร์" ที่ท้ายบรรทัดคำสั่ง แต่หวังว่าข้อมูลนี้จะช่วยให้ผู้อื่นที่อ่านข้อความนี้ได้ใกล้ชิดกับผลลัพธ์ที่ต้องการมากขึ้น


2
ฉันลองคำตอบอื่น ๆ ทั้งหมด แต่นี่เป็นคำตอบเดียวที่เหมาะกับฉัน! ขอขอบคุณที่แจ้งเส้นทางนี้
ประโยค

6

สตริง escape ใหม่ใน PowerShell V3 อ้างอิงจากคุณสมบัติภาษาใหม่ V3 :

การใช้บรรทัดคำสั่งจาก Cmd.exe ได้ง่ายขึ้น

เว็บเต็มไปด้วยบรรทัดคำสั่งที่เขียนขึ้นสำหรับ Cmd.exe บรรทัดคำสั่งเหล่านี้ทำงานได้บ่อยใน PowerShell แต่เมื่อมีอักขระบางตัวเช่นเครื่องหมายอัฒภาค (;) เครื่องหมายดอลลาร์ ($) หรือเครื่องหมายปีกกาคุณต้องทำการเปลี่ยนแปลงบางอย่างอาจเพิ่มคำพูด นี่ดูเหมือนจะเป็นที่มาของอาการปวดหัวเล็กน้อย

เพื่อช่วยแก้ไขสถานการณ์นี้เราได้เพิ่มวิธีใหม่ในการ "แยก" การแยกวิเคราะห์บรรทัดคำสั่ง หากคุณใช้พารามิเตอร์เวทมนต์ -% เราจะหยุดการแยกวิเคราะห์บรรทัดคำสั่งของคุณตามปกติและเปลี่ยนไปใช้สิ่งที่ง่ายกว่ามาก เราไม่ตรงกับคำพูด เราไม่หยุดที่เครื่องหมายอัฒภาค เราไม่ขยายตัวแปร PowerShell เราขยายตัวแปรสภาพแวดล้อมหากคุณใช้ไวยากรณ์ Cmd.exe (เช่น% TEMP%) นอกเหนือจากนั้นอาร์กิวเมนต์จะถูกส่งไปยังจุดสิ้นสุดของบรรทัด (หรือไพพ์หากคุณกำลังไพพ์) ตามที่เป็นอยู่ นี่คือตัวอย่าง:

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

6

คุณสามารถใช้ได้:

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 ตามคู่มือช่วยเหลือ จะก่อให้เกิดคู่มือวิธีใช้สำหรับ commandlet Get-Help <Commandlet-name> -Detailedเพียงพิมพ์ใน Get-Help Start-Process -Detailedในกรณีนี้ก็คือ


5

ฉันลองใช้คำแนะนำทั้งหมด แต่ก็ยังไม่สามารถทำงาน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()

3

สิ่งนี้ใช้ได้กับฉัน:

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

คีย์ดูเหมือนว่าคำสั่งทั้งหมดจะอยู่ในเครื่องหมายอัญประกาศภายนอกเครื่องหมาย "&" จะใช้เพื่อระบุไฟล์คำสั่งลูกอีกไฟล์หนึ่งที่กำลังดำเนินการจากนั้นจึงหนีเครื่องหมายอัญประกาศ (ดับเบิล - ดับเบิล -) รอบ ๆ พา ธ / ชื่อไฟล์ด้วยช่องว่าง ในที่คุณต้องการที่จะดำเนินการในสถานที่แรก

นี่เป็นความสำเร็จของวิธีแก้ปัญหาเฉพาะสำหรับปัญหาการเชื่อมต่อ MS ที่ - ไฟล์ไม่ส่งคืนรหัสที่ไม่เป็นศูนย์และ - คำสั่งเป็นทางเลือกเดียวเท่านั้น แต่จนถึงตอนนี้ก็คิดว่าข้อ จำกัด ของ -Command คือมันไม่รองรับช่องว่าง ฉันได้อัปเดตรายการข้อเสนอแนะด้วยเช่นกัน

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


1
นี่ไม่เกี่ยวกับคำถาม ops เขาถามโดยเฉพาะว่าจะเรียกใช้คำสั่งยาวในโพสต์ของเขาใน PowerShell ไม่ใช่วิธีการเรียกใช้สคริปต์ PowerShell ที่มีช่องว่างในเส้นทางของไฟล์
leinad13

อ่านชื่อของคำถามช่องว่างเป็นปัญหาที่ไม่ยาว นี่คือหนึ่งคำตอบที่ถูกต้องสำหรับปัญหาดังกล่าวดังนั้นการแบ่งปันที่คุ้มค่า คุณมีปัญหาเดียวกันและลองใช้จริงหรือไม่ หากคุณต้องการที่จะปรับปรุงมันส่งการแก้ไขซึ่งรวมถึงคำสั่งจริงในคำถามและฉันจะยอมรับมัน
Tony Wall

3

คำตอบอื่นคือการใช้สวิตช์คำสั่งที่เข้ารหัสBase64 :

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

คุณสามารถเรียกใช้ไฟล์ exe ได้หลายวิธี ตัวอย่างเช่นหากคุณต้องการเรียกใช้ 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 (เครื่องมือในการจัดการเครื่องเสมือน Virtualbox) คุณต้องเรียกพารามิเตอร์พารามิเตอร์นอกสตริงเช่นนี้โดยไม่มีเครื่องหมายอัญประกาศ:

> $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 คุณสามารถคลายซิปด้วย cmdlet คำสั่งที่เรียกใช้และพารามิเตอร์เงียบ / S (จะแยกตัวเองในโฟลเดอร์เดียวกันมากกว่าที่ถูกบีบอัด)

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

ดังนั้นจึงมีหลายวิธีในการเรียกใช้ไฟล์. exe พร้อมอาร์กิวเมนต์ใน powershell

บางครั้งเราต้องหาวิธีแก้ปัญหาเพื่อให้มันทำงานได้อย่างถูกต้องซึ่งอาจต้องใช้ความพยายามและความเจ็บปวดเพิ่มเติม :) ขึ้นอยู่กับวิธีที่. exe รวบรวมหรือทำให้ผู้สร้าง


1

ฉันใช้วิธีที่เรียบง่ายสะอาดและมีประสิทธิภาพ

ฉันวางอาร์กิวเมนต์ในอาร์เรย์ 1 ต่อบรรทัด วิธีนี้ง่ายต่อการอ่านและแก้ไข จากนั้นฉันก็ใช้เคล็ดลับง่ายๆในการส่งอาร์กิวเมนต์ทั้งหมดภายในเครื่องหมายคำพูดคู่ไปยังฟังก์ชันด้วยพารามิเตอร์เดียว 1 ตัว ซึ่งทำให้แบนรวมถึงอาร์เรย์ให้เป็นสตริงเดียวซึ่งฉันจะดำเนินการโดยใช้ 'Invoke-Expression' ของ PS คำสั่งนี้ถูกออกแบบมาโดยเฉพาะเพื่อแปลงสตริงให้เป็นคำสั่งที่รันได้ ทำได้ดี:

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

1

ฉันมีรหัสต่อไปนี้ทำงานได้อย่างสมบูรณ์แบบบนแล็ปท็อปของฉัน:

& $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"

จากนั้นเมื่อฉันพยายามเรียกใช้โดยตรงบนเซิร์ฟเวอร์หนึ่งฉันเริ่มรับข้อผิดพลาดเหล่านั้น "Unrecognized argument ...etc.... All arguments must begin with "-". "

หลังจากลองวิธีแก้ปัญหาที่เป็นไปได้ทั้งหมด (ไม่สำเร็จ) ฉันพบว่า Powershell บนเซิร์ฟเวอร์ (Windows 2008 R2) เป็นรุ่น 3.0 ในขณะที่แล็ปท็อปของฉันมี 5.0 (คุณสามารถใช้ "$ PSVersionTable" เพื่อดูรุ่น)

หลังจากอัปเกรด Powershellเป็นเวอร์ชันล่าสุดแล้วก็เริ่มทำงานอีกครั้ง


1

cmd สามารถจัดการกับการรัน exe ที่ยกมา แต่ Powershell ไม่สามารถ ฉันแค่จะจัดการกับการเรียกใช้ exe ตัวเองเพราะฉันไม่ได้ หากคุณต้องการส่ง doublequotes ไปยังอาร์กิวเมนต์ของคำสั่งภายนอกนั่นเป็นอีกปัญหาหนึ่ง

1) เพิ่มโฟลเดอร์ exe ในเส้นทางของคุณอาจอยู่ในโปรไฟล์ $ ของคุณ

$env:path += ';C:\Program Files\IIS\Microsoft Web Deploy\'
msdeploy

2) backquote ช่องว่าง:

C:\Program` Files\IIS\Microsoft` Web` Deploy\msdeploy.exe

0

ดังนั้นฉันจึงพบปัญหาที่คล้ายกันและเลือกที่จะแก้ปัญหาด้วยวิธีนี้แทน:

  1. หลีกเลี่ยงอักขระที่อ้างถึง (") ของคุณด้วย backtick (`)
  2. ล้อมรอบการแสดงออกใหม่ของคุณด้วยคำพูด (")
  3. ใช้ตัวดำเนินการโทร (&) ออกคำสั่งinvoke-expressionบนสตริงใหม่

ตัวอย่างการแก้ปัญหา:

& {invoke-expression "C: \ Program Deploy \ msdeploy.exe เว็บ C: \ Program เว็บ --verb: ซิงค์ - แหล่งที่มา: dbfullsql =` "แหล่งข้อมูล = mysource; การรักษาความปลอดภัยแบบรวม = false; ID ผู้ใช้ = sa; Pwd = sapass !; Database = mydb; `" -dest: dbfullsql = `" แหล่งข้อมูล =. \ mydestsource; Integrated Security = false, ID ผู้ใช้ = sa; Pwd = sapass!; ฐานข้อมูล = mydb; `", computername = 10.10.10.10, ชื่อผู้ใช้ = ผู้ดูแลระบบรหัสผ่าน = adminpass` ""}


0

สำหรับชื่อที่ปฏิบัติการได้cmdlet นามแฝงใหม่สามารถใช้เพื่อหลีกเลี่ยงการจัดการกับช่องว่างหรือต้องการเพิ่มไฟล์ที่เรียกใช้งานได้ในสภาพแวดล้อม $ PATH

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

หากต้องการแสดงหรือแก้ไขนามแฝง PS โปรดดูที่

PS> get-alias
PS> set-alias

จากJeffery Hicks Aarticle

คำตอบอื่น ๆ ที่อยู่ข้อโต้แย้ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.