Output single line of multi-line CimInstance - powershell

I am trying to find a full solution to capture information from with Get-CimInstance Win32_NetworkAdapter and save it to a table on a server. Currently I am using the code around below:
$SerialNum = Get-CIMInstance WIN32_BIOS | SELECT -ExpandProperty SerialNumber
Get-CimInstance Win32_NetworkAdapter | Select-Object * |
Export-Csv S:\$SerialNum-NetAdptr.csv -Force -NoTypeInformation
Import-Csv S:\$SerialNum-NetAdptr.csv |
Select-Object *, #{Name='Serial';Expression={Get-CIMInstance WIN32_BIOS | Select-Object -ExpandProperty SerialNumber}} |
Export-Csv S:\$SerialNum-NetAdptrSerialized.csv -Force -NoTypeInformation
Remove-Item S:\$SerialNum-NetAdptr.csv
The issue I am having is computers with multiple NICs output multiple lines so outputting like:
$NetAdptrINF = Get-CIMInstance Win32_NetworkAdapter | Select-Object *
$objRecordSet.Fields.Item("ProductName").Value = ($NetAdptrINF.ProductName).ToString()
or
$objRecordSet.Fields.Item("ProductName").Value = $NetAdptrINF.ProductName
Saves something along the lines of: System[].object in the field. I have been looking at using foreach to print one line of each network adapter property at a time but have been unable to get anything that even remotely works. I am using PowerShell bundled in Windows 10 ADK.
$NetAdptrInf.ProductName outputs:
Microsoft Kernel Debug Network Adapter
Intel(R) Dual Band Wireless-AC 7260
Intel(R) Ethernet Connection I217-LM
Microsoft Wi-Fi Direct Virtual Adapter
Microsoft Hosted Network Virtual Adapter
Microsoft ISATAP Adapter
Microsoft Teredo Tunneling Adapter
Microsoft ISATAP Adapter
Microsoft ISATAP Adapter
VirtualBox Host-Only Ethernet Adapter
I need to be able to output one ProductName save it to a record along with other information collected from Win32_NetworkAdapter then move to the next one and repeat.
Thank you.

According the fact that $NetAdptrINF is evaluated as follow :
$NetAdptrINF = Get-CIMInstance Win32_NetworkAdapter
You can use the following to retreive a text list of product names :
($NetAdptrINF | % { $_.productname}) -join ','
Edited :
If you want to get a reccord by productname :
Get-CIMInstance Win32_NetworkAdapter | Select-Object DeviceId,Name,Productname,ServiceName,AdapterType

Related

Powershell get installed program script doesn't return computer name

I'm trying to get a list of installed programs off a group of remote servers. I'm able to get the program name but not return the system name. Below is my script.
$computerfile = get-content "D:\Users\Admin\Docs\PrimaryServers.txt"
ForEach ($computer in $computerfile) {
Get-WmiObject Win32_Product -ComputerName $computer |
Select-Object SystemName,Name,Version,PackageName,Installdate,Vendor |
Format-Table -AutoSize
}
Below is my output
First, -ComputerName can take an array of names so by looping you are going to increase the time because the loop will be in serial where utilizing the array for computername will be in parallel.
Second, it's best practice to use the CIM cmdlets in place of the WMI cmdlets. They operate over WSMAN by default and are easier to work with.
Third, Win32_Product forces a consistency check so reading the Uninstall registry keys is usually superior.
Lastly, SystemName isn't a property name that is returned by Get-WMIObject. PSComputerName is the property you are looking for and you can make a Calculated Property from it.
$computerfile = get-content "D:\Users\Admin\Docs\PrimaryServers.txt"
Get-CimInstance Win32_Product -ComputerName $Computerfile |
Select-Object #{n=SystemName;e={$_.PSComputerName}},Name,Version,PackageName,Installdate,Vendor |
Format-Table -AutoSize
Another approach is to use the Invoke-Command where it automatically extends the result with the PSComputerName column
First build up the script blocks to use as query
Block 1 is my approach for both x32 and x64 implementations. Consider this as an alternative because I has some issues with the proposed implementation.
$block1={
# Query x64 bit applications
$queryPath="HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*"
Get-ItemProperty $queryPath | Select-Object -Property DisplayName, Publisher, InstallDate, DisplayVersion
# Query x32 bit applications
$queryPath="HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
Get-ItemProperty $queryPath | Select-Object -Property DisplayName, Publisher, InstallDate, DisplayVersion
}
Block 2 is the proposed approach on this question
$block2={
Get-CimInstance Win32_Product | Select-Object Name,Version,PackageName,Installdate,Vendor
}
For either $block1 or $block2 execute remotely on a server list
Invoke-Command -ComputerName $computernames -ScriptBlock $block1
And one record looks like this
DisplayName : Microsoft Visual C++ 2013 x86 Additional Runtime - 12.0.21005
Publisher : Microsoft Corporation
InstallDate : 20161202
DisplayVersion : 12.0.21005
PSComputerName : MECDEVAPP01
RunspaceId : 4b8cc747-da25-4c6e-b108-0ca3138c0335

Find NIC by IP address

I need to be able to find a NIC by IP address, whether full or partial. So writing something like:
Get-NIC-By-IP 10.10.*
Could return:
Ethernet
I know how to do this in Bash but haven't been able to find a PowerShell solution to this.
For versions of Windows and/or PowerShell that do not support Get-NetIPAddress, you can get the requisite information with a combination of the WMI queries for the classes Win32_NetworkAdapterConfiguration and Win32_NetworkAdapter:
$Configs = Get-WMIObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled='TRUE'" | Where-Object {$_.IPAddress -like "192.168.*"}
ForEach ($Config in $Configs) {
Get-WMIObject -Class Win32_NetworkAdapter -Filter "Index=$($Config.Index)" | Select-Object NetConnectionID,Description
}
By using the following command you will receive every interface which matches the IP-addres which you mention in the match clause.
Get-NetIPAddress | ?{ $_.AddressFamily -eq "IPv4" -and ($_.IPAddress -match "192.")} | Select-Object InterfaceAlias
In my case this is:
InterfaceAlias
--------------
Ethernet 2
Ethernet
Of course, you can modify the output if necessary.
Supplement for old OS'es
You can't run this script on old Windows browsers as the cmdlet isn't included according to this thread on TechNet: https://social.technet.microsoft.com/Forums/office/en-US/dcc966a1-24c2-4ae4-b39d-b78df52b6aef/install-of-powershell-3-on-windows-7-seems-to-be-missing-modules?forum=winserverpowershell
There are many cmdlets in Powershell for Windows 8 and Server 2012 (PS V3) that are not included in the V3 release for Windows 7.  An example would be Get-NetIPAddress, and many other network-related cmdlets.
Then again, it might be a good idea to upgrade the OS to a supported version (if possible of course).

Default Gateway Manipulation [duplicate]

If a computer has multiple gateways, how can I determine which is the default gateway using the PowerShell?
If you're on PowerShell v3, you can use Get-NetIPConfiguration e.g.:
Get-NetIPConfiguration | Foreach IPv4DefaultGateway
I think this will be more cross platform:
Get-NetRoute |
where {$_.DestinationPrefix -eq '0.0.0.0/0'} |
select { $_.NextHop }
You need to know which of the multiple gateways are used? If so. From what I remember, when multiple gateways are available the gateway with the lowest metric("cost" based on link speed) is used. To get this, run the following command:
Get-WmiObject -Class Win32_IP4RouteTable |
where { $_.destination -eq '0.0.0.0' -and $_.mask -eq '0.0.0.0'} |
Sort-Object metric1 | select nexthop, metric1, interfaceindex
if there are multiple default gateways with the same cost, I think it's decided using the binding order of the network adapters. The only way I know to get this is using GUI and registry. To include binding order you could save the output of the script over, get the settingsid from Win32_networkadapterconfiguration (identify using interfaceindex), and read the registry key HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Linkage\Bind. This key lists the binding order it seems, and the settingsid you get from win32_networkadapterconfiguration is the GUID they identify the device with. Then sort the gateways with equal metrics using their order in the Bind reg.key and you got your answer.
Explained in: Technet Social - NIC adapter binding
I found it as the below which lists all active gateways, correct me if I am wrong
(Get-wmiObject Win32_networkAdapterConfiguration | ?{$_.IPEnabled}).DefaultIPGateway
Use the WMI queries to pull the data that you're looking for. Below is a fairly simple example to pull the default gateway for a device specified in the first line variable. This will query the device for network adapters and display the found information (for each adapter) to the console window - pulls adapter index, adapter description, and default gateway
Shouldn't take much to expand this to process multiple devices, or process based on a list fed via an input file.
$computer = $env:COMPUTERNAME
Get-WmiObject win32_networkAdapterConfiguration -ComputerName $computer |
Select index,description,defaultipgateway |
Format-Table -AutoSize
$ActiveNet = Get-NetAdapter –Physical |Where-Object {$_.status -eq "Up"} | select name
$Network = Get-NetIPAddress |Where-Object EnabledDefault -EQ 2 | Where-Object InterfaceAlias -EQ $ActiveNet.name | Where-Object IPv4Address -NE $null | select *
$DefautGateway = Get-NetRoute -InterfaceIndex $Network.InterfaceIndex -DestinationPrefix "0.0.0.0/0" | select NextHop
$DefautGateway.NextHop

Adding a route on Windows machine for a specific adapter using powershell

I am working on a Windows Server will multiple adapters.
The primary adapter has a default gateway.
Now I need to setup a gateway (Not Default gateway) for the secondary adapter.
Generally I would use a route add command for that specific adapter for which I need to Interface ID which I get by typing the "route print".
However I am not able to find any way to find the Interface ID of the adapter programmatically.
Any options?
You can use the Get-NetIPInterface cmdlet to retrieve all interfaces. The ifIndex property will have the ID you're looking for.
Once you've found the index or alias of the desired interface, use New-NetRoute to add the route
Prior to Windows Server 2012, use netsh or the route command
You can get the InterfaceIndex using either Win32_NetworkAdapter or Win32_NetworkAdapterConfiguration WMI-class. I would use Win32_NetworkAdapterConfiguration as you could filter on IPEnabled and DefaultIPGateway to find the active network adapter with no default gateway. Ex:
#Get enabled network adapters
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled = 1" |
#With no default gateway or no IPv4 default gateway
Where-Object { $_.DefaultIPGateway -eq $null -or (#($_.DefaultIPGateway -match '\d+\.\d+\.\d+\.\d+').Count -eq 0) } |
Format-Table Caption, InterfaceIndex, IPEnabled, {$_.IPAddress[0]}
Caption InterfaceIndex IPEnabled $_.IPAddress[0]
------- -------------- --------- ---------------
[00000002] D-Link DWA-140 Wireless N USB Adapter(rev.B3) 2 True 192.168.1.5
#Get interfaceindex
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled = 1" |
Where-Object { $_.DefaultIPGateway -eq $null -or (#($_.DefaultIPGateway -match '\d+\.\d+\.\d+\.\d+').Count -eq 0) } |
Select-Object -ExpandProperty InterfaceIndex
2
You could probably add the route using Win32_IP4RouteTable or Win32_IP4PersistedRouteTable but it's probably easier to just use route add and use WMI only to get the InterfaceIndex

How to get the default gateway from powershell?

If a computer has multiple gateways, how can I determine which is the default gateway using the PowerShell?
If you're on PowerShell v3, you can use Get-NetIPConfiguration e.g.:
Get-NetIPConfiguration | Foreach IPv4DefaultGateway
I think this will be more cross platform:
Get-NetRoute |
where {$_.DestinationPrefix -eq '0.0.0.0/0'} |
select { $_.NextHop }
You need to know which of the multiple gateways are used? If so. From what I remember, when multiple gateways are available the gateway with the lowest metric("cost" based on link speed) is used. To get this, run the following command:
Get-WmiObject -Class Win32_IP4RouteTable |
where { $_.destination -eq '0.0.0.0' -and $_.mask -eq '0.0.0.0'} |
Sort-Object metric1 | select nexthop, metric1, interfaceindex
if there are multiple default gateways with the same cost, I think it's decided using the binding order of the network adapters. The only way I know to get this is using GUI and registry. To include binding order you could save the output of the script over, get the settingsid from Win32_networkadapterconfiguration (identify using interfaceindex), and read the registry key HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Linkage\Bind. This key lists the binding order it seems, and the settingsid you get from win32_networkadapterconfiguration is the GUID they identify the device with. Then sort the gateways with equal metrics using their order in the Bind reg.key and you got your answer.
Explained in: Technet Social - NIC adapter binding
I found it as the below which lists all active gateways, correct me if I am wrong
(Get-wmiObject Win32_networkAdapterConfiguration | ?{$_.IPEnabled}).DefaultIPGateway
Use the WMI queries to pull the data that you're looking for. Below is a fairly simple example to pull the default gateway for a device specified in the first line variable. This will query the device for network adapters and display the found information (for each adapter) to the console window - pulls adapter index, adapter description, and default gateway
Shouldn't take much to expand this to process multiple devices, or process based on a list fed via an input file.
$computer = $env:COMPUTERNAME
Get-WmiObject win32_networkAdapterConfiguration -ComputerName $computer |
Select index,description,defaultipgateway |
Format-Table -AutoSize
$ActiveNet = Get-NetAdapter –Physical |Where-Object {$_.status -eq "Up"} | select name
$Network = Get-NetIPAddress |Where-Object EnabledDefault -EQ 2 | Where-Object InterfaceAlias -EQ $ActiveNet.name | Where-Object IPv4Address -NE $null | select *
$DefautGateway = Get-NetRoute -InterfaceIndex $Network.InterfaceIndex -DestinationPrefix "0.0.0.0/0" | select NextHop
$DefautGateway.NextHop