Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 4322438
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 21, 20262026-05-21T08:52:25+00:00 2026-05-21T08:52:25+00:00

I write an app in C#, .NET 3.0 in VS2005 with a feature of

  • 0

I write an app in C#, .NET 3.0 in VS2005 with a feature of monitoring insertion/ejection of various removable drives (USB flash disks, CD-ROMs etc.). I did not want to use WMI, since it can be sometimes ambiguous (e.g. it can spawn multiple insertion events for a single USB drive), so I simply override the WndProc of my mainform to catch the WM_DEVICECHANGE message, as proposed here. Yesterday I run into a problem when it turned out that I will have to use WMI anyway to retrieve some obscure disk details like a serial number. It turns out that calling WMI routines from inside the WndProc throws the DisconnectedContext MDA.

After some digging I ended with an awkward workaround for that. The code is as follows:

    // the function for calling WMI 
    private void GetDrives()
    {
        ManagementClass diskDriveClass = new ManagementClass("Win32_DiskDrive");
        // THIS is the line I get DisconnectedContext MDA on when it happens:
        ManagementObjectCollection diskDriveList = diskDriveClass.GetInstances();
        foreach (ManagementObject dsk in diskDriveList)
        {
            // ...
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        // here it works perfectly fine
        GetDrives();
    }


    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);

        if (m.Msg == WM_DEVICECHANGE)
        {
            // here it throws DisconnectedContext MDA 
            // (or RPC_E_WRONG_THREAD if MDA disabled)
            // GetDrives();
            // so the workaround:
            DelegateGetDrives gdi = new DelegateGetDrives(GetDrives);
            IAsyncResult result = gdi.BeginInvoke(null, "");
            gdi.EndInvoke(result);
        }
    }
    // for the workaround only
    public delegate void DelegateGetDrives();

which basically means running the WMI-related procedure on a separate thread – but then, waiting for it to complete.

Now, the question is: why does it work, and why does it have to be that way? (or, does it?)

I don’t understand the fact of getting the DisconnectedContext MDA or RPC_E_WRONG_THREAD in the first place. How does running GetDrives() procedure from a button click event handler differs from calling it from a WndProc? Don’t they happen on the same main thread of my app? BTW, my app is completely single-threaded, so why all of the sudden an error referring to some ‘wrong thread’? Does the use of WMI imply multithreading and special treatment of functions from System.Management?

In the meantime I found another question related to that MDA, it’s here. OK, I can take it that calling WMI means creating a separate thread for the underlying COM component – but it still does not occur to me why no-magic is needed when calling it after a button is pressed and do-magic is needed when calling it from the WndProc.

I’m really confused about that and would appreciate some clarification on that matter. There are only a few worse things than having a solution and not knowing why it works :/

Cheers,
Aleksander

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-21T08:52:25+00:00Added an answer on May 21, 2026 at 8:52 am

    There is a rather long discussion of COM Apartments and message pumping here. But the main point of interest is the message pump is used to ensure that calls in a STA are properly marshaled. Since the UI thread is the STA in question, messages would need to be pumped to ensure that everything works properly.

    The WM_DEVICECHANGE message can actually be sent to the window multiple times. So in the case where you call GetDrives directly, you effectively end up with recursive calls. Put a break point on the GetDrives call and then attach a device to fire the event.

    The first time you hit the break point, everything in fine. Now press F5 to continue and you will hit the break point a second time. This time the call stack is something like:

    [In a sleep, wait, or join]
    DeleteMeWindowsForms.exe!DeleteMeWindowsForms.Form1.WndProc(ref System.Windows.Forms.Message m) Line 46 C#
    System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0x13 bytes
    System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x31 bytes
    System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x64 bytes
    [Native to Managed Transition]
    [Managed to Native Transition]
    mscorlib.dll!System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle waitableSafeHandle, long millisecondsTimeout, bool hasThreadAffinity, bool exitContext) + 0x2b bytes
    mscorlib.dll!System.Threading.WaitHandle.WaitOne(int millisecondsTimeout, bool exitContext) + 0x2d bytes
    mscorlib.dll!System.Threading.WaitHandle.WaitOne() + 0x10 bytes
    System.Management.dll!System.Management.MTAHelper.CreateInMTA(System.Type type) + 0x17b bytes
    System.Management.dll!System.Management.ManagementPath.CreateWbemPath(string path) + 0x18 bytes
    System.Management.dll!System.Management.ManagementClass.ManagementClass(string path) + 0x29 bytes
    DeleteMeWindowsForms.exe!DeleteMeWindowsForms.Form1.GetDrives() Line 23 + 0x1b bytes C#

    So effectively the window messages are being pumped to ensure the COM calls are properly marshalled, but this has the side effect of calling your WndProc and GetDrives again (as there are pending WM_DEVICECHANGE messages) while still in a previous GetDrives call. When you use BeginInvoke, you remove this recursive call.

    Again, put a breakpoint on the GetDrives call and press F5 after the first time it’s hit. The next time around, wait a second or two then press F5 again. Sometimes it will fail, sometimes it won’t and you’ll hit your breakpoint again. This time, your callstack will include three calls to GetDrives, with the last one triggered by the enumeration of the diskDriveList collection. Because again, the messages are pumped to ensure the calls are marshaled.

    It’s hard to pinpoint exactly why the MDA is triggered, but given the recursive calls it reasonable to assume the COM context may be torn down prematurely and/or an object is collected before the underlying COM object can be released.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I write my app in VS 2008 and so use all the fanciful stuffs
When I write an app, I use the System.Data interfaces (IDbConnection, IDbCommand, IDataReader, IDbDataParameter,
I want to write an app that takes in a model filename via cmd
I'm trying to write an app using Ruby on Rails and I'm trying to
Anyone know if it is possible to write an app that uses the Java
How would one go about displaying taskbar notifications? I want to write an app
I'd like to write a Silverlight app that has 2 or more browser windows
I'm trying to write a small app that monitors how much power is left
I am trying to write a console app that simply lists the number of
I want to write a little app for myself which notifies me if there

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.