Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. WPF
  4. Impossible? Get instance of MainWindow from extern WPF-application

Impossible? Get instance of MainWindow from extern WPF-application

Scheduled Pinned Locked Moved WPF
csharpwpfcomhelpquestion
8 Posts 3 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Mc_Topaz
    wrote on last edited by
    #1

    I have two WPF-applications. Let's call them A and B. In A I wan't to start B as a new process and get the instance of B's MainWindow to further gain access of the controls in B. When A has started it sets up an instance of the Process class to start B. The instance is kept in A to help in any other way to access or terminate B. In A I have a StartB method and a GetB method:

    public partial class MainWindow : Window
    {
    Process Process { get; set; }

    public MainWindow()
    {
        InitializeComponent();
    }
    
    private void Window\_Loaded(object sender, RoutedEventArgs e)
    {
        StartB();
        GetB();
    }
    
    void StartB()
    {
        var path = @"C:\\Some\\Path\\To\\B.exe";
        var info = new ProcessStartInfo(path);
        Process = new Process();
        Process.StartInfo = info;
        Process.Start();
    }
    
    void GetB()
    {
        var title = Process.MainWindowTitle;
        var visual = System.Windows.Interop.HwndSource.FromHwnd(Process.MainWindowHandle);
        var window = visual.RootVisual as Window;
    }
    

    }

    The StartB method works. But the GetB method don't work. This line in GetB returns null:

    var visual = System.Windows.Interop.HwndSource.FromHwnd(Process.MainWindowHandle);

    I have googled and I found somewhere that the call to System.Windows.Interop.HwndSource.FromHwnd should work, but it didn't. Is there a solution for this? Best regards, Stefan

    R L 2 Replies Last reply
    0
    • M Mc_Topaz

      I have two WPF-applications. Let's call them A and B. In A I wan't to start B as a new process and get the instance of B's MainWindow to further gain access of the controls in B. When A has started it sets up an instance of the Process class to start B. The instance is kept in A to help in any other way to access or terminate B. In A I have a StartB method and a GetB method:

      public partial class MainWindow : Window
      {
      Process Process { get; set; }

      public MainWindow()
      {
          InitializeComponent();
      }
      
      private void Window\_Loaded(object sender, RoutedEventArgs e)
      {
          StartB();
          GetB();
      }
      
      void StartB()
      {
          var path = @"C:\\Some\\Path\\To\\B.exe";
          var info = new ProcessStartInfo(path);
          Process = new Process();
          Process.StartInfo = info;
          Process.Start();
      }
      
      void GetB()
      {
          var title = Process.MainWindowTitle;
          var visual = System.Windows.Interop.HwndSource.FromHwnd(Process.MainWindowHandle);
          var window = visual.RootVisual as Window;
      }
      

      }

      The StartB method works. But the GetB method don't work. This line in GetB returns null:

      var visual = System.Windows.Interop.HwndSource.FromHwnd(Process.MainWindowHandle);

      I have googled and I found somewhere that the call to System.Windows.Interop.HwndSource.FromHwnd should work, but it didn't. Is there a solution for this? Best regards, Stefan

      R Offline
      R Offline
      Richard Deeming
      wrote on last edited by
      #2

      I suspect you're calling GetB too early - the main window hasn't shown up yet. Assuming you have control of both applications, you'd probably be better off using IPC, probably using anonymous named pipes: Pipe Operations in .NET | Microsoft Docs[^]


      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

      M 1 Reply Last reply
      0
      • R Richard Deeming

        I suspect you're calling GetB too early - the main window hasn't shown up yet. Assuming you have control of both applications, you'd probably be better off using IPC, probably using anonymous named pipes: Pipe Operations in .NET | Microsoft Docs[^]


        "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

        M Offline
        M Offline
        Mc_Topaz
        wrote on last edited by
        #3

        I did wait so the MainWindow/Process of B had shown up before I ran the GetB() method. But it didn't matter that I waited... I don't want to alter the B WPF-application. Therefore I cannot implement IPC in any way in it.

        1 Reply Last reply
        0
        • M Mc_Topaz

          I have two WPF-applications. Let's call them A and B. In A I wan't to start B as a new process and get the instance of B's MainWindow to further gain access of the controls in B. When A has started it sets up an instance of the Process class to start B. The instance is kept in A to help in any other way to access or terminate B. In A I have a StartB method and a GetB method:

          public partial class MainWindow : Window
          {
          Process Process { get; set; }

          public MainWindow()
          {
              InitializeComponent();
          }
          
          private void Window\_Loaded(object sender, RoutedEventArgs e)
          {
              StartB();
              GetB();
          }
          
          void StartB()
          {
              var path = @"C:\\Some\\Path\\To\\B.exe";
              var info = new ProcessStartInfo(path);
              Process = new Process();
              Process.StartInfo = info;
              Process.Start();
          }
          
          void GetB()
          {
              var title = Process.MainWindowTitle;
              var visual = System.Windows.Interop.HwndSource.FromHwnd(Process.MainWindowHandle);
              var window = visual.RootVisual as Window;
          }
          

          }

          The StartB method works. But the GetB method don't work. This line in GetB returns null:

          var visual = System.Windows.Interop.HwndSource.FromHwnd(Process.MainWindowHandle);

          I have googled and I found somewhere that the call to System.Windows.Interop.HwndSource.FromHwnd should work, but it didn't. Is there a solution for this? Best regards, Stefan

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #4

          An exe can be treated as a dll. You haven't said why you need to "start" B. If it's B's main window you want, you can instantiate it via A. That applies to anything public in B.

          It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food

          M 1 Reply Last reply
          0
          • L Lost User

            An exe can be treated as a dll. You haven't said why you need to "start" B. If it's B's main window you want, you can instantiate it via A. That applies to anything public in B.

            It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food

            M Offline
            M Offline
            Mc_Topaz
            wrote on last edited by
            #5

            It might be time to tell the my idéa. B is a WPF-application my company has. We don't have any unit test for the GUI of B. We want that. So I thought if: * B is a WPF-project in our Visual Studio solution. * A is a unit test project in the same solution. * A has some "code/package/NuGet" to start, terminate B and gain access of all public controls in B. * In A we write the unit tests that use the "code/package/NuGet" to access the controls in B to do our unit tests. For instance if I want to test a button's click event in B: 1) In A: Run a specific test case. 2) In A: Start B. 3) In A: Someway gain access of all public controls of B. 4) In A: Put a text in a TextBox located in B. 5) In A: Trigger the click event of a Button located in B. 6) In B: The Button's click event puts the TextBox's text in a TextBlock. 7) In A: Read the Text from the TextBlock inside of B. 8) In A: Verify the text and pass or fail the test. 9) In A: Terminate B. I have looked at Appium with the WinAppDriver solution. That works, but it requires the WinAppDriver application running in the background to handle all communications between A and B. I don't want a third party or be forced to write any IPC in B. Unit test should be easy to write and run. If each develop must install the WinAppDriver to run tests, it's just tedious. However, I like the way that WinAppDriver use the AutomationProperties.AutomationId and other properties on controls to allow "A" to access it "B". I would like a similar solution. @Gerry Schmitz How should I do to instantiate B in A? If that give me access to all public controls, that will be fine! Best regards, /Steffe

            R L 2 Replies Last reply
            0
            • M Mc_Topaz

              It might be time to tell the my idéa. B is a WPF-application my company has. We don't have any unit test for the GUI of B. We want that. So I thought if: * B is a WPF-project in our Visual Studio solution. * A is a unit test project in the same solution. * A has some "code/package/NuGet" to start, terminate B and gain access of all public controls in B. * In A we write the unit tests that use the "code/package/NuGet" to access the controls in B to do our unit tests. For instance if I want to test a button's click event in B: 1) In A: Run a specific test case. 2) In A: Start B. 3) In A: Someway gain access of all public controls of B. 4) In A: Put a text in a TextBox located in B. 5) In A: Trigger the click event of a Button located in B. 6) In B: The Button's click event puts the TextBox's text in a TextBlock. 7) In A: Read the Text from the TextBlock inside of B. 8) In A: Verify the text and pass or fail the test. 9) In A: Terminate B. I have looked at Appium with the WinAppDriver solution. That works, but it requires the WinAppDriver application running in the background to handle all communications between A and B. I don't want a third party or be forced to write any IPC in B. Unit test should be easy to write and run. If each develop must install the WinAppDriver to run tests, it's just tedious. However, I like the way that WinAppDriver use the AutomationProperties.AutomationId and other properties on controls to allow "A" to access it "B". I would like a similar solution. @Gerry Schmitz How should I do to instantiate B in A? If that give me access to all public controls, that will be fine! Best regards, /Steffe

              R Offline
              R Offline
              Richard Deeming
              wrote on last edited by
              #6

              Try using the UI Automation library: Test Run: Automating UI Tests In WPF Applications | Microsoft Docs[^]


              "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

              1 Reply Last reply
              0
              • M Mc_Topaz

                It might be time to tell the my idéa. B is a WPF-application my company has. We don't have any unit test for the GUI of B. We want that. So I thought if: * B is a WPF-project in our Visual Studio solution. * A is a unit test project in the same solution. * A has some "code/package/NuGet" to start, terminate B and gain access of all public controls in B. * In A we write the unit tests that use the "code/package/NuGet" to access the controls in B to do our unit tests. For instance if I want to test a button's click event in B: 1) In A: Run a specific test case. 2) In A: Start B. 3) In A: Someway gain access of all public controls of B. 4) In A: Put a text in a TextBox located in B. 5) In A: Trigger the click event of a Button located in B. 6) In B: The Button's click event puts the TextBox's text in a TextBlock. 7) In A: Read the Text from the TextBlock inside of B. 8) In A: Verify the text and pass or fail the test. 9) In A: Terminate B. I have looked at Appium with the WinAppDriver solution. That works, but it requires the WinAppDriver application running in the background to handle all communications between A and B. I don't want a third party or be forced to write any IPC in B. Unit test should be easy to write and run. If each develop must install the WinAppDriver to run tests, it's just tedious. However, I like the way that WinAppDriver use the AutomationProperties.AutomationId and other properties on controls to allow "A" to access it "B". I would like a similar solution. @Gerry Schmitz How should I do to instantiate B in A? If that give me access to all public controls, that will be fine! Best regards, /Steffe

                L Offline
                L Offline
                Lost User
                wrote on last edited by
                #7

                Since it's a "formal" test scenario, you add a "reference" to B's exe / namespace in A (versus dynamic assembly referencing); then it's: var windowB = new B.MainWindow(); etc. This assumes there isn't some code in B.App.Startup that MainWindow is dependent on (I use static "data" classes for lazy loading) As for manipulating controls (and methods), you obviously need public accessors (in one form or another).

                It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food

                M 1 Reply Last reply
                0
                • L Lost User

                  Since it's a "formal" test scenario, you add a "reference" to B's exe / namespace in A (versus dynamic assembly referencing); then it's: var windowB = new B.MainWindow(); etc. This assumes there isn't some code in B.App.Startup that MainWindow is dependent on (I use static "data" classes for lazy loading) As for manipulating controls (and methods), you obviously need public accessors (in one form or another).

                  It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food

                  M Offline
                  M Offline
                  Mc_Topaz
                  wrote on last edited by
                  #8

                  :doh: Why didn't I thought of that. I tried it yesterday and it worked great. Thanks!

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups