Escape space and resolve variable in Jenkins powershell script not working - powershell

I tried different ways to escape the space in "Program Files" but this is not working. I receive the following error in Jenkins after this part is executed:
powershell.exe : FileStream was asked to open a device that was not a file. For support for devices like 'com1:' or 'lpt1:', call At
C:\web\JenkinsMaster\workspace\XXX#tmp\durable-d3011838\powershellWrapper.ps1:5
char:3
+ & powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -Fi ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (FileStream was ... 'lpt1:', call :String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError CreateFile, then use the FileStream constructors that take an OS handle as an IntPtr.
CategoryInfo : OpenError: (:) [Out-File], NotSupportedException
FullyQualifiedErrorId : FileOpenFailure,Microsoft.PowerShell.Commands.OutFileCommand
PSComputerName : XXXXX
powershell script: '''
$pass = ConvertTo-SecureString -AsPlainText "XXXX" -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList "XXXX",$pass
$sessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
$session = New-PSSession -ComputerName XXXXXXXX -UseSSL -Credential $cred -SessionOption $sessionOption
Copy-Item $env:WORKSPACE\\* -Destination "C:\\data\\install\\" -Filter *TEST* -Recurse -Force -Verbose -ToSession $session
$filename = $env:JOB_NAME + "_" + $env:BUILD_DISPLAY_NAME + "_wwwroot.7z"
Invoke-Command -Session $session -ScriptBlock {cmd /c "C:\\Program Files\\7-Zip\\7z.exe\\" x C:\\Data\\Install\\$filename -oC:\\data\\install\\test -aoa >NUL}
Remove-PSSession $session
Exit-PSSession
'''
If I change the Invoke-Command to the following, the Program Files directory seems to be resolved correctly, but then the variable $filename is not resolved anymore.
Invoke-Command -Session $session -ScriptBlock {cmd /c \'"C:\\Program Files\\7-Zip\\7z.exe" x C:\\Data\\Install\\$filename -oC:\\data\\install\\test -aoa >NUL'}
powershell.exe : NotSpecified: (:String) [], RemoteException At
C:\web\Jenkins\workspace\XXX#tmp\durable-53dbead2\powershellWrapper.ps1:5
char:3
+ & powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -Fi ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (NotSpecified: (...RemoteException:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
CategoryInfo : NotSpecified: (:String) [], RemoteException
FullyQualifiedErrorId : NativeCommandError
PSComputerName : XXXXX
ERROR: The system cannot find the file specified.
C:\Data\Install\$filename
System ERROR:
The system cannot find the file specified.
Hopefully you can assist me in this case! The rest of the commands is working fine.
Thanks!

The 7z.exe path in your first command has an extraneous trailing \, which causes problems:
cmd /c "C:\\Program Files\\7-Zip\\7z.exe\\" # <- trailing \\ shouldn't be there
In your 2nd command, you're using single quotes around the command passed to cmd /c ('...'), but the contents of '...' strings in PowerShell are treated as literals, which explains why $fileName was not expanded (interpolated);
only double-quoted ("...") strings and, within limits, unquoted command arguments are expanded in PowerShell; e.g., compare the output from Write-Output '$HOME' to the output from Write-Output "$HOME" / Write-Output $HOME.
As iRon mentions, there's no need to involve cmd at all - PowerShell is perfectly capable of executing command-line programs directly, so this should work:
Invoke-Command -Session $session -ScriptBlock { & "C:\\Program Files\\7-Zip\\7z.exe" x C:\\Data\\Install\\$using:filename -oC:\\data\\install\\test -aoa >$null }
Due to invoking 7z.exe directly, now there's no outer quoting needed anymore, and $fileName should be expanded.
Note, however, that $fileName was replaced with $using:fileName, which is necessary in order for the target session to know about the local $fileName variable - see Get-Help about_Remote_Variables.
Since the 7z.exe file path is quoted (of necessity, due to containing spaces), you must use &, the call operator, to invoke it.
Since the > redirection is now performed by PowerShell itself, the cmd-style >NUL output suppression was replaced with its PowerShell analog, >$null.

I wonder if it necessarily at all to invoke a CMD shell for this.
I guess it would be simpler to directly invoke the 7z.exe with its parameters.
Nevertheless, you can build you own script block like this:
[ScriptBlock]::Create('cmd /c "C:\\Program Files\\7-Zip\\7z.exe" x C:\\Data\\Install\\' + $filename + ' -oC:\\data\\install\\test -aoa >NUL')

Related

How to use -ArgumentList with Invoke-Command to pass flags to a script?

How to use -ArgumentList with Invoke-Command to pass flags to a script?
# File: ./setup.ps1
param(
[Parameter(Mandatory=$false)]
[alias("force")]
[switch]$opt_force
)
if ($opt_force) {
write-host "FORCING something!"
}
write-host "Done"
Powershell Command Line:
PS> Invoke-Command -Computer pv3039 -FilePath ./setup.ps1 -ArgumentList "-force"
Error Message:
positional parameter cannot be found that accepts argument '-force'.
+ CategoryInfo : InvalidArgument: (:) [], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound
+ PSComputerName : pv3039
If you want to call a remote script, you can use Start-Process instead of Invoke-Command. Maybe you can try something like this.
Start-Process PowerShell -ArgumentList "YOUR_SCRIPT_PATH\setup.ps1 -Force" -NoNewWindow -Wait
This way it can accept parameters from the called script.

calling PowerShell script from batch file to connect remote machine is not working

When I am running a PowerShell script normally it's working fine, issue is raising when calling the same script from batch file.
Unt1.ps1 script:
$linux_app_user="ORXXXX\"+$args[0]
$pass_win=$args[1]
$path=$args[2]
$pass = ConvertTo-SecureString -AsPlainText $pass_win -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList
$linux_app_user, $pass
$Invoke-Command -ComputerName XXXXXXXX.XXXX.XXX.XXXX -Credential $cred -ErrorAction
Stop -ScriptBlock {
param($path)
Invoke-Expression $path
} -Arg $path
cal.bat script:
#echo off
SET Server=slXXXXXXXX.XXX.XXXX.com
SET PowerShellDir=C:\Windows\System32\WindowsPowerShell\v1.0
CD /D "%PowerShellDir%
powershell.exe -ExecutionPolicy RemoteSigned -File
C:\Users\chaj\Documents\String\Unt1.ps1 'XXXX' 'XXXX#321' 'C:\cal.bat'
Error:
[xxxxxx.xx.xxxxx.xxx] Connecting to remote server xxxxxx.xx.xxxxx.xxx failed
with the following error message : The user name or password is incorrect.
For more information, see the about_Remote_Troubleshooting Help topic.
At C:\Users\chafg\Documents\String\Unt1.ps1:7 char:1
+ $Result=Invoke-Command -ComputerName xxxxxx.xx.xxxxx.xxx -Credenti ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (xxxxxx.xx.xxxxx.xxx) [], PSRemotingTransportException
+ FullyQualifiedErrorId : LogonFailure,PSSessionStateBroken
When using the PowerShell CLI with the -File parameter, all arguments are used verbatim - except if enclosed in "..." (double quotes): unlike when you use -Command, '...' (single quotes) are not recognized as string delimiters.
Therefore, your command (simplified here):
powershell.exe -File C:\path\to\Unt1.ps1 'XXXX' 'XXXX#321' 'C:\cal.bat'
causes the Unt1.ps1 script to see the arguments with the enclosing ', which is not your intent; e.g., instead of $args[0] receiving XXXX, as intended, it receives 'XXXX', verbatim.
The fix is to use "..." (double quotes):
powershell.exe -File C:\path\to\Unt1.ps1 "XXXX" "XXXX#321" "C:\cal.bat"
Alternatively, given that your specific sample arguments don't require quoting (though the real ones may):
powershell.exe -File C:\path\to\Unt1.ps1 XXXX XXXX#321 C:\cal.bat

Invoke-command error when install Citrix VDA

I'm looking to install the Citrix VDA remotely. I ran this same command on the app server and it installed like I would expect. But now when I try to install it remotely with the invoke-command I get an error.
Invoke-Command -computer appserver.domain.com -scriptblock {start-process -FilePath "C:\XenDesktop 7.15\x64\XenDesktop Setup\XenDesktopVDASetup.exe" -ArgumentList "/noreboot /quiet /components VDA,plugins /masterimage /baseimage /enable_remote_assistance /enable_hdx_ports /optimize /controllers "ddc.domain.com""}
A positional parameter cannot be found that accepts argument 'ddc.domain.com'.
+ CategoryInfo : InvalidArgument: (:) [Start-Process], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.StartProcessCommand
+ PSComputerName : appserver.domain.com
You should either put dcc.domain.com in single quotes: 'ddc.domain.com' or fix those double quotes. To use double quotes in a double quoted string, you'll need to double them up:
-ArgumentList "/noreboot /quiet /components VDA,plugins /masterimage /baseimage /enable_remote_assistance /enable_hdx_ports /optimize /controllers ""ddc.domain.com"""
-ArgumentList '/noreboot /quiet /components VDA,plugins /masterimage /baseimage /enable_remote_assistance /enable_hdx_ports /optimize /controllers "ddc.domain.com"'

How to pass arguments to an Invoke-Expression, in PowerShell?

I have the following (not working) PowerShell script:
$scriptPath = ((new-object net.webclient).DownloadString('https://gist.githubus
ercontent.com/AndrewSav/c4fb71ae1b379901ad90/raw/23f2d8d5fb8c9c50342ac431cc0360ce44465308/SO33205298')); $args = "`"aaa
bbb`""; iex $scriptPath $args
So I'm:
downloading the script to execute.
settiping up my argument list to send into the script
executing the script (for me, this is in the cli right now).
but it's erroring:
Invoke-Expression : A positional parameter cannot be found that accepts argument '"aaa bbb"'.
At line:1 char:209
+ ... 44465308/SO33205298')); $args = "`"aaa bbb`""; iex $scriptPath $args
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-Expression], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.InvokeExpressionCommand
How can I pass in the args to this script?
Note: this question references/spawned from this other SO question.
You should try something like this :
$scriptPath = ((new-object net.webclient).DownloadString('https://gist.githubusercontent.com/AndrewSav/c4fb71ae1b379901ad90/raw/23f2d8d5fb8c9c50342ac431cc0360ce44465308/SO33205298'))
Invoke-Command -ScriptBlock ([scriptblock]::Create($scriptPath)) -ArgumentList "coucou"
You have to create a ScriptBlock from source before invoking it.
As a pure one liner (you don't need to create the scriptblock separately)
Also, using DownloadData in case the script has UTF-8 characters. Finally, Use an array for the ArgumentList to avoid issues with spaces in args.
powershell -nop -ExecutionPolicy Bypass -c "Invoke-Command -ScriptBlock ([scriptblock]::Create([System.Text.Encoding]::UTF8.GetString((New-Object Net.WebClient).DownloadData('https://server.com/upload/script.ps1')))) -ArgumentList #('somearg','someotherarg')"

Trying to Invoke a Script on a Remote Computer

I'm having to construct some paths before attempting to invoke the script which is present on the remote computer. I'm adapting something we have working in TeamCity, but I'm currently getting the following error:
The command cannot be run because the File parameter requires a file path. Supply a path for the File parameter and then try the command again.
+ CategoryInfo : NotSpecified: (The command can... command again.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
Relevant code below:
$stageScript = "D:\pkg\${dir}\stage.ps1"
$options = "production \\192.168.0.x\staging \\${server}\staging"
Invoke-Command -computername server.domain.com { powershell.exe -noprofile -executionpolicy Bypass -file $stageScript $options } -Credential $credential
You need to pass local variables to the script block as an argument list
$stageScript = "D:\pkg\${dir}\stage.ps1"
$options = "production \\192.168.0.x\staging \\${server}\staging"
Invoke-Command -computername server.domain.com { powershell.exe -noprofile -executionpolicy Bypass -file $args[0] $args[1] } -ArgumentList $stageScript,$options -Credential $credential