Category Archives: Development - Page 7

QuickMon 2.5.2

Sometimes keeping track of version numbers is a job all on its own. I released an update to QuickMon to include the syntax highlighting component I found on Code Project (‘Fast Colored TextBox’ from Pavel Torgashov) for the manual xml editing and SQLQuery collector editing. After some initial issues with the control due to a bug in the .Net framework (Regex classes with Compiled option on x64) it is now working nicely.

Happy monitoring

RegexOptions.Compiled and x64 are not friends

As part of my attempt to use the FastColoredTextBox control I stumble across one of those undocumented .Net bugs that has been laying around for some time without being fixed – The Regex class with RegexOptions.Compiled option compiled under x64 or (Any CPU) that executes extremely slowly. In fact, it performs so slowly that it appears the whole application is frozen for a few minutes while the memory usage slowly climbs to ridiculous levels.

There are only 2 solutions to this issue for now: (1) compile all assemblies with x86 option only (not great if you are running on 64-bit) or (2) do not use the RegexOptions.Compiled option. For me the latter is a better choice since there is hardly a different between compiled and not compiled regular expression processing times – that I can see and certainly better than waiting minutes for a frozen app to start reacting again.

Thanks Microsoft for this one. Great way to waste time trying to look for problems in you own app while it is their crap breaking stuff.

 

Syntax high-lighting

I came across a cool control for syntax high-lighting based on a language (programming languages like C#, TSql etc.) created by  Pavel Torgashov. It provides a customizable way to configure syntax high-lighting based on configuration and you can even provide custom high-lighting based on a simple xml file.

I plan on using it in the QuickMon SQL Query collector’s editor so it  is easier to edit tsql statements. Seeing your code (sql) in different colors make it easier to spot editing problems and also to get a picture of what/where you are doing stuff. Of course, this control is not a compiler so it doesn’t actually do syntax or error checking but it helps with spotting problems if there are simple ones.

 

QPerfmon v1.7 update

I’ve done an update to my QPerfmon utility and converted it to VS2010 using the .Net 4.0 Client framework. Some of the other changes are:

* Line color customizations are now stored in the qpmset definition files

* A direct result of that is that the structure of the qpmset files have changed so version 1.7 files are not compatible with earlier versions of the tool.

* Ability to ‘not’ have an invalid performance counter be disabled. This is useful if you want the tool to continue trying to record values for the perf counter until it becomes available.

* The tool now comes with a proper MSI installer

 

Formatting C# code for blogging

I came across a nice example of a tool that can help with formatting of C# source code that you want to publish (on say Word Press that does not support it). The tool’s source code can be extracted from CodeProject (Fast Colored TextBox for syntax highlighting). Incidentally it can also format VB, HTML, SQL and PHP (pitty about JavaScript 😉 )

EventScavenger updates

I’ve added new Installers for the 2 Windows services in EventScavenger – one for x86 and one for x64. These were just added to the latest recommended download on the site. This include the ‘self-installing’ functionality where you can register the services with Service manager using the “-install” or “-uninstall” parameters.

QuickMon Version 2.3 and Installers

I’ve now updated the QuickMon installers to include some ‘new’ functionality that allows you to choose to install the Windows service as part of the MSI installation.

There are still a few possible quirks – like what happens when you choose not to install the service initially (and do it manually afterwards) or when uninstalling the MSI (without removing the service manually) and then installing a new version ‘and then ‘choosing to install the service. In that case you get an error message that the service is already installed (duh as if you don’t know), the MSI Installer fails and rolls back completely. The solution (one of them) is to simply install the MSI and not choose to install/register the service in Service Manager.

Installers

I’ve learned a whole bunch of new ‘things’ about the standard VS installer during all of this. Mostly how limited the build-in Installer technology is but also some tweaks you can do to still (despite) get something good out of it.

Here is a few tips I came across:

1. When you add a ‘Checkboxes’ custom dialog to the ‘User Interface’ of the installer and want to use the checkbox value as a condition in one of the Custom Action it must look like this e.g: ‘CHKINSTALLSERVICE=1’  (without the quotes). I tried all kind of weird combinations like =”True”, =”1″ etc. that didn’t work…

2. You can have the MSI Installer call the ‘Installer’ classes housed inside your service project (and automatically install it) by adding a ‘Custom Action’ – ‘Install’ action. The default for it is to look for any installer classes inside the assembly. Similarly you can add the same for ‘Uninstall’ but this requires that the service has actually been installed (which is a problem for me since the user can choose not to install it at all)

3. Adding the “-install” and “-uninstall” parameters is nice and all but please remember to run it under an Administrator account (elevated) otherwise it simply fails with an “Access is denied” error. If you understand why then it seems obvious but for people that do not know about this it could be a pain (the error message does not tell you why ‘Access is denied…’)

4. The whole ‘backwards compatibility ID generation thing still baffles me. Upgraded projects (from VS2008 to VS2010) does not show it and the default on VS2010 is false. If not set it seems each time you install a newer version any copy of your shortcuts (like pinned to the taskbar) becomes ‘invalid. This is really a big pain (yes, it is probably easy enough to just unpin/pin again to fix it…)

5. The whole ‘Target platform’ thing is a mess – especially when the solution is under source control. Why do you have to check out the whole project just to change the Target platform setting to rebuild the MSI installer? Why is there not an option to build ‘both’ x86 and x64 at the same time (separate directories or something)?

6. Yes, using a better Installer tool like Wix will probably help… still need to learn how to use it. Anyone have some good tutorials somewhere? 🙂

 

Creating a self installing Windows Service

Being in the business of creating several Windows Services myself (EventScavenger, Event Collector, QuickMon) I started thinking about how to make the whole install and set up process a bit easier and eliminating the manual steps to install a Windows Service.

So what if you can simply run the service ‘exe’ with a “-install” or “-uninstall” parameter and let it do the work for you? Additionally, what if it it can even prompt you for start up type and user account details during the process – all of this without even using installutil…?

Well after some research, testing, trail and error, losing some more hair and eventually finding a way to make it work I now have a way to do all this. Nice thing is it can be used together with an MSI installer as well or even an external app or script.

ProjectInstaller

The trick is to create a custom ProjectInstaller class (not use the wizards that comes with VS to add installers). I’ve added some properties to this class to specify things like Service name, display name, start up type, account type, user name and password.

[RunInstaller(true)]
public class ProjectInstaller : Installer
{

private ServiceProcessInstaller processInstaller;
private System.ServiceProcess.ServiceInstaller serviceInstaller;

#region Added properties
public string ServiceName
{
get { return serviceInstaller.ServiceName; }
set { serviceInstaller.ServiceName = value; }
}
public string DisplayName
{
get { return serviceInstaller.DisplayName; }
set { serviceInstaller.DisplayName = value; }
}
public string Description
{
get { return serviceInstaller.Description; }
set { serviceInstaller.Description = value; }
}
public ServiceStartMode StartType
{
get { return serviceInstaller.StartType; }
set { serviceInstaller.StartType = value; }
}
public ServiceAccount Account
{
get { return processInstaller.Account; }
set { processInstaller.Account = value; }
}
public string ServiceUsername
{
get { return processInstaller.Username; }
set { processInstaller.Username = value; }
}
public string ServicePassword
{
get { return processInstaller.Password; }
set { processInstaller.Password = value; }
}
#endregion

public ProjectInstaller()
{

processInstaller = new ServiceProcessInstaller();
serviceInstaller = new System.ServiceProcess.ServiceInstaller();

Installers.AddRange(new Installer[] {
processInstaller,
serviceInstaller});

}

protected override void OnBeforeInstall(System.Collections.IDictionary savedState)
{

SetContextParameter(“name”, ServiceName);
SetContextParameter(“display”, DisplayName);
SetContextParameter(“desc”, Description);
SetContextParameter(“start”, StartType.ToString());
SetContextParameter(“account”, Account.ToString());

if (Account == ServiceAccount.User)
{

SetContextParameter(“user”, ServiceUsername);
SetContextParameter(“password”, ServicePassword);

}
base.OnBeforeInstall(savedState);

}

public void SetContextParameter(string key, string value)
{

if (!this.Context.Parameters.ContainsKey(key))

this.Context.Parameters.Add(key, value);

else

this.Context.Parameters[key] = value;

}

}

Calling the Installer/uninstaller

In order to get the service executable to handle the -“install” or “-uninstall” parameters I modified the Main method in Program.cs to accept a string parameter array and then call the appropriate method if either of those two parameters are passed.

Example code:

static class Program
{

static void Main(string[] args)
{

if (args.Length > 0)
{

if (args[0].ToUpper() == “-INSTALL”)
{

InstallService();
return;

}
else if (args[0].ToUpper() == “-UNINSTALL”)
{

UnInstallService();
return;

}

}
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new SelfInstallService() };
ServiceBase.Run(ServicesToRun);

}

private static bool InstallService()
{

bool success = false;
try
{

string exeFullPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
string workingPath = System.IO.Path.GetDirectoryName(exeFullPath);
string logPath = System.IO.Path.Combine(workingPath, “Install.log”);
ServiceStartMode startmode = ServiceStartMode.Automatic;
ServiceAccount account = ServiceAccount.LocalService;
string username = “”;
string password = “”;

InstallerForm installerForm = new InstallerForm();
installerForm.StartType = ServiceStartMode.Automatic;
installerForm.AccountType = ServiceAccount.User;
if (installerForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{

startmode = installerForm.StartType;
account = installerForm.AccountType;
if (installerForm.AccountType == ServiceAccount.User)
{

username = installerForm.UserName;
password = installerForm.Password;

}

}

Hashtable savedState = new Hashtable();
ProjectInstaller myProjectInstaller = new ProjectInstaller();
InstallContext myInstallContext = new InstallContext(logPath, new string[] { });
myProjectInstaller.Context = myInstallContext;
myProjectInstaller.ServiceName = “SelfInstallService”;
myProjectInstaller.DisplayName = “Self Install Service”;
myProjectInstaller.Description = “Self Install Service test”;
myProjectInstaller.StartType = startmode;
myProjectInstaller.Account = account;
if (account == ServiceAccount.User)
{

myProjectInstaller.ServiceUsername = username;
myProjectInstaller.ServicePassword = password;

}
myProjectInstaller.Context.Parameters[“AssemblyPath”] = exeFullPath;

myProjectInstaller.Install(savedState);
success = true;

}
catch (Exception ex)
{

System.Windows.Forms.MessageBox.Show(ex.Message, “Install service”, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);

}
return success;

}

private static bool UnInstallService()
{

bool success = false;
try
{

string exeFullPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
string workingPath = System.IO.Path.GetDirectoryName(exeFullPath);
string logPath = System.IO.Path.Combine(workingPath, “Install.log”);

ServiceInstaller myServiceInstaller = new ServiceInstaller();
InstallContext Context = new InstallContext(logPath, null);
myServiceInstaller.Context = Context;
myServiceInstaller.ServiceName = “SelfInstallService”;
myServiceInstaller.Uninstall(null);
success = true;

}
catch (Exception ex)
{

System.Windows.Forms.MessageBox.Show(ex.Message, “Uninstall service”, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);

}
return success;

}

}

You might notice I use a custom form ‘InstallerForm’ here which I’m not showing the code for. All it is is a simple Windows Form that allows you to enter or choose some settings that this code is using. I’ll upload some code example a bit later.

Now, you can simple go to the command line (or create a batch file) that calls the service exe with either the “-install” or “-uninstall” parameters.

Update: I’ve added some sample code here. There have been some improvements since the article. It turns out the overridden method OnBeforeInstall is not necessary at all.

In a new blog post I’ve enhanced the functionality to include multi instance functionality. See this.

QuickMon Version 2.2

There has been some updates to my QuickMon tool (or set of tools). Since the last update I’ve added a new collector – the SQL Query collector, enhance the Windows Service to allow multiple monitor packs to be use at the same time and tried to simplify the management user interface.

With the latest changes it is becoming even more useful. Try it out!

Development tip for testing

Quick tip for all developers/programmers and anyone involved with creating software…

You haven’t tested your software until you’ve broken it yourself – aka negative testing.

If you couldn’t break your program yourself then… either you’re a super duper crazy developer or someone else will find a way to break it and make you look bad!