PowerShell if -like error - powershell

Not sure what's wrong with this script
$SSODelete= "Delete"
$SSOfiles = "SSo.xml"
$channlename = "INC8-Patch"
write-host $channlename
if ($channelname -like *INC8*){
$SSOarg = "$SSODelete $SSOfiles"
Write-Host $SSOarg
}
It throws following error:
You must provide a value expression following the '*' operator.
At line:5 char:25
+ if ($channelname -like *INC8*){
+ ~~~~~
Unexpected token 'INC8*' in expression or statement.
Tried using "*INC8*" and '*INC8' but it then it does not qualify if statement.
Adding screenshot for script and it's results
Simple Script and results

The PowerShell -like operator should be used with the matching string quoted, e.g., $variable -like "*pattern*". -like accepts the simple wildcard (*) only; you can compare against regular expressions (regexps) by using -match. See Get-Help about_Comparison_Operators.

Thanks , it was due to variable name i was comparing ... i need to be more cautious

Related

Powershell get SQL instance

I am using the below script to get the SQL instance name and then perform some tasks related to it. I am unable to get it working can you help me figure out how to fix the issue?
$SQLInstances = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server').InstalledInstances
foreach ($sql in $SQLInstances) {
[PSCustomObject]#{
InstanceName = $sql
}
}
Write-Host "The following SQL Instances were detected on the server $env:Computername $SQLInstances" -ForegroundColor Yellow
If ($SQLInstances -ne "MSSQLSERVER")
{Write-Host $($env:Computername)\$($SQLInstances)
$serverName = $($env:Computername)\$($SQLInstances)}
Else {Write-Host "Standard SQL Instance was found, proceeding with the script."
$ServerName = $env:Computername}
So the above code doesn't work, Write-Host displays"ComputerName(SPACE)\InstanceName" so there is an extra space there that i want to get rid off, plus $serverName = $($env:Computername)\$($SQLInstances)} throws " unexpected token / expression
How Do i fix this?
You are seeing this issue with Write-Host because of how the parser is interpreting tokens. () or $() (unless () or $() is part of a string) is going to be treated as one argument in expression mode. Since the default separator for Write-Host is a space, you get the extra space between each of your processed arguments. If you surround your entire value with double quotes, it will be parsed as a single token.
Write-Host "$($env:Computername)\$SQLInstances"
Regarding the $serverName assignment, it is also a parsing issue. When assigning to a variable, the parser is in expression mode. Therefore, the value must be a valid expression. The \ character is what throws the error. Double quotes will also suffice here.
$serverName = "$($env:Computername)\$SQLInstances"
Try the Get-SqlInstance cmdlet from module sqlserver:
Import-Module sqlserver
If (Get-SQLInstance -ServerInstance "MSSQLSERVER"){
# Instance found
}
Else {
# Instance not found

PowerShell alias - No restrictions on name

I have written a simple SetDifference function, by using the Compare-Object function:
Function SetDifference {
param(
[Parameter(Mandatory=$true)]$ReferenceObject,
[Parameter(Mandatory=$true)]$DifferenceObject
)
Compare-Object $ReferenceObject $DifferenceObject |
Where-Object { $_.SideIndicator -eq '<=' } |
ForEach-Object { $_.InputObject }
}
I've noticed that ANY alias can be used without PowerShell complaining:
Set-Alias '\' 'SetDifference'
Set-Alias '.' 'SetDifference'
Set-Alias '+' 'SetDifference'
Shouldn't there be restrictions on what the alias name can be - to stop you from using symbols that are already part of PowerShell syntax?
You should get an error, when using i.e. the '+'.
See here, you should follow this: "You can use any alphanumeric characters in an alias, but the first character cannot be a number."
Also resuing an already defined alias will throw an error.

Beginner Problems with Equals Operator

everyone trying to learn Powershell off and on and I'm stuck on this problem. I cannot seem to find an equals operator that this code will accept at the = true portion .
Ive tried -eq, =, ==, and === .
Trying to get the Msg box to pop up if this Test-path command returns a true condition.
$wshell = New-Object -ComObject Wscript.Shell
If( Test-Path 'C:\wmw\~$test.xlsx' **= True)**
{
$wshell.Popup("Hey $Env:ComputerName This file is in use!",0,"test")}
else
{$wshell.Popup("Hey $Env:ComputerName This file is not in use!",0,"test")}
First of all, the literal for true is $true in PowerShell. And the operator for equality comparison is -eq. Then there is the issue that parameters to cmdlets start with - and you'd need to wrap the command in parentheses. Otherwise -eq would be interpreted as a (non-existent) parameter to Test-Path. So putting that all together:
If( (Test-Path 'C:\wmw\~$test.xlsx') -eq $True) { ... }
or, since if just needs a value that can be coerced to a boolean you don't even need the explicit comparison in most cases:
if (Test-Path 'C:\wmw\~$test.xlsx') { ... }
One hint for future exploration of the shell: Read the error messages. Most of the time they are helpful.
Omitting the parentheses and using -eq tells you about the fact that it's interpreted as a parameter:
Test-Path : A parameter cannot be found that matches parameter name 'eq'.
Same with = which is interpreted as a parameter value here:
Test-Path : A positional parameter cannot be found that accepts argument '='.
Using parentheses correctly and using -eq breaks the parser, admittedly:
You must provide a value expression following the '-eq' operator.
Unexpected token 'True' in expression or statement.
Missing closing ')' after expression in 'if' statement.
Unexpected token ')' in expression or statement.
Using parentheses and = is helpful again:
The assignment expression is not valid. The input to an assignment operator must be an object that is able to accept assignments, such as a variable or a property.

How to escape characters inside of a parameter in Powershell?

This is a simplified version of my function:
function DetectLocalUser($localGroup, $members)
{
$result = net localgroup "$localGroup"
#$members= $members.Replace("\","\\")
if ($result -match $members)
{
return $true
}
else
{
return $false
}
}
To invoke the function I use this example (Typical values I am going to receive):
DETECTLocalUser "test" "iis apppool\userapi"
The parameters are not controlled by me. If they were I would escape directly the second parameter "iis apppool\\userapi"
On execution I have a problem with the \ in the parameter. The exact error is:
parsing "iis apppool\icisapi" - Unrecognized escape sequence \i. At
C:\k\a.ps1:6 char:9
+ if ($result -match $members)
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException
I found a workaround by adding #$members= $members.Replace("\","\\") fixes the problem but I am not sure if is the best option.
Is my workaroud acceptable or is there a better way of escaping $members parameter?
[RegEx]::Escape($members)
That will ensure that characters in strings get interpreted as literals and not as part of the RegEx.
To explain further, the -match operator is doing a regular expression match, so the string you pass to it is interpreted as a regular expression.
Backslash happens to be the escape character in a regular expression, so that's where your issue is. Using [RegEx]::Escape() ensures that other characters won't be interpreted, such as [,],.,+,(,),^,$,?,*, etc.

How to provide Linux-style parameter names in a powershell script

I would like to create a Powershell script that takes parameters in the standard Linux style, i.e., --my-param, with a leading --. I thought this might be possible using the alias parameter attribute, as in
Param (
[parameter(Mandatory=$true)]
[alias("-my-param","p")]
[String]
$param
)
What I hoped with this was that the call
c:\src\ps\params.ps1 --my-param "x"
would be recognized as referring to the alias -my-param. Unfortunately, what I get is
C:\src\ps\params.ps1 : A positional parameter cannot be found that accepts argument 'x'.
At line:1 char:21
+ c:\src\ps\params.ps1 <<<< --my-param1 "x"
+ CategoryInfo : InvalidArgument: (:) [params.ps1], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,params.ps1
On the other hand, using the alias my-param in this lets me call the script with -my-param.
Is there a way of specifying parameter names with leading -- in Powershell?
Your syntax fails at tokenizer level. Compare:
[Management.Automation.PSParser]::Tokenize(
'Command -parameter',
[ref]$null
)
...and...
[Management.Automation.PSParser]::Tokenize(
'Command --parameter',
[ref]$null
)
As you can see former is seen by parser as parameter, latter - as argument.
So the only way would be parsing all arguments "internally" and guessing what is parameter (from your perspective), and what is argument.
I'm not aware of any libraries that will parse Unix-style parameters for you (which doesn't necessarily mean there isn't one...), but you could just not declare any parameters, and parse the parameters yourself in the body of the script.
This will create a hashtable of the parameters, where they keys are the parameter names and the values are the parameter values. Switch parameters will have null values.
$params = #{}
$MyInvocation.Line.Substring(($MyInvocation.Line.IndexOf('--') + 2)) -split ' --' | %{
$_ -match '(\S+) ?(.+)?' | Out-Null
$params.($matches[1]) = $matches[2]
}
$MyInvocation.Line gives you the command line that was used to invoke the script. $MyInvocation.Line.Substring(($MyInvocation.Line.IndexOf('--') + 2)) gives you everything following the first --.
$_ -match '(\S+) ?(.+)?' assigns the parameter name to the first match group, and the value to the second match group. The Out-Null prevents PowerShell from printing True for each iteration.
The reason I used (.+)? rather than (.*) is to make the values of switch parameters null. (.*) will match an empty string if there is nothing to match, making the value of $matches[2] an empty string, whereas (.+)? won't match, making $matches[2] null.
This is assuming that all parameters begin with --. If you want to allow a single hyphen, restrict single-dash parameter names to a single letter, or check for incorrectly declared parameters (for example throw an error if there's a triple-hyphen), you'll have to account for that in your code, but this is the basic idea.