Archive for the “Uncategorized” Category
I have written a few posts on debugging using the PowerShell ISE lately. If you care to have a look, here are the links to ISE Debugging 101 and ISE Debugging 102. Those blog posts got newcomers to the ISE slightly more comfortable with the idea of debugging and the the specific tools offered in the ISE. I had a few questions and responses to these posts and I thought the best way to encapsulate this information was with a screen cast. I have taken what I covered and expanded it a bit to the realm of modules and how you can use the ISE debugging tools to work with Modules as easily as you can work with scripts and functions.
I hope you find this video helpful. I would love to hear any kind of feedback on the video, positive or negative. All I can say is that it is a bit easier to talk to yourself in front of a computer after a glass of wine Seriously, feedback is greatly appreciated.
Andy
4 Comments »
I have always found the origin of words to be fascinating. Apparently, the terms bug and debugging in regards to computers are attributed to Admiral Grace Hopper in the 1940’s.
While she was working on a Mark II Computer at Harvard University, her associates discovered a moth stuck in a relay and thereby impeding operation, whereupon she remarked that they were "debugging" the system.
When I first started scripting and writing a little code, the concept of debugging something seemed really hard. However, I have found that with a few simple steps I can debug most of my scripts pretty quickly.
Ninety nine percent of the time, debugging scripts requires being able to watch a variable at some point in a script or a function. Have you ever written a function and thought, “If only I knew what x was before y started messing with it?”
The PowerShell Integrated Scripting Environment makes this pretty easy. You can set a breakpoint on any line in the ISE using the Debug Menu and choosing “Toggle Breakpoint.” or by using the F9 shortcut key.

When you toggle a breakpoint on and then run the script, the script will stop at that point. You should note that at this point, the highlighted line has not been executed yet.
Here’s what it looks like when you hit a breakpoint. You get thrown into a nested prompt where you can poke around and look at any variables you want to. Notice the >>> prompt and notice $b has not yet been set, but $a has.
Now that you are paused right around the line of code you want to check out, you can use the “Step Into” Feature.
This will execute the next line of code in the script (the highlighted line) and then stop.
Now you can see that $b has been set but $c doesn’t have a value yet.
You can continue to step through as much as many lines as you need to until you see something that is not quite right.
This is just the beginning of what we can do in regards to debugging scripts and functions. In the next couple weeks I plan to share more as I learn about debugging and the ISE. Just to whet your appetite, you can run the command get-command –noun psbreakpoint to see what kinds of goodies await!
4 Comments »
There was a very interesting post over on the PowerShell team blog on Dynamic Binary Modules where Nigel Sharples describes how to run a cmdlet on a remote machine if you have the source code to the cmdlet and don’t want to deal with any intermediate assembly files to clean up.
I went and tried to do this straight away on my local machine without the remoting bit. I copied some cmdlet source code from MSDN. As a Systems Engineer, I haven’t written many compiled cmdlets in C# but I have edited a few for my liking and written one or two when script just wouldn’t cut it. One thing I have learned is that you always need a Snapin to register your cmdlet. So you have your namespace with a class for your snapin and then a class for each cmdlet that you create.
The bottom line here is that with dynamic modules you don’t need to create a Snapin class for your cmdlet. The only other tweak is that I used the –language parameter on Add-Type to specify CSharpVersion3 so I could use automatic properties and not have to explicitly write the getter and setter for the parameter “Name.”
[string]$code = @"
using System.Management.Automation;
namespace SendGreetingDemo1
{
[Cmdlet(VerbsCommunications.Send, "Greeting")]
public class SendGreetingCommand : Cmdlet
{
[Parameter(Mandatory=true,Position=0)]
public string Name {get;set;}
protected override void ProcessRecord()
{
WriteObject("Hello " + Name + "!");
}
}
}
"@
$assembly = (Add-Type -TypeDefinition $code `
-Language CSharpVersion3 `
-passthru ).Assembly
$assembly | Import-Module
1 Comment »
A few weeks ago I had the pleasure of speaking at Tech Summit for Avanade. Tech Summit is sort of like an internal Tech Ed for Avanade Employees. My talk, of course, was all about PowerShell V2 and how to leverage the features like Remoting, Modules, and Advanced Functions.
Advanced Functions essentially allows PowerShell users to leverage nearly all the features that are available to a developer writing a Cmdlet in C# in functions written in PowerShell script.
After the talk, one question that was brought up was “If you can leverage all of these features in Advanced Functions, at what point would you convert over to C# (or VB .NET) and write a full blown compiled binary Module.
The first is all about performance. Well written compiled code will almost always out perform well written interpreted code. There are a ton of factors here that can come into play, but as a general rule, binaries will be faster than script.
The second reason you may want to stick with compiled code is if you want to include a provider with your Module. A provider presents any kind of data store to a PowerShell user in the same way they are presented the filesystem. You can do things like set-location, new-item, set-itemproperty, cd, ls, md, etc etc. Just as an example, the PowerShell Community Extensions has a provider for Active Directory.
If you are a sys admin that has never cracked open Visual Studio, you obviously will start off with Advanced Functions. However, I would really like to point out that the glide path to compiled C# from Advanced Functions is not super steep. There is a ton of documentation on Beginner Development and how to write your first Cmdlet. So if you are interested at all in learning, I say go for it and jump in with both feet. Even if you are not looking to be a full time software developer, looking at and understanding how a compiled cmdlet is written will bring a deeper understanding to how you use PowerShell.
3 Comments »
I had previously mentioned that there would be another Script Club this month, but schedule wise, things did not quite work out.
My wife and I are in “getting ready for new baby” mode. The C-section is scheduled for the 1st week of June.
I am guessing the next one will be in July sometime.
1 Comment »
In my last post, I discussed how to fire up a WPF window in PowerShell. You can make XAML look pretty amazing, but if buttons and controls never get wired up to any functionality, it gets boring pretty quick. Here is the code I had last time with a small addition.Blend allows you to name your controls. This turns into what you see in line 018 in the XAML. x:Name=”Close.”
|
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027
|
[xml]$xaml = @" <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="Window" Title="Blend and PowerShell" Width="640" Height="480" AllowsTransparency="False"> <Grid x:Name="LayoutRoot"> <Rectangle Margin="22,8,22,0" VerticalAlignment="Top" Height="178" Stroke="#FF000000"> <Rectangle.Fill> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FF000000" Offset="0"/> <GradientStop Color="#FF861A1A" Offset="1"/> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> <Button Margin="121,0,129,96" VerticalAlignment="Bottom" Height="100" Content="Button" x:Name="Close"/> </Grid> </Window> "@ $reader = New-Object System.Xml.XmlNodeReader $xaml $d = [Windows.Markup.XamlReader]::Load($reader) $d.FindName("Close").add_click({ $d.Close() }) $d.ShowDialog() | out-null
|
Once you have the name, you can call the FindName method (see line 024) on your WPF Window. This allows you to find the named control that you want to add event handling for. Using FindName, we can add the add_Click method and pass in the ScriptBlock that we want to execute on the click event.
When you run this, clicking the button will close the dialog box.
1 Comment »
I just started rebuilding a laptop with Windows 7 RC and thought I would do a bit of a refresh on my typical tool list that gets added to my machine immediately after a clean install. Notepad2 with PowerShell support is the latest must add for me.
Scott Hanselman has a phenomenal list of tools that he posted back in 2007 but they are still worth a look through. Most are free and the ones that are not are worth paying for.
Scott is mainly a developer so a lot of the tools are dev focused, but a the top 10 would apply to anyone that wants to interact with their computer in a more effective way.
I have heard him mention on his podcast that people are starting to complain that he hasn’t refreshed the list in a while. Maybe we will have the pleasure of the 2009 list soon. We’ll see.
1 Comment »
On Tuesday we had our first Script Club in Seattle. There was even mention of the Script Club on This Week on Channel 9. The night went really well. There were lots of good discussions between PowerShell experts and beginners alike.
Some people are already asking when the next meeting will be. Mark Tuesday, May 26th on your calendars. It will be at 818 Stewart in downtown Seattle at 7:00 just like last time.
Hope to see you there!
Andy
1 Comment »
Thought I would share my ISE profile and test out Write-CommandBlogPost in Live Writer with Doug Finke’s Live Writer Add-In
Microsoft.PowerShellISE_profile.ps1
Synopsis:
Creating and using a Windows PowerShell profile
Here’s Microsoft.PowerShellISE_profile.ps1:
function Set-File {
param
(
[parameter(Mandatory=$true,ValueFromPipeline=$true)]
[string]
$file
)
$psise.CurrentOpenedRunspace.OpenedFiles.Add($file)
}
function Insert-Text{
param
(
[parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string]
$text
)
$currentFilePath = $psise.CurrentOpenedFile.FullPath
$currentFile = $psIse.CurrentOpenedRunspace.OpenedFiles |
where {$_.FullPath -eq $currentFilePath}
$currentFile.editor.InsertText($text)
}
function New-FunctionTemplate{
param
(
[parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string]
$verb,
[parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string]
$noun
)
$f = @"
function $Verb-$Noun {
param (
[parameter(Mandatory=$true, ValueFromPipeline=$true)
[string]
$p1
)
begin {}
process {}
end {}
}
"@
Insert-Text -text $f
}
function invoke-region{
param
(
[int] $num
)
$ed = $psISE.CurrentOpenedFile.Editor
$lines = [Regex]::Split($ed.text,"`r`n" )
$foundfirst = -1
$foundlast = -1
for($count = 0;$count -le $lines.length-1;$count++)
{
if ($lines[$count].startswith("#region") -and $lines[$count].contains("@$num"))
{ $foundfirst = $count;break}
}
if($foundfirst -gt -1)
{
for ($count = $foundfirst; $count -le $lines.length-1;$count++)
{
if ($lines[$count].startswith("#endregion") )
{$foundlast = $count;break}
} # end For $lines
if ($foundlast -gt -1)
{
$torun = ""
$lines[$foundfirst..$foundlast] | % { $torun+=$_ + "`r`n"}
invoke-expression $torun
} # end if $foundLast
} # End for $count
} # End Function Invoke-Region
$psise.options.CommandPaneUp = $true
$psise.options.fontname = "Consolas"
$psise.options.fontsize = 16
[void]$psIse.CustomMenu.Submenus.Add("_Function Template", {New-FunctionTemplate},"Alt+F")
[void]$psISE.CustomMenu.Submenus.Add("Region 1", {invoke-region 1 },'ctrl+1')
[void]$psISE.CustomMenu.Submenus.Add("Region 2", {invoke-region 2 },'ctrl+2')
[void]$psISE.CustomMenu.Submenus.Add("Region 3", {invoke-region 3 },'ctrl+3')
[void]$psISE.CustomMenu.Submenus.Add("Region 4", {invoke-region 4 },'ctrl+4')
[void]$psISE.CustomMenu.Submenus.Add("Region 5", {invoke-region 5 },'ctrl+5')
[void]$psISE.CustomMenu.Submenus.Add("Current Line", {invoke-caretline},'f7')
$docs = $(resolve-path "$Env:userprofile\documents")
$desktop = $(resolve-path "$Env:userprofile\desktop")
$myMod = $(resolve-path $($Env:PSMODULEPATH -split ";")[0])
Automatically generated with a custom version of Write-CommandBlogPost
1 Comment »
With PowerShell V2 we can now get nearly all the functionality of the PowerShell engine that is available to Cmdlet developers that are using C#. Granted, if you haven’t written any Cmdlets in C#, you probably don’t understand the power that this brings, but trust me, its huge!
Here are just a couple things to think about as we start to build more industrial strength functions. We can do all kinds of cool things with parameters now. We can validate that the entry matches a regular expression. We can tell the parameter to accept a value from the pipeline. We can declare whether or not a parameter is mandatory or not.
In addition to tons of flexibility with parameters, we can also leverage the built in help for functions that we write. Rather than going on and listing every single feature, let me just give an example of what I am talking about.
1: Function Get-EvenNumber {
2: #.Synopsis
3: # Returns even numbers using the Modulo operator
4: #.Description
5: # takes a set of numbers and tells you which ones are even
6: #.Parameter number
7: # An integer that is required, can take values from the pipeline as well
8: #.Example
9: # 1..10 | Get-EvenNumber
10:
11: param (
12: [Parameter(Position=0,
13: Mandatory=$true,
14: ValueFromPipeline=$true,
15: HelpMessage="Please type a number between 1 and 10")]
16: [Alias("integer")]
17: [int]
18: $number
19:
20: )
21: begin {"Begining of Pipeline"}
22:
23: process {
24: if (($number % 2) -eq 0) {"$number is even"}
25: }
26:
27: end {"End of Pipeline"}
28:
29: }
Now here are some screen shots of how you can use this function, just like a Cmdlet in version 1.
In this first one, we first use the function with a parameter, and then in the pipeline.
In the function, we used the Begin, Process, and End Blocks, so we can do stuff before we send anything down the pipeline, then work on the pipeline objects, and then do anything else we need to do to wrap up. This is why you see the text “Beginning Pipeline” and “End of Pipleline".” This is for demonstration purposes only.
Because we declared that the number parameter is mandatory and we specified a help message, we get this great interactivity for only setting a couple attributes. PowerShell tells the user, “You forgot this mandatory paramter, and if you need help, type !? and you can see what the function author wants you to know about the parameter. Pretty flippin’ awesome!
And finally , of course we get the following when we type help get-evennumber because of all the great code commenting we did at the beginning of the function. Notice how nicely its formatted. It even automagically pulls all the parameters and their types for you in the SYNTAX section.
No Comments »
|