Hi there!
We've done our own test and were able to confirm that it's probably a VS 2010 Setup & Deployment project bug. The installer generated by Visual Studio 2010 will fail during installation unless TARGETDIR parameter is passed with a trailing backslash: /AppLocation="[TARGETDIR]\". However, that required trailing backslash leads to duplicate backslash in the directory path, and needs to be stripped out before registering an application with UltiDev Cassini.
Here's how you go about dealing with this issue. You will need to do create an Installer class. The best place to put it is a separate Class Library project. After you have added an Installer class to a DLL project, you need to wire the DLL to Setup project's custom actions. To do that you could follow
this MSDN article starting from "To add the custom action" section, or look at
this part of UltiDev Cassini developer's guide (only instead of using UltiDevCassiniServerConfiguration.dll as a custom action target, you'll use your own Class Library or EXE assembly with the
Installer.cs class having the code below).
The code below is taken from UltiDev Cassini Configuration installer class, updated to handle Visual Studio 2010 parameter problem and can be used freely to replace Installer implementation from UltiDevCassiniServerConfiguration.dll.
Code:using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
namespace UltiDev.Cassini
{
[RunInstaller(true)]
public class Installer : System.Configuration.Install.Installer
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public Installer()
{
// This call is required by the Designer.
InitializeComponent();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
#region BL Methods
private void RegisterApplication(IDictionary stateSaver)
{
string step = string.Empty;
try
{
step = "converting appID parameter to GUID";
string appIDString = Context.Parameters["appid"];
Guid appID = new Guid(appIDString);
step = "getting appLocation parameter value";
string appLocation = Context.Parameters["applocation"];
if (appLocation == null || appLocation.Length == 0)
throw new ApplicationException("Unable to register application. AppLocation parameter is not specified.");
appLocation = appLocation.TrimEnd('\\'); // Added to work around VS 2010 parameter bug
step = "getting appName parameter value";
string appName = Context.Parameters["appname"];
step = "getting appDescription parameter value";
string appDescription = Context.Parameters["appdescription"];
step = "getting appPort parameter value";
int port = 0;
string portValue = Context.Parameters["appport"];
if (portValue != null && portValue.Length > 0)
port = int.Parse(portValue);
step = "getting appDefaultDoc parameter value";
string defaultDocument = Context.Parameters["appdefaultdoc"];
step = "getting appKeepRunning parameter value";
string keepRunningString = Context.Parameters["appkeeprunning"];
bool keepRunning = true;
if (keepRunningString != null && keepRunningString.Length > 0)
keepRunning = bool.Parse(keepRunningString);
step = "calling CassiniConfiguration.Metabase.RegisterApplication() method";
CassiniConfiguration.Metabase.RegisterApplication(
appID, appName, port, appDescription,
appLocation, defaultDocument, keepRunning);
stateSaver["AppID"] = appID.ToString();
}
catch (Exception e)
{
string msg = string.Format("Failed to register an application with Cassini while {0}.", step);
throw new Exception(msg, e);
}
}
private void UnregisterApp()
{
string step = string.Empty;
try
{
step = "converting appID parameter to GUID";
string appIDString = Context.Parameters["appid"];
Guid appID = new Guid(appIDString);
step = "calling CassiniConfiguration.Metabase.UnregisterApplication(appID) method";
CassiniConfiguration.Metabase.UnregisterApplication(appID);
}
catch (Exception e)
{
string msg = string.Format("Failed to unregister Cassini application while {0}.", step);
throw new Exception(msg, e);
}
}
#endregion BL Methods
#region Installer class implementation
/// <summary>
/// Install should not be used with VS 2008-generated MSI
/// because Install is called BEFORE Uninstall.
/// </summary>
/// <param name="stateSaver"></param>
public override void Install(IDictionary stateSaver)
{
base.Install (stateSaver);
}
public override void Commit(IDictionary savedState)
{
base.Commit(savedState);
this.RegisterApplication(savedState);
}
public override void Uninstall(IDictionary savedState)
{
base.Uninstall (savedState);
this.UnregisterApp();
}
public override void Rollback(IDictionary savedState)
{
base.Rollback (savedState);
this.UnregisterApp();
}
#endregion Installer class implementation
}
}
Please let us know if this has helped.
Cheers,
UltiDev Team.
Please donate at
http://www.ultidev.com/products/Donate.aspx to help us improve our products.