Archives

Archives / 2009 / December
  • WPK – 2: Some thoughts, and my first really small databound app

    My second article on using WPF from PowerShell. You can download WPK as part of the Windows 7 Resource Kit PowerShell Pack. When you can navigate to the folder <My Documents>\WindowsPowerShell\Modules you see the modules that are installed. The folder WPK contains the WPK module.

    On the Modules level a few documents are installed:

    • Readme1st.txt – information on installing, using, uninstalling the PowerShellPack
    • About the Windows 7 Resource Kit PowerShell Pack.docx – an overview of the available modules
    • Writing User Interfaces with WPK.docx - the first place to get started when working with WPK

    Especially the Readme1st.txt contains two interesting pieces of information:

    1. The file starts with the following text:

      Readme for the Windows 7 Resource Kit PowerShell Pack

                               by James Brundage

                   Copyright (c) 2009 by Microsoft Corporation
                    Portions copyright (c) 2009 James Brundage
                               All Rights Reserved


      I thought James Brundage is an employee of Microsoft, why does he own portions of the copyright?

    2. The disclaimer contains the following text:

      The Windows 7 Resource Kit PowerShell Pack included on the companion CD is
      unsupported by Microsoft and is provided to you as-is, with no warranty or
      guarantee concerning its functionality. For the latest news and usage tips
      concerning this PowerShell Pack, see the Windows PowerShell Team Blog at
      http://blogs.msdn.com/powershell/.

      So no support from Microsoft’s side. I wonder how issues will be resolved and new releases will be published.

    Ok, and now on to some programming. In the document Writing User Interfaces with WPK.docx we find a nice example of a process viewer that updates the list of processes every 15 seconds.

    A simple process viewer
    1. New-ListView -Width 350 -Height 350 -DataBinding @{
    2.    ItemsSource = New-Binding -IsAsync -UpdateSourceTrigger PropertyChanged -Path Output
    3. } -View {
    4.    New-GridView -AllowsColumnReorder -Columns {
    5.        New-GridViewColumn "Name"
    6.        New-GridViewColumn "Id"
    7.    }
    8. } -DataContext {
    9.    Get-PowerShellDataSource -Script {
    10.        Get-Process | ForEach-Object { $ ; Start-Sleep -Milliseconds 25 }
    11.    }
    12. } -OnLoaded {
    13.    Register-PowerShellCommand -Run -In "0:0:15" -ScriptBlock {
    14.        $window.Content.DataContext.Script = $window.Content.DataContext.Script
    15.    }
    16. } -asjob

    See the document for a great explanation on how it works.

    When looking at this example I had a few questions:

    1. What if I don’t want to do a timed update, but just bind to some existing data?
    2. All examples do the data collection in the Get-PowerShellDataSource script block, is it possible to have the data already somewhere in a variable?
    3. Can I skip the binding stuff, I know its really powerful, but I want to start simple?
    4. Retrieve data in a background job is really cool, but what if we just want to load data and go?

    My first simple try after a lot of testing and tweaking is the following:

     

    Some names and ages
    1. New-ListView -Show -DataBinding @{
    2.    ItemsSource = New-Binding -Path Output
    3. } -View {
    4.    New-GridView -Columns {
    5.        New-GridViewColumn "Name"
    6.        New-GridViewColumn "Age"
    7.        }
    8. } -DataContext {
    9.    Get-PowerShellDataSource -Script {
    10.        $list = @()
    11.        $list += New-Object Object |
    12.            Add-Member NoteProperty Name "Serge" -passthru |
    13.            Add-member NoteProperty Age "43" -passthru
    14.        $list += New-Object Object |
    15.            Add-Member NoteProperty Name "Dinah" -passthru |
    16.            Add-member NoteProperty Age "42" -passthru
    17.        $list += New-Object Object |
    18.            Add-Member NoteProperty Name "Scott" -passthru |
    19.            Add-member NoteProperty Age "8" -passthru
    20.        $list += New-Object Object |
    21.            Add-Member NoteProperty Name "Dean" -passthru |
    22.            Add-member NoteProperty Age "4" -passthru
    23.        $list += New-Object Object |
    24.            Add-Member NoteProperty Name "Tahne" -passthru |
    25.            Add-member NoteProperty Age "1" -passthru
    26.        $list
    27.    }
    28. }

     

    I still use binding to the output, and in the datacontext script block I write the elements to bind to to the output. I still don’t bind to pre-calculated data in a variable.

    After a lot more testing I came to the following code:

    Names and ages from variable
    1. $list = @()
    2. $list += New-Object Object |
    3.    Add-Member NoteProperty Name "Serge" -passthru |
    4.    Add-member NoteProperty Age "43" -passthru
    5. $list += New-Object Object |
    6.    Add-Member NoteProperty Name "Dinah" -passthru |
    7.    Add-member NoteProperty Age "42" -passthru
    8. $list += New-Object Object |
    9.    Add-Member NoteProperty Name "Scott" -passthru |
    10.    Add-member NoteProperty Age "8" -passthru
    11. $list += New-Object Object |
    12.    Add-Member NoteProperty Name "Dean" -passthru |
    13.    Add-member NoteProperty Age "4" -passthru
    14. $list += New-Object Object |
    15.    Add-Member NoteProperty Name "Tahne" -passthru |
    16.    Add-member NoteProperty Age "1" -passthru
    17.  
    18. New-ListView -Name mylistview -Show -View {
    19.    New-GridView -Columns {
    20.        New-GridViewColumn "Name"
    21.        New-GridViewColumn "Age"
    22.    }
    23. } -On_Loaded {
    24.    $mylistview = $window | Get-ChildControl mylistview
    25.    $mylistview.ItemsSource = $list
    26. }

     

    In the above code I create a variable with a list of objects with two properties, Name and Age, and bind the ItemsSource property of the ListView to this variable.

    I bind the data in the Loaded event, the complete control tree is in place when this event fires.

    I have named the ListView control ‘mylistview’, and with the  code in line 24 I can find the control by name. The $window variable points to the implicitly created Window control surrounding the ListView, and is always available.

    Note that if we add the –AsJob parameter to the New-ListView command, the creation and binding is done in a background job on another thread, and the $list variable is not visible, not even if it is defined as a global variable (as $global:list)

    Diving into this simplification kept me busy for a while and gave me as a WPF nono some insights in how things are working in WPF when doing this from PowerShell.

    One question I still have in this simple example: is there an easier way to fill the $list variable so its still useful for databinding.I tried $list = @{ Name="Serge"; Age="43" }, @{ Name="Dinah"; Age="42" } but that does not work:-(

    Let me know if this is of any help to you.

    Happy coding!

  • WPK - 1: Creating WPF applications using PowerShell

    My first article on using WPF from PowerShell. What is WPK? Were can you get it? How to get started?

    I have been programming in PowerShell since 2006. At Macaw we use PowerShell for most of the development on the Macaw Solutions Factory. I have written thousands and thousands of lines of code in PowerShell 1.0. Some of the GUI tools in the Macaw Solutions Factory are even written completely in PowerShell. We use PrimalForms for the generation of the PowerShell code to render the GUI.

    PrimalForms: PrimalForms Community Edition is a free GUI builder tool for PowerShell users. It edits and stores Windows Forms in a native XML format and generates PowerShell code on demand. Sample forms included.

    More complex GUI tools are written in standard C#/WinForms. I prefer to have the tools in the Macaw Solutions Factory to be written completely in PowerShell. The reason is that most innovations to the Macaw Solutions Factory are done in real world projects. Because the Macaw Solutions Factory almost completely consists of script code, it is possible to add new features on any development machine that checked out the Factory code together with the source code of the project. No special development environment is needed. Good innovations are merged into the trunk of the Factory. Also fixing issues or making project specific modifications is a breeze.

    Writing WinForms applications using PowerShell never really worked well for us. Writing WinForms applications without designer is just terrible. PrimalForms makes life better, but still…

    Enter WPF! I have been playing with WPF and PowerShell a few years ago. Problem was that PowerShell had to be executed in a Single Threaded Apartment (STA) instead of the default Multi Threaded Apartment (MTA). My first discussion on this with Bruce Payette never resulted into a good working solution.

    A few days ago I ran across an interesting project at CodePlex: PowerBoots. This tooling provides WPF from both PowerShell 1.0 and PowerShell 2.0. I did some tests with it, and had some trouble, partly due to complete lack of knowledge of WPF. While searching the web I also stumbled upon WPK, the Windows Presentation Foundation PowerShell Kit. It is part of the just released Windows 7 Resource Kit PowerShell Pack (most things work on any OS with PowerShell 2.0 installed). WPK takes a very similar approach as PowerBoots. Check them both out!

    It is Christmas time. This means: two weeks no real company work, a bit of free time to dive into something new. I have been running around the last three days in PowerBoots and WPK, and I must say: the demo’s look great and most of them work, but even the most simple baby steps completely fail on me, especially due to my complete ignorance of what happened in the WPF space for the last years. Yes, I am ashamed of myself. Time to catch up… baby steps at a time. There are actually two things to dive into: the new features of PowerShell 2.0 and WPK. So don’t expect much of the next posts, it is all really basic stuff, but I see on my blog that the baby step posts are the most popular posts. Posts like how to call a PowerShell function with arguments (fn –arg1 a –arg2 b instead of fn(a,b)). So expect some post at this level… is just write down the things I go through myself.

    To get yourself started on the possibilities of WPK, have a look at the WPK video’s available on Channel 9. James Brundage, part of the Microsoft PowerShell Test team, does a good job on explaining WPK. There are a few videos there now, with more to come. For questions have a look at the discussion thread on the PowerShellPack site.

    Happy WPK’ing..