Sunday, September 18, 2011

VS 2008 Setup Project Upgrade – File replacement rules for versioned and non versioned files


Recently I ran into an interesting problem in one of a .NET Windows Application's Setup project. This is a .NET 3.5 application, hence used the visual studio 2008 setup project to build MSI installer for the application. While first time installation was successful, upgrade version of the setup project failed to update few of the files.

After going through few MSDN link, got to know when you have an updated application and set RemovePreviousVersions as true in setup project “VS 2005 setup project will create MSI which completely uninstalls the old version and reinstalls the new version” but “VS 2008 will create MSI which updates the old installation based on pre defined file replacement rules”. In simplified terms below are the rules,
  1. Both the old and new files are versioned files (i.e. application’s executable, dll files)
    • If your new file is having higher version compared to old files (e.g., old dll version is 1.0.0.1 and new dll version is 1.0.0.2), old file will be replaced by new file
    • If your new file is having same or lower version compared to old files (e.g., old dll version is 1.0.0.1 and new dll version is 1.0.0.0 or 1.0.0.1), old file will not be replaced by new file
  2. Both the old and new files are non versioned files (i.e. txt files, help files)
    • Installer will compare the created time and the last modified time of the old file. If the times are not same (case when the file is modified after installation in users machine), old file will not be replaced by new file (though your new file could be different than old file). The intent of this logic is to prevent Windows Installer from overwriting files that users have modified on their machine.
    • Installer will compare the created time and the last modified time of the old file. If the times are same (case when user haven’t changed the file), old file will be replaced by new file.
A detailed combination of the rules are given in this MSDN link.

As one of my text file (non versioned) was not updated in my upgrade MSI, I ran the MSI with verbose log to understand how the Windows Installer treats my file. Below is the command to run MSI with verbose log in command prompt.
msiexec /i "SampleInstaller.msi" /l*v "d:\SampleInstaller.log"
/l tells Windows Installer to create a log, * tells it to log everything and v tells it to use verbose mode.
This is the entry in log file for one of the file which failed to update.
MSI (s) (60:8C) [09:48:51:735]: Executing op: FileCopy(SourceName=SAMPLE~1.TXT|SampleTextFile.txt,SourceCabKey=_897AF91AADD144A4A32B738927E9B501,DestName=SampleTextFile.txt,Attributes=512,FileSize=6608,PerTick=32768,,VerifyMedia=1,,,,,CheckCRC=0,,,InstallMode=58982400,,,,,,,)
MSI (s) (60:8C) [09:48:51:735]: File: C:\Program Files\Sample Application\SampleTextFile.txt;    Won't Overwrite;    Won't patch;    Existing file is unversioned but modified
The log tells that SampleTextFile.txt as “Existing file is unversioned but modified”, hence Windows Installer “Won't Overwrite;    Won't patch;”.

Ouch, SampleTextFile.txt has been modified after it was installed, hence my upgrade MSI is not updating this file. What can I do to solve this?

After googling got to know, there are no direct solutions inside Visual Studio (atleast to my knowledge in VS 2008). Here are the steps to follow to solve this issue.
  1. Download ORCA, a free utility to edit the MSI packages
  2. Open the MSI file in ORCA editor
  3. Look for Property table under Tables
  4. Add a new property named REINSTALLMODE and set its value as amus
  5. Save the MSI and close ORCA
That's It. This property REINSTALLMODE with value amus tells the Windows Installer to uninstall old files and install new files irrespective of rules (similar to VS 2005).

Here are the screen shots of ORCA editor.


Monday, May 30, 2011

HTML5 - Canvas

Recently got a chance to learn some of the new HTML5 standards. There are lot of new features supported out of box by the browsers adapting the HTML5 syntax.

DIVE INTO HTML5 is a wonderful book/tutorial on HTML5. This article, lists out the top 28 features one must know before coding in HTML5.

There are many new element tags introduced by HTML5 standards. As per HTML5 standards, Canvas element is defined “a resolution-dependent bitmap canvas which can be used for rendering graphs, game graphics, or other visual images on the fly”. Along with strong JavaScript support, Canvas is one of the best competitor to RIA development tools like Flash & Silverlight.

To start with HTML5 learning, I thought of migrating my MIX 10 10K coding puzzle developed in Silvelight to HTML5 Canvas element. Below is the puzzle displayed using Canvas element.

The above puzzle is displayed by the below given source code.

<!DOCTYPE html>
<html>
<head>
    <title>Lights On</title>
    <!--[if IE]>
      <script src="http://explorercanvas.googlecode.com/svn/trunk/excanvas.js"></script>
    <![endif]-->
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
    <style>
      #container { position: relative; background-color:#005B96; width:550px; height:280px; }   
      #surface { position: relative; background-color:#ffffff; margin:9px; }   
      #title {margin-left:10px; font-family:Verdana; font-size:smaller; color:White; font-weight:bold}
      #description {float:left; margin-left:10px; font-family:Verdana; font-size:smaller; color:White; font-weight:lighter;}
      #reset {float:left; margin-left:10px; font-family:Verdana; font-size:smaller; font-weight:lighter;}
      #clickCount {margin-left:5px; font-family:Verdana; font-size:smaller; font-weight:lighter; color:White; vertical-align:bottom;}
      #clickCounter {margin-left:5px; font-family:Verdana; font-size:smaller; font-weight:lighter; color:White; vertical-align:bottom;}
    </style>
</head>
<body>
    <div id="container">
        <table>
            <tr>
                <td style="width:50%; vertical-align:top;">
                    <span id="title">Turn On the lights in all the cells.</span><br><br>
                    <span id="description">Clicking a cell will Turn On / Off its light, as well as its Horizontal & Vertical adjacent cells.</span><br><br><br><br><br><br><br><br><br><br>
                    <input type="button" id="reset" value="Restart" onclick="reset();" />
                    <span id="clickCount">No of Clicks: </span>
                    <span id="clickCounter">0</span>
                </td>
                <td style="width:50%; vertical-align:middle;">
                    <canvas id="surface">Canvas is not supported</canvas> 
                </td>
            </tr>
        </table>        
    </div>
    <script>
    var rowCount;
    var columnCount;
    var blockWidth;
    var blockHeight;
    var padding;    
    var canvasWidth;
    var canvasHeight;
    var ctx;
    var blocks;
    var canvasLeft;
    var canvasTop;
    var clickCount;
    function init() {
        rowCount = 5;
        columnCount = 5;
        blockWidth = 50;
        blockHeight = 50;
        padding = 1;
        clickCount = 0;
        blocks = new Array(rowCount);
        for (i = 0; i < rowCount; i++) {
            blocks[i] = new Array(columnCount);
            for (j = 0; j < columnCount; j++) {
                blocks[i][j] = 0; // Set as not lighted
            }
        }
        
        ctx = $('#surface')[0].getContext("2d");
        canvasWidth = ((blockWidth + padding) * columnCount) + padding;
        ctx.canvas.width = canvasWidth;
        canvasHeight = ((blockHeight + padding) * rowCount + padding);
        ctx.canvas.height = canvasHeight;
        draw();           
        
        canvasLeft = $("#surface").offset().left;
        canvasTop = $("#surface").offset().top;
        $("#clickCounter").text(clickCount); 
    }
    function rect(x, y, w, h) {
        ctx.beginPath();
        ctx.rect(x, y, w, h);
        ctx.closePath();
        ctx.fill();
    }
    function clear() {
        ctx.clearRect(0, 0, canvasWidth, canvasHeight);
    }
    function reset() {
        init();
    }
    function draw() {
        //draw blocks
        for (i = 0; i < rowCount; i++) {
            for (j = 0; j < columnCount; j++) {
                if (blocks[i][j] == 0) {
                    ctx.fillStyle = "#D3D3D3";
                }
                else {
                    ctx.fillStyle = "#FF0000";
                }
                rect((j * (blockWidth + padding)) + padding, (i * (blockHeight + padding)) + padding, blockWidth, blockHeight);
            }
        }
    }
    function onClick(e) {
        var x = Math.floor((e.pageX - canvasLeft) / blockWidth);
        var y = Math.floor((e.pageY - canvasTop) / blockHeight);
        var lightState;
        lightState = blocks[y][x] == 1 ? 0 : 1;
        blocks[y][x] = lightState;
        if (y - 1 >= 0) {
            lightState = blocks[y - 1][x] == 1 ? 0 : 1;
            blocks[y - 1][x] = lightState;
        }
        if (x - 1 >= 0) {
            lightState = blocks[y][x - 1] == 1 ? 0 : 1;
            blocks[y][x - 1] = lightState;
        }
        if (y + 1 < rowCount) {
            lightState = blocks[y + 1][x] == 1 ? 0 : 1;
            blocks[y + 1][x] = lightState;
        }
        if (x + 1 < columnCount) {
            lightState = blocks[y][x + 1] == 1 ? 0 : 1;
            blocks[y][x + 1] = lightState;
        }
        draw();
        clickCount += 1;
        $("#clickCounter").text(clickCount);       
    }        
    $(document).ready(function() {
        init();
        $("#surface").click(onClick);
    });
    </script>       
</body>
</html>

Thursday, January 27, 2011

Embedding SilverLight XAP in Blogger

I just thought of showing my simple "Lights On" puzzle in my blog. I hosted my XAP file in Google sites and tried adding it in <objecttag, like adding in a normal HTML file as shown below.
<object id="SL" data="data:application/x-silverlight," type="application/x-silverlight-2" 
style="width: 550px; height: 280px">
<param name="source" value="https://sites.google.com/site/rajganeshmountbatton/home/blogspotdocuments/25SquarePuzzle.xap" />
<param name="minRuntimeVersion" value="3.0.40624.0" />
<param name="enableHtmlAccess" value="true" />
<param name="initParams" value="someParam=value" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration: none;">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181" style="border-style: none"
alt="Get Microsoft Silverlight" />
</a>
</object>

The above code looks good and every one expects it to work fine. But in real, it just displays a white blank SilverLight application. This is an expected behavior of SilverLight and Timheuer talks about the solution in this link.

The solution is to map proper XAP MIME Type, adding few changes in AppManifest.xml file and adding the below param tag inside the object tag as shown below.

Below code block is the change to be done in AppManifest.xml file.
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
ExternalCallersFromCrossDomain="ScriptableOnly">
<Deployment.Parts>
</Deployment.Parts>    
</Deployment>


Param change in object tag
<param name="enableHtmlAccess" value="true" />

AppManifest and Param changes are in our hands and can be modified, but mapping proper MIME type for SilverLight application in Google site cannot be done. Other options are like hosting your SilverLight application in some other MIME configurable hosting provider. But there are no better free SilverLight hosting provider available. Any other options? I heard about Google app engine. So thought of trying to use app engine as host.

Here is good post about embedding SilverLight in app engine. I followed the same and hosted my application in app engine. Then changed the source attribute in the object tag to the app engine URL. What a surprise, the application worked like charm.
Below is the code after hosting in the Google App Engine.
<object id="SL" data="data:application/x-silverlight," type="application/x-silverlight-2" 
style="width: 550px; height: 280px">
<param name="source" value="http://rajganeshsilverlight.appspot.com/25SquarePuzzle.xap" />
<param name="minRuntimeVersion" value="3.0.40624.0" />
<param name="enableHtmlAccess" value="true" />
<param name="initParams" value="someParam=value" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration: none;">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181" style="border-style: none"
alt="Get Microsoft Silverlight" />
</a>
</object>

Here is the link to my hosted SilverLight application blog. Enjoy the Light On application and try lighting up 25 squares.

Wednesday, September 1, 2010

Bing Maps Developer API

Good link in MSDN about the Bing Map API.

http://msdn.microsoft.com/en-us/library/dd877180.aspx

Sunday, August 1, 2010

Visual Studio Keybinding Posters

Visual Studio team has released the shortcut keys for Visual Studio 2010 in various PDF formats.

Here is the download link