Technically Blogging

Sunday, August 26, 2007

Moved to spaces.live.com

new URL is:

http://ahmed0192.spaces.live.com/
http://blog.zamd.net

good bye blogspot.

Tuesday, November 28, 2006

Registration-Free Activation

I was working with Registration-Free COM and found these two excellent articles.

http://msdn2.microsoft.com/en-us/library/ms973915.aspx

http://msdn2.microsoft.com/en-us/library/ms973913.aspx#rfacomwalk_topic8

Tuesday, November 21, 2006

Customize MSBUILD without modifying your project file

In this post I’ll explain how you can use "project.user" file along with custom target file to
customize MSBuild project behavior.

Little background

Like *.suo (Visual Studio Solution User Options), which stores user specific settings for the solution(including breakpoints information), MSBUILD also supports the notion of user specific settings on per project basis. This is done using a file with the same name as your project plus the “.user” tag appended at the end and is called “Visual Studio Project User Options file”.

So if you project file is named “Common.csproj”, your user option will be named Common.csproj.user”.MSBuild checks for this file in the same directory as your project and imports it, if it’s available.

This file can be used to define user specific project properties. As this file is imported in “Microsoft.Common.targetsfile, so it can be used to override all the properties defined in yourProject.csproj and Microsoft.CSharp.targets or Microsoft.VisualBasic.targets.

Why will you customize using .user file?

A typical use case is that you have customized your project settings (e.g referring to assemblies in a different way than build machine). You can keep all your customization in .user file allowing your project file to remain pure so it can be used by multiple people while checked into the source control. I usually don’t check-in .user file in source control.

This gives you best of both worlds, project on other machines work in default/standard way, however when it gets built on your machine, it uses your custom settings from .user file.

Another scenario is you want to add your custom task in the build process but you don’t want to modify your project file.

How to do this

You cannot do much with user files alone. As most of the target dependencies are defined after this file is imported. So if you have inserted your target in some dependency chain, it will be overridden by default dependencies. E.g If you have added your task as the first dependencies of core build tasks using following property.

<PropertyGroup>

<CoreBuildDependsOn>YourTargetName;$(CoreBuildDependsOn)</CoreBuildDependsOn>

</PropertyGroup>

It will be overwritten because of following property definition in Microsoft.Common.targets.

<PropertyGroup>

<CoreBuildDependsOn>

BuildOnlySettings;

PrepareForBuild;

PreBuildEvent;

UnmanagedUnregistration;

ResolveReferences;

PrepareResources;

ResolveKeySource;

Compile;

GenerateSerializationAssemblies;

CreateSatelliteAssemblies;

GenerateManifests;

GetTargetPath;

PrepareForRun;

UnmanagedRegistration;

IncrementalClean;

PostBuildEvent

</CoreBuildDependsOn>

</PropertyGroup>

There is another interception point in MSBuild which we can utilize to achieve above scenarios. MSBuild looks for custom Targets before and after default targets. Specifically, MSBuild looks for following two properties, if anyone of them is defined, MSBuild imports it and use it.

  • CustomBeforeMicrosoftCommonTargets
  • CuCustomAfterMicrosoftCommonTargets

We will use CustomeAfterMicrosoftCommonTargets property to define our target(s) and run it based on some other target.

So, create a file in your project root with name custom.target


<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<UsingTask TaskName="BuildInspector" AssemblyFile="C:\zahmed\Temp\building\CustomTasks\bin\Debug\CustomTasks.dll" />

<PropertyGroup>

<CoreBuildDependsOn>MyCustomTarget;$(CoreBuildDependsOn)</CoreBuildDependsOn>

</PropertyGroup>


<Target Name="MyCustomTarget">

<Message Text="Running custom task ..."/>

<!--Run my custom task. -->


<BuildInspector/>

</Target>

</Project>


Now create the project.user file with following contents.


<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">;

<PropertyGroup>

<CustomAfterMicrosoftCommonTargets>

C:\zahmed\Temp\building\conApp\custom.target

</CustomAfterMicrosoftCommonTargets>


</PropertyGroup>

</Project>


Now build your project to run your custom task.

Note: You need to reload the project to load project.user file.



Friday, March 24, 2006

Deployment with Generic Bootstrapper

With .net Framework 2.0, Microsoft has provided a generic bootstrapper (Setup.bin), which can be used to deploy complex application having lots of dependencies.

Pull based deployment technology, ClickOnce also uses the same bootstrapper component for application deployment.

The concept of bootstrapper is based around packages. So you have any application which you needs to deploy. It could be .msi of a custom executable. That application depends on certain prerequisites to be installed on target machine. Windows Installer could be one of them, if your application is packages as msi.

So the deal is that you encapsulate all the prerequisite in their respective packages using a published xml schema. Every package is written using 2 xml files. (Package.xml and Product.xml). So specify required installation instractions for every package in these 2 files.

Once you are finished with packages. You feed all those package files along to an MSBuild task-- which will take the bare setup.bin, process instructions from all the files and put certain markers into the setup.bin file and in end emits a setup.exe -- which is final bootstrapper.

Now you distribute this bootstrapper alone -- When this bootstrapper will be executed on target machine. First thing it will do is to see what prerequieste needs to be installed. If it finds that certain prerequisites needs to be installed. It fectches them from some location (could be Web or UNC) and install them. It only install those prerequiste which are not present on the target machine.
Once all the prerequiste got installed, it launches thet setup of your application.

So bootstrapper makes the deployment fairly easy task.

By the way, if you use ClickOnce and ClickOnce Publish page-- Most of this stuff is done for you. You don't need to know all this detail. But it's handy if you need to write your own packages and have to build custom bootstrapper.

Wednesday, January 18, 2006

div and CSS

Very good presenation showing the use of div and CSS to create professional and device independent web site.

http://www.hotdesign.com/seybold/

Monday, January 16, 2006

Adding new Page to Outlook Options Dialog (C#)

Standard way is create a new user control (a class derived from System.Windows.UserControl) and use it as your custom page.

To hook this custom page in Outlook options dialog, create an event handler for
OptionsPagesAdd event of a Application object like this:


this.OptionsPagesAdd += delegate(Outlook.PropertyPages pages)
{
pages.Add(new CustomPageControl(), "My Page");
};

Now one caveat, if you go this way-- you will encounter "operation failed" exception -- quite nasty.

Why?
Because Outlook property pages expects a control as COM activeX. By default your user control is not visible to COM, so it can't be used as property page.

Solution is to apply ComVisible(true) attribute to you custom control class like this:

[ComVisible(true)]
public class CustomPageControl:System.Windows.Forms.UserControl
{

}

Without [ComVisible(true)], you will always get operation failed exception.

Tuesday, November 23, 2004

Tease yourself

Replace the TBD comment with a single line of code that causes this program to display

"Win-Dev!"

You can only use the class PrintMessage method for this purpose. You cannot modify any of the existing code, or add code above or below the existing code.

You can only write one line of code in place of the TBD comment and you cannot use the Console class.

class App

{

static void Main()

{

// TBD

}

}

sealed class Internal

{

sealed class Private

{

static void PrintMessage( string s1, string s2 )

{

System.Console.WriteLine(s1 + "-" + s2);

}

}

}