Link to home
Start Free TrialLog in
Avatar of dbtoth
dbtoth

asked on

Programmatically disable autorun C#.NET

I have a need to disable autorun for a CD backup application I'm writing. I've tried all the registry tricks I could find and none are stopping windows from popping up an annoying E:\ explorer window every time I put a CD in.

I found the following instructions on MSDN, but being rather new to C# and .NET I'm at a loss as to how to implement this solution:

---------------

Users can manually suppress AutoRun by holding down the SHIFT key when they insert the CD-ROM. However, it is usually preferable to handle this operation programmatically rather than depending on the user.

With systems that have Shell version 4.70 and later, Microsoft Windows sends a "QueryCancelAutoPlay" message to the foreground window. Your application can respond to this message to suppress AutoRun. This approach is used by system utilities such as the Open common dialog box to disable AutoRun. You will not get a "QueryCancelAutoPlay" message with versions of Windows 95 that do not have the Microsoft Internet Explorer 4.0 integrated Shell installed.

The following code fragments illustrate how to set up and handle this message. Your application must be running in the foreground window. First, register "QueryCancelAutoPlay" as a Windows message:

uMessage = RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));
                  
Your application's window must be in the foreground to receive this message. The message handler should return TRUE to cancel AutoRun and FALSE to enable it. The following code fragment illustrates how to use this message to disable AutoRun.

UINT g_uQueryCancelAutoPlay = 0;

LRESULT WndProc(HWND hwnd, UINT uMsg,  WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    ...
    default:
        if (!g_uQueryCancelAutoPlay)
        {
            g_uQueryCancelAutoPlay = RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));
        }
        if (uMsg && uMsg == g_uQueryCancelAutoPlay)
        {
            return TRUE;       // cancel auto-play
        }
    }
}


----------------------

Can anyone spell out how to accomplish the above in C#.NET


ASKER CERTIFIED SOLUTION
Avatar of naveenkohli
naveenkohli

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of dbtoth
dbtoth

ASKER

OK... I found some instructions to that effect from Google.

I have managed to implement the RegisterWindowMessage function and get the messageID of the QueryCancelPlay.

The instructions I found indicated it was necessary to override WndProc in order to trap the message.

I've managed to do that, and I can pop up a dialog box that shows I'm receiving and trapping the QueryCancelAutoPlay

The problem I have at the moment is that the cancel instructions above say you need to return TRUE (1) to cancel the autorun, but when I override WndProc is creates

protected override void WndProc(ref System.Windows.Forms.Message m)

with a return type of void, I can't return true; or return 1; once I trap the message. It won't let me change the return type from void to int or anything else because it's an inherited member.

Avatar of dbtoth

ASKER

OK... I finally figured it out after tons of searches through VS help files and MSDN.

Administrator: I'd like to give 100 points to naveenkohli for providing the correct code fragment which confirmed I was on the right track!

The complete solution is as follows:

public class Util
{
      [DllImport("user32",EntryPoint="RegisterWindowMessage")]
      public static extern int RegisterWindowMessage(string msgString);
            
      public Util()
      {
      }
}

public int QueryCancelAutoPlay = 0;


---------------

Expand in project explorer classes tab:

Click Classes>Namespaces>{Namespace Name}>Classes>{Form Name}>Bases and Interfaces>Classes

Right click on WndProc and select Override, modify the inserted WndProc stub with with the following code:

----------------


protected override void WndProc(ref System.Windows.Forms.Message m)
{
      if (QueryCancelAutoPlay == 0)
      {
            QueryCancelAutoPlay = Util.RegisterWindowMessage("QueryCancelAutoPlay");
      }
      if (m.Msg == QueryCancelAutoPlay)
      {
            m.Result = (IntPtr)1;
            return;
      }
      base.WndProc(ref m);
}


I presume it's possible for the DLLImport to fail, but if your system doesn't have a user32.dll you've got bigger problems then this :)

This solution requires the PC is running an OS integrated with a version of IE higher then 4.01 or something like that, or the QueryCancelAutoPlay message doesn't get sent.

Also, the application MUST have foreground focus in order to trap this message, or it gets sent to the application that HAS the foreground focus and you won't trap the message.
Avatar of dbtoth

ASKER

The above is working fine except for one small glitch... because the code only works when the window has focus, I'm running into snags if there's a MessageBox on the screen at the time the disc inserts, I still get the E:\ explorer popup.

This is getting really annoying, as I'm gaining access to the device about 5 seconds before the autoinsert kicks in... so I'm popping up Yes/No message boxes to get info from the user (like if they want to erase the disc) and it's disabling my event trap above.

Can anyone offer a workaround that might do the job? Is is possible to hook into MessageBox to trap catch the offending call in there as well?

I'm giving bonus points for anyone that can give me a working code sample to deal with this.
My guess would be that the delay is due to the CD spinning up. One thing you could try is to perform a directory listing or something similar on the CD drive before you pop up any windows. Those types of methods won't return until the CD is spun up, and so you should get the QueryCancelAutoPlay right away.

Zaphod.
Avatar of dbtoth

ASKER

Points still up for grabs if anyone can come up with a solution to this issue. Nothing I've tried reliably suppresses auto-insert/auto-run on Win2K
OK, if the delay idea didn't work, I have another idea, not quite so easy to implement. Since the problem is that you can't respond to the windows message because you have a message box up, put the code that checks for that message in a separate thread, then it will always be able to respond. So create a hidden form whose sole purpose is to handle that message and have your main app start a thread that launches that form. Still fairly straightforward, and I can give you some sample code if you need it.

Zaphod.
Avatar of dbtoth

ASKER

At this point some sample code might be nice. I haven't been inside the code for this app for a while...
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Bob Learned
No comment has been added lately, so it's time to clean up this TA.
I will leave the following recommendation for this question in the Cleanup topic area:

Split: naveenkohli {http:#9038744} & Z_Beeblebrox {http:#9566816}

Please leave any comments here within the next seven days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

TheLearnedOne
EE Cleanup Volunteer