Adding NSLookup to Ping Script - powershell

I have this ping script that works well for what I need. I want to add to this but not sure how. I want it to output like a NSLookup. Sometimes I have the host name for the printer and would like it to output the IP if one is found and add that to another column.
First EX:
Get-Content "C:\Users\Username\Desktop\New folder\hnames.txt" | ForEach-Object { #Change User to your name and after desktop where you have IPs you want to ping
if(Test-Connection $_ -Count 1 -ErrorAction SilentlyContinue){
$status = 'Alive'
}
else {
$status = 'Dead'
}
$dns = Resolve-DnsName $_ -DnsOnly -ErrorAction SilentlyContinue
# output 1 object with two separate properties
[pscustomobject]#{
Status = $status
Target = $_
IPAddress = $dns.IPAddress -join ', '
}
} |Export-Csv 'C:\Users\Username\Desktop\New folder\output.csv' -NoTypeInformation #change this to where you want the export to go, Change Output to what you want to save as
Second EX:
Get-Content "C:\Users\Username\Desktop\New folder\hnames.txt" | ForEach-Object { #Change User to your name and after desktop where you have IPs you want to ping
if(Test-Connection $_ -Count 1 -ErrorAction SilentlyContinue){
$status = 'Alive'
}
else {
$status = 'Dead'
}
# output 1 object with two separate properties
[pscustomobject]#{
Status = $status
Target = $_
IPAddress = $success.Address.IPAddressToString
}
} |Export-Csv 'C:\Users\Username\Desktop\New folder\output.csv' -NoTypeInformation #change this to where you want the export to go, Change Output to what you want to save as

If you're doing hostname to IP Address you could use the output from Test-Connection already, for example:
Get-Content ..... | ForEach-Object {
$status = 'Dead'
if($success = Test-Connection $_ -Count 1 -ErrorAction SilentlyContinue) {
$status = 'Alive'
}
[pscustomobject]#{
Status = $status
Target = $_
IPAddress = $success.Address.IPAddressToString
}
} | Export-Csv ..... -NoTypeInformation
Another option is to use Resolve-DnsName:
Get-Content ..... | ForEach-Object {
$status = 'Dead'
if(Test-Connection $_ -Count 1 -ErrorAction SilentlyContinue) {
$status = 'Alive'
}
$dns = Resolve-DnsName $_ -ErrorAction SilentlyContinue
[pscustomobject]#{
Status = $status
Target = $_
IPAddress = $dns.IPAddress -join ', '
}
} | Export-Csv ..... -NoTypeInformation

Related

CSV Output Unreadable

I'm trying to export the results of this simple script to a .csv file. I get the results but it either returns information about data of the results or a long jumble of data I'm sure how to parse correctly.
<#
Will ping all devices in list and display results as a simple UP or DOWN, color coded Red or Green.
#>
$Names = Get-Content -Path "C:\TestFolder\GetNames.txt"
$Output = #()
foreach ($name in $names)
{
if (Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue)
{
$Result1 += "$name, up"
Write-Host "$name, up" -ForegroundColor Green
}
else
{
$Result2 += "$name, down"
Write-Host "$name, down" -ForegroundColor Red
}
}
$Output += $Result1, $Result2
$Output = $Output | Select-Object
$Output | Export-Csv -Path 'C:\psCSVFiles\mycsv.csv' -NoTypeInformation
Results of this return:
Length
49768
25081
What am I doing wrong here? Thanks
Don't attempt to "format" the output strings manually - Export-Csv will take care of that part.
What you want to do is create objects with properties corresponding to the columns you want in your CSV:
$Names = Get-Content -Path "C:\TestFolder\GetNames.txt"
$Output = foreach ($name in $names) {
# test if computer is reachable/pingable
$isUp = Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue -Quiet
# construct output object with results
[pscustomobject]#{
ComputerName = $name
Status = if($isUp){ 'Up' }else{ 'Down' }
}
}
# Export to CSV
$Output |Export-Csv -Path 'C:\psCSVFiles\mycsv.csv' -NoTypeInformation
Alternatively, use Select-Object to modify the input strings directly using the pipeline:
Get-Content -Path "C:\TestFolder\GetNames.txt" |Select #{Name='ComputerName';Expression={$_}},#{Name='Status';Expression={if(Test-Connection -ComputerName $_ -Count 1 -ErrorAction SilentlyContinue -Quiet){'Up'}else{'Down'}}} |Export-Csv -Path 'C:\psCSVFiles\mycsv.csv' -NoTypeInformation

How to Scan multiple Hostnames to resolve Ip addresses Powershell script

I am looking for some help with a script that will read a textfile full of server names and resolve the IP address and export this into a csv file. I am using powershell for this and the Test-Connection command. Please see below code - i am getting the error - cmdlet ForEach-Object at command pipeline position 1 Supply values for the following parameters:Process[0]:
(removed my username and swapped with ***)
$array=#()
$computer=Get-Content -Path c:\Users\****\Desktop\ping_IP_host\computers.txt
ForEach ($server in $computer){
if(Test-Connection $server -Quiet)
{
try {
$IP=
[System.net.dns]::GetHostEntry($server).AddressList | %
{$_.IpAddressTostring}
}
catch {"Invalid HostName" - $server}
$obj = New-Object PSObject -Property #{
Hostname=$server
IP=$IP
}
$array += $obj
else {
$IP="Invalid Host"
}
$obj = New-Object PSObject -Property #{
Hostname=$server
IP=$IP
}
$array += $obj
}
}
$array | Export-Csv C:\Users\****\Desktop\ping_IP_host\results.csv
There is a misplace curly bracket, duplicated code, logic error and unwrapped objects.
Indenting properly will help you to find errors and duplicated code.
The custom object you build does contain both IPv4 and IPv6 addresses, so you may want to join the 2 addresses OR just select the IPv4 address - I do not know your requirements.
Edit:
The try..catch block is not needed as it depends on GetHostEntry() getting a result for the DNS lookup of $server, which is already verified by the test-connection. In short, your code defaults to the else clause "Invalid Host" when the host does not exist OR the host does not answer to ICMP.
the try..catch block around $IP = ([System.net.dns]::GetHostEntry($server).AddressList should be located before the Test-Connection because an error means the host name is invalid so no point in trying a ping.
Note: The code below does not take into account the above edit.
Working code:
$array=#()
$computer=Get-Content -Path $env:userprofile\Desktop\ping_IP_host\computers.txt
ForEach ($server in $computer) {
if (Test-Connection $server -Quiet -count 1) {
try {
$IP = ([System.net.dns]::GetHostEntry($server).AddressList | ForEach-Object {$_.IPAddressToString} ) -join ";"
}
catch {"Invalid HostName" - $server}
}
else {
$IP="Invalid Host"
}
$obj = New-Object PSObject -Property #{
Hostname = $server
IP = $IP
}
$array += $obj
}
$array | Export-Csv -NoTypeInformation $env:userprofile\Desktop\ping_IP_host\results.csv
Output:
"IP","Hostname"
"216.58.206.68;2a00:1450:4002:803::2004","www.google.com"
"Invalid Host","jupiter"
"Invalid host","microsoft.com"
Select IPv4 address only
$array=#()
$computer=Get-Content -Path $env:userprofile\computers.txt
ForEach ($server in $computer) {
if (Test-Connection $server -Quiet -count 1) {
try {
$IP = [System.net.dns]::GetHostEntry($server).AddressList | Where-Object {$_.AddressFamily -eq 'InterNetwork'} | ForEach-Object {$_.IPAddressToString}
}
catch {"Invalid HostName" - $server}
}
else {
$IP="Invalid Host"
}
$obj = New-Object PSObject -Property #{
Hostname = $server
IP = $IP
}
$array += $obj
}
$array | Export-Csv -NoTypeInformation $env:userprofile\Desktop\ping_IP_host\results.csv
Output:
"IP","Hostname"
"216.58.206.68","www.google.com"
"Invalid Host","jupiter"
"Invalid host","microsoft.com"

Output if/else statement results to formatted table

I have written an environment IP check script in Powershell which works but I can't figure out how to display the output to screen in a formatted table which auto sizes the columns.
$infile = Import-Csv "~\Env_IPlist.csv" -Delimiter ","
$arr1 = #()
$IP_Addresses = $infile |
Select-Object "Device_Type", "Device_Name", "IP_Address",
"IP_Role", "Location"
Write-Host "Started Ping Test ..."
foreach ($IP in $IP_Addresses) {
if (Test-Connection $IP.("IP_Address") -Quiet -Count 1 -ErrorAction SilentlyContinue) {
Write-Host $IP.("Device_Name") ":" $IP.("IP_Address") "Ping successful" -ForegroundColor Green
} else {
Write-Host $IP."Device_Name" ":" $IP.("IP_Address") "Ping failed" -ForegroundColor Red -BackgroundColor white
}
}
Write-Host "Ping Test Completed!"
Add the Test-Connection result via a calculated property, then pipe the output to Format-Table.
$infile |
Select-Object Device_Type, Device_Name, IP_Address, IP_Role, Location,
#{n='Online';e={
[bool](Test-Connection $_.IP_Address -Quiet -Count 1 -EA SilentlyContinue)
}} |
Format-Table -AutoSize
I rewrote the script using PSObject as initially suggested but now I do not know how to add the ForegroundColor in the if..else statement.
$infile = Import-Csv "~\Env_IPlist.csv" -Delimiter ","
$arr1 = #()
$IP_Addresses = $infile |
Select-Object Device_Type, Device_Name, IP_Address, IP_Role,
Location, Status
foreach ($IP in $IP_Addresses) {
if (Test-Connection $IP.IP_Address -Quiet -Count 1 -ErrorAction SilentlyContinue) {
$PSObject = New-Object PSObject -Property #{
Device_Type = $IP.Device_Type
Device_Name = $IP.Device_Name
IP_Address = $IP.IP_Address
IP_Role = $IP.IP_Role
Location = $IP.Location
Status = "Successful"
}
} else {
$PSObject = New-Object PSObject -Property #{
Device_Type = $IP.Device_Type
Device_Name = $IP.Device_Name
IP_Address = $IP.IP_Address
IP_Role = $IP.IP_Role
Location = $IP.Location
Status = "Failed"
}
}
$arr1 += $PSObject
}
$arr1 | Format-Table -AutoSize

Writing errors to CSV in Powershell

$csv = Get-Content c:\users\user\downloads\OutofContact.csv
foreach ($computer in $csv)
{
try{
$report = New-Object -TypeName PSObject -Property #{
ComputerName = (Resolve-DnsName $computer).Name
IPAddress = (Resolve-DnsName $computer).IPAddress
}
$report | select-object -Property ComputerName, IPAddress | Export-Csv -Path Results.csv -notype -append
}catch{
Write-Error "$computer not found" | Export-Csv -Path Results.csv -notype -append
}
}
I'm using the above code to check the DNS entries for a list of machines. Some of the machines do not exist in DNS and will throw an error. I want those machines to write the error into the CSV, however they just show up as blank rows.
How can I get the errors to write to the CSV as well?
I would refactor and optimize duplicate calls, and only add one object at the end...
Something like this:
#$csv = Get-Content c:\users\user\downloads\OutofContact.csv
# test
$csv = #('localhost', 'doesnotexist', 'localhost', 'doesnotexist')
$allReports = [System.Collections.ArrayList]::new()
foreach ($computer in $csv)
{
$report = [pscustomobject]#{
'ComputerName' = $computer
'IPAddress' = 'none'
'Status' = 'none'
}
try
{
# this can return multiple entries/ipaddresses
$dns = Resolve-DnsName $computer -ErrorAction Stop | Select -First 1
$report.ComputerName = $dns.Name
$report.IPAddress = $dns.IPAddress
$report.Status = 'ok'
}
catch
{
Write-Error "$computer not found"
}
finally
{
$null = $allReports.Add($report);
}
}
# write to csv file once...
$allReports | Export-Csv -Path c:\temp\Results.csv -NoTypeInformation #??? keep this? -Append
You will want to walk through the code and debug and change to your specific requirements.

get last user logon time without AD

I'm trying to create a script that can get the user profiles that haven't logged on a specific computer within 30 days NOT using active directory but my script didn't work. I am using Powershell version 3. This is my code:
netsh advfirewall firewall set rule group="Windows Management Instrumentation (WMI)" new enable=yes
$ComputerList = Get-Content C:\temp\Computers1.txt
$myDomain = Get-Content C:\temp\Domain.txt
$csvFile = 'C:\temp\Profiles.csv'
# Create new .csv output file
New-Item $csvFile -type file -force
# Output the field header-line to the CSV file
"HOST,PROFILE" | Add-Content $csvFile
# Loop over the list of computers from the input file
foreach ($Computer in $ComputerList) {
# see if ping test succeeds for this computer
if (Test-Connection $Computer -Count 3 -ErrorAction SilentlyContinue) {
$ComputerFQDN = $Computer + $myDomain
$Profiles = Get-WmiObject -Class Win32_UserProfile -Computer $ComputerFQDN | Where{$_.LocalPath -notlike "*$env:SystemRoot*"}
foreach ($profile in $profiles) {
try {
$objSID = New-Object System.Security.Principal.SecurityIdentifier($profile.LocalPath) | Where {((Get-Date)-$_.lastwritetime).days -ge 30}
#| Where-Object {$_.LastLogonDate -le $CurrentDate.AddDays(-60)}
$objuser = $objsid.Translate([System.Security.Principal.NTAccount])
$objusername = $objuser.value
} catch {
$objusername = $profile.LocalPath
}
switch($profile.status){
1 { $profileType="Temporary" }
2 { $profileType="Roaming" }
4 { $profileType="Mandatory" }
8 { $profileType="Corrupted" }
default { $profileType = "LOCAL" }
}
$User = $objUser.Value
#output profile detail for this host
"$($Computer.toUpper()), $($objusername)" | Add-Content $csvFile
}
} else {
#output failure message for this host
"$($Computer.toUpper()), PING TEST FAILED" | Add-Content $csvFile
}
#LOOP
}
I tried to change the -ge to -le in the line $objSID = New-Object System.Security.Principal.SecurityIdentifier($profile.LocalPath) | Where {((Get-Date)-$_.lastwritetime).days -ge 30}, as well as changing the range after it but it still gave me the same list of computers regardless of my changes.
There are a few problems with the script, most notable is that your use of Where-Object is testing an object (SID) that doesn't know anything about dates.
I would break it down a little differently. I would write a function to catch all the stuff I need to do to attempt to figure out the last logon. That's my goes in my stack of utility functions in case I need it again.
Then I have something to use that function which deals with implementing the logic for the immediate requirement.
So you end up with this. It's a bit long, see what you think.
function Get-LastLogon {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline = $true)]
[String]$ComputerName = $env:COMPUTERNAME
)
process {
Get-WmiObject Win32_UserProfile -ComputerName $ComputerName -Filter "Special='FALSE'" | ForEach-Object {
# Attempt to get the UserAccount using WMI
$userAccount = Get-WmiObject Win32_UserAccount -Filter "SID='$($_.SID)'" -ComputerName $ComputerName
# To satisfy WMI all single \ in a path must be escaped.
# Prefer to use NTUser.dat for last modification
$path = (Join-Path $_.LocalPath 'ntuser.dat') -replace '\\', '\\'
$cimObject = Get-WmiObject CIM_DataFile -Filter "Name='$path'" -ComputerName $ComputerName
if ($null -eq $cimObject) {
# Fall back to the directory
$path = $_.LocalPath -replace '\\', '\\'
$cimObject = Get-WmiObject CIM_Directory -Filter "Name='$path'" -ComputerName $ComputerName
}
$lastModified = $null
if ($null -ne $cimObject) {
$lastModified = [System.Management.ManagementDateTimeConverter]::ToDateTime($cimObject.LastModified)
}
# See if LastUseTime is more useful.
$lastUsed = $null
if ($null -ne $_.LastUseTime) {
$lastUsed = [System.Management.ManagementDateTimeConverter]::ToDateTime($_.LastUseTime)
}
# Profile type
$profileType = switch ($_.Status) {
1 { "Temporary" }
2 { "Roaming" }
4 { "Mandatory" }
8 { "Corrupted" }
0 { "LOCAL" }
}
[PSCustomObject]#{
ComputerName = $ComputerName
Username = $userAccount.Caption
LastChanged = $lastModified
LastUsed = $lastUsed
SID = $_.SID
Path = $_.LocalPath
ProfileType = $profileType
}
}
}
}
$myDomain = Get-Content C:\temp\Domain.txt
Get-Content C:\temp\Computers1.txt | ForEach-Object {
$ComputerName = $_ + $myDomain
if (Test-Connection $ComputerName -Quiet -Count 3) {
Get-LastLogon -ComputerName $ComputerName | Select-Object *, #{Name='Status';Expression={ 'OK' }} |
Where-Object { $_.LastChanged -lt (Get-Date).AddDays(-30) }
} else {
# Normalise the output so we don't lose columns in the export
$ComputerName | Select-Object #{Name='ComputerName';e={ $ComputerName }},
Username, LastChanged, LastUsed, SID, Path, ProfileType, #{Name='Status';Expression={ 'PING FAILED' }}
}
} | Export-Csv 'C:\temp\Profiles.csv' -NoTypeInformation