Thursday, March 26, 2009

Fxcop stylesheet

For some reason FxCop still points to a stylesheet from gotdotnet which is broken.

Today we had a requirement to generate static code analysis report in a simple tabular form.

Following snippet did the job. You can apply any css on this for better look. Or even set style for table, tr and td.

<?xml version="1.0"?>
<
xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<
xsl:template match="/">
<
html>
<
body >
<
table>
<
xsl:for-each select="//Issue">
<
tr>
<
td><xsl:value-of select="@Certainty"/></td>
<
td><xsl:value-of select="@File"/></td>
<
td><xsl:value-of select="@Line"/></td>
<
td><xsl:value-of select="../@FixCategory"/></td>
<
td><xsl:value-of select="@Level"/></td>
<
td><xsl:value-of select="."/></td>
</
tr>
</
xsl:for-each>
</
table>
</
body>
</
html>
</
xsl:template>
</
xsl:stylesheet>

Just thought of sharing it.

Monday, March 23, 2009

Program Files folder in X64

While qualifying one of our projects for X64, we encountered issue with Program Files folder.

We use Wix for building msi package.

Wix could get %PROGRAMFILES% variable from OS and place files appropriately at C:\Program Files (x86)\

But our product was looking at C:\Program Files.

I prefer picking up any paths from app.config files and delegate task to Wix to update application specific configuration files during installation. This makes life so simple when moving between x86 and x64.

Here I am referring to running x86 stuff as is on x64. Rules change when we compile code for X64.

Friday, March 20, 2009

Internet Explorer 8 Released

Microsoft Released Internet Explorer 8 today. Its app 17 MB download and took 8 minutes to install.

And recommends to restart system after reboot. Compatibility mode, developer tools, quick search in address bar are few impressive things. Private browsing is just like any other new age browser feature. It is supported on

Find release notes at http://msdn.microsoft.com/en-us/ie/dd441788.aspx

Java 6 update 11 is recommended version for viewing Java Applets.

Sunday, March 15, 2009

Clickonce installer with example

Smartclient is a nice concept for occasionally connected applications. A windows forms application or a WPF application can be made available for easy deployment from a webserver, file share etc.. Not only that it can also serve as an update server too.

Though Wix ClickThrough is another concept for similar use, both got unique advantages. And I feel clickonce is the option for today while and clickthrough is evolving.

In this post I would like describe some of the basic concepts of clickonce. I feel this would be useful for anyone starting with clickonce. Let us start with a bit basic theory then move on to infrastructure required to do this and then to an example.

Concept

The core ClickOnce deployment architecture is based on two XML manifest files –Application manifest and Deployment manifest.

The application manifest describes the application itself, including the assemblies, the dependencies and files that make up the application, the required permissions, and the location where updates will be available.

The deployment manifest describes how the application is deployed, including the location of the application manifest, and the version of the application that clients should run.

Following diagram shows how versions will be maintained in webserver. Each version will have its own Application Manifest file.

At any time deployment manifest points to one of the versions. Deployment manifest contains an URI which client tries to access from web browser. Click once infrastructure sends pointed version to client. If client contains that version previously then download doesn’t takes place, rather application is launched in client. Else assemblies of that version will be copied to client.

image

In Client each version is stored in separate directory in application cache which is typically at “C:\Documents and Settings\username\Local Settings\Apps\2.0\<xx>”. In addition click once application gets added to add/remove programs (if install option  is selected in deployment manifest). In such case application automatically gets added to start menu also. Applications also run under Code Access Security purview. By default click once application gets deployed with Full trust permissions. However this can be tuned in application manifest.

Also click once applications can be updated automatically. Assume that client has 1.0.0.0 version installed. Click once applications can be configured to check for new updates during start up (Other options are also available like, after start up, periodically etc.). During start up if application detects if deployment manifest is pointing to new version. If so then it prompts user to update to new version. If user prefers to update new version is downloaded and made as default version. Incase user is not comfortable with updated version, he or she can prefer to un-install latest update and rollback to previous version. This roll back can be done as many times till lower version is available.

In case of large applications downloading entire application in one lot may not be very much acceptable. For such scenarios click once offers optional group mechanism. With this initial download happens for required assemblies only. Options groups will be downloaded on demand.

With this background let us move to infrastructure needed for this.

Infrastructure

Click expects .Net 3.0 to be available in target applications. If your application depends on higher version of  .Net framework, then that becomes as necessary pre-requisite. Pre-requisites can be handled using bootstrapper. I will not cover bootstrap here. Let us assume required .Net framework version is available in client machine.

As mentioned above clickonce installation is nothing but “target assemblies + application manifest” + “deployment manifest”. Assemblies are built by developer. Then manifests can be built using mage.exe or mageui.exe. This is part of Windows SDK. Thus if you have Visual Studio 2005/2008 installed on your machine then you have both of these tools.

Apart from these developer also needs a “Personal Information Exchange (.pfx)” file to sign manifests. Signing manifests is mandatory. You may find this post useful to create a pfx file.

Thus to summaries this section. We need following set of files to create click once installation setup

  1. Application assemblies
  2. Personal Information Exchange File (pfx)
  3. mege.exe or mageUI.exe

Now let us start on example.

Example 1 - Basic

Let us take a forms application. As a first step let us try to create a clickonce installation setup for this forms application.

Just start Visual Studio and create a forms application by name “MyWebForm”. Just change Form title to “MyWebForm”. That is it nothing else. Build Release version. So MyWebFormApp.exe is the only file we want to create clickonce installation setup.

In IIS create a virtual directory by name MyWebForm. Under that create a subdirectory by name “1.0.0.0”. And copy MyWebFormApp.exe  to that folder.

image

Now start mageui.exe from “C:\Program Files\Microsoft SDKs\Windows\<v6.0A>\Bin\”.

Create application manifest

image

  1. Click on File – > New – > Application Manifest
  2. Enter Name as MyWebFormApp
  3. Enter version as 1.0.0.0
  4. Select ‘Files’ from list box then select application directory. In this case it is “C:\Inetpub\wwwroot\MyWebForm\1.0.0.0”
  5. Click on populate.
  6. Then save manifest to folder 1.0.0.0 as “MyWebFormApp.exe.manifest”. MageUI prompts to sign application before saving. Select pfx file and click on save.

 

Create deployment manifest

image

  1. Click on File – > New – > Deployment Manifest
  2. Enter Name as MyWebFormApp
  3. Enter version as 1.0.0.0
  4. Select ‘Description’ from list box enter product name
  5. Select ‘Deployment Options’ from list box enter start location as “http://<webserver>/MyWebForm/MyWebForm.application”
  6. Select ‘Update Options’ from listbox and check on “Before Application Starts”
  7. Select ‘Application Reference’ from listbox and click on ‘Select Manifest’
  8. Select “MyWebFormApp.exe.manifest” from “C:\Inetpub\wwwroot\MyWebForm\1.0.0.0\” folder
  9. Then save manifest to folder “C:\Inetpub\wwwroot\MyWebForm\” as “MyWebForm.application”. MageUI prompts to sign application before saving. Select pfx file and click on save.

Installing first version

Open browser and browse to “http://<webserver>/MyWebForm/MyWebForm.application”

A window pops us prompting to install. Click on install. Application starts automatically and form is shown

You can also observe a new start menu short cut and an entry in Add/Remove programs.

 

So that is quite simple. Now let us add an optional package.

Example 2 – Optional group

Before we proceed uninstall application installed in last step from Add/Remove programs.

Add another project

Now let us create another form project to solution file by name “MyWebFormOptional1”.

Add reference of this project to main project.

Also add a button to main form MyWebFormApp. In button click event add code to launch second form.

        private void button1_Click(object sender, EventArgs e)
{
MyOptionalForm1 opt1 = new MyOptionalForm1();
opt1.ShowDialog();
}




Update code to Dynamically load assembly



Idea here is to make MyWebFormOptional1 as optional group. Thus when click once application is downloaded first time only MyWebFormApp gets downloaded. Upon clicking on button “MyWebFormOptional1.exe” gets downloaded.



In order to this we use Application.LoadFile method. Copy paste following code in MyWebForm.cs



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Reflection;
using System.Deployment.Application;
using System.Security.Permissions;
using System.IO;
using MyWebFormOptional1;

namespace MyWebFormApp
{
public partial class MyWebForm : Form
{
Dictionary<String, String> DllMapping = new Dictionary<String, String>();

[SecurityPermission(SecurityAction.Demand, ControlAppDomain = true)]
public MyWebForm()
{
InitializeComponent();

DllMapping["MyWebFormOptional1"] = "MyWebFormOptional1";
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}


/// <summary>
/// Use ClickOnce APIs to download the assembly on demand.
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
/// <returns></returns>
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
Assembly newAssembly = null;

if (ApplicationDeployment.IsNetworkDeployed)
{
ApplicationDeployment deploy = ApplicationDeployment.CurrentDeployment;

//MessageBox.Show(args.Name);

// Get the assembly name from the Name argument.
string[] nameParts = args.Name.Split(',');
string assemblyName = nameParts[0];
string downloadGroupName = DllMapping[assemblyName];

try
{
deploy.DownloadFileGroup(downloadGroupName);
}
catch (DeploymentException de)
{
MessageBox.Show("Downloading file group failed. Group name: " + downloadGroupName + "; Assembly name: " + args.Name);
throw (de);
}

// Load the assembly.
// Assembly.Load() doesn't work here, as the previous failure to load the assembly
// is cached by the CLR. LoadFrom() is not recommended. Use LoadFile() instead.
try
{
if (File.Exists(Application.StartupPath + @"\" + assemblyName + ".exe"))
newAssembly = Assembly.LoadFile(Application.StartupPath + @"\" + assemblyName + ".exe");
else if (File.Exists(Application.StartupPath + @"\" + assemblyName + ".dll"))
newAssembly = Assembly.LoadFile(Application.StartupPath + @"\" + assemblyName + ".dll");

}
catch (Exception e)
{
throw (e);
}
}
else
{
//Major error - not running under ClickOnce, but missing assembly. Don't know how to recover.
throw (new Exception("Cannot load assemblies dynamically - application is not deployed using ClickOnce."));
}


return (newAssembly);
}

private void button1_Click(object sender, EventArgs e)
{
MyOptionalForm1 opt1 = new MyOptionalForm1();
opt1.ShowDialog();
}
}
}


Build application and copy MyWebFormApp.exe and MyWebFormOptional1.exe to 1.0.0.0 folder.



Update Application manifest



Open MyWebFormApp.exe.manifest file from 1.0.0.0 folder in MageUI.exe.



Select ‘Files’ from list box then populate files again. Now “MyWebFormOptional1.exe ” gets added.



Click on checkbox to select this file as optional. And enter “MyWebFormOptional1” as group. Save application manifest.



Update deployment manifest



Then open deployment manifest. Select ‘Application Reference’ from listbox and click on ‘Select Manifest’. Select same manifest again and save manifest once again.



Installing second version




  1. Open browser and browse to “http://<webserver>/MyWebForm/MyWebForm.application”


  2. A window pops us prompting to install. Click on install. Application starts automatically and form is shown


  3. Now open application cache at C:\Documents and Settings\username\Local Settings\Apps\2.0\<xx>” and observe that only MyWebFormApp.exe is downloaded.


  4. Now click on button to open MyWebFormOptional1. Window opens.


  5. Again check application cache. This time observe that application downloads second form automatically.



Example 3 – Update



Now let us target on auto updating application to new version. Don’t un-install previous application.




  1. Create a new folder under C:\Inetpub\wwwroot\MyWebForm\ as 1.0.1.0


  2. Update AssemblyInfo.cs file in solution for both project as

    [assembly: AssemblyVersion("1.0.1.0")]


    [assembly: AssemblyFileVersion("1.0.1.0")]


  3. Build application and copy MyWebFormApp.exe and MyWebFormOptional1.exe to 1.0.1.0 folder.


  4. Create Application manifest. But ensure to set version as 1.0.1.0 and also files are populated from 1.0.1.0 folder


  5. Update deployment manifest by selecting manifest from 1.0.1.0 folder in “Application Reference” pane.



Now launch application from start menu. This time user will be prompted with following dialog.



image



 



Hope you found this post useful.

Saturday, March 14, 2009

Experts Exchange subscription

Online forums are always helpful. But sometimes you end up with paid solutions like experts exchange to get a more closure solution. During last year I was in similar situation and paid for a premium service for a month. And I used my credit card to pay it.

But unfortunately EE stored my cc details and charged my card every month since then. As it is small amount it went un-noticed.

Today I just cancelled. I am sure there is no where I selected for a recurring payment on monthly basis. Be watchful about EE.

Monday, March 09, 2009

Find and replace a pattern using VIM

In recent past I am not using shell scripts and thus lost touch with powerful search replace options for patters.

As Windows Find replace options doesn’t support much of regex stuff, I resorted to VIM.

My intention to fix an XML file in structured format.

I have an xml file with elements like following (it is just a snippet of big file)

<PolicyNo>012345678</PolicyNo>
<DateOfCommencement>03DEC1983</DateOfCommencement>
<Plan_Term>579-60</Plan_Term>
<SumAssured>2,00,000</SumAssured>
<GrievanceRedressalOfficer>011-57293184</GrievanceRedressalOfficer>

And I wanted it in the format of

<DataPoint PolicyNo=”012345678”></DataPoint>
<DataPoint DateOfCommencement=”03DEC1983”></DataPoint>
<DataPoint Plan_Term=”579-60”</DataPoint>
<DataPoint SumAssured=”2,00,000”></DataPoint>
<DataPoint GrievanceRedressalOfficer=”011-57293184”</DataPoint>

Following expression did the trick. I got to tweak second back reference little a bit for different cases where non special characters are present.

And I could also prefix line numbers to confine operations to limited set of lines

like

:9,26s…..

:s/<\(\w\+\)>\(.\+\)<\/\(\w\+\)>/<Detail \1=”\2”><\/Detail>/gc

As usual this is a simple search replace syntax in the format of :s/<find string>/<replace string>/<options in this case gc>

Here find string is formatted as

  1. starting with ‘<’
  2. start of first back reference \(
  3. word of one of more length \w\+
  4. close of first back reference \)
  5. ending with ‘>’
  6. start of second back reference <\
  7. characters repeated till character ‘<’. I changed this for few lines
  8. escape for close charcter ‘/’
  9. closing tag. Though this is need not be back reference. I just did it
  10. ending with >

Now replace string is

  1. “<Detail “
  2. First back reference \1
  3. followed by ‘=’
  4. followed by opening quotes “
  5. second back reference ‘\2’
  6. followed by closing quotes ‘”’
  7. Closing tag syntax.

And the options include

g – all occurrences in a line

c – seek confirmation

Following links might be useful

VIM Regular Expressions

And my favorite regex site Regular Expressions Reference