Powershell | Unable to perform command with space character - powershell

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

Related

Uninstall program using get-process and uninstallstring with call operator (&)

I'm trying create a uninstall script to uninstall any program tha I want.
I was using this script:
get-package -Name "XXXXX" | Uninstall-Package
But I saw that when the "provideName" attribut is "Program" it not working, so I use this.
$packageArray = get-package "*XXXX*"
foreach ($package in $packageArray){
$a = $package.ProviderName
if ($a -eq "Programs"){
& {($package.Meta.Attributes["UninstallString"] -replace '"') /S}
}
if ($a -ne "Programs"){
get-package -Name "*XXXXX*" | Uninstall-Package
}
}
This part bellow was working fine when I have not ""&quot."", like this.
& {($package.Meta.Attributes["UninstallString"] -replace '"') /S}
Print:
But now I'm getting erro when a uninstall string has "&quot." value, like this.
UninstallString=""&quot";C:\Users\rsantanna\AppData\Local\GoToMeeting\19950\G2MUninstall.exe" /uninstall"
Print.
When it occur I get this error.
& : The term 'C:\Users\rsantanna\AppData\Local\GoToMeeting\19950\G2MUninstall.exe /uninstall' 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:6 char:7
& ($UninstallString)
~~~~~~~~~~~~~~~~~~
CategoryInfo : ObjectNotFound: (C:\Users\rsanta....exe /uninstall:String) [], CommandNotFoundException
FullyQualifiedErrorId : CommandNotFoundException
Anyone can help me ?
You cannot directly execute a string expression such as ($package.Meta.Attributes["UninstallString"] -replace '"')
While you can do so via &, the call operator, it only works if the string expression evaluates to a command name or executable file path only.
Notably, you can not use & to execute an entire command line, which is what $package.Meta.Attributes["UninstallString"] typically contains.
Note that your use of & is with a script block ({ ... }), which allows you to execute arbitrary statements contained in the block; however, perhaps needless to say, these statements are subject to the usual syntax rules, and it is the one and only statement in your block that causes a syntax error (that is actually different from the error you report).
As explained in detail in this answer, the command lines stored in UninstallString registry values are designed for invocation from cmd.exe or from no-shell environments.
Therefore, the simplest solution is to call via cmd.exe /c:
cmd.exe /c "$($package.Meta.Attributes["UninstallString"]) /S"
If your uninstall command line, as returned from $package.Meta.Attributes["UninstallString"], really contains " in lieu of verbatim " characters (double quotes) - which would be unusual - you'll need to replace the former with the latter first:
cmd.exe /c "$($package.Meta.Attributes["UninstallString"] -replace '"', '"') /S"
It's unclear what command produced the " output in your screenshot, but given that it shows the text of an XML document, the use of " instead of " is simply a necessity for encoding literal " chars.

Set window title when running "start powershell" in powershell not working?

The following command works in CMD (How to start powershell with a window title?).
start powershell -NoExit -command "$Host.UI.RawUI.WindowTitle = 'bits'"
But it doesn't work in Powershell.
PS C:\> start powershell -noexit -command "$Host.UI.RawUI.WindowTitle = 'test'; read-host"
Start-Process : A parameter cannot be found that matches parameter name 'noexit'.
At line:1 char:18
+ start powershell -noexit -command "$Host.UI.RawUI.WindowTitle = 'test ...
+ ~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Start-Process], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.StartProcessCommand
The following command can open a new powershell window.
start powershell "$Host.UI.RawUI.WindowTitle = 'test'; read-host"
However, the new window shows the following error message and the title is not set.
System.Management.Automation.Internal.Host.InternalHost.UI.RawUI.WindowTitle : The term
'System.Management.Automation.Internal.Host.InternalHost.UI.RawUI.WindowTitle' 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
+ System.Management.Automation.Internal.Host.InternalHost.UI.RawUI.Wind ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (System.Manageme...wUI.WindowTitle:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Bacon Bits' helpful answer explains that start in cmd.exe means something different than in PowerShell.
Use Start-Process as follows to get the desired result; note that powershell implicitly binds to parameter -FilePath, whereas the ,-separated arguments starting with -NoExit bind implicitly to the -ArgumentList (-Args) parameter, which accepts an array of strings:
# In PowerShell, `start` is an alias for `Start-Process`
start powershell '-NoExit', '-command', "`$Host.UI.RawUI.WindowTitle = 'bits'"
In paticular, --prefixed pass-through arguments must be quoted so that they're not mistaken for Start-Process's own parameters.
Also note the ` preceding the $ in $Host, which prevents up-front interpolation of $Host by the calling PowerShell instance.
You could also use '$Host.UI.RawUI.WindowTitle = ''bits''', a single-quoted literal string with embedded single quotes escaped as ''.
Important:
While passing arguments as an array to -ArgumentList is conceptually the best approach, it is unfortunately ill-advised due to a long-standing bug in Start-Process, still present as of this writing (v7.1) - see GitHub issue #5576.
For now, using a single string comprising all arguments, enclosed in embedded "..." quoting as necessary, is the only generally robust approach. As discussed in the linked GitHub issue, an -ArgumentArray parameter that supports robust array-based argument passing may be introduced in the future.
In the case at hand this means the following, as suggested by PetSerAl in a comment on the question:
Start-Process powershell '-NoExit -command "$Host.UI.RawUI.WindowTitle = ''bits''"'
Note the single-quoting_ ('...') of the overall argument-list string, which then necessitates escaping the embedded single quotes - those that PowerShell should see as part of the command - as ''.
In Command Prompt, start is the start internal command. In Windows Powershell, start is an alias for Start-Process, which does something similar but isn't identical.
Try running this:
powershell -NoExit -command "`$Host.UI.RawUI.WindowTitle = 'bits'"
Here's another way, while avoiding the dollar sign. The double quotes have to be on the outside, so that bits stays quoted.
start powershell "-noexit (get-variable host).value.ui.rawui.windowtitle = 'bits'"
You can always avoid these quoting issues putting the command in a file.
start powershell '-noexit .\window.ps1'
start powershell with the command option for setting the window title did not work for me. Maybe because I want to open another powershell with a ps1 file. so in the other ps1 file I added the first line as below,
(Get-Host).ui.RawUI.WindowTitle='TEST TEST'
and it worked like a charm....
If you add this to your powershell profile.ps1 you can get the window title to show the current running script and if you are just opening a window with no script then 'pwsh' will be displayed.
Will be systematic with no need to add a line on top of each script. The other answers
combined with $MyInvocation.MyCommand seem to give the name of the profile.ps1 instead when running a script from the context menu.
This can also be tweaked to change the result.
[console]::title = Split-Path -Leaf ([Environment]::GetCommandLineArgs()[-1]).Replace('pwsh.dll','pwsh')
Works on both PS 5 and 7 . For ver. 5 replace pwsh.dll by powershell.exe

How to use an environment variable in PowerShell console?

I have an environment variable named GOPATH. In old style command shell I could run the command %GOPATH%\bin\hello like this:
Is there an equivalently simple command in Windows PowerShell?
EDIT
I am not trying to print the environment variable. I am trying to USE it.
The variable is set correctly:
C:\WINDOWS\system32> echo $env:gopath
C:\per\go
Now I want to actually use this in a command line call, and it fails:
C:\WINDOWS\system32> $env:gopath\bin\hello
At line:1 char:12
+ $env:gopath\bin\hello
+ ~~~~~~~~~~
Unexpected token '\bin\hello' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
Use $env:[Variablename]
For example:
$env:Appdata
or
$env:COMPUTERNAME
using your example:
$env:GOPATH
To use this to execute a script use
& "$env:GOPATH\bin\hello"
Using an environment variable in a path to invoke a command would require either dot notation or the call operator. The quotation marks expand the variable and the call operator invokes the path.
Dot Notation
. "$env:M2_Home\bin\mvn.cmd"
Call Operator
& "$env:M2_Home\bin\mvn.cmd"
One solution is to use start-process -NoNewWindow to run it.
C:\windows\system32> start-process -nonewwindow $env:gopath\bin\hello.exe
C:\windows\system32Hello, Go examples!
>
This is much more verbose obviously and puts the command prompt at an odd looking prompt: >. But it does work.

Powershell spaces in script path

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' }

Running program from fileshare in powershell

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