简体   繁体   中英

Execute batch file with spaces in path

I have problems to execute a batch file on a remote server via PowerShell. The user can choose several opinions in a pop-up window like Servername , starting or killing process and Servicename . The chosen items will be saved in variables.

If all items are chosen, I want to merge the strings to one string and execute the batch script which is named like this result string. I try to do it as described in this post , but the batch script won't be executed.

Example:

[String]$scriptpath="C:\tmp\"
[String]$Servername = "xx040"
[String]$actionprefix = "kill_process"
[String]$action = $($actionprefix) + "-"
[String]$Servicename = "service1"
[String]$ServiceFullname = $($action) + $($Servicename) + ".bat"
$batchPath = $("`"$scriptpath + $ServiceFullname `"")
Invoke-Command -ComputerName $Servername -ScriptBlock {
  cmd.exe /c "`"$batchPath`""
}

In your code you are not passing in anything to your invoke-command, so when it's running remotely it doesn't know what $batchPath is. Take a look at this SO answer How do I pass named parameters with Invoke-Command?

Invoke-Command -ComputerName $Servername -ScriptBlock {param($batchPath) cmd.exe /c "`"$batchPath`"" } -ArgumentList $batchPath

Is how you would want to make your call.

Simply use the call operator ( & ) and put the variable with the path to your batch file in double quotes.

& "$batchPath"

You also need to make the variable $batchPath known inside your scriptblock via the using: scope modifier, otherwise $batchPath inside the scriptblock would be a different (empty) variable than $batchPath outside the scriptblock.

Invoke-Command -Computer $Servername -ScriptBlock {
  & "$using:batchPath"
}

An alternative would be to pass the variable into the scriptblock as an argument:

Invoke-Command -Computer $Servername -ScriptBlock {
  Param($BatchPath)
  & "$BatchPath"
} -ArgumentList $batchPath

Use Join-Path for building paths, so you don't need to deal with leading/trailing path separators yourself. Also, PowerShell expands variables in double-quoted strings, allowing you to avoid excess concatenations. In single-quoted strings variables are not expanded, so I normally use double quotes for strings with, and single quotes for strings without variables in them.

Modified code:

$Servername   = 'xx040'
$scriptpath   = 'C:\tmp'
$actionprefix = 'kill_process'
$Servicename  = 'service1'

$batchPath = Join-Path $scriptpath "$actionprefix-$Servicename.bat"

Invoke-Command -ComputerName $Servername -ScriptBlock {
   & "$using:batchPath"
}

One alternative to avoid paths with spaces in them is to use the 8.3 short notation.

Open a command line in Windows and use the /x parameter of dir. To find the shortname of the program files dir you would use dir C:\\prog* /x . This is the result:

21.10.2015  14:46    <DIR>          PROGRA~1     Program Files
21.10.2015  12:47    <DIR>          PROGRA~2     Program Files (x86)
04.09.2014  18:25    <DIR>          PR6AFF~1     Programs16Bit

If you were to address C:\\Program Files you could write C:\\PROGRA~1 too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM