Category Archives: .Net

Getting Installed Browsers and Version C#

I ran into a few posts that solved the problem of getting the installed browsers on a Windows machine and getting the version that were very helpful.

Getting Chrome and Firefox version locally, C#

Finding All Installed Browsers in Windows XP and Vista – beware 64bit!

These snippets were very helpful. So now I will hand it combined to you on a silver platter as a downloadable Console App.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Win32;


namespace GetAllInstalledBrowsers
{
class Program
{
static void Main(string[] args)
{
foreach (Browser browser in GetBrowsers())
{
Console.WriteLine(string.Format("{0}: \n\tPath: {1} \n\tVersion: {2} \n\tIcon: {3}", browser.Name, browser.Path, browser.Version, browser.IconPath));
}
Console.ReadKey();
}


public static List<Browser> GetBrowsers()
{
RegistryKey browserKeys;
//on 64bit the browsers are in a different location
browserKeys = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\Clients\StartMenuInternet");
if (browserKeys == null)
browserKeys = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Clients\StartMenuInternet");
string[] browserNames = browserKeys.GetSubKeyNames();
var browsers = new List<Browser>();
for (int i = 0; i < browserNames.Length; i++)
{
Browser browser = new Browser();
RegistryKey browserKey = browserKeys.OpenSubKey(browserNames[i]);
browser.Name = (string)browserKey.GetValue(null);
RegistryKey browserKeyPath = browserKey.OpenSubKey(@"shell\open\command");
browser.Path = (string)browserKeyPath.GetValue(null).ToString().StripQuotes();
RegistryKey browserIconPath = browserKey.OpenSubKey(@"DefaultIcon");
browser.IconPath = (string)browserIconPath.GetValue(null).ToString().StripQuotes();
browsers.Add(browser);
if (browser.Path != null)
browser.Version = FileVersionInfo.GetVersionInfo(browser.Path).FileVersion;
else
browser.Version = "unknown";
}
return browsers;
}
}


internal static class Extensions
{
///
/// if string begins and ends with quotes, they are removed
///
internal static String StripQuotes(this String s)
{
if (s.EndsWith("\"") && s.StartsWith("\""))
{
return s.Substring(1, s.Length - 2);
}
else
{
return s;
}
}
}


class Browser
{
public string Name { get; set; }
public string Path { get; set; }
public string IconPath { get; set; }
public string Version { get; set; }
}
}

If you run this code you will get results that resemble this:

Mozilla Firefox:
Path: C:\Program Files (x86)\Mozilla Firefox\firefox.exe
Version: 31.0
Icon: C:\Program Files (x86)\Mozilla Firefox\firefox.exe,0
Google Chrome:
Path: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
Version: 37.0.2062.124
Icon: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe,0
Internet Explorer:
Path: C:\Program Files\Internet Explorer\iexplore.exe
Version: 10.00.9200.16521 (win8_gdr_soc_ie.130216-2100)
Icon: C:\Program Files\Internet Explorer\iexplore.exe,-9

Happy coding!

Advertisements

Master Page DataBind() will clear data on your page – remember!

I was working on a problem with a drop down list getting un-initialized and had run across this page:

c# – .Net Webform losing data – Stack Overflow.

This simple post is about a coder who was getting their ddl control reset every time a postback occurred. They had not yet learned about putting the initialization inside an if statement that only runs when the page is first loaded.

I had done this, and had not changed the code on this page for days and yet it stopped working.

Then I realized — I had been fighting with the links on the site.master.cs page that were causing the link to come up blank. I learned that when you have a reference in your head element on the master page like so:

<script src='<%# Helper.ResolveMyUrl(“/Scripts/libs/jquery-1.7.1.min.js”) %>’ type=”text/javascript”></script>

You need this:

Page.DataBind(); // (yes, but not quite…)

in your Page_Load so that the function call will be resolved. I added that line and my links all started working — and my drop down list started clearing on a postback. But there were enough hours between these discoveries, that I hadn’t made the connection.

What I really needed was:

if (! Page.IsPostBack)  // (better, but not yet done…)
Page.DataBind();

since the DataBind affects all of the data bound controls on all of the pages that use it as a master page.

But wait, there’s more!

I thought this had cleared up my issue, but then I found that another control that I initialized lost its value. It turns out that this DataBind on the entire page is not a good idea. Instead you need to be specific about the stuff on the master page. So I did this:

if (! Page.IsPostBack)
{
  Page.Header.DataBind(); // initializes the script references
  LoginView1.DataBind(); // initializes a link inside LoginView1
}

Ok, I think that does it. I feel better about a more qualified / constrained approach too.

With this qualification, I got the initialization on the links I needed, and didn’t interfere with the drop down lists that were initialized once and then needed to remain populated. I didn’t find this anywhere, and so I am hoping that it will save someone the couple hours I spent.

Happy coding!

This was a weird issue that a coworker had that I thought I would re-post so others (and I) could find it easily when it comes up again. We were adding a report via the report wizard. Visual Studio (apparently) attempts to load the data sources you may have sitting in your Bin folder. If it cannot load one of those (for some reason), it will fail to bring up the report wizard (where you may be creating a new data source anyway).

ReportWizardError

The solution feels a lot like a hack (but this is Microsoft, right – comes with the territory).

Rename your Bin folder, then run your wizard, then rename it back.

Just wow.

I got this solution from here.

LinqPad – Get Pdf from binary column

A friend asked me to share this technique (which rocks!) for a simple way to pull a pdf from a table without writing an application to do it. It has saved me a lot of time when I need to get to a stored pdf quickly.

LinqPad (which if you do any Linq, and in this case even if you just need to get to a binary object) is a must-have program that allows you to do this.

Here is the simple code snippet that pulls the pdf, saves it to a file, and opens it. You have to connect your database on the top right, and select “C# Statements” in the middle drop down list:

string id = "60821 003";
string dir = "C:\\TempDocs";

// create output directory
Directory.CreateDirectory(dir);

// create output filename
string outputPDFFile = Path.Combine(dir, id + ".pdf");

// find the record we want (you have to be connected 
// to the database you want to search, and
// PDFDocuments below must match the table you are pulling data from
var mypdf = (from q2 in PDFDocuments where q2.PrintBatchId == id select q2);

// above returns only one record, so below I use SingleOrDefault to get that record.
// otherwise here you could iterate through the records...
// the ".Pdf portion pf this is the column name of the pdf binary data in the table
File.WriteAllBytes(outputPDFFile, mypdf.SingleOrDefault().Pdf.ToArray());

// this part opens up the pdf for viewing / verifying I have the right one
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.EnableRaisingEvents = false;
proc.StartInfo.FileName = outputPDFFile;
proc.Start();

Have fun!

WebMatrix Deployment

I have been noodling with MVC3 / cshtml / Razor, and I put together a web site and tried to deploy it. I was using the WebSecurity that was nicely integrated into the default web site that I started with, and was delighted about how easy it was to implement. With a few hours of work, I had a site that was performing registration, adding users to my database, emailing for confirmation and I didn’t write any of that code! Sweet. Let’s deploy. Then, ugh, an error.

Server Error in ‘/’ Application.


Configuration Error

Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.

Parser Error Message: The connection name ‘LocalSqlServer’ was not found in the applications configuration or the connection string is empty.

Source Error:

Line 238: <membership> Line 239: <providers> Line 240: <add name=”AspNetSqlMembershipProvider” type=”System.Web.Security.SqlMembershipProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a” connectionStringName=”LocalSqlServer” enablePasswordRetrieval=”false” enablePasswordReset=”true” requiresQuestionAndAnswer=”true” applicationName=”/” requiresUniqueEmail=”false” passwordFormat=”Hashed” maxInvalidPasswordAttempts=”5″ minRequiredPasswordLength=”7″ minRequiredNonalphanumericCharacters=”1″ passwordAttemptWindow=”10″ passwordStrengthRegularExpression=”” />  Line 241: <add name=”MySQLMembershipProvider” type=”MySql.Web.Security.MySQLMembershipProvider, MySql.Web, Version=6.3.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d” connectionStringName=”LocalMySqlServer” enablePasswordRetrieval=”false” enablePasswordReset=”true” requiresQuestionAndAnswer=”true” applicationName=”/” requiresUniqueEmail=”false” passwordFormat=”Clear” maxInvalidPasswordAttempts=”5″ minRequiredPasswordLength=”7″ minRequiredNonalphanumericCharacters=”1″ passwordAttemptWindow=”10″ passwordStrengthRegularExpression=”” /> Line 242: </providers>


Source File: C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config    Line: 240


Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.272

I started immediately looking for an entry possibly added by WebMatrix. But there was none referencing AspNetSqlMembershipProvider, or LocalSqlServer. Then I noticed that this reference was in the machine.config of the server. Well, this is not my server, so I contacted support to ask them about it. They promptly and courteously told me that they did not solve programming questions. OK, on my own – no big surprise there. But I thought it might be a normal “gotcha” that lots of people run into. Well, it is… Here is what needs to happen:

First the reference is partially right. You DO need to have this reference in place, however the machine config does not know where your site has put the Membership info. So you have to replace it. Use this:

<connectionStrings>
<clear />
<add name=”myDB” providerName=”System.Data.SqlClient”
connectionString=”Data Source=someserver.com;Initial Catalog=myDB;User ID=myDB_user;Password=’xxxxx’;Integrated Security=False;” />
<remove name=”LocalSqlServer” />
<add name=”LocalSqlServer” providerName=”System.Data.SqlClient”
connectionString=”Data Source=someserver.com;Initial Catalog=myDB;User ID=myDB_user;Password=’xxxxx’;Integrated Security=False;” />
</connectionStrings>

Of course replace the database details with your own.

Once this was in place, I ran it again and got the following error:

Server Error in ‘/’ Application.


The Role Manager feature has not been enabled.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Configuration.Provider.ProviderException: The Role Manager feature has not been enabled.

Source Error:

Line 3: var providerName = “System.Data.SqlClient”; Line 4: //var db = Database.OpenConnectionString(connectionString, providerName); Line 5: WebMatrix.WebData.WebSecurity.InitializeDatabaseConnection (connectionString, providerName, Line 6: “UserProfile”, “UserId”, “Email”, true); Line 7:


Source File: e:\web\myWeb\_AppStart.cshtml    Line: 

It is now looking at my (mind you WORKING LOCALLY 🙂 ) init and saying it is failing. To be honest, since this is new tech for me, I wasn’t sure if I should be enabling the role manager, or if I had enabled something that was adding a new / different security setting that would cause some conflict. With a bit more research (Googling WebSecurity and Role Manager), I saw that the WebSecurity uses the Role Manager in “SimpleMembership” mode. OK, so this is needed and probably ok.

But I don’t need the AspNetSqlMembershipProvider… So I removed it (with the <clear/> below):

Inside the System.Web section of my web.config:

<membership defaultProvider=”SimpleMembershipProvider”>
<providers >
<clear/>
<add name=”SimpleMembershipProvider” type=”WebMatrix.WebData.SimpleMembershipProvider,WebMatrix.WebData”/>
</providers>
</membership>

Then I got the error:

Server Error in ‘/’ Application.


Default Membership Provider must be specified.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Configuration.Provider.ProviderException: Default Membership Provider must be specified.

With a little more digging, I found that this entry in the appSettings section will take care of that issue.

<add key=”enableSimpleMembership” value=”true” />

I hope this helps someone make a few less round trips searching!

Peace…

Helpful Links for this issue:

http://stackoverflow.com/questions/3874279/the-role-manager-feature-has-not-been-enabled

http://forums.asp.net/t/1695156.aspx/1?WebSecurity+in+MVC

https://forums.iis.net/p/1188577/2018786.aspx

Windows Service testing

This is a handy way to test your windows service; something I have been doing for awhile. I was looking at it recently, and thought it might be handy for someone else:

public static class Program
{
///
/// The main entry point for the application. /// 

public static void Main()
{
#if (!DEBUG)
  ServiceBase[] ServicesToRun;
  ServicesToRun = new ServiceBase[] { new MyWinService() };
  ServiceBase.Run(ServicesToRun);
#else
  //Debug code: this allows the process to run 
  // as a non-service. It will kick off the
  // service start point, and then run the 
  // sleep loop below.
  MyWinService service = new MyWinService();
  service.Start();
  // Break execution and set done to true to run Stop()
  bool done = false;
  while (!done)
   Thread.Sleep(10000);
  service.Stop();
#endif
}

By using this approach, you can compile a release version of the service that runs like a service, and while debugging, you can run the loop in the debug section that allows you to break and set done and fully test your startup and shutdown code.

HTH,

Robb

Migrating to TFS 2010 from TFS 2008

This is a quick summary of our experiences moving from TFS 2008 to TFS 2010.

If you are like us (and many others) out there, you are building an msi to deploy your projects and you are using TFS to do it. We had to run DevEnv in our build script to accomplish this because MSBuild does not support the web deployment project and will give you a warning that it is skipped if you have it included in a solution that is sent to build.

In VS 2008, you can accomplish this in your build script, and it is a bit messy, but works (it also builds the entire solution twice, ugh!). I am not going to go into those details, but you can find more here and here.

So we created a new branch in TFS 2010 and brought over the code we are migrating and first I ran the build using the same TFS 2005 script that we have been using (in 2005 and 2008). This was a tfsbuild.proj file. To do this I used the 2010 build xaml file that reads in this tfsbuild.proj script called upgradetemplate.xaml.

This worked after a few config changes (we had shortened the names of some of the default configuration values in the build config because of the visual studio – MSBuild directory structure limit workarounds.

The build worked and then we migrated the solution to VS 2010.

This worked with only a few quirks where VS 2010 forced some projects to be upgraded and would not load them otherwise because of version mismatches. We also found out Test Projects in Visual Studio 2010 Must Target .NET Framework 4.

So I got the .Net framework versions all happy with one another and then the project built locally on my dev box.

We started out assuming that we could not use Web Deployment projects in VS 2010, and started looking at alternatives. There are mixed messages out there. But a coworker found this:

Download details: Visual Studio® 2010 Web Deployment Projects – RTW

This is a fix that adds the Web Deployment Project back into VS 2010 allowing us to still build our msi file from DevEnv. This allowed us to use the script that calls DevEnv pointing to the VS 2010 installation on the build server.

So I sent it off to the build server. Success! That wasn’t so bad… Now for conversion to the defaultTemplate.xaml that would allow us to use the nifty build workflow UI.

I followed the instructions for Building Visual Studio Setup Projects with TFS 2010 Team Build. This was very helpful in putting this together initially and I had a hard time finding it, so here is one more reference for you all.

When I started the build, it came back almost immediately with: The path … is already mapped in workspace VMLSBUILD_6_1.

This was an interesting one. It turns out that there are caches of the workspaces and while TFSBuild 2008 didn’t seem to mind, TFS2010 did. When I ran Team Foundation Sidekicks to see what the issue was, I found a lot of residual workspaces – some years old – that were just hanging out there. For some it is not as simple as my fix, but all I had to do was delete the workspaces and I was back in business.

You can also view your workspaces by running this from the Visual Studio Command Line on the box that contains the build workspaces:

tf workspaces /owner:* /computer:”BUILDCOMPUTERNAME” /s:”http://yourTFSServerURL&#8221;

OK, kicked the build off again…

Then I ran into the error: “Package ‘Microsoft.VisualStudio.TestTools.TestCaseManagement.QualityToolsPackage, Microsoft.VisualStudio.QualityTools.TestCaseManagement, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’ failed to load.” This is a pain, but the workaround is not so bad:

Package Microsoft.VisualStudio.QualityTools.TestCaseManagement failed to load in Team Build 2010. | // TODO: name this blog

Thanks to Scott for that – it was a simple solution once you saw it, but I hadn’t thought of it.

One more time to the build, and we were successful.

Edit / Note: The above fix does not guarantee that this issue doesn’t come up, but instead is a symptom of other build issues in DevEnv.com. If this error is encountered, as the blog states, you have to dig  into the log  and see what the true issue is. I  have not found a good way to reflect the true error out to the build, but at least you have a way to get to it.

Hopefully this helps out someone who is doing the same as we are. Peace…

A few more links:

TFPT Error: Unable to determine the workspace – Ozzie Rules Blogging – Site Home – MSDN Blogs

Workspaces Command

WCF – ____ is already defined.

This drove me crazy for a several hours. Turned out the solution was simple. Again MS has limitations that don’t allow combinations of input / output. YOu have either use wrappers or no wrappers. It seems like I have seen implementations where this limit did not exist, but putting wrappers (reauest / response) around my new entry points fixed the issue.

More info at stack overflow:

wcf – Add Service Reference “___ is already defined”a – Stack Overflow

 

TFS Alternative to Cloaking – shorten build base path

I was facing yet another [ProjectName] “contains more than the allowed 259 characters. Type or select a shorter path.”

I have learned how to cloak these entries when they are not needed for the build I am doing, and we have also resorted to shortening the path names of some so that we can include them. But our base folders were pretty long so I decided to try and change them. I googled for the $(SourceDir) entry and found a couple of helpful articles:

tfs – How do I change the build directory that MSBuild uses under Team Foundation Build? – Stack Overflow

TFS Top Tip #16 – Limit What you Build – Martin Woodward

From these I was able to change the entries in the config and Build Agent settings that would help me to shorten the path to something that would stop the madness of cloaking and avoid the above error (until we go above the limit again).

Here is what I did (this is all VS and TFS 2008):

I went to the Team Explorer in Visual Studio and right clicked on Builds and selected

I then inside the the manage selected my (only) build agent and got the window below:

Changing this from e:\teambuild\projects (which was a decent naming convention) to the shortened E:\Bld saved us 15 characters which solved a bunch of path length issues.

In addition, I changed the default “Sources” in the file

c:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\tfsbuildservice.exe.config

from <add key=”SourcesSubdirectory” value=”Sources” />

to <add key=”SourcesSubdirectory” value=”Src” />

saving me an additional 4 characters for a full 19 characters of shortening.

This seems very silly in a world where we are trying to be more descriptive and I hope that MS will eventually let us do as we please with our file and folders, but it saved us some hassle and maybe it will save you some too.

Worker Thread Class

In an article by Juval Löwy, he does a great job of describing and providing an example of a worker thread class. Since many of us are not yet able to pick up .Net 4, we do not yet have the threading beauty that apparently awaits us there. So I adopted this worker thread and made a few changes that fill a few gaps for me. The listing is below along with comments where I made changes to Juval’s original work.

 /// <summary>
 /// Thread mgmt wrapper class - base code taken from devx.com article by Juval Löwy
 /// Added mutex and exception string to allow exception info to be stored and passed out from thread.
 /// Also added ability to pass in delegate that is run as the worker thread function, and some
 /// additional ways to construct.
 /// Added a mutex and wrapped it in a contained class to pass into the worker so that they can monitor
 /// the EndLoop value. I also added a passthrough object to this class so that the worker can take in
 /// an object when it starts and pass one back out when it is done.
 /// Also found a race condition for a test that Juval was doing on the IsAlive when it asserted that
 /// the handle could not be same value as isalive, but when function is done and closing,
 /// this value could be set right at the end and isalive not yet unset. I changed it to a definite
 /// test - that the handle is set when isalive is false. This must be true, since the thread has to exit
 /// that way (unless someone crawls in and kills it which this wrapper is supposed to allow you to avoid
 /// completely).
 /// </summary>
public class WorkerThread : IDisposable
 {
 /// <summary>
 /// Thread function passing ref to Thread Objects so we can:
 /// 1. check to see if we're done, and
 /// 2. Pass in or out values to / from the thread.
 /// </summary>
 public delegate void ThreadFunc(ThreadObjects threadObjects);

 /// <summary>The <see cref="ThreadFunc"/> delegate.</summary>
 protected ThreadFunc threadFunc = null;

 /// <summary>The <see cref="ManualResetEvent"/> m_WorkerStartedEvent - that is reset when the worker thread starts its task.</summary>
 protected ManualResetEvent m_WorkerStartedEvent;
 /// <summary>ManualResetEvent m_WorkerDoneEvent - reset when the worker thread has completed its task.</summary>
 protected ManualResetEvent m_WorkerDoneEvent;
 /// <summary>The <see cref="ManualResetEvent"/> m_WorkerExceptionEvent - reset when an exception occurs</summary>
 protected ManualResetEvent m_WorkerExceptionEvent;

 /// <summary>The System thread that we are using to implement our worker thread</summary>
 protected Thread m_ThreadObj;

 /// <summary>holds the objects used to initialize, communicate with, and pull data back from the worker thread.</summary>
 protected ThreadObjects m_mutexedObjects;

 /// <summary>
 /// This object is passed into the worker so it can monitor when to stop,
 /// and to get / set the passthrough object
 /// </summary>
 public class ThreadObjects
 {
 /// <summary>if true tells thread to stop processing (must be processed by the worker thread user code)</summary>
 protected bool _mEndLoop;
 /// <summary>controls access to m_endloop</summary>
 protected Mutex _endLoopMutex;

 /// <summary>used to pass data into and out of the worker thread</summary>
 protected object _mPassThrough;
 /// <summary>controls access to the passthrough data</summary>
 protected Mutex _mPassThroughMutex;

 /// <summary>
 /// Initializes a new instance of the <see cref="ThreadObjects"/> class.
 /// Creates the mutexes.
 /// </summary>
 public ThreadObjects()
 {
 _endLoopMutex = new Mutex();
 _mPassThroughMutex = new Mutex();
 }
 /// <summary>
 /// Gets or sets a value indicating whether the worker thread should stop processing.
 /// This is initially set false and then set to true by the caller to tell the worker
 /// thread to stop. The worker thread function should check this value periodically so
 /// that the thread can be shutdown gracefully.
 /// </summary>
 /// <value><c>true</c> if processing should stop; otherwise, <c>false</c>.</value>
 public bool EndLoop
 {
 set
 {
 _endLoopMutex.WaitOne();
 _mEndLoop = value;
 _endLoopMutex.ReleaseMutex();
 }
 get
 {
 bool result = false;
 _endLoopMutex.WaitOne();
 result = _mEndLoop;
 _endLoopMutex.ReleaseMutex();
 return result;
 }
 }

 /// <summary>
 /// Gets or sets an object value that the worker thread can use or set.
 /// It is recommended that this only be set before starting the thread by the caller
 /// and that it be checked by the caller only after the thread is complete. Otherwise the
 /// values are possibly unreliable and require careful management.
 /// For instance, this could be used to hold an array of strings indicating the status of
 /// a thread that cyclically performs a task. The Thread could keep it updated and
 /// delete old info out of it when it has new and keep just the last 20 events in there
 /// so a status monitor could check out whats happening from time to time without
 /// forcing the thread to stop and restart.
 /// </summary>
 /// <value>Any value that the caller / worker wishes to pass through.</value>
 public object PassThrough
 {
 set
 {
 _mPassThroughMutex.WaitOne();
 _mPassThrough = value;
 _mPassThroughMutex.ReleaseMutex();
 }
 get
 {
 object result = "";
 _mPassThroughMutex.WaitOne();
 result = _mPassThrough;
 _mPassThroughMutex.ReleaseMutex();
 return result;
 }
 }

 internal void Close()
 {
 _endLoopMutex.Close();
 _mPassThroughMutex.Close();
 }

 private string _name = "";
 /// <summary>Gets or sets the name of the thread.</summary>
 public string Name { get { return _name; }  set { _name = value; } }
 }

 /// <summary>
 /// Gets or sets a value indicating whether the worker thread should stop processing.
 /// This is initially set false and then set to true by the caller to tell the worker
 /// thread to stop. The worker thread function should check this value periodically so
 /// that the thread can be shutdown gracefully.
 /// </summary>
 /// <value><c>true</c> if processing should stop; otherwise, <c>false</c>.</value>
 public bool EndLoop
 {
 get { return m_mutexedObjects.EndLoop; }
 set { m_mutexedObjects.EndLoop = value; }
 }

 /// <summary>
 /// Gets or sets an object value that the worker thread can use or set.
 /// It is recommended that this only be set before starting the thread by the caller
 /// and that it be checked by the caller only after the thread is complete. Otherwise the
 /// values are possibly unreliable and require careful management.
 /// For instance, this could be used to hold an array of strings indicating the status of
 /// a thread that cyclically performs a task. The Thread could keep it updated and
 /// delete old info out of it when it has new and keep just the last 20 events in there
 /// so a status monitor could check out whats happening from time to time without
 /// forcing the thread to stop and restart.
 /// </summary>
 /// <value>Any value that the caller / worker wishes to pass through.</value>
 public object PassThrough
 {
 get { return m_mutexedObjects.PassThrough; }
 set { m_mutexedObjects.PassThrough = value; }
 }

 /// <summary>
 /// Gets the ThreadState of the thread.
 /// </summary>
 /// <value>The <see cref="System.Threading.ThreadState"/> of the underlying thread.</value>
 public ThreadState State { get { return m_ThreadObj.ThreadState; } }

 /// <summary>Holds the exception details (if any) when an exception is generated in the thread so
 /// that it can be picked up by the thread that started this worker.</summary>
 protected string m_ExceptionInfo;

 /// <summary>controls access to the exception info</summary>
 protected Mutex m_ExceptionInfoMutex;

 /// <summary>Gets the thread being managed.</summary>
 public Thread Thread{get{return m_ThreadObj;}}

 /// <summary>
 /// Gets or sets the exception info. A holding place for any exception that occurs in the thread.
 /// It will contain whatever string the worker function puts in it (i.e. message, stack, etc.).
 /// Generally this should be an empty string unless there is an exception, thus allowing the
 /// caller to be able to determine if a thread processed successfully.
 /// </summary>
 /// <value>The exception info, or an empty string if there was no exception.</value>
 public string ExceptionInfo
 {
 set
 {
 m_ExceptionInfoMutex.WaitOne();
 m_ExceptionInfo = value;
 m_ExceptionInfoMutex.ReleaseMutex();
 }
 get
 {
 string result = "";
 m_ExceptionInfoMutex.WaitOne();
 result = m_ExceptionInfo;
 m_ExceptionInfoMutex.ReleaseMutex();
 return result;
 }
 }

 /// <summary>
 /// Gets the generated thread name using the namespace and the current system
 /// ticks. It does not need to be unique, but we make it so in order to tell
 /// threads apart (since they were not explicitly named).
 /// </summary>
 /// <value>The name of the generated thread.</value>
 static string GenThreadName { get { return typeof(WorkerThread).FullName + DateTime.Now.Ticks.ToString(); } }

 /// <summary>
 /// Initializes a new instance of the <see cref="WorkerThread"/> class
 /// using a <see cref="ThreadFunc"/> delegate and a thread name.
 /// </summary>
 /// <param name="threadFuncIn"><see cref="ThreadFunc"/> delegate
 /// passes an object that allows the worker function to get
 /// input and/or set a result, and to monitor if the caller
 /// has requested that the worker stop processing.
 /// </param>
 /// <param name="threadName">Name of the thread. If this is made meaningful, then
 /// it makes debugging easier, so it is recommended that it be set accordingly.</param>
 public WorkerThread(ThreadFunc threadFuncIn, string threadName)
 {
 m_mutexedObjects = new ThreadObjects();
 m_mutexedObjects.Name = threadName;
 m_mutexedObjects.EndLoop = false;
 m_ThreadObj = null;
 m_ExceptionInfo = "";
 m_ExceptionInfoMutex = new Mutex();
 m_WorkerStartedEvent = new ManualResetEvent(false);
 m_WorkerDoneEvent = new ManualResetEvent(false);
 m_WorkerExceptionEvent = new ManualResetEvent(false);
 threadFunc = threadFuncIn;
 ThreadStart threadStart = new ThreadStart(Worker);
 m_ThreadObj = new Thread(threadStart);
 m_ThreadObj.Name = threadName;
 }

 /// <summary>
 /// Initializes a new instance of the <see cref="WorkerThread"/> class
 /// using a <see cref="ThreadFunc"/> delegate. The thread name is generated
 /// using <see cref="GenThreadName"/> which grabs the full name of the WorkerThread type and
 /// appends the system clock ticks.
 /// </summary>
 /// <param name="threadFunc"><see cref="ThreadFunc"/> delegate
 /// passes an object that allows the worker function to get
 /// input and/or set a result, and to monitor if the caller
 /// has requested that the worker stop processing.
 /// </param>
 public WorkerThread(ThreadFunc threadFunc) : this(threadFunc, GenThreadName)
 {
 }

 /// <summary>
 /// Initializes a new instance of the <see cref="WorkerThread"/> class.
 /// </summary>
 /// <param name="autoStart">if set to <c>true</c> if the thread should start
 /// as soon as it is set up. The thread name is generated
 /// using <see cref="GenThreadName"/> which grabs the full
 /// name of the WorkerThread type and appends the system clock ticks.</param>
 /// <param name="threadFunc"><see cref="ThreadFunc"/> delegate
 /// passes an object that allows the worker function to get
 /// input and/or set a result, and to monitor if the caller
 /// has requested that the worker stop processing.
 /// </param>
 public WorkerThread(bool autoStart, ThreadFunc threadFunc)
 : this(autoStart, threadFunc, GenThreadName)
 {
 }

 /// <summary>
 /// Initializes a new instance of the <see cref="WorkerThread"/> class.
 /// </summary>
 /// <param name="autoStart">if set to <c>true</c> if the thread should start
 /// as soon as it is set up. The thread name is generated
 /// using <see cref="GenThreadName"/> which grabs the full
 /// name of the WorkerThread type and appends the system clock ticks.</param>
 /// <param name="threadFunc"><see cref="ThreadFunc"/> delegate
 /// passes an object that allows the worker function to get
 /// input and/or set a result, and to monitor if the caller
 /// has requested that the worker stop processing.
 /// </param>
 /// <param name="threadName">Name of the thread. If this is made meaningful, then
 /// it makes debugging easier, so it is recommended that it be set accordingly.</param>
 public WorkerThread(bool autoStart, ThreadFunc threadFunc, string threadName)
 : this(threadFunc, threadName)
 {
 if (autoStart)
 {
 Start();
 }
 }

 /// <summary>
 /// This <see cref="WaitHandle"/> is used to indicate that the thread worker has started.
 /// It is set at the beginning of the thread function inside the WorkerThread class, and
 /// verified in the IsAlive, that if the thread is dead, that this handle got set.
 /// If not, an exception is thrown.
 /// See also <seealso cref="WorkerDoneHandle"/> and <seealso cref="WorkerExceptionHandle"/>
 /// </summary>
 /// <value>The handle.</value>
 public WaitHandle WorkerStartedHandle
 {
 get
 {
 return m_WorkerStartedEvent;
 }
 }

 /// <summary>
 /// This <see cref="WaitHandle"/> is used to indicate that the thread worker has finished.
 /// It is set at the end of the thread function inside the WorkerThread class, and
 /// verified in the IsAlive, that if the thread is dead, that this handle got set.
 /// If not an exception is thrown.
 /// See also <seealso cref="WorkerStartedHandle"/> and <seealso cref="WorkerExceptionHandle"/>
 /// </summary>
 /// <value>The handle.</value>
 public WaitHandle WorkerDoneHandle
 {
 get
 {
 return m_WorkerDoneEvent;
 }
 }

 /// <summary>
 /// This <see cref="WaitHandle"/> is used to indicate that the thread worker terminated in an exception state.
 /// It is set if an exception is caught in the wrapper worker function.
 /// See also <seealso cref="WorkerStartedHandle"/> and <seealso cref="WorkerDoneHandle"/>
 /// </summary>
 /// <value>The handle.</value>
 public WaitHandle WorkerExceptionHandle
 {
 get
 {
 return m_WorkerExceptionEvent;
 }
 }

 /// <summary>
 /// Starts the thread after checking that it is currently instantiated and
 /// is not alive. This is called automatically if autostart is set in the
 /// call to the constructor.
 /// </summary>
 public void Start()
 {
 if(m_ThreadObj == null)
 throw new NullReferenceException("Start called on null thread object.");

 if(m_ThreadObj.IsAlive)
 throw new ThreadStateException("Start called on thread that is already running.");

 m_ThreadObj.Start();
 }

 /// <summary>
 /// If object is being disposed, this function will ensure that the thread is killed.
 /// Moved the close handles to this function from Kill, because we may still want to use these
 /// values after killing the thread to check on what happened.
 /// </summary>
 public void Dispose()
 {
 Kill();
 m_mutexedObjects.Close();
 m_WorkerStartedEvent.Close();
 m_WorkerDoneEvent.Close();
 m_WorkerExceptionEvent.Close();
 }

 /// <summary>
 /// Kills this thread. First it checks to see if we have a thread and if it is currently
 /// alive. If not, the function returns without doing anything. Otherwise, EndLoop is set,
 /// and it waits using a Join for the thread to die. If the thread won't die after the allotted time,
 /// then the thread is aborted. THe called thread should never require this of the caller, but
 /// in some cases, since we are calling code that is unmanaged and outside of our control,
 /// we may have threads that are hung. Thus the thread should have resource freeing coded into
 /// the catch handler of the thread function.
 /// </summary>
 public void Kill(TimeSpan timeout)
 {
 //Kill is called on client thread - must use cached object
 if (m_ThreadObj == null) // thread is not there - leave it
 return;

 if (IsAlive == false)
 return;

 m_mutexedObjects.EndLoop = true;
 //Wait for thread to die
 Join(timeout);

 if (m_ThreadObj.IsAlive == true)
 {    // this thread refuses to die and we gave it 2 minutes - abort.
 m_ThreadObj.Abort(); // send abort Exception
 }
 }

 /// <summary>
 /// Kills this thread. First it checks to see if we have a thread and if it is currently
 /// alive. If not, the function returns without doing anything. Otherwise, EndLoop is set,
 /// and it waits using a Join for the thread to die.
 /// </summary>
 public void Kill()
 {
 Kill(new TimeSpan(0, 2, 0));
 }

 /// <summary>
 /// Joins thread - if thread is already dead, it returns, otherwise it waits on the thread to die.
 /// </summary>
 public void Join()
 {
 if (m_ThreadObj == null) // thread is not there - leave it
 return;

 if (IsAlive == false)
 return;

 Debug.Assert(Thread.CurrentThread.GetHashCode() !=
 m_ThreadObj.GetHashCode());

 m_ThreadObj.Join();
 }

 /// <summary>
 /// Joins with the specified milliseconds timeout.
 /// </summary>
 /// <param name="millisecondsTimeout">The milliseconds timeout.</param>
 /// <returns></returns>
 public bool Join(int millisecondsTimeout)
 {
 TimeSpan timeout = TimeSpan.FromMilliseconds(millisecondsTimeout);

 return Join(timeout);
 }

 /// <summary>
 /// Joins with the specified timeout.
 /// </summary>
 /// <param name="timeout">The timeout.</param>
 /// <returns></returns>
 public bool Join(TimeSpan timeout)
 {
 if (m_ThreadObj == null) // thread is not there - leave it
 return true;

 if (IsAlive == false)
 return true;

 if (Thread.CurrentThread.GetHashCode() == m_ThreadObj.GetHashCode())
 throw new Exception("Attempting to Join a thread that has the same identity as the current thread.");

 return m_ThreadObj.Join(timeout);
 }

 /// <summary>
 /// Gets or sets the name of the thread.
 /// </summary>
 /// <value>The name of the thread.</value>
 public string Name { get { return m_ThreadObj.Name; } set { m_ThreadObj.Name = value; } }

 /// <summary>
 /// Gets a value indicating whether the worker thread is alive.
 /// </summary>
 /// <value><c>true</c> if the worker thread is alive; otherwise, <c>false</c>.</value>
 public bool IsAlive
 {
 get
 {
 Debug.Assert(m_ThreadObj != null);
 bool isAlive = m_ThreadObj.IsAlive;
 return isAlive;
 }
 }

 /// <summary>
 /// Worker runs the function that was passed in wrapped by an exception handler.
 /// If the function being called has any issues the exception is caught
 /// and the exception message is put into a string along with the thread name,
 /// call stack and any inner exceptions for access by the caller / creator of the thread.
 /// </summary>
 protected void Worker()
 {
 try
 {
 if (threadFunc != null)
 {
 m_WorkerStartedEvent.Set(); // indicate that we have started
 threadFunc.Invoke(m_mutexedObjects);
 }
 else
 throw new NullReferenceException("WorkerThread function expected.");
 }
 catch(Exception ex)
 {
 string exInfo = ex.Message;
 ExceptionInfo = Thread.CurrentThread.Name + " exception:" + exInfo;
 m_WorkerExceptionEvent.Set();
 }
 finally
 {
 m_WorkerDoneEvent.Set();
 }
 }
 }