I'm setting up a RADIUS server and all works fine except for laptops with a certain Wireless NIC.
I managed to solve the problem, but I wish to have a list of all my AD Domain joined computers with the faulty/outdated NIC (all of our laptops are in several different OU's).
I was thinking something of combining the GET-ADcomputer -filter * (to list all computer objects) and combine this with the get-wmiobject win32_networkadapter | select netconnectionid, name | where name -eq "Intel(R) Dual Band Wireless-AC 8265"
The PS cmdlets work separately, but I want to match the get-wmiobject for each match triggered by the get-adcomputerCan you help me out ? :)
This is how you can approach your script. I do agree with Abraham's comment, if you can, use Get-CimInstance:
Get-CimInstance win32_networkadapter | Where-Object Name -EQ $match
$computers = Get-ADComputer -Filter *
$match = 'Intel(R) Dual Band Wireless-AC 8265'
$result = foreach($computer in $computers)
{
$wmi = Get-WmiObject win32_networkadapter | Where-Object Name -EQ $match
if(-not $wmi){ continue }
[pscustomobject]#{
ComputerName = $computer.Name
NetconnectionID = $wmi.NetConnectionID
Name = $wmi.Name
}
}
$result | Export-Csv 'path/to/csv.csv' -NoTypeInformation
Edit
I haven't tested this nor I have a way of testing it right now, but if this works should be a lot faster, using query language:
$computers = (Get-ADComputer -Filter *).sAMAccountName
$match = 'Intel(R) Dual Band Wireless-AC 8265'
$filter = #{
ComputerName = $computers
Query = "SELECT NetConnectionID, Name FROM win32_networkadapter WHERE Name = '$match'"
}
Get-WmiObject #filter
Related
I have issues with this PowerShell script, if i execute the line without the foreach works great but with him don't show up nothing, can someone tell me why?
The foreach works fantastic by himselft he read all the data from the CSV but for some reason don't work, the CSV contain PC names like PC1, Pc-RRHH, JosePc from my network, like i say without the foreach is fine.
$computers = Import-Csv “C:\PowerShell\Pc.csv”
$array = #()
foreach($pc in $computers)
{
Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Product -Computer $pc.computername
Select-Object Name, Version, PSComputerName
Where-Object -FilterScript {$_.Name -like “Adobe*”}
}
Best regards
Assuming your CSV file indeed has a header with column 'computername' in it, you can change your code to:
$computers = Import-Csv "C:\PowerShell\Pc.csv"
# let PowerShell collect the data for you in an array
$array = foreach($pc in $computers) {
# because NameSpace 'root/CIMV2' is the default, you do not have to specify that
Get-CimInstance -ClassName Win32_Product -ComputerName $pc.computername |
# or use the old Get-WmiObject
# Get-WmiObject -Class Win32_Product -Computer $pc.computername |
Where-Object { $_.Name -like "Adobe*" } |
Select-Object Name, Version, PSComputerName
}
Instead of piping to a Where-Object {..} clause, you can also use the -Filter parameter.
Beware though that this filter requires WQL syntax, which is different from PowerShell syntax.
$computers = Import-Csv "C:\PowerShell\Pc.csv"
# let PowerShell collect the data for you in an array
$array = foreach($pc in $computers) {
# because NameSpace 'root/CIMV2' is the default, you do not have to specify that
Get-CimInstance -ClassName Win32_Product -ComputerName $pc.computername -Filter "Name like 'Adobe%'" |
Select-Object Name, Version, PSComputerName
}
Or use the -Query parameter:
$computers = Import-Csv "C:\PowerShell\Pc.csv"
# the query string to filter on. Also WQL syntax
$query = "Select * from Win32_Product where Name LIKE 'Adobe%'"
# let PowerShell collect the data for you in an array
$array = foreach($pc in $computers) {
Get-CimInstance Get-CimInstance -Query $query -ComputerName $pc.computername |
Select-Object Name, Version, PSComputerName
}
From your comment, I gather that your CSV file isn't a CSV at all, but just a text file with pc names each on a separate line and that there is not header 'computername'.
In that case, change $computers = Import-Csv "C:\PowerShell\Pc.csv" to $computers = Get-Content -Path "C:\PowerShell\Pc.csv" and in the loop use -ComputerName $pc instead if -ComputerName $pc.computername
The majority of this code was pulled from a blog online, but I think it's exactly the way I need to be tackling this. I want to get the top 4 machines from an OU based on uptime, and run a script that lives on each of the top 4 machines. I know that the problem involves the Array losing access to the Get-ADComputer properties, but I'm unsure of how to pass these new properties back to their original objects. This works as expected until it gets to the foreach loop at the end.
$scriptBlock={
$wmi = Get-WmiObject -Class Win32_OperatingSystem
($wmi.ConvertToDateTime($wmi.LocalDateTime) – $wmi.ConvertToDateTime($wmi.LastBootUpTime)).TotalHours
}
$UpTime = #()
Get-ADComputer -Filter 'ObjectClass -eq "Computer"' -SearchBase "OU=***,OU=***,OU=***,DC=***,DC=***" -SearchScope Subtree `
| ForEach-Object { $Uptime += `
(New-Object psobject -Property #{
"ComputerName" = $_.DNSHostName
"UpTimeHours" = (Invoke-Command -ComputerName $_.DNSHostName -ScriptBlock $scriptBlock)
}
)
}
$UpTime | Where-Object {$_.UpTimeHours -ne ""} | sort-object -property #{Expression="UpTimeHours";Descending=$true} | `
Select-Object -Property ComputerName,#{Name="UpTimeHours"; Expression = {$_.UpTimeHours.ToString("#.##")}} | Select-Object -First 4 |`
Format-Table -AutoSize -OutVariable $Top4.ToString()
foreach ($Server in $Top4.ComputerName) {
Invoke-Command -ComputerName $Server -ScriptBlock {HOSTNAME.EXE}
}
I'm not married to Invoke-Command in the last foreach but am having the same issues when I try to use psexec. Also, I'm running hostname.exe as a check to make sure I'm looping through the correct machines before I point it at my script.
Here's a streamlined version of your code, which heeds the comments on the question:
# Get all computers of interest.
$computers = Get-ADComputer -Filter 'ObjectClass -eq "Computer"' -SearchBase "OU=***,OU=***,OU=***,DC=***,DC=***" -SearchScope Subtree
# Get the computers' up-times in hours.
# The result will be [double] instances, but they're also decorated
# with .PSComputerName properties to identify the computer of origin.
$upTimes = Invoke-Command -ComputerName $computers.ConputerName {
((Get-Date) - (Get-CimInstance -Class Win32_OperatingSystem).LastBootUpTime).TotalHours
}
# Get the top 4 computers by up-time.
$top4 = $upTimes | Sort-Object -Descending | Select-Object -First 4
# Invoke a command on all these 4 computers in parallel.
Invoke-Command -ComputerName $top4.PSComputerName -ScriptBlock { HOSTNAME.EXE }
#Listing machine from which we will Query
$Machines = Get-ADComputer -Filter * -SearchBase 'OU=Laptops,OU=Win10Modern,OU=LN,OU=Workstations,DC=cooley,DC=com' | Select-Object Name
#Getting the Network Adapter version for Wi-Fi Adapter
ForEach ($Machine in $Machines) {
Get-NetAdapter | Select-Object Name,InterfaceDescription,DriverVersion,DriverDate,DriverProvider
}
Currently, your code loops over objects in variable $Machines, where each object has a single property called Name.
In order to get just the name values, either use Select-Object -ExpandProperty Name or get the array of names like this:
# get an array of computernames
$Machines = (Get-ADComputer -Filter * -SearchBase 'OU=Laptops,OU=Win10Modern,OU=LN,OU=Workstations,DC=cooley,DC=com').Name
Next loop over these computernames and have each computer run the Get-NetAdapter cmdlet:
# capture the output(s) in variable $result
$result = foreach ($Machine in $Machines) {
if (Test-Connection -ComputerName $Machine -Count 1 -Quiet) {
Invoke-Command -ComputerName $Machine -ScriptBlock {
Get-NetAdapter | Select-Object SystemName,Name,InterfaceDescription,
DriverVersion,DriverDate,DriverProvider,Status,AdminStatus
}
}
else {
Write-Warning "Computer '$Machine' does not respond"
}
}
# output on screen
$result
# or to GridView
$result | Out-GridView -Title 'NetAdapterInfo'
# or to CSV file
$result | Export-Csv -Path 'X:\NetAdapterInfo.csv' -NoTypeInformation
AdminStatus is a setting (enabled --> 'up'; disabled --> 'down')
Status is operational status (connected --> 'up'; disconnected --> 'down')
I don't think you can use Get-NetAdapter to connect to remote computers.
You can however use Get-WmiObject Win32_NetworkAdapter -ComputerName .
Like this:
ForEach ($Machine in $Machines) {
Get-WmiObject -Class Win32_NetworkAdapter -Filter "NetConnectionStatus = 2" -ComputerName $Machine
}
You need to become familiar with the properties of the Win32_NetworkAdapter class. You can see all of the properties by running this command:
Get-WmiObject -Class Win32_NetworkAdapter -ComputerName "Localhost" | fl * -Force
or you can use this command to see all of the properties (and methods) available to you.
Get-WmiObject -Class Win32_NetworkAdapter -ComputerName "Localhost" | Get-Member
Most computers will have more than 1 network card (some are hidden) and you have to filter the irrelevant ones out.
I am missing something fundamental in PowerShell.
I have a script that generates two collections, computer names with version details of a specific application and a separate user name list that is taken from the computer names list because the user names are in the computer names, for example a computer name is:
XXXXXX02jbloggs
The owner of this computer is jbloggs and jbloggs is a valid AD object which has a full name of joe blogs.
The ultimate objective of the script is to produce a report with computer names, owner SamAccountName, full name and application details, which the script will specifically check for.
For example,
what version(s) of Adobe Reader exist on this range of machines
So far I have:
$ErrorActionPreference = "SilentlyContinue"
$Computers = Get-ADComputer -Server BlahBlah.com -Filter {name -like "XXXXXX02*"} |
Select-Object -ExpandProperty Name
$Users = $Computers -Replace '\D*\d*(\w*)', '$1'
$Results = foreach ($Computer in $Computers) {
Get-CimInstance -ComputerName $Computer -ClassName Win32_Product |
Where-Object{$_.Name -like "*Adobe Reader*"} |
Select-Object PSComputerName, Name, Version, InstallDate
}
$FullNames = ForEach ($user in $Users) {
Get-ADUser -Server BlahBlah.com -Identity $User -Properties * |
Select-Object -ExpandProperty Name
}
$Results gets me a list of computer names, Adobe Reader xxx, the version and install date.
$FullNames gets me a list of the full names based on their user IDs
I do not know how to construct the script so it produces Full Name, User Name, Computer Name, Application Name and Install Date.
This is why I say I am missing something fundamental in PowerShell, I have been looking at custom objects, nested loops and other ideas but to no avail. Really looking for some advice on this type of problem as I several similar examples I need to accomplish.
Any advice would be greatly appreciated.
Get the single current user inside the foreach($computer in $Computers) instead of creating two separate foreach.
Add a calculated property to the select to include FullName in
$Result
$ErrorActionPreference = "SilentlyContinue"
$Computers = Get-ADComputer -Server BlahBlah.com -Filter {name -like "XXXXXX02*"} |
Select-Object -ExpandProperty Name
$Results = foreach ($Computer in $Computers) {
$User = $Computer -Replace '\D*\d*(\w*)', '$1'
$FullName = (Get-ADUser -Server BlahBlah.com -Identity $User -Properties *).Name
Get-CimInstance -ComputerName $Computer -ClassName Win32_Product |
Where-Object{$_.Name -like "*Adobe Reader*"} |
Select-Object PSComputerName, Name, Version, InstallDate,#{n='FullName';e=#{$FullName}}
}
I want to write a PowerShell script to get all the print servers in a network.
I have used the following LDAP query, but it returns only servers with network printers attached to it. But not other print servers that have a remote printer attached to it.
Here's the code I used to get the print servers (But getting only the servers with n/w printers)
Import-Module ActiveDirectory
[array]$testarray = Get-ADObject -LDAPFilter "(&(&(&(uncName=*)(objectCategory=printQueue))))" -properties *|Sort-Object -Unique -Property servername |select servername
$testarray
You could try something like Get-WMIObject win32_printer | select name,local wrapped in a foreach-object loop like this:
$servers | ForEach-Object {
Get-WMIObject Win32_Printer -computername $_ | Where-Object {$_.local -like 'False'} | select Name,local,SystemName | format-table -a
}
The $servers can be what scoped to whatever servers you need to check.
Use Get-WMIObject Win32_Printer | select * to see what properties you want to report back on and include them in the | select Name,local,SystemName section of the script
You could use a combination of Get-ADComputer and Get-Printer to list all shared printer queues on computers joined to your domain:
Get-ADComputer -Filter * | % {
$computer = $_.Name
Get-Printer -Computer $computer | ? { $_.Shared } | select -Expand Name
}
This doesn't cover computers that aren't domain members, though.