Issue in Power shell script while using Ping command - powershell

I am trying to read the host file and trying to ping the each host name and after that capturing the IP address in the response and trying to match with the IP address mentioned in the host file.
I have three scenarios:-
1) Its pinging the host and getting the reply back with the correct IP
Result :-Resolved and Replied
2) It's Not pinging at all and not resolving the IP
Result :-Not Resolved and Not Replied
3) It's Pinging but not resolving the IP correctly mentioned to the IP in the host file
Result :-Not Resolved and Replied
I am trying to achieve that scenario with the below script but not fully achieved as different expression need to be used.
Can someone help me to finish it
$lines = Get-Content myfile.txt | Where {$_ -notmatch "((^#)|(^\s+$))"}
# get all test pairs
$tests=$lines |
ForEach-Object{
$fields = $_ -split '\s+'
echo " Fields are $fields"
for ($i = 1; $i -lt $fields.Length; $i++){
New-Object PsObject -Property #{IP=$fields[0];Host=$fields[$i]}
}
}
$tests |
ForEach-Object{
$props=#{
IPAddress=$_.ip
Hostname=$_.Host
Resolve =' '
Reply = ' '
}
$PingResult = ping -n 1 -w 10 $_.host
#echo "$PingResult"
foreach ($line in $PingResult)
{
if ($line.StartsWith("Pinging") -eq $true)
{
$_.ip= $line -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
echo "IP is $IP"
if ($matches[0])
{
$props.Resolve ='Y'
$props.Reply='Y'
}
else
{
$props.Resolve ='Y'
$props.Reply='N'
}
}
}New-Object PsCustomObject -Property $props
}|
Format-Table -AutoSize | Out-String | Out-File D:\CEP\testlogging.txt
Note:- Cannot use Test-Connection because it throws exception when server wont reply back or doesnot exist and it takes more time to ping.
Thanks.

Suppose it's too late to be of much help but this should resolve the issues you are reporting with Test-Connection.
Test-Connection -ComputerName $IP -Count 1 -ErrorAction SilentlyContinue
That will limit the ping count to 1 and error will be ignored. Then you can work with the object it produces instead of having to parse lines.

Related

How to see the hostname when you ping the server?

I pinged the servers and it is working (it shows me the ip address that could be pinged) but I want it to show the hostname and the ip address.
I tried to incorporate [System.Net.Data.Dns]::GetHostName(), but I don't know where to put it. I am a beginner using PowerShell. I also tried to used -and, but it doesn't work.
I understand how to do it python I just don't know how to translate it to PowerShell.
$columnC = "n1-1mon-i3fp04","n1-1mon-i3fp06","n1-1mon-i3fp07","n1-r-1mon-i3fp09","n1-r-1mon-i3fp10","n1-1mon-i3fp08","n1-1mon-i3fp03","n1-1mon-i3fp02","n1-1mon-i3fp111"
$columnC | % $_ {$Device = Resolve-DnsName -Name $_
$Device.[System.Net.Data.Dns]::GetHostName()
if (test-connection $Device.("IPAddress")) {write-host Device.("IPAddress") "Ping succeeded." -foreground green}
else {write-host $Device.("IPAddress") "Ping failed." -foreground red}}
The result shows an error message like the syntax is wrong. I want it to show both ip address and the hostname.
[edit - Theo pointed out that GetHostByName has been deprecated in favor of GetHostEntry. when i tested that, it gave more consistent results, so i swapped them.]
this will get the ComputerName, HostName, and Online status. then save those into a custom object, send the object to the $Results collection, and - finally - show what is in the collection. [grin]
# fake reading in a text file
# in real life use Get-Content
$ComputerList = #'
BetterNotBeThere
LocalHost
10.0.0.1
127.0.0.1
'# -split [environment]::NewLine
$Results = foreach ($CL_Item in $ComputerList)
{
try
{
$HostName = [System.Net.Dns]::GetHostEntry($CL_Item).HostName
}
catch
{
$HostName = '__Not Found__'
}
[PSCustomObject]#{
ComputerName = $CL_Item
HostName = $HostName
Online = Test-Connection -ComputerName $CL_Item -Count 1 -Quiet
}
}
$Results
output ...
ComputerName HostName Online
------------ -------- ------
BetterNotBeThere __Not Found__ False
LocalHost [MySysName] True
10.0.0.1 __Not Found__ False
127.0.0.1 [MySysName] True

Powershell function returning an array instead of string

i'm importing a csv and i would like to add a column to it (with the result based off of the previous columns)
my data looks like this
host address,host prefix,site
10.1.1.0,24,400-01
i would like to add a column called "sub site"
so I wrote this module but the problem is, the actual ending object is an array instead of string
function site {
Param($s)
$s -match '(\d\d\d)'
return $Matches[0]
}
$csv = import-csv $file | select-object *,#{Name='Sub Site';expression= {site $_.site}}
if I run the command
PS C:\>$csv[0]
Host Address :10.1.1.0
host prefix :24
site :400-01
sub site : {True,400}
when it should look like
PS C:\>$csv[0]
Host Address :10.1.1.0
host prefix :24
site :400-01
sub site : 400
EDIT: I found the solution but the question is now WHY.
If I change my function to $s -match "\d\d\d" |out-null I get back the expected 400
Good you found the answer. I was typing this up as you found it. The reason is because the -match returns a value and it is added to the pipeline, which is all "returned" from the function.
For example, run this one line and see what is does:
"Hello" -match 'h'
It prints True.
Since I had this typed up, here is another way to phrase your question with the fix...
function site {
Param($s)
$null = $s -match '(\d\d\d)'
$ret = $Matches[0]
return $ret
}
$csv = #"
host address,host prefix,site
10.1.1.1,24,400-01
10.1.1.2,24,500-02
10.1.1.3,24,600-03
"#
$data = $csv | ConvertFrom-Csv
'1 =============='
$data | ft -AutoSize
$data2 = $data | select-object *,#{Name='Sub Site';expression= {site $_.site}}
'2 =============='
$data2 | ft -AutoSize

How to Get The Real RecordData from DnsServerResourceRecord Using Powershell?

I'm using PowerShell to extract information from an Active Directory DNS server and I'm having trouble getting to the data I want.
Specifically, I'm trying to get the names of hosts that belong to a particular subnet, 10.104.128.x.
When I use the following commands:
Get-DnsServerResourceRecord -ComputerName AD_DNS_SERVER -ZoneName 104.10.in-addr.arpa -RRType Ptr | Where-Object {$_.HostName -like '*.128'}`
I get output that looks like this:
HostName RecordType Timestamp TimeToLive RecordData
-------- ---------- --------- ---------- ----------
104.128 PTR 10/19/2015 3:00:0... 00:15:00 adl5c260a86ba79.XYZ.net.
11.128 PTR 12/29/2015 6:00:0... 00:15:00 adl3c970e8d7166.XYZ.net.
110.128 PTR 1/29/2012 11:00:0... 00:15:00 nroxitow7tst.ABC.com.
114.128 PTR 1/20/2012 7:00:00 AM 00:15:00 adl5c260a86c29e.ABC.com
What I really want are the first column, (HostName), which has the last two octets of the IP; and the fifth column, (RecordData), which has the name of the host the IP is assigned to.
The hostname is the data I really want/need. And I see it right there!
So I used the select command to pare down the output in the pipe train. New command looks like this:
Get-DnsServerResourceRecord -ComputerName AD_DNS_SERVER -ZoneName 104.10.in-addr.arpa -RRType Ptr | Where-Object {$_.HostName -like '*.128'} | select HostName, RecordData
But the output looks like this:
HostName RecordData
-------- ----------
104.128 DnsServerResourceRecordPtr
11.128 DnsServerResourceRecordPtr
110.128 DnsServerResourceRecordPtr
114.128 DnsServerResourceRecordPtr
Dosen't get me the hostname though. Just the type of object the RecordData is but not the data that the object contains, perhaps?
I also tried piping the output to CSV and got the same result.
Then I tried looking at the DnsServerResourceRecord object properties with Get-Member. That showed me the object had a property called PSComputerName. I thought maybe that would have the name of the host but that came up blank when I tried to select it.
I then Googled around a bit and found a few pages that recommended a few ways to use RecordData.ipv4address to coax the data out of the DnsServerResourceRecordPtr object but I haven't gotten any of them to work yet. Output still prints blanks.
So my question is: does a reliable method exist for getting the actual hostname from a PTR record?
To select the PtrDomainName property from the DnsServerResourceRecordPtr object, use a calculated property:
... |Select-Object HostName, #{Name='RecordData';Expression={$_.RecordData.PtrDomainName}}
Yes it's really weird that you can't just call ToString on the DNS record data, it's all formatted using the PowerShell formatters which you can only access with Format-List or Format-Table, rather than just calling $resourceRecord.RecordData.ToString().
I've added more data types than Krzysztof Madej by just hacking out the PowerShell formatters from the XML file, the details are here.
http://david-homer.blogspot.com/2020/10/getting-text-representation-of.html
$dnsserver = "yourowndnsserver"
$dnszones = Get-DnsServerZone -ComputerName $dnsserver | Select-Object ZoneName
ForEach ($zone in $dnszones) {
$data = New-Object System.Object
$ZoneName = $zone.ZoneName
$data = Get-DnsServerResourceRecord $ZoneName -ComputerName $dnsserver
foreach ($registros in $data) {
$data = $ZoneName
$data += ","
$data += $registros.hostname;
$data += ","
$data += $RecordType = $registros.recordType;
$data += ","
if ($RecordType -like "PTR") {
$data += $registros.RecordData.PtrDomainName
}
elseif ($RecordType -like "A") {
$data += $([system.version]($registros.RecordData.ipv4address.IPAddressToString));
}
elseif ($RecordType -like "CNAME") {
$data += $registros.RecordData.HostNameAlias;
}
elseif ($RecordType -like "NS") {
$data += $registros.RecordData.nameserver;
}
elseif ($RecordType -like "MX") {
$data += $registros.RecordData.MailExchange;
}
elseif ($RecordType -like "SOA") {
$data += $registros.RecordData.PrimaryServer;
}
elseif ($RecordType -like "SRV") {
$data += $registros.RecordData.DomainName;
}
$data | out-file -FilePath $env:TEMP\$(Get-Date -Format dd_MM_yyyy)_DNSRecords.csv -Append
}
}

Resolve-DNSName for Windows 2008

I have a script working for Windows 2012 (PowerShell v4) but it has to work also for Windows 2008 (PowerShell v2), what is the equivalent of the cmdlet "Resolve-DNSName" for Windows 2008?
Resolve-DnsName -Name client01 -Server server01
I know it exists the same for nslookup and this is what I would like as a cmdlet (one-liner, with no input required from my part)
nslookup
server server01
client01
The following works for DNS resolution but is missing the -server parameter :
[Net.DNS]::GetHostEntry("MachineName")
Thanks
Unfortunately there isn't a way to do this natively in powershell prior to Version 4 in Windows 8.1 or Server 2012. There are .NET methods however:
https://stackoverflow.com/a/8227917/4292988
The simplest solution in powershell is to call nslookup, and cleanup the output
&nslookup.exe client01 server01
I removed select-string from the original sample, it left less to work with
The function you posted following mine doesnt work very well, and will never work in PowershellV2, [PSCustomObject] wasn't supported until v3. Furthermore if you send a dns query that would normally return a single address, it returns nothing. For queries with aliases, it returns the aliases where the ipaddress should be. Test Resolve-DnsName2008 -name www.stackoverflow.com -server 8.8.8.8.
The Following is a function that should do what your asking, at least for ipv4addresses:
function Resolve-DnsName2008
{
Param
(
[Parameter(Mandatory=$true)]
[string]$Name,
[string]$Server = '127.0.0.1'
)
Try
{
$nslookup = &nslookup.exe $Name $Server
$regexipv4 = "^(?:(?:0?0?\d|0?[1-9]\d|1\d\d|2[0-5][0-5]|2[0-4]\d)\.){3}(?:0?0?\d|0?[1-9]\d|1\d\d|2[0-5][0-5]|2[0-4]\d)$"
$name = #($nslookup | Where-Object { ( $_ -match "^(?:Name:*)") }).replace('Name:','').trim()
$deladdresstext = $nslookup -replace "^(?:^Address:|^Addresses:)",""
$Addresses = $deladdresstext.trim() | Where-Object { ( $_ -match "$regexipv4" ) }
$total = $Addresses.count
$AddressList = #()
for($i=1;$i -lt $total;$i++)
{
$AddressList += $Addresses[$i].trim()
}
$AddressList | %{
new-object -typename psobject -Property #{
Name = $name
IPAddress = $_
}
}
}
catch
{ }
}
I use this code to input FQDNs one per line and output respective IPs.
$Server = Get-Content servers.txt
$OutArray = #()
$output = foreach ($Server in $Server) {
$IP = [System.Net.Dns]::GetHostAddresses($Server)
$OutArray += $Server + " " + $IP.IPAddressToString
}
$OutArray | Out-File IPs.txt
The problem is that if I use :
&nslookup.exe client01 server01 | select-string "Name", "Addresses"
It will only display the first record, in my case I had 5 records found and only one displayed.
The solution I found works very well :
function Resolve-DNSName2008
{
Param
(
[string]$Name,
[string]$Server
)
$nslookup = &nslookup.exe $Name $Server
$name = [string]($nslookup | Select-String "Name")
$nameClean = ([regex]::match($name,'(?<=:)(.*\n?)').value).Trim()
$addresses = (([regex]::match($nslookup,'(?<=Addresses:)(.*\n?)').value).Trim()).Split(' ')
$addressesClean = $addresses.Split('',[System.StringSplitOptions]::RemoveEmptyEntries) | Sort-Object
$addressesClean | %{
[PSCustomObject]#{
Name = $nameClean
IPAddress = $_
}
}
}
Usage:
Resolve-DNSName2008 -Name server.domain.com -Server 10.0.0.0
Output:
Name IPAddress
---- ---------
server.domain.com 10.0.0.1
server.domain.com 10.0.0.2
server.domain.com 10.0.0.3
server.domain.com 10.0.0.4
server.domain.com 10.0.0.5

getting two ipaddress from the same FQDN

I am trying to get a list of IP addresses from several servers defined in server.txt.
Each server has 2 IP addresses and 2 FQDN.
Example:
servername (Production lan):server1 IPaddress:147.111.111.16
servername (backup lan):server1-bck IPaddress:10.0.4.12
Here is the code I'm using:
$servers = Get-Content server.txt
$server2 = "$servers-bck"
$zai = ""
foreach ($server in $servers)
{
$zai = $zai + $server + "`t" +
([System.Net.Dns]::GetHostAddresses($server) | foreach {echo $_.IPAddressToString}) +
"`t" +
([System.Net.Dns]::GetHostAddresses($server2) | foreach {echo $_.IPAddressToString}) +
"`n"
}
$zai > IP-address.csv
Unfortunately only the IP for Production lan is correct. The IP for backup lan only shows the IP of the last server in server.txt. I assume the problem is in: "foreach { echo $._IPAddressToString". I don't know how to fix it.
Any idea or advice will be helpful.
You seem to assume that
$server2="$servers-bck"
would append -bck to the name of each element in the array $servers. That is not the case. Instead, the array is expanded by joining its elements using the output field separator, so that -bck ends up after the last array element:
PS C:\> $a = 'a', 'b', 'c'
PS C:\> $a
a
b
c
PS C:\> "$a-bck"
a b c-bck
To get the backup server for each server from your list you need to append -bck inside the loop:
...([System.Net.Dns]::GetHostAddresses("$server-bck"))...
As a side-note, you shouldn't build CSVs manually. Let PowerShell do that for you:
$servers | % {
New-Object -Type PSObject -Property #{
'Name' = $_
'Production' = ([Net.Dns]::GetHostAddresses($_) | select -Expand IPAddressToString) -join ' '
'Backup' = ([Net.Dns]::GetHostAddresses("$_-bck") | select -Expand IPAddressToString) -join ' '
}
} | Export-Csv 'IP-address.csv' -NoType -Delimiter "`t"