Category Archives: Development - Page 9

Basic string to integer conversion extensions

Sometimes the more simpler things in life really help. Take the following couple of .Net extensions posted to CodeProject. Some of these will make (developer) life a bit easier.

http://www.codeproject.com/Tips/211015/Basic-string-to-integer-conversion-extensions

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.

Event collector

Ok, I’ve built a working service that utilize the event driven Event log functionality built into .Net’s EvenLog class – and not the newer System.Diagnostics.Eventing.Reader classes because I’m having problems getting it to properly return all the data I require.

This new service (a Windows service) runs alongside the existing EventScavenger service. It does not replace it since there are core functionality it lacks (and always will). For example – there is no guarantee that it will capture every event generated in the event log and any entries that get logged while it is not running will be missed – this include past entries as well. So I’m contemplating running both services side-by-side, first for testing but also probably in the future. The only real benefit of the new service is that it keeps the data stored in the database much more ‘up to date’ in case that is what you want. However, EventScavenger was created in the beginning to do the opposite – to be able to look up events in the past and do some reporting on it. Perhaps the combination of both old and new services together can be of use to some.

To poll or not to poll, what am I polling?

This is a question many have asked but the answer is never right for all scenarios. The question is coming up again with my EventScavenger system but the answer is not obvious. There are benefits to both polling and not polling (usually by something that raises events). This is really an architectural question and I’m kind of just blamestorming by myself (blaming myself among other things).

A quick overview of the definitions (in my context of my scenario):

What is polling?

Usually this is an action where something running locally periodically access something remotely and then gather data, do some work (store data) and then go to some sleep or waiting state again until a next scheduled time.

What is the alternative (not polling)?

Usually this involves something at the source pushing the data you need locally to you (or the data storage place where you can access it). You also must have something that ‘subscribe’ to this event to capture it.

What are the benefits of each/each approach?

Polling:

  • Not active the whole time – i.e. open connections over network, resource handles etc. It spends time ‘waiting’ until next scheduled polling event.
  • Don’t require remote software to be installed (something that subscribes to the events)
  • No ‘missed’ events to worry about. On each poll you gather all relevant data since previous polling anyway.
  • Easier to administrate as it is usually a central component/service.

Not polling (Events):

  • Data gets transferred/stored ‘as it happens’.
  • No big batches of data send over network – each event’s data is sent on its own.
  • No network traffic while there is no data to report on
  • Number of remote locations not (so much) limited to what a single ‘poller’ could handle.

Unfortunately there is no golden ‘middle way’. Its either the one or the other approach (per resource you want to access). The current approach for EventScavenger is plain old polling (each event log is done on a separate thread. This works well up to a point until (1) the number of threads become too many, (2) the number of events per ‘poll’ get so many that the particular thread cannot process things quickly enough. To overcome the these problems you can install an instance (collector as named in the EventScavenger context) on the source machine. That can work if you access to the machine (are allowed to install) but then you might as well ask why not use the event driver approach?

The flip side is with subscribing to events is that you must have something installed ‘locally’ on the resource (eventlog in this case) to access the data. That requires something installed and/or running extra there. Also, if for any reason the subscriber is down/busy or something the events raised would be missed with no way to get them back again afterwards.

I’ve been looking at the EventLog.EntryWritten event and also the whole new System.Diagnostics.Eventing.Reader.EventLogWatcher class. Both only works for the local event logs and I’m having issues with the newer EventRecord class that does not give me the proper full description message (always return a null). Perhaps I have to look at an additional component that runs alongside the existing ‘collectors’ services to gather ‘problem child’ event logs – but on the actual source machine and just for raised events. This could help other people but I’m having a situation where I cannot install something on the sources of the logs that must be imported since they are ‘off-limits’ (Domain controllers and Windows Core installs)

Why can’t life be easy? 😉

EventScavenger 4.2

I recently had the ‘pleasure’ of having my EventScavenger tool being used to track the security event logs of a couple of domain controllers for a ‘full’ enterprise company. It may be temporary for us to help a specific issue but in the process I had to re-look at how the collector service (the heart of EventScavenger) performs under really high stress. In case you don’t fully appreciate it, with full auditing for successful and failed events these event logs full up within an hour or so – and they have been set to something like 100MB+! Events literally flood into the logs at (sometimes) 10000 plus events in a single minute.

Now, I’ve never had any performance problems with the collectors until now. I’ve had a single collector running on a plain old pc gathering around 50 logs or more running 24×7 for 4-5 years. In all those cases each individual event log never have more than 20MB of data in them and almost never full of data that gets overwritten within an hour or so. The problem with the domain controller event logs are the sheer volume of events written ‘all the time’ plus the collector is running on a separate pc with the sql database on a remote system that is shared with dozen of other systems. The end result is that events retrieved from the logs cannot (1) be read quickly enough and (2) written quickly enough to the database. The first problem is not something I can do anything about now – other than having a collector installed on each of the domain controllers. This is not feasible as it won’t be allowed and they are Windows Core machines anyway.

To address the second issue I did some research into how to submit batches of records to the database since doing it one by one just isn’t fast enough. I know about the new table variable in newer versions of sql server but unfortunately the server that was provided is only sql 2005 which does not support that. Fortunately it does support the xml data type even as a parameter. I found an article ‘Sending Multiple Rows to Database for Modification‘ on codeproject that specifically deals with sql 2005 that describes 2 ways to accomplish this: using a delimited string or the xml data type. The delimited option won’t work for me as it is limited to about 4000 characters and the amount of data I deal with is orders of magnitude more than that. The xml data type allows for up to 2GB in a single shot!

I did quite a few performance tests and there is a real increase in number of records that can be processed using batches – despite the possible overhead of first converting the rows to xml and then sql server converting it back to a table (in memory). Interestingly, increasing the batch size beyond a certain point (1000 as I tested) does not increase the overall throughput. It more or less stay linear. The problem with that is you increase the chance that a single failure caused by one row can make the whole batch fail. So the best is to have a batch size that is big enough to warrant the benefit but not too big so it can cause failures.

Example code

A basic example of the sql xml handling:

Declare @xml  XML
SET @xml = N’
<rs>
<r cn=”machineName” l=”logName” etc />
…
</rs>’
SELECT
T.Row.value(‘@cn’, ‘VARCHAR(255)’) MachineName,
T.Row.value(‘@l’, ‘varchar(255)’) LogName
FROM   @xml.nodes(‘/rs/r’) AS T(Row)

To generate the xml on client side (simplified code):

System.IO.MemoryStream outstream = new System.IO.MemoryStream();
using (System.Xml.XmlTextWriter wrt = new System.Xml.XmlTextWriter(outstream, Encoding.UTF8))
{

wrt.Formatting = System.Xml.Formatting.Indented;
wrt.Indentation = 1;
wrt.IndentChar = ‘ ‘;
wrt.WriteStartDocument();
wrt.WriteStartElement(“rs”);

foreach (EventLogEntry ele in eventEntries)
{

wrt.WriteStartElement(“r”);
wrt.WriteAttributeString(“cn”, machine);
wrt.WriteAttributeString(“l”, logName);

…
wrt.WriteEndElement(); //r

}

wrt.WriteEndElement(); //rs
wrt.WriteEndDocument();
wrt.Flush();

outstream.Position = 0;
InsertEventLogEntries(outstream);

}

…

public InsertEventLogEntries(System.IO.Stream xml)
{

string sql = “InsertEventLogEntries”;
System.Data.SqlTypes.SqlXml sxl = new System.Data.SqlTypes.SqlXml(xml);
SqlParameter[] parms = new SqlParameter[] {
new SqlParameter(“@xml”, SqlDbType.Xml) { Value = sxl}
};
using (SqlCommand cmnd = new SqlCommand(sql, insertConn))
{
cmnd.CommandType = CommandType.StoredProcedure;
cmnd.CommandTimeout = CommandTimeout;
cmnd.Parameters.AddRange(parms);
try
{

cmnd.ExecuteNoQuery();

}
catch { throw; }

}

So with this change it is possible to handle larger sets of inserts into the database. Now only if there was a way to make reading an event log faster…

Embedding a Form inside another control

This is something I was thinking about at the beginning of my TDI (Tabbed document interface) ‘adventure’ but I didn’t think it would be easy or possible back then. Then I came across a custom tab control (A highly configurable MDI tab control from scratch) that actually allowed you to use plain old WinForms to add to it. The control itself was written in VB and ultimately I abandoned using it but I was intrigued with how it could use a plain WinForm. It actually has some real advantages like.

  • A form you can design easier in the IDE (than a user control).
  • A form can be tested/used separately on it own without being embedded onto something else first.
  • And I had a blank thinking of more reasons…

If you try to just add a Form to another container – like a panel, tabpage etc. and try to run it you would get the error: ‘Top-level control cannot be added to a control.‘. This happens because Forms are marked as Top Level controls. Fortunately, there is a simple way around it. You need to mark the form as not being a ‘Top level control’ like this: (assuming you have a panel called panel1)

Form f = new Form();
f.TopLevel = false;
panel1.Controls.Add(f);
f.Show(); //this is needed to actually have the form display itself inside the container

That will make the form load inside the panel without run-time errors – but it would look ugly if you just leave it like that. To properly ’embed’ it you need to add some more code:

Form f = new Form();
f.TopLevel = false;
f.MdiParent = null;
f.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
f.Dock = DockStyle.Fill;
panel1.Controls.Add(f);
f.Show();

So, there you have it!

Form2 f = new Form2();
            f.TopLevel = false;

Tab control

I’ve come across a tab control that I can customize for my needs in creating a MDI window replacement. It is based on the KRBTabControl article from Karub Yaz?l?m on CodeProject.

I’ve added some built-in context menu that adds a few options for closing a tab, closing all tabs, closing all other tabs and view a list of the available tabs from a modal dialog window. The rest is pretty much the original control except for some enums that I moved around.

My version can be found here.

* Update *

I’ve added an event to the control to fire when a tab page get removed. The code to achieve this looks like this:

public event TabPageRemovedDelegate TabPageRemoved;
private void RaiseTabPageRemoved(TabPageEx tab)
{

if (TabPageRemoved != null)

TabPageRemoved(tab);

}

The ‘RaiseTabPageRemoved’ method then gets called from the main OnMouseClick plus my new context menu events to close tabs.

Multilingual applications

Living in the good old S of A it is natural for us to be bilingual or even multilingual. So what do we do if we have to create software that can/must be used by people of multiple language backgrounds? Traditionally Microsoft had the concept of resource files that you can use to create multiple versions of the same application for different languages or locales. Problem with this is once the executable has been compiled it is also fixed. What happens if you want the application to be multilingual at ‘run-time’?

Well, I’ve had to do something like this for myself. I first looked at resource files but it just did not solve the whole issue on its own. So I started creating something for myself that works for my application. Part of the solution still use .Net resource files for storing xml data that gets use in the language look up procedure. The idea is to load the text of controls and windows at the time the window open since control and window text get loaded at run-time anyway. The following is an explanation of the classes I created to facilitate my solution. It is a fully working solution and already in use inside a proper application. There may be other and even better or smarter solutions ‘out there’ but this one works for me.

LanguageHandler

This is the central class that handles all the language setting/reading etc. functionality. It encapsulate the list of ‘phrases’ used in the application and provides methods to retrieve words or phrases depending on a look-up key. Simply translating words alone is not good enough so the focus is on whole ‘phrases’.

The following is a partial view of the class without methods:

public static class LanguageHandler
{

private static List<Phrase> phraseList = new List<Phrase>();

#region Properties
private static string languageID = “en-za”;
public static Language AppLanguage {

get {

switch (languageID) {
case “af”:
return Language.Afrikaans;
case “en-za”:
return Language.English;
default:
return Language.Afrikaans; }

}
set {

switch (value) {
case Language.Afrikaans:
languageID = “af”;
break;
case Language.English:
languageID = “en-za”;
break;
default:
languageID = “en-za”;
break; }

}

public static string PhraseSource { set; get; }
#endregion

}

PhraseList.xml

The definition of the phrases can probably be stored in any data form but I choose a plain simple xml file to host the raw phrase data. This make it easy to maintain and port. It is also included into the application as a file resource although theoretically it could be located anywhere as long as the application can reach it.

The structure is also very basic as it is simply a serialized version of List<Phrase>

<?xml version=”1.0″ encoding=”utf-16″?>
<ArrayOfPhrase xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema”>
<phrase id=”someId” default=”Some default”>

<phraseEntry lang=”af”>Afrikaanse waarde</phraseEntry>
<phraseEntry lang=”en-za”>English value</phraseEntry>

</phrase>
<phrase id=”someId2″ default=”Some default 2″>

…

</ArrayOfPhrase>

LoadPhrases method

Loading the data is as simple as deserializing the data. I have a helper class (not shown) to simply take the xml file and deserialize it:

#region LoadPhrases
public static void LoadPhrases()
{

if ((PhraseSource != null) && (PhraseSource.Length > 0))

phraseList = SerializationUtils.DeserializeXML<List<Phrase>>(PhraseSource);

}
#endregion

GetLanguagePhrase method

The main (and only relevant) method for retrieving stuff from the class is GetLanguagePhrase. It simply takes one parameter – the id value of the phrase required.

#region GetLanguagePhrase
public static string GetLanguagePhrase(string languagePhraseID)
{

if (phraseList.Count == 0)

LoadPhrases();

Phrase phrase = (from p in phraseList where p.LanguagePhraseID == languagePhraseID select p).FirstOrDefault();
if (phrase != null)
{

PhraseEntry phraseEntry = (from pe in phrase.Phrases where pe.LangId == languageID select pe).FirstOrDefault();
if (phraseEntry != null)

return phraseEntry.Text;

else

return phrase.DefaultValue;

}
throw new Exception(“Undefined language phrase ID”);

}
#endregion

SetControlTextAndTip methods

To make it a bit easier to set the text (and tooltips if available) of controls (my implementation use WinForms) I created a few helper methods to automatically set the text on the control based on a phrase id specified.

#region SetControlText
public static void SetControlTextAndTip(string languagePhraseID, params ToolStripItem[] tsis)
{

string text = GetLanguagePhrase(languagePhraseID);
foreach (ToolStripItem tsi in tsis)
{

tsi.Text = text;
tsi.ToolTipText = text;

}

}
public static void SetControlTextAndTip(string languagePhraseID, params Control[] crtls)
{

string text = GetLanguagePhrase(languagePhraseID);
foreach (Control crtl in crtls)
{

crtl.Text = text;

}

}
public static void SetControlTextAndTip(string languagePhraseID, params ColumnHeader[] columnHeaders)
{

string text = GetLanguagePhrase(languagePhraseID);
foreach (ColumnHeader ch in columnHeaders)
{

ch.Text = text;

}

}
#endregion

The Phrase and PhraseEntry classes

These two classes are really simple. For the purpose of this article they could be a lot simpler but since I built a separate ‘editor’ they have a bunch of attributes to make editing easier. This editor plus a few method inside LanguageHandler will have to wait for another article.

[Serializable, XmlType(“phrase”)]
public class Phrase : IComparable
{

[XmlAttribute(“id”),
Browsable(true),
CategoryAttribute(“Identifier”),
DefaultValueAttribute(“”),
DescriptionAttribute(“Phrase ID”),
ReadOnly(true)]
public string LanguagePhraseID { get; set; }
[XmlElement(“phraseEntry”),
Browsable(true),
CategoryAttribute(“Value details”),
DefaultValueAttribute(“”),
DescriptionAttribute(“Phrase entries”)]
public List<PhraseEntry> Phrases { get; set; }
[XmlAttribute(“default”),
Browsable(true),
CategoryAttribute(“Value details”),
DefaultValueAttribute(“”),
Editor(typeof(MultilineStringEditor), typeof(UITypeEditor)),
DescriptionAttribute(“Default value. Use ‘\\r\\n’ to indicate crlf.”)]
public string DefaultValue { get; set; }

#region IComparable Members
public int CompareTo(object obj)
{

Phrase otherPhrase = (Phrase)obj;
return LanguagePhraseID.CompareTo(otherPhrase.LanguagePhraseID);

}
#endregion

}

[Serializable, XmlType(“entry”), TypeConverter(typeof(PhraseEntryConverter))]
public class PhraseEntry
{

public PhraseEntry() { }
public PhraseEntry(string phraseEntryDef)
{

if (phraseEntryDef.Contains(“:”))
{

LangId = phraseEntryDef.Substring(0, phraseEntryDef.IndexOf(“:”));
Text = phraseEntryDef.Substring(phraseEntryDef.IndexOf(“:”) + 1);

}

}

[XmlAttribute(“lang”),
Browsable(true),
CategoryAttribute(“Phrase entry”),
DefaultValueAttribute(“”),
DescriptionAttribute(“Language”)]
public string LangId { get; set; }
[XmlText(),
Browsable(true),
CategoryAttribute(“Phrase entry”),
DefaultValueAttribute(“”),
Editor(typeof(MultilineStringEditor), typeof(UITypeEditor)),
DescriptionAttribute(“Text”)]
public string Text { get; set; }

public override string ToString()
{

return LangId + “:” + Text;

}

}

Using it all

Using LanguageHandler is really easy. Typically in a form’s onload event I call a private local method that sets all the texts of the controls that need to be set. There is no real performance issue to worry about since all the phrase data is stored in memory. One disadvantage is that normally the form need to be closed and reopened if the ‘language’ has change. This is not really a problem since changing the language is something that should not happen often. Technically this private LoadLanguageResources method could be ran any number of times whenever you want. The only place where I usually call it multiple times is on the ‘Options’ dialog where you choose the language being used.

If you have to use the same phrase multiple times you can always store the value in a local string variable.

The following is a short example of how to use it:

static class Program
{

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{

…
if (Properties.Settings.Default.LanguageID == “English”)

LanguageHandler.AppLanguage = Language.English;

else

LanguageHandler.AppLanguage = Language.Afrikaans;

LanguageHandler.PhraseSource = Properties.Resources.PhraseList;
LanguageHandler.LoadPhrases();
…
Form mainForm = new MainForm();
…
Application.Run(mainForm);

}

public partial class MainForm : Form
{

….

private void LoadLanguageResources()
{

Text = LanguageHandler.GetLanguagePhrase(“AppName”);
LanguageHandler.SetControlTextAndTip(“File”, fileToolStripMenuItem);
LanguageHandler.SetControlTextAndTip(“NewPerson”, newPersoonToolStripMenuItem);
…

}

private void MainForm_Load(object sender, EventArgs e)
{

LoadLanguageResources();
…

}

…

}

Summary

As you can see the solution is not really complicated. I really like simple solutions that ‘just works’. This one has proven to be working for my needs so far. I have over 340 different phrases, some are very long themselves like message box prompts.

Creating a zip file in .Net without using external libraries

I came across an article on Codeproject that show how to use the built-in Microsoft .Net 4 classes (hidden) to handle more generic zip files. .Net does have a public System.IO.Compression namespace but it only expose gzip class. There is also the System.IO.Packaging classes but it is proprietary interface to support only things like Office Open XML.

Fortunately the .Net 4 assembly WindowsBase.DLL contains some more generic zip file handling routines (MS.Internal.IO.Zip) but unfortunately it is not exposed publicly. With the use of reflection you can access it – although it is probably not recommended for general use as Microsoft can change the interfaces any time they like because it is not public. Also, because it uses reflection there might be a performance hit plus issues trying to use it while not running under Full Trust because it requires ‘ReflectionPermission’ permissions.

At least this is a potential alternative. On the long run it would be better if Microsoft expose a generic public zip file handling interface. There might be a licensing issue that is causing them not to include it – since the zip standard as far as I remember is owned by PKWARE and it is not public.

IlSpy

Until fairly recently you could use a free tool called Reflector to view/disassemble .Net libraries to see what is going on inside them. The company making this tool got greedy and is now charging for it – not nice of them. Fortunately another team of developers started creating another open source tool with similar functionality – IlSpy.

It also support plug-ins so it is also extendable. Nice!