Tag Archives: code - Page 3

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.

 

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 😉 )

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.

TreeViewEx – a few enhancements

Sometimes I wonder why some functionality that should be common is simply left out of general controls.. like the WinForms TreeView (and ListView) controls that don’t have specific events for the enter key pressed. I’ve been taught long ago to always provide functionality so keyboard events also can be used to navigate around applications – like when the mouse is unavailable, broken or not your first choice (like for disabled people). Yes, I know the controls have general events for key pressing but it requires some hectic coding each time to do something that should be simple.

Anyway, adding it isn’t too difficult (but I still wished I didn’t have to do it each time I need to use it).

public class TreeViewEx : TreeView
{

public TreeViewEx() : base()
{

DoubleBuffered = true;

}
public event MethodInvoker EnterKeyPressed;
public event MethodInvoker DeleteKeyPressed;
protected override void OnKeyPress(KeyPressEventArgs e)
{

if (e.KeyChar == ‘\r’)

if (EnterKeyPressed != null)
{

EnterKeyPressed();
e.Handled = true;

}

base.OnKeyPress(e);

}

protected override void OnKeyDown(KeyEventArgs e)
{

if (e.KeyCode == Keys.Delete)

if (DeleteKeyPressed != null)
{

DeleteKeyPressed();
e.Handled = true;

}

base.OnKeyDown(e);

}

}

The code for the ListView control is basically (exactly) the same.

Extension method to create CSV from List collection

A quick one to share:

I needed to a method to quickly convert a List<string> to a plain comma delimited string. So I created this little Extension class:

public static class ListEx
{

public static string ToCSVString(this List<string> l)
{

StringBuilder sb = new StringBuilder();
if (l != null)
{

l.ForEach(li => sb.Append(li + “, “));

}
return sb.ToString().Trim(‘ ‘, ‘,’);

}

}

Of course this is still very specific to string collections only. I could have created something that does the same to say a List<T> list that is more generic but that I’ll leave for another day.

[Update]

While I’m at it – here is the opposite method:

public static List<string> ToListFromCSVString(this string s, bool ordered = false)
{

List<string> list = new List<string>();
if (s != null && s.Trim().Length > 0)
{

if (ordered)

list.AddRange((from sitem in s.Split(new char[] { ‘,’ }, StringSplitOptions.RemoveEmptyEntries)
orderby sitem
select sitem.Trim()).ToArray());

else

list.AddRange((from sitem in s.Split(new char[] { ‘,’ }, StringSplitOptions.RemoveEmptyEntries)
select sitem.Trim()).ToArray());

}

return list;

}

XmlElementEx – a few XmlElement extension methods

I thought I’d just share a few extension methods I created for myself to handle a hew things with the XmlElement, XmlNode and XmlDocument classes of System.Xml namespace.

These include:

  • ReadXmlElementAttr
  • CreateAttributeWithValue
  • SetAttributeValue
  • AppendElementWithText
  • AppendElementWithCDATA
using System.Xml;

    public static class XmlElementEx
    {
        public static string ReadXmlElementAttr(this XmlElement e, string attrName, string defaultValue = "")
        {
            try
            {
                if (e.HasAttribute(attrName))
                    return e.Attributes.GetNamedItem(attrName).Value;
            }
            catch { }
            return defaultValue;
        }
        public static string ReadXmlElementAttr(this XmlNode e, string attrName, string defaultValue = "")
        {
            return ReadXmlElementAttr((XmlElement)e, attrName, defaultValue);
        }
        public static XmlAttribute CreateAttributeWithValue(this XmlDocument xml, string attrName, bool value)
        {
            return xml.CreateAttributeWithValue(attrName, value.ToString());
        }
        public static XmlAttribute CreateAttributeWithValue(this XmlDocument xml, string attrName, int value)
        {
            return xml.CreateAttributeWithValue(attrName, value.ToString());
        }
        public static XmlAttribute CreateAttributeWithValue(this XmlDocument xml, string attrName, long value)
        {
            return xml.CreateAttributeWithValue(attrName, value.ToString());
        }

        public static XmlAttribute CreateAttributeWithValue(this XmlDocument xml, string attrName, string value)
        {
            XmlAttribute attr;
            attr = xml.CreateAttribute(attrName);
            attr.Value = value;
            return attr;
        }
        public static XmlAttribute SetAttributeValue(this XmlNode e, string attrName, string value)
        {
            return SetAttributeValue((XmlElement)e, attrName, value);
        }
        public static XmlAttribute SetAttributeValue(this XmlElement e, string attrName, string value)
        {
            if (e.HasAttribute(attrName))
                e.Attributes[attrName].Value = value;
            else
                e.Attributes.Append(CreateAttributeWithValue(e.OwnerDocument, attrName, value));
            return e.Attributes[attrName];
        }

        public static XmlElement AppendElementWithText(this XmlElement e, string elementName, string text)
        {
            XmlElement newElement = e.OwnerDocument.CreateElement(elementName);
            newElement.InnerText = text;
            e.AppendChild(newElement);
            return newElement;
        }
        public static XmlElement AppendElementWithCDATA(this XmlElement e, string elementName, string cdataText)
        {
            XmlElement newElement = e.OwnerDocument.CreateElement(elementName);
            XmlCDataSection commentNode = e.OwnerDocument.CreateCDataSection(cdataText);
            newElement.AppendChild(commentNode);
            e.AppendChild(newElement);
            return newElement;
        }
    }

 

Is it my time or not?

Sounds like another philosophical question but no, you can relax. This is another developmental (yes almost mental) posting.

Say you need to create a piece of functionality that must only operate within a predefined time period of a day – call it a ‘service window’. It could be that you may even need several of these ‘windows’ per day – i.e. if there is a pause period inside the day and work must be processed before (up until) and after the pause.

For this kind of functionality I created a ‘ServiceWindows’ class. It basically host a list of ‘from’ and ‘to’ times plus methods that makes it possible to find out if a specified time is somewhere ‘inside’ or ‘outside’ any ‘service window’. Additionally the class can be ‘populated’ from an xml config string so it can be used in applications that operates from xml config files.

So without much further chit-chatting here is the guts of the class (not for sensitive readers 😉

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

    public class ServiceWindow
    {
        public ServiceWindow(DateTime from, DateTime to)
        {
            From = from;
            To = to;
        }
        public DateTime From { get; set; }
        public DateTime To { get; set; }
    }

    public class ServiceWindows
    {
        private List<ServiceWindow> times = new List<ServiceWindow>();
        public List<ServiceWindow> Times { get { return times; } }

        public void AddTimeWindow(DateTime fromTime, DateTime toTime)
        {
            times.Add(new ServiceWindow(fromTime, toTime));
        }
        public bool IsInTimeWindow()
        {
            return IsInTimeWindow(DateTime.Now);
        }
        public bool IsInTimeWindow(DateTime nowTime)
        {
            if (times.Count == 0)
                return true;
            else
                return (from t in times
                        where t.From.TimeOfDay <= nowTime.TimeOfDay &&
                              t.To.TimeOfDay >= nowTime.TimeOfDay
                        select t).Count() > 0;
        }

        public void CreateFromConfig(string config)
        {
            if (config.Length > 0)
            {
                times.Clear();
                XmlDocument configXml = new XmlDocument();
                configXml.LoadXml(config);
                XmlElement root = configXml.DocumentElement;
                foreach (XmlNode windowItem in root.SelectNodes("window"))
                {
                    try
                    {
                        DateTime fromTime = DateTime.Parse(windowItem.ReadXmlElementAttr("from", "00:00:01"));
                        DateTime toTime = DateTime.Parse(windowItem.ReadXmlElementAttr("to", "23:59:59"));
                        times.Add(new ServiceWindow(fromTime, toTime));
                    }
                    catch { }
                }
            }
        }
        public string ToConfig()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("<serviceWindows>");
            if (times.Count > 0)
                foreach (ServiceWindow timeWindow in times)
                    sb.AppendLine(string.Format("<window from=\"{0}\" to=\"{1}\" />",
                              timeWindow.From.ToString("HH:mm:ss"),
                              timeWindow.To.ToString("HH:mm:ss")));

            sb.AppendLine("</serviceWindows>");
            return sb.ToString();
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            if (times.Count > 0)
                foreach (ServiceWindow timeWindow in times)
                    sb.Append(string.Format("{0} to {1} and ",
                           timeWindow.From.ToString("HH:mm:ss"),
                           timeWindow.To.ToString("HH:mm:ss")));
            else
                sb.Append("None");
            return sb.ToString().Trim(' ', 'a', 'n', 'd');
        }
    }

I noticed that I included an XmlNode extension method (ReadXmlElementAttr) that I defined elsewhere but all it does is to read an xml element attribute or provide a default value if not found. I’ll list that class here on my blog too soon.

Waiting for your exit

With a heading like this the post could be mistaken for something more philosophical but fortunately this is a plain developmental posting 🙂

Suppose you have some program that does some work and then have to ‘sleep’ for a while before doing some more work – like a service checking or polling stuff. You can simply use something like a Thread.Sleep() but that also means the thread cannot do or respond to anything else during that time – like the program or service stopping. That would mean the stopping process has to wait until the ‘sleeping’ thread becomes active again.

A solution to this is by having a variable or property that indicates if the program or service is still running and having the ‘waiting’ routine wait in little ‘jumps’ checking the ‘IsRunning’ variable each time and then waiting a little bit more until the full ‘sleeping’ period time is done.

private void BackgroundWaitIsPolling(int nextWaitInterval)
{
   int waitTimeRemaining;
   int decrementBy = 2000;
   if (IsRunning)
   {
       try
       {
           if ((nextWaitInterval <= decrementBy) && (nextWaitInterval > 0))
           {
               Thread.Sleep(nextWaitInterval);
           }
           else
           {
               waitTimeRemaining = nextWaitInterval;
               while (IsRunning && (waitTimeRemaining > 0))
               {
                  if (waitTimeRemaining <= decrementBy)
                  {
                      waitTimeRemaining = 0;
                  }
                  else
                  {
                      waitTimeRemaining -= decrementBy;
                  }
                  if (decrementBy > 0)
                  {
                      Thread.Sleep(decrementBy);
                  }
               }
           }
        }
        catch { }
   }
}

 

Extending the TreeView control

Here is a little Extension class to the TreeView control. I created it to add some new functionality that is not available in the base control. It is based on the System.Windows.Forms namespace TreeView but probably can be use relatively easy without too much modification on WPF as well (haven’t tried it yet)

public static class TreeViewEx
    {
        public static int CheckedCount(this TreeView tvw)
        {
            int count = 0;
            count = (from TreeNode n in tvw.Nodes
                     where n.Checked
                     select n).Count();
            foreach (TreeNode childNode in tvw.Nodes)
            {
                count += CheckedCount(childNode);
            }

            return count;
        }
        public static int CheckedCount(this TreeNode parentNode)
        {
            int count = 0;
            count = (from TreeNode n in parentNode.Nodes
                     where n.Checked
                     select n).Count();
            foreach (TreeNode childNode in parentNode.Nodes)
            {
                count += CheckedCount(childNode);
            }
            return count;
        }
        public static List<TreeNode> CheckedNodes(this TreeView tvw)
        {
            List<TreeNode> checkedNodes = new List<TreeNode>();
            foreach(TreeNode node in (from TreeNode n in tvw.Nodes
                         select n))
            {
                if (node.Checked)
                    checkedNodes.Add(node);
                checkedNodes.AddRange(node.CheckedNodes().ToArray());
            }
            return checkedNodes;
        }
        public static List<TreeNode> CheckedNodes(this TreeNode parentNode)
        {
            List<TreeNode> checkedNodes = new List<TreeNode>();
            foreach (TreeNode node in (from TreeNode n in parentNode.Nodes
                                           select n))
            {
                if (node.Checked)
                    checkedNodes.Add(node);
                checkedNodes.AddRange(node.CheckedNodes().ToArray());
            }
            return checkedNodes;
        }
        public static void ExpandAllParents(this TreeNode node)
        {
            TreeNode parent = node.Parent;
            while (parent != null)
            {
                parent.Expand();
                parent = parent.Parent;
            }
        }
    }

Console.ReadKey with timeout

There have been multiple times I wished I had a method for this. Often when you are testing things using a plain console application you want to view some output but not have to wait forever (using something like Thread.Sleep) or every time needing to press the ‘Any’ key 😉

Actually I’m a bit surprised .Net hasn’t got something like this built in yet but since it doesn’t I had to create one myself. I created a utility class with a single method to accomplish this. I thought about using an extension method but since the Console class is itself static extension methods does not work for it.

public static class ConsoleHelper
{

public static ConsoleKeyInfo ReadKeyWithTimeOut(int timeOutMS)
{

DateTime timeoutvalue = DateTime.Now.AddMilliseconds(timeOutMS);

while (DateTime.Now < timeoutvalue)
{

if (Console.KeyAvailable)
{

ConsoleKeyInfo cki = Console.ReadKey();
return cki;

}
else
{

System.Threading.Thread.Sleep(100);

}

}
return new ConsoleKeyInfo(‘ ‘, ConsoleKey.Spacebar, false, false, false);

}

}

What this gives you is a method that waits until the specified time-out expires or any (normal) key has been pressed.