PowerShell – Running Parallel Workflows FAST !

January 9, 2015

Windows Workflows are really great in particular to execute parallel code.

When would you want to use this ?

Let’s take this example, where you want to know all IP addresses of the PC’s in your network.

It you had to scan them 1 by 1 sequentially it would be a SLOW process.

Therefore the new feature of Windows Workflows in PS v3.0 it the tool to use. In combination with the parallel execution parameter.

But you might run in to this error if you are trying to use Parameters in you Workflow statement.

Positional parameters are not supported in a Windows PowerShell Workflow. To invoke this command, use explicit parameter names with all values. For example: “Command -Parameter <value>”.
+ CategoryInfo          : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : PositionalParametersNotSupported

image

It took me a more then an hour to figure out what this meant and another hour to figure out how to correct it.

I ran this code and got the above error ?

CLS

import-module activedirectory

workflow Invoke-ForEachParallel-WF  {

param([string[]]$computerName) 

 # The contents of the foreach block will be executed in parallel
 # look at the keyword -parallel

 foreach -parallel ($computer in $computerName)
 { # "Executing on $computer"
   test-connection -count 1 $computer
  }

}

Invoke-ForEachParallel-WF  (Get-AdComputer -filter {(Name -Like "srv*") } | select name -ExpandProperty name)

Solution :

CLS

import-module activedirectory

workflow Invoke-ForEachParallel-WF  {

param([string[]]$ComputerName) 

 # The contents of the foreach block will be executed in parallel
 # look at the keyword -parallel

 foreach -parallel ($computer in $computerName)
 { # "Executing on $computer"
   test-connection -count 1 -ComputerName $computer
   # Look at the special syntax -ComputerName + variable $computer
  }

}

Invoke-ForEachParallel-WF  (Get-AdComputer -filter {(Name -Like "srv*") } | select name -ExpandProperty name)

Look at the special extra parameter “-ComputerName” value in the foreach code block

The code runs realy fast and will give you this kind of output.

image

Hope this will save you all some time.


PowerShell – Using the .Net Charting Controls

January 4, 2015

Picked this up on the internet Smile Great extension to Powershell and .NET

What you need to get started is the

Microsoft Chart Controls for Microsoft .NET Framework 3.5

The Charting Controls documentation is here :

Microsoft Chart Controls for .NET Framework Documentation

image

Once installed you are ready to go, here is an example script showing the top 5 largest files in a directory.

image

If you hit the “Save button” it will save the graph to the desktop.

Here is the script :

CLS

if([Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization") -eq $null)
{
    #Microsoft Chart Controls are not installed
    [void][reflection.assembly]::Load("System.Windows.Forms, Version=2.0.0.0,`
    Culture=neutral, PublicKeyToken=b77a5c561934e089")
    [void][System.Windows.Forms.MessageBox]::Show("Microsoft Chart Controls for Microsoft .NET 3.5`
    Framework is required", "Microsoft Chart Controls Required")
    #Open the URL
    [System.Diagnostics.Process]::Start("http://www.microsoft.com/downloads/en/`
    details.aspx?familyid=130F7986-BF49-4FE5-9CA8-910AE6EA442C&displaylang=en");
    return $false
}

# load the appropriate assemblies 
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization")

   
# create chart object 
$Chart = New-object System.Windows.Forms.DataVisualization.Charting.Chart 
$Chart.Width = 500 
$Chart.Height = 450
$Chart.Left = 40 
$Chart.Top = 30
   
# create a chartarea to draw on and add to chart 
$ChartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea 
$Chart.ChartAreas.Add($ChartArea)


# add data to chart 
$Files = dir $env:USERPROFILE -Recurse -File | sort length  | select -last 5 # | % {"$_.Name " + [math]::Round(($_.Length / 1MB),2)}
$FileNames = @(foreach($File in $Files){$File.Name}) 
$FileSize = @(foreach($File in $Files){[math]::Round(($File.Length / 1MB),2)}) 


[void]$Chart.Series.Add("Data") 
$Chart.Series["Data"].Points.DataBindXY($FileNames, $FileSize)

# add title and axes labels 
[void]$Chart.Titles.Add("Top 5 Files - Descending") 
$ChartArea.AxisX.Title = "File Name" 
$ChartArea.AxisY.Title = "File Size - [MB]"

# Find point with max/min values and change their colour 
$maxValuePoint = $Chart.Series["Data"].Points.FindMaxByValue() 
$maxValuePoint.Color = [System.Drawing.Color]::Red 

$minValuePoint = $Chart.Series["Data"].Points.FindMinByValue() 
$minValuePoint.Color = [System.Drawing.Color]::Green

# change chart area colour 
$Chart.BackColor = [System.Drawing.Color]::Transparent

# make bars into 3d cylinders 
$Chart.Series["Data"]["DrawingStyle"] = "Cylinder"

# display the chart on a form 
$Chart.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right -bor 
                [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left

# sorting the dataset
$Chart.Series["Data"].Sort([System.Windows.Forms.DataVisualization.Charting.PointSortOrder]::Descending, "Y")

# add a save button 
$SaveButton = New-Object Windows.Forms.Button 
$SaveButton.Text = "Save" 
$SaveButton.Top = 500 
$SaveButton.Left = 450 
$SaveButton.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right 
$SaveButton.add_click({$Chart.SaveImage($Env:USERPROFILE + "\Desktop\Chart.png", "PNG")}) 


# save chart to file 
$Chart.SaveImage($Env:USERPROFILE + "\Desktop\Chart.png", "PNG")

$Form = New-Object Windows.Forms.Form 
$Form.Text = "PowerShell Chart" 
$Form.Width = 600 
$Form.Height = 600 
$Form.controls.add($Chart) 
$Form.Add_Shown({$Form.Activate()}) 

$Form.controls.add($SaveButton)

$Form.ShowDialog()

A good way to start is reading here :

http://blogs.technet.com/b/richard_macdonald/archive/2009/04/28/3231887.aspx

You can build some nifty Tools with this ?

image

Enjoy!


PowerShell – Output to a GUI

January 4, 2015

Ever wanted to get the output of PowerShell to a GUI.

Well that’s not so difficult, since PS is built on top op .NET you can use the .NET Forms Class for this.

This example will capture your Computer Name, and the Process list and display it is a list box.

CLS
 
# add a Listbox
$objListBox = New-Object Windows.Forms.Listbox
$objListBox = New-Object System.Windows.Forms.ListBox
$objListBox.Location = New-Object System.Drawing.Size(15,10)
$objListBox.Size = New-Object System.Drawing.Size(550,10)
$objListBox.Height = 400
 
# add a save button
$oButton = New-Object Windows.Forms.Button
$oButton.Text = "Get Computer Name"
$oButton.Top = 500
$oButton.Left = 350
$oButton.Width = 150
$oButton.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right 
 
$oButton.add_click({$SaveButton.Text = $env:ComputerName})
$oButton.add_click({$objListBox.Items.Add($env:ComputerName)})
 
$oButton.add_click({
 
$sTemp = Get-Process
 
$sTemp | % { $item = $_.ProcessName
$objListBox.Items.Add($item) }
 
})
 
# Build the GUI
$Form = New-Object Windows.Forms.Form
$Form.Text = "PowerShell Output"
$Form.Width = 600
$Form.Height = 600 
 
$Form.Add_Shown({$Form.Activate()}) 
 
$Form.controls.add($oButton)
$Form.controls.add($objListBox)
 
$Form.ShowDialog()
 
rv objListBox, Form, oButton, sTemp, item

When pressing the button it will trigger the actions Winking smile

 

Here are some more Advanced Examples :

Create a Report Builder Gui

Create an SSRS GUI

Create a Ribbon menu GUI

Enjoy!


PowerShell – Manage your Hyper-V virtual machines

December 18, 2014

If you are running a Windows Server 2008 you are missing this crucial PS tool to help you manage your Hyper-V machines.

It was not so easy to first find the proper Hyper-V PS Modules and secondly to get them installed.

1. Download the Hyper-V module

from Codeplex http://PShyperV.codeplex.com

It is a bit strange that MS does not distribute the Module officially. But it does the job well so go ahead.

2. Set-ExecutionPolicy to RemoteSigned

But make sure you open the PS command with elevated credentials !

image

3. Check the policy Get-ExecutionPolicy

Check that the Execution Policy was initialized correctly.

4. DO NOT RUN the install bat files !

Because this will install Powershell and some more features on your windows 2008r2 server.

Instead just use the module from where you extracted it

Import-Module “C:\Temp\HyperV\HyperV.psd1” or different directory where you placed the files from the zip.

image

5. Test it against your live Hyper-V environment.

image

Enjoy!


PowerShell – Accessing MS SQL (CE) Compact Edition

July 1, 2014

When you start working using Webmatrix or Windows Mobile, you might encounter a database format which is SQL CE.

This portable file format is a reduced format of MS SQL and written as an .SDF file.

Microsoft SQL Server Compact 4.0 is a free, embedded database that software developers can use for building ASP.NET websites and Windows desktop applications. SQL Server Compact 4.0 has a small footprint and supports private deployment of its binaries within the application folder, easy application development in Visual Studio and WebMatrix, and seamless migration of schema and data to SQL Server

There are GUI Tools around to access the table and data inside. But I have not seen an ODBC  database driver around to access it. And reuse the data in you application.

That ‘s where PowerShell can come in.

Here is an example to on how to access the data inside the SDF file using native SQL Commands.

Using google you will find a demo database Northwind.sdf easily.

cls
$Host.UI.RawUI.BufferSize = New-Object Management.Automation.Host.Size (500, 25)

$binpath = "C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v4.0\Desktop\";
[Reflection.Assembly]::LoadFile("$binpath\System.Data.SqlServerCe.dll") | out-null

$connString = "Data Source=C:\Northwind.sdf"
$cn = new-object "System.Data.SqlServerCe.SqlCeConnection" $connString

# create the command
$cmd = new-object "System.Data.SqlServerCe.SqlCeCommand"
$cmd.CommandType = [System.Data.CommandType]"Text"
$cmd.CommandText = "SELECT  * FROM Customers"
$cmd.Connection = $cn

#get the data
$dt = new-object "System.Data.DataTable"

$cn.Open()
$rdr = $cmd.ExecuteReader()

$dt.Load($rdr)
$cn.Close()

# $dt | Out-Default | Format-Table
$dt | Out-GridView -Title "My LDF Database Test"

image

When you get an UPGRADE error, using an older version of SDF database file like this.

image

You can use this code to upgrade from version 3.x to 4.x database format

cls

$binpath = "C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\Desktop\";
[Reflection.Assembly]::LoadFile("$binpath\System.Data.SqlServerCe.dll")

$connStringCI = "Data Source=C:\Northwind.sdf; LCID= 1033; Case Sensitive=true;"

#Set "Case Sensitive" to true to change the collation from CI to CS.
$connStringCS = "Data Source='C:\Northwind.sdf'; LCID= 1033; Case Sensitive=true"

$engine = New-Object "System.Data.SqlServerCe.SqlCeEngine" $connStringCI

# The collation of the database will be case sensitive because of
# the new connection string used by the Upgrade method.
$engine.Upgrade($connStringCS)

# $cn = new-object "System.Data.SqlServerCe.SqlCeConnection" $connStringCI
# $cn.Open()

For more Tools see shortList here

Enjoy !!


PowerShell – IDE missing on Servers ?!

January 26, 2013

 

On Windows Server 2008R2 this PS IDE is not installed by default ?

So you need to add it the feature yourself.

image

 

Or

Import-Module ServerManager  
Add-Windowsfeature PowerShell-ISE

I hope this helps !