Ping then DNS lookup before I purge an asset - powershell
So I am trying to Purge IPs from tool that we use. Before I can purge the assets we need to make sure the host is not pingable and not in DNS. I am new to PS and cant seem to wrap my head around on doing this. Any help is greatly appreciated. I have been doing this as a manual process by pinging the list of IPs and hostnames and doing a nslookup in cmd prompt before selecting the IPs that are needing to be removed. I have about 13k IPs left to do.
Update:
I want to implement this portion into it. Where In cell A it will have the IP
cell B will let me know if it is up or down. And Cell D will let me know if it is DNS aswell. Below is the script I got for pinging and checking if up or down and checking AD to see if the hostname is still in AD. I want it similar to this.. Please excuse my english
$path = ".\results.xls"
$objExcel = new-object -comobject excel.application
if (Test-Path $path)
{
$objWorkbook = $objExcel.WorkBooks.Open($path)
$objWorksheet = $objWorkbook.Worksheets.Item(1)
}
else {
$objWorkbook = $objExcel.Workbooks.Add()
$objWorksheet = $objWorkbook.Worksheets.Item(1)
}
$objExcel.Visible = $True
#########Add Header####
$objWorksheet.Cells.Item(1, 1) = "HostName"
$objWorksheet.Cells.Item(1, 2) = "Result"
$objWorksheet.Cells.Item(1, 3) = "MachineIP"
$objWorksheet.Cells.Item(1, 4) = "Active Directory"
$machines = Get-Content .\machinelist.txt
$row=2
$machines | foreach-object{
$ping = $null
$iname = $null
$machine = $_
$ping = Test-Connection $machine -Count 1 -ea silentlycontinue
$checkAD = try {$comp = Get-ADComputer -Identity $machine -ErrorAction
Stop
if ($comp){"Yes"}else{throw}
}
catch {"No"}
$objWorksheet.Cells.Item($row,4) = $checkAD
if($ping){
$objWorksheet.Cells.Item($row,1) = $machine
$objWorksheet.Cells.Item($row,2) = "UP"
$iname = $ping.IPV4Address.IPAddressToString
$objWorksheet.Cells.Item($row,3) = $iname
$row++}
else {
$objWorksheet.Cells.Item($row,1) = $machine
$objWorksheet.Cells.Item($row,2) = "DOWN"
$row++}
}
Here's a start, using Test-Connection and Resolve-DnsName, assuming you have a list of hosts' IP and name separated by a space, with a carriage return between each host:
$Assets = #"
127.0.0.1 localhost
255.255.255.255 fakehost
"#
$FailedPing = #()
$NoDNS = #()
$Assets -split "`r" | %{
$ipaddress = ($_.split(' ')[0]).trim()
$hostName = ($_.split(' ')[1]).trim()
Write-Host "IP: $ipaddress HOST: $hostName "
Try {
Test-Connection -ComputerName $ipaddress -Count 2 -ErrorAction Stop | Out-Null
}Catch {
$FailedPing += [pscustomobject]#{IP=$ipaddress; HostName = $hostName}
}
Try {
Resolve-DnsName -Name $hostName -ErrorAction Stop | Out-Null
}Catch {
$NoDNS += [pscustomobject]#{HostName = $hostName;Problem = $Error[0].Exception}
}
}
$FailedPing | ft
$NoDNS | ft
Related
Powershell - Show only down IP addresses
Need some help adjusting this code so that it will only provide IP addresses that are not pinging and will be exported to a CSV. Currently, it outputs both up and down IP's and I want to clean up some of the clutter. $ping = (Test-Connection -ComputerName $comp.IPAddress -Count 1 -ErrorAction SilentlyContinue) if($ping) { $status = "Up" } else { $status = "Down" } [pscustomobject]#{ Location = $comp.Location IP = $comp.IPAddress Status = $status } I have tried manipulating the $status variable but haven't had any luck. I am sure it's something very simple, I am just missing it.
# -Quiet means we just return a boolean true / false value $ping = Test-Connection -ComputerName ($comp.IPAddress) -Count 1 -ErrorAction SilentlyContinue -Quiet if(-not $ping) { # we only care about when it's down, so move the logic to return our object here [pscustomobject]#{ Location = $comp.Location IP = $comp.IPAddress Status = 'Down' } }
Aramus, Welcome to SO! Test-Connection returns a Null if the connection is down so... $ping = (Test-Connection -ComputerName $($comp.IPAddress) -Count 1 -ErrorAction SilentlyContinue) if($Null -ne $ping) { $status = "Up" } else { $status = "Down" } Also note the $() around $Comp.IPAddress, this is to insure the parser fetches the IPAddress before running the rest of the command.
Output correct IP
Right now the below script imports info from a CSV file then outputs in a CSV file the computer name, expectedIP, Status, GoodIP, dnsName. This is all through custom PS object. I am currently trying to get an output known as actual IP. I am not quite sure how to pull the IP via the ping function that pings the host name. For instance if the hostname that is being pinged check the IP and returns true or false. How could it output what the actual IP of the server is instead of outputting true or false? Here is the script: $compinfo = import-csv .\compinfo.csv $lookupData = foreach ($comp in $cominfo) { $nslkup = [System.Net.DNS]::GetHostEntry($comp.hname) $ping = (Test-Connection -ComputerName $comp.hname -Count 1 -ErrorAction SilentlyContinue) if ($ping) { $status = "up" } else { $status = "down" } if ($nslkup.AddressList.IPAddressToString -eq $comp.ip) { $ipgood = $true } else { $ipgood = $false } [PSCustomObject]#{ computerName = $comp.hname expectedIp = $comp.ip status = $status goodIp = $ipgood dnsName = $nslkup.hostname } } $lookupData | Export-Csv .\lookups.csv -NoTypeInformation
I appreciate everyone that commented on this. I figured it out. Here is the correct code for anyone else that has this issue in the future. $compinfo = import-csv .\compinfo.csv $lookupData = foreach($comp in $compinfo) { $nslkup = [System.Net.DNS]::GetHostEntry($comp.hname) $ping = (Test-Connection -ComputerName $comp.hname -Count 1 -ErrorAction SilentlyContinue) if($ping) { $status = "up" } else { $status = "down" } if($nslkup.AddressList.IPAddressToString -eq $comp.ip) { $ipgood = $true } else { $ipgood = $nslkup.AddressList.IPAddressToString } [pscustomobject]#{ computerName = $comp.hname expectedIp = $comp.ip status = $status goodIp = $ipgood dnsName = $nslkup.hostname } } $lookupData | export-csv .\lookups.csv -NoTypeInformation Notice I replaced $False with $nslkup.AddressList.IPAddressToString
Configure Smtp Virtual Server in windows Server using Powershell-(Relay,Connection)
Using powershell I have to enable SMTP and Add relay Ip Add connection IPs Set Access Control Authentication I found following code for the above operation $GetSMTP = Get-CimInstance -Namespace "root\MicrosoftIISv2" -Class "IISSMTPServerSetting" -Filter "Name ='SmtpSvc/1'" $RelayIps = #(10,92,32,83,127,0,0,1) $GetSMTP.RelayIpList = $RelayIps Set-CimInstance -InputObject $GetSMTP $GetSMTP $GetSMTP = Get-CimInstance -Namespace "root\MicrosoftIISv2" -Class "IIsIPSecuritySetting" -Filter "Name ='SmtpSvc/1'" $NewConnectionIps = #( "10.92.32.80, 10.92.32.81"; "10.92.32.83,127.0.0.1"; ) $GetSMTP.ipgrant += $NewConnectionIps Set-CimInstance -InputObject $GetSMTP $GetSMTP The above powershell code executed successfully and it list as it is added. But when i connect to smtp server, the following error is throwing I have a found a solution to solve the above issue, To delete the folders inside "C:\inetpub\mailroot" and where i am able to start the default Smtp Virtual Server, but again facing an issue while click smtp vitrual server properties
Loading Feature Installation Modules Import-Module ServerManager Installing Features Add-WindowsFeature SMTP-Server,Web-Mgmt-Console,WEB-WMI Adding Relay , connection IPs and Authentication Basic for SMTP $Networkip =#() $Networks = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName localhost | ? {$_.IPEnabled} foreach($Network in $Networks) { $Networkip = $Network.IpAddress[0] } Adding Relay and Authentication Basic for SMTP $ipblock= #(24,0,0,128, 32,0,0,128, 60,0,0,128, 68,0,0,128, 1,0,0,0, 76,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 2,0,0,0, 1,0,0,0, 4,0,0,0, 0,0,0,0, 76,0,0,128, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 255,255,255,255) $ipList = #() $octet = #() $connectionips=$arg[0] $ipList = "127.0.0.1" $octet += $ipList.Split(".") $octet += $Networkip.Split(".") $ipblock[36] +=2 $ipblock[44] +=2; $smtpserversetting = get-wmiobject -namespace root\MicrosoftIISv2 -computername localhost -Query "Select * from IIsSmtpServerSetting" $ipblock += $octet $smtpserversetting.AuthBasic=1 $smtpserversetting.RelayIpList = $ipblock $smtpserversetting.put() Adding Connection for SMTP $connectionips="10.10.10.10" $checkArray =$connectionips.split(",") if($checkArray -notcontains $Networkip) { $connectionips += ","+$Networkip } $connectionipbuild=#() $ipArray=$connectionips.split(",") foreach ($ip in $ipArray) { $connectionipbuild +=$ip+",255.255.255.255;" } $iisObject = new-object System.DirectoryServices.DirectoryEntry("IIS://localhost/SmtpSvc/1") $ipSec = $iisObject.Properties["IPSecurity"].Value # We need to pass values as one element object arrays [Object[]] $grantByDefault = #() $grantByDefault += , $false # <<< We're setting it to false $ipSec.GetType().InvokeMember("GrantByDefault", $bindingFlags, $null, $ipSec, $grantByDefault); $iisObject.Properties["IPSecurity"].Value = $ipSec $iisObject.CommitChanges() $iisObject = new-object System.DirectoryServices.DirectoryEntry("IIS://localhost/SmtpSvc/1") $ipSec = $iisObject.Properties["IPSecurity"].Value $bindingFlags = [Reflection.BindingFlags] "Public, Instance, GetProperty" $isGrantByDefault = $ipSec.GetType().InvokeMember("GrantByDefault", $bindingFlags, $null, $ipSec, $null); # to set an iplist we need to get it first if($isGrantByDefault) { $ipList = $ipSec.GetType().InvokeMember("IPDeny", $bindingFlags, $null, $ipSec, $null); } else { $ipList = $ipSec.GetType().InvokeMember("IPGrant", $bindingFlags, $null, $ipSec, $null); } # Add a single computer to the list: $ipList = $ipList + $connectionipbuild # This is important, we need to pass an object array of one element containing our ipList array [Object[]] $ipArray = #() $ipArray += , $ipList # Now update $bindingFlags = [Reflection.BindingFlags] "Public, Instance, SetProperty" if($isGrantByDefault) { $ipList = $ipSec.GetType().InvokeMember("IPDeny", $bindingFlags, $null, $ipSec, $ipArray); } else { $ipList = $ipSec.GetType().InvokeMember("IPGrant", $bindingFlags, $null, $ipSec, $ipArray); } $iisObject.Properties["IPSecurity"].Value = $ipSec $iisObject.CommitChanges()
In addition to PonVimal's answer (accepted): This solution uses Get-NetworkAddress function from Indented.NetworkTools If you would like to specify relay for a group of computers instead of single address you can use System.DirectoryServices in a following manner (thanks to this answer as well): $IpRelayList = #("192.168.1.0, 255.255.0.0", "127.3.4.0, 255.255.255.192") #adding relays $iisObject = new-object System.DirectoryServices.DirectoryEntry("IIS://localhost/smtpsvc/1") $relays = $iisObject.Properties["RelayIpList"].Value $bindingFlags = [Reflection.BindingFlags] "Public, Instance, GetProperty" $ipList = $relays.GetType().InvokeMember("IPGrant", $bindingFlags, $null, $relays, $null); #if relay list is empty we are retrieving host subnets and adding to relay $Networkip =#() if($IpRelayList.Count -eq 0) { $Networks = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName localhost | ? {$_.IPEnabled} foreach($Network in $Networks) { $line = Get-NetworkAddress $Network.IpAddress[0] $Network.IpSubnet[0] $line = $line + ", " + $Network.IpSubnet[0] $Networkip += $line } } $ipList = $Networkip + $IpRelayList # This is important, we need to pass an object array of one element containing our ipList array [Object[]] $ipArray = #() $ipArray += , $ipList # Now update $bindingFlags = [Reflection.BindingFlags] "Public, Instance, SetProperty" $ipList = $relays.GetType().InvokeMember("IPGrant", $bindingFlags, $null, $relays, $ipArray); $iisObject.Properties["RelayIpList"].Value = $relays $iisObject.CommitChanges()
In addition to PonVimal's answer (accepted): I also wanted the SMTPSVC service to be automatic and came up with an idempotent script that ensures that the service is not only installed but also set to automatic and started so that any subsequent machine restarts does not require me to manually start the service. # ----- Converting service: "Simple Mail Transfer Protocol" to be automatic from manual ------ $ServiceName= "SMTPSVC" If (Get-Service $ServiceName -ErrorAction SilentlyContinue) { If ((Get-Service $ServiceName).StartType -ne "Automatic") { If ((Get-Service $ServiceName).Status -eq 'Running') { Stop-Service $ServiceName "Stopping $ServiceName" } Else { "ServiceName found, and it is stopped." } Set-Service -Name $ServiceName -StartupType "Automatic" Do{ "Starting service: $ServiceName" sc.exe start "$ServiceName" start-sleep -s 5 $ServiceStatus = (get-service -name $ServiceName) } Until ($ServiceStatus.Status -eq "running") "Service Started: $ServiceName" } If ((Get-Service $ServiceName).Status -eq 'Running') { "`n$ServiceName configured as automatic and running`n" } Else { Do{ "Starting service: $ServiceName" sc.exe start "$ServiceName" start-sleep -s 5 $ServiceStatus = (get-service -name $ServiceName) } Until ($ServiceStatus.Status -eq "running") "Service Started: $ServiceName" } } Else { "$ServiceName not found" } # Test to check if the service is configured correctly and is running If (Get-Service $ServiceName) { If ((Get-Service $ServiceName).StartType -ne "Automatic") { throw "$ServiceName is not configured as automatic" } If ((Get-Service $ServiceName).Status -ne 'Running') { throw "$ServiceName is not running" } "`n$ServiceName configured as automatic and running`n" }
This is actually possible, and more complicated than one might think. This magical relay IP list object has some collection lengths hard-coded into it. Here's part of my script that I used after I figured out that oddity. param( [Parameter(ValueFromRemainingArguments=$true)][object[]]$AllowedIPs ) $SMTPServerWmi = Get-WmiObject IISSmtpServerSetting -namespace "ROOT\MicrosoftIISv2" | Where-Object { $_.name -like "SmtpSVC/1" } $SMTPServerWmi.RelayIpList = #(24,0,0,128, 32,0,0,128, 60,0,0,128, 68,0,0,128, 1,0,0,0, 76,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, $AllowedIPs.Count,0,0,0, 2,0,0,0, ($AllowedIPs.Count + 1),0,0,0, 4,0,0,0, 0,0,0,0, 76,0,0,128, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 255,255,255,255) + $AllowedIPs.ForEach({ $_.Split(".")}) $SMTPServerWmi.Put() If those values aren't correct, the UI may show your IPs and a lot of random junk, crash, or become broken such that you cannot use it to remove the items from the list using the UI.
How can I automate Telnet port checking in Powershell?`
I'm currently trying to put together a script that queries AD for a list of computers, pings the computers to determine which ones are still active, and then telnets into a specific port on all the pingable computers. The output I'm looking for is a full list of pingable computers in AD for which I can't telnet to the said port. I've read these few questions, but they don't quite hit on what I'm trying to do. I just want to see if the telnet connection is successful without entering telnet (or automate the quitting of telnet) and move on to the next machine to test. The AD and pinging portions of my script are set, I'm just stuck here. The things I've tried haven't quite worked as planned. Here is the code for the first parts of the script, if needed: Get-ADComputer -Filter * -SearchBase 'DC=hahaha,DC=hehehe' | ForEach { $computerName = $_.Name $props = #{ ComputerName = $computerName Alive = $false PortOpen = $false } If (Test-Connection -ComputerName $computerName -Count 1 -Quiet) { $props.Alive = $true }
Adapting this code into your own would be the easiest way. This code sample comes from the PowerShellAdmin wiki. Collect the computer and port you want to check. Then attempt to make a connection to that computer on each port using Net.Sockets.TcpClient. foreach ($Computer in $ComputerName) { foreach ($Port in $Ports) { # Create a Net.Sockets.TcpClient object to use for # checking for open TCP ports. $Socket = New-Object Net.Sockets.TcpClient # Suppress error messages $ErrorActionPreference = 'SilentlyContinue' # Try to connect $Socket.Connect($Computer, $Port) # Make error messages visible again $ErrorActionPreference = 'Continue' # Determine if we are connected. if ($Socket.Connected) { "${Computer}: Port $Port is open" $Socket.Close() } else { "${Computer}: Port $Port is closed or filtered" } # Apparently resetting the variable between iterations is necessary. $Socket = $null } }
Here is a complete powershell script that will: 1. read the host and port details from CSV file 2. perform telnet test 3. write the output with the test status to another CSV file checklist.csv remoteHost,port localhost,80 asdfadsf,83 localhost,135 telnet_test.ps1 $checklist = import-csv checklist.csv $OutArray = #() Import-Csv checklist.csv |` ForEach-Object { try { $rh = $_.remoteHost $p = $_.port $socket = new-object System.Net.Sockets.TcpClient($rh, $p) } catch [Exception] { $myobj = "" | Select "remoteHost", "port", "status" $myobj.remoteHost = $rh $myobj.port = $p $myobj.status = "failed" Write-Host $myobj $outarray += $myobj $myobj = $null return } $myobj = "" | Select "remoteHost", "port", "status" $myobj.remoteHost = $rh $myobj.port = $p $myobj.status = "success" Write-Host $myobj $outarray += $myobj $myobj = $null return } $outarray | export-csv -path "result.csv" -NoTypeInformation result.csv "remoteHost","port","status" "localhost","80","failed" "asdfadsf","83","failed" "localhost","135","success"
Powershell Timeout After two Seconds
I'm new to powershell. I read some lines on www.powershell.com. Now I need your help to solve a problem. I want to read the UUID from clients in the Network. Therefore I created a document "pcs.txt" where all PCs are stored. $pc = Get-Content pcs.txt #Read content of file $cred = Get-Credential “domain\user” for ($i=0; $i -lt $pc.length; $i++) { $Result=test-connection -ComputerName $pc[$i] -Count 1 -Quiet If ($Result -eq 'True') { $uuid = (Get-WmiObject Win32_ComputerSystemProduct -ComputerName $pc[$i] -Credential $cred).UUID $Ausgabe=$pc[$i] + ';'+$uuid $Ausgabe } else { $Ausgabe=$pc[$i] + '; UUID nicht erhalten' $Ausgabe } } First I test if the ping works. When the ping works I try to get the uuid. Sometimes I don't get the uuid even if the ping worked. So I would like to code a timeout, which say -> go to next pc when you don't have the uuid after 2 seconds. Can you help me please?
Alas, there is no timeout parameter for Get-WmiObject commandlet. There is a feature request in MS Connect, but it is from 2011 and still open. A workaround, which I haven't tested is available by using System.Management. I'll copy-and-paste it here in case the link goes dead. (And I hate SO answers that only contain links to resouces that may or may not exist...) Function Get-WmiCustom([string]$computername,[string]$namespace,[string]$class,[int]$timeout=15){ $ConnectionOptions = new-object System.Management.ConnectionOptions $EnumerationOptions = new-object System.Management.EnumerationOptions $timeoutseconds = new-timespan -seconds $timeout $EnumerationOptions.set_timeout($timeoutseconds) $assembledpath = "\\" + $computername + "\" + $namespace #write-host $assembledpath -foregroundcolor yellow $Scope = new-object System.Management.ManagementScope $assembledpath, $ConnectionOptions $Scope.Connect() $querystring = "SELECT * FROM " + $class #write-host $querystring $query = new-object System.Management.ObjectQuery $querystring $searcher = new-object System.Management.ManagementObjectSearcher $searcher.set_options($EnumerationOptions) $searcher.Query = $querystring $searcher.Scope = $Scope trap { $_ } $result = $searcher.get() return $result }
I found a good workaround! http://theolddogscriptingblog.wordpress.com/2012/05/11/wmi-hangs-and-how-to-avoid-them/ Here my working code: $pc = Get-Content pcs.txt #FILE FROM THE HARDDISK $cred = Get-Credential “DOMAIN\USER” # for ($i=0; $i -lt $pc.length; $i++) { $Result=test-connection -ComputerName $pc[$i] -Count 1 -Quiet If ($Result -eq 'True') { $WMIJob = Get-WmiObject Win32_ComputerSystemProduct -ComputerName $pc[$i] -Credential $cred -AsJob $Timeout=Wait-Job -ID $WMIJob.ID -Timeout 1 # the Job times out after 1 seconds. $uuid = Receive-Job $WMIJob.ID if ($uuid -ne $null) { $Wert =$uuid.UUID $Ausgabe=$pc[$i] + ';'+$Wert $Ausgabe } else { <#$b = $error | select Exception $E = $b -split (:) $x = $E[1] $Error.Clear() #> $Ausgabe=$pc[$i] + '; got no uuid' $Ausgabe } } else { $Ausgabe='PC not reached through ping.' $Ausgabe } } I hope I can help somebody with that