Tuesday, August 03, 2010

Friday, June 04, 2010

Another String Function

So a reader called MD left a comment on my previous Case Insensitive String Replace post asking how he could use similar logic to find a substring, but instead of replacing it, surround it with other strings without changing the case of the original text. Specifically, he wanted to insert some kind of formatting tags around the substring to highlight it when it was displayed on screen, for use in a ‘find’ feature.

Well, this isn’t very hard at all. The basic logic for the original function went something like this;

1. Find the index of the first/next instance of the substring.

2. Add everything up to that point to the return value.

3. Add the substitute value to the return value.

4. Repeat from step 1 until no more instances found.

5. Append any remaining text after the last substring occurrence found.

This gets adjusted to;

1. Find the index of the first/next instance of the substring.

2. Add everything up to that point to the return value.

3. Add the prefix to the return value.

4. Add the portion of the original string from the index where the substring was found, up to the length of the substring (i.e the substring in it’s original case).

5. Add the suffix to the return value.

4. Repeat from step 1 until no more instances found.

5. Append any remaining text after the last substring occurrence found.

There’s a little bit of extra code to deal with situations like the substring not being found at all, or null values being passed in, but that’s basically it. Here’s a simple, verbose implementation of the code;

    static void Main(string[] args) 
    { 
      string testStr = "Microsoft Visual Studio"; 
      string newStr = EncloseSubstring(testStr, "VISUAL", "<b>", "</b>");
      newStr = EncloseSubstring(testStr, "o", "[", "]"); 
      newStr = EncloseSubstring(testStr, "Microsoft", "<b>", "</b>"); 
      newStr = EncloseSubstring(testStr, "StuDiO", "<b>", "</b>"); 
      newStr = EncloseSubstring(testStr, "fred", "<b>", "</b>"); 
    }    
    
    private static string EncloseSubstring(string originalString, string substring, string prefix, string suffix) 
    { 
      if (originalString == null) throw new ArgumentNullException("originalString"); 
      if (substring == null) throw new ArgumentNullException("substring");
      if (prefix == null) throw new ArgumentNullException("prefix"); 
      if (suffix == null) throw new ArgumentNullException("suffix"); 
      int substringStartIndex = originalString.IndexOf(substring, 0, StringComparison.OrdinalIgnoreCase);
      int substringLength = substring.Length; 
      int previousIndex = 0; 
      StringBuilder retVal = new StringBuilder(originalString.Length); 
      
      while (substringStartIndex >= 0) 
      { 
        retVal.Append(originalString.Substring(previousIndex, substringStartIndex - previousIndex)); 
        retVal.Append(prefix); 
        retVal.Append(originalString.Substring(substringStartIndex, substringLength));
        retVal.Append(suffix);
        previousIndex = substringStartIndex + substringLength; 
        substringStartIndex = originalString.IndexOf(substring, substringStartIndex + 1, StringComparison.OrdinalIgnoreCase);
      }
      if (retVal.Length > 0 && substringStartIndex < originalString.Length && substringStartIndex >= 0)
        retVal.Append(originalString.Substring(previousIndex + substringLength));
      else if (previousIndex < originalString.Length)
        retVal.Append(originalString.Substring(previousIndex));
      return retVal.ToString();
    }
 




Technorati Tags: ,,,

Friday, May 07, 2010

POS for .NET and Framework 4

Sigh. It would *appear* that the Microsoft Pos .Net library and the .Net 4.0 framework are not 100% compatible. This Pos .Net Forum post explains the problem, which is basically that the Pos .Net binaries include CAS policies (which they should have in previous versions) and .Net 4 has dropped CAS support in many cases. As a result .Net 4 now generates a warning/error unless the application configuration file is modified to specifically re-enable CAS.

Hopefully Microsoft will provide a fix for Pos .Net soon... but perhaps more of a concern is what other libraries, be they 1st, 2nd or 3rd party, are now broken ? You're own libraries you can update easily enough (probably), but if this becomes a prevalent problem with other .Net dependencies it could be a real headache !

Thursday, May 06, 2010

2.5x More Storage for SQL Server Express

This might be old news to some people, but this morning I had reason to download SQL Server Express 2008 R2 and I noticed they are advertising databases sizes of up to 10 gigabytes, which is roughly 2.5 times the maximum database size allowed in Sql 2005 (4gb).

That's pretty cool.

Thank you Microsoft.

Thursday, April 15, 2010

Accessing Outgoing Message Queues with C#

The point of sale application I work on, Ontempo Store, most commonly uses a Microsoft Message Queue (MSMQ) based component for moving data between POS’, and POS’ and servers. We’ve also decided to use ‘recoverable’ messages within MSMQ to provide an added layer of robustness on top of our own data transfer layer.
This works great in normal circumstances, but sometimes situations crop up where a problem occurs. Sometimes a PC’s static IP changes for some reason (changes to the networking such as different VPN software or vendors, change in ISP, or the retailers IT department introduces a new numbering system for the IP addresses etc.). Sometimes the wrong IP address was configured initially (i.e the wrong address was entered into our configuration database before the POS PC was actually installed).Obviously if the machines are addressed by name (and the name itself hasn’t changed), and the network supports DNS this isn’t a problem, but often this isn’t the case. Most of our clients don’t have DNS supported on their store networks and so just use static IP addresses.
In these cases there are now messages ‘stuck’ in a queue for an address that doesn’t exist, and while we could resend the original data from our own system, it' would be much nicer to have the system detect the address has changed and automatically resend (or more correctly, move) the undelivered messages to the correct queue. This is a feature I’ve been working on for the next release. I managed to write all the code to detect the address changing, gather the new and old address values and notify the appropriate components in our own architecture. The only thing left to do was write the code inside the MSMQ transport component to move the messages from the old outgoing queue and into the new one. Putting the messages in the new queue is simple enough, just create the queue and send to it like any other… but getting the messages from the old outgoing queue so I could do this proved to be a bit more challenging.
Neither the Visual Studio help, nor anything I could find on the internet clearly showed me how to read messages from the local outgoing queues using C# and the .Net System.Messaging namespace objects. There was one CodeProject article that showed a very rough way of achieving this but required using the COM based library which I wanted to avoid.
Then I found this web page on Ingo Rammer’s blog which talked about purging local outgoing queues. He says that accessing the local outgoing queues is possible using the MSMQ Win32 API (and presumably COM library) but not when using the .Net System.Messaging objects. He then provides code for purging an outgoing queue using the Win32 API, and follows that code with this comment;
“(The secret here lies in MQ_ADMIN_ACCESS which tells MSMQ that you'd like to work with the "outgoing queue" for the specified remote queue.)”
Despite the fact his article claimed you couldn’t use .Net to access the outgoing queue I decided to try it anyway, by opening the queue with ‘admin’ access specified… and as soon as I did that, it worked fine. Here’s a sample of the line needed to open the queue;
string queueFormatName = "FORMATNAME:DIRECT=TCP:10.10.10.10\\PRIVATE$\\Queue Name";
MessageQueue sourceQueue = new MessageQueue(queueFormatName, QueueAccessMode.ReceiveAndAdmin);


(Note the 10.10.10.10 should be replaced with the relevant IP address, and Queue Name should be the actual name of your queue, but the rest of the format name should be as is).


The key is the second parameter (QueueAccessMode.ReceiveAndAdmin) which specifies the access type, which must include ‘admin’ access. Once I opened the queue this way I was able to peek and receive the messages from the outgoing queue without getting the ‘The format name is invalid’ error I got previously when I had just specified receive access (out of the good habit of only ever requesting the minimum amount of permission required). I’ve tried this on an outgoing queue for an address that doesn’t actually exist and it still works, so I’m definitely accessing the local outgoing queue and not the remote version… besides which, I can see the messages being removed from the old queue and put in the new one using MSMQ explorer when I refresh the queues messages lists.


I haven’t tried purging the outgoing queue like Ingo was trying, since it’s not a requirement for me, but I would assume it is possible if the queue is opened this way.


So thanks to Ingo for providing the information that lead me to a solution, and if you’re wanting to open an outgoing queue make sure you specify admin access when opening the queue.





UPDATE : 16/04/2010 – Note that you cannot read messages from the local outgoing queue if you do not have administrative rights (that is you are running under a Windows administrator account and if you are on Vista/Weven with UAC enabled the account has been elevated).








Sunday, January 03, 2010

“Dispose” Of Duplicated Code

As you know, when working with disposable objects you always need to dispose them when you’re finished. The using block is great for this, but not always appropriate - sometimes you have one or more disposable objects as fields in a class (or being passed among classes) and you can’t wrap them in a using block.

In these situations I often end up finding myself writing code like this;

IDisposable dispObj = value as IDisposable;
if (dispObj != null)
{
try
{
dispObj.Dispose();
}
catch
{
#if DEBUG
throw;
#endif
}
}



First, I attempt to cast the object to the IDisposable interface, but I use the as keyword to ensure no exception is thrown if the object doesn’t support the interface.



Why ? Because sometimes the item I (may) need to dispose is a custom component loaded from another assembly which I’m accessing via a common interface or base class. In this case I don’t know at design time whether or not it needs to be disposed… but I can tell at runtime by checking if it supports the IDisposable interface. Also, some classes that DO need to be disposed don’t expose Dispose as a public method on their default interface and must be cast to IDisposable to access the Dispose method (i.e they implement IDisposable explicitly, not implicitly).



Next, assuming the cast was successful I setup an error handler that catches all exceptions… bad practice I know, but I do it (most of the time) anyway because failing to dispose an object isn’t usually something that should crash my application… normally the GC will ensure the object is properly disposed later, the user certainly doesn’t care the dispose failed, besides usually there is no ill effect from ignoring an error here. Errors here are highly uncommon and I might have a bunch of other objects that need to be disposed and won’t be if we throw an exception that isn’t handled here.



You’ll note however that I don’t ignore the exception if the code is in debug mode… this alerts me to any possible issues while I’m developing/testing the code in Visual Studio.



Finally, I dispose the object.



Repeating this all over the place seemed like a bad idea, so I came up with the following two methods in order to re-use the code. I have them as static methods on a static class, but you could make them instance or extension methods;



/// <summary>
/// Attempts to dispose an object. Determines first if the object is disposable, and not null, and if so then disposes it.
/// </summary>
/// <remarks>Any errors that occur during dispose are swallowed by this method.</remarks>
/// <param name="value">The object to be disposed.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
public static void DisposeObject(object value)
{
    IDisposable dispObj = value as IDisposable;
    if (dispObj != null)
    {
        try
        {
            dispObj.Dispose();
        }
        catch
        {
            #if DEBUG
                throw;
            #endif
        }
    }
}


/// <summary>
/// Disposes all objects in the specified enumerable set, and disposes the set itself where the object(s) support <see cref="System.IDisposable"/>.
/// </summary>
/// <remarks>Any object not supporting <see cref="System.IDisposable"/> is ignored. If the enumerable set is null, then the function does nothing and returns. Any errors that occur during the dispose are swallowed.</remarks>
/// <param name="values">An enumerable set of objects to be disposed.</param>
public static void DisposeObjects(System.Collections.IEnumerable values)
{
    if (values != null)
    {
        foreach (object o in values)
        {
            DisposeObject(o);
        }
        DisposeObject(values);
    }
}