How to use Jenkins pipeline variable into powershell or cmd code? - windows

I am in need of modifying a Jenkins Pipeline script. This is a snippet. It works down to the Def in the rename. The error I get is
groovy.lang.MissingPropertyException: No such property: newFileName for class: groovy.lang.Binding
I am looking to inject the version number into the filename which is then processed by a homegrown app to move it where it needs to go and some other stuff. I have tried passing the concatenated ${version} into the Upload executable but it then errors as a literal instead of a variable.
Update: I predefine the variable and get a new error
powershell.exe : newFileName : The term 'newFileName' is not recognized as the name of a cmdlet, function, script file, or operable
At C:\workspace\workspace\Centurion Dashboard#tmp\durable-eb5db1ae\powershellWrapper.ps1:3 char:1
& powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -Comm
CategoryInfo : NotSpecified: (newFileName : T...e, or >operable :String) [], RemoteException
FullyQualifiedErrorId : NativeCommandError
Thoughts?
stage('Rename') {
powershell """
rename-item -Path "C:\\Users\\Administrator\\Documents\\Advanced Installer\\Projects\\Proj\\Setup Files\\SetupCenturionDashboard.exe" -NewName "OtherProject-${version}.exe"
def newFileName = "C:\\Users\\Administrator\\Documents\\Advanced Installer\\Projects\\Proj\\Setup Files\\OtherProject-" + ${version} + ".exe"
echo ${newFileName}
"""
}
stage('Upload') {
bat label: 'Upload', script: 'C:\\Static\\BuildHelper\\BuildHelper.exe ${newFileName} "develop" "home" "${version}"'
}

powershell != groovy
You cannot run groovy inside of powershell block
powershell """
"""
and def newFileName is groovy, that is why you get the error:
The term 'newFileName' is not recognized as the name of a cmdlet...
As you can see, newFileName executable does not exist on windows.
variables on windows
If you just need to pass the version and newFileName variables to your powershell or bat code, you need to use the windows syntax %var% for variables, not the unix ${var} and use global variables if it is possible in your pipeline:
def version = "1.0.0";
def newFileName;
stage('Rename') {
powershell """
rename-item -Path "C:\\Users\\foo.exe" -NewName "OtherProject-%version%.exe"
"""
newFileName = "C:\\Users\\OtherProject-${version}.exe"
}
stage('Upload') {
bat label: 'Upload', script: 'C:\\Static\\BuildHelper\\BuildHelper.exe %newFileName% "develop" "home" "%version%"'
}

Related

"Unable to find specified file" - Powershell

I wrote this function in my powershell profile:
function start {
if ($args[0] == "blender") {
Invoke-Item 'C:\Program Files\Blender Foundation\Blender 2.90\blender.exe'
}
}
It gives me the error below on line 1, at character 1:
Unable to find specified file
The file path is correct, since if I copy and paste the code Invoke-Item ... in my powershell it opens Blender normally. What can the problem be?
Thank you!
This happens, as your function name collides with Start-Process.:
get-alias -Name start
CommandType Name Version Source
----------- ---- ------- ------
Alias start -> Start-Process
Renaming the function is the first step for correction like so,
function start-myApps {
if ($args[0] == "MyApplication") {
Invoke-Item 'C:\Program Files\MyApplication\MyApplication.exe'
}
}
But that isn't enough, as it gives another an error:
Start-MyApps "MyApplication"
= : The term '=' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:2 char:19
+ if ($args[0] == "MyApplication") {
+ ~
+ CategoryInfo : ObjectNotFound: (=:String) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : CommandNotFoundException
This one is caused because Powershell's equality comparison operator is -eq, not ==.
The working version has different name and operator like so,
function start-myApps {
if ($args[0] -eq "MyApplication") {
Invoke-Item 'C:\Program Files\MyApplication\MyApplication.exe'
}
}

How call invoke-expression to pass arguments when calling a remote script in powershell? [duplicate]

This question already has answers here:
What is shortest possible way to download script from HTTP and run it with parameters using Powershell?
(2 answers)
Closed 1 year ago.
My script content:
param (
[string]$arg1 = "2.2.2",
[string]$arg2 = "master"
)
& {
Write-Host "show $arg1 and $arg2 .."
}
Then I want to call this script in remote machine via http.
Invoke-Expression (Invoke-Webrequest "https://x.x.x.x/myscript.ps1" -UseBasicParsing).Content
But I don't know how to pass parameters to the script. Like this?
Invoke-Expression (Invoke-Webrequest "https://x.x.x.x/myscript.ps1" -UseBasicParsing).Content -arg1 2.2.1 -arg2 dev
How can help me? thanks!
If I do not pass arguments, the following commands are working fine.
Invoke-Expression (Invoke-Webrequest "https://x.x.x.x/myscript.ps1" -UseBasicParsing).Content
Download the code, create a scriptblock from it, and provide the arguments when calling Invoke() on the scriptblock.
$script = Invoke-RestMethod -Uri 'https://gist.githubusercontent.com/gittorta/75838602b2712d49c44e85ea0bc179e9/raw/8392f437943f66d47731423b674b81bd74378e4b/myscript.ps1'
$sb = [scriptblock]::Create($script)
$arg1 = "test1"
$arg2 = "test2"
$sb.Invoke($arg1, $arg2)
Output
show test1 and test2 ..
Same command condensed into a one-liner
([scriptblock]::Create((Invoke-RestMethod -Uri 'https://gist.githubusercontent.com/gittorta/75838602b2712d49c44e85ea0bc179e9/raw/8392f437943f66d47731423b674b81bd74378e4b/myscript.ps1'))).Invoke("test1", "test2")

Powershell warning and error handling

The following code I am writing to replace a batch script which I have below.
$Script:srcpath = ((Get-Location).Path)
$Script:configure = "$Script:srcpath\qtbase\configure.bat"
if (Get-Item "$Script:srcpath\qtbase\configure.bat" -WarningAction (Write-Warning "$Script:configure not found. Did you forget to run 'init-repository'?")) {
continue
}
I am try to rewrite the qt configure batch script:
set "srcpath=%~dp0"
set "configure=%srcpath%qtbase\configure.bat"
if not exist "%configure%" (
echo %configure% not found. Did you forget to run "init-repository"? >&2
exit /b 1
)
if not exist qtbase mkdir qtbase || exit /b 1
echo + cd qtbase
cd qtbase || exit /b 1
echo + %configure% -top-level %*
call %configure% -top-level %*
set err=%errorlevel%
cd ..
exit /b %err%
The error I am getting in PowerShell is the following:
Get-Item : Cannot bind parameter 'WarningAction' to the target. Exception setting
"WarningAction": "Object reference not set to an instance of an object."
At line:4 char:67
+ ... rningAction (Write-Warning "$Script:configure not found. Did you forg ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (:) [Get-Item], ParameterBindingException
+ FullyQualifiedErrorId : ParameterBindingFailed,Microsoft.PowerShell.Commands.GetItemCommand
The problem is the error being thrown is erroneous because the warning am calling is what should take its place to tell people that the item doesn't exist. so run "init-repository".
There isn't a good, "if not exist" in PowerShell.
Okay, there is, but it looks like this:
catch [System.Management.Automation.ItemNotFoundException]
which I am having problems with getting to work.
Why am I doing this before someone asks is because I feel that Microsoft will phase out CMD some time it's good to have updated scripts.
Why it's not working
WarningAction does not work like that.
From the about_CommonParameters documentation:
Determines how the cmdlet responds to a warning from the command. "Continue" is the default value. This parameter works only when the command generates a warning message. For example, this parameter works when a command contains the Write-Warning cmdlet.
So, essentially, the value of WarningAction is Continue by default and can be set to Inquire, SilentlyContinue or Stop. The value it is set to determine what action is taken if the Get-item command throws a warning, not what warning to write if Get-item throws a warning.
You can change the preference variable $WarningPreference to set the WarningAction within the current scope, or precede by a scope modifier.
How to make it work
Test-Path
I second Richard's comment to use Test-Path. This will return True or False, depending on whether it finds the file.
if (-not (Test-Path -Path "$Script:srcpath\qtbase\configure.bat")){
Write-Warning 'Does not exist!'
# do other stuff
continue
}else{
Get-Item $configure
}
try/catch
You could try to catch the exception thrown by Get-Item directly in a try/catch. In a similar way to WarningAction, there is ErrorAction which determines what to do if an error is thrown. Terminating error is required, so ErrorAction is set to Stop.
try{
Get-Item $configure -ErrorAction Stop
}catch [System.Management.Automation.ItemNotFoundException]{
Write-Output "Item not found"
# do other stuff
}catch{
Write-Output "Some other error"
$Error[0] # prints last error
}

passing parameters from a windows batch script into a powershell script

I have a powershell script which uses 'quser' command to extract data regarding users logged onto a series of terminal servers.
I want to add a timestamp to the output files, this timestamp variable is created in a windows batch file which then calls the powershell script passes the computername and timestamp, but the powershell script is erroring with 'Missing ')' in function parameter list'
param(
[CmdletBinding()]
[Parameter(ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[string[]]$ComputerName = 'localhost'
[string[]]$timestamp <========= this is the line I have added
)
If I remove my added line (marked in the code above), the script runs fine
You need to add a comma between the parameters:
param(
[CmdletBinding()]
[Parameter(ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[string[]]$ComputerName = 'localhost',
[string[]]$timestamp
)
Also unless you want multiple timestamps you probably just want it to be a string rather than a string array (so [string]$timestamp).
The error message I get looks like this (except that it is in red). The first error points at the end of the localhost line then there is a knock-on error for what by that time seems to be a spurious ):
PS C:\> param(
>> [CmdletBinding()]
>> [Parameter(ValueFromPipeline=$true,
>> ValueFromPipelineByPropertyName=$true)]
>> [string[]]$ComputerName = 'localhost'
>> [string[]]$timestamp
>> )
>>
At line:5 char:38
+ [string[]]$ComputerName = 'localhost'
+ ~
Missing ')' in function parameter list.
At line:7 char:1
+ )
+ ~
Unexpected token ')' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingEndParenthesisInFunctionParameterList
I'm using Powershell 3 here. Other versions may show the error differently.

Call a script in SharePoint PowerShell post-deployment command line with array in parameters

I try to call on post-deployment action a powerShell script with an array parameter, but without success.
Here is the script:
param(
[string[]]$ModelNameList = "DefaultModelName"
)
Write-Host "Number of Models is: $($ModelNameList.Count)"
and this is the post-deployment command line:
%windir%\sysnative\windowspowershell\v1.0\powershell -File "$(ProjectDir)Scripts\Post_Deployment\Script.Post-Deployment.ps1" -ModelNameList "m2","m1"
Result : Number of Models is: 1
Running the same script in SharePoint2010 Management Shell return the correct result.
Result : Number of Models is: 2
CMD doesn't know anything about PowerShell arrays, so it passes "m2","m1" into the powershell script as a single string. You can see that when you add
Write-Host $ModelNameList[0]
Write-Host $ModelNameList[0].GetType()
to your PowerShell script. I think you have to split the argument inside your script:
if ($ModelNameList[0] -match ',') {
$ModelNameList = $ModelNameList[0].Split(',')
}

Resources