SDDN October: Silverlight with RIA and using MVVM

October 29, 2009

I just got home from the attending the October Silverlight Designer and Designer Network (SDDN) meeting. It was a trillogy presentation from the Readify guys, Jordan Knight, David Burela and Philip Beadle.

Who respectively presented on:

  • Connecting Silverlight to RIA,
  • Binding data to Bing Maps and
  • A testable Silverlight architecture and development approach walk-through

There was also an announcement for the 2010 Melbourne Silverlight CodeCamp, with registrations now open at the SilverlightCodeCamp.com.au. The schedule is still open for volunteers to offer up presentations. It will be run at the new NAB training facilities. The registration site was mentioned with the footnote of “it’s not tested yet” which at the time of this post seems to be the case, my registration isn’t being processed correctly or at least there’s no feedback of success.

First up Jordan ran through the basics of using .NET RIA Services to produce a simple data-bound Silverlight website log-in component. It included demonstrating how to use attributes to decorate the RIA based entities to assist with validation that can be shared server side and client side. The benefit being a visually well designed Silverlight application can benefit from robust validation logic, and make use of it through field level bindings to easily display validation feedback to the user.

Next up was a quick presentation from David showing us data binding capabilities of data collections to Bing Maps, to produce overlays and interactive features on a map view. He should be posting the material up soon on his blog, including some code snippets that will make achieving what he demonstrated quick and easy.

The final presentation from Phil, which was nicely presented using Prezi.com was all about putting together a collection of tools and concepts to develop a robust and testable Silverlight based application. It focused around using the Model-View-ViewModel (MVVM) architecture/design pattern. It included examples of regular unit tests, automated UI tests, and integration tests, making use of an Inversion of Control (IoC) framework called Unity a Microsoft Application Block up on CodePlex and the Visual Studio 2008 Test Edition. There’s a bit of a discussion going on at StackOverflow about Unity.

Some key things that Phil pointed out to stay up to date with Silverlight and of course to assist with building more testable Silverlight applications include:

All up, a good round of presentations.


Exceptions in (my) LINQ (presentation)

October 8, 2009

Last night I presented to the Melbourne Patterns & Practices group, thanks to my audience for paying attention, having great input and asking interesting questions. I would like to clarify some things I glossed over in the powerpoint slides, and explain why some of the simple extension methods didn’t execute in the live code demos. I also have posted the pptx file here.

The first thing that I did not give a detailed enough explanation about was the Exception Handling slide where I was using the ‘let’ keyword in a LINQ statement. The question was along the lines of the benefit of the exception handling offered up by making use of let in a LINQ query. To clarify this, the let keyword is used to create a contextual keyword as part of the LINQ query (a Range Variable). This range variable can then be used to create an anonymous type using projection. I incorrectly tied the explanation of let to the point I was trying to make about handling exceptions. The key take-away is that because the query is a deferred execution any exception handling needs to be wrapped around the code that performs the execution. So have the Try {} Catch (E ex) {} surround the processing code not the query definition.

There’s a great post about using ‘Let’ in a LINQ Query by Greg Beech that goes into greater detail. This topic lead to a question about what would happen to processing when an exception did occur.

Another issue that came up during live code tweaking was making use of certain extensions, in particular .Reverse() didn’t seem to compile. I am unable to recreate the issue quite possible some weird state in Visual Studio 2010 Beta 1, if that was the case then the clean and rebuild was the solution.

But here is the final very simple code that reads a directory and outputs the file names in a reverse order:

var xmlFilesQuery =
      from fileInfo in
           System.IO.Directory.GetFiles(@"D:\soExportData\")
      where fileInfo.Contains(".xml")
      select fileInfo;

foreach (var fileName in xmlFilesQuery.Reverse())
{
    Console.WriteLine(fileName);
}

The last clarification point was a scenario where the PLINQ execution of a task compared to it’s LINQ execution offered up a speed up of 2.18 times. Not sure what state the application was in to allow that. I’ll do some investigation and based on how complex the cause was either update here or create a new post.

Greater Than 2x Speed Up (On Dual Core Machine)

Greater Than 2x Speed Up (On Dual Core Machine)


How much memory are you currently using?

September 25, 2009

Following on from my previous post about a demo PLINQ application, I had some small discoveries about memory usage and wanted to blog them.

As I was loading large chunks of data into memory and started monitoring my little demo applications RAM footprint, I discovered that even tho the garbage collection system had already cleaned up my now out-of-scope variables, the RAM utilisation as reported to windows did not necessarily drop.

This actually turns out is quite a logical thing to have happen and works this way for good reason, I just hadn’t thought about it. I was simply expecting an action of explicit free-up of memory to instantly translate into free’d memory in Windows.

The process was just holding onto a reserved amount of memory the .NET runtime assuming I would soon need that space again, and it was correct in its assumptions; I did need that memory very soon.

Use More Memory!

Use More Memory!

To prove this: subsequent button clicks to load more data (roughly the same size volume), didn’t make the application’s memory footprint grow even larger. Another interesting thing I noted with the task manager window open all the time, was when I loaded additional applications and my demo app didn’t need the memory, it would free up the few hundred mb it had a hold of but wasn’t currently making use of.

Demo Application Memory Usage

Demo Application Memory Usage


Playing with PLINQ Performance using the StackOverflow Data Dump

September 25, 2009

Not having made use of PLINQ in an actual product yet, I decided to have a play with how it works, and to try and obtain my own small metrics on it’s performance benefits. PLINQ is part of a larger push from the .NET teams at Microsoft to get concurrent/parallel processing out of the box in your C# and VB.NET code. As for performance analysis there are already some great posts out there, not just from the Parallel Team at MS but also from great breakdowns with nice charts such as this.

Right off the bat, I’d like to stress that adding a .AsParallel() to your code won’t magically speed it up. Knowing this I still had unrealistic expectations when I began creating a demo to specifically show performance improvements. Often enough the level of processing I was performing (even on larger sets of data), did not benefit from being made concurrent across 2 cores. A level of variation in my results, leads me to believe part of the issue is also the ability to obtain enough resources to make effective use of 2+ cores. For example running out of the 4GB ram I have available, interference from other processes on the machine (Firefox, TweetDeck, virus scanner).

In my attempts at re-creating the “Baby Names” demo Scott Hanselman previewed at the 2009 NDC Conference in his great presentation: “Whirlwind Tour of .NET 4“. I first got a hold of the preview code samples back from 2008 for PLINQ that were part of the Parallel Extenstions CTP.

I then went on to from scratch create my own simple PLINQ – Windows Presentation Foundation (WPF) application.

I chose WPF to test a small feature I hadn’t made use of yet only because I happened to stumble upon it on that day; Routed Events see this StackOverflow question.

Once I completed my take on a LINQ processing demo based on 2 minutes of video showing the operation of ‘Baby Names’, I discovered (by accident*) the Visual Studio 2010 and .NET Framework 4 Training Kit – May Preview, which contains the demo code for what I was trying to re-create.

*The accident in which I discovered the Training Kit, was I actually performed a google image search on the term ‘PLINQ’ to see what came up for ideas for a graphic to add to this post. The 11th image (centre screen) was the baby name graph displayed in theWhirlwind Tour of .NET 4 presentation. The post that had the image was from Bruno Terkaly, the post was about the tool kit, great!

VS 2010 Training Kit May Preview

VS 2010 Training Kit May Preview

None the less, my not-as polished demo application, makes use of the StackOverflow creative commons data dump (actually the Sep 09 drop).

Some background: I grabbed the StackOverflow data dump via the LegalTorrents link, then I followed this great post from Brent Ozar, where he supplies code for 5 stored procedures to create a table schema and import the XML data into SQL Server. It was as simple as running them, and then writing 5 exec statements and waiting the ~1 hour to load the data (resulting for me in a 2.5 gig DB).

The way I structured a lengthy processing task that can benefit from parallel processing, is by making use of the Posts data (questions and answers), in particular questions with an accepted answer. I make an attempt through a repetitive simple string comparison process to determine how valid the tags on the question are, by scanning the question text for the tags, and counting frequency. Then timing the processing of sequential operation vs the parallel operation as I pipe varying levels of data into the function.

First I extract the data into memory from SQL Server (using LINQ to SQL Entities). Just a note on the specifics of the SO Data Dump structure; ‘Score’ is a nullable int so just to keep the data set down in volume I select posts that have some score and greater than a selected input (usually 10+ at least 1 person liked it), same with a reasonable amount of views (on average 200+).

private IEnumerable<Post> GetPosts(int score, int views)
{
   var posts = from p in db.Posts
           where (p.Score ?? 0) > score
           && p.ViewCount > views
           select p;

   return posts.ToList();
}

The next step was to create a function that would take some time to process, and of course potentially benefit from being run in parallel. Each post and it’s tags are operated in isolation, so this is clearly prime for separation over multiple cores. Sadly my development laptop only has 2 cores.

private bool IsDescriptive(Post p)
{
   //lengthy boring code
   //pseudocode instead:

   var words = extract_all_unique_words_from_the_post();
     //excluding punctuation
     //and other formatting details (markup).

   var tags = extract_tags_from_post();

   return were_the_tags_used_enough_in_post(words, tags);
}

Note: A more sophisticated algorithm here could help actually determine (and recommend) more appropriate tags based on word frequencies, but that’s beyond what I have time to implement for performance testing purposes. It would need to know to avoid common used words such as ‘the’, ‘code’, ‘error’, ‘problem’, ‘unsure’, etc (you get the point). It would then need to go further and know what words actually make sense to describe the technology (language/environment) the stack overflow question is about.

The Parallel operation is applied to a ‘Where’ filtering of data and this is where the timing and the reporting of the performance is based on. Making use of System.Diagnostics.StopWatch.


//running sequentially:
posts.Where(p => IsDescriptive(p));

// vs making use of parallel processing:
posts.AsParallel().Where(p => IsDescriptive(p));

On average this function making use of .AsParallel(), for varying records quantities from 100k to 300k would result in a 1.75 times speed up over the function operating sequentially on a single core. Which is what I was hoping to see.

All this was performed on a boot from VHD instance of Windows 7 (a great setup guide by Scott Hanselman here) with Visual Studio 2010 Beta 1 and SQL Server 2008, so I do understand there was some performance hit (both running as a VHD and having SQL on the same machine) but on average for effective PLINQ setup functions there was at least a 1.6 times factor speed up.

It’s that simple; it doesn’t do much yet, but there is potential for improved/more-interesting data analysis and performance measuring of it too. I will make time to clean up the demo application and post the solution files in a future post, so stay tuned for that. When I get a chance I’ll also try to investigate more of the data manipulations people are performing via data mining techniques and attempt to re-create them just for more performance tests. When I do I’ll be starting here.

That’s it, I’ll have a follow up post with some more details in particular the types of queries I had that did not benefit from PLINQ once I get a chance to determine how they were flawed or if they simply just run better on a single thread/core.


Quarterly Technology Briefing, Melbourne Q3 2009

September 16, 2009

This morning I attended the Thoughtworks Melbourne Quarterly Technology Briefing event at the Westin.

It was an interesting sessions with 2 key speakers. The format was basically 2 by approx 40 minute presentations, each presenter giving their take on a single topic of ‘Agile Governance’ and how adoption of it improved their respective organisations; to delivery improved quality products and achieve their specific needs of process improvement. The speakers were introduced by Lindy Stephens, Professional Services Manager at Thoughtworks, and she gave a 10 minute introduction to some history around Agile.

First up was Nigel Dalton, GM IT, Lonely Planet whose presentation focussed on how agile was the most logical and most valuable shift Lonely Planet was able to undertake a few years ago. Nigel was a terrific presenter with solid and interesting metaphors for the process.

His first slide made reference to a historical event involving the action of a “Burning Boat” with a nice image of a large ship engulfed in flames. This extreme situation was a metaphor and served as an to parallel to committing soldiers (consultants/developers/resources) to a battlefield (client engagement) and burning the transport mechanism to prevent a revolt (no choice, no turning back, keep going forward). This has some scary truths in how an organisation will commit extensively making it next to impossible to withdraw (pause and regroup) even if the logical and wise choice is to withdraw and try again. Of course not always at the highest level (i.e. entire project) but aspects, features, deliverables.

As a side note the burnt boats scenario was a reference to a documented historical event by a Conquistador Hernán Cortés during the Spanish conquest of the Aztec Empire. The concept was summed up well in a discussion with my friend the Urban Mariner:

Conquistador’s were different from regular armies, as that they operated more like Privateers. They were motivated purely by the promise of a share of the spoils, rather than service to the crown. As such, a captain maintained control only by exerting control over the prize. Cortés ‘burning’ his ships motivated his men to keep their eyes on the mission, as that was their only hope of escaping and claiming their share.

Nigel went on to discuss one of the greatest hurdles to overcome, on the path to successful agile adoption; combating ingrained “illusions of control“. His recommendation for this is to attempt to prove to stakeholders that the improved transparency of agile will be of far greater benefit. In that there will be more timely and accurate information, and no forced ’spin’ on the results in a single monthly status meeting. A downside of this (initially) is the level of criticism invited by having everyone able to see detailed concepts, such as; daily burn-down and velocity metrics. But this should not be a disincentive to proceed with agile adoption. The advice here is be patient and bring those willing to be involved in as deep into the process as you can spare time for.

A key concern for those resisting agile adoption is often the question: Where are the guarantees? In particular the lawyers and bean counters (accountants). Nigel described a (still not completely resolved) situation of a long standing practice of accountants is the desire to classify a project/product as “Finished” and “Final” only to simplify their accounting practices; to begin the accounting process of depreciating the value of that asset. The challenge here is to shift the understanding and help revise the practices of other business processes to better suit what is required under an agile methodology, which is at its heart forever iterative.

The final comment from Nigel was a ‘yes’ to a simple question of using outsourcing in conjunction with an agile delivery model. Proven in their situation for their style of product making use of technology to still perform the necessary aspects of running agile; scrum, storyboards, cards, etc. They were able to successfully work with a team with a 2 hour time delay, potentially larger delays could hinder necessary activities, like scrum sessions.

The second speaker was Josh Melville, Executive Manager, Suncorp. Josh was discussing how a large complex corporate consolidation of Suncorp involving 9 separate divisions obtained through various mergers and acquisitions was undertaken. How adopting a corporate wide agile approach to all aspects of their business allowed them to consolidate and improve key processes. The scenario for moving a large corporate mesh of business units into 1 single method, required buy-in from all levels outlining that the greatest challenges were in-fact people. People in a sense were also a concern for Nigel making a bold but accurate statement as a key issue was “quality of talent”.

The approach Suncorp took was to allow their business units to be self-organising and self-directing in line with a larger business plan. Josh went further to outline how buy in from typically resistive parts of businesses i.e. “Risk & Compliance” departments was essential. To support the claim made by Nigel, once these departments were made aware of the increase visibility it allowed for much greater risk assessment. Through such agile tactics as; investigate, build and test the components with greatest risk first, allowing artefacts of a project that will not succeed or haven’t been thought out well enough to be dropped before they cause damage (waste resources). As a result Suncorp was able to get a more extensive buy-in from a broader base of their business.

Key Takeaways:

  • Agile will work if there is complete buy-in.
  • People need to be made aware of the benefits and allowed to adapt in time to the changes.
  • Old thinking of “final deadline”, “total cost” and “total time” are no longer valid.
  • It is absolutely necessary to have people questioning the flow and hitting an imaginary alarm button to get attention.
  • Stay lean.
  • Illusion of control is dangerous and detrimental.
  • There is immense value in true transparency.
  • Just like the coding practice; fail early, fail fast, and fail cheaply, recover and move forward.

LINQ Basics (Part 2) – LINQ to SQL in .NET 4.0

September 13, 2009

Continuing my 3 part series on LINQ Basics, here I will attempt to discuss a few improvements in LINQ to SQL as part of the .NET 4.0 release scheduled soon. A key post on the 4.0 changes is by Damien Guard who works on LINQ at Microsoft along with other products. This will allow me to discuss some of the changes but also go into a bit more detail extending the “basics discussion” started in the previous post.

Note: In October 2008 there was a storm of discussion about the future of LINQ to SQL, in response to a focus shift from Microsoft for “Entity Framework”, the key reference post for this is again one by Damien G.

The upcoming 4.0 release doesn’t to cause damage to the capability of LINQ to SQL as people may have been worried about (i.e. disabling/deactivation in light of the discussions of Oct 2008). There are actually a reasonable amount of improvements, but as always there’s a great deal of potential improvements that there was not capacity/desire to implement for a technology set that is not a major focus. But LINQ to SQL is still capable enough to function well to be used for business systems.

First up there are some performance improvements in particular surrounding caching of lookups and query plans in it’s interaction with SQL Server. There are a few but not all desired improvements in the class designer subsystem, including support for some flaws with data-types, precisions, foreign key associations and general UI behaviour flaws.

There is a discussion on Damien’s post about 2 potential breaking changes due to bug fixes.

  1. A multiple foreign key association issue – which doesn’t seem to be a common occurrence (in any business systems I’ve been involved in).
  2. A call to .Skip() with a zero input: .Skip(0) is no longer treated as a special case.

A note on .Skip(), such a call is translated into subquery with the SQL NOT EXISTS clause. This comes in handy with the .Take() function to achieve a paging effect on your data set. There seems to be some discussion on potential performance issues using large data sets, but nothing conclusive came up in my searches, but this post by Magnus Paulsson was an interesting investigation.

As for the bug It does seem logical to have treated it as a special case and possibly help simplify code that might be passing a zero (or equivalent null set), but if it was an invalid case for .Skip() to be applied to with a value greater than zero it will fail forcing you to improve the query or its surrounding logic.

Just for the sake of an example here is .Skip() & .Take(). Both methods have an alternate use pattern too: SkipWhile() and TakeWhile(). The while variants take as input a predicate to perform the subquery instead of a count.

var sched = ( from p in db.Procedures
             where p.Scheduled == DateTime.Today
             select new {
                      p.ProcedureType.ProcedureTypeName,
                      p.Treatment.Patient.FullName
                     };
                ).Skip(10).Take(10);

There are also improvements for the use of SQL Metal which is the command line code generation tool. As a side note to make use of SQL Metal to generate a DBML file for a SQL Server Database execute the command as such in a Visual Studio command prompt:

    sqlmetal /server:SomeServer /database:SomeDB /dbml:someDBmeta.dbml

LINQ Basics

September 11, 2009

As part of preparation work I’m doing for a presentation to the Melbourne’s Patterns & Practices group in October on LINQ and PLINQ. I thought I would cover off the basics of LINQ in .NET 3.5 and 3.5 SP1 in this post. The changes in .NET 4.0 in the next post, and then a discussion about PLINQ in a third post.

O.k. so let’s sum up the basics. The core concept of LINQ is to easily query any kind of data you have access to in a type-safe fashion. Be it SQL Server stored, a collection (i.e. something implementing IEnumerable) or an xml data structure. A further addition to this power is the ability through C# 3.0 to create projections of new anonymous structural types on the fly. See the first code sample below for the projection; in that simple examples it’s the creation of an anonymous type that has 2 attributes.

Continuing on with my “medical theme” used for the WCF posts, here is a simple schema layout of the system, consisting of a patient and a medical treatment/procedure hierarchy. This is given the title of ‘MedicalDataContext’ to be used in our LINQ queries.

Medical System Basic Schema

Medical System Basic Schema

These items have been dragged onto a new ‘LINQ to SQL Classes’ diagram from the Server Explorer > Data Connections view of a database.

Server Explorer Window

Server Explorer Window

To create the ‘LINQ to SQL Classes’ diagram simply add …

Add New Item

Add New Item


a new …
Linq to SQL Classes

Linq to SQL Classes

Back to the logic. We have a Patient who’s undergoing a certain type of treatment, and that treatment has associated procedures. To obtain a collection of procedures for today, and the name of the patient who will be attending we simply build up a new query as such:

var db = new MedicalDataContext();

var sched = from p in db.Procedures
            where p.Scheduled == DateTime.Today
            select new {
                     p.ProcedureType.ProcedureTypeName,
                     p.Treatment.Patient.FullName
                    };

Note: The patient table structure doesn’t have a field called ‘FullName’ I make use of a partial class extending its properties to add a read-only representation, check out this post by Chris Sainty for more info on making use of partial classes with LINQ.

At this point we can now iterate over each item in our ’sched’ (scheduled procedures) collection.

foreach (var procedure in sched)
{
   //process/display/etc
}

This brings me to another key point ‘Delayed Execution’ or (‘Deferred Execution’) check out Derik Whittaker’s: Linq and Delayed execution blog post for a more detailed walk through.

Basically the query we defined earlier is only a representation of the possible result set. Therefore when you first make a call to operate on the variable representing the query results, that’s when execution will occur.

So it becomes a program flow decision whether to always execute the query live when it’s being processed (i.e. most up-to-date data) or to force a single execution then make use of that data in the current process flow. A forced execution can be easily achieved several ways, the simplest choice is to just create a new list object via ToList() to execute the fetching of the data.

var allProcedures = todaysProcedures.ToList();

So far this has all revolved around accessing data in a SQL Server Database (the setup of a LINQ to SQL class). LINQ’s purpose is to be able to query any form of collection of data.

Now let’s say we wanted to obtain some information through recursion of a class using reflection.

Note: a business case for the use of reflection is often tied very deeply into some limitation, special case, etc. So a more specific example would take us well away from the topic of LINQ. So will keep this example trivial, this could just as easily manipulate a more useful class object to interrogate it.

var staticMethods =
    from m in typeof(string).GetMethods()
    where !m.IsStatic
    order by m.Name
    group m by m.Name into g
    select new
      {
         Method = g.Key,
         Overloads = g.Group.Count()
      };

Which output element by element will generate this output:

  { Method = Clone, Overloads = 1 }
  { Method = CompareTo, Overloads = 2 }
  { Method = Contains, Overloads = 1 }
  { Method = CopyTo, Overloads = 1 }
  { Method = EndsWith, Overloads = 3 }
  . . .

For an off-topic discussion, check out this article by Vance Morrison post titled Drilling into .NET Runtime microbenchmarks: ‘typeof’ optimizations, as a discussion of the use of ‘typeof’ in my above query.

For a more typical business case example using a LINQ statement to fetch a collection of controls and operate on them (in this case disable them). Here we’re operating on a Control collection.

Panel rootControl;

private void DisableVisibleButtons(Control root)
{
   var controls = from r in root.Controls
                       .OfType<Control>()
                   where r.Visible
                   select r;

    foreach(var c in controls)
    {
        if(c is Button) c.Enabled = false;
        DisableVisibleButtons(c);  //recursive call
    }
}

//kick off the recursion:
DisableVisibleButtons(rootControl);

Summary:

  • LINQ to SQL generates classes that map directly to your database.
  • LINQ helps you manipulate strongly typed results (including intellisense support).
  • “LINQ to SQL” is basically “LINQ to SQL Server” as that is the only connection type it supports.
  • There is a large set of extension methods out of the box check out for samples: 101 LINQ Samples.

Package-up a SketchFlow Project

August 27, 2009

A key objective of using SketchFlow in the prototyping phase is to gather feedback from key users. So once you have your prototype to a state where you would like users to start exploring it, you can package up the project.

File Menu Select Package SketchFlow

File Menu Select Package SketchFlow

Then select a name and location:

Package Name and Location

Package Name and Location

This exports a compiled Silverlight application file (a XAP).

Making use of the PowerShell script I created in my previous post it will extract the HTML and XAP file from the package folder and zip them up.

It is then ready to send off to eager users, who simply open the html file in their browser of choice (with Silverlight installed).

Note 1: In more sophisticated or larger SketchFlow projects the process of only extracting out the XAP file may remove functionality within the prototype so it is highly advised that you test each screen in your prototype.

Note 2: If you’re pedantic about details, the HTML page can be renamed to be more detailed about the project instead of it’s project filename.

<head>
    <title>My Prototype 1 - Design Phase</title>

A File Copy and Compress – PowerShell Script

August 27, 2009

Following on from my previous post. I’m creating a PowerShell script that takes an input of a file location via a dialog. Extracts some files through a copy action, and compresses them into an archive. As I will show in the 3rd post, the purpose is to extract out 2 files to help with deploying a SketchFlow project. Such a complex script is overkill for 2 files, but is easily extensible to handle a larger set of files.

Step 1 – User input of folder:
Create a function to launch a folder select dialog, this is achieved through a com object call.

function Select-Folder($message='Select a folder', $path = 0)
{
    $object = New-Object -comObject Shell.Application

    $folder = $object.BrowseForFolder(0, $message, 0, $path)
    if ($folder -ne $null)
    {
        $folder.self.Path
    }
}

Note: Could call this twice to prompt user for output location also.
OR
To speed up script execution supply input parameter(s) to the script [input (and output) directory].

To achieve this simply use $args[0] (and $args[1]) instead of the Select-Folder cmdlet call.

The Select-Folder cmdlet launches:

Browse For Folder Dialog

Browse For Folder Dialog

Step 2 – Extract (via copy) the deployable files:
There are 3 tricks here; first extracting only files via not PSisContainer, grouping them via their extensions (in order to easily process them in a copy loop) and matching only a list of valid extensions (in this case xap and html).

$types = ".xap", ".html"

$files=  Get-ChildItem $folder | Where-Object {-not$_.PSisContainer} | Group-Object Extension 

$files = $files | Where-Object {$types-contains$_.Name}

New-Item -itemType Directory -path $deploymentFolder -ea SilentlyContinue

$files | ForEach-Object { $_.Group | Copy-Item -destination  $deploymentFolder }

Tip: use Some-Cmdlet | Format-Table or its variants to output details to screen to help with debugging.

Step 3 – Compress
This last step in the script is a compression action. I got the compression functions from David Aiken’s MSDN blog post. The Add-Zip function was unable to take a file path containing a directory-up (\..\), so the final script has Move-Item cmdlet line to compensate.

function Add-Zip
{
    param([string]$zipfilename)

    if(-not (test-path($zipfilename)))
    {
        set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
        (dir $zipfilename).IsReadOnly = $false
    }

    $shellApplication = new-object -com shell.application
    $zipPackage = $shellApplication.NameSpace($zipfilename)

    foreach($file in $input)
    {
            $zipPackage.CopyHere($file.FullName)
            Start-sleep -milliseconds 500
    }
}

The complete script file can be found here on Gist.GitHub.

The next step in this script could be to email the newly created zip file, but that’s something for a future post.


A Look Back at Discovering PowerShell

August 27, 2009

This is part 1 of a 3 part series, in which I will be creating a PowerShell script that accepts as input a folder location via a standard windows popup dialog and then performs some repetitive action. I’ll get to the details in the next post where I actually build the script. In the 3rd post will be putting it to use…

But first some background on PowerShell and some details on my awkward attachment to it, back in December 2007 I attended a Readify (RDN) session about PowerShell presented by Mitch Denny and was blown away by its potential and power, along with an attention grabbing demo of it running a Space Invaders game. I proceeded to adapt his demo and do my own investigation and the following month demonstrated the PowerShell concepts internally to my colleagues who specialise in the .NET development space.

I was trying to promote the use of PowerShell to replace a large collection of batch (.bat) scripts we were using at the time across many projects, to do things ranging from mass source control check-outs/check-ins to building deployments of production packages, yes **shudder**. Sadly more often than not, I did not make time to improve and replace all batch scripts I encountered either through the use of PowerShell or alternate approaches to running a script.

Double checking with this post on the MSDN PowerShell blog, I can confirm that at the time it was the first CTP release of PowerShell 2.0 that got my attention. With my switch now to Windows 7 and currently working on a new laptop it was fantastic to see an already installed out of the box PowerShell, which I simply searched for by typing into my start menu.

A few months back I discovered a site that got my attention again with little tips and video tutorials about using PowerShell, sadly a lot of their videos are no longer available, but I still subscribe to an almost daily newsletter with 1 single tip per day. So for a while I’ve been amassing the emails from PowerShell.com in one of my gmail accounts, labelling them thinking “oh that’s cool tip” but not having the time to test it out. Well the other day the “perfect” tip for a planned task came along to get me cracking on this script and blog posts.

In the next post I’ll be running through its actual creation.