juil. 11

So you have setup your continuous integration and every time you are doing a checkin, a new automated build is launched on your build server. Nice !

You have also launched the Team Foundation Build Notification tool to have a small popup alert every time a build finishes and starts. Nice !

But you would like to go a bit further and receive a mail with the build result every time a build fails (or let's say do not succeed).

Use the TFS' alerts

The Team Foundation Server includes a powerful alert system, but by default, you cannot do so many things.

Use the Team Foundation Server Power Tools

If the Project Alerts does not allow so many things, the underlying alert system is very powerful. And you can use the Team Foundation Server Power Tools (http://visualstudiogallery.msdn.microsoft.com/c255a1e4-04ba-4f68-8f4e-cd473d6b971f) that allow a very fine control of the alerts.

You can then create a new rule like the following one : 

Note that for the Send To field, you can either indicate a account name, or an email address. In the case of an account name, this correspond to an AD account, and you must have configured the email address of that person in the Active Directory.

How to customize the received email ?

All the alert process is based on XML and XSL and so you can customize the email you will received.

In the above windo, you have the Event field, corresponding to the alert type that will be raised. In our case, this correspond to the type BuildCompletionEvent2.

You can find in the folder C:\Program Files\Microsoft Team Foundation Server 2010\Application Tier\TFSJobAgent\Transforms all the XSL that are used to transform the XML into a nice HTML or plain text email. The XSL are named with the event type. So in our case, we are interesed in the two following files : 

  • BuildCompletionEvent2.xsl for HTML emails
  • BuildCompletionEvent2.plaintextXsl for plain text emails
Now it's up to you to customize the XSL content to include for example your company logo.

Which fields are available to include in the XSL ?

It's nice to be able to customize the XSL to change its look, but it could be interesting also to include some more information.

So which are the information available ?
You can have access to the XSD in the TFS database.

Just run the following query in your TFS database :
select * from tbl_EventType
and you will see for each event type the available fields.

If you want to really see the XML and not the XSD, you can simply

  • specify that your alert launch an plain text email
  • replace the XSL by one that does give the XML like the following one
    
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:msxsl="urn:schemas-microsoft-com:xslt"
   exclude-result-prefixes="msxsl" >
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="@* | node()">
      <xsl:copy>
         <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>
Tags: |
juin 01

In some cases, when you are writing a unit test, you might need to have a valid HttpContext. Fortunately, you have the ability to do that with the Visual Studio's unit tests.

Let's use a static web site

So to do that, you can simply use a local existing web site. And can define your unit test as following :

[TestMethod]
[HostType("ASP.NET")]
[UrlToTest("http://localhost:7778/Default.aspx")]
[AspNetDevelopmentServerHost(@"c:\temp\WebSite\", "/")]
public void MyTestAccessingHttpContext()
{
   Assert.IsNotNull(HttpContext.Current);
}

So what does that mean ?

  • HostType specifies that you are writing an ASP.NET Unit test
  • UrlToTest defined the URL of your web site
  • AspNetDevelopmentServerHost is optional. It's required only if the website you want to use is not hosted in IIS. In that case, you will just specify a folder that is located on your computer and that will be mounted as a WebSite using the Visual Studio Web Server (Cassini). The port specified in the UrlToTest will be used to mount your web site.

How to use a "dynamic" web site ?

That's pretty cool, but the main drawback is that your website must exist on your disk. So when you have this kind of test in your team, all the team members' computer must be setup the same way to be sure to find the local website. And of course, this is the same thing for you conitnuous integration server.

To avoid this, you could have a website located in your solution (and so with a path that will change from environment to environment) and refer to this website. You could also have a folder defined in your test project and use it as a local web site. That's this second solution I will explain here (the first one is just similar, but even simpler).

First step : create your website

Here the usual way I create my minimal test web site.

My website just contain a empty Default.aspx page. The readme file is just some documentation to explain why I use this website.

I use two parent folders : 

  • The WebSite folder is the one that I will be using as a reference in my test. In my scenario, this must be unique (meaning that if you have several test projects, and some of them are using the same technique, just choose a unique name for each web site folder).
  • The __Deployment__ folder is the folder where I include all my deployable artifacts that I need for my tests. This will be more explained in the Second Step.

Second step : deploy your website

For now my website just exist in my solution, but I want it to be deployed for each test run. To do that, I need to update the testsettings of my solution.

In a basic scenario, we can just update the Local.testsettings file that is available under Solution Items. Of course if you have multiple "testsettings files", you may need to update all of them.

So what are we doing here ? We are asking MsTest to deploy, each time we are doing a test run, to deploy our "__Deployment__" folder. As a consequence, this folder will be copied to our 

Last step : use it in your test

So now when we run our test, we can have access to this website as it will be available in our current folder. So how can we transform our test code ?

/// <summary>
/// Initialization of the test class
/// </summary>
/// <param name="testContext">The test execution context</param>
[ClassInitialize]
public static void ClassInitialize(TestContext testContext)
{
   //Set an env. variable that can be used with AspNetDevelopmentServerHostAttribute
   Environment.SetEnvironmentVariable("DeployDirectory", testContext.DeploymentDirectory);
}

[TestMethod]
[HostType("ASP.NET")]
[UrlToTest("http://localhost:7778/Default.aspx")]
[AspNetDevelopmentServerHost(@"%DeployDirectory%\WebSite\", "/")]
public void MyTestAccessingHttpContext()
{
   Assert.IsNotNull(HttpContext.Current);
}

So in the initialization of our test (here I have chosen the ClassInitialize to run it only once before the first test of the class), we can create an environment variable that can be used in our aspNetDevelopmentServerHost.

With such a configuration, our test will work perfecly no matter which client computer or build server.

Tags: | |
mai 27

The scenario

CSS3 is released and implemented in all major browser latest version.

Time to use it ! So you have defined a "nice" CSS3 page like

<!DOCTYPE HTML>
<html>
<head>
   <title></title>
   <style type="text/css">
      div
      {
         padding: 10px;
         background-color: Blue;
         border: 1px solid black;
         border-radius: 30px;
         width: 800px;
         box-shadow: 10px 10px 50px red;
      }
   </style>
</head>
<body>
   <p>
      Before</p>
   <div>
      <p>
         Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum et ipsum eget nibh gravida porta. Morbi vitae felis risus, sagittis egestas ligula. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi
         pretium eleifend ultricies. Nulla ut tellus vel dui ultricies scelerisque ut at odio. Morbi sem magna, facilisis non facilisis vel, molestie non diam. Aliquam ultrices velit nec lorem venenatis sit amet ultrices justo facilisis. Vivamus posuere ultricies
         mauris, accumsan tempus nibh scelerisque eget. Curabitur sed tortor feugiat diam tincidunt ultrices. Aenean fringilla dictum risus, imperdiet rutrum nibh adipiscing non. Praesent porta massa ut risus consequat ut aliquam sapien venenatis. Phasellus
         bibendum facilisis lacus, nec suscipit ante faucibus eget. Donec dolor sem, congue vestibulum malesuada et, condimentum at ante. 
      </p>
   </div>
   <p>After</p>
</body>
</html>

and you have checked in your favorite browser that the display is correct.

And now you want to use this page in a Windows Form / WPF application, hosting the page in a WebBrowser control.

The problem

One you have created a basic form and that you have rendered this HTML page in the WebBrowser, here is how it is rendered :

Well... seem that all the CSS3 functionalities have been skipped.

How the WebBrowser control works

When you use a WebBrowser control, there are several things to know:

  • The WebBrowser control use the rendering engine of Internet Explorer that is installed in you computer
  • More precisely it uses the ieframe.dll that is located in c:\Windows\System32

So if you have checked that you have correctly installed IE9 and that the ieframe.dll is at the correct version (meaning at least 9.0.8112.16421 for the first RTM version of IE9), the WebBrowser control will use the rendering engine of IE9.

But you must know that by default, the WebBrowser control is run in "IE7 compatibility mode", and so, quite logically, CSS3 is not supported.

How to correct it ?

Another important thing to know is that the WebBrowser control can be intensively configured thru the registry. That's what we call the Internet Feature Controls. More info about all those features can be found on http://msdn.microsoft.com/en-us/library/ee330720(v=VS.85).aspx

And one of these features is called Browser Emulation. It is the feature that controls the compatibility mode used by the WebBrowser control when rendering a page. The possible values are : 

  • 7000 : IE7 Standard mode (default)
  • 8000 : IE8 mode if containing standards-based DOCTYPE
  • 8888 : IE8 mode, whatever the DOCTYPE
  • 9000 : IE9 mode if containing standards-based DOCTYPE
  • 9999 : IE9, whatever the DOCTYPE

All info can be found on http://msdn.microsoft.com/en-us/library/ee330730%28v=vs.85%29.aspx#browser_emulation

So what do you need to do ? Just add a new DWORD value in the following registrey key:

  • HKEY_LOCAL_MACHINE
    • SOFTWARE
      • Microsoft
        • Internet Explorer
          • MAIN
            • FeatureControl
              • FEATURE_BROWSER_EMULATION

The key you need to add is the name of your executable, meaning, if your application is named "WindowsFormsApplication1"

  • WindowsFormsApplication1.exe when you will run directly the executable of your application
  • WindowsFormsApplication1.vshost.exe when you will run your application in debug in Visual Studio

And so let's run once more our application : 

Now everything is ok !

Thanks to Mike Dos Zhang for helping me to point out this solution !

avr. 21

What happens if you create a new Bug in Team Foundation Server, and if you see afterwards that this is not a bug ? Usually, you would like to reject it. But... you can't! Indeed, by default Team Foundation Server allows you to resolve a bug with one of the following reasons : 

  • As Designed
  • Cannot Reproduce
  • Deferred
  • Duplicate
  • Fixed
  • Obsolete
In some cases, none of these values can do the job. So if this does not suit your need, let's see together how can we update the normal workflow to include this new value.

Use the Team Foundation Server Power Tools

This free Visual Studio extension can be found here. It will add some nice extensions to Visual Studio to help you working with the Team Foundation Server, and above all it will add a new menu in the tool menu : Process Editor.

Let's use it to update our workflow. First select the Work Item Type (WIT) you want to update

Just select the Work Item Type you want to update (here select Bug), and you will have the following screen:

Here we are interested by two tabs : 

  • The Fields tab list all the fields that are used in the Bug Work Item Type.
  • The Workflow tab show the the different status that the Work Item Type can hold, and the transition between each state

Change the list of possible values for "Resolved Reason"

When you resolve a Work Item, you have a field called Resolved Reason that holds the reason of the resolution. In our case, we need a new value Rejected. So how do we define it ?

  • Go on the Field Tab
  • Select the Resolved Reason field
  • Click on Edit
  • On the Field Definition window, select the Rules tab
  • Edit the ALLOWEDVALUES field
  • Add a new value Rejected


And here it is, you have a new resolution value, that can be used in the workflow.

Note that the list we have just updated is used when performing validation of the workflow. If we do not update this list, therefore, our workflow would be valid, but when changing the resolution of a bug, we would have an error.

Update the workflow

So now, we can go back to the main screen and select the Workflow tab. You should see something like :

What does that mean ?

  • The bug item type has three states : Active, Resolved and Closed
  • We have an entry point leading to the Active state
  • We have some transitions 
    • from Active to Resolved
    • from Resolved to Active
    • from Resolved to Close
    • from Close to Active

In our case, we want to add a new way of resolving a bug, so let's double click (or right click, and Open Details) on the transition from Active to Resolve and let's create a new Transition Reason.


Now we'll need to edit this new reason. Let's go the Fields tab and let's create a new Field reference. This Field Reference will be of type ResolvedReason and will have two Rules : COPY and ALLOWEDVALUE.

How do we parameter these two Rules ? Quite Simple. We are just copying a new value, which is Rejected, and after we'll check that the value is within the list of the allowed values.

And here we are ! We just have to check that everything is ok now.

Check that the new workflow is correct

Once we have saved our Work Item Type definition, we can open a bug and check that everything is correct.

Tags: |
avr. 20

Recently, I was needing to publish the powerpoints coming from various speakers on my server. When I have seen the size of some powerpoints (more than 20Mo) I thought it would not be a very nice user experience if my end-users were needing to download documents of such a size.

The problem

When you deal with Powerpoint documents, you will add some medias (images, cliparts, ...) to give them a better look. And of course the more medias you add, the bigger will be your powerpoint document.

As long as you work locally, this is not such a big deal. But when you need to publish your document (send it by mail, publish on internet, ...) it can bother you if you do not want your recipients or end user needing to download files of 10 or 20Mo.

Do we need such a size ? Usually, no. So what can we do ?

The Microsoft solution

Powerpoint includes a way to compress all the pictures of your document. To do that, they will reduce the quality of the images (DPI) depending of the profile (print, screen, email), and also remove the cropped parts of your images. To do that,

  • select one of your images
  • do to the Picture Tools / Format menu
  • choose Compress Pictures

This should normally help you to reduce your document size.

So is there a problem ?

This solution is nice but does not give you a lot of control about the document size. Let's imagine you have added some TIFF or BMP pictures in your powerpoint document (or doing some "Print Screen" and "CTRL+C"). Powerpoint will shrink them but will never point out that you have included some file format that are probably completely useless.

So in my view the real solution to investigate and understand the document size is to be able to check very quickly all the media that are present in your document, and check their size. The biggest ones can so be pointed as the first one to correct !

Lets use Jarod.PowerpointAnalyser

To be able to analyse the documents, I have quickly written a tool that will analyse the content of the powerpoint to help you pointing wich medias are responsible of your document size. 

How does it work ?

  1. Select the document you want to analyse by using the browse button
  2. Then click on the button Analyse
  3. Check the different medias you have and their respective size

In the given example you can clearly determine the source of the problem : 3 images of 3 and 6Mo are clearly responsible of the document size.

Which image are they ? The column Used in slides will tell you where they are used in your powerpoint. Some explanations : 

  • slide17 : your image is located in the slide number 17
  • slideMaster1 : your image is located on your first slide master
  • slideLayout1 : each slide master can be composed on several layout (empty slide, image slide, ...). In that case you image is located on the first layout

If you have several images on the same slide, you can quickly use the View link to get a preview of the image.

How to install it ?

Some limitations ?

I have quickly released this tool as a v0.1. So of course, it has a bunch of limitations (or bugs). Let's note : 

  • It can analyse only PPTX files (2007 or 2010 format), as long as they have been saved in the default format (Powerpoint Presentation *.pptx)
  • The PPTX file is locked while the tool is open
  • If you select a file that does not exist, or that is not in the correct format, the tool will crash
  • The "Image Preview" is available on all media, even if the media is NOT an image (a video for example). If you try to preview a media that is NOT an image, the tool will crash.

Are you interested in this tool ?

Do you think it is interesting? Is there anything missing to suit your needs ? Would you like to see another feature ? Leave a comment !