[System.Net.Dns]::GetHostbyAddress COMPARE strings - powershell

I have a CSV file with hostnames and their IP addresses and I've to deploy something on them but, I can only use their IP addresses.
So I need to confirm if the IP address stills matching the hostname before start the deployment.
I wrote this script but is not doing what I expected...
Anyone can see where is the problem?
Thanks
$computerName = 'testName'
$computerIP = '192.168.32.148'
$var1 = [System.Net.Dns]::GetHostbyAddress("$computerIP").hostname
if ($var1 -like $computerName) {
"$computerName IS LIKE $var1"
}else{
"$computerName NOT LIKE $var1"
}
OUTPUT
testName NOT LIKE testName.mycompany.net
DESIRED OUTPUT
testName IS LIKE testName.mycompany.net

-like uses exact wildcard matching, and you're not using any wildcards in your -like operation!
Try this:
if ($var1 -like "$computerName*") {
"$computerName IS LIKE $var1"
}else{
"$computerName NOT LIKE $var1"
}
(Notice the * after the $computerName value)
For more information about wildcard matching, check out Get-Help about_Wildcards

Related

PowerShell If statement not equating properly

What am I doing wrong here?
Why do the 2 variables not equal each other?
When I run this script
$temp1 = "#{Dhcp=Disabled}"
$temp2 = Get-NetIPInterface My_Ethernet | select Dhcp
write-host ""
write-host "1" $temp1
write-host "2" $temp2
write-host ""
if ($temp2 -eq $temp1){
write-host "IP address is Static "
}
Else {
write-host "IP address is Not Static"
}
I get this result
1 #{Dhcp=Disabled}
2 #{Dhcp=Disabled}
IP address is Not Static
With the helpful suggestion from Mathias this is now working as expected
$temp1 = "Disabled"
$temp2 = Get-NetIPInterface My_Ethernet | select Dhcp
write-host ""
write-host ""
write-host "1" $temp1
write-host "2" $temp2.dhcp
write-host ""
write-host ""
if ($temp2.dhcp -eq $temp1){
write-host "IP address is Static "
}
Else {
write-host "IP address is Not Static"
}
Just to complement your own effective solution:
Since your intent was to compare a property's value to another value, select -ExpandProperty Dhcp would have returned that value directly (see the docs for Select-Object):
if ((Get-NetIPInterface My_Ethernet | select -ExpandProperty Dhcp) -eq $temp1) { # ...
However, it would be much simpler to use direct property access, using ., the member-access operator:
if ((Get-NetIPInterface My_Ethernet).Dhcp -eq $temp1) { # ...
Note that .Dhcp would work even if your Get-NetIPInterface call returned multiple objects, in which case an array of values is returned, courtesy of PowerShell's member-access enumeration feature.[1]
Finally, note that Write-Host is typically the wrong tool to use, unless the intent is to write to the display only, bypassing the success output stream and with it the ability to send output to other commands, capture it in a variable, or redirect it to a file. To output a value, use it by itself; e.g. $value, instead of Write-Host $value (or use Write-Output $value); see this answer.
To explicitly print only to the display but with rich formatting, use Out-Host, given that the .ToString() stringification that Write-Host uses on its input is often unhelpful - see this post.
[1] Note that PowerShell's comparison operators such as -eq exhibit filtering behavior when their LHS is an array (collection); that is, instead of returning $true or $false, they then return the sub-array of matching elements - see about_Comparison_Operators.

Foreach loop in powershell with hasharray

I'm writing a powershell script to ping all the servers and check which are offline. but i have a bug. By name it works perfectly. But when i do test-connection with an IP it seems to work BUT i cant output the name of the IP in the hashlist. Could someone help me figure this out? Thanks!!
System.Collections.Hashtable.keys Is online/available, This is what it outputs. But i want it to say "Servername is online/available"
#Creating IP Array list
$ip_array = #{
Server = [ipaddress] "192.168.1.1"
sws = [ipaddress] "192.168.1.1"
}
Foreach ($ip in $ip_array)
{
if((Test-Connection -IPAddress $ip.values.ipaddresstostring -quiet -count 1 ) -eq $false)
{
write-output("$ip.keys Is offline/unavailable, please troubleshoot connection, script is terminating") | Red
}
else
{
$ping = $true
write-output("$ip.keys Is online/available") | Green
}
}
PowerShell's default pipeline semantics (any collection that can be enumerated and unraveled will be) makes dictionaries a pain to work with - piping them anywhere would result in a list of disjoint key-value-pairs, dictionary itself lost.
For this reason, PowerShell refuses to automatically enumerate dictionaries, and you must manually obtain an enumerator in order to loop over the entries in it:
foreach($entry in $ip_hash.GetEnumerator()){
# reference `$entry.Key` or `$entry.Name` for the key (eg. Server)
# reference `$entry.Value` for the value (eg. 192.168.1.1)
}
If you really intend to use a Hashtable for this, combining IP addresses with computernames, change to something like this:
# creating IP Hashtable
$ip_hash = #{
'192.168.1.1' = 'Server1'
'192.168.1.2' = 'Server2'
# etcetera
}
# loop through the hash, key-by-key
foreach ($ip in $ip_hash.Keys) {
$ping = Test-Connection -ComputerName $ip -Quiet -Count 1 -ErrorAction SilentlyContinue
if(!$ping) {
Write-Host "Server $($ip_hash[$ip]) is offline/unavailable, please troubleshoot connection, script is terminating" -ForegroundColor Red
}
else {
Write-Host "Server $($ip_hash[$ip]) is online/available" -ForegroundColor Green
}
}
Output would look like:
The Keys in the hash must all have unique values

Script to search several servers for connected client IP addresses

I'm trying to make a Powershell script to search 5 servers for connected client's IP addresses. There are 5 servers and clients are connected via a user tunnel and an asset one. I'm trying to make a looping script that asks for the asset number and username then searches all 5 servers then reports back the tunnel IPs.
My Powershell skills are very rudimentary. I've managed to make a script that mostly works, the trouble I seem to be having is getting the script to report negative results properly. Here's where I am so far:
Clear-Host
$continue = $true
while ($continue){
Write-Host "Tunnel IP finder" -ForegroundColor White
$Asset = Read-Host "Enter asset number"
$AssetAddress = "$asset.corporate.domain.com"
$User = Read-Host "Enter Username"
$Username = "$User#domain.com"
$servers = "RRAS_01","RRAS_02","RRAS_03","RRAS_04","RRAS_05"
Write-Host ""
$data1 = Foreach ($Server1 in $Servers)
{
Get-RemoteAccessConnectionStatistics -computername $Server1 | Where {$_.UserName -eq $AssetAddress} | Select ClientIPAddress | findstr /r "[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*"
}
foreach($item1 in $data1){
if($item1.length -gt 1){
Write-Host "Asset tunnel IP is $item1"-ForegroundColor Green}
}
if($item1.length -LT 1){
Write-Host "Unable to locate asset on RRAS servers"-ForegroundColor yellow
}
$data2 = Foreach ($Server2 in $Servers)
{
Get-RemoteAccessConnectionStatistics -computername $Server2 | Where {$_.UserName -eq $Username} | Select ClientIPAddress | findstr /r "[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*"
}
foreach($item2 in $data2){
if($item2.length -gt 1){
Write-Host "User tunnel IP is $item2"-ForegroundColor Green}
}
if($item2.length -lt 1){
Write-Host "Unable to locate user on RRAS servers"-ForegroundColor yellow
}
Write-Host ""
}
When I search for an asset number and username of someone who is connected it is reporting the results back like this:
Tunnel IP finder
Enter asset number: N02312
Enter Username: SmithJ
Asset tunnel IP is 10.120.xxx.xxx
User tunnel IP is 10.120.xxx.xxx
AOVPN Tunnel IP finder
Enter asset number:
Which is what I was looking to achieve, it displays the IPs and loops to enter more if needed, however when I input details that is not currently connected I get:
Tunnel IP finder
Enter asset number:
Enter Username:
AOVPN Tunnel IP finder
Enter asset number:
It's not reporting the negative results. When I take the scripting off and just have it dump what it thinks $item1/2 is supposed to be it prints nothing, so as far as I can tell $item1/2.length -LT 1 should be doing it.
I've tried experimenting with Else and Elseif, but I can't seem to make those work. There are probably better ways of doing this, but my Powershell is still very basic.
Any help would be greatly appreciated.
Thanks in advance.
It seems if you loop through a collection that has $null value the $item.length will be equal to 1, not to 0 and its value will not be equal to $null. Maybe that´s what happening to you.
PS C:\Windows\System32\WindowsPowerShell\v1.0> $x = $null
PS C:\Windows\System32\WindowsPowerShell\v1.0> $x.length
0
PS C:\Windows\System32\WindowsPowerShell\v1.0> $arr = {$null}
PS C:\Windows\System32\WindowsPowerShell\v1.0> $arr.length
1
PS C:\Windows\System32\WindowsPowerShell\v1.0> $arr | % {$_.length}
1
PS C:\Windows\System32\WindowsPowerShell\v1.0> $arr | % {$_ -eq $null}
False
In your code you only check for the length to be either less or greater than 1 so in the case of the length being equal to 1 it would not print anything. Since the $null check doesnt work I think the best option would be to change the second comparison operator to less or equal instead of less than:
if($item1.length -LE 1){
Write-Host "Unable to locate asset on RRAS servers"-ForegroundColor yellow
}

Comparing multiple email address using powershell match

I have a CSV file of 2000 email addresses. I am using PowerShell to check if the user is active in AD. Another developer wrote a PowerShell script for me to do this but he only used the main domain for the email format to match, he didn't add the subdomian that it could have. Some of our email addresses have a 3 part email address after the # symbol.
For example, his code:
foreach ($user in $users) {
Write-Host $user.email
if ($user.email -match "\#mycompany\.com$") {
$status = "NOT FOUND"
# loop through possible AD domains until there is a hit
foreach ($domain in "na","au","eu","as") {
if ($status -eq "NOT FOUND") {
Write-Host " $($domain)" -NoNewline
$status = Get-UserFromEmail -EMail $user.email -ADDomain $domain
Write-Host $status
}
else {
break
}
}
Write-Host
Add-Content -Path $outcsv -Value "$($user.email),$($user.type),`"$($status)`""
}
else {
Add-Content -Path $outcsv -Value "$($user.email),$($user.type),NOT MYCOMPANY"
}
What I need to be able to do is get the match to check if it is a two or three part email address.
#consultant.mycompany.com or #mycompany.com.
Any insight for this PowerShell newbie would be appreciated.
here is one way to test for membership in more than one email domain. all of the domains are all in the same example.com, but they could easily be in testing.com or wizbang.org.
this demos the idea, i presume you can insert it into your script as needed. [grin]
what it does ...
builds a list of email addresses to test
you will get that from your source ... just be sure they are plain strings, not a string inside a property of an object.
builds a domain list
uses the built in regex escape method to escape things like dots as they are needed
adds a $ to the end of each escaped string to anchor the pattern to the end of the email address
uses the escaped strings to build a regex OR of that list
iterates thru the email address list and gets the ones that match one of the domain list items
saves the matches to a $Var
displays the content of that $Var on screen
the code ...
$EmailList = #(
'ABravo#example.com'
'BCharlie#more.example.com'
'CDelta#example.com'
'DEcho#zigzag.papers.com'
'EFoxtrot#even.more.example.com'
)
$DomainList = #(
'#example.com'
'#more.example.com'
'#even.more.example.com'
)
$Regex_DL = $DomainList.ForEach({
[regex]::Escape($_) + '$'
}) -join '|'
$ValidEmailAddressList = $EmailList -match $Regex_DL
$ValidEmailAddressList
output ...
ABravo#example.com
BCharlie#more.example.com
CDelta#example.com
EFoxtrot#even.more.example.com
You can always use the -or operator to chain multiple expressions inside the if condition:
if ($user.email -match "\#mycompany\.com$" -or $user.email -match '#consultant\.mycompany\.com$'){
# ...
}
Alternatively, you can construct a regex pattern that'll match both:
if($user.email -match '#(?:consultant\.)?mycompany\.com$'){
# ...
}
If you're ever unsure about how to escape a literal string in a reguar expression, use [regex]::Escape():
PS C:\> [regex]::Escape('#consultant.mycompany.com')
#consultant\.mycompany\.com

Would this work better with loops rather than functions?

The following code works, but I'm interested in knowing if there would have been a more efficient way of writing the script, may be by using loops, or it this is the correct way to write such a script? The problem I had when trying to use loop statements was that I couldn't work out how to put the $Dialog "OK" into a loop where it can then loop back to itself if the IP Address still wasn't valid.
The idea of the script is to get the (first three octets of an) IP address, and see if it's valid (i.e not 0.0.0.0 or 169.254.*) before storing it as a variable, and if it isn't valid to throw a dialog box to give to administrator the opportunity to correct it, and then check again, and so on.
function Check-IP
{
$IPSiteAddress = Get-IPAddress
if ($IPSiteAddress -like "0.*" -or $IPSiteAddress -like "169.254.*") {DialogBox-IP}
}
function Get-IPAddress
{
(Get-WmiObject Win32_NetworkAdapterConfiguration |
Where { $_.IPAddress } |
Select -Expand IPAddress).split('.')[0..2] -join '.'
}
function DialogBox-IP
{
$IPDialog = [System.Windows.Forms.MessageBox]::show( "This computer doesn't have a valid IP Address.
Please correct the IP Address and click OK, or click Cancel to exit.","No Network Connection",1)
if ($IPDialog -eq "OK") {Check-IP} else {exit}
}
Check-IP
$IPSiteAddress = Get-IPAddress
If anyone has a nicer solution or, any thoughts, I'll love to hear them
function Check-IP
{
param ($IPSiteAddress)
return !($IPSiteAddress -like "0.*" -or $IPSiteAddress -like "169.254.*")
}
function Get-IPAddress
{
(Get-WmiObject Win32_NetworkAdapterConfiguration | Where { $_.IPAddress } | Select -Expand IPAddress).split('.')[0..2] -join '.'
}
while (!(Check-IP Get-IPAddress))
{
DialogBox-IP
}