How to give the path as a parameter or a variable in powershell - powershell

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.

Related

My script can read a text file when run manually through ISE, but it looks in a different directory when run through Task Scheduler

Powershell noob here.
I have a script for copying PDF documents and CSV files. The script gets the CSV data from a URL defined in a .txt file in the same directory as the script. In the script, the file is determined like this:
$publishedCSV = Get-Content .\DriveURL.txt -Raw
When I run this script in ISE, it works fine and retrieves all the CSV data. However, when I run it in Scheduler, it tries to find the DriveURL file in System32, rather than in the path that is specified (I used transcript to find out what was happening)
I figured that out, and defined the FULL path of DriveURL, rather than just using the .\ notation. It works, but I don't know why it works
What I did:
Specified proper path of DriveURL and now my script works. I don't understand why it worked previously with using ./DriveURL.txt rather than the full path when I'd run it in ISE, but it didn't when run in Scheduler. It's the same script
If you use relative paths then you must also either set your working directory, or in the script change to the appropriate directory before referencing said relative paths. Alternatively you can use full paths, as you have already discovered.
A simple use of cd or pushd and the automatic $PSScriptRoot variable will change your working directory to wherever the script is saved to:
pushd $PSScriptRoot

How to use a variable as part of the path of a calling program

As a new PowerShell user, I am planning to call a local program whose path is not in the PATH environment variable. When calling the program the relative or full path of the program has to be given, e.g. .\Users\xxx\Downloads\program_name\bin\prog. However, as this path is way long and sometimes might be changed, so as a Linux Shell script programmer I would like to use a variable in the path, for instance .\$prog_home\bin\prog.
Hereby my question is how to initialize this variable so that it can be used as I assumed beforehands? I tried to initialized the variable in such way -
$prog_home="User\xxx\Downloads\program_name"
Unfortunately, this really can not work at all like in Linux Shell
Please consider to use the Join-Path cmdlet to combine a path. There is also a builtin USERPROFILE environment variable which you can use. This is how you could do it:
$prog_home = Join-Path $env:USERPROFILE 'program_name'
$prog = Join-Path $prog_home '\bin\prog.exe'
& $prog #execute it

How to use a Jenkins variable in my Powershell Script

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 :)

Get Powershell top-level script location?

$PSScriptRoot and $PSCommandPath are very useful in locating script files that are consumed by other scripts. Is there an easy, reliable way of getting the top-level script file that was actually executed? My users are right-clicking .ps1 files to execute them from File Explorer.
Example:
C:\Powershell\a.ps1
C:\Powershell\lib\b.ps1
I need a command that I can use from b.ps1 that preferably returns C:\Powershell\a.ps1, or at least C:\Powershell. $PSScriptRoot, $PSCommandPath, and $MyInvocation.MyCommand.Path all return C:\Powershell\lib\b.ps1, though.
Thanks!
This seems to work:
get-variable psscriptroot -scope ((get-pscallstack).count - 2)
That should get you the scriptroot in the fist child scope of the global scope, which would be the script scope of the initial script invocation.
Inside b.ps1, use the cmdlet:
Get-Location
This will return the parent path that you expect.
Why This Works:
This works because you will navigate to the directory C:\Powershell\ and execute the script a.ps1 from there. When you execute . .\lib\b.ps1 you haven't left that execution location, so it will return exactly what you want.
Note: Note that this only works if you first navigate to the directory first, or for scheduled tasks you specify a "Start in" directory. So if you are in a different directory and execute your first script like this: C:\Powershell\a.ps1 it will return your other directory.
If you are really keen, more info on encapsulation is here: Further Down the Rabbit Hole PowerShell Modules and Encapsulation

Why won't this powershell script accept parameters?

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.