I am trying to streamline how I execute some scripts I wrote by setting up a function and alias to run them. I currently have functions to change my directory to where the scripts need to be run, but when I try to run the script itself I get the following error:
C:\Users\me\Desktop\BoB : The term 'C:\Users\me\Desktop\BoB' 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:1 char:1
+ C:\Users\me\Desktop\BoB Tools\folderScannerV0.4.ps1
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\jteit\Desktop\BoB:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
The function is:
function run-scanner { "& 'C:\Users\me\Desktop\BoB Tools\folderScannerV0.4.ps1'" | Invoke-Expression }
I've tried a few variations based on other answers I've found, but I keep getting the same error. I would prefer to not remove the space on the path because other scripts use it successfully. Running the script from the ISE gives me no problems.
Ideally I would like the function to also allow me to have the script run on the folders I would like without changing the working directory (each script works on a particular set of files that are in a static location but some of them use $PWD to get the folders in the location).
For example in my $profile file I have this function: function go-to-temp {cd "C:\Users\me\Desktop\Bob Tools\To be Formatted\Temp"} which I run before I execute the above script. I would like them rolled into a single command without my working directory changing (which would render the go-to-temp function redundant.
What am I doing wrong?
There is no reason to run your script through Invoke-Expression.
Unless your script relies on $PWD, then you should be able to execute it with the call operator: &. As the other poster mentioned, you can use dot-sourcing (.) if you need the variables the script generates, but this will import all global objects (aliases, variables, functions) to your current scope. If it does rely on $PWD, you can utilize Start-Process with -WorkingDirectory to avoid changing where you're at.
function Start-Scanner {
& "$HOME\Desktop\BoB Tools\folderScannerV0.4.ps1"
}
or
function Start-Scanner {
$startArgs = #{
FilePath = "$PSHOME\powershell.exe"
ArgumentList = '-File', "`"$HOME\Desktop\BoB Tools\folderScannerV0.4.ps1`""
WorkingDirectory = "$HOME\Desktop\BoB Tools"
NoNewWindow = $true
Wait = $true
}
Start-Process #startArgs
}
You can just use dot-sourcing for this:
function run-scanner { . 'C:\Users\me\Desktop\BoB Tools\folderScannerV0.4.ps1' }
Related
I'm invoking a script as described here and exemplified here. It's running and I can see the outputs to the console (both hazaa and shazoo). However, the method declared in it does not appear to be there, despite testing both versions below.
Invoke-Expression -Command $target
$target | Invoke-Expression
The contents of the file are like this.
Write-Host "Hazaa"
function TestPower { Write-Host "I got the power..." }
Write-Host "Shazoo"
When I execute the same function definition in the console, it's there, working fine. I'm not getting any errors on the manual execution nor the invokation from the other file. No warnings neither.
The weirdest part is that the function definitions done in the invoking script (i.d. the one that the invokes the execution not the one that in being targeted for the invokation).
To rephrase your issue - a function defined in a script invoked with Invoke-Expression isn't available after the expression has executed, i.e.:
test.ps1
Write-Host "Hazaa"
function TestPower { Write-Host "I got the power..." }
Write-Host "Shazoo"
Interactive
PS> Invoke-Expression -Command "C:\src\so\test.ps1"
PS> TestPower
TestPower : The term 'TestPower' 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:1 char:1
+ testpower
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (testpower:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
You can fix this by dot-sourcing the script in the expression instead:
PS> Invoke-Expression -Command ". 'C:\src\so\test.ps1'"
Hazaa
Shazoo
PS> TestPower
I got the power...
Note that the documentation for script scope and dot sourcing says:
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.
Which explains why TestPower isn't available outside of your Invoke-Expression because the script is running in its own scope.
By contrast, using dot sourcing:
The dot sourcing feature lets you run a script in the current scope instead of in the script scope. ... After the script runs, you can use the created items and access their values in your session.
I wrote a script in PowerShell and I am having various success calling Image Magick's montage.exe on different computers. The computer on which I wrote the script has no problem executing the 'montage' command, however on another computer with IM Installed the script errors out:
montage : The term 'montage' 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 \\Server\Contact_Sheet_Local.ps1:51 char:9
+ montage -verbose -label %t -pointsize 20 -background '#FFFFFF ...
+ ~~~~~~~
+ CategoryInfo : ObjectNotFound: (montage:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
I have tried using montage.exe and even tried the entire path C:\Program Files\ImageMagick-7.0.3-Q16\montage.exe. Additionally I tried setting the directory first:
Set-Location -Path 'C:\Program Files\ImageMagick-7.0.3-Q16'
montage...
Each time on a particular computer this fails. I have tried with IM versions 7.0.3-Q16 and 6.9.1-6-Q8 both x64 as both computers are x64
In the past, I have created scripts in .bat that use ImageMagick and I had to define the full path to the .exe as I mentioned above. But this doesn't seem to help in PowerShell.
Does anyone have any advice or experience with this problem?
If your path has spaces, it will fail if you're just trying to execute based on that. You'll want to utilize the dot operator
$Exe = 'C:\Program Files\ImageMagick-6.9.1-6-Q8\montage.exe'
If (-not (Test-Path -Path $Exe))
{
$Exe = 'C:\Program Files\ImageMagick-7.0.3-Q16\montage.exe'
}
. $Exe -arg1 -etc
PowerShell does not execute programs in the current directory by default. If you want to run an executable that's sitting in the current directory, prefix the executable's name with .\ or ./. Example:
Set-Location "C:\Program Files\ImageMagick-7.0.3-Q16"
.\montage.exe ...
If you have an executable's name in a string or string variable and you want to execute it, you can do so using the & (call or invocation) operator:
& "C:\Program Files\ImageMagick-7.0.3-Q16\montage.exe" ...
If you specify a path and filename that doesn't contain spaces, the & operator isn't required; example:
C:\ImageMagick\montage.exe ...
You could also write it this way:
& C:\ImageMagick\montage.exe ...
If you have an executable's filename in a string variable and you want to execute it, use &; example:
$execName = "C:\Program Files\ImageMagick-7.0.3-Q16\montage.exe"
& $execName ...
I am trying to generate a MachineKey for my application using the PowerShell script found in kb2915218.
I have copied the function into notepad and saved as a .PS1 file. Now if I look at this file through explorer it is being recognised as a PowerShell file.
I then have run PowerShell and CD to the directory of my .PS1 file.
I then ran the following command:
Set-ExecutionPolicy Unrestricted
followed by:
.\Powershell-Generate-MachineKey.ps1
(the name of my script). And finally I then tried running the command
Generate-MachineKey
However I get the message:
Generate-MachineKey : The term 'Generate-MachineKey' 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:1 char:1
+ Generate-MachineKey
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Generate-MachineKey:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Can someone please tell me where I am going wrong here?
The script just defines a function, so if you execute it like this:
.\Powershell-Generate-MachineKey.ps1
it won't do anything, because the function isn't invoked anywhere and also isn't made available in the current context. For the latter you need to dot-source the script
. .\Powershell-Generate-MachineKey.ps1
The dot-operator basically executes the script in the current context instead of a child context. That way the definitions from the script become available in the current context, and you can invoke the function like this:
Generate-MachineKey
What I need to do is execute a program on a remote fileshare inside powershell. An example path would be:
\mycompany\filesharename\folder\program.exe
This program takes a command line arguement, a string, and decrypts it. Problem is I need to decrypt and encrypt literally thousands of lines from different files on different computers. Doing it one at a time through that thing is driving me mad. I've started out with this:
clear-host
([string]$step='this')
$value = Invoke-Command '\\mycompany\fileshare\folder\software\program.exe' $step
write-host $value
This is throwing an error:
The term '\\mycompany\fileshare\folder\software\program.exe' is not re
cognized 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 C:\Users\Me\Documents\Scripts\test.ps1:3 char:77
+ $value = \\mycompany\fileshare\folder\software\program.exe <<<< $st
ep
+ CategoryInfo : ObjectNotFound: (\\mycompany\fileshare...\program.exe:String
) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Eventually the plan is to code a gui, have the script grab the strings I need from the files themselves, and print them inside a local folder. Right now I need to figure out how the heck to use that progam inside my script. Any help?
Use Invoke-Expression instead of Invoke-Command:
$step='this'
$value = Invoke-Expression "\\mycompany\fileshare\folder\software\program.exe $step"
write-host $value
Can anyone explain to me why:
iex "C:\Program Files\test\test.exe"
Returns:
C:\Program : The term 'C:\Program' 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:1 char:1
+ C:\Program Files\test\test.exe
+ ~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Program:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
I've tried to get this working multiple different ways:
Wrapping the text in ()
Putting the string into a variable and passing it as a variable instead
Using single quotes
Using double quotes
I don't know how else I can get it to realize that the entire string must be run, not just the first word.
Post-answered example
The question has been answered. Here is something I was trying to get working:
$tool = "C:\Windows\System32\cmd.exe"
$param = "/c ping google.com -n 1"
$test = & $tool $param
Write-Host $test
It turns out that the line with & does NOT work with double quotes "" in this instance, and actually worked without them. I think this has to do with there being arguments/parameters involved.
Use the & operator together with quotes:
& "C:\Program Files\test\test.exe"
From help about_operators:
& Call operator
Runs a command, script, or script block. The call operator, also known as
the "invocation operator," lets you run commands that are stored in
variables and represented by strings. Because the call operator does not
parse the command, it cannot interpret command parameters.
C:\PS> $c = "get-executionpolicy"
C:\PS> $c
get-executionpolicy
C:\PS> & $c
AllSigned