by Brian Ensink
12. November 2008 01:05
I have been working on a custom setup application to install a large amount of data onto a customer's system. The application is entirely written in C# and calls Windows Installer functions to install dozens (or hundreds) of small "dumb" MSI packages. At some point the user will be prompted to put in the next disk not by Windows Installer (which would normally handle this) but by the custom application. As soon as the disk spins up Windows will by default try to autorun the contents of the disk which can be confusing and unexpected by the user who is simply trying to install data. How can the autoplay be ignored in this case?
Microsoft Windows sends a message to the foreground window which gives the window a chance to cancel or allow autoplay. Line #7 of the code below registers this message by platform-invoking the Win32 function RegisterWindowMessage to get the ID of the message. We also override the form's WndProc function to handle this message and return a result value of 1 to cancel autoplay. That's all there is to it!
1: public partial class Form1 : Form
2: {
3: private uint m_QueryCancelAutoPlayID;
4: public Form1()
5: {
6: InitializeComponent();
7: m_QueryCancelAutoPlayID = Win32.RegisterWindowMessage("QueryCancelAutoPlay");
8: }
9:
10: protected override void WndProc(ref Message m)
11: {
12: base.WndProc(ref m);
13: if (m.Msg == m_QueryCancelAutoPlayID)
14: {
15: // Cancel autoplay
16: m.Result = (IntPtr)1;
17: }
18: }
19: }
20:
21: internal static class Win32
22: {
23: [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
24: internal static extern uint RegisterWindowMessage(string lpString);
25: }
(This message only goes to the foreground window. A second approach involves placing an object that implements the IQueryCancelAutoPlay interface into the running object table. This allows autoplay to be canceled for non-foreground windows but this bigger solution wasn't necessary for our custom setup application.)