SVN, Hudson and MSBuild - Continuous Integration

SVN, Hudson and MSBuild - Revision control repository
SVN, Hudson and MSBuild - Building code on post commit

This is the second installment in the series I’m writing about SVN, Hudson and MSBuild.

This time I’ll show you how to set up a job in Hudson to build and package an ASP.NET MVC 3 Hello World sample app (download it here). This job will point to the SVN repository set up in the 1st part of this series. I’ve committed the app’s source code to the trunk folder and it’s now versioned.

Question: Why should I use a Continuous Integration ( CI ) process?

Because it allows you to fine tune and extend your build process. You’ll be able to plug hooks in various stages of your build process. CI gives you more control over the process allowing an infinite set of possibilities as for example an automated build => test => package => deploy scenario.

In this post I’m going to show this simple workflow: build => package

So, to start off, the first thing you should do is to download Hudson at http://hudson-ci.org/. The latest production version is 2.1.0 as of the time of this post. Download the .war file (53.3 MB) to your C:/ drive to keep things at hand. When the download finishes, read this thorough installation guide: Install Hudson as a Windows service. This is how I’ve set up Hudson. There should be no errors if you follow the instructions.

Note
Open a command prompt at C:\ and type:

java -jar hudson-2.1.0.war

This will start Hudson and you should be able to install it as a service following this link.

Now I suppose you have Hudson working on your machine.

Head over to you Hudson instance that is located at this URL by default:

http://localhost:8080/

Let’s configure a new Job in Hudson:

Selecting New Job in Hudson dashboardFigure 1 - Selecting New Job in Hudson dashboard

When you click the New Job link you go to a screen where you can give a name to the job and choose what kind of build you want the job to execute.

I named the job HelloWorldMvc3 and selected Build a free-style software project because it fits the purpose of this series.

* As you can see I already have a job called FitnessCenter configured.

Naming the New Job and selecting the build typeFigure 2 - Naming the New Job and selecting the build type

After clicking OK we go to a new page that allows us to enter detailed configuration settings. The following image shows the options I used (click the image to enlarge it):

Configuring the job and adding a Visual Studio project or solution build stepFigure 3 - Configuring the job and adding a Visual Studio project or solution build step

Note above in the Source Code Management section that I have chosen Subversion and passed the Repository URL:

file:///C:/svn/MyProject/trunk

The path above is related to the SVN repository I set up here.

The sample ASP.NET MVC 3 Hello World app is located in the /trunk folder.

Now we must add a build step to tell Hudson we want to build and package the app as part of the job execution. I have highlighted the option in blue in Figure 3 above. I selected Build a Visual Studio project or solution using MSBuild.

When you add that build step you must pass some info to Hudson as shown in the following picture:

Selecting MSBuild version, filling MSBuild Build File and specifying the command line arguments

Figure 4 - Selecting MSBuild version, filling MSBuild Build File and specifying the command line arguments

MsBuild Build File = the path to the .proj or .sln file that MSBuild will use to build. This path is related to the trunk folder structure you have. In this case I have this folder structure:

C:\MyProject\trunk\HelloWorldMvc3\HelloWorldMvc3.csproj

Command Line Arguments = a whitespace separated list of command line arguments you can specify. These can be the same as if you were to run msbuild from the command line.

I used these command line arguments above to package the app:

/T:Package /P:Configuration=Release;
SolutionDir="C:\hudson\jobs\MyProject\workspace\;
PackageLocation="C:\MyProject\Package.zip"

Apontando para cima These command line arguments are power in our hands…

You can also select post-build actions as to send an e-mail notification. If configured, Hudson will send out an e-mail to the specified recipients when a certain important event occurs:
1 - Every failed build triggers a new e-mail.
2 - A successful build after a failed (or unstable) build triggers a new e-mail, indicating that a crisis is over.
3 - An unstable build after a successful build triggers a new e-mail, indicating that there's a regression.
4 - Unless configured, every unstable build triggers a new e-mail, indicating that regression is still there.

When you finish the configuration, make sure to click the Save button.

This is everything you need to configure a new job in Hudson.

With this we achieved our objective, that is, Hudson and SVN are now plugged.

To run the job and build the app I just have to click the Build Now link in Hudson panel (see left menu bar at the top in Figure 3) but the great thing about a Continuous Integration process it to have the build process happen automatically and this is definitely possible.

Summary
Hudson is a free CI server which makes it a viable option for the majority of developers and companies out there that don’t want to spend a lot of money with equivalent expensive software. Besides, as you saw in this post you can get it working with Subversion in a couple of minutes.

Hudson has a lot of additional goodies that you can and should explore. Go over each menu option to learn about its additional features.

Next in this series
In the next and final part of this series I’m going to show you what’s missing to get SVN to inform Hudson that it’s time to build the code just committed to the repository. In the meanwhile I’ll entertain you with the Console Output regarding the first execution of the job we created in this post. It took only 08.33 seconds to build and package the app in a beautiful .zip package that can be used to deploy the app in IIS (I'll do a blog post about this topic in the future):

Started by user anonymous
Checking out file:///C:/svn/MyProject/trunk
A         HelloWorldMvc3.sln
AU        HelloWorldMvc3.suo
A         HelloWorldMvc3
A         HelloWorldMvc3\HelloWorldMvc3.csproj
A         HelloWorldMvc3\Properties
A         HelloWorldMvc3\Properties\AssemblyInfo.cs
A         HelloWorldMvc3\Web.Release.config
A         HelloWorldMvc3\packages.config
A         HelloWorldMvc3\Global.asax
A         HelloWorldMvc3\Controllers
A         HelloWorldMvc3\Controllers\HomeController.cs
A         HelloWorldMvc3\Controllers\AccountController.cs
A         HelloWorldMvc3\Web.Debug.config
A         HelloWorldMvc3\App_Data
A         HelloWorldMvc3\Scripts
A         HelloWorldMvc3\Scripts\modernizr-1.7.js
A         HelloWorldMvc3\Scripts\jquery.validate.js
A         HelloWorldMvc3\Scripts\jquery.unobtrusive-ajax.js
A         HelloWorldMvc3\Scripts\MicrosoftMvcValidation.js
A         HelloWorldMvc3\Scripts\jquery.validate-vsdoc.js
A         HelloWorldMvc3\Scripts\MicrosoftMvcAjax.js
A         HelloWorldMvc3\Scripts\jquery.validate.unobtrusive.min.js
A         HelloWorldMvc3\Scripts\MicrosoftMvcValidation.debug.js
A         HelloWorldMvc3\Scripts\jquery-1.5.1-vsdoc.js
A         HelloWorldMvc3\Scripts\MicrosoftMvcAjax.debug.js
A         HelloWorldMvc3\Scripts\jquery-ui-1.8.11.min.js
A         HelloWorldMvc3\Scripts\jquery-1.5.1.min.js
A         HelloWorldMvc3\Scripts\MicrosoftAjax.js
A         HelloWorldMvc3\Scripts\jquery-ui-1.8.11.js
A         HelloWorldMvc3\Scripts\jquery-1.5.1.js
A         HelloWorldMvc3\Scripts\MicrosoftAjax.debug.js
A         HelloWorldMvc3\Scripts\modernizr-1.7.min.js
A         HelloWorldMvc3\Scripts\jquery.validate.min.js
A         HelloWorldMvc3\Scripts\jquery.unobtrusive-ajax.min.js
A         HelloWorldMvc3\Scripts\jquery.validate.unobtrusive.js
A         HelloWorldMvc3\Content
A         HelloWorldMvc3\Content\themes
A         HelloWorldMvc3\Content\themes\base
A         HelloWorldMvc3\Content\themes\base\jquery.ui.base.css
A         HelloWorldMvc3\Content\themes\base\jquery.ui.slider.css
A         HelloWorldMvc3\Content\themes\base\jquery.ui.button.css
A         HelloWorldMvc3\Content\themes\base\jquery.ui.progressbar.css
A         HelloWorldMvc3\Content\themes\base\jquery.ui.accordion.css
A         HelloWorldMvc3\Content\themes\base\jquery.ui.theme.css
A         HelloWorldMvc3\Content\themes\base\jquery.ui.selectable.css
A         HelloWorldMvc3\Content\themes\base\jquery.ui.resizable.css
A         HelloWorldMvc3\Content\themes\base\jquery.ui.autocomplete.css
A         HelloWorldMvc3\Content\themes\base\jquery.ui.dialog.css
A         HelloWorldMvc3\Content\themes\base\images
AU        HelloWorldMvc3\Content\themes\base\images\ui-bg_glass_95_fef1ec_1x400.png
AU        HelloWorldMvc3\Content\themes\base\images\ui-icons_2e83ff_256x240.png
AU        HelloWorldMvc3\Content\themes\base\images\ui-bg_flat_75_ffffff_40x100.png
AU        HelloWorldMvc3\Content\themes\base\images\ui-bg_glass_55_fbf9ee_1x400.png
AU        HelloWorldMvc3\Content\themes\base\images\ui-icons_222222_256x240.png
AU        HelloWorldMvc3\Content\themes\base\images\ui-icons_888888_256x240.png
AU        HelloWorldMvc3\Content\themes\base\images\ui-bg_glass_65_ffffff_1x400.png
AU        HelloWorldMvc3\Content\themes\base\images\ui-icons_454545_256x240.png
AU        HelloWorldMvc3\Content\themes\base\images\ui-icons_cd0a0a_256x240.png
AU        HelloWorldMvc3\Content\themes\base\images\ui-bg_glass_75_e6e6e6_1x400.png
AU        HelloWorldMvc3\Content\themes\base\images\ui-bg_flat_0_aaaaaa_40x100.png
AU        HelloWorldMvc3\Content\themes\base\images\ui-bg_highlight-soft_75_cccccc_1x100.png
AU        HelloWorldMvc3\Content\themes\base\images\ui-bg_glass_75_dadada_1x400.png
A         HelloWorldMvc3\Content\themes\base\jquery.ui.datepicker.css
A         HelloWorldMvc3\Content\themes\base\jquery.ui.all.css
A         HelloWorldMvc3\Content\themes\base\jquery.ui.tabs.css
A         HelloWorldMvc3\Content\themes\base\jquery.ui.core.css
A         HelloWorldMvc3\Content\Site.css
A         HelloWorldMvc3\Global.asax.cs
A         HelloWorldMvc3\Models
A         HelloWorldMvc3\Models\AccountModels.cs
A         HelloWorldMvc3\Web.config
A         HelloWorldMvc3\Views
A         HelloWorldMvc3\Views\Shared
A         HelloWorldMvc3\Views\Shared\_Layout.cshtml
A         HelloWorldMvc3\Views\Shared\Error.cshtml
A         HelloWorldMvc3\Views\Shared\_LogOnPartial.cshtml
A         HelloWorldMvc3\Views\_ViewStart.cshtml
A         HelloWorldMvc3\Views\Web.config
A         HelloWorldMvc3\Views\Account
A         HelloWorldMvc3\Views\Account\ChangePasswordSuccess.cshtml
A         HelloWorldMvc3\Views\Account\LogOn.cshtml
A         HelloWorldMvc3\Views\Account\Register.cshtml
A         HelloWorldMvc3\Views\Account\ChangePassword.cshtml
A         HelloWorldMvc3\Views\Home
A         HelloWorldMvc3\Views\Home\Index.cshtml
A         HelloWorldMvc3\Views\Home\About.cshtml
AU        HelloWorldMvc3.sln.docstates.suo
A         packages
A         packages\jQuery.UI.Combined.1.8.11
A         packages\jQuery.UI.Combined.1.8.11\Content
A         packages\jQuery.UI.Combined.1.8.11\Content\Scripts
A         packages\jQuery.UI.Combined.1.8.11\Content\Scripts\jquery-ui-1.8.11.min.js
A         packages\jQuery.UI.Combined.1.8.11\Content\Scripts\jquery-ui-1.8.11.js
A         packages\jQuery.UI.Combined.1.8.11\Content\Content
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\jquery.ui.base.css
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\jquery.ui.slider.css
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\jquery.ui.button.css
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\jquery.ui.progressbar.css
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\jquery.ui.accordion.css
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\jquery.ui.theme.css
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\jquery.ui.selectable.css
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\jquery.ui.resizable.css
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\jquery.ui.autocomplete.css
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\jquery.ui.dialog.css
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\images
AU        packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\images\ui-bg_glass_95_fef1ec_1x400.png
AU        packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\images\ui-icons_2e83ff_256x240.png
AU        packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\images\ui-bg_flat_75_ffffff_40x100.png
AU        packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\images\ui-bg_glass_55_fbf9ee_1x400.png
AU        packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\images\ui-icons_222222_256x240.png
AU        packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\images\ui-icons_888888_256x240.png
AU        packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\images\ui-bg_glass_65_ffffff_1x400.png
AU        packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\images\ui-icons_454545_256x240.png
AU        packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\images\ui-icons_cd0a0a_256x240.png
AU        packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\images\ui-bg_glass_75_e6e6e6_1x400.png
AU        packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\images\ui-bg_flat_0_aaaaaa_40x100.png
AU        packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\images\ui-bg_highlight-soft_75_cccccc_1x100.png
AU        packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\images\ui-bg_glass_75_dadada_1x400.png
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\jquery.ui.datepicker.css
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\jquery.ui.all.css
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\jquery.ui.tabs.css
A         packages\jQuery.UI.Combined.1.8.11\Content\Content\themes\base\jquery.ui.core.css
AU        packages\jQuery.UI.Combined.1.8.11\jQuery.UI.Combined.1.8.11.nupkg
A         packages\jQuery.Validation.1.8.0
A         packages\jQuery.Validation.1.8.0\Content
A         packages\jQuery.Validation.1.8.0\Content\Scripts
A         packages\jQuery.Validation.1.8.0\Content\Scripts\jquery.validate.js
A         packages\jQuery.Validation.1.8.0\Content\Scripts\jquery.validate-vsdoc.js
A         packages\jQuery.Validation.1.8.0\Content\Scripts\jquery.validate.min.js
AU        packages\jQuery.Validation.1.8.0\jQuery.Validation.1.8.0.nupkg
A         packages\jQuery.vsdoc.1.5.1
A         packages\jQuery.vsdoc.1.5.1\Content
A         packages\jQuery.vsdoc.1.5.1\Content\Scripts
A         packages\jQuery.vsdoc.1.5.1\Content\Scripts\jquery-1.5.1-vsdoc.js
AU        packages\jQuery.vsdoc.1.5.1\jQuery.vsdoc.1.5.1.nupkg
A         packages\repositories.config
A         packages\EntityFramework.4.1.10331.0
AU        packages\EntityFramework.4.1.10331.0\EntityFramework.4.1.10331.0.nupkg
A         packages\EntityFramework.4.1.10331.0\lib
AU        packages\EntityFramework.4.1.10331.0\lib\EntityFramework.dll
A         packages\EntityFramework.4.1.10331.0\lib\EntityFramework.xml
A         packages\jQuery.1.5.1
AU        packages\jQuery.1.5.1\jQuery.1.5.1.nupkg
A         packages\jQuery.1.5.1\Content
A         packages\jQuery.1.5.1\Content\Scripts
A         packages\jQuery.1.5.1\Content\Scripts\jquery-1.5.1.min.js
A         packages\jQuery.1.5.1\Content\Scripts\jquery-1.5.1.js
A         packages\Modernizr.1.7
AU        packages\Modernizr.1.7\Modernizr.1.7.nupkg
A         packages\Modernizr.1.7\Content
A         packages\Modernizr.1.7\Content\Scripts
A         packages\Modernizr.1.7\Content\Scripts\modernizr-1.7.min.js
A         packages\Modernizr.1.7\Content\Scripts\modernizr-1.7.js
At revision 2
Path To MSBuild.exe: C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
Executing command: cmd.exe /C C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe /T:Package /P:Configuration=Debug;SolutionDir=C:\hudson\jobs\MyProject\workspace\;PackageLocation=C:\MyProject\Package.zip HelloWorldMvc3\HelloWorldMvc3.csproj && exit %%ERRORLEVEL%%
[workspace] $ cmd.exe /C C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe /T:Package /P:Configuration=Debug;SolutionDir=C:\hudson\jobs\MyProject\workspace\;PackageLocation=C:\MyProject\Package.zip HelloWorldMvc3\HelloWorldMvc3.csproj && exit %%ERRORLEVEL%%
Microsoft (R) Build Engine Version 4.0.30319.1
[Microsoft .NET Framework, Version 4.0.30319.454]
Copyright (C) Microsoft Corporation 2007. All rights reserved.

Build started 7/30/2011 12:16:23 AM.
Project "C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\HelloWorldMvc3.csproj" on node 1 (Package target(s)).
ValidateGlobalPackageSetting:
  $(PackageAsSingleFile) is True
  $(PackageFileName) is C:\MyProject\Package.zip. Validating...
PrepareForBuild:
  Creating directory "bin\".
  Creating directory "obj\Debug\".
GenerateTargetFrameworkMonikerAttribute:
Skipping target "GenerateTargetFrameworkMonikerAttribute" because all output files are up-to-date with respect to the input files.
CoreCompile:
  c:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:C:\hudson\jobs\HelloWorldMvc3\workspace\packages\EntityFramework.4.1.10331.0\lib\EntityFramework.dll /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.CSharp.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ComponentModel.DataAnnotations.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Configuration.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Core.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.DataSetExtensions.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.Entity.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Drawing.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.EnterpriseServices.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.Abstractions.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.ApplicationServices.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.DynamicData.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.Entity.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.Extensions.dll" /reference:"c:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies\System.Web.Helpers.dll" /reference:"c:\Program Files\Microsoft ASP.NET\ASP.NET MVC 3\Assemblies\System.Web.Mvc.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.Routing.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.Services.dll" /reference:"c:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies\System.Web.WebPages.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Xml.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Xml.Linq.dll" /debug+ /debug:full /optimize- /out:obj\Debug\HelloWorldMvc3.dll /target:library Controllers\AccountController.cs Controllers\HomeController.cs Global.asax.cs Models\AccountModels.cs Properties\AssemblyInfo.cs "C:\Windows\TEMP\.NETFramework,Version=v4.0.AssemblyAttributes.cs"
_CopyFilesMarkedCopyLocal:
  Copying file from "C:\hudson\jobs\HelloWorldMvc3\workspace\packages\EntityFramework.4.1.10331.0\lib\EntityFramework.dll" to "bin\EntityFramework.dll".
  Copying file from "C:\hudson\jobs\HelloWorldMvc3\workspace\packages\EntityFramework.4.1.10331.0\lib\EntityFramework.xml" to "bin\EntityFramework.xml".
CopyFilesToOutputDirectory:
  Copying file from "obj\Debug\HelloWorldMvc3.dll" to "bin\HelloWorldMvc3.dll".
  HelloWorldMvc3 -> C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\bin\HelloWorldMvc3.dll
  Copying file from "obj\Debug\HelloWorldMvc3.pdb" to "bin\HelloWorldMvc3.pdb".
CollectFilesFromIntermediateAssembly:
  Gather all files from Project items @(IntermediateAssembly). Adding:
  bin\HelloWorldMvc3.dll to bin\HelloWorldMvc3.dll
  bin\HelloWorldMvc3.pdb to bin\HelloWorldMvc3.pdb
CollectFilesFromContent:
  Gather all files from Project items @(Content). Adding:
  Content\themes\base\images\ui-bg_flat_0_aaaaaa_40x100.png;Content\themes\base\images\ui-bg_flat_75_ffffff_40x100.png;Content\themes\base\images\ui-bg_glass_55_fbf9ee_1x400.png;Content\themes\base\images\ui-bg_glass_65_ffffff_1x400.png;Content\themes\base\images\ui-bg_glass_75_dadada_1x400.png;Content\themes\base\images\ui-bg_glass_75_e6e6e6_1x400.png;Content\themes\base\images\ui-bg_glass_95_fef1ec_1x400.png;Content\themes\base\images\ui-bg_highlight-soft_75_cccccc_1x100.png;Content\themes\base\images\ui-icons_222222_256x240.png;Content\themes\base\images\ui-icons_2e83ff_256x240.png;Content\themes\base\images\ui-icons_454545_256x240.png;Content\themes\base\images\ui-icons_888888_256x240.png;Content\themes\base\images\ui-icons_cd0a0a_256x240.png;Content\themes\base\jquery.ui.accordion.css;Content\themes\base\jquery.ui.all.css;Content\themes\base\jquery.ui.autocomplete.css;Content\themes\base\jquery.ui.base.css;Content\themes\base\jquery.ui.button.css;Content\themes\base\jquery.ui.core.css;Content\themes\base\jquery.ui.datepicker.css;Content\themes\base\jquery.ui.dialog.css;Content\themes\base\jquery.ui.progressbar.css;Content\themes\base\jquery.ui.resizable.css;Content\themes\base\jquery.ui.selectable.css;Content\themes\base\jquery.ui.slider.css;Content\themes\base\jquery.ui.tabs.css;Content\themes\base\jquery.ui.theme.css;Global.asax;Scripts\jquery-1.5.1-vsdoc.js;Scripts\jquery-1.5.1.js;Scripts\jquery-1.5.1.min.js;Scripts\jquery-ui-1.8.11.js;Scripts\jquery-ui-1.8.11.min.js;Scripts\jquery.validate-vsdoc.js;Scripts\jquery.validate.js;Scripts\jquery.validate.min.js;Scripts\modernizr-1.7.js;Scripts\modernizr-1.7.min.js;Web.config;Web.Debug.config;Web.Release.config;Content\Site.css;Scripts\jquery.unobtrusive-ajax.js;Scripts\jquery.unobtrusive-ajax.min.js;Scripts\jquery.validate.unobtrusive.js;Scripts\jquery.validate.unobtrusive.min.js;Scripts\MicrosoftAjax.js;Scripts\MicrosoftAjax.debug.js;Scripts\MicrosoftMvcAjax.js;Scripts\MicrosoftMvcAjax.debug.js;Scripts\MicrosoftMvcValidation.js;Scripts\MicrosoftMvcValidation.debug.js;Views\_ViewStart.cshtml;Views\Account\ChangePassword.cshtml;Views\Account\ChangePasswordSuccess.cshtml;Views\Account\LogOn.cshtml;Views\Account\Register.cshtml;Views\Home\About.cshtml;Views\Home\Index.cshtml;Views\Shared\Error.cshtml;Views\Shared\_LogOnPartial.cshtml;Views\Shared\_Layout.cshtml;Views\Web.config;packages.config
CollectFilesFromIntermediateSatelliteAssembliesWithTargetPath:
  Gather all files from Project output (IntermediateSatelliteAssembliesWithTargetPath). Adding:
CollectFilesFromReference:
  Gather all files from Project items @(ReferenceCopyLocalPaths,ReferenceComWrappersToCopyLocal,ResolvedIsolatedComModules,_DeploymentLooseManifestFile,NativeReferenceFile).
CollectFilesFromAllExtraReferenceFiles:
  Gather all files from Project items @(AllExtraReferenceFiles). Adding:
CollectFilesFrom_binDeployableAssemblies:
  Gather all files from Project items @(_binDeployableAssemblies). Adding:
PipelineCollectFilesPhase:
  Publish Pipeline Collect Files Phase
CollectWebConfigsToTransform:
  Found The following for Config tranformation:
  Web.config, Views\Web.config
  Creating directory "C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\TransformWebConfig\transformed\".
  Creating directory "C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\TransformWebConfig\transformed\Views\".
PreTransformWebConfig:
  Copying Web.config to obj\Debug\TransformWebConfig\original\Web.config.
TransformWebConfigCore:
  Transforming Source File: C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\Web.config
    Applying Transform File: C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\Web.Debug.config
    Output File: obj\Debug\TransformWebConfig\transformed\Web.config
  Transformation succeeded
PostTransformWebConfig:
  Transformed Web.config using Web.Debug.config into obj\Debug\TransformWebConfig\transformed\Web.config.
PipelineTransformPhase:
  Publish Pipeline Transform Phase
PreAutoParameterizationWebConfigConnectionStrings:
  Creating directory "C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\CSAutoParameterize\transformed\Views\".
  Copying Views\Web.config to obj\Debug\CSAutoParameterize\original\Views\Web.config.
  Copying obj\Debug\TransformWebConfig\transformed\Web.config to obj\Debug\CSAutoParameterize\original\Web.config.
AutoParameterizationWebConfigConnectionStringsCore:
  Transforming Source File: C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\Views\Web.config
    Applying Transform File: <?xml version="1.0"?>
          <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
            <connectionStrings>
              <add
                connectionString="{% token='$(ReplacableToken_#(parameter)_#(tokennumber))' xpathlocator='name' parameter='$(name)-Web.config Connection String' description='$(name) Connection String used in web.config by the application to access the database.' defaultValue='$(connectionString)' tags='SqlConnectionString' %}"
                xdt:Transform="SetTokenizedAttributes(connectionString)" xdt:SupressWarnings="True" />
            </connectionStrings>
          </configuration>
    No element in the source document matches '/configuration/connectionStrings'
    Not executing SetTokenizedAttributes (transform line 6, 15)
    Output File: obj\Debug\CSAutoParameterize\transformed\Views\Web.config
  Transformation succeeded
  Transforming Source File: C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\TransformWebConfig\transformed\Web.config
    Applying Transform File: <?xml version="1.0"?>
          <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
            <connectionStrings>
              <add
                connectionString="{% token='$(ReplacableToken_#(parameter)_#(tokennumber))' xpathlocator='name' parameter='$(name)-Web.config Connection String' description='$(name) Connection String used in web.config by the application to access the database.' defaultValue='$(connectionString)' tags='SqlConnectionString' %}"
                xdt:Transform="SetTokenizedAttributes(connectionString)" xdt:SupressWarnings="True" />
            </connectionStrings>
          </configuration>
    Output File: obj\Debug\CSAutoParameterize\transformed\Web.config
  Transformation succeeded
PostAutoParameterizationWebConfigConnectionStrings:
  Auto ConnectionString Transformed Views\Web.config into obj\Debug\CSAutoParameterize\transformed\Views\Web.config.
  Auto ConnectionString Transformed obj\Debug\TransformWebConfig\transformed\Web.config into obj\Debug\CSAutoParameterize\transformed\Web.config.
CopyAllFilesToSingleFolderForPackage:
  Creating directory "obj\Debug\Package\PackageTmp".
  Copying all files to temporary location below for package/publish:
  obj\Debug\Package\PackageTmp.
  Copying bin\HelloWorldMvc3.dll to obj\Debug\Package\PackageTmp\bin\HelloWorldMvc3.dll.
  Copying bin\HelloWorldMvc3.pdb to obj\Debug\Package\PackageTmp\bin\HelloWorldMvc3.pdb.
  Copying Content\themes\base\images\ui-bg_flat_0_aaaaaa_40x100.png to obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_flat_0_aaaaaa_40x100.png.
  Copying Content\themes\base\images\ui-bg_flat_75_ffffff_40x100.png to obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_flat_75_ffffff_40x100.png.
  Copying Content\themes\base\images\ui-bg_glass_55_fbf9ee_1x400.png to obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_glass_55_fbf9ee_1x400.png.
  Copying Content\themes\base\images\ui-bg_glass_65_ffffff_1x400.png to obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_glass_65_ffffff_1x400.png.
  Copying Content\themes\base\images\ui-bg_glass_75_dadada_1x400.png to obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_glass_75_dadada_1x400.png.
  Copying Content\themes\base\images\ui-bg_glass_75_e6e6e6_1x400.png to obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_glass_75_e6e6e6_1x400.png.
  Copying Content\themes\base\images\ui-bg_glass_95_fef1ec_1x400.png to obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_glass_95_fef1ec_1x400.png.
  Copying Content\themes\base\images\ui-bg_highlight-soft_75_cccccc_1x100.png to obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_highlight-soft_75_cccccc_1x100.png.
  Copying Content\themes\base\images\ui-icons_222222_256x240.png to obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-icons_222222_256x240.png.
  Copying Content\themes\base\images\ui-icons_2e83ff_256x240.png to obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-icons_2e83ff_256x240.png.
  Copying Content\themes\base\images\ui-icons_454545_256x240.png to obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-icons_454545_256x240.png.
  Copying Content\themes\base\images\ui-icons_888888_256x240.png to obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-icons_888888_256x240.png.
  Copying Content\themes\base\images\ui-icons_cd0a0a_256x240.png to obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-icons_cd0a0a_256x240.png.
  Copying Content\themes\base\jquery.ui.accordion.css to obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.accordion.css.
  Copying Content\themes\base\jquery.ui.all.css to obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.all.css.
  Copying Content\themes\base\jquery.ui.autocomplete.css to obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.autocomplete.css.
  Copying Content\themes\base\jquery.ui.base.css to obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.base.css.
  Copying Content\themes\base\jquery.ui.button.css to obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.button.css.
  Copying Content\themes\base\jquery.ui.core.css to obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.core.css.
  Copying Content\themes\base\jquery.ui.datepicker.css to obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.datepicker.css.
  Copying Content\themes\base\jquery.ui.dialog.css to obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.dialog.css.
  Copying Content\themes\base\jquery.ui.progressbar.css to obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.progressbar.css.
  Copying Content\themes\base\jquery.ui.resizable.css to obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.resizable.css.
  Copying Content\themes\base\jquery.ui.selectable.css to obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.selectable.css.
  Copying Content\themes\base\jquery.ui.slider.css to obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.slider.css.
  Copying Content\themes\base\jquery.ui.tabs.css to obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.tabs.css.
  Copying Content\themes\base\jquery.ui.theme.css to obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.theme.css.
  Copying Global.asax to obj\Debug\Package\PackageTmp\Global.asax.
  Copying Scripts\jquery-1.5.1-vsdoc.js to obj\Debug\Package\PackageTmp\Scripts\jquery-1.5.1-vsdoc.js.
  Copying Scripts\jquery-1.5.1.js to obj\Debug\Package\PackageTmp\Scripts\jquery-1.5.1.js.
  Copying Scripts\jquery-1.5.1.min.js to obj\Debug\Package\PackageTmp\Scripts\jquery-1.5.1.min.js.
  Copying Scripts\jquery-ui-1.8.11.js to obj\Debug\Package\PackageTmp\Scripts\jquery-ui-1.8.11.js.
  Copying Scripts\jquery-ui-1.8.11.min.js to obj\Debug\Package\PackageTmp\Scripts\jquery-ui-1.8.11.min.js.
  Copying Scripts\jquery.validate-vsdoc.js to obj\Debug\Package\PackageTmp\Scripts\jquery.validate-vsdoc.js.
  Copying Scripts\jquery.validate.js to obj\Debug\Package\PackageTmp\Scripts\jquery.validate.js.
  Copying Scripts\jquery.validate.min.js to obj\Debug\Package\PackageTmp\Scripts\jquery.validate.min.js.
  Copying Scripts\modernizr-1.7.js to obj\Debug\Package\PackageTmp\Scripts\modernizr-1.7.js.
  Copying Scripts\modernizr-1.7.min.js to obj\Debug\Package\PackageTmp\Scripts\modernizr-1.7.min.js.
  Copying Content\Site.css to obj\Debug\Package\PackageTmp\Content\Site.css.
  Copying Scripts\jquery.unobtrusive-ajax.js to obj\Debug\Package\PackageTmp\Scripts\jquery.unobtrusive-ajax.js.
  Copying Scripts\jquery.unobtrusive-ajax.min.js to obj\Debug\Package\PackageTmp\Scripts\jquery.unobtrusive-ajax.min.js.
  Copying Scripts\jquery.validate.unobtrusive.js to obj\Debug\Package\PackageTmp\Scripts\jquery.validate.unobtrusive.js.
  Copying Scripts\jquery.validate.unobtrusive.min.js to obj\Debug\Package\PackageTmp\Scripts\jquery.validate.unobtrusive.min.js.
  Copying Scripts\MicrosoftAjax.js to obj\Debug\Package\PackageTmp\Scripts\MicrosoftAjax.js.
  Copying Scripts\MicrosoftAjax.debug.js to obj\Debug\Package\PackageTmp\Scripts\MicrosoftAjax.debug.js.
  Copying Scripts\MicrosoftMvcAjax.js to obj\Debug\Package\PackageTmp\Scripts\MicrosoftMvcAjax.js.
  Copying Scripts\MicrosoftMvcAjax.debug.js to obj\Debug\Package\PackageTmp\Scripts\MicrosoftMvcAjax.debug.js.
  Copying Scripts\MicrosoftMvcValidation.js to obj\Debug\Package\PackageTmp\Scripts\MicrosoftMvcValidation.js.
  Copying Scripts\MicrosoftMvcValidation.debug.js to obj\Debug\Package\PackageTmp\Scripts\MicrosoftMvcValidation.debug.js.
  Copying Views\_ViewStart.cshtml to obj\Debug\Package\PackageTmp\Views\_ViewStart.cshtml.
  Copying Views\Account\ChangePassword.cshtml to obj\Debug\Package\PackageTmp\Views\Account\ChangePassword.cshtml.
  Copying Views\Account\ChangePasswordSuccess.cshtml to obj\Debug\Package\PackageTmp\Views\Account\ChangePasswordSuccess.cshtml.
  Copying Views\Account\LogOn.cshtml to obj\Debug\Package\PackageTmp\Views\Account\LogOn.cshtml.
  Copying Views\Account\Register.cshtml to obj\Debug\Package\PackageTmp\Views\Account\Register.cshtml.
  Copying Views\Home\About.cshtml to obj\Debug\Package\PackageTmp\Views\Home\About.cshtml.
  Copying Views\Home\Index.cshtml to obj\Debug\Package\PackageTmp\Views\Home\Index.cshtml.
  Copying Views\Shared\Error.cshtml to obj\Debug\Package\PackageTmp\Views\Shared\Error.cshtml.
  Copying Views\Shared\_LogOnPartial.cshtml to obj\Debug\Package\PackageTmp\Views\Shared\_LogOnPartial.cshtml.
  Copying Views\Shared\_Layout.cshtml to obj\Debug\Package\PackageTmp\Views\Shared\_Layout.cshtml.
  Copying packages.config to obj\Debug\Package\PackageTmp\packages.config.
  Copying C:\hudson\jobs\HelloWorldMvc3\workspace\packages\EntityFramework.4.1.10331.0\lib\EntityFramework.dll to obj\Debug\Package\PackageTmp\bin\EntityFramework.dll.
  Copying C:\hudson\jobs\HelloWorldMvc3\workspace\packages\EntityFramework.4.1.10331.0\lib\EntityFramework.xml to obj\Debug\Package\PackageTmp\bin\EntityFramework.xml.
  Copying obj\Debug\CSAutoParameterize\transformed\Views\Web.config to obj\Debug\Package\PackageTmp\Views\Web.config.
  Copying obj\Debug\CSAutoParameterize\transformed\Web.config to obj\Debug\Package\PackageTmp\Web.config.
PipelinePreDeployCopyAllFilesToOneFolder:
  Publish Pipeline Deploy phase Pre-Deploy CopyAllFilesToOneFolder Stage
Package:
  Invoking Web Deploy to generate the package with the following settings:
  $(LocalIisVersion) is 7
  $(DestinationIisVersion) is 7
  $(UseIis) is False
  $(IncludeIisSettings) is False
  $(_DeploymentUseIis) is False
  $(DestinationUseIis) is False
GenerateMsdeployManifestFiles:
  Generate source manifest file for Web Deploy package/publish ...
CollectDatabasesToPublish:
  Creating directory "obj\Debug\Database".
PackageUsingManifest:
  Packaging into C:\MyProject\Package.zip.
  Starting Web deployment task from source:manifest(C:\MyProject\Package.SourceManifest.xml) to Destination:package(C:\MyProject\Package.zip).
  Adding package (package).
  Adding child iisApp (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp).
  Adding child createApp (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp).
  Adding child contentPath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp).
  Adding child dirPath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp).
  Adding child dirPath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\bin).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\bin\EntityFramework.dll).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\bin\EntityFramework.xml).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\bin\HelloWorldMvc3.dll).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\bin\HelloWorldMvc3.pdb).
  Adding child dirPath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\Site.css).
  Adding child dirPath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes).
  Adding child dirPath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base).
  Adding child dirPath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\images).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_flat_0_aaaaaa_40x100.png).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_flat_75_ffffff_40x100.png).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_glass_55_fbf9ee_1x400.png).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_glass_65_ffffff_1x400.png).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_glass_75_dadada_1x400.png).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_glass_75_e6e6e6_1x400.png).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_glass_95_fef1ec_1x400.png).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-bg_highlight-soft_75_cccccc_1x100.png).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-icons_222222_256x240.png).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-icons_2e83ff_256x240.png).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-icons_454545_256x240.png).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-icons_888888_256x240.png).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\images\ui-icons_cd0a0a_256x240.png).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.accordion.css).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.all.css).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.autocomplete.css).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.base.css).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.button.css).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.core.css).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.datepicker.css).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.dialog.css).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.progressbar.css).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.resizable.css).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.selectable.css).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.slider.css).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.tabs.css).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Content\themes\base\jquery.ui.theme.css).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Global.asax).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\packages.config).
  Adding child dirPath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\jquery-1.5.1-vsdoc.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\jquery-1.5.1.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\jquery-1.5.1.min.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\jquery-ui-1.8.11.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\jquery-ui-1.8.11.min.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\jquery.unobtrusive-ajax.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\jquery.unobtrusive-ajax.min.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\jquery.validate-vsdoc.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\jquery.validate.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\jquery.validate.min.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\jquery.validate.unobtrusive.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\jquery.validate.unobtrusive.min.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\MicrosoftAjax.debug.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\MicrosoftAjax.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\MicrosoftMvcAjax.debug.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\MicrosoftMvcAjax.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\MicrosoftMvcValidation.debug.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\MicrosoftMvcValidation.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\modernizr-1.7.js).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Scripts\modernizr-1.7.min.js).
  Adding child dirPath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views).
  Adding child dirPath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views\Account).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views\Account\ChangePassword.cshtml).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views\Account\ChangePasswordSuccess.cshtml).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views\Account\LogOn.cshtml).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views\Account\Register.cshtml).
  Adding child dirPath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views\Home).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views\Home\About.cshtml).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views\Home\Index.cshtml).
  Adding child dirPath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views\Shared).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views\Shared\Error.cshtml).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views\Shared\_Layout.cshtml).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views\Shared\_LogOnPartial.cshtml).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views\Web.config).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Views\_ViewStart.cshtml).
  Adding child filePath (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp\Web.config).
  Adding child setAcl (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp).
  Adding child setAcl (C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\obj\Debug\Package\PackageTmp).
  Adding declared parameter 'IIS Web Application Name'.
  Adding declared parameter 'ApplicationServices-Web.config Connection String'.
  Successfully executed Web deployment task.
  Package "Package.zip" is successfully created as single file at the following location:
  file:///C:/MyProject
  To get the instructions on how to deploy the web package please visit the following link:
  http://go.microsoft.com/fwlink/?LinkId=124618
GenerateSampleDeployScript:
  Sample script for deploying this package is generated at the following location:
  C:\MyProject\Package.deploy.cmd
  For this sample script, you can change the deploy parameters by changing the following file: 
  C:\MyProject\Package.SetParameters.xml
Done Building Project "C:\hudson\jobs\HelloWorldMvc3\workspace\HelloWorldMvc3\HelloWorldMvc3.csproj" (Package target(s)).

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:08.33
Finished: SUCCESS

Import/Export SQL Server database data with SSMS

This post is a visual guide about one of the most powerful features of Microsoft SQL Server Management Studio (SSMS) 2008: Import/Export database data.

These tasks are useful for example when you need to debug an application with real world/production data to find possible bugs in your code. You can import the production database data to your local development database and find what’s causing problems. These tasks can be used to create a protection layer because you won’t be working “directly” with production data.

As you see, if I right click a database in SSMS I get access to this rich menu full of interesting options that deserve a careful study:

SSMS 2008 Import Export Database Tasks

Looking at the above picture you see in Object Explorer that I’m connected to two SQL database servers. The first one is a remote SQL Server (version 10.0.2775) and the other one is my local SQL Server Express (version 10.50.1617) instance.

With this configuration I have the perfect scenario to visually show you how the Import/Export Data… menu options work.

In this blog post I’ll execute the Export Data task. This allows me to test my web application using my local SQL Server instance with real world/production data.
The Import Data… task does practically the same thing but in reverse, logically. I’ll let the execution of the Import task to you dear reader!

OK… If I proceed and select the Export Data… menu option I’ll be able to bring new data to the database that is located on my machine. Data comes from the remote/production server to my local copy of the same database.

After clicking Export Data…, SQL Server Import and Export Wizard pops up. I then select the Data source/Server name (from which Data source type and Server I want to get the data to be imported). In this case, the data comes from the remote SQL server. I use SQL Server Authentication, fill the user name and password and select the Database that’ll provide the data. In Server name field I used the IP address of my remote server.

SQL Server Import and Export Wizard - Choose a Data Source

Now is the time to choose the Destination. In this case it’s my local SQL Server instance. LENIEL-PC is my Windows 7 machine name. SQLEXPRESS is the default SQL Express server name. I also selected the Database I want to receive the imported data. As you see both databases (source and destination) have the same name to make things easy.

SQL Server Import and Export Wizard - Choose a Destination

The wizard then asks if I want to copy data directly from table to table or if I want to write a custom SQL query to shape the data according to specific needs. I’ll select the first option to keep things simple.

SQL Server Import and Export Wizard - Specify Table Copy or Query

In the next screen we get a beautiful list of available tables and views. I’ve selected two tables that I want to copy.

SQL Server Import and Export Wizard - Select Source Table and Views

If you click the Edit Mappings… button (which applies to each table selected in the grid), I can also specify if I want to delete rows before importing data or if I want to append rows to the destination table. I’ll append rows because I have already erased both tables (exams and files) on my local database.

Apontando para cima Table files is linked to table exams through a foreign key. I disabled this foreign key constraint in my local database to avoid conflicts/errors during the import process. Beware because conflicts do appear most of the time. Conflicts are generally related to key violation/duplication.

SQL Server Import and Export Wizard - Column Mappings

As I’m using the free SQL Server Express Edition, the following screen has an interesting information:

In SQL Server Express, Web, or Workgroup, you can run the package that the Import and Export Wizard creates, but cannot save it. To save packages that the wizard creates, you must upgrade to SQL Server Standard, Enterprise, Developer or Evaluation.

This is telling me that I’ll have to go over the wizard (#7 steps) again if I happen to execute this very import process. Really annoying… Irritado … but that’s the price you must pay when using free tools.

SQL Server Import and Export Wizard - Run Package

Next button once more (the last one hallelujah) and we’re ready to go. It’s just a matter of reviewing what’ll be done and pressing the finish button.

SQL Server Import and Export Wizard - Complete the Wizard

After clicking Finish I got this last window:

SQL Server Import and Export Wizard - Execution Successful

Hope this simple and visual guide helps you understand how the data Import and Export processes work when dealing with a SQL Server database inside SSMS.

Free tools
Microsoft SQL Server Express Edition
Microsoft SQL Server 2008 Management Studio Express (SSMSE)

Sistema para Gerenciamento de Academia de GinĂĄstica

Esta Ă© uma aplicação web que nasceu atravĂ©s de uma parceria entre mim (o Ășnico desenvolvedor) e o proprietĂĄrio de uma academia de ginĂĄstica ( a qual eu frequento ). O sistema estĂĄ em uso e o proprietĂĄrio/usuĂĄrio estĂĄ muito satisfeito.

A aplicação valoriza a simplicidade e é super fåcil de usar.

A figura a seguir mostra a home page de onde o usuårio pode acessar as funcionalidades da aplicação. Clique nela para ver uma versão ampliada...

Pågina inicial da aplicação Fitness Center

A aplicação é composta por 5 módulos e possui Controle de Acesso baseado em cargos (Administrador, Professor, Usuårio, etc).

MĂłdulos
- Alunos
- Anamneses
- Medidas
- Pagamentos
- RelatĂłrios ( baseados em grĂĄficos e listas )

O sistema estĂĄ disponĂ­vel em PortuguĂȘs do Brasil (pt-BR) e InglĂȘs (en-US). Ele tem tudo pronto para o caso em que exista a necessidades de localizaçÔes adicionais. É completamente viĂĄvel ter a aplicação em execução em qualquer outra cultura/idioma com pouco trabalho.

Estilos/cores/formatação e logotipo podem ser personalizados usando (CSS).

Tecnologias
A aplicação usa o estado da arte das tecnologias da pilha Microsoft, bem como bibliotecas de código aberto:

C#, .NET Framework 4, ASP.NET MVC 3, SQL Server Compact 4.1, CSS, jQuery 1.5.2, jQuery UI 1.8.12, jQuery Globalization 1.0, jQuery qTip2, modernizr 1.7, Microsoft MVC Ajax, Microsoft Chart Controls for. NET 4, WebGrid, Chirpy

Telas
VocĂȘ pode ver screenshots da aplicação aqui.

Descrição
As seçÔes subsequentes descrevem cada módulo e as açÔes que o usuårio tem permissão para executar.

A lógica de negócios também é descrita ao longo do caminho se eu ver que ela se encaixa na descrição do módulo.

Não é minha intenção descrever cada regra de negócio da aplicação neste post. Este post é uma visão geral.

Alunos
AçÔes: Criar, Editar, Detalhes, Excluir
Este mĂłdulo trata de dados bĂĄsicos do aluno como foto, nome e sobrenome, data de nascimento, endereço, sexo, telefone, e-mail, etc. 
Tudo no sistema estĂĄ relacionado ao aluno. Isto significa que se um aluno Ă© excluĂ­do, os dados de cada mĂłdulo que fazem referĂȘncia aquele aluno tambĂ©m serĂŁo excluĂ­dos.
Alunos que estão em débito são destacados em vermelho na lista/grid de alunos.
Se o nome de um aluno Ă© clicado na lista de alunos, o sistema leva o usuĂĄrio Ă  lista de pagamentos do respectivo aluno.

Anamneses
AçÔes: Criar, Editar, Detalhes, Excluir
Este mĂłdulo manipula as informaçÔes bĂĄsicas sobre o histĂłrico de saĂșde do aluno, tais como se o aluno Ă© hipertenso, diabĂ©tico, fumante, etc. Diferentes tipos de doenças tambĂ©m podem ser selecionados. Estas doenças sĂŁo agrupadas em categorias, tais como doenças dos ossos e articulaçÔes, respiratĂłrias e doenças da tireoide. O estilo da atividade fĂ­sica na qual um aluno se encaixa quando ele se matricula na academia tambĂ©m pode ser selecionado.

Medidas
AçÔes: Criar, Editar, Detalhes, Excluir
Este mĂłdulo trata das medidas das circunferĂȘncias do corpo do aluno. Estas sĂŁo as medidas que o sistema controla:
- Altura (m)
- Peso (kg)
- Gordura (%) 
- Pescoço (m)
- TĂłrax (m)
- GlĂșteos (m)
- Ombro (m)
- Abdome (m)
- Cintura (m)
- Braço Esquerdo (m)
- Braço Direito (m)
- Coxa Esquerda (m)
- Coxa direita (m)
- Panturrilha Esquerda (m)
- Panturrilha Direita (m)

O usuĂĄrio Ă© notificado atravĂ©s da lista de medidas se Ă© hora de tomar novas medidas de um aluno. O intervalo de tempo entre as avaliaçÔes (medidas) pode ser configurado no sistema. Atualmente estĂĄ definido como um intervalo de trĂȘs meses.
A % de Gordura é calculada pelo sistema através de uma fórmula padrão (ver link). Se o usuårio passar o mouse sobre o cabeçalho da coluna (%) Gordura na listagem de medidas ele verå uma tabela com valores padrão para % de gordura que inclui Essencial, Atleta, Fitness, Média e Obeso.

Pagamentos
AçÔes: Criar, Editar, Detalhes, Excluir
Este mĂłdulo Ă© o coração do sistema, uma vez que lida com o que podemos chamar de a Raison d'ĂȘtre (razĂŁo de ser) de um sistema como este.
O sistema permite a criação de pagamentos para um determinado aluno.
O usuårio define um valor de desconto (se necessårio) e o campo total é calculado automaticamente. Depois disso uma data de pagamento deve ser selecionada. Hå também um campo de observação no qual o usuårio pode anotar alguma coisa importante relacionada ao pagamento.
O usuĂĄrio sinaliza que o pagamento foi realizado marcando o campo pago.
Sempre que um pagamento Ă© marcado como pago, o sistema gera um novo pagamento automaticamente (cĂłpia do pagamento feito) para o mesmo aluno com a data de vencimento 1 mĂȘs Ă  frente.

RelatĂłrios
Este mĂłdulo gera 4 tipos de relatĂłrios. SĂŁo eles:

- Total de Pagamentos (grĂĄfico)
O usuĂĄrio seleciona uma data de inĂ­cio e uma data de fim para gerar um grĂĄfico de colunas que agrupa os pagamentos por mĂȘs.

- Pagamentos em Atraso/Vencidos (grid/lista) 
O sistema gera automaticamente um relatĂłrio em formato de lista extraindo os dados dos pagamentos que tĂȘm uma data de vencimento inferior a uma data especificada. Por exemplo: pode-se conceder uma margem (em dias) para que o sistema considere que o aluno estĂĄ em dĂ©bito - 1 semana, 2 semanas, etc apĂłs a data do vencimento do pagamento. Isso pode ser configurado no sistema.

- % Alunos Ativos/Inativos (grĂĄfico)
O sistema gera automaticamente um gråfico em formato de pizza que retrata muito bem essa informação.

- Medidas ao Longo do Tempo (grĂĄfico)
O usuårio seleciona um aluno e uma data de início e fim para gerar um belo gråfico de linhas que mostra o aumento/diminuição das medidas ao longo do tempo.

Por que comprar?
O principal benefĂ­cio Ă© que vocĂȘ terĂĄ um ponto central para gerenciar sua Academia de GinĂĄstica. A partir dele vocĂȘ pode extrair informaçÔes valiosas dos dados. Isto te permite estar sempre um passo Ă  frente para planejar seu prĂłximo passo. NĂŁo haverĂĄ mais anotaçÔes em cadernos e com isso vocĂȘ deixarĂĄ de perder dados importantes!

Instalação
A aplicação é um arquivo .zip (arquivo compactado) e possui todo o que é necessårio para ser executada em um servidor web que tenha o .NET Framework 4 instalado.

Se precisar de ajuda adicional no que diz respeito Ă  hospedagem web/instalação e configuração, eu tambĂ©m posso fazer isso por vocĂȘ. É sĂł me avisar.

HĂĄ tambĂ©m a possibilidade de executar a aplicação em um servidor web local usando Microsoft WebMatrix por exemplo. É assim que instalei o sistema no computador do usuĂĄrio. Fazendo dessa forma vocĂȘ nĂŁo terĂĄ que pagar um provedor de hospedagem on-line. A Ășnica desvantagem neste caso Ă© que vocĂȘ nĂŁo serĂĄ capaz de acessar a aplicação a partir de qualquer lugar.

Como comprar?
Basta clicar no botão abaixo para comprar esta app barata ( somente R$ 1.200,00 ) através do PayPal:


Depois de clicar no botĂŁo acima e concluir o processo de pagamento, escreva para mim e me informe sobre sua compra. Poderei, entĂŁo, dar prosseguimento no processo de negociação entregando para vocĂȘ a aplicação atravĂ©s de e-mail. A aplicação estĂĄ contida em um arquivo .zip pequeno ~4MB.

Software Ă© um campo muito interessante porque vocĂȘ trabalha muito para construir uma aplicação, digamos meses, e o produto Ă© apenas um pacote de alguns megabytes. Vai entender…

Direitos autorais
Este produto de software Ă© protegido por direitos autorais.

VocĂȘ pode ler a EULA aqui (em construção).

Suporte
Ficarei mais do que feliz em fornecer qualquer informação adicional que vocĂȘ precise para que a aplicação seja instalada e funcione em seu servidor.

Se vocĂȘ encontrar algum bug na aplicação eu prontamente irei corrigi-lo e disponibilizarei a aplicação atualizada para vocĂȘ.

Recursos adicionais
Se vocĂȘ precisar de qualquer outro recurso, seja ele um novo mĂłdulo ou relatĂłrio que nĂŁo faz parte desta aplicação, apenas me informe e o considerarei para uma versĂŁo futura.

Software to automate website screenshot capture

I needed a software that allowed me to capture screenshots of a web application I developed. The software should do it automatically (batch capture). This way it’d save me a lot of time.

How do I used to do that?
I visited each web page I wanted to take a screenshot. It took me about 1 hour to finish the work.

I posted a question at Super User as always: Software to automate website screenshot capture and got an answer suggesting that I use a combination of a URL fetcher + Selenium capability to take screenshots.

Well, I tried Selenium (.NET bindings selenium-dotnet-2.0rc3.zip ) to test its screenshot capture feature but it doesn’t seem to fit the job because it doesn’t allow you to configure screenshot properties as size (height x width). Moreover it doesn’t work well with Ajax (requires you to write a lot of code to check for the existence of Ajax calls, etc). This kills a screenshot that needs everything in place (I mean every DOM object should be part of the screenshot). I tried the 3 drivers available: Internet Explorer, Firefox and Chrome. Screenshots taken with Internet Explorer driver were close to what I expected.

This is a sample code I used based on the code taken from here:

using System;
using System.Drawing.Imaging;
using System.Text;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Support.UI;

namespace SeleniumTest
{
    [TestFixture]
    public class SeleniumExample
    {
        private FirefoxDriver firefoxDriver;
    
        #region Setup

        [SetUp]
        public void Setup()
        {
            firefoxDriver = new FirefoxDriver();
        }

        #endregion

        #region Tests

        [Test]
        public void DisplayReport()
        {
            // Navigate
            firefoxDriver.Navigate().GoToUrl("http://localhost/FitnessCenter/Report/TotalPaymentsByPeriod");

            IWebElement startDate = firefoxDriver.FindElement(By.Name("StartDate"));
            
            startDate.Clear();
            startDate.SendKeys("January 2011");

            IWebElement generate = firefoxDriver.FindElement(By.Id("Generate"));
            generate.Click();

            var wait = new WebDriverWait(firefoxDriver, TimeSpan.FromSeconds(5));
            wait.Until(driver => driver.FindElement(By.Id("Map")));

            SaveScreenShot(firefoxDriver.Title);
        }

        /// <summary>
        /// Saves a screenshot of the current error page
        /// </summary>
        public void SaveScreenShot(string fileName)
        {
            // Get the screenshot
            Screenshot screenshot = firefoxDriver.GetScreenshot();

            // Build up our filename
            StringBuilder filename = new StringBuilder(fileName);
            filename.Append("-");
            filename.Append(DateTime.Now.ToString("yyyy-MM-dd HH_mm_ss"));
            filename.Append(".png");

            // Save the image
            screenshot.SaveAsFile(filename.ToString(), ImageFormat.Png);
        }

        #endregion

        #region TearDown

        [TearDown]
        public void FixtureTearDown()
        {
            if (firefoxDriver != null) firefoxDriver.Close();
        }

        #endregion
    }
}

Indeed, Selenium is powerful for what it does, that is, helping you automate browser interactions while you test your code. It even allows you to take a screenshot let’s say when something goes wrong (a test fail for example). That’s great and that’s what it does best. It’s a choice for every operating system since it’s an API that can be programmed against.

Paparazzi! beautiful application iconWhat I needed was something more specialized to take screenshots. A software that allows me to configure screenshot properties. The good news is that I managed to find such piece of software and it’s called Paparazzi! - a very suggestive name by the way. One drawback is that it’s only available for Mac OS. As one would expect, it uses Safari browser engine behind the curtains to capture the screenshots. Paparazzi! has minor bugs but it gets the job done. It doesn’t have documentation. I had a hard time trying to make it work. It has batch capture capability but no docs explaining how to do it. So I hope this post will shed some light…

The following lines describe what I did to achieve my objective with Paparazzi!:

1 - Created a list of URLs I’d like to take screenshots of. Like this (one URL per line):

http://192.168.1.106/FitnessCenter/Account/ChangeCulture?lang=en&returnUrl=%2FFitnessCenter%2F
http://192.168.1.106/FitnessCenter/Student
http://192.168.1.106/FitnessCenter/Student/Create
http://192.168.1.106/FitnessCenter/Student/Edit/79
http://192.168.1.106/FitnessCenter/Student/Details/79
http://192.168.1.106/FitnessCenter/Student/Delete/79
http://192.168.1.106/FitnessCenter/Anamnesis
http://192.168.1.106/FitnessCenter/Anamnesis/Create
http://192.168.1.106/FitnessCenter/Anamnesis/Edit/79
http://192.168.1.106/FitnessCenter/Anamnesis/Details/79

.
.
.

2 - Open Paparazzi! and click the Window menu => Batch capture (really difficult to find this option Disappointed smile ):

Paparazzi! difficult to find Batch Capture menu optionPicture 1 - Paparazzi! difficult to find Batch Capture menu option

3 - Drag and drop a text file .txt (the file that contains the URLs) to the Batch Capture window:

Paparazzi! Batch Capture window surfacePicture 2 - Paparazzi! Batch Capture window surface

Here is where I think I found a limitation and it’s by design. This should definitely not happen IMHO. If you try to add a file clicking on ( + button), Paparazzi won’t let you select a text file. The only way I got it working was selecting the .txt file and then drag and dropping the file to the Batch Capture window.

4 - Configure screenshot properties by clicking the list button (see mouse cursor above it):

Paparazzi! screenshot process basic configurationsPicture 3 - Paparazzi! screenshot process basic configurations

You can define the screenshot size. There are pre-defined values for standard screen resolutions. It allows you to define new presets.

You can also delay the capture to wait the page finish loading, etc.

There are a set of configurations available related to the batch capture functionality. To access these configurations, go to Paparazzi! menu and select Preferences:

Paparazzi! Preferences… menu optionPicture 4 - Paparazzi! Preferences… menu option

The first configuration worth mentioning the Default Filename Format available in the General section:

Paparazzi! General preferences sectionPicture 5 - Paparazzi! General preferences section

Above I’m defining this format:

%t = page title
%Y = year
%m = month
%d = day
%H = hour
%M = minute
%S = second

The example in the picture is pretty clear… Smile

Another set of configurations is available in the Batch capture section:

Paparazzi! Batch Capture preferences sectionPicture 6 - Paparazzi! Batch Capture preferences section

Here you can choose where to save the screenshots as well as the type of the images.

After configuring the batch capture session, it’s the gran finale time...

5 - Click the Play button, go take a coffee and relax while the computer does the job for you Fingers crossed.

Paparazzi! Batch Capture in actionPicture 7 - Paparazzi! Batch Capture in action

Hope you have found this post interesting and that it’s useful to help in documenting a little bit of this small but really powerful application.

Pointing up Now I get all the screenshots in less than 1 minute!

References
Paparazzi!
http://derailer.org/paparazzi/

Fitness Center management software ( web app )

Fitness Center Management System/Web Application
This is a web application that was born in a partnership between me (the only developer) and the owner of a Fitness Center that I happen to be a frequenter/student. It’s currently being used there and he (the owner/user) is really satisfied with it.

The application values simplicity and is super easy to use.

The following screenshot shows the home page from where the user can access the application functionalities. Click it to see a larger version…

Fitness Center Management System Home page

The app comprises 5 modules and has access control based on Roles (Administrator, User, etc).

Modules
- Students
- Anamneses
- Measurements
- Payments
- Reports (chart and grid based reports)

It’s available in Portuguese from Brazil (pt-BR) and English (en-US). It has everything in place in case of additional localization needs. It’s completely viable to have the app running in any other culture/language with little work.

Application styles/colors and logo can be customized using cascading style sheet (CSS).

Technologies
The app uses state of the art technologies from Microsoft stack as well as open source libraries:
C#, .NET Framework 4, ASP.NET MVC 3, SQL Server Compact 4.1, CSS, jQuery 1.5.2, jQuery UI 1.8.12, jQuery Globalization 1.0, jQuery qTip2, modernizr 1.7, Microsoft MVC Ajax, Microsoft Chart Controls for .NET 4, WebGrid, Chirpy

Screenshots
You can see screenshots of the application here.

Description
The subsequent sections describe each module and the actions the user is allowed to perform. Business logic is also described along the way if I see it fits. It’s not my intention to describe every business rule of the application in this post. It’s just an overview.

Students
Actions: Create, Edit, Details, Delete
This module handles basic student data as photo, first and last names, birth date, address, gender, phone, email, etc. 
Everything in the system is related to Student. This means that if a Student is deleted, every other module's data is deleted as well.
Students that are in debt are highlighted in red in the Students list/grid.
If the name of a Student is clicked in the list, the system takes the user to the Payments list of that respective Student.

Anamneses
Actions: Create, Edit, Details, Delete
This module handles basic information about the Student health history such as if the student is hypertense, diabetic, smoker, etc. Different types of diseases can also be selected. These diseases are grouped in categories such as Bones and Joints, Respiratory and Thyroid diseases. The style of physical activity a student currently fits in when he/she joins the Fitness Center can also be selected.

Measurements
Actions: Create, Edit, Details, Delete
This module handles measurements of a Student's body circumferences. These are the measurements the system keeps track:
- Height (m)
- Weight (kg)
- Fat (%)
- Neck (m)
- Thorax (m)
- Buttocks (m)
- Shoulder (m)
- Abdomen (m)
- Waist (m)
- Left Arm (m)
- Right Arm (m)
- Left Thigh (m)
- Right Thigh (m)
- Left Calf (m)
- Right Calf (m)

The user is notified through the measurements list if it's time to take new measurements for a Student. The time interval between measurements can be configured in the system. Currently this is set as a 3 month interval.
Fat (%) is calculated by the system. If the user hovers his mouse over the Fat (%) table header he/she can see a table with standard Fat (%) values that include Essential, Athletes, Fitness, Average and Obese.

Payments
Actions: Create, Edit, Details, Delete
This module is the heart of the system since it handles what we can call the Raison d'ĂȘtre of a system like this.
The system allows the creation of payments for a given Student. The user defines a value, discount (if necessary) and the Total field is automatically calculated. After that a Due date must be selected. There’s also an observation field in which the user can annotate anything important related to that payment. The user signals that a payment was made by checking the Paid field.
Whenever a payment is marked paid, the system automatically generates a new payment (copy of the payment being made) for that same Student with a due date 1 month ahead.

Reports
This module generates 4 types of reports. They are:

- Total Payments ( chart )
The user selects a Start and End date to generate a column chart that groups the payments by month.

- Overdue Payments ( grid/listing ) 
The system automatically generates a grid/listing report extracting data for payments that have a due date less than a specified date. This can be configured in the system.

- % of Active/Inactive Students ( chart )
The system automatically generates a pie chart that depicts very well this information.

- Measurements Over Time ( chart )
The user selects a Student and a Start and End date to generate a beautiful line chart that shows measurements increase/decrease over time.

Why to buy?
I think the main benefit is that you’ll have a centralized point to manage your Fitness Center. From this you can extract valued information from data and be always one step ahead to plan your next endeavor. No more notebook entries and missing important data!

Installation
The app is self-contained in a .zip file that has everything it needs to run on a webserver that has the .NET Framework 4 installed.

If you need additional assistance regarding installation/web server hosting and configuration, I can also do that for you. Just let me know.

There's also the possibility of running the app in a local webserver by using Microsoft WebMatrix for example. This is how I installed it in the user's computer. Doing this way you won't need to pay an online hosting provider. The only downside here is that you won't be able to access the app on the go.

How to buy?
Just click the following button to buy this cheap app ( only $ 600.00 ) through PayPal:

After clicking the button above and completing the payment process, write to me and let me know about the purchase. I can then go further in the negotiation process and handle you the app through e-mail since it’s a small .zip package ~4MB.

Software is a really interesting field because you put a lot of work to construct it, let’s say months and the product is just a package of only a few megabytes. Go figure.

Support
I'll be more than happy in providing any further information you need to get the app up and running on your server.

If you find any bug in the app I'll promptly correct it and send the patched app to you.

Additional features
If you need any other feature, be it a new module or report that is not part of this app, just let me know and I'll consider it for a future release.