Powershell - if $var -like $var* - powershell

I'm working with SCSM in Powershell but running into an issue with an if statement.
I have a function that collects data based on a criteria that is passed into the function as a variable.
Example:
$JMLs1 = collectTickets -crit $JMLCriteria1
collectTickets is the function, $JMLCriteria1 is the criteria that is passed.
This is the collectTickets function:
function collectTickets
{
param (
[parameter (Mandatory=$true)]
$crit
)
$fullDate = Get-Date
if ($fullDate.DayOfWeek -eq 'Monday')
{
$olderThan = $fullDate.AddDays(-4)
}
elseif ($fullDate.DayOfWeek -eq 'Tuesday')
{
$olderThan = $fullDate.AddDays(-4)
}
else
{
$olderThan = $fullDate.AddDays(-2)
}
if ($crit -like '$JML*')
{
$data = Get-SCSMObject -Criteria $crit | select 'Id', 'Title', 'LastModified', 'Priority'
}
else
{
$data = Get-SCSMObject -Criteria $crit | Where-Object {($_.LastModified -lt $olderThan)} | select 'Id', 'Title', 'LastModified', 'Priority'
}
return $data
}
The issue I'm having is with the second if statement, the if ($crit -like '$JML*') - I'm not sure if we can use wildcards like this against variables or if the syntax is just not correct.
Just to clarify there will be multiple $JML criteria variables as well as multiple other criteria variables, but it's only the $JML criteria variables that I want to treat differently.

Use double quotes instead of single. With single quotes, PowerShell thinks you are looking for the the literal string $JML, not the variable.
if ($crit -like "$JML*")
Edit: about_Quoting documentation

Related

Powershell DataTable,Select Filter does not accept single quote character

I'm writing a simple Name search against a datatable using Powershell. The code as following:
$filter = "Name = '$aContact'"
$arow = $dt_resources.Select($filter)
This works all fine except if $aContact contains a single quote (') character, like "O'Connor".
Any ideal how can I workaround this issue?
Thanks all in advance.
Mathias R. Jessen already commented on the solution to the question but to put it as an answer, you can escape the ' by doubling them. I added a simple function that will also serve as workaround for possible $null input since both methods (.Contains and .Replace) would throw an exception in that case.
$dtt = [System.Data.DataTable]::new()
'Name', 'Value' | ForEach-Object{
$dtt.Columns.Add([System.Data.DataColumn]::new($_))
}
$row = $dtt.NewRow()
$row.Name = "O'Connor"
$row.Value = [random]::new().Next()
$dtt.Rows.Add($row)
$row = $dtt.NewRow()
$row.Name = "Doe"
$row.Value = [random]::new().Next()
$dtt.Rows.Add($row)
function CheckQuery {
param(
[parameter(ValueFromPipeline)]
[string]$Value
)
if($Value.Contains("'")) { return $Value.Replace("'","''") }
return $Value
}
"O'Connor", "Doe", $null | ForEach-Object {
$filter = "Name = '{0}'" -f ($_ | CheckQuery)
$dtt.Select($filter)
}

Get-ADUser - want to write only one part of the OU into a variable

I have this:
Get-ADUser myuser |
Select #{n='OU';e={$_.DistinguishedName -replace '^.*?,(?=[A-Z]{2}=)'}}
But I need to get only on part of the OU of a specific user which I have to define as a variable in the beginning.
I get this
OU=Users,OU=Munich,DC=xyzdom,DC=xyz
And I want to detect if the user is in the Munich OU or where ever.
So the output should be just $city and the input $username
I have no clue how to do this. But I suspect it should be not as hard to achieve this goal.
Maybe someone has time and passion to show me how :)
Thank you so much
Greetings
Thanks a lot for the help. (I can't use the city property.) My solution looks like this now:
Import-Module ActiveDirectory
$samaccountname = "Smith"
$ou = Get-ADUser $samaccountname | Select #{n='OU';e={$_.DistinguishedName.split(',')[-3].split("=")[-1]}} | FT -HideTableHeaders
$ou
Now, the output is just: Munich
I want to go on using this variable but maybe it's in a wrong format. when I try to use it with orchestrator I get an output like this: Microsoft.PowerShell.Commands.Internal.Format.FormatStartData Microsoft.PowerShell.Commands.Internal.Format.GroupStartData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.GroupEndData Microsoft.PowerShell.Commands.Internal.Format.FormatEndData
So maybe it has to be formated as string??? How can I do that?
I agree with Santiago that using the users AD attribute City would be a much better solution, but if you don't have that filled in on the users, you may try below.
A DistinguishedName can contain commas, escaped characters and even special characters converted to their HEX representation.
See here and there
Simply splitting a DN on the comma can therefore return unwanted results.
For this, I've written a small helper function some time ago you could use:
function Parse-DistinghuishedName {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)]
[string[]]$DistinghuishedName
)
begin {
function _ReplaceSpecial([string]$value) {
# replace all special characters formatted as BackSlash-TwoDigitHexCode
$match = ([regex]'(?i)\\([0-9a-f]{2})').Match($value)
while ($match.Success) {
$value = $value -replace "\\$($match.Groups[1].Value)", [char][convert]::ToUInt16($match.Groups[1].Value, 16)
$match = $match.NextMatch()
}
# finally, replace all backslash escaped characters
$value -replace '\\(.)', '$1'
}
}
process {
foreach ($dn in $DistinghuishedName) {
$hash = [ordered]#{}
# split the string into separate RDN (RelativeDistinguishedName) components
$dn -split ',\s*(?<!\\,\s*)' | ForEach-Object {
$name, $value = ($_ -split '=', 2).Trim()
if (![string]::IsNullOrWhiteSpace($value)) {
$value = _ReplaceSpecial $value
switch ($name) {
'O' { $hash['Organization'] = $value }
'L' { $hash['City'] = $value }
'S' { $hash['State'] = $value }
'C' { $hash['Country'] = $value }
'ST' { $hash['StateOrProvince'] = $value }
'UID' { $hash['UserId'] = $value }
'STREET' { $hash['Street'] = $value }
# these RDN's can occur multiple times, so add as arrays
'CN' { $hash['Name'] += #($value) }
'OU' { $hash['OrganizationalUnit'] += #($value) }
'DC' { $hash['DomainComponent'] += #($value) }
}
}
}
$hash
}
}
}
It parses the DN into its RDN components and returns a Hashtable.
In your case, use it like:
(Parse-DistinghuishedName 'OU=Users,OU=Munich,DC=xyzdom,DC=xyz').OrganizationalUnit[1] # --> Munich

Initialize hashtable from array of objects?

I'm brand new to powershell, as in less than a day experience. I have an array of objects returned from a Get-ADUser call. I will be doing a lot of lookups so thought it best to build a hashtable from it.
Is there a shorthand way to initialize the hashtable with this array and specify one of the object's attributes to use as a key?
Or do I have to loop the whole array and manually add to the set?
$adSet = #{}
foreach ($user in $allusers) {
$adSet.add($user.samAccountname, $user)
}
[...] do I have to loop
Yes
... the whole array ...
No
You don't have to materialize an array and use a loop statement (like foreach(){...}), you can use the pipeline to turn a stream of objects into a hashtable as well, using the ForEach-Object cmdlet - this might prove faster if the input source (in the example below, that would be Get-Service) is slow:
$ServiceTable = Get-Service |ForEach-Object -Begin { $ht = #{} } -Process { $ht[$_.Name] = $_ } -End { return $ht }
The block passed as -Begin will execute once (at the beginning), the block passed to -Process will execute once per pipeline input item, and the block passed to -End will execute once, after all the input has being recevied and processed.
With your example, that would look something like this:
$ADUserTable = Get-ADUser -Filter * |ForEach-Object -Begin { $ht = #{} } -Process { $ht[$_.SAMAccountName] = $_ } -End { return $ht }
Every single "cmdlet" in PowerShell maps onto this Begin/Process/End lifecycle, so generalizing this pattern with a custom function is straightforward:
function New-LookupTable {
param(
[Parameter(Mandatory, ValueFromPipeline)]
[array]$InputObject,
[Parameter(Mandatory)]
[string]$Property
)
begin {
# initialize table
$lookupTable = #{}
}
process {
# populate table
foreach($object in $InputObject){
$lookupTable[$object.$Property] = $object
}
}
end {
return $lookupTable
}
}
And use like:
$ADUserTable = Get-ADUser |New-LookupTable -Property SAMAccountName
See the about_Functions_Advanced document and related help topics for more information about writing advanced and pipeline-enabled functions

Concatenating a variable and a string literal without a space to an array using PowerShell

I'm trying add to a variable and a string in an array dynamically but i'm not getting expected output.
(1) I'm getting env name
(2) Concatinating the string and variable in an array
Code is as follows.
$env = $env:COMPUTERNAME.Substring(0,2)
$servers = { $env+"server1.test.com",$env+"server2.test.com" }
$serverCount = $servers -split(",") | measure | % { $_.Count }
For ($i=0; $i -lt $serverCount; $i++)
{
$ServerName = $servers -split(',') -replace '\[\d+\]'
$server = $ServerName[$i]
Write-Host $server
}
output i'm getting as
$env+"server1.test.com"
$env+"server2.test.com"
Values are not getting concatenated properly and variable value is not getting displayed. Any help.
$servers = { $env+"server1.test.com",$env+"server2.test.com" }
This is a scriptblock, not an array. {} is like a function, you have to run it for it to do anything (such as evaluating $env).
When you force it into a string using -split(",") what you get is text representation of the source code in the scriptblock, including the variable names.
As #Olaf comments, the right way to create an array of names is
$servers = ($env + "server1.test.com"), ($env + "server2.test.com")
This might be how I'd write it:
$env = $env:COMPUTERNAME.Substring(0,2)
"server1.test.com", "server2.test.com" | foreach-object {
"$env$_" -replace '\d+'
}

How can I pass dynamic parameters to powershell script and iterate over the list?

I want to create a powershell script that accepts dynamic parameters and I also want to iterate through them.
eg:
I call the powershell script in the following manner.
ParametersTest.ps1 -param1 value1 -param2 value2 -param3 value3
And I should be able to access my params inside the script as follows:
for($key in DynamicParams) {
$paramValue = DynamicParams[$key];
}
Is there anyway to do this in powershell? Thanks in advance.
There is nothing built-in like that (essentially you're asking for PowerShell parameter parsing in the absence of any definition of those parameters). You can emulate it, though. With $args you can get at all arguments of the function as an array. You can then iterate that and decompose it into names and values:
$DynamicParams = #{}
switch -Regex ($args) {
'^-' {
# Parameter name
if ($name) {
$DynamicParams[$name] = $value
$name = $value = $null
}
$name = $_ -replace '^-'
}
'^[^-]' {
# Value
$value = $_
}
}
if ($name) {
$DynamicParams[$name] = $value
$name = $value = $null
}
To iterate over dynamic parameters you can either do something like you wrote
foreach ($key in $DynamicParams.Keys) {
$value = $DynamicParams[$key]
}
(note the foreach, not for, the latter of which cannot work like you wrote it) or just iterate normally over the hash table:
$DynamicParams.GetEnumerator() | ForEach-Object {
$name = $_.Key
$value = $_.Value
}