Category Archives: C#

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!

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!

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

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();
 }
 }
 }

Email with attachment from byte array

How to Send Email with Attachment using ASP.NET 2.0 and C#

This article tells how to send an email with an attachment. I made a few modifications to make it work because I had to attach a byte array that came from a database. So this is how you do that:


void SendEmail()
{
List<String> recipientList = GetEmailAddressList();

SmtpClient client = new SmtpClient(GetSMTPServer(), GetSMTPPort());

MailAddress from = new MailAddress(ConfigurationManager.AppSettings["EmailContacts.From"]);

 if (recipientList.Count == 0)
 {
 AddError("no email addresses found.");
 return;
 }

 MailMessage message = new MailMessage();
 message.From = from;
 foreach (string to in recipientList)
 {
 message.To.Add(to);
 }

 //create the message
 message.Body = "A new file is attached for your review.";

 message.BodyEncoding = Encoding.UTF8;

 // Get pdf binary data and save the data to a memory stream
 System.IO.MemoryStream ms = new System.IO.MemoryStream(GetPdf());

 // Create the attachment from a stream. Be sure to name the data with a file and
 // media type that is respective of the data
 message.Attachments.Add(new Attachment(ms, "myFile.pdf", "application/pdf"));

 message.Subject = "New File for Review";

 //send it
 client.Send(message);
}

Tony Sneed’s Blog -> Michael C. Kennedy’s Weblog -> Facebook C# SDK

This:

Using Open Source? Get NuGet. | Tony Sneed’s Blog

has a reference to this:

Michael C. Kennedy’s Weblog – 11 Killer Open Source Projects I Found with NuGet

which has a reference to this:

Facebook C# SDK

which looks extermely cool and useful. More as I dig in.

Thanks Tony!

 

Nicely written post extending the MSDN audio CD writing sample to make it actually write CDs.

Once I have implemented this, I will update with feedback.

C# Audio CD Writer for Windows XP – Sichbo Interactive

 

Using Open Source? Get NuGet. | Tony Sneed’s Blog

 

Cropper

Cropper. Free SnagIt alternative with source code – worth a look… Does what you wish Print Screen would do.

Getting the Rolling Log File Setting from your app.config

I couldn’t find an easy way to retrieve the log file location setting from the rolling log file settings in my Logging Application Block settings and after writing a query at a few places, decided that I would have to do it by reading the XML and parsing through to the log setting.

It was not too difficult, but I figured I would post it here so I could remember what I did and for others to find…

Here is a simple form that finds and lists the rolling log file name (you must put a copy of your config file into the bin\debug folder and name it “configData.xml” where this little program runs in order for it to find it):

using System;
using System.Windows.Forms;
using System.Xml.XPath;

namespace GetTheRollingLogFiles
{
 /// <summary>
 /// Summary description for Form1.
 /// </summary>
 public class Form1 : System.Windows.Forms.Form
 {
 private System.Windows.Forms.Button button1;
 private System.Windows.Forms.ListBox listBox1;
 /// <summary>
 /// Required designer variable.
 /// </summary>
 private System.ComponentModel.Container components = null;

 public Form1()
 {
 // Required for Windows Form Designer support
 InitializeComponent();
 // TODO: Add any constructor code after InitializeComponent call
 }

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

 #region Windows Form Designer generated code
 /// <summary>
 /// Required method for Designer support - do not modify
 /// the contents of this method with the code editor.
 /// </summary>
 private void InitializeComponent()
 {
 this.button1 = new System.Windows.Forms.Button();
 this.listBox1 = new System.Windows.Forms.ListBox();
 this.SuspendLayout();
 //
 // button1
 //
 this.button1.Location = new System.Drawing.Point(12, 12);
 this.button1.Name = "button1";
 this.button1.Size = new System.Drawing.Size(152, 24);
 this.button1.TabIndex = 0;
 this.button1.Text = "GO!";
 this.button1.Click += new System.EventHandler(this.button1_Click);
 //
 // listBox1
 //
 this.listBox1.Location = new System.Drawing.Point(12, 42);
 this.listBox1.Name = "listBox1";
 this.listBox1.Size = new System.Drawing.Size(428, 433);
 this.listBox1.TabIndex = 1;
 //
 // Form1
 //
 this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
 this.ClientSize = new System.Drawing.Size(455, 502);
 this.Controls.Add(this.listBox1);
 this.Controls.Add(this.button1);
 this.Name = "Form1";
 this.Text = "Form1";
 this.Load += new System.EventHandler(this.Form1_Load);
 this.ResumeLayout(false);

 }
 #endregion

 /// <summary>
 /// The main entry point for the application.
 /// </summary>
 [STAThread]
 static void Main()
 {
 Application.Run(new Form1());
 }

 private void button1_Click(object sender, System.EventArgs e)
 {
 listBox1.Items.Clear();

 string fileName = "configData.xml";
 XPathDocument doc = new XPathDocument(fileName);
 XPathNavigator nav = doc.CreateNavigator();

 // Compile a standard XPath expression
 XPathExpression expr;
 expr = nav.Compile("/configuration/loggingConfiguration/listeners/*");
 XPathNodeIterator iterator = nav.Select(expr);

 // Iterate on the node set
 listBox1.Items.Clear();
 try
 {
 while (iterator.MoveNext())
 {
 XPathNavigator nav2 = iterator.Current.Clone();
 string rollingLogFileName = "";
 listBox1.Items.Add(nav2.Name);
 listBox1.Items.Add("HasAttributes: " + nav2.HasAttributes.ToString());
 if (nav2.MoveToFirstAttribute())
 {
 bool isRollingLogConfig = false;
 string fileNameHolder = "";
 while (true)
 {
 listBox1.Items.Add(nav2.Name + ": " + nav2.Value);
 if ((nav2.Name.ToLower() == "type") && nav2.Value.Contains("RollingFlatFileTraceListener"))
 isRollingLogConfig = true;

 if (nav2.Name == "fileName")
 fileNameHolder = nav2.Value;

 if (!nav2.MoveToNextAttribute()) break;
 }
 if (isRollingLogConfig)
 {
 rollingLogFileName = fileNameHolder;
 listBox1.Items.Add("Rolling Log file is: " + rollingLogFileName);
 }
 }
 }
 }
 catch(Exception ex)
 {
 MessageBox.Show(ex.Message);
 }
 }

 private void Form1_Load(object sender, System.EventArgs e)
 {
 }
 }
}