Hi Jeff,
Sorry for letting you wait.
I have performed intensive debugging over this issue. Finally, I found the
root cause.
It seems that we should not place the <system.windows.forms
jitDebugging="true" /> section in the begin of the machine.config. This
will break the .Net Winform JIT debugging feature..Net will always probe
the machine.config <system.windows.forms> section before app.config. If we
remove this section from machine.config, app.config <system.windows.forms
jitDebugging="true" /> will ok without any problem. You may give it a try.
Also, to use <system.windows.forms jitDebugging="true" /> in the
machine.config at the machine-wide. You have to place the
<system.windows.forms jitDebugging="true" /> at the end closing of
<configuration>, just before </configuration>, like this:
....
</system.web>
<system.windows.forms jitDebugging="true"/>
</configuration>
Based on my testing, this works well on my machine.
If you are curious about the internal debugging result, below is some
information.
If .Net winform can probe jitDebugging="true" in app.config, it will setup
a "DebuggableCallback" for the window procedure, if not, it will use
"Callback". "Callback" method will set a big try...catch to catch any
exception in the Winform app and display an error dialog, see the code
below(OnThreadException in the code will show the error dialog):
private IntPtr Callback(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam)
{
Message m = Message.Create(hWnd, msg, wparam, lparam);
try
{
if (this.weakThisPtr.IsAllocated && (this.weakThisPtr.Target !=
null))
{
this.WndProc(ref m);
}
else
{
this.DefWndProc(ref m);
}
}
catch (Exception exception)
{
this.OnThreadException(exception);
}
finally
{
if (msg == 130)
{
this.ReleaseHandle(false);
}
if (msg == NativeMethods.WM_UIUNSUBCLASS)
{
this.ReleaseHandle(true);
}
}
return m.Result;
}
While "DebuggableCallback" will not catch the dialog but let the exception
throw out for JIT debugging:
private IntPtr DebuggableCallback(IntPtr hWnd, int msg, IntPtr wparam,
IntPtr lparam)
{
Message m = Message.Create(hWnd, msg, wparam, lparam);
try
{
if (this.weakThisPtr.IsAllocated && (this.weakThisPtr.Target !=
null))
{
this.WndProc(ref m);
}
else
{
this.DefWndProc(ref m);
}
}
finally
{
if (msg == 130)
{
this.ReleaseHandle(false);
}
if (msg == NativeMethods.WM_UIUNSUBCLASS)
{
this.ReleaseHandle(true);
}
}
return m.Result;
}
To use "DebuggableCallback" or "Callback" is determined in the following
method by checking WndProcShouldBeDebuggable property:
internal void AssignHandle(IntPtr handle, bool assignUniqueID)
{
lock (this)
{
this.CheckReleased();
this.handle = handle;
if (userDefWindowProc == IntPtr.Zero)
{
string lpProcName = (Marshal.SystemDefaultCharSize == 1) ?
"DefWindowProcA" : "DefWindowProcW";
userDefWindowProc = UnsafeNativeMethods.GetProcAddress(new
HandleRef(null, UnsafeNativeMethods.GetModuleHandle("user32.dll")),
lpProcName);
if (userDefWindowProc == IntPtr.Zero)
{
throw new Win32Exception();
}
}
this.defWindowProc = UnsafeNativeMethods.GetWindowLong(new
HandleRef(this, handle), -4);
if (WndProcShouldBeDebuggable)
{
this.windowProc = new
NativeMethods.WndProc(this.DebuggableCallback);
}
else
{
this.windowProc = new NativeMethods.WndProc(this.Callback);
}
....................
While this "WndProcShouldBeDebuggable " property checking logic is
implemented in the "WndProcFlags" static property:
internal static bool WndProcShouldBeDebuggable
{
get
{
return ((WndProcFlags & 4) != 0);
}
}
private static int WndProcFlags
{
get
{
int wndProcFlags = NativeWindow.wndProcFlags;
if (wndProcFlags == 0)
{
if (userSetProcFlags != 0)
{
wndProcFlags = userSetProcFlags;
}
else if (userSetProcFlagsForApp != 0)
{
wndProcFlags = userSetProcFlagsForApp;
}
else if (!Application.CustomThreadExceptionHandlerAttached)
{
if (Debugger.IsAttached)
{
wndProcFlags |= 4;
}
else
{
wndProcFlags =
AdjustWndProcFlagsFromRegistry(wndProcFlags);
if ((wndProcFlags & 2) != 0)
{
wndProcFlags =
AdjustWndProcFlagsFromMetadata(wndProcFlags);
if ((wndProcFlags & 0x10) != 0)
{
if ((wndProcFlags & 8) != 0)
{
wndProcFlags =
AdjustWndProcFlagsFromConfig(wndProcFlags);
}
else
{
wndProcFlags |= 4;
}
}
}
}
}
wndProcFlags |= 1;
NativeWindow.wndProcFlags = (byte) wndProcFlags;
}
return wndProcFlags;
}
}
So, finally, it is "AdjustWndProcFlagsFromConfig" method that probes
"machine.config" and "app.config":
[MethodImpl(MethodImplOptions.NoInlining)]
private static int AdjustWndProcFlagsFromConfig(int wndProcFlags)
{
if (WindowsFormsSection.GetSection().JitDebugging)
{
wndProcFlags |= 4;
}
return wndProcFlags;
}
This is my findings. But I still did not find out why .Net will not allow
the <system.windows.forms jitDebugging="true" /> section to reside at the
begin of the machine.config. Anyway, I think we have a resolution for the
problem now.
Hope it helps.
Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.