I am using Invoke-WMIMethod to identify all SIDS beginning with S-1-5-21, like so (thanks to Mathias R. Jessen):
$Keys = Invoke-WmiMethod -Path $ClassPath -Name EnumKey -ArgumentList 2147483651,''
| Select-Object -ExpandProperty sNames | Where-Object {$_ -match 'S-1-5-21-[\d\-]+$'}
I want to convert these SIDs from the remote system to usernames on the remote system using WMI. Is this possible through WMI or Invoke-WmiMethod?
You can use the Win32_SID class to obtain the account name:
foreach($Key in $Keys)
{
$SID = [wmi]"\\$RemoteComputer\root\cimv2:Win32_SID.SID=$Key"
New-Object psobject -Property #{
SID = $Key
Username = $SID.ReferencedDomainName,$SID.AccountName -join '\'
}
}
Rather than grabbing from the registry you could get the same information from the Win32_UserProfile provider. Then if folder name is good enough, consider something like this:
$Computer = "ExampleComputer"
Get-WMIObject Win32_UserProfile -Filter "SID like 'S-1-5-21-*'" -ComputerName $Computer |
select SID,#{name=LocalPath;Expression={Split-Path -leaf $_.LocalPath}}
Otherwise Win32_UserAccount exists but can be really slow with a large domain.
$Computer = "ExampleComputer"
$SIDs = Get-WMIObject Win32_UserProfile -Filter "SID like 'S-1-5-21-*'" -ComputerName $Computer | select -ExpandProperty SID
$UserAccounts = Get-WMIObject Win32_UserAccount -ComputerName $Computer
foreach ($SID in $SIDs) {
foreach ($Account in $UserAccounts) {
If ($SID -eq $Account.SID) {
$Account
}
}
}
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
I am trying to collect different properties from all computer listed from my AD but I can't get format to recolected querys
I run get-adcomputer query
$computerList = Get-ADComputer -Filter 'Name -like "SCPW*" -and ObjectClass -eq "Computer"' | Select-Object -Property Name,objectClass`
I collect info from al computer listed in $computerlist
$list = foreach ($computer in $computerList) {Get-WmiObject -Class Win32_Product | Select-Object -Property Name }
$WFeature = foreach ($computer in $computerList) {Get-windowsfeature | Where {$_.installed -Eq $true} | Select-Object -Property Name}
$Wrole = foreach ($computer in $computerList) {Get-WmiObject -Class Win32_ServerFeature -Property * | select pscomputername,name }
Finally I try to list all info collected in a unique table with
%{[PSCustomObject]#{
'ComputerName' = $computer.Name
'features' = $WFeature.name
'Role' = $Wrole.name
'list' = $list.name
} } | Format-table
but the table listed is only in one line
ComputerName features Role list
------------ -------- ---- ----
SCPWEXC0101 {File-Services, FS-FileServer, Remote-Desktop-Services, RDS-RD-Server...} {Web Server (IIS), File Services, Print and Document Services, Remote Desktop Services...} {Microsoft Ap...
the table listed only in one line (screenshot)
I really will be much gratefull if somebody give me some help, I'm learning PS and I really lossed with this query. I've been running Ps 5.1
Thanks!!
You will have to put the queries inside a loop for each single computer to keep the correlation between the collected information and the computer name. Something like this should get you started:
$computerList = Get-ADComputer -Filter 'Name -like "SCPW*" -and ObjectClass -eq "Computer"'
$Result =
foreach ($computer in $computerList) {
$CimSession = New-CimSession -ComputerName $computer.name
[PSCustomObject]#{
ComputerName = $computer.Name
WindowsFeatureList = (Get-windowsfeature -ComputerName $computer.name | Where-Object { $_.installed } | Select-Object -Property Name) -join ', '
W32ServerFeatureList = (Get-CimInstance -CimSession $CimSession -ClassName Win32_ServerFeature | Select-Object -Property Name) -join ', '
W32ProductList = (Get-CimInstance -CimSession $CimSession -ClassName Win32_Product | Select-Object -Property Name) -join ', '
}
}
$Result
#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'm trying to get the hostname and the MAC address from all PCs in the Active Directory. I know that MAC addresses are not in the Activce Directory. That's why I already used a small script from someone else. The point is that I have to make a list of hostnames, which I can do, but then the other script runs into a problem because some computers are not online.
Can anyone help me get a list with only the pc's that are online?
This is the part that searches the list I create with hostnames.
$Computers = Import-CSV C:\Users\admin_stagiair\Desktop\Computers.txt
$result = #()
foreach ($c in $Computers){
$nic = Invoke-Command {
Get-WmiObject Win32_NetworkAdapterConfiguration -Filter 'ipenabled = "true"'
} -ComputerName $c.Name
$x = New-Object System.Object | select ComputerName, MAC
$x.Computername = $c.Name
$x.Mac = $Nic.MACAddress
$result += $x
}
$result | Export-Csv C:\Users\admin_stagiair\Desktop\Computers.csv -Delimiter ";" -NoTypeInformation
And this is the part that I tried to make search the list and filter out the online computers, which absolutely does not work and I can't figure out how to do it.
$Computers = Import-Csv C:\Users\admin_stagiair\Desktop\Computers.txt
foreach ($c in $Computers) {
$ping = Test-Connection -Quiet -Count 1
if ($ping) {
$c >> (Import-Csv -Delimiter "C:\Users\admin_stagiair\Desktop\online.txt")
} else {
"Offline"
}
}
Last bit, this is the part I use to create a list of all computers in the Active Directory.
Get-ADComputer -Filter {enabled -eq $true} -Properties * |
select Name > C:\Users\(user)\Desktop\Computers.txt
If you only want one property from Get-ADComputer don't fetch all
a computer could have more than one MAC, to avoid an array be returned join them.
$result += inefficiently rebuilds the array each time, use a PSCustomObject instead.
Try this (untested):
EDIT: first test connection, get MAC only when online
## Q:\Test\2018\09\18\SO_52381514.ps1
$Computers = (Get-ADComputer -Filter {enabled -eq $true} -Property Name).Name
$result = ForEach ($Computer in $Computers){
If (Test-Connection -Quiet -Count 1 -Computer $Computer){
[PSCustomPbject]#{
ComputerName = $Computer
MAC = (Invoke-Command {
(Get-WmiObject Win32_NetworkAdapterConfiguration -Filter 'ipenabled = "true"').MACAddress -Join ', '
} -ComputerName $Computer)
Online = $True
DateTime = [DateTime]::Now
}
} Else {
[PSCustomPbject]#{
ComputerName = $Computer
MAC = ''
Online = $False
DateTime = [DateTime]::Now
}
}
}
$result | Export-Csv C:\Users\admin_stagiair\Desktop\Computers.csv -Delimiter ";" -NoTypeInformation
What about trying something like this:
# Get all computers in list that are online
$Computers = Import-Csv C:\Users\admin_stagiair\Desktop\Computers.txt |
Select-Object -ExpandProperty Name |
Where-Object {Test-Connection -ComputerName $_ -Count 1 -Quiet}
# Grab the ComputerName and MACAddress
$result = Get-WmiObject -ComputerName $computers -Class Win32_NetworkAdapterConfiguration -Filter 'ipenabled = "true"' |
Select-Object -Property PSComputerName, MacAddress
$result | Export-Csv C:\Users\admin_stagiair\Desktop\Computers.csv -Delimiter ";" -NoTypeInformation
I am putting together a script that will check all of my web servers certificates so that I can monitor when they are set to expire. When the script goes to execute the Invoke-Command I am getting this error:
Here is my code:
Import-Module WebAdministration
$results = #()
$ou = 'OU=test,OU=test,OU=Servers,DC=contoso,DC=com'
$subtree = Get-ADOrganizationalUnit -SearchBase $ou -SearchScope Subtree -filter * | Select-Object -ExpandProperty DistinguishedName
ForEach($dn in $subtree){
$servers = Get-ADComputer -Filter * -SearchBase $dn | select Name
$results += $servers
}#ForEach($dn in $subtree)
$scriptBlock = [scriptblock]::Create({
Import-Module WebAdministration; Get-ChildItem -Path IIS:SSLBindings | ForEach-Object -Process `
{
If($_.Sites){
$certificate = Get-ChildItem -Path CERT:LocalMachine/My |
Where-Object -Property Thumbprint -EQ -Value $_.Thumbprint
[PSCustomObject]#{
Sites = $_.Sites.Value
CertificateDNSNameList = $certificate.DnsNameList
CertificateNotAfter = $certificate.NotAfter
}#[PSCustomObject]
}#If($_.Sites)
}#Import-Module
})#ScriptBlock
ForEach($server in $results){
Invoke-Command -ComputerName $server -ScriptBlock $scriptBlock | Select Sites,CertificateDNSNameList,CertificateNotAfter,PSComputerName #ScriptBlock
}#ForEach($server in $results)
Now, If I take the following line out of the loop and replace $server with an actual server name, I get the results I am looking for:
Invoke-Command -ComputerName ServerName -ScriptBlock $scriptBlock | Select Sites,CertificateDNSNameList,CertificateNotAfter,PSComputerName
Any ideas what I am doing wrong?
Your Results-Array is not an array of string, it is an array of object. Each object have the attribute name. Change your last ForEach-Loop into this and your script will work:
ForEach($server in $results){
Invoke-Command -ComputerName $server.name -ScriptBlock $scriptBlock | Select Sites,CertificateDNSNameList,CertificateNotAfter,PSComputerName #ScriptBlock
}#ForEach($server in $results)
It looks to me like "select Name" is returning an object rather than a string. Try changing the line that fetches the servers to this:
$servers = Get-ADComputer -Filter * -SearchBase $dn | select -ExpandProperty Name