Archive for June 2010

How to determine the project type of an existing Visual Studio project?

Ok, so I have an existing C++ Visual Studio project (at my new position here as a Developer at LANDesk) and who knows who created it or when it was created.  Anyway, I wanted to start a new project and use the same project type.

So how do I find out the project type.

In Visual Studio, I opened the ProjectName.vcproj file and found this information near the top:

<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
	ProjectType="Visual C++"
	Version="9.00"
	Name="MSICheckForPatch"
	ProjectGUID="{0793FB88-8BED-4297-8615-9408EA2FBE74}"
	Keyword="AtlProj"
	TargetFrameworkVersion="196613"
	>
	<Platforms>
		<Platform
			Name="Win32"
		/>
	</Platforms>
	...

So I noticed the Keyword was AtlProj, so that clued me in.

Looks like it was as easy as opening a text file and looking.

If there is a better or easier way, please comment and let me know.

How to get the current running executable name as a string in C#?

Ok, there are multiple options.

Here is the code, you choose the option you want.

It is best to use Option 1 or Option 2. Read this blog at MSDN for a better understanding:
Assembly.CodeBase vs. Assembly.Location

using System;

namespace GetCurrentProcessName
{
    class Program
    {
        static void Main(string[] args)
        {
            // It is best to use Option 1 or Option 2.  Read this:
            // http://blogs.msdn.com/b/suzcook/archive/2003/06/26/assembly-codebase-vs-assembly-location.aspx

            // Option 1 - Using Location (Recommended)
            String fullExeNameAndPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
            String ExeName = System.IO.Path.GetFileName(fullExeNameAndPath);

            // Option 2 - Using CodeBase instead of location
            String fullExeNameAndPathUrl = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
            String codeBase = System.IO.Path.GetFileName(fullExeNameAndPathUrl);

            // Option 3 - Usable but during debugging in Visual Studio it retuns ExeName.vhost.exe
            String fullVhostNameAndPath = Environment.GetCommandLineArgs()[0];
            String vhostName = System.IO.Path.GetFileName(fullVhostNameAndPath);

            // Option 4 - Also usable but doesn't include the extension .exe and also returns ExeName.vhost
            // during debuggin in visual studio
            String prcessName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
        }
    }
}

Copyright ® Rhyous.com – Linking to this page is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.

How to limit or prevent characters in a TextBox in C#? Or How to create a NumberTextBox or DigitBox object?

Let say you want to have a TextBox in which you only want to allow integers (0-9) or maybe you only want to allow strings, A-Za-z.

Well, lets play around with this for a second and see what we can do.

To get started do this:

  1. Create a new WPF Application project.
  2. In the designer, add a TextBox from the Toolbox.
  3. In the properties field for the TextBox click the icon that look like a lightening bolt to bring up events.
  4. Find the KeyDown event and double-click on it.

Ok, so you should now have the following function:

        private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
        }

The key that was pressed is accessible from the KeyEventArgs variable, e. Specifically e.Key.

Key just happens to be an enum, which means they can basically be treated as integers.

The key press can be ignored by telling setting e.Handled=true. This way it is already marked as handled and will not be added to the TextBox.

Allow only number keys 0-9 in a TextBox

Here is a simple function to allow only natural numbers or number keys 0-9 in a TextBox. Be aware that the keys may be different in other languages.

        private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key < Key.D0 || e.Key > Key.D9)
            {
                e.Handled = true;
            }
        }

Wow, that was pretty simple, right?  WRONG! It is not that easy.

You realize that there are two sets of numbers on a keyboard right? You have numbers in row above your QWERTY keys and you likely have a Number pad on the right of your keyboard as well.  That is not all either.

What else did we forget, you might ask?  Well, of the seven requirements we need to handle, we only handled one.  For an application to be considered release quality or enterprise ready or stable, all seven of these should be handled.

  1. Numbers 1234567890 above QWERTY keys.
  2. Numpad numbers.
  3. You may want to allow pressing of the Delete, Backspace, and Tab keys.
  4. What about pasting?
  5. What about drag and drop?
  6. What about someone else calling your code and changing the text?
  7. Mnemonics should work.

Requirements

Here are the six requirements in clear statements.

  1. Allow pressing Numbers 1234567890 above QWERTY keys.
  2. Allow pressing Numpad numbers.
  3. Allow pressing of the Delete, Backspace, and Tab keys.
  4. Allow pasting so that only numbers in a string are added: A1B2C3 becomes 123.
  5. Allow drag and drop so that only numbers in a string are added: A1B2C3 becomes 123.
  6. Allow change in code at runtime so that only numbers in a string are added: A1B2C3 becomes 123.
  7. When another control has a mnemonic, such as Alt + S, pressing Alt + S, should property change the focus and place the cursor in the Alt + S control.

Remembering lists like this is something that comes with experience.  If you thought of these on your own, good work.  If you didn’t think of them on your own, don’t worry, experience comes with time.

So lets enhance this to handle each of these.

Handling both Number keys and Numpad keys

        private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
                e.Handled = !IsNumberKey(e.Key);
        }

        private bool IsNumberKey(Key inKey)
        {
            if (inKey < Key.D0 || inKey > Key.D9)
            {
                if (inKey < Key.NumPad0 || inKey > Key.NumPad9)
                {
                    return false;
                }
            }
            return true;
        }

All right, we now have two of the six requirements down.

Handling Delete, Backspace, and Tab, and Mnemonics

You can probably already guess how easy it will be to do something similar to handle these two keys.

        protected void OnKeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = !IsNumberKey(e.Key) && !IsActionKey(e.Key);
        }

        private bool IsNumberKey(Key inKey)
        {
            if (inKey < Key.D0 || inKey > Key.D9)
            {
                if (inKey < Key.NumPad0 || inKey > Key.NumPad9)
                {
                    return false;
                }
            }
            return true;
        }

        private bool IsActionKey(Key inKey)
        {
            return inKey == Key.Delete || inKey == Key.Back || inKey == Key.Tab || inKey == Key.Return || Keyboard.Modifiers.HasFlag(ModifierKeys.Alt);
        }

Ok, now we have four of six requirements handled.

Handling Paste (Ctrl + V) and Drag and Drop

Yes, I can handle both at the same time with a new event TextChanged.

This is setup so that if someone pastes both letters and number, only the numbers are pasted: A1B2C3 becomes 123.

This event is not configured so we have to set it up.

  1. In the designer, click the TextBox.
  2. In the properties field for the TextBox click the icon that look like a lightening bolt to bring up events.
  3. Find the TextChanged event and double-click on it.

You should now have this stub code for the event function.


        private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
        {
        }

Here is some easy code to make sure each character is actually a digit.

        protected void OnTextChanged(object sender, TextChangedEventArgs e)
        {
            base.Text = LeaveOnlyNumbers(Text);
        }

        private string LeaveOnlyNumbers(String inString)
        {
            String tmp = inString;
            foreach (char c in inString.ToCharArray())
            {
                if (!IsDigit(c))
                {
                    tmp = tmp.Replace(c.ToString(), "");
                }
            }
            return tmp;
        }

        public bool IsDigit(char c)
        {
            return (c >= '0' && c <= '9');
        }

Guess what else? This last function actual handles the first five requirements all by itself. But it is less efficient so we will leave the previous requirements as they are.

Handling Direct Code Change

Ok, so some somehow your TextBox is passed inside code during runtime a string that contains more than just numbers.  How are you going to handle it.

This is setup so that if someone pastes both letters and number, only the numbers are pasted: A1B2C3 becomes 123.  Well, we need to run the same function as for Drag and Drop, so to not duplicate code, it is time to create a class or object.

Creating a NumberTextBox object

Now we need to make our code reusable. Lets create a class called NumberTextBox and it can do everything automagically.

NumberTextBox

using System;
using System.Windows.Controls;
using System.Windows.Input;

namespace System.Windows.Controls
{
    public class DigitBox : TextBox
    {
        #region Constructors
        /// <summary> 
        /// The default constructor
        /// </summary>
        public DigitBox()
        {
            TextChanged += new TextChangedEventHandler(OnTextChanged);
            KeyDown += new KeyEventHandler(OnKeyDown);
        }
        #endregion

        #region Properties
        new public String Text
        {
            get { return base.Text; }
            set
            {
                base.Text = LeaveOnlyNumbers(value);
            }
        }

        #endregion

        #region Functions
        private bool IsNumberKey(Key inKey)
        {
            if (inKey < Key.D0 || inKey > Key.D9)
            {
                if (inKey < Key.NumPad0 || inKey > Key.NumPad9)
                {
                    return false;
                }
            }
            return true;
        }

        private bool IsActionKey(Key inKey)
        {
            return inKey == Key.Delete || inKey == Key.Back || inKey == Key.Tab || inKey == Key.Return || Keyboard.Modifiers.HasFlag(ModifierKeys.Alt);
        }

        private string LeaveOnlyNumbers(String inString)
        {
            String tmp = inString;
            foreach (char c in inString.ToCharArray())
            {
                if (!IsDigit(c))
                {
                    tmp = tmp.Replace(c.ToString(), "");
                }
            }
            return tmp;
        }

        public bool IsDigit(char c)
        {
            return (c >= '0' && c <= '9');
        }
        #endregion

        #region Event Functions
        protected void OnKeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = !IsNumberKey(e.Key) && !IsActionKey(e.Key);
        }

        protected void OnTextChanged(object sender, TextChangedEventArgs e)
        {
            base.Text = LeaveOnlyNumbers(Text);
        }
        #endregion
    }
}

Now I can delete the events and functions from the Window1.xaml.cs file. I don’t have to add any code to the Window1.xaml.cs. Instead I need to reference my local namespace in the Window1.xaml and then change the TextBox to a local:NumberTextBox. Here is the XAML.

<Window x:Class="TextBoxIntsOnly.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TextBoxIntsOnly"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <local:DigitBox Margin="87,27,71,0" VerticalAlignment="Top" x:Name="textBox1" />
        <Label Height="28" HorizontalAlignment="Left" Margin="9,25,0,0" Name="label1" VerticalAlignment="Top" Width="72">Integers:</Label>
        <TextBox Height="23" Margin="87,56,71,0" Name="textBox2" VerticalAlignment="Top" />
        <Label Height="28" HorizontalAlignment="Left" Margin="9,54,0,0" Name="label2" VerticalAlignment="Top" Width="72">Alphabet:</Label>
    </Grid>
</Window>

And now all seven requirements are met.

7 Free Open Source Manuals…

7 Free, Open Source Tomes For Your Edification

Quote:

While the actual manuals and documentation you get with many open source applications and platforms can be underwhelming, the good news is that there are a lot of free, online books on open source topics available. We round these up on a regular basis here at OStatic, and in this post you’ll find seven online books that you can get comfortable with quickly. They introduce essential concepts for getting started with Linux, Firefox, Blender (3D graphics and animation), GIMP (graphics), the OpenOffice suite of productivity applications, and more.

EndQuote

Common Regular Expression Patterns for C#

The following are code snippets for common regular expressions in C#.

If you have a regular expression that you think is common or a correction/improvement to one of mine, please submit it.

IP address pattern or expression

The expression:

^[0-9]{1,3}\.){3}[0-9]{1,3}$

In CSharp code:

String theIpAddressPattern = @"^[0-9]{1,3}\.){3}[0-9]{1,3}$";

Domain name pattern or expression

The expression:

^[\-\w]+\.)+[a-zA-Z]{2,4}$

In CSharp code:

String theDoainNamePattern = @"^[\-\w]+\.)+[a-zA-Z]{2,4}$";

Email address pattern or expression

The expression:

^[\w!#$%&'*+\-/=?\^_`{|}~]+(\.[\w!#$%&'*+\-/=?\^_`{|}~]+)*@((([\-\w]+\.)+[a-zA-Z]{2,4}$)|(([0-9]{1,3}\.){3}[0-9]{1,3}))

In CSharp code:

String theEmailPattern = @"^[\w!#$%&'*+\-/=?\^_`{|}~]+(\.[\w!#$%&'*+\-/=?\^_`{|}~]+)*"
                                   + "@"
                                   + @"((([\-\w]+\.)+[a-zA-Z]{2,4})|(([0-9]{1,3}\.){3}[0-9]{1,3}))$";

a

The URL Pattern

The expression:

((^http(s)*://(([\-\w]+\.)+[a-zA-Z]{2,4}.*)))$|(^ftp://([\w](:[\w]))*(([\-\w]+\.)+[a-zA-Z]{2,4}[/\w]*))$

In CSharp code:

            String theURLPattern = @"((^http(s)*://(([\-\w]+\.)+[a-zA-Z]{2,4}.*)))$"
                                 + @"|(^ftp://([\w](:[\w]))*(([\-\w]+\.)+[a-zA-Z]{2,4}[/\w]*))$";

Regular Expressions in C# (including a new comprehensive email pattern)

Of course C# supports regular expressions. I happen to have learned regular expressions in my dealings with FreeBSD, shell scripting, php, and other open source work. So naturally I would want to add this as a skill as I develop in C#.

What is a Regular Expression?

This is a method in code or script to describe the format or pattern of a string. For example, look at an email address:

someuser@somedomain.tld

It is important to understand that we are not trying to compare the email string against another string, we are trying to compare the string against a pattern.

To verify the email was in the correct format using String functions, it would take dozens of different functions running one after another.  However, with a regular expression, a proper email address can be verified in one single function.

So instead regular expression is a language, almost like a scripting language in itself, for defining character patterns.

Most characters represent themselves.  However, some characters don’t represent themselves without escaping them with a backslash because they represent something else.  Here is a table of those characters.

Expression Meaning
* Any number of the previous character or character group.
+ One of more of the previous character or character group.
^ Beginning of line or string.
$ End of line or string.
? Pretty much any single character.
. Pretty much any character, zero characters, one character, or any number of characters
[ … ] This forms a character class expression
( … ) This forms a group of items

You should look up more regular expression rules. I don’t explain them all here. This is just to give you an idea.

Example 1 – Parameter=Value

Here is a quick example of a regular expression that matches String=String. At first you might think this is easy and you can use this expression:

.*=.*

While that might work, it is very open. And it allows for zero characters before and after the equals, which should not be allowed.

This next pattern is at least correct but still very open.

.+=.+

What if the first value is limited to only alphanumeric characters?

[a-zA-z0-9]=.+

What if the second value has to be a valid windows file path or URL? And we will make sure we cover start to finish as well.

^[0-9a-zA-Z]+=[^<>|?*\”]+$

See how the more restrictions you put in place, the more complex the expression gets?

Example 2 – The email address

The pattern of an email is as follows: (Reference: wikipedia)

See updates here: C# – Email Regular Expression

  1. It will always have a single @ sign
  2. 1 to 64 characters before the @ sign called the local-part. Can contain characters a–z, A–Z, 0-9, ! # $ % & ‘ * + – / = ? ^ _ ` { | } ~, and . if it is not at the first or end of the local-part.
  3. Some characters after the @ sign that have a pattern as follows called the domain.
    1. It will always have a period “.”.
    2. One or more character before the period.
    3. Two to four characters after the period.

So a simple patterns of an email address should be something like these:

  1. This one just makes sure there are characters before and after the @
    .+@.+
  2. This one makes sure the are characters before and after the @ as well as a character before and after the . in the domain.
    .+@.*+\..+
  3. This one makes sure that there is only one @ symbol.
    [^@]+@[^@]+\.

This are all quick an easy examples and will not work in every instance but are usually accurate enough for casual programs.

But a comprehensive example is much more complex.

  1. I wrote one myself that is the shortest and gets the best results of any I have found:
    ^[\w!#$%&'*+\-/=?\^_`{|}~]+(\.[\w!#$%&'*+\-/=?\^_`{|}~]+)*@((([\-\w]+\.)+[a-zA-Z]{2,4})|(([0-9]{1,3}\.){3}[0-9]{1,3}))$
    
    
  2. Here is another complex one I found: [reference]
    ^(([^<>()[\]\\.,;:\s@\""]+(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$
    

So let me explain the first one that I wrote as it passes my unit tests below:

The start
[\w!#$%&’*+\-/=?\^_`{|}~]+ At least one valid local-part character not including a period.
(\.[\w!#$%&’*+\-/=?\^_`{|}~]+)* Any number (including zero) of a group that starts with a single period and has at least one valid local-part character after the period.
@ The @ character
( Start group 1
( Start group 2
([\-\w]+\.)+ At least one group of at least one valid word character or hyphen followed by a period
[\w]{2,4} Any two to four valid top level domain characters.
) End group 2
| an OR statement
( Start group 3
([0-9]{1,3}\.){3}[0-9]{1,3} A regular expression for an IP Address.
) End group 3
) End group 1

Code for both examples

Here is code for both examples. My email regular expression is enabled and the one I found on line is commented out. To see how they work differently, just comment out mine, and uncomment the one I found online.

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace RegularExpressionsTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // Example 1 - Parameter=value
            // Match any character before and after the =
            // String thePattern = @"^.+=.+$";

            // Match only Upper and Lowercase letters and numbers before
            // the = as a parameter name and after the equal match the
            // any character that is allowed in a file's full path
            //
            // ^[0-9a-zA-Z]+    This is any number characters upper or lower
            //                  case or 0 thru 9 at the string's beginning.
            //
            // =                Matches the = character exactly
            //
            // [^<>|?*\"]+$     This is any character except < > | ? * "
            //                  as they are not valid in a file path or URL

            String theNameEqualsValue = @"abcd=http://";

            String theParameterEqualsValuePattern = "^[0-9a-zA-Z]+=[^<>|?*\"]+$";
            bool isParameterEqualsValueMatch = Regex.IsMatch(theNameEqualsValue, theParameterEqualsValuePattern);
            Log(isParameterEqualsValueMatch);

            // Example 2 - Email address formats

            String theEmailPattern = @"^[\w!#$%&'*+\-/=?\^_`{|}~]+(\.[\w!#$%&'*+\-/=?\^_`{|}~]+)*"
                                   + "@"
                                   + @"((([\-\w]+\.)+[a-zA-Z]{2,4})|(([0-9]{1,3}\.){3}[0-9]{1,3}))$";

            // The string pattern from here doesn't not work in all instances.
            // http://www.cambiaresearch.com/c4/bf974b23-484b-41c3-b331-0bd8121d5177/Parsing-Email-Addresses-with-Regular-Expressions.aspx
            //String theEmailPattern = @"^(([^<>()[\]\\.,;:\s@\""]+(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))"
            //                       + "@"
            //                       + @"((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])"
            //                       + "|"
            //                       + @"(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$";

            Console.WriteLine("Bad emails");
            foreach (String email in GetBadEmails())
            {
                Log(Regex.IsMatch(email, theEmailPattern));
            }

            Console.WriteLine("Good emails");
            foreach (String email in GetGoodEmails())
            {
                Log(Regex.IsMatch(email, theEmailPattern));
            }
        }

        private static void Log(bool inValue)
        {
            if (inValue)
            {
                Console.WriteLine("It matches the pattern");
            }
            else
            {
                Console.WriteLine("It doesn't match the pattern");
            }
        }

        private static List GetBadEmails()
        {
            List emails = new List();
            emails.Add("joe"); // should fail
            emails.Add("joe@home"); // should fail
            emails.Add("a@b.c"); // should fail because .c is only one character but must be 2-4 characters
            emails.Add("joe-bob[at]home.com"); // should fail because [at] is not valid
            emails.Add("joe@his.home.place"); // should fail because place is 5 characters but must be 2-4 characters
            emails.Add("joe.@bob.com"); // should fail because there is a dot at the end of the local-part
            emails.Add(".joe@bob.com"); // should fail because there is a dot at the beginning of the local-part
            emails.Add("john..doe@bob.com"); // should fail because there are two dots in the local-part
            emails.Add("john.doe@bob..com"); // should fail because there are two dots in the domain
            emails.Add("joe<>bob@bob.come"); // should fail because <> are not valid
            emails.Add("joe@his.home.com."); // should fail because it can't end with a period
            emails.Add("a@10.1.100.1a");  // Should fail because of the extra character
            return emails;
        }

        private static List GetGoodEmails()
        {
            List emails = new List();
            emails.Add("joe@home.org");
            emails.Add("joe@joebob.name");
            emails.Add("joe&bob@bob.com");
            emails.Add("~joe@bob.com");
            emails.Add("joe$@bob.com");
            emails.Add("joe+bob@bob.com");
            emails.Add("o'reilly@there.com");
            emails.Add("joe@home.com");
            emails.Add("joe.bob@home.com");
            emails.Add("joe@his.home.com");
            emails.Add("a@abc.org");
            emails.Add("a@192.168.0.1");
            emails.Add("a@10.1.100.1");
            return emails;
        }
    }
}

Detecting when you press "Enter" in a WPF TextBox

Hey all,

You have a TextBox and you want to detect when someone presses “Enter” and do something different than if they type text.

This one is simple, but you need to be careful when closing a window in multiple places.

The Event you want to use is KeyDown.

Imagine you have a TextBox called TextBoxCompanyName where you are asking the company name.  It is common to enter the name and press Enter and have “Enter” act just like the OK button.

You already have an OK button and it is setup to close the window or do other stuff first.


        private void ButtonOK_Click(object sender, RoutedEventArgs e)
        {
            // May do other stuff.
            this.Close();
        }

        private void TextBoxCompanyName_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                ButtonOK_Click(this, new RoutedEventArgs());
            }
        }

Notice I don’t just call this.Close() again in the new TextBoxCompanyName_KeyDown event; but instead I call the ButtonOK_Click function to simulate the OK button being clicked. This way:

  • I don’t have duplicate code
  • I prevent a potential bug where if I had simply called this.Close() again, then someone in the future might add code to ButtonOK_Click and they might not know that TextBoxCompanyName_KeyDown will close the window a different way, leaving you in a weird state where the button does something that pressing “Enter” doesn’t do.

You now know how to do something different when you press “Enter”. I hope that was easy for you.


Copyright ® Rhyous.com – Linking to this page is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.

C# – Email Regular Expression

I wrote a regex for email that is gets the best results of any I have found online. Along with getting better results, it is shorter too.

Download the C# project with unit tests here: EmailRegEx on GitHub
The pattern of an email is described as follows:

  1. It will always have a single @ sign
  2. 1 to 64 characters before the @ sign called the local-part. Can contain characters a–z, A–Z, 0-9, ! # $ % & ‘ * + – / = ? ^ _ ` { | } ~, and . if it is not at the first or end of the local-part.
  3. Some characters after the @ sign that have a pattern as follows called the domain.
    1. It will always have a period “.”.
    2. One or more character before the period.
    3. Two to four characters after the period.

So a simple patterns of an email address should be something like these:

  1. This one just makes sure there are characters before and after the @
    .+@.+
  2. This one makes sure the are characters before and after the @ as well as a character before and after the . in the domain.
    .+@.*+\..+
  3. This one makes sure that there is only one @ symbol.
    [^@]+@[^@]+\.

These are all quick an easy examples and will not work in every instance but are usually accurate enough for casual programs.

But a comprehensive example is much more complex.

  1. I wrote one myself that is the shortest and gets the best results of any I have found:
    ^[\w!#$%&'*+\-/=?\^_`{|}~]+(\.[\w!#$%&'*+\-/=?\^_`{|}~]+)*@((([\-\w]+\.)+[a-zA-Z]{2,4})|(([0-9]{1,3}\.){3}[0-9]{1,3}))\z
    
  2. Here is another complex one I found: [reference]
    ^(([^<>()[\]\\.,;:\s@\""]+(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$
    

So let me explain the first one that I wrote as it passes my unit tests below:

The start
[\w!#$%&’*+\-/=?\^_`{|}~]+ At least one valid local-part character not including a period.
(\.[\w!#$%&’*+\-/=?\^_`{|}~]+)* Any number (including zero) of a group that starts with a single period and has at least one valid local-part character after the period.
@ The @ character
( Start group 1
( Start group 2
([\-\w]+\.)+ At least one group of at least one valid word character or hyphen followed by a period. The attached project has a more complex hostname regex option too.
[\w]{2,4} Any two to four valid top level domain characters.
) End group 2
| an OR statement
( Start group 3
([0-9]{1,3}\.){3}[0-9]{1,3} A regular expression for an IP Address. The attached project has a more complex IP regex example too.
) End group 3
) End group 1
\z No end of line: \r or \n.

Code for the Email Regular Expression

Here is code for both examples. My email regular expression is enabled and the one I found on line is commented out. To see how they work differently, just comment out mine, and uncomment the one I found online.

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace RegularExpressionsTest
{
    class Program
    {
        static void Main(string[] args)
        {
            String theEmailPattern = @"^[\w!#$%&'*+\-/=?\^_`{|}~]+(\.[\w!#$%&'*+\-/=?\^_`{|}~]+)*"
                                   + "@"
                                   + @"((([\-\w]+\.)+[a-zA-Z]{2,4})|(([0-9]{1,3}\.){3}[0-9]{1,3}))\z";

            // The string pattern from here doesn't not work in all instances.
            // http://www.cambiaresearch.com/c4/bf974b23-484b-41c3-b331-0bd8121d5177/Parsing-Email-Addresses-with-Regular-Expressions.aspx
            //String theEmailPattern = @"^(([^<>()[\]\\.,;:\s@\""]+(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))"
            //                       + "@"
            //                       + @"((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])"
            //                       + "|"
            //                       + @"(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$";

            Console.WriteLine("Bad emails");
            foreach (String email in GetBadEmails())
            {
                Log(Regex.IsMatch(email, theEmailPattern));
            }

            Console.WriteLine("Good emails");
            foreach (String email in GetGoodEmails())
            {
                Log(Regex.IsMatch(email, theEmailPattern));
            }
        }

        private static void Log(bool inValue)
        {
            if (inValue)
            {
                Console.WriteLine("It matches the pattern");
            }
            else
            {
                Console.WriteLine("It doesn't match the pattern");
            }
        }

        private static List<String> GetBadEmails()
        {
            List<String> emails = new List<String>();
            emails.Add("joe"); // should fail
            emails.Add("joe@home"); // should fail
            emails.Add("a@b.c"); // should fail because .c is only one character but must be 2-4 characters
            emails.Add("joe-bob[at]home.com"); // should fail because [at] is not valid
            emails.Add("joe@his.home.place"); // should fail because place is 5 characters but must be 2-4 characters
            emails.Add("joe.@bob.com"); // should fail because there is a dot at the end of the local-part
            emails.Add(".joe@bob.com"); // should fail because there is a dot at the beginning of the local-part
            emails.Add("john..doe@bob.com"); // should fail because there are two dots in the local-part
            emails.Add("john.doe@bob..com"); // should fail because there are two dots in the domain
            emails.Add("joe<>bob@bob.com"); // should fail because <> are not valid
            emails.Add("joe@his.home.com."); // should fail because it can't end with a period
            emails.Add("john.doe@bob-.com"); // should fail because there is a dash at the start of a domain part
            emails.Add("john.doe@-bob.com"); // should fail because there is a dash at the end of a domain part
            emails.Add("a@10.1.100.1a");  // Should fail because of the extra character
            emails.Add("joe<>bob@bob.com\n"); // should fail because it end with \n
            emails.Add("joe<>bob@bob.com\r"); // should fail because it ends with \r
            return emails;
        }

        private static List<String> GetGoodEmails()
        {
            List<String> emails = new List<String>();
            emails.Add("joe@home.org");
            emails.Add("joe@joebob.name");
            emails.Add("joe&bob@bob.com");
            emails.Add("~joe@bob.com");
            emails.Add("joe$@bob.com");
            emails.Add("joe+bob@bob.com");
            emails.Add("o'reilly@there.com");
            emails.Add("joe@home.com");
            emails.Add("joe.bob@home.com");
            emails.Add("joe@his.home.com");
            emails.Add("a@abc.org");
            emails.Add("a@abc-xyz.org");
            emails.Add("a@192.168.0.1");
            emails.Add("a@10.1.100.1");
            return emails;
        }
    }
}

Well, now you have the best C# Email Regular Expression out there.

Update: My attached project has an even better and more accurate one now too.

(Reference: wikipedia)

How to create a directory on an FTP server using C#?

Ok, so I already can upload a file to an FTP server: How to upload a file to an FTP server using C#?

However, now I need to create a directory first.

It follows some basic steps:

  1. Open a request using the full destination ftp path: Ftp://Ftp.Server.tld/ or Ftp://Ftp.Server.tld/Some/Path
  2. Configure the connection request
  3. Call GetResponse() method to actually attempt to create the directory
  4. Verify that it worked.

See the steps inside the source as comments:

using System;
using System.IO;
using System.Net;

namespace CreateDirectoryOnFtpServer
{
    class Program
    {
        static void Main(string[] args)
        {
            CreateDirectoryOnFTP("ftp://ftp.server.tld", /*user*/"User1", /*pw*/"Passwd!", "NewDirectory");

        }

        static void CreateDirectoryOnFTP(String inFTPServerAndPath, String inUsername, String inPassword, String inNewDirectory)
        {
            // Step 1 - Open a request using the full URI, ftp://ftp.server.tld/path/file.ext
            FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(inFTPServerAndPath + "/" + inNewDirectory);

            // Step 2 - Configure the connection request
            request.Credentials = new NetworkCredential(inUsername, inPassword);
            request.UsePassive = true;
            request.UseBinary = true;
            request.KeepAlive = false;

            request.Method = WebRequestMethods.Ftp.MakeDirectory;

            // Step 3 - Call GetResponse() method to actually attempt to create the directory
            FtpWebResponse makeDirectoryResponse = (FtpWebResponse)request.GetResponse();
        }
    }
}

All right, now you have created a directory on the FTP server.


Copyright ® Rhyous.com – Linking to this page is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.

Detecting if the install is occuring on a 64 bit or 32 bit machine

Ok, so NSIS has most the 64 bit functionality available for their installers.

I need to write a registry key to the 64 bit registry on 64 bit machines.

I may need to install to Program Files or Program Files (x86).

If on 64 bit workstation you need to install to Program Files (x86) that is done by default because the $PROGRAMFILES constant goes to the Program Files (x86) directory.

So a simple solution that should be obvious is to check for something that is on a 64 bit machine that is not on a 32 bit machine.  Lets make a list of such differences.

Files

  1. c:\Program Files (x86) – Since this is just a folder, it could exist on a 32 bit machine, though that would be unlikely.
  2. c:\windows\SysWow64

Registry key

  1. HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node – This is a 64 bit registry and does not exist in 32 bit operating systems.

So some of these are susceptible to be “faked”.  I could see some idiot writing an installer on Windows 7 and hard coding the Program Files (x86) directory so it is installed there even on 32 bit systems.  The SysWow64 directory seems more safe and it exists on Vista, Windows 7, and 2008.  I don’t have XP or 2003 64 bit machines so someone can check for me. It seems that the registry key is also likely to be a safe check.

You can check any of these you want. 

Here is how you would change which registry to work with.

	IfFileExists $WINDIR\SYSWOW64\*.* Is64bit Is32bit
	Is32bit:
		SetRegView 32
		GOTO End32Bitvs64BitCheck

	Is64bit:
		SetRegView 64

	End32Bitvs64BitCheck:

That fixes the registry keys. So if you only care about the registry you are fine. However, you software will still install to the Program Files (x86) directory. To fix both, you could place the following code in BOTH the .onInit and the un.onInit functions.

	; Install to the correct directory on 32 bit or 64 bit machines
	IfFileExists $WINDIR\SYSWOW64\*.* Is64bit Is32bit
	Is32bit:
		MessageBox MB_OK "32 bit"
		SetRegView 32
		StrCpy $INSTDIR "$PROGRAMFILES32\LANDesk\Health Check"
		GOTO End32Bitvs64BitCheck

	Is64bit:
		MessageBox MB_OK "64 bit"
		SetRegView 64
		StrCpy $INSTDIR "$PROGRAMFILES64\LANDesk\Health Check"

	End32Bitvs64BitCheck:

Don’t forget to comment out the usual place that INSTDIR is configured.

Anyway, that seems to work.


Copyright ® Rhyous.com – Linking to this page is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.

Google voice: Is it a good way to send a text message from a computer?

I just sent a text using Google voice to tell someone not to pick me up at 6:45 am.  Usually online texting tools never work for me.  Somehow,  I think Google Voice is different.

Anyway, if my friend/co-worker knocks at my door at 6:45 am, then I will complain and update this post with a big negative.  If it works, it will get a big positive.

Yes, Google Voice worked!

I tried a half a dozen online message tool and this one was the only one that got the IM through.

Notepad++ and the XML Tools plugin

Ok, so I do a lot with Xml files.  Between working with my company’s product LDMS and all the Xmls it uses, to my own code using Serialization, I seem to always have an Xml file open.

I hate it when I open and Xml File and it is all on one line.  Or every element is a separate line but not a single line is indented.

Visual Studio can fix these for me rather easily.  But I have a lot of different machines in my lab and often work in other’s labs, or on customer’s computers while remote controlling them for support reasons. I can’t just quickly download an install Visual Studio. While yes, there is a free Express Edition version, it is just an overkill for the simple job of making an Xml file look pretty in text.  I need a small simple, quick to download and install tool.

The solution was right in front of me the whole time: Notepad++ and the XML Tools plugin

I always use Notepad++ as my random text editor on windows.  I already use its Compare plugin constantly, so I am very familiar with it.  It finally donned on me to check if it had an plugin that could help me with Xmls and sure enough, it did.

The XML Tools plugin, has almost all the features I wanted.

Notepad++ is just over 3 megabytes and download rather quickly.  The XML Tools plugin is not installed by default but can quickly be installed using the Plugin Manager.  Don’t worry about the additional download, the XML Tools plugin is only just over 300 kilobytes.

So I can now prettify my Xml files with a small, quick to download and install, windows tool.

Here is the menu this plugin provides, so you can see a list of some of the features.

So the Pretty pring (XML only – with line breaks) will take an Xml that is all on one single line, and expand it to have line breaks and also give it the proper indents.

There is also a tool to make sure the Syntax is correct.

The only feature I want that it doesn’t have is a tool to sort child elements and attributes.


Copyright ® Rhyous.com – Linking to this page is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.

Options for serializing an Array or List when using Serializable?

Lets say you have to implement Xml Serialization on your objects. Many of your exiting Xml files have Lists. However, what if you are working with existing Xml files and you don’t get to reformat them? So you have to make the List in your object react the way it already looks in possible poorly designed Xml Files.

Ok, so off the top of my head, I can think of many ways that a List of objects could be displayed in XML (and there are probably more). For simplicity’s sake, I am going to use String objects for this, but this goes along with any object.

So how does Xml Serialization hold up when confronted with existing Xml files and existing lists?

Well, lets first show you some example Lists in Xml and then lets see what types are supported.

Type 1 – Grouped Lists

Status: Supported – This is the default way Xml Serialization stores lists in Xml files.
Xml Design: Excellent.

The object elements are contained in a parent element. As shown, each String element is inside the Strings (notice it is plural) element.

<RootElement>
  <Strings>
    <String>Some string 0.</String>
    <String>Some string 1.</String>
    <String>Some string 2.</String>
    <String>Some string 3.</String>
    <String>Some string 4.</String>
  </Strings>
</RootElement>

Type 2 – Grouped Lists numbered

Status: Unknown – I haven’t found a way to do this yet, but I am not ready to say it can’t be done.  If it can’t be done, I think it “should be” supported.
Xml Design: Average. I am not sure if you can serialize this. Someone designing an Xml without serialization in mind would not think this design is wrong.

Same as above only each element is numbered incrementally from 0. (Or it could start at 1, right?)

<RootElement>
  <Strings>
    <String0>Some string 0.</String0>
    <String1>Some string 1.</String1>
    <String2>Some string 2.</String2>
    <String3>Some string 3.</String3>
    <String4>Some string 4.</String4>
  </Strings>
</RootElement>

Type 3 – Flat List

Status: Supported – If you add [XmlElement] above the property, then this is the format you get.
Xml Design: Excellent. This is a standard supported format.

There is just a list, with no parent attribute containing the list items.

<RootElement>
    <String>Some string 0.</String>
    <String>Some string 1.</String>
    <String>Some string 2.</String>
    <String>Some string 3.</String>
    <String>Some string 4.</String>
</RootElement>

Type 4 – Flat List numbered

Status: Unknown – I haven’t found a way to do this yet, but I am not ready to say it can’t be done. If it can’t be done, I think it “should be” supported.
Xml Design: Average. I am not sure if you can serialize this. Someone designing an Xml without serialization in mind would not think this design is wrong.

Same as the Flat list above only each element is numbered incrementally from 0. (Or it could start at 1, right?)

<RootElement>
    <String0>Some string 0.</String0>
    <String1>Some string 1.</String1>
    <String2>Some string 2.</String2>
    <String3>Some string 3.</String3>
    <String4>Some string 4.</String4>
</RootElement>

Type 5 – Attribute Lists

Status: Broken but working – If you put [XmlAttribute] before and Array or List, beware. It seems it uses space as the delimiter. I can’t seem to find a way to change the delimiter.
Xml Design: Poor. You can serialize this, but it deserialize the same way as it serializes.

A single attribute that contains a list. Obviously the object can’t be complex to match this type.  String works, but a complex object has to be an element not an attribute.

I can already see that this method would be tough to use. Right away I am wondering seeing the problem of using white space as a delimiter. However, quotes are important too. Xml Serialization automatically replaces quotes with the following string:

"

I would have thought since it uses a space as a delimiter that it would have replaced white space with some similar character entity string, but it did not.

<RootElement Strings="Some string 0. Some string 1. Some string 2. Some string 3. Some string 4.">
</RootElement>

Type 6 – Attribute Lists numbered

Status: Unknown – This is what I expected when I used the [XmlAttribute] tag but instead I got Type 5.  I have seen this in Xml files, so supporting it would be nice.
Xml Design: Average.  If a List exists that is always expected to have only one to five elements, I see nothing wrong with this design.

A separate, numbered attribute for each element in the list.

<RootElement String0=Some string 0." String1="Some string 1." String2="Some string 2." String3="Some string 3." String4="Some string 4."
</RootElement>

Type 7 – Delimited text in an element

Status: No supported – This just is not how it is designed to work, nor should it every work this way.
Xml Design: Poor – This defeats the whole purpose of an Xml.

This assumes that the list is inside a single element and has some kind of delimiter. Below the delimiter is a new line character. (Let’s assume that we expect white space at the front and end of the string to be trimmed and blank lines to be ignored.)

<RootElement>
  <Strings>
    Some string 0.
    Some string 1.
    Some string 2.
    Some string 3.
    Some string 4.
  <Strings>
</RootElement>

Conclusion

Type 1 and Type 2 are the ideal methods and work perfectly for me.

Types 2, 4, 6 should be supported if they aren’t already.  Maybe there is a way to do these that I don’t know about.

Type 5 seems to work but doesn’t and it is really disappointing that the [XmlAttribute] tag works this way instead of like Type 6.

Type 7 is bad and you pretty much are left to fixing this with manual code and not using Xml Serialization.


Copyright ® Rhyous.com – Linking to this page is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.

How to create a custom class template for Xml Serializable classes?

Ok, so you don’t always want a default class template for every type of class.  I have to create a bunch of classes that implement Serializable and if the class template assumed this, that would be great.  However, I don’t want my default class template to assume this.

So here is what I did broken down into four simple steps.

  1. Open or create a c# project.
  2. Create a class file.
  3. Add the text and the variables to replaced.
  4. Export the item as a template.

Step 1 – Open or create a c# project.

Ok, so any project will do.  I used an existing project, but you can create a new one if you want.  Any C# project should allow this to happen.

Step 2 – Create a class file.

In one of my C# projects in Visual Studio, I created a new class called XmlClass.cs.

Step 3 – Add the text and the variables to replaced

I put the following text into my new class:

using System;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace $rootnamespace$
{
	[Serializable]
	public class $safeitemrootname$
	{
		#region Member Variables
		#endregion

		#region Constructors

		/*
		 * The default constructor
 		 */
		public $safeitemrootname$()
		{
		}

		#endregion

		#region Properties
		#endregion

		#region Functions
		#endregion

		#region Enums
		#endregion
	}
}

Step 4 – Export the item as a template

  1. In Visual Studio, chose File | Export Template.  This starts a wizard that is extremely easy to follow.Note: If you have unsaved files in your project, you will be prompted to save them.
  2. Chose Item template, select your project, and click Next.
  3. In the next screen there was a tree view of check boxes for all my objects.  I checked the box next to my XmlClass.cs.
  4. In the next screen, provide references.Note: I added only System and System.Xml.
  5. In the next screen, provide a Template name and a Template description.
  6. Click finish.

You should now have the option under My Templates when you add a new item to your project.

This class will be  useful and will save you and your team some typing when you are in the class creation phase of your project and you are creating all your Serializable classes.


Copyright ® Rhyous.com – Linking to this page is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.