Getting Script name in Powershell - powershell

Is there any other way except $MyInvocation.InvocationName in powershell to get the script name?
As i need to turn my script in an exe and in that case it doesnt work on that exe.

I'm assuming since you convert the powershell script to an executable that you are after the location of the executable. You can get it this way:
[Environment]::GetCommandLineArgs()[0]

If you want something that works within and outside of ISE you can use
$MyInvocation.InvocationName
Since full paths and .\YourScript.ps1 can be returned you can parse the name with:
[Regex]::Match( $MyInvocation.InvocationName, '[^\\]+\Z', [System.Text.RegularExpressions.RegexOptions]::IgnoreCase -bor [System.Text.RegularExpressions.RegexOptions]::SingleLine ).Value

Related

Running a small WMI Powershell Script

I'm trying to have a few scripts that I can map to run from my keyboard for quickly changing the monitor/screen brightness. After some searching on the internet, I found this script which works when I enter it into Powershell.
$monitor=#(gwmi WmiMonitorBrightnessMethods -ns root/wmi)[0]
$monitor.WmiSetBrightness(50,0)
After I saved it as a .ps1 file and tried running it from the file, powershell tells me: The term "path of the file" is not recognized as the name of a cmdlet, function... and so on.
I'm not familiar with Powershell at all, can someone help with what I need to add in order for the script to run properly?
By default you can't run a PowerShell script that is in the current directory without putting .\ in front of the script name, or calling the full path of the script.
This is a security feature.
If you are in the directory that contains the script, run it by executing in a PowerShell window:
.\yourscript.ps1
Where yourscript is the name of your script.
See here for more information: https://ss64.com/ps/syntax-run.html
You may also see this error if your script has spaces in its name. If that is the case, enclose the path in quotes:
.\'your script.ps1'

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.

PowerShell: Run command from script's directory

I have a PowerShell script that does some stuff using the script’s current directory. So when inside that directory, running .\script.ps1 works correctly.
Now I want to call that script from a different directory without changing the referencing directory of the script. So I want to call ..\..\dir\script.ps1 and still want that script to behave as it was called from inside its directory.
How do I do that, or how do I modify a script so it can run from any directory?
Do you mean you want the script's own path so you can reference a file next to the script? Try this:
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
Write-host "My directory is $dir"
You can get a lot of info from $MyInvocation and its properties.
If you want to reference a file in the current working directory, you can use Resolve-Path or Get-ChildItem:
$filepath = Resolve-Path "somefile.txt"
EDIT (based on comment from OP):
# temporarily change to the correct folder
Push-Location $dir
# do stuff, call ant, etc
# now back to previous directory
Pop-Location
There's probably other ways of achieving something similar using Invoke-Command as well.
There are answers with big number of votes, but when I read your question, I thought you wanted to know the directory where the script is, not that where the script is running. You can get the information with powershell's auto variables
$PSScriptRoot # the directory where the script exists, not the
# target directory the script is running in
$PSCommandPath # the full path of the script
For example, I have a $profile script that finds a Visual Studio solution file and starts it. I wanted to store the full path, once a solution file is started. But I wanted to save the file where the original script exists. So I used $PsScriptRoot.
If you're calling native apps, you need to worry about [Environment]::CurrentDirectory not about PowerShell's $PWD current directory. For various reasons, PowerShell does not set the process' current working directory when you Set-Location or Push-Location, so you need to make sure you do so if you're running applications (or cmdlets) that expect it to be set.
In a script, you can do this:
$CWD = [Environment]::CurrentDirectory
Push-Location $MyInvocation.MyCommand.Path
[Environment]::CurrentDirectory = $PWD
## Your script code calling a native executable
Pop-Location
# Consider whether you really want to set it back:
# What if another runspace has set it in-between calls?
[Environment]::CurrentDirectory = $CWD
There's no foolproof alternative to this. Many of us put a line in our prompt function to set [Environment]::CurrentDirectory ... but that doesn't help you when you're changing the location within a script.
Two notes about the reason why this is not set by PowerShell automatically:
PowerShell can be multi-threaded. You can have multiple Runspaces (see RunspacePool, and the PSThreadJob module) running simultaneously withinin a single process. Each runspace has it's own $PWD present working directory, but there's only one process, and only one Environment.
Even when you're single-threaded, $PWD isn't always a legal CurrentDirectory (you might CD into the registry provider for instance).
If you want to put it into your prompt (which would only run in the main runspace, single-threaded), you need to use:
[Environment]::CurrentDirectory = Get-Location -PSProvider FileSystem
This would work fine.
Push-Location $PSScriptRoot
Write-Host CurrentDirectory $CurDir
I often used the following code to import a module which sit under the same directory as the running script. It will first get the directory from which powershell is running
$currentPath=Split-Path ((Get-Variable
MyInvocation -Scope
0).Value).MyCommand.Path
import-module "$currentPath\sqlps.ps1"
I made a one-liner out of #JohnL's solution:
$MyInvocation.MyCommand.Path | Split-Path | Push-Location
Well I was looking for solution for this for a while, without any scripts just from CLI. This is how I do it xD:
Navigate to folder from which you want to run script (important thing is that you have tab completions)
..\..\dir
Now surround location with double quotes, and inside them add cd, so we could invoke another instance of powershell.
"cd ..\..\dir"
Add another command to run script separated by ;, with is a command separator in powershell
"cd ..\..\dir\; script.ps1"
Finally Run it with another instance of powershell
start powershell "cd..\..\dir\; script.ps1"
This will open new powershell window, go to ..\..\dir, run script.ps1 and close window.
Note that ";" just separates commands, like you typed them one by one, if first fails second will run and next after, and next after... If you wanna keep new powershell window open you add -noexit in passed command . Note that I first navigate to desired folder so I could use tab completions (you couldn't in double quotes).
start powershell "-noexit cd..\..\dir\; script.ps1"
Use double quotes "" so you could pass directories with spaces in names e.g.,
start powershell "-noexit cd '..\..\my dir'; script.ps1"

How to give the path as a parameter or a variable in 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.

Powershell.exe running the script in cli, or a wrapper?

I have a third-party application that's extensible by adding exe-files that perform dataconversion etc. I've written an extension in Powershell that does the conversion I want, but I'm unable to get the third-party app to run my ps1, as it will only accept an .exe file as an extension.
The app adds a filename as the first (and only) commandline argument to the extension, so the command it runs looks like:
someprogram.exe somefile.xml
I tried to get it to run Powershell.exe with my script as an argument, but I haven't been able to figure out how and if that's possible. Some stuff I tried like
powershell.exe myscript.ps1
won't work. I tried getting the script to find the correct XML file itself, but still somehow I couldn't get Powershell to run off the commandline and take a script as an argument and run it.
Next I thought about writing a small .exe file that only runs the Powershell script, but is that even possible? If it is, could someone nudge me in the right direction?
Powershell wants to have a qualified path to script files before it will run them. So you need to either use
powershell.exe .\myscript.ps1
if it lies in the current working directory (unlikely and prone to break for this use case) or use the full path to the script:
powershell.exe C:\Users\Foo\Scripts\myscript.ps1
or similar.
You can also try Powershell.exe -Command "& your-app.exe ${your-arguments}