PowerShell In GUI Blog

PowerShell GUI Box Just In A Few Clicks

Protected: test code 2: PowerGUI 2.4 vs IsePack

with one comment

This content is password-protected. To view it, please enter the password below.

Written by Alexander Petrovskiy

May 6, 2011 at 5:15 am

Posted in Powershell

Tagged with

In response to the comment about using IsePack

with one comment

A recommendation for using PowerShellPack’s IsePack Copy-ColoredAsHtml has been made in the comment to my post. I’m not a big fan of this huge package, but this is worth testing for publishing.

I use the same code copy-pasted from an ISE tab:

cls
#region WordPress posting code test
#this is a test of Powershell code coloring
[string]$stringVar1 = "string 1";
[string]$private:stringVar2 = 'string 2';
[string]$script:stringVar3=
@'
string data
'@
[scriptblock]$global:sb = {{Write-Host scriptblock}.Invoke();};
function
write1{Write-Host $stringVar1;}
function private:write2
{param([string]$str2 = '')
Write-Host $str2;}
function script:write3
#this is a function
{
Write-Host $script:stringVar3;
}
function global:Print-SB
{
<#
.SYNOPSIS
This is a code coloring test.
.DESCRIPTION
This test function represents an advanced Powershell function syntax.

.PARAMETER Param
Demonstrates how a scriptblock can be passed as a reference.

.EXAMPLE
PS C:\> Print-SB ([ref]$sb)
#>
[CmdletBinding()]
param(
[Parameter(Position=0, Mandatory=$true)]
[ref]$Param
)
Begin{}
Process{$Param.Value.Invoke()}
End{}
}
write1
private:write2 $private:stringVar2;
script:write3
Print-SB ([ref]$global:sb)
#endregion WordPress posting code test

Below is the result of IsePack code preparation:

cls            
#region WordPress posting code test            
#this is a test of Powershell code coloring            
[string]$stringVar1 = "string 1";            
[string]$private:stringVar2 = 'string 2';            
[string]$script:stringVar3=            
@' string data '@            
[scriptblock]$global:sb = {{Write-Host scriptblock}.Invoke();};            
function            
write1{Write-Host $stringVar1;}            
function private:write2            
{param([string]$str2 = '')            
Write-Host $str2;}            
function script:write3            
#this is a function            
{            
Write-Host $script:stringVar3;            
}            
function global:Print-SB            
{            
 Print-SB ([ref]$sb) #>            
[CmdletBinding()]            
param(            
[Parameter(Position=0, Mandatory=$true)]            
[ref]$Param            
)            
Begin{}            
Process{$Param.Value.Invoke()}            
End{}            
}            
write1            
private:write2 $private:stringVar2;            
script:write3            
Print-SB ([ref]$global:sb)            
#endregion WordPress posting code test

This looks great and very similar to the hand-made colored code from my post. But who has stolen my advanced function’s comment?! 🙂 All the text between <# and C:\> inclusively erased as a cow licked out.

Written by Alexander Petrovskiy

May 5, 2011 at 6:30 pm

Posted in ISE, Powershell, WordPress

Tagged with

WordPress inspired me with ‘Copy a Post’ tool (StatusStrip + ProgressBar)

leave a comment »

Today’s update announced by WordPress motivated me to add a ProgressBar to the same post that is about a StatusStrip. Why? One of two today’s new features is ‘Copy a Post’. What is it? In spite of the availability of that page, I’ll say a little about blogger’s work.

Usually, the PowerShell (or of any programming environment) blogger needs an idea, a time, a code that will be put out and a description. Also, categories and/or tags to make a post visible throughout the Internet.

WordPress provided such a very simple, even boring feature as a copying of existing post. But imagine that on May, 1st I bought a brand new, lightweight Android 2.2 netbook. A great thing for blogging, skyping and facebooking, it was brought to Finland on 2nd and used on the way to see Google maps. How long did I manage not to write a post? I wrote one today, not a post, but a pleasantry great deal of code. Great under these unusual circumstances as a non-Windows/Linux keyboard layout and lack of habitual tools support.

I used some RDP application (demo with no more one host at a time) to connect to my home Windows 7 with Script Editor and ISE. Some key sequences on an Android’s are not habitual, there aren’t such keys as Insert, Home (to a beginning of text string I mean), Del, all Fs (it’s really pity if you use Far or Unreal Commander). The right shift worked as Tab, the left one went weird from time to time, but the vast majority o code was written on Android’s keyboard!

When I was ready to save me first draft accomplished on an Android device, I noticed these features. How do you think whether I was glad or excited after all that fighting with Android OS? The post will be put out later, maybe tomorrow.

And now, this Copy a Post feature again helps me: I thought that there isn’t a reason not to all System.Windows.Forms.ProgressBar example to the very similar StatusBar code. No doubts, Copy a Post is the first I did.

After this long introduction, let’s turn to a sample. I added a progress bar, three radio buttons, two group boxes (to split up radio buttons to two groups) and added some additional code. Should I add more details? If so, please write request in comments.

I’ll simply describe the functions until questions arrived:

– setStatusStrip used for labels and a bar of the $script:stStrip control

– setProgressBar is the same but for a ProgressBar

– createRadioButton creates radio buttons and adds a handler to enable the user set a style to the StatusStrip and ProgressBar

cls
Set-StrictMode -Version Latest
#region $form1
[System.Windows.Forms.Form]$form1 = New-Object System.Windows.Forms.Form;
$form1.Width = 500;
$form1.Height = 500;
[System.Windows.Forms.Button]$btnDirC = New-Object System.Windows.Forms.Button;
$btnDirC.Text = 'dir c:\';
$btnDirC.Left = 300;
$btnDirC.Top = 100;
$btnDirC.add_Click(([System.EventHandler]$handler =
	{
		processDirC;
	}));
$form1.Controls.Add($btnDirC);
[System.Windows.Forms.GroupBox]$script:groupProgressBar = `
	New-Object System.Windows.Forms.GroupBox;
$script:groupProgressBar.Left = 20;
$script:groupProgressBar.Top = 20;
$script:groupProgressBar.Width = 250;
$script:groupProgressBar.Height = 100;
$script:groupProgressBar.Text = "ProgressBar";
[System.Windows.Forms.GroupBox]$script:groupStatusStrip = `
	New-Object System.Windows.Forms.GroupBox;
$script:groupStatusStrip.Left = 20;
$script:groupStatusStrip.Top = 200;
$script:groupStatusStrip.Width = 250;
$script:groupStatusStrip.Height = 150;
$script:groupStatusStrip.Text = "StatusStrip";
$form1.Controls.AddRange(@($script:groupProgressBar, $script:groupStatusStrip));
function processDirC
{
	[int]$maxNumber = (dir c:\).Length;
	setStatusStrip -OperationName $null `
		-OperationProgress $null `
		-ProgressBarMinimum 1 `
		-ProgressBarMaximum $maxNumber `
		-ProgressBarValue 1;
	setProgressBar -ProgressBarMinimum 1 `
		-ProgressBarMaximum $maxNumber `
		-ProgressBarValue 1;
	[int]$counter = 1;
	dir c:\ | `
		%{
          setStatusStrip -OperationName $_ `
			-OperationProgress "$($counter) of $($maxNumber)" `
			-ProgressBarMinimum $null `
			-ProgressBarMaximum $null `
			-ProgressBarValue $counter;
		  setProgressBar  -ProgressBarMinimum $null `
			-ProgressBarMaximum $null `
			-ProgressBarValue $counter;
          [System.Windows.Forms.Application]::DoEvents();
		  sleep -Milliseconds 500;
		  $counter++;
		  }
}
#endregion $form1
#region StatusBar
$form1.Controls.Add(
	(([System.Windows.Forms.StatusStrip]$script:stStrip = `
	#region StatusBar properties
	New-Object System.Windows.Forms.StatusStrip) `
	| %{#at the bottom of the window
		$script:stStrip.Dock = [System.Windows.Forms.DockStyle]::Bottom;
		$script:stStrip.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor `
			[System.Windows.Forms.AnchorStyles]::Left;
		#layout style by default
		$script:stStrip.LayoutStyle = [System.Windows.Forms.ToolStripLayoutStyle]::Table;
		#operation name
		[System.Windows.Forms.ToolStripLabel]$script:stStripLabelOperation = `
			New-Object System.Windows.Forms.ToolStripLabel;
		$script:stStripLabelOperation.Text = "Write the operation name here";
		#which item is being processed
		[System.Windows.Forms.ToolStripLabel]$script:stStripLabelProgress = `
			New-Object System.Windows.Forms.ToolStripLabel;
		$script:stStripLabelProgress.Text = "Write the item number here";
		#the progress bar
		[System.Windows.Forms.ToolStripProgressBar]$script:stStripProgressBar = `
			New-Object System.Windows.Forms.ToolStripProgressBar;
		$script:stStrip.Items.AddRange([System.Windows.Forms.ToolStripItem[]]@(
									$script:stStripLabelOperation,
									$script:stStripLabelProgress,
									$script:stStripProgressBar
									));
		$script:stStrip.Name = "stStrip";
		$script:stStrip.AutoSize = $true;
		$script:stStrip.Left = 0;
		$script:stStrip.Visible = $true;
		$script:stStrip.Enabled = $true;
		$script:stStripLabelOperation.Width = 50;
		$script:stStripLabelProgress.Width = 50;
		$script:stStripProgressBar.Width = 50;
		$script:stStripProgressBar.Visible = $false;
	#endregion StatusBar properties
	$script:stStrip;}
)	);
#endregion StatusBar
#region ToolStripLayoutStyle
	#region function createRadioButton
function createRadioButton
{
	param([string]$ControlName,
		  [ref]$Top
		  )
	$rb = $null;
	[System.Windows.Forms.RadioButton]$private:rb = `
		New-Object System.Windows.Forms.RadioButton;
	$private:rb.Name = $ControlName;
	$private:rb.Text = $ControlName;
	$private:rb.Left = 20;
	$private:rb.Top = ($Top.Value += 20);
	$private:rb.Width = 200;
	$private:rb.add_CheckedChanged(([System.EventHandler]$handler =
	{
		param($sender)
		if ($sender.Checked){
			if ($sender.Parent -eq $script:groupStatusStrip)
			{
				$script:stStrip.LayoutStyle = `
					([System.Windows.Forms.ToolStripLayoutStyle]($sender.Name));
			}
			else
			{
				$script:pgBar.Style = `
					([System.Windows.Forms.ProgressBarStyle]($sender.Name));
			}
		}
	}));
	return $private:rb;
}
	#endregion function createRadioButton
[int]$top = 0;
$script:groupStatusStrip.Controls.AddRange(
	[System.Windows.Forms.Control[]]@(
	(createRadioButton ([System.Windows.Forms.ToolStripLayoutStyle]::Flow.ToString()) ([ref]$top)),
	(createRadioButton ([System.Windows.Forms.ToolStripLayoutStyle]::HorizontalStackWithOverflow.ToString()) ([ref]$top)),
	(createRadioButton ([System.Windows.Forms.ToolStripLayoutStyle]::StackWithOverflow.ToString()) ([ref]$top)),
	(createRadioButton ([System.Windows.Forms.ToolStripLayoutStyle]::Table.ToString()) ([ref]$top)),
	(createRadioButton ([System.Windows.Forms.ToolStripLayoutStyle]::VerticalStackWithOverflow.ToString()) ([ref]$top))
	));
$script:groupStatusStrip.Controls[([System.Windows.Forms.ToolStripLayoutStyle]::Table.ToString())].Checked = $true;
#endregion ToolStripLayoutStyle
#region ProgressBarStyle
[int]$top = 0;
$script:groupProgressBar.Controls.AddRange(
	[System.Windows.Forms.Control[]]@(
	(createRadioButton ([System.Windows.Forms.ProgressBarStyle]::Blocks.ToString()) ([ref]$top)),
	(createRadioButton ([System.Windows.Forms.ProgressBarStyle]::Continuous.ToString()) ([ref]$top)),
	(createRadioButton ([System.Windows.Forms.ProgressBarStyle]::Marquee.ToString()) ([ref]$top))
	));
$script:groupProgressBar.Controls[([System.Windows.Forms.ProgressBarStyle]::Blocks.ToString())].Checked = $true;
#endregion ProgressBarStyle
#region function setStatusStrip
function setStatusStrip
{
	param($OperationName = "",
		  $OperationProgress = "",
		  $ProgressBarMinimum = 0,
		  $ProgressBarMaximum = 0,
		  $ProgressBarValue = 0
		  )
		try{$null = $script:stStrip;
			if ($OperationName -ne $null -and `
				$script:stStripLabelOperation -ne $null)
				{
					$script:stStripLabelOperation.Text = $OperationName;
					$script:stStripLabelOperation.Width = 200;
				}
			if ($OperationProgress -ne $null -and `
				$script:stStripLabelProgress -ne $null)
				{
					$script:stStripLabelProgress.Text = $OperationProgress;
					$script:stStripLabelProgress.Width = 100;
				}
			if ($script:stStripProgressBar -ne $null){
				if ($ProgressBarMinimum -ne $null)
					{$script:stStripProgressBar.Minimum = $ProgressBarMinimum;}
				if ($ProgressBarMaximum -ne $null)
					{$script:stStripProgressBar.Maximum = $ProgressBarMaximum;}
				if ($ProgressBarValue -ne $null)
					{$script:stStripProgressBar.Value = $ProgressBarValue;}
				if ($script:stStripProgressBar.Minimum -eq `
					$script:stStripProgressBar.Maximum)
					{$script:stStripProgressBar.Visible = $false;}
				else
					{$script:stStripProgressBar.Visible = $true;}
			}
		}
		catch{}
}
#endregion function setStatusStrip
#region ProgressBar
[System.Windows.Forms.ProgressBar]$script:pgBar = New-Object System.Windows.Forms.ProgressBar;
$script:pgBar.Left = 100;
$script:pgBar.Top = 150;
$script:pgBar.Visible = $true;
$script:pgBar.Minimum = 1;
$form1.Controls.Add($script:pgBar);
	#region function setProgressBar
function setProgressBar
{
	param($ProgressBarMinimum = 0,
		  $ProgressBarMaximum = 0,
		  $ProgressBarValue = 0
		  )
		try{$null = $script:pgBar;
			if ($script:pgBar -ne $null){
				if ($ProgressBarMinimum -ne $null)
					{$script:pgBar.Minimum = $ProgressBarMinimum;}
				if ($ProgressBarMaximum -ne $null)
					{$script:pgBar.Maximum = $ProgressBarMaximum;}
				if ($ProgressBarValue -ne $null)
					{$script:pgBar.Value = $ProgressBarValue;}
				if ($script:pgBar.Minimum -eq `
					$script:pgBar.Maximum)
					{$script:pgBar.Visible = $false;}
				else
					{$script:pgBar.Visible = $true;}
			}
		}
		catch{}
}
	#endregion function setProgressBar
#endregion ProgressBar
$form1.ShowDialog() | Out-Null;

The code is downloadable as a script from here.

A hand-made script-to-form converter (sooner a sample than a tool)

leave a comment »

With eternal love to automation, I began today a small project aiming to help creation of PowerShell GUI forms. This post is the first step, will or won’t I do the next is not clearly even to me.

A year ago I wrote something like this. It was a PropertiesBrowser module/add-on, which I used as the Watches window, typical of any IDE, sometimes. It hasn’t been published, though.

Having today morning an hour or slightly more, I decided to write a post mostly to test the new smartbook I own the third day, but at the same time I caught what I want. A simple form generator.

How should it work? Almost every script produces an output. Strings, numbers, boolean, objects, all what may return a PowerShell code. Why don’t allow the scripter to put it on a form without an effort? Sound like a GUI modeling tool (but looks much more uglyer).

Here it is, the code giving some output and used as a sample:

cls
Set-StrictMode -Version Latest
Import-Module FormGen -Force

[int]$i = 3;
Set-OutputToForm $i
Set-OutputToForm $i -SuppressLabel $true
Set-OutputToForm $i -Description "int"
$f = New-Object System.Windows.Forms.Form
Set-OutputToForm $f;
$a = @("s", "T");
Set-OutputToForm $a $false "Array"
Get-ChildItem | Select-Object -First 3 | %{Set-OutputToForm $_ -Description "fileinfo of $($_.FullName)";}
1..2 | %{Set-OutputToForm $_;}
Get-ChildItem | Select-Object -First 1 | %{Set-OutputToForm $_ -Description "fileinfo of $($_.FullName)" -ControlType 'System.Windows.Forms.ListView';}
Get-ChildItem | Select-Object -First 1 | %{Set-OutputToForm $_ -Description "fileinfo of $($_.FullName)" -ControlType 'System.Windows.Forms.TreeView';}
Get-ChildItem | Select-Object -First 1 | %{Set-OutputToForm $_ -Description "fileinfo of $($_.FullName)" -ControlType 'System.Windows.Forms.ComboBox';}
Show-Result;

As can be seen, there is the FormGen module and two functions exported from it, Set-OutputToForm and Show-Result. While the former adds data to a form still invisible, the latter, to be used once, displays the form.

Set-StrictMode -Version Latest
[int]$script:topPosition = 0;
[System.Windows.Forms.Form]$script:frmMain = `
	New-Object System.Windows.Forms.Form;
$script:frmMain.Width = 500;

function Set-OutputToForm
{
 Set-OutputToForm $data
			PS> 1..10 | %{Set-OutputToForm $_;}
			PS> Get-ChildItem | %{Set-OutputToForm $_ -SuppressLabel $true; $null;}
		.Notes
			Author: Alexander Petrovskiy
	#>
	[CmdletBinding()]
	param([Parameter(Mandatory=$true,ValueFromPipeline=$true)]
    	  [ValidateNotNullOrEmpty()]
		  $InputObject,
		  [bool]$SuppressLabel = $false,
		  [string]$Description = "",
		  [string]$ControlType = ""
		  )
	Begin{}
	Process{
	[bool]$result = $false;
	try{
		if (-not $SuppressLabel)
		{
			[System.Windows.Forms.Label]$private:label = `
				New-Object System.Windows.Forms.Label;
			$script:topPosition += 10;
			$private:label.Top = $script:topPosition;
			$private:label.Left = 50;
            $private:label.Width = $script:frmMain.Width - 50;
            $private:label.Visible = $true;
			if ($Description.Length -gt 0)
			{
				$private:label.Text = $Description;
			}
            else
            {
                $private:label.Text = $InputObject.GetType().ToString();
            }
			$script:frmMain.Controls.Add($private:label);
			$script:topPosition += $private:label.Height;
		}

		[bool]$private:useCustomControl = $false;
		[System.Windows.Forms.Control]$private:ctrl = `
			New-Object System.Windows.Forms.Control;
		if ($ControlType.Length -gt 0)
		{
			try{[System.Windows.Forms.Control]$private:ctrl =
				New-Object $ControlType;
				$private:useCustomControl = $true;
			}catch{$private:useCustomControl = $false;}
		}
		#of which type these data?
		#an array?
		if ($InputObject -is [System.Array])
		{
			if (-not $private:useCustomControl){
				[System.Windows.Forms.ListBox]$private:ctrl = `
					New-Object System.Windows.Forms.ListBox;}
			for($private:i = 0; $private:i -lt $InputObject.Length;
				$private:i++)
			{
				if ($private:ctrl -is [System.Windows.Forms.ListBox] -or `
					$private:ctrl -is [System.Windows.Forms.ComboBox] -or `
					$private:ctrl -is [System.Windows.Forms.ListView]){
						$private:ctrl.Items.Add($InputObject[$private:i]);}
				if ($private:ctrl -is [System.Windows.Forms.TreeView]){
					$private:ctrl.Nodes.Add($InputObject[$private:i]);}
			}
		}
		#a string? int one? other simple type?
		elseif ($InputObject.GetType().BaseType.Name -eq 'ValueType')
		{
			if (-not $private:useCustomControl){
				[System.Windows.Forms.Label]$private:ctrl = `
					New-Object System.Windows.Forms.Label;}
			if ($private:ctrl -is [System.Windows.Forms.ListBox] -or `
				$private:ctrl -is [System.Windows.Forms.ComboBox] -or `
				$private:ctrl -is [System.Windows.Forms.ListView]){
					$private:ctrl.Items.Add($InputObject.ToString());}
			if ($private:ctrl -is [System.Windows.Forms.TreeView]){
				$private:ctrl.Nodes.Add($InputObject.ToString());}
			if ($private:ctrl -is [System.Windows.Forms.Label] -or `
				$private:ctrl -is [System.Windows.Forms.TextBox]){
					$private:ctrl.Text = $InputObject.ToString();}
		}
		else
		{
			if (-not $private:useCustomControl){
				[System.Windows.Forms.PropertyGrid]$private:ctrl = `
					New-Object System.Windows.Forms.PropertyGrid;}
			if ($private:ctrl -is [System.Windows.Forms.PropertyGrid]){
				$private:ctrl.SelectedObject = $InputObject;}
			if ($private:ctrl -is [System.Windows.Forms.ListBox] -or `
				$private:ctrl -is [System.Windows.Forms.ComboBox] -or `
				$private:ctrl -is [System.Windows.Forms.ListView]){
					$private:ctrl.Items.Add($InputObject.ToString());}
			if ($private:ctrl -is [System.Windows.Forms.TreeView]){
				$private:ctrl.Nodes.Add($InputObject.ToString());}
		}
		#common properties
		$private:ctrl.Left = 50;
		$private:ctrl.Top = $script:topPosition;
		$private:ctrl.Visible = $true;
		$script:frmMain.Controls.Add($private:ctrl);
		$script:topPosition += $private:ctrl.Height;
	}catch{}

	$result = $true;
	return $result;}
	End{}
}

function Show-Result
{
	$script:frmMain.Height = $script:topPosition + 40;
	$script:frmMain.ShowDialog() | Out-Null;
}

Export-ModuleMember -Function Set-OutputToForm, Show-Result;

Need to repeat, this is sooner a concept than a ready-to-use tool, so that use it as is. Probably, I’ll update it. The current version attached here.

Although it’s not an advantage for powershellers, I’m proud that at least a half of this code was written on my Android smartbook. This means that I can write from more places than I could before. I have had for two years a netbook, but without 3G and its keyboard was damaged on travel. Gladly, now I can write on the go again, with the actually mobile device.

WordPress and PowerShell Code. The Second Try

with 4 comments

Last week I complained about how it is not easy to post Powershell code here. The letter of my dissatisfaction has been sent to and the answer was received from the WordPress support.

As a first step of our efforts to improve the code coloration was the question about what is wrong and what I’ve wanted. Of course, I assured the support specialist that I’ll provide so many examples of code that they will be able to polish publishing if they want to. That time the code sample appeared as on the following figure:

Image

This post is the next step. I copy-pasted the WordPress code from my previous post on this topic to LibreOffice Writer 3.3, marked the most of significant blocks of code with several colors and put it back to WordPress page as an HTML.

Below is what I’d expect I might have had in my blog when I use the ‘sourcecode’ tag:

cls
#region WordPress posting code test
#this is a test of Powershell code coloring
[string]$stringVar1 = “string 1”;
[string]$private:stringVar2 = ‘string 2’;
[string]$script:stringVar3=
@’
string data
‘@
[scriptblock]$global:sb = {{Write-Host scriptblock}.Invoke();};
function
write1{Write-Host $stringVar1;}
function private:write2
{param([string]$str2 = )Write-Host $str2;}
function script:write3
#this is a function
{
Write-Host $script:stringVar3;
}
function global:Print-SB
{
<#
.SYNOPSIS
This is a code coloring test.

.DESCRIPTION
This test function represents an advanced Powershell function syntax.

.PARAMETER Param
Demonstrates how a scriptblock can be passed as a reference.

.EXAMPLE
PS C:\> Print-SB ([ref]$sb)
#>
[CmdletBinding()]
param(
[Parameter(Position=0, Mandatory=$true)]
[ref]$Param
)
Begin{}
Process{$Param.Value.Invoke()}
End{}
}
write1
private:write2 $private:stringVar2;
script:write3
Print-SB ([ref]$global:sb)
#endregion WordPress posting code test

I divided all the sample code into several meaningful groups. Although the exact color schema is a subject of possible further discussion, I used some, taken from both Powershell ISE and PowerGUI as an average. Here are groups instructions of the sample were split into.

1) the comments (green) group includes one-string comment beginning with the # sign and a multi-string comment applicable for advanced functions and consisting of all between <# and #> character sequences (sequences are included too).

2) commandlets and commands (some blue-gray color that has been used in the original WordPress’s coloration), and their aliases like Out-Null, Get-ChildItem, dir. There is a fixed list of them. Custom aliases and commandlets are not supposed to be colored due to the fact that WordPress doesn’t run any PS code and it’s completely unaware of new constructs.

3) data types and attributes (light-blue or green-blue) group constitutes of all the code in square parentheses but inner round parentheses.

4) the string data (brown) group is comprised of one-string declarations limited with single quotes or double quotes and a multi-string construction beginning with @’ and finishing at ‘@.

5) variable names (magenta) includes all unquoted string beginning with the $ sign and containing letters, numbers, underlines, question mark and colon. The dot is an end as well as the space.

6) specific words used within function declarations (bright blue). This groups the word function, and the function-related words param, begin, process, end inside curly brackets following the word function.

This color also can be used for statements like foreach, for, switch, if and so on.

7) function names (light lilac) of two types of occurrence: within the function declaration (that is, following the word function) and anywhere in the code. Function names usually contain letters, numbers and colons.

I hope that there is no need to repeat how lucky would be all WordPress Powershell bloggers if the WordPress developing team does the requested.

Written by Alexander Petrovskiy

April 30, 2011 at 5:25 pm

Posted in Powershell, WordPress

Tagged with

StatusStrip. An easy way

leave a comment »

Long operations are among things annoying most. To prevent users from getting bored with application that is mining data or doing multi-change, it’s common to use a kind of progressbar.

Let’s take a StatusStrip control. It’s relatively new control, firstly introduced in .NET 2.0 (or like) and it’s container. This container allows you to add a label, a progress bar and a couple of other controls.

Below is a typical function working with a statusstrip that contains two label and one progress bar. For our purposes, the first label is operation name (the name of an action performed now) and the second is a counter like ‘3 of 87’.

cls
Set-StrictMode -Version Latest
#region $form1
[System.Windows.Forms.Form]$form1 = New-Object System.Windows.Forms.Form;
$form1.Width = 500;
[System.Windows.Forms.Button]$btnDirC = New-Object System.Windows.Forms.Button;
$btnDirC.Text = 'dir c:\';
$btnDirC.Left = 300;
$btnDirC.Top = 100;
$btnDirC.add_Click(([System.EventHandler]$handler = 
	{
		processDirC;
	}));
$form1.Controls.Add($btnDirC);
function processDirC
{
	[int]$maxNumber = (dir c:\).Length;
	setStatusStrip -OperationName $null `
		-OperationProgress $null `
		-ProgressBarMinimum 1 `
		-ProgressBarMaximum $maxNumber `
		-ProgressBarValue 1;
	[int]$counter = 1;
	dir c:\ | `
		%{
          setStatusStrip -OperationName $_ `
			-OperationProgress "$($counter) of $($maxNumber)" `
			-ProgressBarMinimum $null `
			-ProgressBarMaximum $null `
			-ProgressBarValue $counter;
          [System.Windows.Forms.Application]::DoEvents();
		  sleep -Milliseconds 500;
		  $counter++;
		  }
}
#endregion $form1
#region StatusBar
$form1.Controls.Add(
	(([System.Windows.Forms.StatusStrip]$script:stStrip = `
	#region StatusBar properties
	New-Object System.Windows.Forms.StatusStrip) `
	| %{#at the bottom of the window
		$script:stStrip.Dock = [System.Windows.Forms.DockStyle]::Bottom;
		$script:stStrip.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor `
			[System.Windows.Forms.AnchorStyles]::Left;
		#layout style by default
		$script:stStrip.LayoutStyle = [System.Windows.Forms.ToolStripLayoutStyle]::Table;
		#operation name
		[System.Windows.Forms.ToolStripLabel]$script:stStripLabelOperation = `
			New-Object System.Windows.Forms.ToolStripLabel;
		$script:stStripLabelOperation.Text = "Write the operation name here";
		#which item is being processed
		[System.Windows.Forms.ToolStripLabel]$script:stStripLabelProgress = `
			New-Object System.Windows.Forms.ToolStripLabel;	
		$script:stStripLabelProgress.Text = "Write the item number here";
		#the progress bar
		[System.Windows.Forms.ToolStripProgressBar]$script:stStripProgressBar = `
			New-Object System.Windows.Forms.ToolStripProgressBar;
		$script:stStrip.Items.AddRange([System.Windows.Forms.ToolStripItem[]]@(
									$script:stStripLabelOperation,
									$script:stStripLabelProgress,
									$script:stStripProgressBar
									));					
		$script:stStrip.Name = "stStrip";							
		$script:stStrip.AutoSize = $true;
		$script:stStrip.Left = 0;
		$script:stStrip.Visible = $true;
		$script:stStrip.Enabled = $true;
		$script:stStripLabelOperation.Width = 50;
		$script:stStripLabelProgress.Width = 50;
		$script:stStripProgressBar.Width = 50;
		$script:stStripProgressBar.Visible = $false;
	#endregion StatusBar properties
	$script:stStrip;}
)	);
#endregion StatusBar
#region ToolStripLayoutStyle
	#region function createRadioButton
function createRadioButton
{
	param([string]$ControlName,
		  [ref]$Top
		  )
	$rb = $null;
	[System.Windows.Forms.RadioButton]$private:rb = `
		New-Object System.Windows.Forms.RadioButton;
	$private:rb.Name = $ControlName;
	$private:rb.Text = $ControlName;
	$private:rb.Left = 20;
	$private:rb.Top = ($Top.Value += 20);
	$private:rb.add_CheckedChanged(([System.EventHandler]$handler = 
	{
		param($sender)
		if ($sender.Checked){
		$script:stStrip.LayoutStyle = `
			([System.Windows.Forms.ToolStripLayoutStyle]($sender.Name));
		}
	}));
	return $private:rb;
}
	#endregion function createRadioButton
[int]$top = 0;
$form1.Controls.AddRange(
	[System.Windows.Forms.Control[]]@(
	(createRadioButton ([System.Windows.Forms.ToolStripLayoutStyle]::Flow.ToString()) ([ref]$top)),
	(createRadioButton ([System.Windows.Forms.ToolStripLayoutStyle]::HorizontalStackWithOverflow.ToString()) ([ref]$top)),
	(createRadioButton ([System.Windows.Forms.ToolStripLayoutStyle]::StackWithOverflow.ToString()) ([ref]$top)),
	(createRadioButton ([System.Windows.Forms.ToolStripLayoutStyle]::Table.ToString()) ([ref]$top)),
	(createRadioButton ([System.Windows.Forms.ToolStripLayoutStyle]::VerticalStackWithOverflow.ToString()) ([ref]$top))
	));
$form1.Controls[([System.Windows.Forms.ToolStripLayoutStyle]::Table.ToString())].Checked = $true;
#endregion ToolStripLayoutStyle
#region function setStatusStrip
function setStatusStrip
{
	param($OperationName = "",
		  $OperationProgress = "",
		  $ProgressBarMinimum = 0,
		  $ProgressBarMaximum = 0,
		  $ProgressBarValue = 0
		  )
		try{$null = $script:stStrip;
			if ($OperationName -ne $null -and `
				$script:stStripLabelOperation -ne $null)
				{
					$script:stStripLabelOperation.Text = $OperationName;
					$script:stStripLabelOperation.Width = 200;
				}
			if ($OperationProgress -ne $null -and `
				$script:stStripLabelProgress -ne $null)
				{
					$script:stStripLabelProgress.Text = $OperationProgress;
					$script:stStripLabelProgress.Width = 100;
				}
			if ($script:stStripProgressBar -ne $null){
				if ($ProgressBarMinimum -ne $null)
					{$script:stStripProgressBar.Minimum = $ProgressBarMinimum;}
				if ($ProgressBarMaximum -ne $null)
					{$script:stStripProgressBar.Maximum = $ProgressBarMaximum;}
				if ($ProgressBarValue -ne $null)
					{$script:stStripProgressBar.Value = $ProgressBarValue;}
				if ($script:stStripProgressBar.Minimum -eq `
					$script:stStripProgressBar.Maximum)
					{$script:stStripProgressBar.Visible = $false;}
				else
					{$script:stStripProgressBar.Visible = $true;}
			}
		}
		catch{}
}
#endregion function setStatusStrip
$form1.ShowDialog() | Out-Null;

In short, the sample consists of a form $form1, a button that demonstrates a comparatively long operation, the status bar itself and five radio buttons showing how the style can be changed.

The setStatusBar function sets texts for the first label (the name of each file), the second label (the counter), minimum and maximum of the progress bar (can be set once), the current progress bar value (in my sample is the same as value used for the second label).

The code is downloadable as a script from here.

WordPress PowerShell Code Coloring Test

with one comment

I have already written about how it’s possibly to post Powershell code here. As a year turned, why don’t check the state of affairs again?

My example is very simple and doesn’t cover all aspects of code. On the other hand, great sheets of code are not what is easily comparable with eyes.

1. This way my example is eyed in ISE:

Image

Bugs are rare, however, it’s necessary to list them:

1.1 String data used without quotes is colored as a function (line 10)

1.2 Methods are not colored. It’s a typical trick, however, since nobody may know what it will be after the run of code. After having run the code, it’s considered here that no reason to re-color already colored code. (lines 10 and 42)

1.3 Property ‘Value’ is not colored (line 42).

Anyway, the coloring left the reader in a mood that all is healthy here.

2. Using Copy as HTML in PowerGUI 2.4 and Chrome 11, after adding manually line breaks (why doesn’t it type
s?), spaces and deleting trailing spaces after backticks (not in this sample), the following is workable:

cls
#region WordPress posting code test 
#this is a test of Powershell code coloring
[string]$stringVar1="string 1"
[string]$private:stringVar2='string 2'
[string]$script:stringVar3=
@' 
string data 
'@ 
[scriptblock]$global:sb= {{Write-Hostscriptblock}.Invoke();}; 
function 
write1{Write-Host $stringVar1;} 
function private:write2 
{param([string]$str2='')Write-Host $str2;} 
function script:write3 
#this is a function

Write-Host$script:stringVar3

function global:Print-SB 

<# 
.SYNOPSIS 
This is a code coloring test. 
.DESCRIPTION 
This test function represents an advanced Powershell function syntax. 
.PARAMETER 
Param Demonstrates how a scriptblock can be passed as a reference. 
.EXAMPLE 
PS C:\> Print-SB ([ref]$sb) 
#> 
[CmdletBinding()] 
param( [Parameter(Position=0, Mandatory=$true)] 
[ref]$Param 

Begin{} 
Process{$Param.Value.Invoke()} 
End{} 

write1 
private:write2 $private:stringVar2
script:write3 
Print-SB ([ref]$global:sb
#endregion WordPress posting code test

2.1 In the second code snippet we have numerous problems with names of functions, both where they are declared and where they are called.

2.2 Write-Host inside the second function

2.3 Such stuff like attributes in an advanced function.

To conclude this section, use the Copy as HTML option is a choice if manual editing doesn’t fatigue you.

3. WordPress provides a set of tags. Several parameters might do the life of a codeblogger simpler, especially 'highlight'.
cls
#region WordPress posting code test
#this is a test of Powershell code coloring
[string]$stringVar1 = "string 1";
[string]$private:stringVar2 = 'string 2';
[string]$script:stringVar3 =
@'
string data
'@
[scriptblock]$global:sb = {{Write-Host scriptblock}.Invoke();};
function
write1{Write-Host $stringVar1;}
function private:write2
{param([string]$str2 = '')Write-Host $str2;}
function script:write3
#this is a function
{

	Write-Host $script:stringVar3;
}
function global:Print-SB
{
<#
	.SYNOPSIS
		This is a code coloring test.

	.DESCRIPTION
		This test function represents an advanced Powershell function syntax.

	.PARAMETER  Param
		Demonstrates how a scriptblock can be passed as a reference.

	.EXAMPLE
		PS C:\> Print-SB ([ref]$sb)
#>
	[CmdletBinding()]
	param(
		  [Parameter(Position=0, Mandatory=$true)]
		  [ref]$Param
		  )
	Begin{}
	Process{$Param.Value.Invoke()}
	End{}
}
write1
private:write2 $private:stringVar2;
script:write3
Print-SB ([ref]$global:sb)
#endregion WordPress posting code test

However, the overall state is not appropriate, from my point of view. Yes, I know that the 'Frustration-Free' trademark is not WordPress's (as it is not Quest's too), but there is a room for improvement:

3.1 Variable names (lines 5, 6, 46, 48)
3.2 Function declarations and names (lines 11-13, 15, 21, 45-48)
3.3 A blob string (lines 7-9)
3.4 A specific to advanced functions comment-description (lines 23-35)
3.5 Types (lines 4-6, 10, 14)
3.6 Unquoted string (line 10)
I'll report these problems to Happiness engineers, maybe they share a bit of their happiness? 😉

Written by Alexander Petrovskiy

April 27, 2011 at 6:37 am

Posted in ISE, PowerGUI, Powershell, WordPress

Tagged with

Adding a MenuStrip to a Form. Hands Only

leave a comment »

As can be clearly seen from the survey Ravikanth conducted here http://www.ravichaganti.com/blog/?p=2111 , the great majority of powershellers do write GUI. Moreover, there is no common universal tool. Every powersheller chooses the way one creates user interface.

Well, why don’t we create a small example by using just bare hands. Let’s do our preparation. A recipe is simple: a bit of text editor (Intellisense-enabled is preferable), a piece of rich text or even a text file, and a keyboard.

Supposedly, we need a form with a menu (two-level one, not to be considered as a simpleton), a label and a textbox. The user should be able to manage content of textbox using menu.

There is two ways to create a form:

1.1 by using PrimalForms:

#Generated Form Function
function GenerateForm { 
########################################################################
 # Code Generated By: SAPIEN Technologies PrimalForms (Community Edition) v1.0.10.0
 # Generated On: 26/04/2011 09:43 p.m.
 # Generated By: apetrovskiy
 ########################################################################

#region Import the Assemblies 
[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
#endregion
#region Generated Form Objects 
$form1=New-Object System.Windows.Forms.Form
$textBox1=New-Object System.Windows.Forms.TextBox
$label1=New-Object System.Windows.Forms.Label
$InitialFormWindowState=New-Object System.Windows.Forms.FormWindowState
#endregion Generated Form Objects 
#region Generated Form Code 
$System_Drawing_Size=New-Object System.Drawing.Size
$System_Drawing_Size.Height =262
$System_Drawing_Size.Width =284
$form1.ClientSize=$System_Drawing_Size
$form1.DataBindings.DefaultDataSourceUpdateMode=0
$form1.Name="form1"
$form1.Text="Primal Form"
$textBox1.DataBindings.DefaultDataSourceUpdateMode=0
$System_Drawing_Point=New-Object System.Drawing.Point
$System_Drawing_Point.X =34
$System_Drawing_Point.Y =82
$textBox1.Location=$System_Drawing_Point
$textBox1.Name="textBox1"
$System_Drawing_Size=New-Object System.Drawing.Size
$System_Drawing_Size.Height =20
$System_Drawing_Size.Width =195
$textBox1.Size=$System_Drawing_Size
$textBox1.TabIndex=1
$form1.Controls.Add($textBox1
$label1.DataBindings.DefaultDataSourceUpdateMode=0
$System_Drawing_Point=New-Object System.Drawing.Point
$System_Drawing_Point.X =36
$System_Drawing_Point.Y =45
$label1.Location=$System_Drawing_Point
$label1.Name="label1"
$System_Drawing_Size=New-Object System.Drawing.Size
$System_Drawing_Size.Height =22
$System_Drawing_Size.Width =177
$label1.Size=$System_Drawing_Size
$label1.TabIndex=0
$label1.Text="label1"
$form1.Controls.Add($label1
#endregion Generated Form Code 
#Save the initial state of the form
$InitialFormWindowState=$form1.WindowState
#Init the OnLoad event to correct the initial state of the form
$form1.add_Load($OnLoadForm_StateCorrection
#Show the Form
$form1.ShowDialog() | Out-Null
#End Function
#Call the Function
GenerateForm

1.2 by typing the following code:

[System.Windows.Forms.Form]$form1=`
New-Object System.Windows.Forms.Form
[System.Windows.Forms.Label]$label1=`
New-Object System.Windows.Forms.Label
$label1.Name="label1"
$label1.Text="label1"
$label1.Left=20; 
$label1.Top=50
[System.Windows.Forms.TextBox]$textbox1=`
New-Object System.Windows.Forms.TextBox
$textbox1.Name="textbox1"
$textbox1.Left=20
$textbox1.Top=100
$form1.Name="form1"
$form1.Controls.Add($label1); 
$form1.Controls.Add($textbox1); 
$form1.ShowDialog() | Out-Null;

All our further actions are insertions to be written above the string  $form1.ShowDialog()

2. Now we add the following simple function:

function addMenuItem 

param([ref]$ParentItem
[string]$ItemName=''
[string]$ItemText=''
[scriptblock]$ScriptBlock=$null 

[System.Windows.Forms.ToolStripMenuItem]$private:menuItem=`
New-Object System.Windows.Forms.ToolStripMenuItem
$private:menuItem.Name =$ItemName
$private:menuItem.Text =$ItemText
if ($ScriptBlock -ne $null
{ $private:menuItem.add_Click(([System.EventHandler]$handler=`
$ScriptBlock)); } 
if (($ParentItem.Value) -is [System.Windows.Forms.MenuStrip]) 
{ ($ParentItem.Value).Items.Add($private:menuItem); } 
if (($ParentItem.Value) -is [System.Windows.Forms.ToolStripItem]) 
{ ($ParentItem.Value).DropDownItems.Add($private:menuItem); } 
return $private:menuItem
}

The function receives a reference to the parent menu item, the name and the label chosen for a new menu element, and, if nesessary, scriptblock. Don’t pass a scriptblock to menuitems that are not at the lowest leel of your menu hierarhy.

3. After that it’s time to add a MenuStrip:

[System.Windows.Forms.MenuStrip]$mainMenu=New-Object System.Windows.Forms.MenuStrip
$form1.Controls.Add($mainMenu);

If we run our form now, we can see a hardly visible (depending on your color schema) strip at the top of the $form1.

4. Now we can add handlers form menu items. To simplify the example, our handlers are scriptblocks. I wrote one, crischening it as $sb1. Undoubtedly, by searching for $mainMenu in ObjectBrowser untidy code you may find more examples.

[scriptblock]$sb1=
#your code
}

5. Finally, we add menu items (see sample code for more details):

#region File 
(addMenuItem -ParentItem ([ref]$mainMenu) -ItemName 'mnuFile' -ItemText 'File' -ScriptBlock $null) | %
$null=addMenuItem -ParentItem ([ref]$_) -ItemName 'mnuFileOpen' -ItemText 'Open' -ScriptBlock $sb1
$null=addMenuItem -ParentItem ([ref]$_) -ItemName 'mnuFileSave' -ItemText 'Save' -ScriptBlock $null
$null=addMenuItem -ParentItem ([ref]$_) -ItemName 'mnuFileExit' -ItemText 'Exit' -ScriptBlock $null;} | Out-Null
#endregion File

Today’s code attached here.

PowerShell-disabled Areas On The Globe

leave a comment »

A couple of weeks ago, I set the world-wide visitors widget (I love geography and maps). My blog is not a very popular place, being updated only from time to time, but the analysis is interesting.

From an independent point of view, examples of Winforms applications running in PowerShell should be equally interesting to people across the globe. However, it’s not so, far beyond from being so.

Let’s look at the coverage:

Image

The US and Europe are undoubtedly global leaders. Western counties are the very center of PowerShell power, great and useful. Asia contributes too. Antipodes visit, but relatively rarely. The visitors are widespread across the US, whereas European ones are concentrated due to comparatively small sizes of their countries.

The most deserted areas like North Africa, Middle Asia, Western Australia and Greenland as well as South-American and African jungles are not supposed to hit the blog. The question here is Russia, with exception for Saint-Petersburg (my visits I suppose) it looks like a desert. Especially oddly does it seem like a Sahara in its European part. What may be the cause of this desertification effect? As I heard, some people in Moscow are aware of powershell advantages. Perhaps, the imperial tradition not to learn language but imperial one prevents guests from reading the blog? There is no answer, and never will be until Russian non-visitors explain such an evasion. 🙂

An Infinitesimal Update To ObjectBrowser

leave a comment »

Hi, today’s update is really small.

– added a progress bar during the collecting Current AppDomain and GAC. This should do the GAC loading slightly less painful.

– the ability to be run from command line powershell as well as from ISE is now restored. Please use the following instruction to import the module:

Import-Module Add-on.PSDevStudioLite.ObjectBrowser -Force

Other changes relate to internal code structure and not to be seen right now in the GUI. As usual, the download location is here: http://www.box.net/shared/ot56ct7ngl

Design a site like this with WordPress.com
Get started