evalute expression output into variable in PowerShell - powershell

I want to be able to build a Get-ADComputer command after building it from strings like so:
$FilterOperatingSystems = "*Windows 7*" -or OperatingSystem -like "*Windows 8*" -or OperatingSystem -like "*Windows 10*"
($FilterOperatingSystems is a parameter to the script, so it'll be future proofed when executed by a Task Scheduler)
$command='Get-ADComputer -properties OperatingSystem -Filter {(OperatingSystem -like '+$FilterOperatingSystems+' )} |'
$command+= 'Where-Object {$_.name -like "*-*"} | '
$command+= 'Where-Object {$_.name -NotLike "V7-*"} | '
$command+= 'Where-Object {$_.name -NotLike "*-NONE"} | '
$command+= 'Where-Object {$_.name -NotLike "*-ONCALL"} | '
$command+= 'Where-Object {$_.name -NotLike "*-BLACKBAUD"} | '
$command+= 'Where-Object {$|_.name -NotLike "SC-WIN7-1"} | '
$command+= 'Where-Object {$_.name -NotLike "UT-SWCLIENT-01"} | '
$command+= 'Select-Object -Expand Name'
Write-Host $command
$computer =iex $command
the $command comes out like this:
Get-ADComputer -properties OperatingSystem -Filter {(OperatingSystem -like "*Windows 7*" -or OperatingSystem -like "*Windows 8*" -or OperatingSystem
-like "*Windows 10*" )} |Where-Object {$_.name -like "*-*"} | Where-Object {$_.name -NotLike "V7-*"} | Where-Object {$_.name -NotLike "*-NONE"} | W
here-Object {$_.name -NotLike "*-ONCALL"} | Where-Object {$_.name -NotLike "*-BLACKBAUD"} | Where-Object {$|_.name -NotLike "SC-WIN7-1"} | Where-Obje
ct {$_.name -NotLike "UT-SWCLIENT-01"} | Select-Object -Expand Name
but I get an error:
$ : The term '$' 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.
So, is it possible to do something like that? And if so, what's the right approach?

I think you just have a typo:
$|_.name -NotLike "SC-WIN7-1"
Should that not be $_.name?

Related

Powershell Get-ADComputer filter for multiple operating systems

I am trying to filter/match the operating system from Get-ADComputer and only return computers that have Windows 7 and above:
$computer = Get-ADComputer -properties OperatingSystem | Where-Object {operatingsystem -match "*Windows 7*|*Windows 8*|*Windows 10*"} |
Where-Object {$_.name -like "*-*"} |
Where-Object {$_.name -NotLike "V7-*"} |
Where-Object {$_.name -NotLike "*-NONE"} |
Where-Object {$_.name -NotLike "*-ONCALL"} |
Where-Object {$_.name -NotLike "*-BLACKBAUD"} |
Where-Object {$_.name -NotLike "SC-WIN7-1"} |
Where-Object {$_.name -NotLike "UT-SWCLIENT-01"} |
Select-Object -Expand Name
but when I do that, the debugger asks for a -Filter parameter
I have also tried:
$computer = Get-ADComputer -properties OperatingSystem -filter {(operatingsystem -match "*Windows 7*|*Windows 8*|*Windows 10*")} |
but I get an error:
Get-ADComputer : Error parsing query: '(operatingsystem -match "*Windows 7*|*Windows 8*|*Windows 10*")' Error Message: 'Operator Not supported:
-match' at position: '18'.
So what's the correct/best way to do this?
When you are doing advanced filtering using Where-Object you need to refer to iterator object. Also in your first code example, include -Filter * to get a complete list of all machines. I.e. try running
$computer = Get-ADComputer -properties OperatingSystem -Filter * `
| Where-Object {$_.operatingsystem -match "*Windows 7*|*Windows 8*|*Windows 10*"}
Alternatively you can do simple filtering and exclude the $_ operator like this
Get-Process | where name -like svchost
However, the -match operator does not seem to support this way of filtering.
You can also filtering the returned result when doing the query for all AD computers, like this
Get-ADComputer -Properties OperatingSystem `
-Filter {OperatingSystem -like "*Windows 7*" -or OperatingSystem -like "*Windows 8*"}
See this blog post on what is allowed when doing advanced filtering against Active Directory.
In my opinion, it's worth trying to do as much filtering as possible at the "server" end of the query and only return what you really need. The benefit is that all further processing at your end will be faster since there's less data to process.
You are trying to use multiple filters condition with your Get-AdComputer cmdlet. Instead of using the -match parameter, I would suggest to use -like parameter. I am not sure if Get-AdComputer supports the -match parameter. You can do something like below -
$computer = Get-ADComputer -properties OperatingSystem -filter 'operatingsystem -like "*Windows 7*" -or operatingsystem -like "*Windows 8*" -or operatingsystem -like "*Windows 10*"' |
If you see Get-Help Get-ADComputer -Examples, you can see how the -filter parameter is used.

PowerShell: How to apply multiple filters via where-object cmdlet?

Is there a better way to filter for objects via where-object then to send the data through multiple pipelines?
$clients = Get-ADComputer
-SearchBase "OU=Clients,DC=contoso,DC=com"
-Filter *
-Properties Description,OperatingSystem
$clients | Where OperatingSystem -notlike "*Windows 7*"
| Where OperatingSystem -notlike "*Windows 10*"
Ideal would be a complex filtering mechanism like we can use for the -Filter Parameter. I would have expected to be able to use something like the following...
$Clients | Where {
(OperatingSystem -notlike "Windows 7") -and (OperatingSystem -notlike "Windows 10")
}
$clients | Where OperatingSystem -notlike "*Windows 7*" |
Where OperatingSystem -notlike "*Windows 10*"
Strictly speaking, this should work.
However, the problem you're running in to is that the simplified Where-Object syntax shown above only works in the most simple cases. When you use the full syntax, you must specify the properties using the $_ variable:
$clients | Where-Object {
($_.OperatingSystem -notlike '*Windows 7*') -and ($_.OperatingSystem -notlike '*Windows 10*')
}
However, since you're using Get-ADComputer, you really should be using the -Filter property on that command. It will be much faster, and will be less work for your domain controller, too:
Get-ADComputer -SearchBase "OU=Clients,DC=contoso,DC=com" `
-Filter "(OperatingSystem -notlike '*Windows 7*') -and (OperatingSystem -notlike '*Windows 10*')" `
-Properties Description,OperatingSystem
It is more efficient to filter directly in the query rather than filtering after-the-fact using Where-Object (which retrieves all objects first). Example using the -LDAPFilter parameter:
Get-ADComputer -LDAPFilter "(&(!operatingSystem=Windows 7*)(!operatingSystem=Windows 10*))" -Properties operatingSystem,description
Something like this perhaps?
$DesktopClients=#('Windows 7','Windows 10')
$Clients=$Clients -notmatch ($DesktopClients -join '|')

Powershell Write-Eventlog Linebreak

I'm making a script which searches all Computer with specific Operating systems, run them through a Whitelist and, if there are Computer that are not on the Whitelist, I write an errorlog. The log looks like this right now:
#{Name=Computername1; Operatingsystem=Windows 10 Enterprise; DistinguishedName=CN=la,OU=computers,OU=lu,OU=Hosting,DC=a,DC=b,DC=ch; OperatingSystemVersion=10.0 (10586)}
But it should look like this:
Name=Computername1
Operatingsystem=Windows 10 Enterprise
DistinguishedName=CN=la,OU=computers,OU=lu,OU=Hosting,DC=a,DC=b,DC=ch
OperatingSystemVersion=10.0 (10586)
I want to delete the #{} and the 4 informations should be separated by line breaks.
My code:
$username = $env:UserName
$getad = Get-ADComputer -Filter {(operatingsystem -like "*Windows 10*" -and OperatingSystemVersion -notlike "*16299*" -and OperatingSystemVersion -notlike "*14393*" -and OperatingSystemVersion -notlike "*14279*" -and OperatingSystemVersion -notlike "*15063*" -and OperatingSystemVersion -notlike "*10159*" -and OperatingSystemVersion -notlike "*16193*" -and OperatingSystemVersion -notlike "*17025*" -and OperatingSystemVersion -notlike "*10074*" -and OperatingSystem -notlike "*LTSB") -or (operatingsystem -like "*Windows Vista*") -or (operatingsystem -like "*Windows XP*") -or (operatingsystem -like "*95*") -or (operatingsystem -like "*94*") -or ( operatingsystem -like "*Windows 8*" -and OperatingSystemVersion -notlike "*9600*" -and OperatingSystem -notlike "*LTSB") -or (operatingsystem -like "*2000 Professional*") -or (operatingsystem -like "*2000 Server*") -or (operatingsystem -like "*2003*") -or (operatingsystem -like "*Windows NT*") -or (operatingsystem -like "*Windows 7*" -and OperatingSystemVersion -notlike "*7601*" -and OperatingSystem -notlike "*LTSB")} -Properties ('Name', 'operatingsystem', 'DistinguishedName', 'OperatingsystemVersion') | ? {$_.distinguishedname -notlike "*OU=Oldwin10-Test,OU=a,OU=b,OU=c,OU=d,DC=e,DC=f,DC=ch"}
$whitelisted = Get-Content "C:\Users\$username\Desktop\whitelistedpcs.txt"
$getad | Select-Object Name, Operatingsystem, DistinguishedName,
OperatingSystemVersion | ForEach-Object {
if ($whitelisted -match $_.DistinguishedName) {
}
else{
Write-EventLog -LogName Application -Source "OldWinalert" -EntryType Error -EventId 1 -Message "$_"
}
}
You need to convert the output to string before sending it to the -Message parameter using Out-String will do:
for your case I would try this:
[...] -EntryType Error -EventId 1 -Message ($_ | Format-List | Out-String)
Another option:
else{
$Message = #"
Name: $($_.name)
Operating System: $($_.Operatingsystem)
Distinguished Name: $($_.DistinguishedName)
Operating System Version: $($_.OperatingSystemVersion)
"#
Write-EventLog -LogName Application -Source "OldWinalert" -EntryType Error -EventId 1 -Message $Message
}
and if you want extra line space add `n (for new line) on each line end after the brackets

Get all EoL Windows Computer in AD With Powershell

I have to create a script to get all EoL Windows computers in our AD.
This is my Code right now:
$getad = Get-ADComputer -Filter {
OperatingSystem -like "Windows 10*"
-or
OperatingSystem -like "*Windows Vista*"
-or
OperatingSystem -like "*Windows XP*"
-or
OperatingSystem -like "*95*"
-or
OperatingSystem -like "*94*"
-or
OperatingSystem -like "*Windows 8*"
-or
OperatingSystem -like "*Windows 8.1*"
-or
OperatingSystem -like "*2000 Professional*"
-or
OperatingSystem -like "*2000 Server*"
-or
OperatingSystem -like "*2003*"
-or
OperatingSystem -like "*Windows NT*"
-or
OperatingSystem -like "*Windows 7*"
-and
#Windows8
OperatingSystemVersion -notlike "*6.3.9600*"
-and
#Windows7 SP1
OperatingSystemVersion -notlike "*6.1.7601*"
-and
#Windows10
OperatingSystemVersion -notlike "*16299*"
-and
#Windows10
OperatingSystemVersion -notlike "*14393*"
-and
#Windows10
OperatingSystemVersion -notlike "*15063*"
} -Properties ('Name', 'operatingsystem', 'DistinguishedName',
'description', 'lastlogondate', 'OperatingsystemVersion')
$selectobj = $getad | Select-Object Name, Operatingsystem,
DistinguishedName, Description, Lastlogondate, OperatingSystemVersion
$selectobj
The problem: The part with -notlike is not applied. I get computers with the versions I do not want to see.
I need all EoL Computers in one variable so i can work with them.
The problem is one of logic with your combination of or and and, but don't use -like and -notlike they don't work the way you think. Use the regular expression switches -imatch and -inotmatch like this:
OperatingSystem -imatch "Windows 10|Windows Vista|Windows XP|95|94|Windows 8|2000|2003|Windows NT|Windows 7"
-and OperatingSystemVersion -inotmatch "6.3.9600|6.1.7601|16299|14393"
I added ( and ) and now it works.
$getad = Get-ADComputer -Filter {(operatingsystem -like "*Windows 10*" -and OperatingSystemVersion -notlike "*16299*" -and OperatingSystemVersion -notlike "*14393*" -and OperatingSystemVersion -notlike "*15063*") -or (operatingsystem -like "*Windows Vista*") -or (operatingsystem -like "*Windows XP*") -or (operatingsystem -like "*95*") -or (operatingsystem -like "*94*") -or ( operatingsystem -like "*Windows 8*" -and OperatingSystemVersion -notlike "*9600*") -or (operatingsystem -like "*2000 Professional*") -or (operatingsystem -like "*2000 Server*") -or (operatingsystem -like "*2003*") -or (operatingsystem -like "*Windows NT*") -or ( operatingsystem -like "*Windows 7*" -and OperatingSystemVersion -notlike "*7601*")} -Properties ('Name', 'operatingsystem', 'DistinguishedName', 'description', 'lastlogondate', 'OperatingsystemVersion', 'Created', 'Enabled', 'SamAccountName')
$selectobj = $getad | Select-Object Name, Operatingsystem, DistinguishedName, Description, Lastlogondate, OperatingSystemVersion, Created, Enabled, SamAccountName
It works but it isn't nice at all because of its lenght.
Is there any other shorter way?

How can I exclude particular names from Get-ADComputer results?

I want to get all computers in my domain that are enabled, and have 2003 operating system, and the name of the computers do Not contain ' ping , pict , pire '
Here is what I have, but totally failing:
Get-ADComputer -filter {(Enabled -eq $True) -and (OperatingSystem -like "*2003*")} -properties OperatingSystem | where {($_.Name -notlike 'PING*') -or ($_.Name -notlike 'PICT*') -or ($_.Name -notlike 'PIRE*')} | Select Name
You can use the -notlike operator inside the filter, so there is no need for the where statement. See the Get-ADComputer reference on technet.
As well as changing your -or operators to -and as I mentioned, I put all conditions into the filter ending up with this:
Get-ADComputer -filter {
Enabled -eq $True -and
OperatingSystem -like '*2003*' -and
Name -notlike 'PING*' -and
Name -notlike 'PICT*' -and
Name -notlike 'PIRE*'
} | Select Name