DCOM Network now available on YouTube.

I started a YouTube channel called DCOM Network (DCOM Productions was taken by someone.. grr). However, I am now going to start providing full, high quality 1080p instructional videos and presentations about C# and .NET, and other related technologeis.

I already have two posted up, go check them out and let me know what you think.

Event-based Asynchronous Pattern
http://www.youtube.com/watch?v=3sUZJQKuCkU

Lightweight Conditional Compilation (C#)
http://www.youtube.com/watch?v=jprkQhJF7l8

Math in C# using the Quadratic Formula

namespace QuadraticFunc
{
    using System;
    using System.Diagnostics;

    class Program
    {
        static void Main(string[] args)
        {
            Action<object> Print = (obj) => { Debug.WriteLine(obj.ToString()); };

            // Returns Quadratic (+,-)
            Func<double, double, double, Tuple<double, double>> Quadratic = (a, b, c) => {
                double x1 = (-b + Math.Sqrt((b * b) - ((4 * a) * c))) / (2 * a);
                double x2 = (-b - Math.Sqrt((b * b) - ((4 * a) * c))) / (2 * a);
                return new Tuple<double, double>(x1, x2);
            };

            Print(Quadratic(1, 3, -4));     // (1, -4)
            Print(Quadratic(2, -4, -3));    // (2.58113883008419, -0.58113883008419)
            Print(Quadratic(0, 0, 0));      // (NaN, NaN)

            Tuple<double, double> result = Quadratic(1, 3, -4);
            Print(result.Item1);
            Print(result.Item2);
        }
    }
}

Simple enough. If you want to ensure exact order translate the local variable function Func(Of double,double,double,Tuple(Of double,double)) to an actual member function or static function.

Async, Await, Tasks, and UI synchronization with C# 5, .NET 4.5 and WinForms

I’m going to cover a easy example on the new asynchronous programming model in C# 5 and .NET 4.5 with the recent release of Visual Studio 11. The example we will be writing is a small WinForm that will calculate the square root of a large number while providing progress updates to the UI, and moreso, doing all of this asynchronously, and safely.

The first note is that all this can be done right inside our form class (eg. Form1.cs), so I won’t include a ZIP file or source download, the example should be very straight forward and simple. Let’s dig right in.

To start with, we’re going to create a SynchronizationContext. This part is not anything new, and has been around since .NET 2.0 so I won’t be covering it. In short, it’s just a very helpful object that allows you to perform synchronization between threads or other asynchronous environments. Add a field, and initialize it in the constructor.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        m_SynchronizationContext = SynchronizationContext.Current;
    }

    private SynchronizationContext m_SynchronizationContext;
}

We will be using this to invoke calls to the UI thread safely later on. Next, let’s declare our async method.

private async void ComputeSquareRootAsync(object sender, EventArgs e)
{
    double sqrt = await Task<double>.Run(() =>
    {
        double result = 0;

        for (int i = 0; i < 5000000; i++)
        {
            result += Math.Sqrt(i);
        }

        return result;
   });
}

There are a few things to note here. One, notice the declaration private async void. Here we are telling the compiler that this method will be intrinsically asynchronous, and because the method will contain awaiters, the C# compiler will know to rewrite our method appropriately under the hood.

If you don’t know already, async and await simply work off of the existing Task objects in the framework. By telling the program to await Task.Run, we are saying “Run all code up until this point synchronously, then run the task on a background method, but don’t block the UI, and return control to the caller when the result is returned”. This means that while our Task is running and doing some work off on a background thread, our program will not continue the normal flow of execution until the result is returned, but at the same time will not block the calling context.

Now drag a button onto your form (eg. button1) and set it’s click event to our ComputeSquareRootAsync method. Now drag a label (eg. label1) and a progressbar (eg. progressBar1). Let’s update our method a bit.

private async void ComputeSquareRootAsync(object sender, EventArgs e)
{
    label1.Text = "Calculating sqrt of 5000000";
    button1.Enabled = false;
    progressBar1.Visible = true;

    double sqrt = await Task<double>.Run(() =>
    {
        double result = 0;

        for (int i = 0; i < 5000000; i++)
        {
            result += Math.Sqrt(i);
        }

        return result;
   });

   label1.Text = "The sqrt of 5000000 is " + sqrt;
   button1.Enabled = true;
   progressBar1.Visible = false;
}

Set the label’s initial text in the designer to “Click the button to begin”, and the progress bar’s visiblility to false initially. I also set the button’s text to “Calculate”. This is just cosmetic, but we are making a small, but not really practical, good demo app.

Now what will happen is that the square root will be executed asynchronously while not blocking the UI, but at the same time the last three lines of code that update the controls will not execute until the result is returned (eg. the Task is returned). This is the magic of the new async model.

Let’s implement our progress updates now. To do this, we’re going to implement a new interface onto our form that is provided by .NET 4.5 explicitly for this scenario, and it is called IProgress(Of T).

To make things simple, we will use IProgress(Of Tuple(Of int, int)) (eg. IProgress>) so we can pass in the maximum value and current value of our progress operation (eg. computing the square root).

public partial class Form1 : Form, IProgress<Tuple<int,int>>

Now implement the interface’s Report method.

public void Report(Tuple<int, int> value)
{
    DateTime now = DateTime.Now;

    if ((now - m_PreviousTime).Milliseconds > 20)
    {
        m_SynchronizationContext.Post((@object) =>
        {
            Tuple<int, int> minMax = (Tuple<int, int>)@object;
            progressBar1.Maximum = minMax.Item1;
            progressBar1.Value = minMax.Item2;
        }, value);

        m_PreviousTime = now;
    }
}

Now you will notice one thing off the bat, I included a reference to a DateTime value named m_PreviousTime. Add this as a field in the Form1 class and set its value to DateTime.Now.

private DateTime m_PreviousTime = DateTime.Now;

You could also do that in the constructor where we initialized our synchronization context. The method is simple. We are creating an anonymous function that passes in an object instance of our Tuple as a parameter, which we explicitly convert through an explicit cast. Through the usage of the Post method, it is actually calling this anonymous function on the synchronization context, which is actually our UI thread, thus giving us a safe UI update and no cross-thread violations. This is similar do doing a Control.Invoke, and I suspect somewhere under the hood it may actually do that but I haven’t looked at the implementation yet.

And now we’re done. Here’s the full Form1 class code so you can make sure you implemented all the steps.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Async {
    public partial class Form1 : Form, IProgress<Tuple<int,int>> {
        public Form1() {
            InitializeComponent();
            m_SynchronizationContext = SynchronizationContext.Current;
        }

        private SynchronizationContext m_SynchronizationContext;
        private DateTime m_PreviousTime = DateTime.Now;

        private async void ComputeSquareRootAsync(object sender, EventArgs e) {
            label1.Text = "Calculating Sqrt of 5000000";
            button1.Enabled = false;
            progressBar1.Visible = true;

            double sqrt = await Task<double>.Run(() => {
                double result = 0;

                for (int i = 0; i < 5000000; i++) {
                    result += Math.Sqrt(i);
                    Report(new Tuple<int,int>(5000000, i));
                }

                return result;
            });

            progressBar1.Visible = false;
            button1.Enabled = true;
            label1.Text = "The sqrt of 5000000 is " + sqrt;
        }

        public void Report(Tuple<int, int> value) {
            DateTime now = DateTime.Now;

            if ((now - m_PreviousTime).Milliseconds > 20) {
                m_SynchronizationContext.Post((@object) => {
                    Tuple<int, int> minMax = (Tuple<int, int>)@object;
                    progressBar1.Maximum = minMax.Item1;
                    progressBar1.Value = minMax.Item2;
                }, value);

                m_PreviousTime = now;
            }
        }
    }
}

I may come back and add the source when I have more time.

How to fix Visual Studio Import and Export Settings Dialog when it disappears or crashes when trying to import or export settings.

I am definitely posting about this, because it annoyed the living crud out of me. If you are like me, you often have heavily modified your Visual Studio settings to your likings. This includes environment settings, user settings, and the works.

The Problem
When you go to ‘Tools > Options > Import and Export Settings…’ and you select either Export or Import and click next, the Import and Export Settings Dialog crashes (disappears)!

Cause
This is caused because at some point you imported settings from a non-standard location (eg. MyDocuments\Visual Studio 2010\Settings). What happens is Visual Studio makes some key registry changes that tell devenv.exe how to handle settings going forward. Because of this, it messes with how default settings are handled. The solution is to undo all this to factory settings, which is easily enough done with some registry hacks.

How to resolve this problem

Disclaimer: If you are not comfortable making changes to the Registry, you should try to repair Visual Studio using the Visual Studio Setup. I take no responsibility for problems caused by you editing your Registry, and this is not guarunteed to work for all cases.

Step 1.
1. Navigate to HKEY_CURRENT_USER\SOFTWARE\Microsoft\VisualStudio\10.0\Profile
2. Change the value of AutoSaveFile (REG_SZ) to %vsspv_visualstudio_dir%\Settings\CurrentSettings.vssettings

Step 2.
1. Navigate to HKEY_CURRENT_USER\SOFTWARE\Microsoft\VisualStudio\10.0\Profile\BrowseFiles.
2. Delete all registry values under the above registry key.
3. Create a new REG_DWORD value and set its name to %vsspv_visualstudio_dir%\Settings\CurrentSettings.vssettings.
4. Set the value of the REG_DWORD value you just created to 0×00000001 (1).

Step 3.
1. Navigate to HKEY_CURRENT_USER\SOFTWARE\Microsoft\VisualStudio\10.0\ImportExportSettings\BrowsePaths.
2. Delete all registry values under the above registry key.
3. Create a new REG_DWORD value and set its name to C:\Users\{USER}\Documents\Visual Studio 2010\Settings where {USER} is your Windows User Account name.
4. Set the value of the REG_DWORD value you just created to 0×00000001 (Hex), or 1 (Decimal).

Step 4.
1. Navigate back to HKEY_CURRENT_USER\SOFTWARE\Microsoft\VisualStudio\10.0\Profile
2. Make sure that registry value named DefaultSettingsDirectory has a value of %vsspv_visualstudio_dir%\Settings\

Step 5.
1. Run cmd.exe (does not have to be as administrator
2. Navigate to devenv.exe (eg. cd c:\program files (x86)\microsoft visual studio 10.0\common7\ide)
3. Run the command devenv.exe /ResetSettings

You should now be able to utilize the Import and Export Settings dialog.

FaultTrack Beta 2 Release

Download Url
http://www.dcomproductions.com/products/faulttrack/

Beta 2 includes many performance optimizations, bug fixes, user interface improvements and now works on Windows XP. For original beta users, click ‘Repair FaultTrack’ on the installer and it will update your installation of FaultTrack. To transfer your existing configuration you will also have to move your server.dat, settings.dat, and preferences files to the new storage locations on disk as FaultTrack no longer requires Administrative priviledges to run, it uses proper storage paths in Windows.

servers.dat, settings.dat
Move to Local Application Data.
C:\Users\username\AppData\Local\DCOM Productions\FaultTrack

username.dat
Move to Common Application Data.
C:\ProgramData\DCOM Productions\FaultTrack\Preferences

If the above locations do not exist, you can run FaultTrack and they will be created automatically, or you may create them manually.

Subscribing to DWebBrowserEvents2::FileDownload from WinForms WebBrowser control through the Dynamic Language Runtime (DLR).

I will come back and add more detail to this blog at a later date, but I was helping on MSDN forums and wrote this neat example for someone. It uses the dynamic language runtime and C# 4.0 to take advantage of some of the events exposed by COM through the ActiveXInstance of the WebBrowser control. It intercepts the file download dialog when it detects you downloading an exe file and cancels the download.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Reflection;

namespace WindowsFormsApplication12 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
            webBrowser1.Url = new Uri("http://www.dcomproductions.com/products/faulttrack");
        }

        /// <summary>
        /// Fires before navigation occurs in the given object (on either a window or frameset element).
        /// </summary>
        /// <param name="pDisp">Object that evaluates to the top level or frame WebBrowser object corresponding to the navigation.</param>
        /// <param name="url">String expression that evaluates to the URL to which the browser is navigating.</param>
        /// <param name="Flags">Reserved. Set to zero.</param>
        /// <param name="TargetFrameName">String expression that evaluates to the name of the frame in which the resource will be displayed, or Null if no named frame is targeted for the resource.</param>
        /// <param name="PostData">Data to send to the server if the HTTP POST transaction is being used.</param>
        /// <param name="Headers">Value that specifies the additional HTTP headers to send to the server (HTTP URLs only). The headers can specify such things as the action required of the server, the type of data being passed to the server, or a status code.</param>
        /// <param name="Cancel">Boolean value that the container can set to True to cancel the navigation operation, or to False to allow it to proceed.</param>
        private delegate void BeforeNavigate2(object pDisp, ref dynamic url, ref dynamic Flags, ref dynamic TargetFrameName, ref dynamic PostData, ref dynamic Headers, ref bool Cancel);

        /// <summary>
        /// Fires to indicate that a file download is about to occur. If a file download dialog box can be displayed, this event fires prior to the appearance of the dialog box.
        /// </summary>
        /// <param name="bActiveDocument">A Boolean that specifies whether the file is an Active Document.</param>
        /// <param name="bCancel">A Boolean that specifies whether to continue the download process and display the download dialog box.</param>
        private delegate void FileDownload(bool bActiveDocument, ref bool bCancel);

        protected override void OnLoad(EventArgs e) {
            dynamic d = webBrowser1.ActiveXInstance;
            string uri = string.Empty;

            d.BeforeNavigate2 += new BeforeNavigate2((object pDisp,
                ref dynamic url,
                ref dynamic Flags,
                ref dynamic TargetFrameName,
                ref dynamic PostData,
                ref dynamic Headers,
                ref bool Cancel) => {

                uri = url.ToString();
                Trace.WriteLine(uri);
            });

            d.FileDownload += new FileDownload((bool bActiveDocument, ref bool bCancel) => {
                bool isFile = uri.EndsWith("exe");

                if (isFile) {
                    bCancel = true;
                    Trace.Write("Canceled a file download from the DLR.");
                }
            });
        }
    }
}

Mid October 2011 Update

Since release of the FaultTrack BETA we haven’t had really any feedback from public users, but we have been seeing downloads which we assume is a good sign! Just pushing this post to get it out there that we are developing an updated version of the website geared more towards you, the users. It will have a better design, and will be easier to navigate with and will be more feature-rich. The sight is being developed in preperation to release the retail build of FaultTrack as well. We don’t have an ETA on any of this yet, but we will keep you posted here and there.

Forums are currently experiencing issues.

We are aware of the issues the forums are having, we are just not sure what caused these issues. We will post more information as we obtain it.
Update: The problem has been resolved.

Steve Jobs, founder of Apple Inc., passed away at the age of 56.

Steve Jobs, the founder to Apple Inc., passed away today in the battle with Pancreatic Cancer. Apple has stated the following on their front-page:

Applecom homepage after death of Steve Jobs 218x300 Steve Jobs, founder of Apple Inc., passed away at the age of 56.

Apple has lost a visionary and creative genius, and the world has lost an amazing human being. Those of us who have been fortunate enough to know and work with Steve have lost a dear friend and inspiring mentor. Steve leaves behind a company that only he could have built, and his spirit will forever be the foundation of Apple.

FaultTrack BETA released.

Download
http://www.dcomproductions.com/products/faulttrack/

KB (Knowledge Base)
http://www.dcomproductions.com/Support/KB/c1/faulttrack.aspx

Official Forum
http://www.dcomproductions.com/forums/viewforum.php?f=68

After many months of work, and weeks of our private testers waiting, I am proud to announce the FaultTrack BETA was uploaded to our servers moments ago. Please use the forum for any discussions, bug reports or feature requests as the development team will be monitoring and providing feedback.

I would also like to thank our many private testers who provided much great feedback throghout the progression of the project.