ping? pong!

Good morning internet!

If you don’t already do this,
you should start reading /r/PowerShell on Reddit.
Many good questions ranging from total beginner to extremely advanced,
and you get to see problems you never knew other people had.

I try to help out there every now and then,
but mostly someone else beats me to it.
No fake internet points for me.

Today, like many times before, someone asked for tips about ping or similar commands,
so I thought I’d do a blog post about different ways to do it, and do some measuring as well!

Let’s start by checking different methods to do this.
In PowerShell there is a well-known command, Test-Connection, that most of use and love.
Simply put, it is equivalent to CMD’s ping, but with added PowerShell glory.

Next up is a somewhat lesser known one, Test-NetConnection.
This command gives you a little bit of different possibilities and results,
like setting target port (for testing stuff like www, ftp..), tracerouting etc.
More info on MS website.

Third (and forth) will be the .net class System.Net.NetworkInformation.Ping

I set up a quick test environment using four external known hosts that reply to ping.
[string[]]$address = '','','',''

And just to make sure all of them are actually available, lets test it first.
$address | foreach {Test-Connection $_ -Count 1}
Well, looks good. Let’s see how much time this takes.
PS> Measure-Command -Expression {$address | foreach {Test-Connection $_ -Count 1}} | Select -ExpandProperty Milliseconds
95 milliseconds.
After doing this 10 times I get between 95 and 105ms.

Does Test-NetConnection beat it? let’s see!
PS> Measure-Command -Expression {$address | foreach {Test-NetConnection $_ }} | Select -ExpandProperty Milliseconds
Whoa! nope, no, njet!
Again, after 10 or so times, average is between 250 and 350ms.
If you are only interested in ping results, avoid this.

So let’s go all in.
We already know using classes are almost always faster,
but it´s not knowledge unless tested.
First up is using good old ping.
PS> Measure-Command -Expression {$address | foreach {[System.Net.NetworkInformation.Ping]::new().Send($_)}} | Select -ExpandProperty Milliseconds
Yupp. It’s faster.
average after 10 tests is 69 to 75ms.

So let’s test one more.
[System.Net.NetworkInformation.Ping]::new() contains a method called SendPingAsync()
Normally, you wait for one ping to return, before sending the next one,
but using async we can send them all at the same time, and just await the results.
This is blazingly fast, but it takes a bit of more code to handle.
As it sends the ping request to a background job,
you have to explicitly tell PowerShell to wait for it to finish.
Let’s try.
PS> Measure-Command -Expression {$a = $address | Foreach {[System.Net.NetworkInformation.Ping]::new().SendPingAsync($_)} ; [Threading.Tasks.Task]::WaitAll($a)} | Select -ExpandProperty Milliseconds
39ms. Again, 10 tries average 39 to 49ms.
After this, you can use your variable ($a in my case) to check the actual status of your servers.

Final result:
1. SendPingAsync() ~40ms
2. Ping() ~75ms
3. Test-Connection ~95ms
4. Test-NetConnection ~347ms

So, is there a point to all this?
Well, I only tested four servers and there was already a massive speed difference.
No go run this test on a park of thousands of servers.

I highly recommend you read Boe Prox blogpost on speedy ping!,
because we all know you can’t have too many tools in your toolbox.

As for me? I think I have to learn how to write code in a blog post.
I wonder if someone has written a blog post about it..

Monday Shorty – Note to self; select-string.

So.. another Monday shorty.
I promised a while ago to make a longer one soon,
and I will.. Big news ahead, but I am not ready to tell you yet.

Anyway, I keep finding that i always have to google or get-help on select-string,
so here´s my note to self:

PS: > gci *.* -Recurse | Select-String -Pattern 'function' | select Path,LineNumber,Line

Path LineNumber Line
---- ---------- ----
PS:\Function\functionTemplate.ps1 3 function $PLASTER_PARAM_FunctionName
PS:\Function\PlasterManifest.xml 5 KTHPlasterFunction
PS:\Function\PlasterManifest.xml 15

Also Todays useful link!

Now hopefully, this is enough to make me remember 🙂


Monday shorty – Whats in that string?

Happy Monday!

Yes, I know, it´s Wednesday, but yesterday was the national day of Sweden so this is, in fact, the first workday of the week.
Let´s just say ‘Monday shorty’ was probably not the most thought through topic I could have chosen.

How many times have you seen this?
PS:\> $string
PS:\> $string -eq 'abc'

Or maybe even this?
PS:\> '^C' -eq '^C'

I know I have run in to it a lot of times,
And I have also answered the question on both Facebook and Reddit,
so Here is my solution to the question:
‘What´s in that string?’

Simply convert it to a char array,
and pipe it to a foreach loop converting each char in the array to an int!
PS:\> $string.ToCharArray() | ForEach-Object -Process {[int][char]$_}

Ok, I understand if you don’t speak int fluently,
So Here is Wikipedia’s list of ASCII chars.
And lo and behold, a trailing space!

Oh, the other one? Those are, after all, the same characters, right?
PS:\> '^C'.ToCharArray() | ForEach-Object -Process {[int][char]$_}
PS:\> '^C'.ToCharArray() | ForEach-Object -Process {[int][char]$_}

Simple, but useful, just how I like it.

See you next “Monday”


Monday Shorty – The wonderful world of DateTime.

Regularity is a good thing, and much needed when starting a blog,
so I was hoping to, at least for now, post one thing every week at least.
I have some plans for a longer post, but it is still far from done,
so instead here is a reminder to myself.

-update: Yes, yes, it took me two weeks to do a monday shorty.. sometimes stuff happens 😀

I often get files in random formats that i have to parse and do things with,
Be it reports, statistics, or anything else.
One of the things constantly written in a million ways is dates.
(Dear world, please implement ISO8601)

I was recently given the date format ‘1705221410’, or more specifically ‘yymmddHHMMss’.
so, off course, first try is
PS:> $a = [string]'1705221410'
PS:> Get-Date $a
Get-Date : Cannot bind parameter 'Date'. Cannot convert value "1705221410" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."

.. well that sucks.

Fortunately, there is, off course, a DateTime type. Lets explore it.
PS:\> [system.datetime] | gm -Static

Name MemberType Definition
---- ---------- ----------
Compare Method static int Compare(datetime t1, datetime t2)
DaysInMonth Method static int DaysInMonth(int year, int month)
Equals Method static bool Equals(datetime t1, datetime t2), static bool ...
FromBinary Method static datetime FromBinary(long dateData)
FromFileTime Method static datetime FromFileTime(long fileTime)
FromFileTimeUtc Method static datetime FromFileTimeUtc(long fileTime)
FromOADate Method static datetime FromOADate(double d)
IsLeapYear Method static bool IsLeapYear(int year)
new Method datetime new(long ticks), datetime new(long ticks, System. ...
Parse Method static datetime Parse(string s), static datetime Parse(str ...
ParseExact Method static datetime ParseExact(string s, string format, System ...
ReferenceEquals Method static bool ReferenceEquals(System.Object objA, System.Obj ...
SpecifyKind Method static datetime SpecifyKind(datetime value, System.DateTim ...
TryParse Method static bool TryParse(string s, [ref] datetime result), sta ...
TryParseExact Method static bool TryParseExact(string s, string format, System. ...
MaxValue Property static datetime MaxValue {get;}
MinValue Property static datetime MinValue {get;}
Now Property datetime Now {get;}
Today Property datetime Today {get;}
UtcNow Property datetime UtcNow {get;}

hmm.. looks promising.. A few parse methods to try.
I we look closer at the ParseExact Method we can see the following
(HINT: If you type a method, but remove the parenthesis, you get to see what that specific method requires you to put inside.. the Overload Definitions.)
PS:\> [system.datetime]::ParseExact

static datetime ParseExact(string s, string format, System.IFormatProvider provider)
static datetime ParseExact(string s, string format, System.IFormatProvider provider, System.Globalization.DateTimeStyles style)
static datetime ParseExact(string s, string[] formats, System.IFormatProvider provider, System.Globalization.DateTimeStyles style)

So lets break down what we see here:
There are three ways of using this class, requiring different inputs.
As i only want the conversion to be done, lets look at the first one.
The ParseExact method needs the following arguments in this order:
The string that we would like to parse, in our example ‘1705221410’.
The string to decide what value equals what, again, in our example ‘yyMMddHHmm’

The last one is somewhat more tricky.
System.IFormatProvider is, simply put, a way of saying ‘we need to know how to interpret this’.
Or, as MSDN says it: Provides a mechanism for retrieving an object to control formatting..
Most common I find that what you need here is some kind of cultural info (how to show numbers, dates, separators and such), but the best way to be sure is, as always, search MSDN.

So now we can see that we need one of the following:
A CultureInfo Object
A DateTimeFormatInfo Object
A custom IFormatProvider
‘If provider is null, the CultureInfo object that corresponds to the current culture is used.’
That last one looks good. we do, after all, want to see dates the way we normally do.
So lets try it:
PS:\> [System.DateTime]::ParseExact('1705221410','yyMMddHHmm',$null)

Monday, 22 May, 2017 14:10:00

Success! but you are never satisfied until you know the details, so lets try with different ways of using it as well:
PS:\> [System.DateTime]::ParseExact('1705221410','yyMMddHHmm',[System.Globalization.DateTimeFormatInfo]::CurrentInfo)

Monday, 22 May, 2017 14:10:00

PS:\> [System.DateTime]::ParseExact('1705221410','yyMMddHHmm',[System.Globalization.CultureInfo]::GetCultureInfo('en-US'))

Monday, 22 May, 2017 14:10:00

Both seems to work fine!

So, now that we can do this, lets try it with even stranger strings.
PS:\> [string]$today = 'year 2017 and date 30 and month may and time 9 00'
PS:\> [string]$pattern = '\year yyyy an\d \da\te dd an\d \mon\t\h MMM an\d \ti\me H mm'
PS:\> [DateTime]::ParseExact($today, $pattern, $null)

Tuesday, 30 May, 2017 09:00:00
Awesome. Quite a long Monday shorty, but at least i posted something.
Next time i hope to present a project i am working on.
Nothing fancy, but it is a fun little home project.
Until then, keep coding, and remember:
If you´ve done it twice, it should be automated.

Todays readworthy links:
DateTime.ParseExact Method
DateTimeFormatInfo Class
IFormatProvider Interface