December 21, 2006

C++/CLI Quick Comparison with C#

The following table provides a summary of the most common constructs for quick reference.
Description C++/CLI C#
Allocate reference type ReferenceType^ h = gcnew ReferenceType; ReferenceType h = new ReferenceType();
Null reference ReferenceType^ h = nullptr; ReferenceType h = null;
Allocate value type ValueType v(3, 4); ValueType v = new ValueType(3, 4);
Reference type, stack semantics ReferenceType h; N/A
Calling Dispose method ReferenceType^ h = gcnew ReferenceType;

delete h;

ReferenceType h = new ReferenceType();

((IDisposable)h).Dispose();

Implementing Dispose method ~TypeName() {} void IDisposable.Dispose() {}
Implementing Finalize method !TypeName() {} ~TypeName() {}
Boxing int^ h = 123; object h = 123;
Unboxing int^ hi = 123;

int c = *hi;

object h = 123;

int i = (int) h;

Reference type definition ref class ReferenceType {};

ref struct ReferenceType {};

class ReferenceType {}
Value type definition value class ValueType {};

value struct ValueType {};

struct ValueType {}
Using properties h.Prop = 123;

int v = h.Prop;

h.Prop = 123;

int v = h.Prop;

Property definition property String^ Name
{
String^ get()
{
return m_value;
}
void set(String^ value)
{
m_value = value;
}
}
string Name
{
get
{
return m_name;
}
set
{
m_name = value;
}
}
Exposing an event TODO // expose the event
event System::EventHandler^ OnEventOccurrance;

//Fire the event
if (OnEventOccurrance != nullptr)
{
OnEventOccurrance(this, gcnew System::EventArgs());
}
Simple type methods, double example double.IsNaN(someDouble); double.NaN; System::Double::IsNaN(someDouble)
System::Double::NaN

December 1, 2006

Authentication and Authorisation in .NET

Detailed workshop on Principal Based security - Simple samples. Authentication is the part of verifying your identity. Authorization is determining whether or not a user has the permission to perform an action in the application. .NET framework provides access to the user through an identity and authorization access through a principal. Principal is (user or group of users) The framework provides two different types of principals, A Windows principal (WindowsPrincipal). It works against the underlying Windows OS A generic principal (GenericPrincipal). A principal and identity that is not bound to the underlying Windows user. + custom principal and identity by implementing the IPrincipal and IIdentity interface.

Reflection And Custom Attributes

Reasonable explanation of reflection Defining a custom class attribute
[AttributeUsage(AttributeTargets.Class)] // attribute is for classes only
public class CustomClassAttribute : System.Attribute
{
    private string m_Caption;
    public CustomClassAttribute(string caption)
    {
       m_Caption = caption;
    }

    public string Caption
    {
       get { return m_Caption; }
    }
}
Processing the Assembly to get the attributes
public void Discover()
{
    Type[] types = System.Reflection.
Assembly.GetExecutingAssembly().GetTypes();
    foreach (Type type in types) // Go over all the types
    {
      // Look for all types derived from BaseClass 
      if (type.BaseType == typeof(BaseClass)) 
      {
        // Look for the 'CustomClassAttribute' attributes on that type
        object[] attributes = 
type.GetCustomAttributes(typeof(CustomClassAttribute), false);
        if (attributes.Length > 0)
        {
          // iterate through the attributes, retrieving the 
          // properties
          foreach (Object attribute in attributes)
          {
            CustomClassAttribute fca = (CustomClassAttribute)attribute;
            DoSomething(type.FullName, fca.Caption);
            break;
          }
        }
      }
    }
}
The attribute is used like this
[CustomClass("Some caption")]
public class SomeClass : BaseClass 
{

...
}
For example, say you have some properties on a type that you wish to iterate through but you do not wish to get the Obsolete ones (marked using "[Obsolete]", then the code would be something like this:
Type type = typeof(MyXXXType);
PropertyInfo[] props = type.GetProperties();
foreach (PropertyInfo prop in props)
{
    object[] attributes = prop.GetCustomAttributes(typeof(ObsoleteAttribute), false);
    if (attributes.Length > 0) // If property is marked as Obsolete then ignore it
        continue;

    // otherwise do something with the property
}

Converting an Integer to a string in Managed C++

String* msg;
msg = String::Format(S"b{0:X4}", __box(m_intValue));
OR
System::Int32 test = iExposureMS*1000; 
String* sst = String::Format("sst {0}", test.ToString());

November 30, 2006

Extracting the MachineSid

using System.Security.Principal;
...
string userName = Environment.MachineName + @"\Administrator";
NTAccount account= new NTAccount(userName);
SecurityIdentifier sid = (SecurityIdentifier)
account.Translate(typeof(SecurityIdentifier)); string machineSid = sid.AccountDomainSid.ToString();

Using an ErrorProvider

1. Add it to the form
// 2. Initialise it:
errorProvider.BlinkStyle = ErrorBlinkStyle.AlwaysBlink;
errorProvider.SetIconAlignment(this, ErrorIconAlignment.MiddleRight);
errorProvider.SetIconPadding(this, 2);

// 3. To flag an error
errorProvider.SetError(tbName, "The specified user name is unknown");

// 4. To stop it flashing
errorProvider.Clear(); 

Useful Assembly Methods

using System.Reflection;


//To retrieve the version number from the 
// assembly in your code, you use can do this:
string strVersion = 
Assembly.GetExecutingAssembly().GetName().Version.ToString(); //To retrieve the version number from the // assembly that is calling your assembly, // you can use this: string strVersion =
Assembly.GetCallingAssembly().GetName().Version.ToString(); // Retrieving the executing assembly's path as a Uri Uri uri = new Uri(System.IO.Path.GetDirectoryName( Assembly.GetExecutingAssembly().GetName().CodeBase)); // and as a string path string path = new Uri(System.IO.Path.GetDirectoryName( Assembly.GetExecutingAssembly().GetName().CodeBase)).LocalPath;

Performing FileToString and StringToFile.

The required methods are on the File class:
using System.IO;

string File.ReadAllText  (string path, Encoding enc);
string File.ReadAllText  (string path);
void   File.WriteAllText (string path, string contents, Encoding encoding);
void   File.WriteAllText (string path, string contents);

Reading and Writing Xml


#region Read/Write Xml

using System.Text;
using System.Xml;
using System.IO;

...

// Reading from XML Reader
private void FromXml(XmlReader reader)
{
   bool corrupt = false;
   while (!reader.EOF && !corrupt)
   {
       if (reader.NodeType != XmlNodeType.EndElement)
       {
           switch (reader.Name)
           {
               case "BaseElement":
                 string tmp = reader.GetAttribute("Guid");
                 m_Guid = new Guid(tmp);                    
               break;

               case "EnumType":
                  string tmp = reader.ReadElementContentAsString();
                  m_EnumType = (EnumType)Enum.Parse(
                       typeof(EnumType), tmp);
               break;
               case "Id":
                   m_Id = reader.ReadElementContentAsString();
               break;
               case "Name":
                   m_SomeThing = reader.ReadElementContentAsString();
               break;
               case "SomeDate":
                   string value = reader.ReadElementContentAsString();
                   DateTime m_SomeDate;
                   DateTime.TryParse(value, out m_SomeDate);
               break;
               default:
               break;
           }
       }
       try
       {
           reader.Read();
       }
       catch (XmlException)
       {
           corrupt = true;
       }
   }
}


// Reading from XML String
private void FromXmlString(string xml)
{
   XmlTextReader reader = new XmlTextReader(xml, XmlNodeType.Element,
       new XmlParserContext(null, new XmlNamespaceManager(
           new NameTable()), null, XmlSpace.Default));
   try
   {
       reader.MoveToContent();
       FromXml(reader);
   }
   finally
   {
       reader.Close();
   }
}

// Reading from XMLFile
public void FromXmlFile(string xmlFile)
{
   if (File.Exists(xmlFile))
   {
       XmlTextReader reader = new XmlTextReader(xmlFile);
       try
       {
           reader.MoveToContent();
           FromXml(reader);
       }
       finally
       {
           reader.Close();
       }
   }
}

// Writing to XML Writer
public void ToXml(XmlWriter writer)
{
   //m_Writer.WriteDocType("", null, null, null);
   writer.WriteStartElement("BaseElement");
   writer.WriteAttributeString("Guid", m_Guid.ToString());
   WriteContent(writer);
   writer.WriteEndElement();
   writer.Flush();
}

protected virtual void WriteContent(XmlWriter writer)
{
   writer.WriteElementString("EnumType", m_EnumType.ToString());
   writer.WriteElementString("Id", m_Id);
   writer.WriteElementString("Name", m_Name);
   writer.WriteElementString("Date", DateTime.Now.ToUniversalTime().ToString());
}

// Writing to XML String
public override string ToXmlString()
{
   StringWriter sw = new StringWriter();
   XmlTextWriter writer = new XmlTextWriter(sw);
   try
   {
       writer.Formatting = Formatting.Indented;
       writer.WriteStartDocument();
       ToXml(writer);
       writer.WriteEndDocument();
   }
   finally
   {
       writer.Close();
   }

   return sw.GetStringBuilder().ToString();
}


public void ToXmlFile(string xmlFile, Encoding encoding)
{
   XmlTextWriter writer = new XmlTextWriter(xmlFile, encoding);
   try
   {
       writer.Formatting = Formatting.Indented;
       writer.WriteStartDocument();
       ToXml(writer);
       writer.WriteEndDocument();
   }
   finally
   {
       writer.Close();
   }
}

#endregion Read/Write Xml

November 29, 2006

Basic OnPaint and OnSizeChanged Methods for a Resizable Control

// after InitializeComponent()
this.ResizeRedraw = true; // If you want resizing to cause a redraw

protected override void OnSizeChanged(EventArgs e)
{
    base.OnSizeChanged(e);
    this.Invalidate();
}

protected override void OnPaint(PaintEventArgs pea)
{
    try
    {
        pea.Graphics.FillRectangle(Brushes.DarkOliveGreen, 
new Rectangle(0, 0, Width, Height)); // Create a new pen. using (Pen pen = new Pen(Brushes.Black)) { // Draw a line Point pt1 = new Point(ClientRectangle.Left,
ClientRectangle.Bottom - 1); Point pt2 = new Point(ClientRectangle.Right,
ClientRectangle.Bottom - 1); pea.Graphics.DrawLine(pen, pt1, pt2); } } catch (Exception ex) { //TODO: Log these errors. } }

Reading the Registry in c#

private static void GetMachineGuid()
{
    string machineGuid = string.Empty;
    RegistryKey rk = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\Cryptography");
    machineGuid = (string)rk.GetValue(@"MachineGuid");
    Console.WriteLine("MachineGuid: " + machineGuid);
}

August 19, 2006

Useful Object Oriented Programming Links

Useful Javascript Links

Javascript tit-bit:
You can always include the last update date on your page by using the following code:
<script language="JavaScript">
document.write("This page created by XXXXX Last update:" + document.lastModified);
</script> 

BeginInvoke On A Gui Object

Good article on BeginInvoke and Invoke differences

On the GUI class (form or control derived object):

  private delegate void DataChanged(Object Sender, BindingEventArgs Args);

  private void HandleDataChanged(Object
Sender, BindingEventArgs Args)
  {
    // If this delegate is invoked on another thread
    if (InvokeRequired)
    {
      // Asynchronously call THIS method later
      // but this time on our own GUI thread
      // BeginInvoke translates to a PostMessage call on
      // our window.
      BeginInvoke(new DataChangedDelegate(HandleDataChanged),
 new object[] { Sender, Args });
    }
    else // when the method is invoked on the GUI thread
    { // Update our forms/controls as required
      UpdateGui(Args);
    }
  }

WIndows CE Notes.Links

Initializing A ComboBox In CE.NET With The Values of An Enum

  SomeEnum status;
  int offset = 0;
  bool defined = false;
  do
  {
      status = (SomeEnum)offset++;
      defined = Enum.IsDefined(typeof(SomeEnum), status.ToString());
      if (defined)
      {
          comboBox.Items.Add(status);
      }

  } while (IsDefined);
  comboBox.SelectedIndex = 0;

Using A ListView

To get a nice excel type view of the list set the properties 'View=Details' and 'GridLines=True' or put the following code in the designer

//this.listView.Anchor =  //Dont forget to set the anchors appropriately
this.listView.AllowColumnReorder = true;
this.listView.View = System.Windows.Forms.View.Details; 
this.listView.GridLines = true;

// Select highlights a full row
this.listView.FullRowSelect = true;

// Select a single row only
this.listView.MultiSelect = false;

// Keep selected rows highlited even when the control does not have the focus 
this.listView.HideDelection = false; 
Adding items to the ListView
private const int NAME_COLUMN = 0;
private const int ID_COLUMN = 1;

void PopulateListView()
{
    // DONT call "listView.Clear()" or you'll lose all your
    // column data and then wonder why you table is empty!
    listView.Items.Clear(); 
    // Add the item to the ListView
    string[] fields = new string[] 
    { 
        "column1string", 
        "column2string", 
        ... 
    };
OR
    fields[NAME_COLUMN] = xxx.Name;
    fields[ID_COLUMN] = xxx.Id.ToString();
    ...

    ListViewItem lvItem = new ListViewItem(fields);
    // Insert at the top of the listview control
    listView.Items.Insert(0, lvItem);
    // Append to the end of the ListView control
    listView.Items.Add(lvItem);

    // with custom listviewitems
    MyListViewItem li = new MyListViewItem(...)
    listView.Items.Add(li);
}

To update a column:
private void UpdateIdColumn(int id)
{
    listView.Items[m_SelectedIndex].SubItems[ID_COLUMN].Text = id.ToString();
}
Optionally define a custom list view item which holds a reference to one of your types XXX
internal class MyListViewItem : ListViewItem
{
    internal MyListViewItem(XXX xxx)
        : base(new string[] { 
                    xxx.Name, 
                    xxx.Description, 
                })
    {
        XXX = xxx;
    }

    internal XXX XXX { get; set; }
}
private void listView_SelectedIndexChanged(object sender, EventArgs e)
{
    if (listView.SelectedItems.Count == 0)
    {
 // Are there any controls need enabling/
 // disabling when the nothing is selected
        button.Enabled = false;
        return;
    }
 
    // Are there any controls need enabling/
    // disabling when the nothing is selected
    otherCtrl.Enabled = true;
 
    foreach (ListViewItem lvi in lvParts.SelectedItems)
    {
        ((XXX)lvi.Tag).DoSomething();
 // or
        MyCustomListItem li = lvi as MyCustomListItem;
        if (li != null)
        {
            li.XXX.DoSomething(); 
        }
        break;
    }
}

Dont forget to add a method to resize the columns:
private void FitColumnsToListView()
{
    int extra = ListViewSpareColumnSpace(lvParts);
    if (extra > 0)
    {
        lvParts.Columns[0].Width += extra;
    }
}

private int ListViewSpareColumnSpace(ListView lv)
{
    if (lv.Columns.Count == 0)
        return 0;

    int width = lv.Size.Width;
    int usedWidth = 0;
    // 2 pixels for the divider lines
    foreach (ColumnHeader ch in lv.Columns)
    {
        usedWidth += ch.Width + 2;
    }
    int extra = width - usedWidth;
    return extra;
}
To disable selection of listview items, handle the ItemSelectionChanged event on the listView:
private void listView_ItemSelectionChanged(object sender, 
  ListViewItemSelectionChangedEventArgs e)
{
  if (e.IsSelected)
    e.Item.Selected = false;
}

Use Reflection To Set A Value On A Field

Setting a field on an object by reflection private static void SetFieldViaReflection( object obj, string fieldName, object value) { Type InstanceType = Instance.GetType(); FieldInfo fi = InstanceType.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); if (fi != null) { fi.SetValue(obj, value); } } SetFieldByReflection(object, "m_field", somevalue as object);

June 6, 2006

Boxing with C#

Theres nothing like learning by trying. Here is some code that I wrote that explicitly demonstrates boxing. I found in MSDN a little boxing test so I copied the balls of it (hope thats not illegal or anything) to here. The original article can be found through a quick google search. It is a good article on boxing.

June 4, 2006

Thread Pattern Starter Class

Background thread class as a starter for a threading class.


class WorkerThread
{

    public WorkerThread()
    {
        StartThread();
    }

    ~WorkerThread()
    {
        Dispose(false);
    }

    #region IDisposable Members

    private bool m_disposed = false;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!m_disposed)
        {
            if (disposing)
            {
                // Dispose managed resources
            }

            // Dispose unmanaged resources
            EndThread();
        }
        m_disposed = true;
    }

    #endregion



    #region Private Threading Related

    /// <summary>
    /// Actual threa object
    /// </summary>
    private Thread m_Thread = null;

    /// <summary>
    /// Give the thread a meaningful threadId
    /// </summary>
    private string threadId = "MyThreadName";

    /// <summary>
    /// Time to wait for the thread to finish 
    /// when merging the thread  
    /// back to the  main thread
    /// </summary>
    private uint waitForEndThread = 5000; // 5 seconds

    /// <summary>
    /// How long to pause for at the end of each iteration 
    /// </summary>
    private int m_ThreadSleepPeriod = 200;

    /// <summary>
    /// We use the m_PauseEvent to control the sleep period 
    /// of the thread. The m_PauseEvent
    /// sleeps for the given period  but we can force it to 
    /// wake up early by calling  
    /// Set on it.
    /// </summary>
    private AutoResetEvent m_PauseEvent = new AutoResetEvent(false);

    /// <summary>
    /// This does not need special protected access.
    /// It is set to false before the thread is  
    /// started  and  can  only get set to  true when 
    /// the  thread thread has begun.
    /// </summary>
    private bool m_Stop = false;

    /// <summary>
    /// Start the thread running
    /// </summary>
    private void StartThread()
    {
        if (m_Thread != null)
        {
            EndThread();
        }

        if (m_Thread == null)
        {
            if (m_PauseEvent == null)
            {
                m_PauseEvent = new AutoResetEvent(false);
            }
            m_Stop = false;
            m_Thread = new Thread(new ThreadStart(
this.ThreadRoutine)); m_Thread.IsBackground = true; m_Thread.Start(); m_Thread.Name = threadId; Thread.Sleep(0); } } /// <summary> /// EndThread to the thread to terminate it /// </summary> private void EndThread() { m_Stop = true; if (m_Thread != null) { if (m_PauseEvent != null) { m_PauseEvent.Set(); } try { if (m_Thread.IsAlive) { System.Diagnostics.Debug.WriteLine(
"WorkerThread.EndThread(): EndThreading this thread \'"+
m_Thread.Name + "\' to \'" + Thread.CurrentThread.Name + "\'"); // Wait X seconds for the thread to finish if (!m_Thread.Join((int)waitForEndThread)) { System.Diagnostics.Debug.WriteLine(
"WorkerThread.EndThread(): EndThread() failed, so ABORTing thread\'" +
m_Thread.Name + "\'"); m_Thread.Abort(); // otherwise abort } else { System.Diagnostics.Debug.WriteLine(
"WorkerThread.EndThread(): EndThread() succeeded, Thread \'"+
m_Thread.Name + "\' is terminated"); } } else { System.Diagnostics.Debug.WriteLine(
"WorkerThread.EndThread(): Thread \'" +
m_Thread.Name + "\' is not 'Alive' so EndThread() not invoked"); } } catch (System.Threading.ThreadStateException ex) { // Swallow any ThreadStateExceptions System.Diagnostics.Debug.WriteLine(
"WorkerThread.EndThread(): ThreadStateException caught in thread \'" +
m_Thread.Name + "\'" + ex.ToString()); } m_Thread = null; if (m_PauseEvent != null) { m_PauseEvent.Close(); m_PauseEvent = null; } } } /// <summary> /// The routine executed within the new thread /// </summary> private void ThreadRoutine() { string thrdName = m_Thread.Name; System.Diagnostics.Debug.WriteLine("Thread \'" +
thrdName + "\' thread routine is started"); try { while (m_Stop != true) { ThreadWork(); if ((m_Stop != true) && (m_ThreadSleepPeriod >= 0)) { m_PauseEvent.WaitOne(m_ThreadSleepPeriod,
false); } } } catch (Exception ex) { m_Stop = true; //if (log != null) System.Diagnostics.Debug.WriteLine(
"FATAL exception caught in thread routine \'" +
thrdName.ToString() + "\' Thread will be terminated" + ex.ToString()); } System.Diagnostics.Debug.WriteLine("Thread \'" + thrdName +
"\' end of thread routine reached"); } private void ThreadWork() { // Do something } #endregion }

Windows Service Pattern

Use this template as an example for creating a service.
Note that XXX is the service implementation class, this class just integrates that service object into windows services.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Runtime.Remoting;

using Logging = log4net;

namespace XXX.service
{
  /// <summary>
  /// Main service class as created by the code generator.
  /// </summary>
  public class XXXService 
  {
    #region Logging

    private static readonly Logging.ILog log =   
        Logging.LogManager.GetLogger(typeof(XXXService));

    #endregion Logging

    /// <summary>
    /// 
    /// </summary>
    public static readonly string ServiceDisplayName =
        "XXXService";

    #region Private Fields

    /// <summary> 
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.Container components
        = null;

    /// <summary>
    /// Did the service start up successfully
    /// </summary>
    private bool startSuccesful = false;

    #endregion Private Fields

    #region Constructor

    /// <summary>
    /// XXXService constructor.
    /// </summary>
    public XXXService()
    {
      // This call is required by the Windows.Forms
      // Component Designer.
      InitializeComponent();
    }

    #endregion Constructor

    #region Main/Initialise

    // The main entry point for the process
    static void Main()
    {
      System.ServiceProcess.ServiceBase[] ServicesToRun;
  
      // More than one user Service may run within the
      // same process. To add another service to this 
      // process, change the following line to
      // create a second service object. For example,
      //
      //   ServicesToRun = new
      //    System.ServiceProcess.ServiceBase[] { 
      //        new XXXService(),
      //        new MySecondUserService() };
      //
      ServicesToRun = new System.ServiceProcess.ServiceBase[] 
        { new XXXService() };

      System.ServiceProcess.ServiceBase.Run(ServicesToRun);
    }

    /// <summary> 
    /// Required method for Designer support - do not modify 
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      components = new System.ComponentModel.Container();
      this.ServiceName = ServiceDisplayName;
    }

    #endregion  Main/Initialise

    #region IDispose Implementation

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    protected override void Dispose( bool disposing )
    {
      if( disposing )
      {
        if (components != null) 
        {
          components.Dispose();
        }
      }
      base.Dispose( disposing );
    }

    #endregion IDispose Implementation

    #region Service Methods

    private bool IsDebugParameter(string arg)
    {
      var param = arg.ToUpperInvariant();

      return (param == "-DEBUG") || (param == "/DEBUG");
    }

    /// <summary>
    /// Set things in motion so your service can do its work.
    /// </summary>
    protected override void OnStart(string[] args)
    {
      // Allow us to be run in a debugger - for
      // development time support.
      if ((args.Length == 1) && IsDebugParameter(args[0]))
        Debugger.Launch();

      startSuccesful = false;
      string fileName = string.Empty;
      try
      { 
        log.Info("OnStart: Starting \'" + ServiceDisplayName<br> + "\'");

        System.IO.FileInfo fi = new System.IO.FileInfo(
            System.Windows.Forms.Application.ExecutablePath);
        System.Environment.CurrentDirectory = 
            fi.Directory.ToString();
        log.Info("Setting current directory to " 
            + System.Environment.CurrentDirectory);
        fileName = System.Windows.Forms.Application.ExecutablePath 
            + ".config";
        log.Info("Loading configuration from " + fileName);
        
        // If you have a remoting object that is 
        // initialised within the Config file       
        // initialise it here.
        // RemotingConfiguration.Configure(fileName);
            
        // Initialise 
        log.Info("OnStart: About to create XXX.");
        
        XXX xxx = new XXX(); // Service implementation class
        xxx.Initialise();
        
        // We assume that if the XXX is not constructed and 
        // initialised correctly it will throw an exception.
        // If we get to this point without an exception 
        // being thrown we assume 'alles ist gut'
        startSuccesful = true; 
        log.Info("OnStart: Started \'" + ServiceDisplayName 
            + "\' successfully=" + startSuccesful.ToString());
      }
      catch(Exception ex)
      {
        string errorMsg = 
          "Exception occured while starting service\'" 
            + ServiceDisplayName 
            + "\'. Expect an error message dialog");
        log.Fatal(errorMsg, ex);
        throw; // Results in error message: "XXX 
        // service on Local Computer started and 
        // then stopped. Some services stop if they 
        // have no work to do, for example, the 
        // Performance Logs and Alert service        
      }   
      if (startSuccesful)
      {
        // Tell the rest of the world we are running.
        ... 
      }
    }
 
    /// <summary>
    /// Stop this service.
    /// </summary>
    protected override void OnStop()
    {
      log.Info("OnStop: Stopping \'" + ServiceDisplayName<br> + "\'");
      
      if (xxx != null)
      {
        xxx.Dispose(); 
        ... 
      }
      
      if (startSuccesful)
      {
        // 
      }
      log.Info("OnStop: Stopped \'" + ServiceDisplayName<br> + "\'");
    }

    #endregion Service Methods

  }

May 25, 2006

Using DOM to parse an Xml Document

XmlDocument xDoc = new XmlDocument();
try
{
  // load the configuration file
  xDoc.Load(sFileName);

  // find the node of interest from the key
  XmlNode theNode = 
  xDoc.SelectSingleNode(@"/thingy/appSettings/add[@key = '" + key + "\']");

  // retrieve the nodes value if it exists
  if (theNode != null)
    return theNode.Attributes["value"].Value;
}

NUnit as the Debugging Application in Visual Studio

See also Using NUnit

Setting Visual Studio To test a particular Assembly using the NUnit GUI In VS, for the particular project of interest go to Project->Properties->Configuration Properties->Debugging and set the following fields:

Start Application:
C:\...\NUnitPath\bin\nunit-gui.exe
Command Line Arguments:
/fixture:namespace.of.assembly.to.test.goes.here /run

System.Threading.Interlocked.CompareExchange

Use
System.Threading.Interlocked.CompareExchange(ref x, y, null);
instead of
if (x == null)
{
    lock (lockObject)
    {
        if (x == null)
        {
            x = y;
        }
    }
}

May 24, 2006

The Close and/or Dispose Connundrum

In my opinion "Close() should not call Dispose()". I am not sure what Microsoft's stance is on this. However their views should not always be taken as best. I remember once I wrote some code to store some settings in a Ini file (this was before Xml and config files) and a colleague came and berated me, telling me that the Microsoft standard is that all settings should go in the registry. I thought 'Ini' files were and still are great. The API is simple as is the 'Ini' file format unlike the registry!
Why should Close() not call or implement Dispose(). What if you call Open on the object again? If its been disposed of by the Close() and SuppressFinaliser() was called then you have problems. How will you get the Finaliser back in the Finaliser queue? If you call Dispose() however then you are explicitly saying that all the objects resources should be relinquished this is not the case with Close() where you might want to Open() the object again.
Also, in OO Semantics Close() does not imply that all unmanaged resources will be released. Calling Close() on an object may release 1 or more unmanaged resources but you cannot assume that it releases all of them. In a lazy implementation it may not release any. You should always call Dispose after Close.
Its possible that Open may be called again on an object some time after Close was called but if the object has been disposed of within the previous call to Close then BANG!. I think Paul Wilson's article makes a good case for this. Check this out as well for some other opinions.
In 'Applied Microsoft .NET Framework Programming', Jeffrey Richter 'strongly discourages' the use of Dispose. He says the garbage collector is well written and you should let it do its job.

Quick Time Comparison in .NET

Use System.Environment.TickCount for quick stop watch type functionality
  private int startTime = System.Environment.TickCount;
  private const int TenSeconds = 10000;
  Math.Abs(System.Environment.TickCount-startTime) > TenSeconds

Reading XSLT From A Manifest Resource annd Applying It

public static string ApplyXslFromManifest(string sourceXml)
{
  Assembly myAssembly = Assembly.GetAssembly(
typeof(assemblyName)); Stream fileStream = myAssembly.GetManifestResourceStream(
"Common.StripComments.xslt"); StreamReader streamReader = new StreamReader(fileStream); string text = streamReader.ReadToEnd(); return ApplyXslTransform(sourceXml, text); } public static string ApplyXslTransform(
string sourceXml, string xslStyleSheet) { //the outputs string result=""; // read XML XmlTextReader xmlReader = new XmlTextReader(new
StringReader(sourceXml)); // read XSLT XmlTextReader xsltReader = new XmlTextReader(new
StringReader(xslStyleSheet)); XslTransform xslt = new XslTransform (); xslt.Load(xsltReader, null, null); //create the output stream StringBuilder sb = new StringBuilder(); TextWriter outputWriter = new StringWriter(sb); // Transform to a new XPath document XPathDocument xPathDocument = new XPathDocument(
xmlReader); xslt.Transform(xPathDocument, null, outputWriter,
null); //get result result=sb.ToString(); return result; }

May 12, 2006

XSL To Strip Comments Out Of Some Xml

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template 
     match="*|@*|processing-instruction()|text()">
    <xsl:copy>
      <xsl:apply-templates
        select="*|@*|processing-instruction()|text()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

May 11, 2006

Using A System.Threading.Timer To Implement A TimeOut Feature

// The Timer delegate to be invoked on a callback (from 
// another thread)
protected void TimeOut(object obj)
{
  lock(accesslock) // Careful. TimeOut callback occurs on 
another thread { log.Error("Something TIMED OUT, will take action"); TakeTimeOutAction(); } } ... // Example usage using (Timer timer = new Timer(new TimerCallback(TimeOut), null,
10000L, Timeout.Infinite)) { while (!complete) { log.Debug("Something waiting for something else to complete"); Thread.Sleep(1000); } }

Non-expiring Singleton Object Lease

To make the lease on a singleton object never expire override the MarshalByRefObject method 'InitializeLifetiemService'. Simply make the method return null

public override object InitializeLifetiemService()
{
  return null;
}

Loading an Assemby and Creating an Object by Reflection

// Load the containing assembly
Assembly assembly = Assembly.LoadFrom(assemblyPath);
// Get the full name for the object including namespace
string objName = ProjConfig.Instance.NamespaceName
+ "." + className; // Create the object obj = assembly.CreateInstance(objName); // Convert to required class or interface Thingy myThingy = obj as Thingy;

March 27, 2006

C# Xml Creation Sample

Parsing Hexadecimal

How to parse a number in Hexadecimal form
 newByte = .Parse(hex, System.Globalization.NumberStyles.HexNumber);

C# OpenPGP Encryption

C# OpenPGP Encryption Imlementation - Could be useful

Dispose Pattern

Explains how to implement IEnumerator and Contains basic IDispose pattern and more Msdn Guidelines on Implementing IDisposable and Equals Operators


Design pattern for a base class with unmanaged resources.

// Design pattern for a base class with unmanaged resources.
public class Base: IDisposable
{

#region Dispose Implementation

// Use C# 'destructor' style syntax for a finalizer.
// Finalizer is only required when the class has Unmanaged resources
// but can also be used to detect memory leaks
~Base() 
{
  // This is defensive code to ensure that even if you forget to call Dispose() unmanaged objects stil get freed
  Dispose (false); // Dispose of unmanaged resources 
  Debug.Assert(false, nameof(Base) + " with id of " + someId + " was not disposed of"); // Useful for detecting memory leaks
}

protected bool _isDisposed;

//Implement IDisposable.
public void Dispose() 
{
  Dispose(true); // Dispose of managed and unmanaged resources
  GC.SuppressFinalize(this); // Not required now
}

protected virtual void Dispose(bool disposing) 
{
  if (_isDisposed)
    return;
    
  if (disposing) 
  {
     // Free other state (managed objects).
  }
      
  // Free your own state (unmanaged objects).
  // Set large fields to null.
  _isDisposed = true;
}

#endregion Dispose Implementation

...
}

Design pattern for a derived class

   
// Design pattern for a derived class.
public class Derived : Base
{  

#region Dispose Implementation 

   protected override void Dispose(bool disposing) 
   {
      if (_isDisposed)
        return;
    
      if (disposing) 
      {
         // Free other state (managed objects).
      }
      
      // Release unmanaged resources here
      // Set large fields to null.
      
      // Call Dispose on your base class.
      base.Dispose(disposing);
   }
   
   // The derived class does not have a Finalize method
   // or a Dispose method with parameters because it inherits
   // them from the base class.

#endregion Dispose Implementation

}

Finally the simplest case

// Design pattern for a simple class with only small unmanaged resources.
public class SimplestDispose : IDisposable
{

#region Dispose Implementation

#region DEBUG
// Finalizer is only used to detect memory leaks
~SimplestDispose() 
{
  Debug.Assert(false, nameof(Base) + " with id of " + someId + " was not disposed of"); // Useful for detecting memory leaks
}
#endregion DEBUG

//Implement IDisposable.
public void Dispose() 
{
  // Dispose of managed resources here
  
#if DEBUG  
  GC.SuppressFinalize(this); // Not required now except for detecting memory leaks
#endif
}

#endregion Dispose Implementation

...
}

Safely Parse An Ip Address

This helper method safely parses an IP address from a string using the System.Net.IPAddress class
private static string SafeIpAddressFromString(string value)
{
  if (ReferenceEquals(value, null))
      value = ""; // System.Net.IPAddress.Parse cannot handle null values
  System.Net.IPAddress ipAddr = System.Net.IPAddress.Parse(value);
  return ipAddr.ToString();
}

March 16, 2006

Installing Windows Services

Using InstallUtil Install: InstallUtil.exe algo.exe Uninstall: InstallUtil.exe /u algo.exe Batch File To Install A service
C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\InstallUtil.exe 
/showcallstack C:\...\bin\XXXService.exe pause
Batch File To Uninstall A service
C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\InstallUtil.exe /u
/showcallstack C:\...\bin\XXXService.exe pause
Programmatically Add a reference to 'System.Configuration.Install' Install:
String []installParams= {filename};
System.Configuration.Install.ManagedInstallerClass.InstallHelper(installParams);
Uninstall:
String []installParams= {"/u", filename};
System.Configuration.Install.ManagedInstallerClass.InstallHelper(installParams);

Manual Locking With Monitors

When we want to use a timed 'lock' we can not use the normal lock statement, we have to use the monitor directly.
private object someLock = new object();
...
// Here we need to execute something within a Timeout period
// but we could exceed the timeout just waiting for the lock on our object!
algo = null;
int start = System.Environment.TickCount;
bool lockAquired = Monitor.TryEnter(someLock, timeout);
if (lockAquired)
{
  try
  {
    int elapsedTime = (System.Environment.TickCount-start);
    // Did we use any time up waiting for the lock? Take it off the original timeout 
    // new timeout = original timeout - time expired obtaining the lock
    int timeLeft = timeout - elapsedTime;
    if (timeLeft > 0)
    {
        DoSomething(timeLeft, out algo);
    }
  }    
  finally
  {
    Monitor.Exit(someLock);
  }
}

March 15, 2006

Free Programmers Resources and Tools

ASP.NET 2.0 Links

February 24, 2006

SNMP in .NET

Useful links for reading about SNMP in a .Net context

System.Net.IPAddress Tests

string noadd = "0.0.0.0";
System.Net.IPAddress ipaddr = System.Net.IPAddress.Parse(noadd);
ipaddr = System.Net.IPAddress.None;
string tmp = System.Net.IPAddress.None.ToString(); // produces "255.255.255.255"
tmp = System.Net.IPAddress.Loopback.ToString(); // produces "127.0.0.1"
tmp = System.Net.IPAddress.Any.ToString();      // produces "0.0.0.0"
tmp = System.Net.IPAddress.Broadcast.ToString(); // produces "255.255.255.255"

ipaddr = System.Net.IPAddress.Parse("");
tmp = ipaddr.ToString(); // produces "0.0.0.0"
ipaddr = System.Net.IPAddress.Parse("0");
tmp = ipaddr.ToString(); // produces "0.0.0.0"
ipaddr = System.Net.IPAddress.Parse("0.0");
tmp = ipaddr.ToString(); // produces "0.0.0.0"
ipaddr = System.Net.IPAddress.Parse("0.0.0");
tmp = ipaddr.ToString(); // produces "0.0.0.0"
ipaddr = System.Net.IPAddress.Parse("0.0.0.0");
tmp = ipaddr.ToString(); // produces "0.0.0.0"

February 13, 2006

Executable Path of the Application

string exeDirPath = System.IO.Path.GetDirectoryName(
          System.Reflection.Assembly.GetExecutingAssembly())
or for the full path of the executable:
string exePath = new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase).LocalPath;
or just (only for Windows Forms application)
System.Windows.Forms.Application.ExecutablePath - Executable path of the application in which the assembly is housed:
string exePath = System.Windows.Forms.Application.ExecutablePath;
or
string[] args = Environment.GetCommandLineArgs();
string exePath = args[0];
To get the working directory where the executable lies (but this does not work for a service or so it seems):
string exePath = System.Windows.Forms.Application.StartupPath; 
or alternatively
string cwd = Environment.CurrentDirectory;
Here is the sample output of these for a test application. The application was started in the "D:\Documents" directory but located at "D:\Documents\Devel\Tools\IdeaTester\bin\x86\Debug\IdeaTester.exe"
First the list of methods used:
1.  System.Reflection.Assembly.GetExecutingAssembly().GetName().ToString()
2.  System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase
3.  System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssem
bly().GetName().CodeBase)
4.  System.IO.Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().GetN
ame().CodeBase).LocalPath)
5.  System.IO.Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().GetN
ame().CodeBase).AbsolutePath)
6.  System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutableP
ath)
7.  System.IO.Path.GetDirectoryName(args[0])
8.  System.Windows.Forms.Application.StartupPath
9.  Environment.CurrentDirectory
10. System.Windows.Forms.Application.ExecutablePath
Here is the output of each method:
1.  IdeaTester, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
2.  file:///D:/Documents/Devel/Tools/IdeaTester/bin/x86/Debug/IdeaTester.exe
3.  file:\D:\Documents\Devel\Tools\IdeaTester\bin\x86\Debug
4.  D:\Documents\Devel\Tools\IdeaTester\bin\x86\Debug
5.  D:\Documents\Devel\Tools\IdeaTester\bin\x86\Debug
6.  D:\Documents\Devel\Tools\IdeaTester\bin\x86\Debug
7.  D:\Documents\Devel\Tools\IdeaTester\bin\x86\Debug
8.  D:\Documents\Devel\Tools\IdeaTester\bin\x86\Debug
9.  D:\Documents
10. D:\Documents\Devel\Tools\IdeaTester\bin\x86\Debug\IdeaTester.exe



c# Code for Reading MP3s

C# Code for reading and Parsing MP3 files C# Shell ID3 Tag Reader

.Net Remoting Useful Links

About .NET Remoting: Three concepts Compared and Simplified Design and Develop Seamless Distributed Applications for the Common Language Runtime Remoting with .NET Description

Use ServiceController class to stop and start services.

Use ServiceController class to stop and start services. This is useful within NUnit tests.
StartService(string XXXServiceName)
{
  serviceController 
    = new System.ServiceProcess.ServiceController(XXXServiceName);

  log.Info(XXXServiceName 
    + " service status is currently set to " 
    + serviceController.Status.ToString());

  if  ((serviceController.Status.Equals(
        System.ServiceProcess.ServiceControllerStatus.Stopped)) ||
       (serviceController.Status.Equals(
        System.ServiceProcess.ServiceControllerStatus.StopPending)))
  {
    serviceController.Start();
    serviceController.Refresh();
    log.Info(ConfiguratorManagerServiceName 
      + " service status is currently set to " 
      + serviceController.Status.ToString());
  }
}

StopService(string XXXServiceName)
{
  serviceController.Stop();
  serviceController.  
  log.Info(XXXServiceName 
    + " service status is currently set to " 
    + serviceController.Status.ToString());
}

XslCompiledTransform

New replacement for XslTransform in .NET version 2.0 is XslCompiledTransform. This is apparently faster. Here is a sample to prepare it:
private XslCompiledTransform xctCached = null;

private XslCompiledTransform GetXsltTransform()
{
  if (this.xctCached == null)
  {
    // Retrieve the xslt
    string xslt = RetrieveEmbeddedStringResource(
        "ViewNUnitTestResults.Resources.NUnitTestResultsToHtml.xsl");
    XmlTextReader xsltReader = new XmlTextReader(new
        StringReader(xslt));                        
    // Create the compiled xslt transform
    this.xctCached = new XslCompiledTransform();
    this.xctCached.Load(xsltReader);
  }
  return this.xctCached;
}
and then use it:
public string ApplyXslTransform(
    string sourceXml, XslCompiledTransform xct)
{
  // read XML
  XmlTextReader xmlReader = new XmlTextReader(
    new StringReader(sourceXml));

  //create the output stream
  StringBuilder sb = new StringBuilder();
  using (StringWriter outputWriter = new StringWriter(sb))
  {
    // Do the transform
    XsltArgumentList args = new XsltArgumentList();
    xct.Transform(xmlReader, args, outputWriter);
  }

  return sb.ToString();
}
You can still use the XslTransform class though:
#region Using XslTransform

public string ApplyXslFromManifest(string sourceXml)
{
    XslTransform xslt = GetXslTransform();
    return ApplyXslTransform(sourceXml, xslt);
}

private XslTransform xtCached = null;

private XslTransform GetXslTransform()
{
    if (this.xtCached == null)
    {
        string xsltString = RetrieveEmbeddedStringResource(
            "ViewNUnitTestResults.Resources.NUnitTestResultsToHtml.xsl");
        XmlTextReader xsltReader = new XmlTextReader(new 
            StringReader(xsltString));
        this.xtCached = new XslTransform();
        this.xtCached.Load(xsltReader);
    }
    return this.xtCached;
}

public static string ApplyXslTransform(
    string sourceXml, XslTransform xslt)
{
    // read XML
    XmlTextReader xmlReader = new XmlTextReader(new
    StringReader(sourceXml));

    //create the output stream
    StringBuilder sb = new StringBuilder();
    TextWriter outputWriter = new StringWriter(sb);

    // Transform the Xml
    XPathDocument xPathDocument = new XPathDocument(xmlReader);
    xslt.Transform(xPathDocument, null, outputWriter, null);

    //get result
    return sb.ToString();
}

#endregion Using XslTransform
Althouh the documentation says it is obsolete, I think if the xslt is only going to be used once only it would be slightly faster to use the XslTransform class. The compiled transform is best when the compiled xslt object is going to be used multiple times, see the article "Properly Utilizing XslCompiledTransform". Check this article on a thorough analysis of the 2 different XSLT transforms in .NET, their speed differences and some recommendations on when to use which.

Using 'ArrayList.ToArray()' method

PKMuxlet[] mIds = (PKMuxlet[])mIdList.ToArray(typeof(PKMuxlet));

January 13, 2006

Threading using the ThreadPool

Use something along the lines:
System.Threading.ThreadPool.QueueUserWorkItem(
new System.Threading.WaitCallback(MyThreadRoutine), stateObject);
where 'stateObject' is an object which is passed as a parameter to the thread routine 'MyThreadRoutine'
For a generic version look here

Using NUnit

Running NUnit on the command line

Run a text fixture using the GUI:
"C:\Program Files\NUnit 2.2\bin\nunit-gui.exe" /fixture:sometests.test.mytest /run

Run a text fixture using the Console:
"C:\Program Files\NUnit 2.2\bin\nunit-console.exe" C:\src\ssg\SrcUnitTests\bin\Debug\NUnitTests.dll /fixture :sometests.test.mytest /out:TestResult.txt /exclude:Manual /thread
This will exclude all tests or test fixtures marked as [Category("Manual")], output goes to Results.txt and /thread causes a separate thread to be created for running the tests.

Description of the NUnit test class attributes can be found here
Here is a NUnit skeleton class with the main attributes:
using NUnit.Framework;

[TestFixture]
public class SomeTester
{
#region Setup/TearDown

  // This is invoked before each [TestFixture]
  // ie once only, before any tests are invoked
  [TestFixtureSetUp] 
  public void TestFixtureSetUp()
  {
  }

  // This is invoked after each [TestFixture]
  // ie once only, after all tests have been invoked
  [TestFixtureTearDown] 
  public void TestFixtureTearDown()
  {
  }

  // This is invoked before each [Test}
  [SetUp] 
  public void Setup()
  {
  } 

  // This is invoked after each [Test}
  [TearDown] 
  public void TearDown()
  {
  }

#endregion Setup/TearDown

  // Format of a Test method, Try to put all the setup for the test in the test.
  // If necessary add private Setup/Initialise/Teardown methods to assist this 
  // rather than using the one listed above
  [Test]
  public void SomeTest()
  {
  }
 
  // You can add test parameters to a test and use it to test multiple cases 
  [Test]
  [TestCase(5.0d, 0.0d, 3.0d)]
  [TestCase(5.0d, 1.0d, 3.0d)]
  [TestCase(5.0d, 0.0d, 5.0d)]
  public void SomeTest(   double fullLengthSecs, double startTimeSecs, int expectedValue)
  {
  }
}

Use these logging lines to generically log the beginning and end of a test using reflection


[Test]
public void SomeTest()
{
 log.Info("*** Beginning Test - " + System.Reflection.
MethodBase.GetCurrentMethod().ToString());
 log.Info("*** Ending Test - " + System.Reflection.
MethodBase.GetCurrentMethod().ToString());
}
alternatively use:
//Output test class and method name:
Debug.WriteLine("*** Beginning Test - " +
  System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.ToString()
  + "." +
  System.Reflection.MethodBase.GetCurrentMethod().Name.ToString());
NUnit Exceptions Use the 'ExpectedException' attribute when the test is expected to result in an exception being thrown.
[Test]
[ExpectedException(typeof(System.Net.Sockets.SocketException))]
public void TestNoServer()
{
...
alternatively use can use the Assert.Throws() method:
Assert.Throws(typeof(System.Net.Sockets.SocketException),
  delegate
  {
     SomeMethodThatShouldThrowAnException();
  });

System.Convert Class

System.Convert Class - Useful for converting classes between the base types

Custom Configuration Handlers In .Net

Implementing 'ConfigurationSectionHandler' objects. Think I may have an error in this code but nothing to difficult to resolve In the '.config' file for the application 1. Specify the handler within the 'configsections' area 2. Add the section as a child node of the 'configuration' node
<configuration>
 <configSections>
...
  <section name="mysection"
type="mynamespace.mysection.StuffConfigurationSectionHandler, Stuff" /> </configSections> ... <mysection TransportStreamPacketSize="188"> <download MaxMessageRetries="5" MaxWaitPeriod="5000"/> <upload MaxMessageRetries="5" MaxWaitPeriod="5000"> </upload> </mysection> ... </configuration>
Then write a 'ConfigurationSectionHandler' class for it This handler must be invoked somewhere for it to do something
System.Configuration.ConfigurationSettings.GetConfig("mysection");   
using System.Configuration;

// Handles the DescriptorFactory configuration
section of the application configuration file. public class StuffConfigurationSectionHandler
: IConfigurationSectionHandler { #region Logging //static readonly Logging.ILog log = ... #endregion Logging #region Private Data private static object threadLock = new object(); private static bool configurationComplete = false; #endregion Private Data #region IConfigurationSectionHandler Members // This method is called as a result of a call to // ConfigurationSettings.GetConfig(). // It sets the configuration data in // the PsiSiComms configuration object public object Create(object parent,
object configContext, XmlNode section) { lock(threadLock) { if (!configurationComplete) { log.Info("Configuring XXX."); RetrieveConfiguration(section); configurationComplete = true; log.Info("PsiSiComms configuration complete."); } } return null; } #region Private Helper Methods private void RetrieveConfiguration(XmlNode parent) { XmlNode node; XmlNode uploadNode = parent.SelectSingleNode("./upload"); if (!ReferenceEquals(uploadNode, null)) { node = uploadNode.Attributes.GetNamedItem
("MaxMessageRetries"); if (!ReferenceEquals(node, null)) { MyXXXConfig.Upload.MaxMessageRetries
= int.Parse(node.Value); } node = uploadNode.Attributes.GetNamedItem
("MaxWaitPeriod"); if (!ReferenceEquals(node, null)) { MyXXXConfig.Upload.MaxWaitPeriod
= int.Parse(node.Value); } RetrieveUploadTablesConfiguration(uploadNode); } } #endregion Private Helper Methods #endregion }