locked
InvalidOperationException when reparenting WindowsFormsHost RRS feed

  • Question

  • I have a program that does the following:

    • Create a WPF control
    • User reparenting to show the control inside another window (Notepad)
    • Add a WindowsFormsHost to the control

    The code is

    UserControl1 control = new UserControl1();
    control.AddFormsHostWithDelay(TimeSpan.FromSeconds(2));;
    if (this.TryGetHandleFromName("Notepad", out IntPtr handle))
    {
       HwndSourceParameters pa = new HwndSourceParameters("WPF Source", 400, 300);
       pa.ParentWindow = handle;
       pa.WindowStyle = 0x40000000 | 0x10000000; // child and visible
       pa.UsesPerPixelOpacity = false;
       pa.SetPosition(5, 5);
       HwndSource src = new HwndSource(pa);
       src.RootVisual = control;
    }

    That code worked for years, but since Windows10 CreatorsUpdate, it crashes as soon as the WindowsFormsHost is added. The message and stack trace is

    'CreatorsUpdateCrashDemo.exe' (CLR v4.0.30319: 
    CreatorsUpdateCrashDemo.exe): Loaded 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\PrivateAssemblies\Runtime\Microsoft.VisualStudio.Debugger.Runtime.dll'. 
    
    Unhandled Exception: System.InvalidOperationException: Hosted HWND must be a child window of the specified parent.
    at System.Windows.Interop.HwndHost.BuildWindow(HandleRef hwndParent)
    at System.Windows.Interop.HwndHost.BuildOrReparentWindow()
    at System.Windows.Interop.HwndHost.OnSourceChanged(Object sender, SourceChangedEventArgs e)

    Full demo can be found at http://www.seetec.eu/entwicklung/BRAU/CreatorsUpdateCrash.zip

    How to reproduce:

    • Use Windows10 CreatorsUpdate
    • Download demo
    • start notepad
    • start CreatorsUpdateCrashDemo
    • Click the crash button
    • Application crashes after 2 seconds

    Does anybody know what to change to avoid this crash? Adding the FormsHost before doing the reparenting resolves the issue but is not possible in the real application.

    Wednesday, August 23, 2017 9:37 AM

Answers

  • This is probably due to a change we made in the Creators Update (1703) related to reparenting windows across a DPI awareness boundary. Desktop applications can run in different modes (DPI unaware, system aware, or "per monitor" aware). When you reparent an HWND across a DPI boundary (say, from an application running system aware into an application that is running "per monitor" aware), Windows takes different behaviors on different versions. In short, there is a requirement that all HWNDs in an HWND tree conform to the same DPI awareness. When you reparent an HWND from one awareness into a different awareness, Windows will either reset the DPI awareness of the source process, or will return an error. This error is probably bubbling up from Win32 to you as an InvalidOperationException.

    This also explains why when you override the DPI-awareness of your process (in the Compatibility tab of the exe) and set it to run as "Application", the error does not occur. "Application" mode maps to "per-monitor" DPI awareness. Notepad is already per-monitor, which means that you're re-parenting from one mode to another. 

    Another way to work around this would be to run your application in per-monitor DPI awareness. You can specify this in the application manifest.

    See the bottom of this page for more info:

    https://msdn.microsoft.com/en-us/library/windows/desktop/mt843498(v=vs.85).aspx

    • Marked as answer by Bernd Rausch Tuesday, March 13, 2018 7:39 AM
    Monday, December 11, 2017 11:07 PM

All replies

  • Hi,

    I run your demo, and I can reproduce your problem .

    I think the problem may have been caused by WindowsFormsHost, When I use a WPF element instead the WindowsFormsHost, it works.

    So I suggest you avoid using the WindowsFormsHost, since WindowsFormsHost is Interoperated between WinForm and  WPF, it is so special.

    About WPF and Win32 Interoperation I suggest you refer below link:

    WPF and Win32 Interoperation

    https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/wpf-and-win32-interoperation

    Best Regards,

    Bob



    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, August 24, 2017 6:36 AM
  • Yes, the problem is clearly WindowsFormsHost. Something inside the BuildWindowCore method changed with CreatorsUpdate. After the call to BuildWindowCore in HwndHost.BuildWindow there are some checks, and one of them fails. Speficially it is this code in HwndHost:

    // Make sure the child window is the child of the expected parent window.
    if(hwndParent.Handle != UnsafeNativeMethods.GetParent(_hwnd))
    {
          throw new InvalidOperationException(SR.Get(SRID.ChildWindowMustHaveCorrectParent));
    }

    Replacing the WindowsFormsHost is a lot of work internally, so I first want to understand what is going on. Is doing things like in the sample illegal and we were just lucky to get away with it until now? Is it a bug in Windows/.Net? Is it a breaking change that hit us?


    Friday, August 25, 2017 10:43 AM
  • Hi,

    Sorry for my late reply.

    Does this issue work on other environment? such as win7...

    After I run your demo again, I can not get the exception , so odd!

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, September 6, 2017 8:09 AM
  • Yes, the code runs fine in every environment (win7, win8.1, win10 before creatorsupdate) except windows 10 creatorsupdate.

    Monday, September 18, 2017 6:15 AM
  • Hi,

    >> Yes, the code runs fine in every environment (win7, win8.1, win10 before creators update) except windows 10 creators update.

    What version of .NET framework on Windows 10, whether   it is difference with .NET Framework on Window 7, 8?

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, September 18, 2017 6:26 AM
  • Update: I found a workaround. If you check "Override high dpi scaling behavior" in the properties of the executable, it no longer crashes. 

    Can anybody explain this behaviour?

    • Proposed as answer by Bob Ding Monday, September 18, 2017 6:45 AM
    Monday, September 18, 2017 6:27 AM
  • Hi,

    Maybe you can following this article: Desktop Applications in the Windows 10 Creators Update

    You can try to report this issue to Peter Felts .

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, September 18, 2017 6:38 AM
  • This is probably due to a change we made in the Creators Update (1703) related to reparenting windows across a DPI awareness boundary. Desktop applications can run in different modes (DPI unaware, system aware, or "per monitor" aware). When you reparent an HWND across a DPI boundary (say, from an application running system aware into an application that is running "per monitor" aware), Windows takes different behaviors on different versions. In short, there is a requirement that all HWNDs in an HWND tree conform to the same DPI awareness. When you reparent an HWND from one awareness into a different awareness, Windows will either reset the DPI awareness of the source process, or will return an error. This error is probably bubbling up from Win32 to you as an InvalidOperationException.

    This also explains why when you override the DPI-awareness of your process (in the Compatibility tab of the exe) and set it to run as "Application", the error does not occur. "Application" mode maps to "per-monitor" DPI awareness. Notepad is already per-monitor, which means that you're re-parenting from one mode to another. 

    Another way to work around this would be to run your application in per-monitor DPI awareness. You can specify this in the application manifest.

    See the bottom of this page for more info:

    https://msdn.microsoft.com/en-us/library/windows/desktop/mt843498(v=vs.85).aspx

    • Marked as answer by Bernd Rausch Tuesday, March 13, 2018 7:39 AM
    Monday, December 11, 2017 11:07 PM