I have written a simple script via PowerShell to gather some files and zip them into one folder, lets call it Script.ps1. I want to make the script run every time Jenkins does a new build, however I also would like the name of the zip file to be the BUILD_NUMBER.
How can I create a variable in PowerShell that is Jenkins's current build number? As of the moment I am calling the Script.ps1 in the execute shell section of configuration.
I'm not familiar with Jenkins, but I believe BUILD_NUMBER is an environment variable.
To access it in PowerShell, use $env:BUILD_NUMBER
E.g. If using 7-zip
7z.exe a "$env:BUILD_NUMBER.zip" C:\Build\Path
You can add arguments to your Script.ps1. Just use Param at the top of the script:
Param( $BuildNumber ) #must be first statement in script
# your current script goes here
then you can call the script passing BUILD_NUMBER as argument from Jenkins. Refer to this question for calling Powershell script with argument.
You could also use the Powershell Plugin, see here.
It allows you to enter PowerShell commands directly in a text box in Jenkins.
Then you can use the available environment variables (see docu of the plugin). The usage is a little cryptic:
(Get-Content ./Sources/SlmMachineControl/GUI/Project1.rc).replace("`"FileVersion`", `"1.0.0.0`"" ,"`"FileVersion`" `"2.3.$($env:BUILD_NUMBER).0`"") | Set-Content ./Sources/SlmMachineControl/GUI/Project1.rc
Also note the escaping of the double-quotes. Took me quite a while :)
Related
I wrote a script to build all .net projects in a folder.
Issue
The issue is I am getting a missing function error when I call Build-Sollution.
What I tried
I made sure that function was declared before I used it so I am not really sure why it saids that it is not defined.
I am new to powershell but I would think a function calling another functions should work like this?
Thanks in advance!
Please see below for the error message and code.
Error Message
Line |
3 | Build-Sollution $_
| ~~~~~~~~~~~~~~~
The term 'Build-Sollution' 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.
Build-Sollution:
Code
param (
#[Parameter(Mandatory=$true)][string]$plugin_path,
[string]$depth = 5
)
$plugin_path = 'path/to/sollutions/'
function Get-Sollutions {
Get-ChildItem -File -Path $plugin_path -Include *.sln -Recurse
}
function Build-Sollution($solution) {
dotnet build $solution.fullname
}
function Build-Sollutions($solutions) {
$solutions | ForEach-Object -Parallel {
Build-Sollution $_
}
}
$solutions_temp = Get-Sollutions
Build-Sollutions $solutions_temp
From PowerShell ForEach-Object Parallel Feature | PowerShell
Script blocks run in a context called a PowerShell runspace. The runspace context contains all of the defined variables, functions and loaded modules.
...
And each runspace must load whatever module is needed and have any variable be explicitly passed in from the calling script.
So in this case, the easiest solution is to define Build-Sollution inside Build-Sollutions
As for this...
I am new to powershell but I would think a function calling another
functions should work like this?
... you cannot use the functions until you load your code into memory. You need to run the code before the functions are available.
If you are in the ISE or VSCode, if the script is not saved, Select All and hit use the key to run. In the ISE use F8 Selected, F5 run all. In VSCode, F8 run selected, crtl+F5 run all. YOu can just click the menu options as well.
If you are doing this from the consolehost, the run the script using dot sourcing.
. .\UncToYourScript.ps1
It's ok to be new, we all started somewhere, but it's vital that you get ramped up first. so, beyond what I address here, be sure to spend time on Youtube and search for Beginning, Intermediate, Advanced PowerShell for videos to consume. There are tons of free training resources all over the web and using the built-in help files would have given you the answer as well.
about_Scripts
SCRIPT SCOPE AND DOT SOURCING Each script runs in its own scope. The
functions, variables, aliases, and drives that are created in the
script exist only in the script scope. You cannot access these items
or their values in the scope in which the script runs.
To run a script in a different scope, you can specify a scope, such as
Global or Local, or you can dot source the script.
The dot sourcing feature lets you run a script in the current scope
instead of in the script scope. When you run a script that is dot
sourced, the commands in the script run as though you had typed them
at the command prompt. The functions, variables, aliases, and drives
that the script creates are created in the scope in which you are
working. After the script runs, you can use the created items and
access their values in your session.
To dot source a script, type a dot (.) and a space before the script
path.
See also:
'powershell .net projects build run scripts'
'powershell build all .net projects in a folder'
Simple build script using Power Shell
Update
As per your comments below:
Sure the script should be saved, using whatever editor you choose.
The ISE does not use PSv7 by design, it uses WPSv5x and earlier.
The editor for PSv7 is VSCode. If you run a function that contains another function, you have explicitly loaded everything in that call, and as such it's available.
However, you are saying, you are using PSv7, so, you need to run your code in the PSv7 consolehost or VSCode, not the ISE.
Windows PowerShell (powershell.exe and powershell_ise.exe) and PowerShell Core (pwsh.exe) are two different environments, with two different executables, designed to run side-by-side on Windows, but you do have to explicitly choose which to use or write your code to branch to a code segment to execute relative to the host you started.
For example, let's say I wanted to run a console command and I am in the ISE, but I need to run that in Pwsh. I use a function like this that I have in a custom module autoloaded via my PowerShell profiles:
# Call code by console executable
Function Start-ConsoleCommand
{
[CmdletBinding(SupportsShouldProcess)]
[Alias('scc')]
Param
(
[string]$ConsoleCommand,
[switch]$PoSHCore
)
If ($PoSHCore)
{Start-Process pwsh -ArgumentList "-NoExit","-Command &{ $ConsoleCommand }" -PassThru -Wait}
Else {Start-Process powershell -ArgumentList "-NoExit","-Command &{ $ConsoleCommand }" -PassThru -Wait}
}
All this code is doing is taking whatever command I send it and if I use the PoSHCore switch...
scc -ConsoleCommand 'SomeCommand' -PoSHCore
... it will shell out to PSCore, run the code, otherwise, it just runs from the ISE>
If you want to use the ISE with PSv7 adn not do the shell out thing, you need to force the ISE to use PSv7 to run code. See:
Using PowerShell Core 6 and 7 in the Windows PowerShell ISE
nuget pack C:\Users\%USERNAME%\Source\Repos\Common\Common\Common.nuspec -OutputDirectory D:\NugetFeed
The above code is what is in my nugetpack.ps1 file. It works perfectly when I directly enter my username is the path, but I need it to be able to work for multiple users. I entered the %USERNAME% username variable into the path but I get the following response:
Could not find a part of the path 'C:\Users\%USERNAME%\Source.....'.
How can I use the %USERNAME% variable in my path. I am new to PowerShell.
Environment variables in PowerShell are on the logical drive env:, but are otherwise syntactically normal PowerShell variables. The use of %...% is BATCH syntax. For PowerShell, use $env:varname, e.g., $env:username.
You may also find that you need the information in "Run Executable From PowerShell Script With Parameters".
I am using ops tool Rundeck that allows for execution of arbitrary scripts. I enter the script text in the web application widget and upon execution, Rundeck saves it to temporary file and calls interpreter. The problem is that the temporary file doesn't have ps1 extension and Powershell refuses to execute it.
Is there any way to set up Powershell to ignore extension ?
=== EDIT 2018 ===
Rundeck now has an option for this within a job definition.
I know I'm not strictly answering your questions regarding setting up PowerShell to ignore extensions, but here is one way of executing code from a textfile:
Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Get-Content .\file.txt)))
This reads the contents of file.txt and converts it into a scriptblock, before executing it using Invoke-Command.
myscript.ps1
Param(
[Parameter(Mandatory=$true,Position=1)]
[string]$computerName
)
echo "arg0: " $computerName
CMD.exe
C:\> myscript.ps1 -computerName hey
Output:
cmdlet myscript.ps1 at command pipeline position 1
Supply values for the following parameters:
computerName: ddd
arg0:
ddd
I'm simply trying to work with Powershell parameters in CMD, and I can't seem to get a script to take one. I see sites saying to precede the script with .\ but that doesn't help. I added the mandatory line to see if Powershell was reading a parameter or not, and it's clearly not. The parameter computerName is obviously the word "hey". The Param block is the very first thing in the script. Powershell appears to recognize a parameter computerName, but no matter how I enter the command, it never thinks I'm actually entering parameter.
What the heck's wrong with my syntax?
By default, Powershell will not run scripts that it just happens to find in your current directory. This is intended by Microsoft as a security feature, and I believe that it mimics behavior found in unix shells.
Powershell will run scripts that it finds in your search path. Your search path is stored in $env:path.
I suspect that you have a script named "myscript.ps1" in some other directory that is on your search path.
I have had this happen to me before. The symptom I saw was that the parameter list seemed different than what I had defined. Each script had a different parameter list, so the script bombed when I fed it a parameter list intended for the other script. My habit is to not rely on parameter position, so this problem was easy to find.
The addition of ".\" to the script ".\myscript.ps1" should force the shell to use the .ps1 file in your current directory. As a test, I would specify the full path to the file you are trying to execute (If there are spaces in the path, be sure to wrap the path in "quotes") or change it to some totally crazy name that won't be duplicated by some other file (like "crazyfishpants.ps1") and see if the shell still finds the file.
You can get into similar problems if you have a function ("Get-Foo") that is loaded out of a module or profile with the same name as a script file ("Get-Foo.ps1"). You may wind up running something other than what you intend.
Position values should be 0-based (0 for the first parameter). That said, I can't duplicate what you're seeing on either PowerShell 2.0 or 3.0.
Thank you all for your very informative responses. It looks like my question was slightly edited before I submitted it, in that the text leads you to believe that I was entering this command directly in Powershell.
I was actually running the command for the script in CMD, which totally explains why it was not passing parameters to the Powershell script. Whoever green-lighted my question probably changed C:\> to PS> thinking that I made a typo.
I assumed that if I could run the script straight from CMD, I could send parameters to it on CMD's command line, but apparently that's not the case. If I run the script in Powershell, it indeed works just fine, I'm now seeing.
My ultimate goal was to allow users to run the Powershell script from CMD. It's looking like I can make a batch file that accepts parameters, and then start powershell and send those parameters to the PS script. And so, in the batch file, I should do something like:
powershell -File C:\myscript.ps -computerName %1
This enigma was probably solved 100 times over on this site, and I apologize for the confusion. Thank you again, for your responses.
I have written a powershell script. the code has paths related to only my PC.
Now the same code cannot be executed by another person on his machine because the path is diff. Therefore please let me know a way where my code can work on all machines.
It depends on the paths. If they're to programs in \Program Files perhaps you can use the environment variable $env:ProgramFiles in your path spec. You can also parameterize your script to take the path like so:
param($path)
# rest of script ...
Note that the param() statement must be the first non-comment line in your script.
You could also use the special $MyInvocation variable available to running scripts. It has access to the path the script was executed from, among other things.
For example a script I use has this line:
$InputCSV = (split-path $myinvocation.mycommand.path) + "\filename.csv"
Which means no matter where the script is run from it will know to grab the CSV file from the same place.