Category Archives: Development

Powershell – ForEach-Parallel

Background

In PowerShell I often find the need to speed things up when having to do querying lots of similar things – usually getting the same stuff from multiple machines. So I ventured out onto the Interwebs and over time slap together a PowerShell module that does parallel processing. I’m not claiming this to be purely my work – I only added and refined it a bit for my needs.

This example works with ‘older’ versions of PowerShell (think version 4/5 and perhaps 3). The latest versions of PowerShell (afaik version 7) now has something like this built in.

Implementation

Using any sort of parallel coding requires a different approach than normal procedural (Start at the top and run code line by line until you get to the end). Basically it is multi-threading but PowerShell ‘out of the box’ has nothing like it. To implement multi threading you need to use ‘runspaces’ which effectively means you are running multiple instances of PowerShell.

The ForEach-Parallel function takes a scriptblock as input. Optionally you can also specify the number of threads used to do the parallel processing.

#ForEach-Parallel.psm1
function ForEach-Parallel {
     param(
         [Parameter(Mandatory=$true,position=0)]
         [System.Management.Automation.ScriptBlock] $ScriptBlock,
         [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
         [PSObject]$InputObject,
         [Parameter(Mandatory=$false)]
         [int]$MaxThreads=5
     )
     BEGIN {
         $iss = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
         $pool = [Runspacefactory]::CreateRunspacePool(1, $maxthreads, $iss, $host)
         $pool.open()
         $threads = @()
         $ScriptBlock = $ExecutionContext.InvokeCommand.NewScriptBlock("param($_)r`n" + $Scriptblock.ToString())
     }
     PROCESS {
         $powershell = [powershell]::Create().addscript($scriptblock).addargument($InputObject)
         $powershell.runspacepool=$pool
         $threads+= @{
             instance = $powershell
             handle = $powershell.begininvoke()
         }
     }
     END {
         $notdone = $true
         while ($notdone) {
             $notdone = $false
             for ($i=0; $i -lt $threads.count; $i++) {
                 $thread = $threads[$i]
                 if ($thread) {
                     if ($thread.handle.iscompleted) {
                         $thread.instance.endinvoke($thread.handle)
                         $thread.instance.dispose()
                         $threads[$i] = $null
                     }
                     else {
                         $notdone = $true
                     }
                 }
             }
         }
     }
 }
 export-modulemember -function ForEach-Parallel 

To make use of this ‘module’ save it to a file named ForEach-Parallel.psm1 and place it in C:\Users\{your user account}\Documents\WindowsPowerShell\modules\ForEach-Parallel

Example

#Example
$computers = 'computer1','computer2','computer3'
 $computers | ForEach-Parallel -MaxThreads 20 -ScriptBlock {
     $computerToPing = $_
     [int]$ResponseTime = 0
     [string]$ResolvedName = ''
     $StepPing = (Test-Connection -ComputerName $computerToPing -Count 1 -ErrorAction SilentlyContinue)
   if ($StepPing -ne $null){
      $ResponseTime = $StepPing.ResponseTime 
   } 
   New-Object psobject -Property @{     
    Name               = $computerToPing     
    ResponseTime       = $ResponseTime                  
   }
 }

Summary

There are a few things to watch out for – like any multi-threading coding. While the code is running there is no indication how far each ‘thread’ is – you have to wait until all of them are done. Threads are independent so they cannot reference each other or even variables in the calling thread.

So.. happy multi-threading.

QuickMon 5.0.10

Just a quick note to mention QuickMon reached version 5.0.10

More advanced Contain string function

Just thought I share this useful function I’ve been using recently to enhance some of my applications to make text/string searching more powerful.

If you want to allow things like ‘and’, ‘or’ and ‘not’ in a text filter this could be useful to you. Additionally I also added keywords for things like ‘matchexactly’, ‘startswith’ and ‘endswith’.

public static class StringCompareUtils
{
  public static bool ContainEx(string source, string findText, bool caseSensitive = false)
  {
    bool found = false;
    string lowerCasefindText = findText.ToLower();
    if (findText.Trim().Length == 0)
    {
      found = true;
    }
    else if (lowerCasefindText.Contains(" and "))
    {
      string[] parts = findText.Split(new string[] { " and ", " AND " }, StringSplitOptions.RemoveEmptyEntries);
      found = true;
      foreach (string part in parts)
      {
        if (!ContainEx(source, part))
        {
          found = false;
          break;
        }
      }
    }
    else if (lowerCasefindText.Contains(" or "))
    {
      string[] parts = findText.Split(new string[] { " or ", " OR " }, StringSplitOptions.RemoveEmptyEntries);
      foreach (string part in parts)
      {
        if (ContainEx(source, part))
        {
          found = true;
          break;
        }
      }
    }
    else
    {
      if (lowerCasefindText.TrimStart().StartsWith("not "))
      {
        found = !source.ContainEx2(findText.TrimStart().Substring(4), caseSensitive);
      }
      else
        found = source.ContainEx2(findText, caseSensitive);
    }
    return found;
  }
  private static bool ContainEx2(this string text, string findText, bool caseSensitive = false)
  {
    string matchText = caseSensitive ? text : text.ToLower();
    string matchFindText = caseSensitive ? findText : findText.ToLower();
    if (matchFindText.ToLower().StartsWith("matchexactly "))
    {
      return text == findText.Substring("matchexactly ".Length);
    }
    else if (findText.ToLower().StartsWith("startswith "))
    {
      return text.StartsWith(findText.Substring("startswith ".Length));
    }
    else if (findText.ToLower().StartsWith("endswith "))
    {
      return text.EndsWith(findText.Substring("endswith ".Length));
    }
    else
    {
      return text.Contains(findText);
    }
  }
}

The default behavior is like the ‘like’ operator (text contains search filter). This allow you to find a string like ‘are’ in ‘You are welcome’. Using this function you can specify a filter like ‘startswith You’ or ‘endswith welcome’.

CodePlex shutting down

So with all good things in life I recently learned that CodePlex is shutting down. This is of course a huge bummer for me as a number of my projects have source code that is hosted there.

Particularly QuickMon would be affected. I’ve already moved the source code repository over to GitHub (https://github.com/RudolfHenning/QuickMon) and will be moving the rest over the coming weeks until the whole project is live there. There is also the problem that all current versions of QuickMon 4 points to CodePlex for checking for new version updates but I’ll release one last version or version 4 pointing to the new repository – hopefully soon.

The rest of my projects will be moved as well as time permits. Wish me luck…

Hiding passwords in (C# App) console

I’m actually a bit surprised that despite .Net/C# being more than 10 years old there is still no native Console.ReadLine() overload that hides the characters you are tying – for when you want to prompt for a password or so. Of course writing your own version to do this is not really difficult but still it would have been nice…

Here is one quick version… in case someone else wants to have one (and is too lazy to create it from scratch) hehe.

 

        private static string GetPwd()
        {
            string pass = "";
            Console.Write("Enter your password: ");
            ConsoleKeyInfo key;

            do
            {
                key = Console.ReadKey(true);

                // Backspace Should Not Work
                if (key.Key != ConsoleKey.Backspace && key.Key != ConsoleKey.Enter)
                {
                    pass += key.KeyChar;
                    Console.Write("*");
                }
                else if (key.Key == ConsoleKey.Backspace) 
                {
                    if (pass.Length > 0)
                        pass = pass.Substring(0, pass.Length - 1);
                    Console.Write("\b \b");
                }
            }            
            // Stops Receving Keys Once Enter is Pressed
            while (key.Key != ConsoleKey.Enter); 
            Console.WriteLine();
            return pass.TrimEnd('\r', '\n'); 
        }

Visual Studio 2013 and 2015 icons

Thanks to VS2015 that happen to have the same icon as VS2013 it can be confusing if you have both installed (side-by-side). So as a simple solution I created my own customized icons based on the standard VS icon that also display the version (shortened). I’m simply sharing it here for other if they like to re-use it.

VS201x

Simply extract somewhere on your local HDD and then customize (create shortcut/pin to taskbar and then properties, Change Icon, browse and select the icon) and whoala!.

Sharing is caring… so they say.

QuickMon 4

Just a quick post to announce the first (official) release of QuickMon 4.

There might be some minor bugs that must be ironed out but the basic product is done.

Have fun.

QuickMon 4 Beta

Heads up folks! A public Beta of QuickMon 4 has been released. Please go to QuickMon to download and play with it.

People that has not seen the Alpha yet would notice some major changes compared to version 3.x. The biggest change it that a Collector (now called Collector host) can contain multiple agents of multiple types all tested together to raise one single alert if needed. Of course you can still use it the old way with a collector host containing only a single agent type and have child collector hosts depending on it.

Another area of big change is that viewing the details of a collector’s state, stats, history, alert details and other info gathered are all placed inside a single view (window). This makes it a lot easier to see what is happening with alerts. This detail view is now also ‘Remote host’ aware so it will run and gather details from a (QuickMon 4) remote host as if it is running on ‘that’ machine.

Ok, go download it and have fun… and report back if you have issues or suggestions.

Calling Soap web service from Desktop app with Windows Authentication

I recently had to create a small proof of concept app that calls a soap web service which must be a bit more secure than just allowing Anonymous access. The Web Service requires Windows Authentication to be enabled (NTLM as main provider) with Anonymous disabled.

Calling this web service should be straight forward as you would expect a Windows (Forms) desktop application to pass any logon details when making network related calls. Unfortunately when using Web Services the call seems to be made ‘Anonymous’ by default using the generated proxy class as created by Visual Studio. Fortunately the solution is straight forward provided you can find it on Google (or any other search engine 😉 )

Without going into the real details of how and why this work here is the solution: You have to add security details to the ‘binding configuration’ of the endpoint of the Web Reference. In short the config must look something like this:

  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
       <binding name="SomeServiceSoap">
                <strong><security mode="TransportCredentialOnly">
                  <transport clientCredentialType="Ntlm" proxyCredentialType="None"
                      realm="" />
                  <message clientCredentialType="UserName" algorithmSuite="Default" />
                </security></strong>
              </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://myserver/webservices/SomeService/SomeService.asmx"
                binding="basicHttpBinding"
                bindingConfiguration="SomeServiceSoap"
                contract="SomeServiceWS.SomeServiceSoap"
                name="SomeServiceSoap" />
    </client>
  </system.serviceModel>

The important part here is the <security> tag and its content. Like explained before on the server side Only ‘Windows Authentication’ must be enabled with the ‘NTLM’ provider as the first provider.

Possibly this can also be done through code but I haven’t tried that yet.

QuickMon HTTP Activation catch

I recently created a test Windows 8 (8.1) VM to just play around and took the opportunity to test the QuickMon install as well. Usually I simply test on my own machine where I know it works already. This is of course not a major problem in itself but it means I’m not testing what will happen to the tool if you install it on a fresh/clean machine.

Surprisingly/luckily just about everything worked first time – not that I expected less (ye ye a bit arrogant I know 😉 ) and I was happy that QuickMon ‘out of the box’ is so good. However…. there is one thing that did not work as expected (ok ok it did not work at all) – The Remote host functionality built into the Windows Service.

This is actually not a QuickMon problem per se – it is a requirement of or dependency on the underlying operating system that the WCF functionality must be available. The remote host functionality of QuickMon uses HTTP Activation which is not installed by default on a new Windows 8 (or probably previous versions) installation.

The ‘fix’ is really simple – simply go to ‘Control Panel’ -> ‘Turn Windows features on or off’ -> .Net Framework 4.5 Advanced Services (or 4.0 if present) -> WCF Services -> check HTTP Activation on. Then do a reboot even though Windows doesn’t ask for it after the install – somehow the functionality does not really work right away. It should then be working provided you checked all the other know issues – like firewalls and stuff.

I’ll see if I can build in some check into the service itself to generate an error (Event log or something) to high-light if this feature is not available on the operating system where it needs to run.

One more thing to add to QuickMon… hehe