internal void NativeShow() { // Applies config struct and other settings, then // calls main Win32 function. if (settings == null) { throw new InvalidOperationException( "An error has occurred in dialog configuration."); } // Do a last-minute parse of the various dialog control lists, // and only allocate the memory at the last minute. MarshalDialogControlStructs(); // Make the call and show the dialog. // NOTE: this call is BLOCKING, though the thread // WILL re-enter via the DialogProc. try { showState = NativeDialogShowState.Showing; // Here is the way we would use "vanilla" PInvoke to call TaskDialogIndirect; // but if we did so here, we'd be at the mercy of the CLR's native DLL cache - // see below for more details. // HRESULT hresult = NativeMethods.TaskDialogIndirect( // nativeDialogConfig, // out selectedButtonID, // out selectedRadioButtonID, // out checkBoxChecked); // Instead, we load comctl and bind to TaskDialogIndirect // We do it this way so we can rigidly control // which version of comctl32 is loaded, // The CLR's PInvoke mechanism maintains a DLL cache that is // NOT invalidated when the OS activation context is changed // such that different DLL versions are needed. IntPtr tdi = DllVersionManager.GetNativeFunctionPointer( ExternDll.ComCtl32, "TaskDialogIndirect"); NativeMethods.TDIDelegate taskDialogFunctionPointer = (NativeMethods.TDIDelegate) Marshal.GetDelegateForFunctionPointer( tdi, typeof(NativeMethods.TDIDelegate) ); // Invoke TaskDialogIndirect. HRESULT hresult = taskDialogFunctionPointer( nativeDialogConfig, out selectedButtonID, out selectedRadioButtonID, out checkBoxChecked); if (ErrorHelper.Failed(hresult)) { string msg; switch (hresult) { case HRESULT.E_INVALIDARG: msg = "Invalid arguments to Win32 call."; break; case HRESULT.E_OUTOFMEMORY: msg = "Dialog contents too complex."; break; default: msg = String.Format( "An unexpected internal error occurred in the Win32 call:{0:x}", hresult); break; } Exception e = Marshal.GetExceptionForHR((int)hresult); throw new Win32Exception(msg, e); } } finally { showState = NativeDialogShowState.Closed; } }