torsdag, januari 21, 2010

 

Deploying applications to Windows and Windows Phones which supports dynamic modules

Many .Net applications being developed today are leveraging the greatness of dependency injection using some sort of inversion of control-container. So do we at RemoteX when we develop the product called RemoteX Applications. The product has two client applications which roughly adresses the same use cases. One is targeting desktop computers and the other one is targeting Windows Phone (you can read more here and here).

As you can tell by the name, the product consists of several applications (or rather modules). Using frameworks like Prism or Caliburn we can, in code, easily manage each part of the product. And the deployment is taken care of using ClickOnce technology using mage.exe (the MAnifest GEnerator).
But that's for the desktop client targeting WPF.

So the big question is, how are we going mobile with this?

What regards an inversion of control-container we are "almost there". We have a home-grown container in place which have been around for a while now, even though it lacks some basic features you would expect an ioc container of year MMX to have.
Speaking of deployment to the Windows Phone you probably know you are kind of locked to using CABinet files. If you are using the tools Microsoft brought to us, you probably also use their Device Setup projects in Visual Studio.
They are good, but you must use Visual Studio to choose the contents of and create/build your CAB file.
What this basically means is that we need to use devenv.exe to build each customer's customized CAB file.
So up til now we have not had per customer customized CAB files.

All I wanted was ClickOnce technology and a manifest generator for the Windows Phone. So what's the solution on that?
Say hello to the PowerShell script New-CabWizInf.ps1:

.\New-CabWizInf.ps1 -path .\myapp.inf -appName "My Application" -manufacturer "RemoteX" -fromDirectory .\MyApplication\bin\Release

It works like mage.exe with its -fromDirectory switch and creates the necessary .inf-file (like an Visual Studio Device Setup project would). All needed from that point is to call CABWIZ.exe and Set-AuthenticodeSignature in PowerShell to create and sign the CAB file.
The real power is the -fromDirectory switch which allows us to create custom CAB files on the fly.

So here is a peek of what our setup package scripts now looks like:

Setup Package for Windows using ClickOnce
mage -new deployment -tofile MyApp.application -fromdirectory bin\Release -name "My App" -publisher "RemoteX"
mage -sign

Setup Package for Windows Phones using CAB files
.\New-CabWizInf.ps1 -path MyApp.inf -fromDirectory bin\Release -appName "My App" -manufacturer "RemoteX"
cabwiz MyApp.inf /dest .\
Set-AuthenticodeSignature .\MyApp.CAB

So right now I'm a very happy camper since our packaging tools for Windows AND Windows Phone have equal capabilities which allows us to use dependency injection with dynamic module selection.

Next stop, Prism and Silverlight for the Windows Phone?

Etiketter: , , , , , ,


onsdag, november 11, 2009

 

Pimping PsUnit with constraint based assertions

Using PsUnit one can set up scripted "unit tests" for PowerShell scripts. I have sort of just started using PsUnit at work and right now I feel that a lot of the basic features of other test frameworks are missing.
PsUnit has one function for doing constraint based assertions. This may be familar to those who are using NUnit. Basically the syntax for this is:


Using NUnit and this constraint based model, a simple assertion can look like this:


I quite don't like the "barebone" scriptblock you need to write to use Assert-That in PsUnit, so here is what I came up with (using my example of above):


I also added another constraint which allows you to assert that some code throws something:

This complements the already built-in feature of PsUnit which allows you to add a parameter, $ExpectedException, to the test. If you have been using MSTest you would use the method attribute ExpectedException for this.

Here is another example which tweaks the constraint to a somewhat more specific type of exception:


A more usable test using the ThrowsException constraint could be:


The biggest improvement using these new constraints is the output in the test result.
While using PsUnit out-of-the-box...

...results with "Assert-That returned false!" in the test result.
Using the constraint in this blog post...:

...results with "ActualValue 'bar' is not equal to expected value 'foo'".

The same level of detail is provided by the ThrowsException constraint, which may result in "No exception was thrown, expected exception of type 'System.ArgumentException'".

Any ideas, suggestions etc.? Please don't hesitate to drop a comment!

Etiketter: , ,


 

Integrating PsUnit and MSBuild

The last month I have been digging into, adding new and refactoring the Powershell scripts we use in RemoteX Applications. We primarily use PowerShell to configure and deploy our product.
More often or too many times - with our latest releases - our fellow collegues at Customer Operations have been telling us "The xyz powershell script doesn't work anymore, what have you done to it???"
I could have answered: "- We don't have automated tests on those scripts, so what do you expect? Manual testing? Pfffff...", but for obvious reasons I didn't :).
So it was time to add some automated tests for those scripts so I could get this guy at Customer Operations back to work.

All compiled code (C#) is automatically tested in our Continuous Integration builds when someone checks in, but until now we haven't had automated tests for our PowerShell scripts. With "automated" I mean that a test runner executes a test suite during a build.
In order to test our PowerShell scripts I have started using PsUnit. Since we are using Team Foundation Server and MSBuild for our CI builds, I needed to integrate PsUnit with MSBuild somehow.

There are several ways to invoke Powershell from an MSBuild script - we have chosen the Exec task which invokes powershell.exe.
First of all I created a separate build target which invokes PsUnit:


Using this batch target, all that needs to be done is to add PsUnitTest items to the build script. Just like the way we set up TestContainer items for use with MSTest:

So far so good, but when tests are failing, the build is successful. This is because the Exec task only reports a build error when the executed command returns an exit code other than zero (0x0). So I started looking into the test runner of PsUnit (PsUnit.Run.ps1) and discovered that it didn't send any output nor produced some other exit code than 0x0. The only output PsUnit will send you is some nice colorful information written to the PowerShell host.
So I ended up with the following:
1. this tiny tweak at the end of PsUnit.Run.ps1:


This makes PsUnit.Run.ps1 send the test results along the pipeline.

2. A small wrapper for the test runner which returns some exit code other than 0x0 to the Exec task in MSBuild:


This makes the Exec task report a build error if we find any failing test in the test result from PsUnit - and last but not least - the name of the failing test and the reason ends up nicely in the MSBuild log file.

So now when somebody checks in a change to compiled code, which affects the result of our setup scripts, we will be able to detect errors ASAP! Yay!

Etiketter: , , ,


torsdag, oktober 29, 2009

 

PowerTip of the day - Variable descriptions

I just got this in my inbox from Powershell.com:
Add Descriptions to Variables

Keeping track of a variable’s purpose can be accomplished by assigning a clear text description:


$ip= '10.10.10.10'

Set-Variable ip -description 'Server IP or Name'


When you now list your variables, you can output the variable description as well:

dir variable:ip | Format-Table Name, Value, Description


Playing around a little I found out that you easily can get the same information about system/environment variables using Get-Variable and Format-Table:

PS > gv | ft Name, Description

Name Description
---- -----------
$
? Execution status of last command.
^
_
args
bla Bla bla bla
ConfirmPreference Dictates when confirmation should be...
ConsoleFileName Name of the current console file.
DebugPreference Dictates action taken when an Debug ...
Error
ErrorActionPreference Dictates action taken when an Error ...
ErrorView Dictates the view mode to use when d...

Etiketter: ,


onsdag, oktober 21, 2009

 

PowerShell Scripting Guidelines

Lately I have been doing some work related to how we automate the process of how we install, configure and deploy our product into a server environment. Since our pre-requisites are Windows Server 2008 and Windows 7, we can totally go crazy with PowerShell scripts. Next thing to sort out after upgrading to Windows Server 2008 R2 is of course PowerShell Remoting.. :)

However, using quite an amount of PowerShell scripts, we need some guidelines to structure them. This to complement our guidelines covering OO design and C# code style.

So I have started out with the following draft and I'm looking for some tips and comments about this and what you (yes, you!) believe is a good rule of thumb to use when developing and maintaining a bunch of PowerShell scripts.

(Sorry for the ugly formatting. Code was pasted from PowerGUI to a word doc and then to blogger :))

1 Scripting Guidelines

When there is a need of a script, use your mighty PowerShell skills!
Here is a couple of guidelines which should be followed to speed up development, maintenance and usage of PowerShell scripts.

Apply the above mentioned principles when applicable.

1.1 Function files

Package common functions into function files and dot-source them in the script which needs them.
Example:
. ..\DB\Common.ps1

1.2 File names

Name PS1 files using standard verbs like get, set, remove, new etc., or a verb that fits the purpose or the script. Do not use verbs in file names for files that have generic purpose, like a function library file. Also consider using PowerShell v2 modules when applicable.

Scripts that are to be called from the prompt are easier to understand if they are named in such way that no “usage” or get-help is needed when invoking the script. Like add-user.ps1, remove-database.ps1 and so on.

Avoid complex scripts with multiple purposes which becomes complex with parameter sets (get-help about_functions_advanced_parameters)

1.3 Script and function parameters

Use built-in support to handle function and script parameters. Avoid index-based unnamed parameters using $args.

Reference: get-help about_arguments; get-help about_functions; get-help about_functions_advanced_parameters
MSDN:
http://msdn.microsoft.com/en-us/library/ms714433(VS.85).aspx

Example, testme.ps1:

param(

[Switch] $ver = [Switch]::Present

)

Write-Host $args

Write-Host "Testing!"

if( $ver )

{

Write-Host "Testing even more!"

}

Output:

PS > .\testme.ps1 –ver
PS > .\testme.ps1 -ver:$false

1.4 Decorate function parameters appropriately using validation rules

Decorate your parameters with validation rules and help messages to avoid tedious work on custom “script usage” functions. Your script users will be able to use “get-help yourscript.ps1”, or the equivalent “yourscript.ps1 -?” to get script usage information. Users will also be prompted if mandatory parameters are left out blank.

Get-help will also print out common parameters (get-help about_commonparameters).

Example:

param(

[Switch] $ver = [Switch]::Present,

[Parameter(mandatory=$true, helpmessage="Your name")]

[ValidateNotNullOrEmpty()]

[string] $name = "John Doe"

)

Write-Host $args

Write-Host "Hello $name!"

if( $ver )

{

Write-Host "Your name is $($name.Length) characters long"

}

Output:

PS > get-help .\testme.ps1

testme.ps1 [-name] [-ver] [-Verbose] [-Debug] [-ErrorAction ] [-WarningAction ] [-ErrorVariable ] [-WarningVariable ] [-OutVariable ] [-OutBuffer ]

1.5 Document script usage using PowerShell comment based help

When it is necessary to document how a script can be used, or when you want to provide more information about your script’s parameters than just the name, document it using the PowerShell help syntax. This can be compared to using XML comments in languages such as C#/VB or javadoc tags in Java.

See “get-help about_comment_based_help” for more information.

Example:

<#

.Synopsis

Synopsis text here

.Description

Usage description here

.Parameter ver

Enabling this switch prints out the length of the given name

.Parameter name

The name to say hello to

#>

param(

[Switch] $ver = [Switch]::Present,

[Parameter(mandatory=$true, helpmessage="Your name")]

[ValidateNotNullOrEmpty()]

[string] $name = "John Doe"

)

Write-Host $args

Write-Host "Hello $name!"

if( $ver )

{

Write-Host "Your name is $($name.Length) characters long"

}

Output:
PS> get-help -full .\testme.ps1

NAME
C:\temp\testme.ps1

SYNOPSIS
Synopsis text here

SYNTAX
C:\temp\testme.ps1 [-ver] [-name] []


DESCRIPTION
Usage description here


PARAMETERS
-ver []
Enabling this switch prints out the length of the given name

Required? False
Position? Named
Default value
Accept pipeline input? False
Accept wildcard characters?

-name
The name to say hello to

Required? True
Position? 1
Default value
Accept pipeline input? False
Accept wildcard characters?


This cmdlet supports the common parameters: Verbose, Debug,
ErrorAction, ErrorVariable, WarningAction, WarningVariable,
OutBuffer and OutVariable. For more information, type,
"get-help about_commonparameters".

INPUTS

OUTPUTS


RELATED LINKS

1.6 Use validation rules to perform parameter input validation

PowerShell has several built-in validation rules for input validation. Use them as long as they add more value than doing custom validation using if-statements.

The built-in validation rules are: AllowNull, AllowEmptyString, AllowEmptyCollection, ValidateCount, ValidateLength, ValidatePattern, ValidateRange, ValidateScript, ValidateSet, ValidateNotNull, ValidateNotNullOrEmpty
See “
get-help about_functions_advanced_parameters” for further reference.

1.7 Putting the right stuff on the pipeline

· Use write-host for console information with fancy colors

· Use write-output to be able to pipe your script/function to another script/function.
Example pipeline scenario, sending a user from add-user to new-guestbookentry:
. .\guestbooks-functions.ps1;
add-user “foo” “password” | new-guestbookentry “Welcome to our guestbooks.com!”

· Avoid unwanted objects on the pipeline using termination with $null assignments or piping the output to NULL, example:
add-user “foo” “password” # put the added user on the pipeline
$null = add-user “foo” “password” # added user object “terminated”
add-user “foo” “password” | out-null # added user object piped to NULL instead of the output

Etiketter: , ,


torsdag, augusti 20, 2009

 

Note to self: Windows is getting sensitive with the IIS PowerShell provider

Today I have struggled with some of the most basic automation tasks with the new IIS 7 web server; Creating a web site, application pool and application using a PowerShell script.

Starting out with this tutorial I managed to use the following sample to accomplish my task:

New-Item IIS:\Sites\DemoSite -physicalPath C:\DemoSite -bindings @{protocol="http";bindingInformation=":8080:"}

Set-ItemProperty IIS:\Sites\DemoSite -name applicationPool -value DemoAppPool

New-Item IIS:\Sites\DemoSite\DemoApp -physicalPath C:\DemoSite\DemoApp -type Application

Set-ItemProperty IIS:\sites\DemoSite\DemoApp -name applicationPool -value DemoAppPool


Everything worked fine with the samples and I started to setup a testing environment on my machine. That involved setting up a local IIS 7, creating some directories in the file system for my test website etc.
All tasks seemed to work, but I repeatedly got the following error when trying to assign the correct application pool to the application:

Set-ItemProperty : Value cannot be null.
Parameter name: path
At C:\.....\WebSetup.ps1:37 char:17
+ Set-ItemProperty <<<< IIS:\Sites\DemoSite\Server -name applicationPool -value DemoAppPool


I tried to use other cmdlets to change the application pool setting, but with no success. I also tried to change all paths, the name of the web site etc. according to the sample. The sample code worked, but the error remained when executing Set-ItemProperty in my script.
I doubled checked the documentation, the sample, the value given to the parameter -Path - but it still failed.
I was just going to post a question about this matter in some forums when I figured it all out.

The name of the directories I created in the file system was using lowercase characters, but not the entries in the IIS configuration!


The cause of this must be the code in either the file system provider or the IIS provider for PowerShell. Some part of the code which is executed when invoking the Set-ItemProperty cmdlet is doing some case sensitive work..
The lesson and recommendation after this experience is that I will try to create both my entries in the file system and in the IIS configuration from the same script. :)

Windows is definitely getting more and more sensitive these days...

Etiketter: , ,


lördag, april 11, 2009

 

Groovy, RESTful Grails and jQuery - where are we heading in .Net land?

While we heavily focus on Windows Communication Foundation at work my collegue Morten has made some interesting developments with Grails and jQuery lately. Hosting provided by mor.ph, the PaaS he have chosen to use.



For almost one and a half year ago the team I work in decided to move all scripting efforts to PowerShell instead of using other scripting technologies for our system.
(Worth to notice here is that the whole system is built up around the Microsoft .Net platform - with extra salt and pepper.. You got WPF, Team System, PowerShell, etc.).



Now that we got PowerShell we can do quite neat things in scripts that are built upon our classes and system modules written in C#. For example, writing a script which adds an user to the system using our domain model implementation (written in C#) and a REST client is no biggie at all. (the way it should be)

So where are we heading in .Net land to achieve more with less?
I believe we are in a huge need of languages such as PowerShell and IronPython.

Do we need an equivalent for Groovy or are we just fine with IronPython, PowerShell or maybe we should move our attention to the wrist friendly Boo?


What I want is to write RESTful Web Services with very few self-explanatory lines of code, hosted by WCF. Is that possible?
Where is the Groovy in my RESTful .Net land?

Etiketter: , , , , , , , , ,


Prenumerera på Inlägg [Atom]