Find VM with exact name in get-vm incase of multiple entries - powershell

I am having code where I am searching VM details using Get-VM -Name $VM_Name.
It is not giving any output in below case where I have 2 entries for same VM name like below
001_MBM1P
001_MBM1P_Clone_Prj_Win
was trying something like blow but getting error
get-vm $VM_Name | where {($_.Name -match $VM_Name) -and ($VM_Name -notcontains 'Clone*')}
get-vm : 1/10/2022 11:36:52 AM Get-VM VM with name '001_MBM1P' was not found using the specified filter(s).
Please let me know how can I filter the search which will work in both cases.

The -contains and -notcontains operators work on arrays only, they are not string operations.
You may use the efficient String::Contains() method:
get-vm | where {($_.Name -match $VM_Name) -and (-not $_.Name.Contains('Clone'))}
Alternatively use the -notlike operator:
get-vm | where {($_.Name -match $VM_Name) -and ($_.Name -notlike '*Clone*')}
Note that Contains() is case-sensitive whereas -like and -notlike are not. This Q/A shows some ways for case-insensitive "contains" operation using String methods.

Related

Powershell where-object complex logic

I am having trouble coming up with a way to do complex logic using the where-object in PowerShell
I have the following code, but separating the and from the ors is not working as intended.
Get-ADComputer -Filter * | Where-Object {($_.Enabled) -and
(($_.DistinguishedName -Contains "world") -or
($_.DistinguishedName -Contains "foo")) -and
(($_.SID -Contains "bar") -or
($_.SID-Contains "something else"))}
If I do this in c# I get results, but in powershell I do not.
Any thoughts on how to get around this?
TIA
This is how you would perform your query using AD PS Module:
Get-ADComputer -LDAPFilter "(!userAccountControl:1.2.840.113556.1.4.803:=2)"|where-object{
$_.DistinguishedName -match 'World|Foo' -and $_.SID -match 'bar|something else'
}
-LDAPFilter "(!userAccountControl:1.2.840.113556.1.4.803:=2)" = Enabled Computer Object
-match allows the use of regex, you can use the pipeline as OR.
-contains is the operator you would use to lookup an item on an array. Example:
PS /> #(
'apple'
'banana'
'pineapple'
) -contains 'apple'
True
In addition, as Dave Wyatt pointed out in a nice post on powershell.org a while ago, you might want to avoid where-object whenever possible since it's the slowest way to filter collections. It's only advantages are the low memory consumption and pipeline streaming.
Here are a few examples of faster efficient code:
#Example 1:
$computers=Get-ADComputer -LDAPFilter "(!userAccountControl:1.2.840.113556.1.4.803:=2)"
$collection=[system.collections.generic.list[Microsoft.ActiveDirectory.Management.ADComputer]]::new()
foreach($computer in $computers)
{
if($computer.DistinguishedName -match 'World|Foo' -and $computer.SID -match 'bar|something else')
{
$collection.add($computer)
}
}
#Example 2:
filter myFilter{
if($_.DistinguishedName -match 'World|Foo' -and $_.SID -match 'bar|something else')
{
$_
}
}
$computers=Get-ADComputer -LDAPFilter "(!userAccountControl:1.2.840.113556.1.4.803:=2)"|myFilter
#Example 3
$computers=(Get-ADComputer -LDAPFilter "(!userAccountControl:1.2.840.113556.1.4.803:=2)").where({
$_.DistinguishedName -match 'World|Foo' -and $_.SID -match 'bar|something else'
})
There is plenty on information on the different ways of filtering Collections on PowerShell and their pros / cons on Google.
this is not an Answer - so please let me know when you have read it so that i can delete it.
this is your code with more informative indentation, with the needless extra parens removed, and with spaces around the operators.
Get-ADComputer -Filter * |
Where-Object {
$_.Enabled -and
($_.DistinguishedName -Contains "world" -or
$_.DistinguishedName -Contains "foo") -and
($_.SID -Contains "bar" -or
$_.SID -Contains "something else")
}
note that the -contains operator is NOT for strings ... it is for membership in a collection. if you want to test against strings, use -match, or .Contains(), or -like with wildcards.

Simple Powershell where filter not working

Dears,
Executing the below powershell command returns no value even though it should return some matched values. Am i missing something?
get-vm | select VMName ReplicationMode, State | Where-Object {(state -eq 'Running') -and (ReplicationMode -eq 'None')}
Is there a way to fix this without using "$_" syntax?
Thanks,
Why do you not want to use $_?
$_ represent each occurrence of your selection.
I did my own example. Where is the problem?
Get-Process | select Id, ProcessName | Where-Object {($_.ProcessName -eq 'chrome') -and ($_.Id -gt 30000)}

Check if hostname is in Array

I have an array with exclusions like:
$hosts= #("*iphone*","*Samsung*")
I would like to exclude this hosts from my dhcp-leases like:
Get-DhcpServerv4Lease -ComputerName $dhcp_server -ScopeId $scope.ScopeID |ForEach-Object {
if(($_) -and $_.Hostname -notlike $hostnames -and $_.ClientID -notlike $clientids -and $_.Description -notlike $descriptions) {
do something
When I work without array like:
$leases += Get-DhcpServerv4Lease -ComputerName $dhcp_server -ScopeId $scope.ScopeID |
where {$_.Hostname -notlike "*iphone*" -and $_.Hostname -notlike...
this works already fine.
So I've no idea, why this does not work when the exclusions are in an array instead of the where clause
AFAIK you should not use -notlike to compare against an array.
You can do it using the Regular Expression operator -notmatch. For that, you combine the options in the array with the regex OR character |.
$hosts= ("iphone","Samsung" | ForEach-Object { [Regex]::Escape($_) }) -join '|'
results in iphone|Samsung.
Note the use of [Regex]::Escape() to make sure Regex special characters get escaped so they are seen as literals.
With that, use a Where-Object clause like this:
Where-Object {$_.Hostname -notmatch $hosts}
Do the same for $clientids and $descriptions

Powershell: Get users with multiple specified Product Licences

I'm trying to get output from O365 via PowerShell for users with specific product licenses assigned.
There's plenty of articles out there of how to get this information but not found information explaining how to grab users with multiple specified products.
So far I have the following (taken from here):
Get-MsolUser -All |
Where-Object {
($_.licenses).AccountSkuId -match "EXCHANGEENTERPRISE" `
-and ($_.licenses).AccountSkuId -match "EMS" `
-and ($_.licenses).AccountSkuId -notmatch "ENTERPRISEPACK"
} |
Select-Object displayname,userprincipalname,{$_.Licenses.AccountSkuId} |
Export-Csv "C:\Temp\EOP2+EMSLicensedUsers.csv" -NoTypeInformation
However, this still shows users who have ENTERPRISEPACK assigned.
PowerShell operators do not work like you think they do.
.AccountSkuId is an array of values. Doing AccountSkuId -notmatch "ENTERPRISEPACK" does not tell you whether "ENTERPRISEPACK" is contained in that array or not. It gives you all the values from that array that do not match "ENTERPRISEPACK".
It's a filter. Try executing "1","2","3" -notmatch "3" to see what I mean.
Therefore, if even one value in AccountSkuId does not match "ENTERPRISEPACK", you still get some values back, and "some values" (i.e. a non-empty list) evaluates to $true in a Boolean expression.
You wanted to write this:
Get-MsolUser -All |
Where-Object {
($_.licenses).AccountSkuId -match "EXCHANGEENTERPRISE"
-and ($_.licenses).AccountSkuId -match "EMS"
-and -not (($_.licenses).AccountSkuId -match "ENTERPRISEPACK")
} |
Select-Object displayname,userprincipalname,{$_.Licenses.AccountSkuId} |
Export-Csv "C:\Temp\EOP2+EMSLicensedUsers.csv" -NoTypeInformation
Note the change. ($_.licenses).AccountSkuId -match "ENTERPRISEPACK" gives you all values that match "ENTERPRISEPACK" (normally 1 or 0) and the -not simply negates that result.
Other things to try with PowerShell operators:
1,2,2,3 -eq 2
1,2,2,3 -ne 2
1,2,2,3 -gt 1
"hallo","hello","foo" -like "*ll*"
"hallo","hello","foo" -replace 'l','L'
Keep in mind that PowerShell operates on lists when it can. A single value is nothing but a list of length 1.

Powershell Where-Object and DN exclusions

I am trying to query a list of users while excluding a specific OU. This is also using Quest's AD snap-in for Get-QADUser. I have this:
$ExcludedOU = "Service Accounts"
$inactiveUsers = Get-QADUser -SizeLimit 3 -SearchRoot $sourceOu -NotLoggedOnFor $InactiveFor -Enabled | Where-Object {$_.description -notlike $DescriptionPrefix -and #{n="ParentContainerDN";e={($_.ParentContainerDN -split ",*..=")[0]}} -notlike $ExcludedOU }
The goal is to exclude any users where the parent OU is "Service Accounts". ParentContainerDN looks like OU=Service Accounts,OU=Our Users,DC=DOMAINNAME,DC=ORG
This query does not error, but it does not exclude either. This is the part I may not have the syntax correct on?
#{n="ParentContainerDN";e={($_.ParentContainerDN -split ",*..=")[0]}} -notlike $ExcludedOU
I was partially wrong about the regex portion of your split. I am still correct in that the string supports regular expressions. That query will split on the CN=, OU= and DN=.
However you placed calculated property syntax into a where-object clause. It didn't error out since it is a valid hashtable and hashtables support like and notlike. Calculated properties are used for things like Format-Table and Select-Object which you can then reference those "new" properties later in other pipes.
$inactiveUsers = Get-QADUser -SizeLimit 3 -SearchRoot $sourceOu -NotLoggedOnFor $InactiveFor -Enabled |
Select-Obejct Name,SamAccountName,Description,#{n="ParentContainerDN";e={($_.ParentContainerDN -split ",*..=")[0]}} |
Where-Object {$_.description -notlike $DescriptionPrefix -and $_.ParentContainerDN -notlike $ExcludedOU }
The above syntax is what was also done in the code you linked to on Social Technet
I cannot make this return false for the life of me. This will evaluate to true which might be why your query was not working as expected. This is valid PowerShell just not correct to use.
#{n="ParentContainerDN";e={$_.WhatEver}} -notlike "string"
However like Kai Zhao mentioned in comments this is not really used effectively and you can get the same results without the calculated property.
$inactiveUsers = Get-QADUser -SizeLimit 3 -SearchRoot $sourceOu -NotLoggedOnFor $InactiveFor -Enabled |
Where-Object {$_.description -notlike $DescriptionPrefix -and ($_.ParentContainerDN -split ",*..=")[1] -notlike $ExcludedOU}