0

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`""
}
Community
  • 1
  • 1
eduardw
  • 1
  • 1

3 Answers3

1

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.

Community
  • 1
  • 1
AutomatedOrder
  • 501
  • 4
  • 14
  • You're right! Now the batch script is running successfully. I'd found a mistake in my code: Changed $batchPath = $("`"$scriptpath + $ServiceFullname `"") to $batchPath = $("`"$scriptpath\$ServiceFullname `"") – eduardw Oct 21 '15 at 13:45
1

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"
}
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
0

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.

Marged
  • 10,577
  • 10
  • 57
  • 99
  • 1
    I don't think it's a good idea as creating `8dot3` NTFS filenames could be disabled (per volume or even per system). See `fsutil.exe behavior set Disable8dot3 /?` and [Disable short file name creation](http://www.itnotes.eu/?p=2322). Some admins do this because they believe that [disabling 8.3 file name creation increases file performance under Windows](https://support.microsoft.com/en-us/kb/121007), so for _performance reasons_ they disable it on their file servers. – JosefZ Oct 21 '15 at 18:56
  • @JosefZ I would say "it depends" ;-) We can only hope that never one of those "bored administrators" sets `DisableCMD=1` (see https://technet.microsoft.com/en-us/library/cc787344(v=ws.10).aspx). – Marged Oct 21 '15 at 19:07