PowerShell Where-Object like multiple string values - powershell

I'm using the following in a do-until block to loop until a specified Exchange Online migration status is present:
(Get-Migrationbatch -Identity $MigrationBatchName | Where {$_.Status -like "Completed" -or "CompletedWithErrors" -or "Corrupted" -or "Failed" -or "Stopped"})
However, the above still returns a job with the status of "Syncing" and so continues the script regardless.
I've tried -match, -eq but still the same.
What am I missing?

You have to write it like this:
(Get-Migrationbatch -Identity $MigrationBatchName | Where {($_.Status -like "Completed") -or ($_.Status -like "CompletedWithErrors") -or ($_.Status -like "Corrupted") -or ($_.Status -like "Failed") -or ($_.Status -like "Stopped")})
Here's another way to do it:
$valuesToLookFor = #(
'Completed',
'CompletedWithErrors',
'Corrupted',
'Failed',
'Stopped')
(Get-Migrationbatch -Identity $MigrationBatchName |
Where-Object { $valuesToLookFor -contains $_.Status })

It would be simpler using -in operator, given that you are not using wildcards:
(Get-Migrationbatch -Identity $MigrationBatchName | Where Status -in "Completed","CompletedWithErrors","Corrupted","Failed","Stopped")

another option convert filter array to regex string...
$filter_status = #("Completed", "CompletedWithErrors","Curropted","Failed", "Stopped")
(Get-Migrationbatch -Identity $MigrationBatchName | Where Status -Match ($filter_status -Join "|")

Related

Powershell script to log out users without specific process

I'm trying to write a script that will log out users which don't have specific process running in their session.
I guess the workflow should look like:
Get usernames of all the users logged in, get list of all the processes runnning on the workstation, check if X process is running for Y user, if not, then log user Y out.
So far i managed to create object with all the users currently logged in:
((quser) -replace '^>', '') -replace '\s{2,}', ',' | ConvertFrom-Csv
And list of all the processes running with usernames:
get-process -IncludeUserName
I believe foreach with if inside should do the job, but I can't quite get my head around it. I would appreciate any help.
Thanks!
edit:
$process = get-process -IncludeUserName|Where-Object{
($_.ProcessName -Like "processIneed1*") -or
($_.ProcessName -Like "processIneed2*") -or
($_.ProcessName -Like "processIneed") -or
($_.ProcessName -like 'processIneed3*') -and
($_.username -notlike '*userIwantToSkip1*') -and
($_.username -notlike '*userIwantToSkip2*')
}
$users = Get-RDUserSession | Where-Object -Property UserName -NE 'administrator'
$ActiveUsers = $users.username
foreach ($ProcUser in $process.username){
foreach ($ActiveUser in $ActiveUsers){
if ($ProcUser -like "*$ActiveUser*"){
$ActiveUsers = $ActiveUsers -notlike "*$ActiveUser*"
}
}
}
in $activeusers we are left with inactive users.
I will most likely change username to session ID and check it this way.
Next step will be logging off disconnected users.
$process = get-process -IncludeUserName|Where-Object{
($_.ProcessName -Like "processIneed1*") -or
($_.ProcessName -Like "processIneed2*") -or
($_.ProcessName -Like "processIneed") -or
($_.ProcessName -like 'processIneed3*') -and
($_.username -notlike '*userIwantToSkip1*') -and
($_.username -notlike '*userIwantToSkip2*')
}
$users = Get-RDUserSession | Where-Object -Property UserName -NE 'administrator'
$ActiveUsers = $users.username
foreach ($ProcUser in $process.username){
foreach ($ActiveUser in $ActiveUsers){
if ($ProcUser -like "*$ActiveUser*"){
$ActiveUsers = $ActiveUsers -notlike "*$ActiveUser*"
}
}
}
foreach ($inactiveusers in $ActiveUsers){
logoff $inactiveuser
}

Empty element not allowed [duplicate]

This question already has answers here:
pipes and foreach loops
(2 answers)
pipe foreach loop CSV PowerShell
(3 answers)
Closed 4 years ago.
I can't seem to export anything into CSV. I did some browsing and reading, but having hard time converting my script.
$allmailbox = Get-Mailbox -ResultSize 20
foreach ($Mailbox in $allmailbox) {
Get-MailboxFolderPermission -Identity ($mailbox.alias+':\calendar') |
Where {
$_.User -like "Anonymous" -and
$_.AccessRights -ne "None" -or
$_.User -like "Default" -and
$_.AccessRights -ne "None" -or
$_.User -like "Default" -and
$_.AccessRights -ne "AvailabilityOnly"
} |
select Identity, User, AccessRights
} | Export-Csv C:\CSVs\calstest.csv
The empty element not allowed is referring to the | at the end of your foreach. The way that your loop is structured does not allow the pipe. Below shows a different approach that can work.
Below should get you everything in one CSV file:
Get-Mailbox -ResultSize 20 | foreach {Get-MailboxFolderPermission -Identity $($_.Alias+":\calendar") | Where {$_.User -like "Anonymous" -and $_.AccessRights -ne "None" -or $_.User -like "Default" -and $_.AccessRights -ne "None" -or $_.User -like "Default" -and $_.AccessRights -ne "AvailabilityOnly"}| select Identity,User,AccessRights} | Export-Csv C:\CSVs\calstest.csv -NoTypeInformation
I tested this without the Where-Object and it exported successfully. If you are not receiving any information you might want look more into your Where . Start with one condition and increase as needed.
$allmailbox = Get-Mailbox -ResultSize 20
Foreach ($Mailbox in $allmailbox){Get-MailboxFolderPermission –Identity ($mailbox.alias+':\calendar') |
Where {
($_.User -like "Anonymous" -and $_.AccessRights -ne "None") -or
($_.User -like "Default" -and $_.AccessRights -ne "None") -or
($_.User -like "Default" -and $_.AccessRights -ne "AvailabilityOnly")
}| select Identity,User,AccessRights} | Export-CSV C:\CSVs\calstest.csv
If that's what you're looking for, though you'll have to add backticks I think for it to be seen as a complete query
This works:
$allmailbox = Get-Mailbox -ResultSize 500
$result = Foreach ($Mailbox in $allmailbox){Get-MailboxFolderPermission –Identity ($mailbox.alias+':\calendar') | Where {$_.User -like "Anonymous" -and $_.AccessRights -ne "None" -or $_.User -like "Default" -and $_.AccessRights -ne "None" -or $_.User -like "Default" -and $_.AccessRights -ne "AvailabilityOnly"} | select Identity,User,AccessRights}
$result | Export-CSV C:\CSVs\calstest.csv -NoType

List users who have an empty description field in PowerShell

I'm trying to get a list of Active Directory users who have no description set.
I start with getting a list of users:
$users = Get-AdUser -Filter {(Enabled -eq "True" )} -Properties Description
And then I tried these options (to get list of users with no description):
$NoDescrUsers = $users | Where-Object {$_.Description -eq ""}
$NoDescrUsers = $users | Where-Object {$_.Description -eq ''}
$NoDescrUsers = $users | Where-Object $_.Description -eq ""
$NoDescrUsers = $users | Where-Object {$_.Description -match ""}
$NoDescrUsers = $users | Where-Object -not {$_.Description -like '*'}
None of these work (or it returns 0 in a foreach or returns everyone). What should my command look like?
I'm not sure why none of the options you tried worked (it seems like they should). Having Googled the general consensus seems to be that you can do this successfully (and more efficiently) within the initial -filter. For example:
$NoDescrUsers = Get-AdUser -Filter {(Enabled -eq "True" ) -and (description -notlike '*')} -Properties Description
If you filter description -like or -notlike
'*'
) that means you'll take any character (or not).
If you want filter only empty description in your AD request, you could do:
$NoDescrUsers = Get-AdUser -Filter {(Enabled -eq "True" ) -Properties Description
if ($NoDescrUsers.Description -eq $null)
{write-host "no description"}

Filter a few computers before exporting from pipeline

I need to filter out 4 machines prior to exporting to a csv file. I have no clue how to filter them out. I tried the IF clause but this produced nothing. Please help.
$old = (Get-Date).AddDays(-90) # Modify the -90 to match your threshold
$oldComputers = Get-ADComputer -SearchBase "OU=Workstations,DC=Corporate,DC=Local" -SearchScope 2 -Filter { PasswordLastSet -le $old } -Properties *
$oldComputers
if ($_.name -notlike "1919DD" -or $_.name -notlike "1919SMAHESHWARE" -or $_.name -notlike "1919IETEST" -or $_.name -notlike "1920BPASCERITB") {
Export-Csv c:\temp\Over90DaysMachines.csv -NoTypeInformation -Force -Append
}
For one thing, to be able to use the current object variable ($_) you need a pipeline context. Simply putting an if statement after echoing a variable doesn't automagically feed the echoed value(s) into the if statement. You need to change this:
$oldComputers
if ($_.Name -notlike "1919DD" -or ...) {
Export-Csv c:\temp\Over90DaysMachines.csv -NoTypeInformation -Force -Append
}
into something like this:
$oldComputers | Where-Object {
$_.Name -notlike "1919DD" -or ...
} | Export-Csv c:\temp\Over90DaysMachines.csv -NoType -Force
However, even with that change your filter won't work correctly, because you connected the -notlike clauses via -or when you should have used -and. You obviously meant to process objects only if their name doesn't match any of the given values. But for your logical expression to evaluate to $false the name would have to match all of the reference value at the same time. Which clearly isn't possible, thus your expression always evaluates to $true.
Example:
Assume that you have a variable $v that should not be equal to either A, B, or C. Applying your logic, the expression would look somewhat like this in PowerShell:
($v -notlike 'A') -or ($v -notlike 'B') -or ($v -notlike 'C')
If $v takes for instance the value A that expression becomes
('A' -notlike 'A') -or ('A' -notlike 'B') -or ('A' -notlike 'C')
⇔ ($false) -or ($true) -or ($true)
⇔ $true
To check if a give value equals neither of the reference values you need to connect the clauses via -and:
('A' -notlike 'A') -and ('A' -notlike 'B') -and ('A' -notlike 'C')
⇔ ($false) -and ($true) -and ($true)
⇔ $false
$oldComputers | Where-Object {
$_.Name -notlike "1919DD" -and
$_.Name -notlike "1919SMAHESHWARE" -and
$_.Name -notlike "1919IETEST" -and
$_.Name -notlike "1920BPASCERITB"
} | Export-Csv c:\temp\Over90DaysMachines.csv -NoType -Force
Note BTW, that the -notlike operator behaves exactly like the -ne operator when the reference string doesn't contain wildcard characters. If you're not doing fuzzy matches anyway you could simplify your expression by checking if the given name is (not) found in an array of names instead of doing multiple checks for (in)equality:
$excludes = '1919DD', '1919SMAHESHWARE', '1919IETEST', '1920BPASCERITB'
$oldComputers | Where-Object {
$excludes -notcontains $_.Name
} | Export-Csv c:\temp\Over90DaysMachines.csv -NoType -Force
Another option would be a regular expression (non-)match:
$oldComputers | Where-Object {
$_.Name -notmatch '^1919DD|1919SMAHESHWARE|1919IETEST|1920BPASCERITB$'
} | Export-Csv c:\temp\Over90DaysMachines.csv -NoType -Force
I'm guessing the code in the OP is a fragment from a larger script. Presumably it is the body or part of the body of a ForEach-Object. (If not then $_ doesn't make sense in this context). However a ForEach-Object isn't necessary. You can filter out the unwanted computers as follows:
$old = (Get-Date).AddDays(-90) # Modify the -90 to match your threshold
$oldComputers = Get-ADComputer -SearchBase "OU=Workstations,DC=Corporate,DC=Local" -SearchScope 2 -Filter { PasswordLastSet -le $old } -Properties *
$oldComputers | Where-Object {
$_.name -notin "1919SMAHESHWARE","1919IETEST", "1920BPASCERITB"
} | Export-Csv c:\temp\Over90DaysMachines.csv -NoTypeInformation -Force -Append
This assumes that $oldComputers is an array of object where each object has a property name and the value of name is a string like "server1", "server2", etc. The script in the OP outputs $oldComputers so verify it looks like a set of objects, with a name property consisting of a string where the servers to be excluded are spelled exactly as listed in the OP.
Please try below code
$old = (Get-Date).AddDays(-90) # Modify the -90 to match your threshold
$oldComputers = Get-ADComputer -searchbase "OU=Workstations,DC=Corporate,DC=Local" -SearchScope 2 -Filter { PasswordLastSet -le $old } -Properties *
$oldComputers = $oldComputers | where {$_.name -notlike "1919DD"
` -or $_.name -notlike "1919SMAHESHWARE"
` -or $_.name -notlike "1919IETEST"
` -or $_.name -notlike "1920BPASCERITB"}
Export-Csv c:\temp\Over90DaysMachines.csv -NoTypeInformation -force -append

Simplify Powershell Where-Object

I have working Import-Csv statement that uses Where-Object
Import-Csv D:\Script\my.csv | Where-Object {$_.SourceIP -Like '10.251.22.11*' -Or $_.SourceIP -Like '10.251.22.*' -Or $_.DestinationIP -Like '10.251.22.11*' -Or $_.DestinationIP -Like '10.251.22.*'}
If I try to simplify the statement, it doesn't work
Import-Csv D:\Script\my.csv | Where-Object {($_.SourceIP -Like ('10.251.22.11*' -Or '10.251.22.*')) -Or ($_.DestinationIP -like ('10.251.22.11*' -Or '10.251.22.*'))}
Google is not helping :-(
Instead of -like, use -match in this case.
Import-Csv D:\Script\my.csv | Where-Object {$_.SourceIP -match '^10\.251\.22\.*' -or $_.DestinationIP -match '^10\.251\.22\.*'}
Also, 10.251.22.* will match 10.251.22.11*, so you can combine them.