Trying to capture IP from powershell script, getting System.String[] instead - powershell

I'm trying to pull a machine's IPAddress, MACAddress, and DefaultIPGateway information from the Win32_NetworkAdapterConfiguration object into an exported CSV file named NetworkAdapterConfiguration.csv using this script:
$StrComputer = $env:computername
$NetAdConfig = gwmi Win32_NetworkAdapterConfiguration -Comp $StrComputer
$NetAdConfig | Select-Object IPAddress,MACAddress,DefaultIPGateway | Export-Csv -Path C:\CSVFolder\NetworkAdapterConfiguration.csv -Encoding ascii -NoTypeInformation
When I view this CSV I get "System.String[]" where the IP and DefaultIPGateway values should be displayed. I'm assuming this information gets represented as an array and that is why I'm seeing the System.String[] view, but I have little experience with Powershell. Any help, advice, and references are much appreciated.

The IPAddress and DefaultIPGateway properties are arrays. If you are sure your machines only have one IP address and default gateway, you can do this:
$computer = $ENV:COMPUTERNAME
get-wmiobject Win32_NetworkAdapterConfiguration -filter "IPEnabled=TRUE" -computername $computer | foreach-object {
new-object PSObject -property #{
"Computer" = $computer
"MACAddress" = $_.MACAddress
"IPAddress" = $_.IPAddress[0]
"DefaultIPGateway" = $_.DefaultIPGateway[0]
} | select-object Computer,MACAddress,IPAddress,DefaultIPGateway
}
Here's another way that uses Select-Object:
$computer = $ENV:COMPUTERNAME
get-wmiobject Win32_NetworkAdapterConfiguration -filter "IPEnabled=TRUE" -computername $computer | foreach-object {
$_ | select-object `
#{Name="ComputerName"; Expression={$_.__SERVER}},
#{Name="MACAddress"; Expression={$_.MACAddress}},
#{Name="IPAddress"; Expression={$_.IPAddress[0]}},
#{Name="DefaultIPGateway"; Expression={$_.DefaultIPGateway[0]}}
}

I have a function that I wrote called Convert-OutputForCSV that can help to remove the string[] issues you are seeing as well. You could do something like this to expand out the arrays into a more readable property.
$StrComputer = $env:computername
$NetAdConfig = gwmi Win32_NetworkAdapterConfiguration -Comp $StrComputer
$NetAdConfig | Select-Object IPAddress,MACAddress,DefaultIPGateway |
Convert-OutputForCSV |
Export-Csv -Path C:\CSVFolder\NetworkAdapterConfiguration.csv -Encoding ascii -NoTypeInformation

Related

foreach powershell i'm totally blind

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

Query the NetAdapter on Multiple Machines

#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.

Converting from bytes into gigabytes

I am using following script to get disk space audit in our enterprise environment.
Everything works fine except that I don't know how to get those values presented in GB/MB.
Any idea?
$Computers = Get-Content -Path D:\DISKSPACE_audit\Servers.txt
Get-WmiObject Win32_LogicalDisk -ComputerName $Computers | Where-Object {
$_.DriveType -eq 3
} | Select-Object SystemName,DeviceID,FreeSpace,Size
Divide the value by 1GB (or 1MB):
$Computers = Get-Content "D:\DISKSPACE_audit\Servers.txt"
Get-WmiObject Win32_LogicalDisk -Computer $Computers -Filter 'DriveType = 3' |
Select-Object SystemName, DeviceID,
#{n='FreeSpace';e={[int]($_.FreeSpace/1GB)}},
#{n='Size';e={[int]($_.Size/1GB)}}

PowerShell - Select-Object from Win32_OperatingSystem displays rather oddly

First time poster here, I'm a bit of a beginner and I've been keen to get my PowerShell scripting skills up to scratch and I'm come across something rather confusing...
I've made a script to query a collection of computers and I want to query Win32_OperatingSystem but only extrapolate the Build number so I can populate my PSObject with it. I'm trying to add some If logic so that if the build number is 7601, I can write a message under my OS column.
The problem I'm having is that the BuildNumber values are coming out as #{BuildNumber=7601} instead of 7601 for instance. That, and my If statement is borked.
$Machines = Get-Content .\Computers.txt
Foreach($Machine in $Machines)
{
$sweet = (Get-WmiObject -Class Win32_OperatingSystem -computer $Machine | Select-Object BuildNumber)
$dversion = if ($sweet -eq "#{BuildNumber=7601}") {Yes!} else {"Nooooo!"}
New-Object PSObject -Property #{
ComputerName = $Machine
Sweet = $sweet
OS = $dversion
}
}
The issue is that the Get-WMIObject cmdlet is returning a Hash Table. Then the Select-Object is returning just the BuildNumber section you want, the BuildNumber property and it's value. You need to add the -ExpandProperty parameter to only get the value back, not the name/value pair.
Get-WMIObject -Class Win32_OperatingSystem | Select-Object BuildNumber
Returns
#{BuildNumber=7601}
With ExpandProperty
Get-WMIObject -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber
Returns
7601
Just another option with a ping test to skip unavailable machines.
Get-Content .\Computers.txt | Where-Object {Test-Connection -ComputerName $_ -Count 1 -Quiet} | Foreach-Object {
$sweet = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $_ | Select-Object -ExpandProperty BuildNumber
New-Object PSObject -Property #{
ComputerName = $_.__SERVER
Sweet = $sweet
OS = if ($sweet -eq 7601) {'Yes!'} else {'Nooooo!'}
}
}

Get-Service on multiple remote machines

I can only get the command to return the services on the first computer in the text file.
Is there a better way than for-each for this task?
Get-Service *vault* -ComputerName (Get-Content c:\users\sean\desktop\js.txt) | select name,status,machinename | sort machinename | format-table -autosize
Try it without the get-content. Try this:
Get-Service *vault* -ComputerName c:\users\sean\desktop\js.txt | select name,status,machinename | sort machinename | format-table -autosize
If that doesn't work, then try:
$Computers = Get-Content c:\users\sean\desktop\js.txt
Get-Service *vault* -computername $Computers | Select name,status,machinename |sort machinename |format-table -autosize
If you are eager for a one-liner then try this:
Get-Content c:\users\sean\desktop\js.txt | Get-Service *vault* | Select name,status,machinename |sort machinename |format-table -autosize
I would try the top one first. I would test, but I don't have access to anything I can do a proper test right now.
$Computers = get-content .\desktop\test.txt
$Service = "Vault"
foreach ($computer in $computers) {
$computer
$Servicestatus = get-service -name $Service -ComputerName $computer
}
$Servicestatus | select-object Name,Status,MachineName | format-table -Autosize
This works for me, it gives me each of the computers in the text file, and it looks for the service.
This is what I use. I get the list of computers from an OU in AD.
Import-Module ActiveDirectory
$ou = "OU=Servers,DC=Domain,DC=com"
$servers = Get-ADComputer -Filter * -SearchBase $ou | select-object -expandproperty name
Foreach ($server in $servers){
$Data = Get-Service -ServiceName *IIS*,*TomCat*,*httpd* -ComputerName $server | select machinename,name | sort machinename | format-table -AutoSize
Write($Data) | Out-File .\WebServices.txt -Append
}
$servers = Get-Content .\servers.txt
Foreach ($server in $servers) {
"$server"
Get-Service -ComputerName $Server -name -like "*vault*"
"-------------------"
}
Following a memory limitation limit with older versions of PowerShell, I was required to refresh my code:
Old code:
gwmi win32_service -computer $allcomputers | Select-Object __SERVER,Name,state,startmode,StartName
New code:
`$servers = Get-Content "computers.txt"
Foreach ($server in $servers) {
Get-WmiObject -Class WIN32_service -ComputerName $server |
Select-Object __SERVER,Name,state,startmode,StartName |
Export-Csv -path "Report.CSV" -NoTypeInformation -Append
}`
This is how you can get list of all services in your AD domain:
Get-ADComputer -Filter {OperatingSystem -Like “Windows 10*”} | ForEach-Object {Get-WmiObject -Class Win32_Service -Computer $_.Name}
More useful examples on this (get list of services for all computer listed in a text file, etc.):
https://www.action1.com/kb/list_of_services_on_remote_computer.html
Get-Service -ComputerName ... has a bug in PowerShell 2.0 that only returns the first computer. This is fixed in newer versions so if you upgrade to PowerShell 3.0 or newer, your original code will work fine.
As a workaround, use a foreach-loop to run Get-Service once for each computer:
Get-Content c:\users\sean\desktop\js.txt |
ForEach-Object { Get-Service -Name *vault* -ComputerName $_ } |
Select-Object -Property Name, Status, MachineName |
Sort-Object -Property MachineName |
Format-Table -AutoSize
Nick's solution totally doesn't work for me. I ended up writing a quick and dirty one that works:
$servers = Get-Content .\servers.txt
Foreach ($server in $servers) {
"$server"
Get-Service *vault*
"-------------------"
}