Colon as string in parameters - powershell

Is there a way to exclude the colon (:), so you can print it via parameters as String?
Little example:
PowerShellTest.ps1:
param (
[string]$message="Error: No message defined!"
);
"Info: Test-Information"
$message;
if you now starts this script via powershell:
powershell.exe D:\PowerShellTest.ps1 -message "Error: Test-Error"
Now you get only the output string Error: the rest will be cut off
What do I have to do to get the whole string Error: Test-Error?

The problem is not the colon, but the space. You need to escape it using the backtick:
powershell.exe D:\PowerShellTest.ps1 -message 'Error:` Test-Error'

Use single quotes ' instead of double quotes " like so,
C:\temp>powershell c:\temp\test.ps1 -message 'Error: Test-Error'
Info: Test-Information
Error: Test-Error

Why are you running it that way? When you run powershell.exe from inside Powershell you are forcing the arguments to go through the old Windows cmd.exe style command line processing.
Instead you should just invoke your script directly:
PS C:\scripts> .\PowershellTest.ps1 -message "Error: Test-Error"
Info: Test-Information
Error: Test-Error
This way all of the arguments will pass right through without being converted to strings, having double quotes stripped and then being re-parsed.
If you get an error because running scripts is not permitted then the answer is to change your execution policy, not to start another copy of powershell.exe:
PS C:\scripts> .\PowershellTest.ps1 -message "Error: Test-Error"
.\PowershellTest.ps1 : File C:\scripts\PowershellTest.ps1 cannot be loaded because running scripts is disabled on this
system. For more information, see about_Execution_Policies at http://go.microsoft.com/fwlink/?LinkID=135170.
At line:1 char:1
+ .\PowershellTest.ps1 -message "Error: Test-Error"
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : SecurityError: (:) [], PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess
If you see this error then start a Powershell window using the 'run as administrator' option and enter the command:
Set-ExecutionPolicy RemoteSigned
Close the administrator powershell and restart any other powershell windows you have running and now you should be able to run locally created scripts without any problems.

Related

Why a powershell command is valid in the terminal but invalid from lnk file?

For example, this command works perfectly from a PowerShell prompt :
powershell.exe -NoExit -c Set-Variable -Name "CA_HOME" -Value "$(Get-Location).Path\intermed-ca"
but fails with an error if used from an lnk file.
Set-Variable : A positional parameter cannot be found that accepts argument '\intermed-ca'.
At line:1 char:1
+ Set-Variable -Name CA_HOME -Value $(Get-Location).Path'\intermed-ca'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-Variable], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SetVariableCommand
Why ?
The error you supplied is not from that particular command. Notice PowerShell is showing us the command it is erroring on.
That particular error is simply a syntax error; that is not how you concatenate strings. Running just $(Get-Location).Path'\intermed-ca' will give you an error: "Unexpected token ''\intermed-ca'' in expression or statement."
Going back to the command you posted at the top of the OP, that is proper syntax, but won't be the Path you're looking for because the logic is flawed. So, what you posted as your command will not generate an error, but will return a path that likely doesn't exist. Assuming your working directory is your user profile, you will get something like this back for $CA_HOME: C:\Users\Zulgrib.Path\intermed-ca. The reason is that you're basically doing this:
$path = (Get-Location).Path
'{0}.Path\intermed-ca' -f $path
The .Path is part of the string, not the string execution. That's why you should add parenthesis to ensure that this property is returned as part of the string execution:
powershell.exe -NoExit -c Set-Variable -Name "CA_HOME" -Value "$((Get-Location).Path)\intermed-ca"
While this is fine and will work without issues, quote translations can be tricky from the command line. So, this really isn't a perfect solution for all scenarios. For better compatibility, I would get in the habit of wrapping the whole command in double quotes and keep single quotes inside the command:
powershell.exe -NoExit -c "Set-Variable -Name 'CA_HOME' -Value ('{0}\intermed-ca' -f (Get-Location).Path)"
For the best compatibility, consider base64 encoding your command and running it with -EncodedCommand. See the very bottom of powershell.exe /? for an example. Be weary that some situations will run into issues with overly long CLI commands.
Note: '{0}\intermed-ca' -f (Get-Location).Path and '{0}\intermed-ca' -f (Get-Location) will give the same result. When PowerShell knows it's injecting a PSOobject into a string, it'll give you the string form of what you likely want.

PowerShell Error - Missing expression after unary operator '-'

I have two PowerShell scripts. One is for uninstalling and installing a SharePoint 2010 solution on the SharePoint server. The other calls this script with two commands, one for the uninstall and one for the install. These are not scripts I wrote, but I have inherited them.
Here is the script that calls the install / uninstall script (I've removed some parameters to simplify for troubleshooting):
& 'C:\Users\username\Documents\setup.ps1' -InstallOrUninstall '/UNINSTALL'
& 'C:\Users\username\Documents\setup.ps1' -InstallOrUninstall '/INSTALL'
Stripped down to almost nothing for the purpose of testing, here is the "setup.ps1" script:
param ($InstallOrUninstall,
$SiteURL,
$WebURL,
[switch]$ignoreFeatures,
[switch]$thisAppDomain )
if (-not $thisAppDomain)
{
Write-Host "Invoking script in a new app domain" -foregroundcolor yellow
Write-Host $MyInvocation.Line
powershell.exe -Version 2 -Command $MyInvocation.Line -thisAppDomain
return;
}
Write-Host "In Body"
Write-Host $MyInvocation.Line
Running the first script returns an error from the first command, but not from the second. The error is:
powershell.exe : - : Missing expression after unary operator '-'.
At C:\Users\username\Documents\setup.ps1:11 char:6
+ powershell.exe -Version 2 -Command $MyInvocation.Line -thisAppDo ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (- : Missing exp...y operator '-'.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ CategoryInfo : ParserError: (-:String) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingExpressionAfterOperator
I believe the reason the install / uninstall script is resending the command for "Version 2" is because of an issue with using PowerShell past Version 2 with SharePoint 2010 (as outlined here). However, I don't understand why only the first line fails. The second command also enters the if statement, but does not error.
If I remove the second line, and only call the setup.ps1 one time, the script that calls the install / uninstall script succeeds.
A nice little brain-teaser. Apparently, $MyInvocation.Line contains the full line, including the newline / linebreak at the end. So, -thisAppDomain is not interpreted as a parameter, but the beginning of a new expression starting with -. This is also, why it works if you remove the 2nd line, because then you do not have a line break at the end.
To reproduce this error, try:
powershell.exe -Version 2 -Command "`r`n-thisAppDomain"
Note that in newer versions the parsing algorithm was obviousy modified and the error message is different. Omit the -Version 2 switch and you likely get:
The term "-thisAppDomain" is not recognized as the name of a cmdlet, function, script file, or operable program...
One simple way to resolve this would be to .Trim() (or .TrimEnd()) the command:
powershell.exe -Version 2 -Command $MyInvocation.Line.Trim() -thisAppDomain
I need to add though, that you should reconsider what your actual problem is, and if your solution is actually the best way to solve it. Have a look at jobs for example.
As marsze said: It is not interpreted as a parameter, but the beginning of a new expression starting with -. This is also, why it works if you remove the 2nd line, because then you do not have a line break at the end.

Calling Powershell script from CMD with paths as parameters

I`m having trouble make this cmd command to run powershell script by passing two parameters (paths).
C:\WINDOWS\System32>powershell -command \"C:\Apps\Scripts\Test\testing.ps1" \"\\Data1\dataholder$\office\J Smith\backup\" \"\\Data1\dataholder$\office\J Smith\backup2\"
I`m getting the error below:
At line:1 char:36
+ ... ps\Scripts\Test\testing.ps1 "\\Data1\dataholder$\office\ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unexpected token '\\Data1\dataholder$\office' in expression or statement.
At line:1 char:146
+ ... Smith\backup" "\\Data1\dataholder$\office\J Smith\backup2"
+ ~
The string is missing the terminator: ".
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
Any idea of why this is failing?
I had to modify the path leading to script. Now the command look like that:
C:\WINDOWS\System32>powershell -command \"C:\Apps\Scripts\Power test\testing.ps1" \"\\Data1\dataholder$\office\J Smith\backup\" \"\\Data1\dataholder$\office\J Smith\backup2\"
This is failing due to the space in the script path, any idea how to handle this?
You need to backslash escape quotes that you want to be sent from cmd shell to PowerShell:
powershell -command "& \"C:\Apps\Scripts\Power test\testing.ps1\" \"\\Data1\dataholder$\office\J Smith\backup\" \"\\Data1\dataholder$\office\J Smith\backup2\""
If your program or script file has spaces, you need to call it with a call operator (&) and include that in your string that is sent to -Command. Notice the double quotes around the entire value/string that maps to -Command.
Note: Inner double quotes work here because $ is succeeded by \. If you had dataholder$folder as an example, you would need single quotes or to escape the $ because PowerShell would try to interpret $folder as a variable.
Here's a backquoting the spaces approach.
type "my script.ps1"
echo $args[0]
powershell .\my` script.ps1 hi` there
hi there
Or strategic placement of single quotes. Something can be executed if the first character isn't a quote. The quote didn't work before the backslash.
powershell .\'my script.ps1' 'hi there'
hi there

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

Powershell | Unable to perform command with space character

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