Powershell scripting issues "Mac Address List"

Experts,

I am looking for a script that can take a list of hostnames ($mypcs) and provide the IP, MacAddress, and Hostname of each of the computers in question.

I would like this script to also be able to tell when computers were not reachable..

I have been working on the following but haven't gotten it to work property yet and need this information ASAP.


Function Get-Mac { 
    $ComputerName = $mypcs 
    $ErrorActionPreference = 'Stop'
    
    $COlResults = foreach ($Computer in $ComputerName) {     
        invoke-command -ComputerName $computer -Credential $cred -ScriptBlock {
            Try{
                $WMI = gwmi -class "Win32_NetworkAdapterConfiguration" |? IpEnabled -EQ "True" | select PSComputerName, description, ipAddress, MACAddress | FT -AutoSize;
                $WMI        
            }catch {
                    Write-Warning "System is not reachable : $Computer";Continue
             }
            
        
    }

    }
    $COlResults
}
. Get-Mac

Open in new window

LVL 15
ITguy565Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Jeremy WeisingerSenior Network Consultant / EngineerCommented:
What error are you getting? Have you tried connecting over WMI:

$ComputerName = $mypcs 
$ErrorActionPreference = 'Stop'
    
$COlResults = foreach ($Computer in $ComputerName) {     
        Try{
            $WMI = gwmi -class "Win32_NetworkAdapterConfiguration" -ComputerName $Computer|? IpEnabled -EQ "True" | select PSComputerName, description, ipAddress, MACAddress | FT -AutoSize
            $WMI        
        }catch {
            Write-Warning "System is not reachable : $Computer";Continue
        }
    }

Open in new window

0
ITguy565Author Commented:
@jeremy

Thanks for your response:

I started out with code very similar to what you presented. I was getting a lot of RPC errors when running it as you can see here:

wmi : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At line:3 char:20
+ ...      $WMI = gwmi -class "Win32_NetworkAdapterConfiguration" -Computer ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException
    + FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

gwmi : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At line:3 char:20
+ ...      $WMI = gwmi -class "Win32_NetworkAdapterConfiguration" -Computer ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException
    + FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

gwmi : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At line:3 char:20
+ ...      $WMI = gwmi -class "Win32_NetworkAdapterConfiguration" -Computer ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException
    + FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

gwmi : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At line:3 char:20
+ ...      $WMI = gwmi -class "Win32_NetworkAdapterConfiguration" -Computer ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException
    + FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

That is when I moved to the invoke-command as you can see in my original example above.

When I run the invoke command I get the proper output, but duplicates of that output across the whole command.


Can you present me with a modification of your code above that utilizes the invoke command and runs a break out based on Name, Ipaddress, and Macaddress?


I have a feeling the only way that is going to work is store the information in an object, and then loop the information into array per computer. I just haven't seemed to be able to get it to function properly yet.
0
Jeremy WeisingerSenior Network Consultant / EngineerCommented:
Sure. Something like this:
$ComputerName = $mypcs 

Function Get-Mac { 
    Param ($computer)
    $ErrorActionPreference = 'Stop'
    invoke-command -ComputerName $computer -ScriptBlock {
        Try{
            gwmi -class "Win32_NetworkAdapterConfiguration" |? IpEnabled -EQ "True" 
        }catch {
            Write-Warning "System is not reachable : $Computer";Continue
        }
    } | select PSComputerName, description, ipAddress, MACAddress
}

$results = foreach($Computer in $ComputerName){Get-Mac -computer $Computer}
$results | ft -AutoSize

Open in new window

I took out the -credential parameter as you shouldn't need it if you're running it with an account that has the proper permissions. But if you need to specify alternate credentials, add the parameter back.
0
Redefine Your Security with AI & Machine Learning

The implications of AI and machine learning in cyber security are massive and constantly growing, creating both efficiencies and new challenges across the board. Check out our on-demand webinar to learn more about how AI can help your organization!

oBdACommented:
the main issue is the  "| FT -AutoSize;" - the Format-* cmdlets should (unless you know exactly what you're doing) be the very last element in the pipeline. They're made to format output for the console/human eye to see, not to process it further. You're destroying the WMI objects returned with that.
Then you should always filter as close to the source as possible. Don't filter WMI results in PS if you can filter them easily already in WMI.
This should do the trick, including error handling:
$inFile = 'C:\temp\mypcs.txt'
$outFile = 'C:\temp\mypcs_netInfo.csv'
Get-Content -Path $inFile | ForEach-Object {
	$computerName = $_
	Write-Host "Processing $($computerName) ..."
	Try {
		Invoke-Command -ComputerName $_ -ErrorAction Stop -ScriptBlock {
			Try {
				Get-WmiObject -Query "SELECT __Server, Description, IPAddress, MACAddress FROM Win32_NetworkAdapterConfiguration WHERE IpEnabled='True'" -ErrorAction Stop
			} Catch {
				$_ | Select-Object @{n='PSComputerName'; e={$ENV:ComputerName}}, @{n='Error'; e={$_.Exception.Message}}
			}
		}
	} Catch {
		$_ | Select-Object @{n='PSComputerName'; e={$computerName}}, @{n='Error'; e={$_.Exception.Message}}
	}
} | Select-Object PSComputerName, Description, IPAddress, MACAddress, Error | Export-Csv -NoTypeInformation -Path $outFile

Open in new window

0
Jeremy WeisingerSenior Network Consultant / EngineerCommented:
Ah, yes. Use oDbA's script. It handles the Invoke-Command properly. It should keep running when it encounters an error connecting to a computer.
0
ITguy565Author Commented:
@Jeremy,

Thanks for your assistance.. You are correct the script that you presented above errored and stopped at the first error and thus didn't log. I appreciate your assistance with this.

@oBdA,

The script that you presented is still running, I will post back with the results as soon as I receive them.. Thanks for your assistance Gentlemen..

I can tell from the error output of your script so far oBdA that it is catching a lot of information, It is also not grabbing some of the computers that I can get by running :

Get-WmiObject -class Win32_NetworkAdapterConfiguration -ComputerName $pc -ErrorAction Stop |
        Where-Object IpEnabled -EQ "True" |
        Select-Object PSComputerName, description, ipAddress, MACAddress

Open in new window

manually which is kinda perplexing but I will know more once the script completes.


An Example of one of the errors are :

"Connecting to remote server SERVERNAME failed with the following error message : WinRM cannot complete the operation. Verify that the specified computer name is valid, that the computer is accessible over the network, and that a firewall exception for the WinRM service is enabled and allows access from this computer. By default, the WinRM firewall exception for public profiles limits access to remote computers within the same local subnet. For more information, see the about_Remote_Troubleshooting Help topic."

I haven't checked the firewall yet on that server.
0
oBdACommented:
There's always the brute force option: attempt the other one as well if the first one fails (not that it's making it any faster ...)
$inFile = 'C:\temp\mypcs.txt'
$outFile = 'C:\temp\mypcs_netInfo.csv'
Get-Content -Path $inFile | ForEach-Object {
	$computerName = $_
	Write-Host "Processing $($computerName) ..." -NoNewline
	Try {
		Get-WmiObject -Query "SELECT __Server, Description, IPAddress, MACAddress FROM Win32_NetworkAdapterConfiguration WHERE IpEnabled='True'" -ComputerName $computerName -ErrorAction Stop |
			Select-Object -Property *, @{n='QuerySuccess'; e={'GetWmiObject'}}
		Write-Host ' remote Get-WmiObject succeeded.' -ForegroundColor Green
	} Catch {
		Write-Host " WMI remoting failed, attempting PS remoting ..." -NoNewline
		$wmiError = $_.Exception.Message
		Try {
			Invoke-Command -ComputerName $computerName -ErrorAction Stop -ScriptBlock {
				Try {
					Get-WmiObject -Query "SELECT __Server, Description, IPAddress, MACAddress FROM Win32_NetworkAdapterConfiguration WHERE IpEnabled='True'" -ErrorAction Stop |
						Select-Object -Property *, @{n='QuerySuccess'; e={'InvokeCommand'}}
					Write-Host ' Invoke-Command succeeded.' -ForegroundColor Green
				} Catch {
					$_ | Select-Object @{n='PSComputerName'; e={$ENV:ComputerName}}, @{n='RemoteWmiError'; e={$wmiError}}, @{n='LocalWmiError'; e={$_.Exception.Message}}
					Write-Host ' Get-WmiObject with Invoke-Command failed.' -ForegroundColor Yellow
				}
			}
		} Catch {
			Write-Host ' Invoke-Command failed.' -ForegroundColor Yellow
			$_ | Select-Object @{n='PSComputerName'; e={$computerName}}, @{n='RemoteWmiError'; e={$wmiError}}, @{n='InvokeError'; e={$_.Exception.Message}}
		}
	}
} | Select-Object PSComputerName, Description, IPAddress, MACAddress, QuerySuccess, RemoteWmiError, LocalWmiError, InvokeError | Export-Csv -NoTypeInformation -Path $outFile

Open in new window

0
ITguy565Author Commented:
oBdA,

Upon completion of the script, I noticed that it failed to connect to a lot of my servers due to the error listed above.

I removed the invoke-command loop from your script and that appeared to clear up a lot of the issues.

$inFile = 'C:\temp\mypcs.txt'
$outFile = 'C:\temp\mypcs_netInfo.csv'
Get-Content -Path $inFile | ForEach-Object {
	$computerName = $_
    Write-Host "Processing $($computerName) ..."
    
			Try {
				Get-WmiObject -computer $_ -Query "SELECT __Server, Description, IPAddress, MACAddress FROM Win32_NetworkAdapterConfiguration WHERE IpEnabled='True'" -ErrorAction Stop
			} Catch {
				$_ | Select-Object @{n='PSComputerName'; e={$ENV:ComputerName}}, @{n='Error'; e={$_.Exception.Message}}
			}
} | Select-Object PSComputerName, Description, IPAddress, MACAddress, Error | Export-Csv -NoTypeInformation -Path $outFile

Open in new window


The code above allowed me to collect the information I needed, the only problem I see is with the IP address.

The IP now is showing as a "System.string[]" rather than the value associated with it. Once that shows the proper value then I believe I will have all the information I need on this.

I REALLY APPRECIATE your assistance with this, because for some reason, I just couldn't wrap my head around this code.
0
oBdACommented:
That should take care of the IP address issue:
$inFile = 'C:\temp\mypcs.txt'
$outFile = 'C:\temp\mypcs_netInfo.csv'
Get-Content -Path $inFile | ForEach-Object {
	$computerName = $_
	Write-Host "Processing $($computerName) ..." -NoNewline
	Try {
		Get-WmiObject -Query "SELECT __Server, Description, IPAddress, MACAddress FROM Win32_NetworkAdapterConfiguration WHERE IpEnabled='True'" -ComputerName $computerName -ErrorAction Stop |
			Select-Object -Property *, @{n='QuerySuccess'; e={'GetWmiObject'}}
		Write-Host ' remote Get-WmiObject succeeded.' -ForegroundColor Green
	} Catch {
		Write-Host " WMI remoting failed, attempting PS remoting ..." -NoNewline
		$wmiError = $_.Exception.Message
		Try {
			Invoke-Command -ComputerName $computerName -ErrorAction Stop -ScriptBlock {
				Try {
					Get-WmiObject -Query "SELECT __Server, Description, IPAddress, MACAddress FROM Win32_NetworkAdapterConfiguration WHERE IpEnabled='True'" -ErrorAction Stop |
						Select-Object -Property *, @{n='QuerySuccess'; e={'InvokeCommand'}}
					Write-Host ' Invoke-Command succeeded.' -ForegroundColor Green
				} Catch {
					$_ | Select-Object @{n='PSComputerName'; e={$ENV:ComputerName}}, @{n='RemoteWmiError'; e={$wmiError}}, @{n='LocalWmiError'; e={$_.Exception.Message}}
					Write-Host ' Get-WmiObject with Invoke-Command failed.' -ForegroundColor Yellow
				}
			}
		} Catch {
			Write-Host ' Invoke-Command failed.' -ForegroundColor Yellow
			$_ | Select-Object @{n='PSComputerName'; e={$computerName}}, @{n='RemoteWmiError'; e={$wmiError}}, @{n='InvokeError'; e={$_.Exception.Message}}
		}
	}
} | Select-Object PSComputerName, Description, @{n='IPAddress'; e={$_.IPAddress -join ', '}}, MACAddress, QuerySuccess, RemoteWmiError, LocalWmiError, InvokeError | Export-Csv -NoTypeInformation -Path $outFile 

Open in new window


Will be offline for the next few hours, so I'm not ignoring you when I don't respond in the next time ...
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ITguy565Author Commented:
Awesome, I will test momentarily!
0
ITguy565Author Commented:
@jeremy

Thanks for assisting with this question!

@oBdA
You are the MAN! thanks you really saved my butt with this one.
0
Jeremy WeisingerSenior Network Consultant / EngineerCommented:
oBdA is the man!
Glad to help out a little. :)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.