4

I'm trying to make a program that opens a browser on each multi-display. When I did it with a notepad, it worked. However, when it's a browser didn't work and showed the error "System.InvalidOperationException: Process must exit before requested information can be determined". I will appreciate your help with this situation.

This is my code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp5
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern int MoveWindow(IntPtr hwnd, int x, int y,
    int nWidth, int nHeight, int bRepaint);

        private void Form1_Load(object sender, EventArgs e)
        {

            foreach (Screen item in Screen.AllScreens)
            {
                //Open a web browser
                System.Diagnostics.Process process1 = System.Diagnostics.Process.Start("C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe");
                //System.Diagnostics.Process process2 = System.Diagnostics.Process.Start("notepad.exe");
                process1.WaitForInputIdle();
                //process2.WaitForInputIdle();

                //Move the browser window
                MoveWindow(process1.MainWindowHandle, item.Bounds.X, item.Bounds.Y, item.Bounds.Width, item.Bounds.Height, 1);
                //MoveWindow(process2.MainWindowHandle, item.Bounds.X, item.Bounds.Y, item.Bounds.Width, item.Bounds.Height, 1);

            }
        }
    }
}
Misa
  • 43
  • 3
  • Which line does the exception throw? – shingo Dec 27 '21 at 05:23
  • This line when second time during debugging : `MoveWindow(process1.MainWindowHandle, item.Bounds.X, item.Bounds.Y, item.Bounds.Width, item.Bounds.Height, 1);` – Misa Dec 27 '21 at 05:57

1 Answers1

0

It seems that msedge.exe use a host process to start different tabs, so we can't use the created process ID to handle it.

Compare created process ID with processes in the Task Manager, the process 38756 is missing.

enter image description here

Another tool to browse edge relative processes is the built-in task manager of edge.

enter image description here

enter image description here

We can't find process 38756 as well.

So re-search the target edge process is necessary.

This repo https://github.com/alex-tomin/Tomin.Tools.KioskMode demostrate how to move chrome window into different monitors and set as full screen.

I tried to extract the necessary and modify your code like below, hope it helps:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace TestWinFormsApp
{
    // Get full definition of SetWindowPosFlags here:
    // https://www.pinvoke.net/default.aspx/Enums/SetWindowPosFlags.html
    [Flags]
    public enum SetWindowPosFlags : uint
    {
        SWP_NOREDRAW = 0x0008,
        SWP_NOZORDER = 0x0004
    }

    // Get full definition of ShowWindowCommands here:
    // https://www.pinvoke.net/default.aspx/Enums/ShowWindowCommand.html
    public enum ShowWindowCommands
    {
        Maximize = 3,
        Restore = 9,
    }

    public static class WinApi
    {
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
    }

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load_1(object sender, EventArgs e)
        {
            var ignoreHandles = new List<IntPtr>();
            foreach (Screen item in Screen.AllScreens)
            {
                this.StartEdgeProcess();

                var windowHandle = this.GetWindowHandle("msedge", ignoreHandles);
                ignoreHandles.Add(windowHandle);

                WinApi.ShowWindow(windowHandle, ShowWindowCommands.Restore);
                WinApi.SetWindowPos(windowHandle, IntPtr.Zero, item.Bounds.Left, item.Bounds.Top, 800, 600, SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_NOREDRAW);
                WinApi.ShowWindow(windowHandle, ShowWindowCommands.Maximize);
            }
        }

        private void StartEdgeProcess()
        {
            var process = new Process();
            process.StartInfo.FileName = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
            process.StartInfo.Arguments = "about:blank" + " --new-window -inprivate ";
            process.Start();
            process.WaitForInputIdle();
        }

        private IntPtr GetWindowHandle(string processName, List<IntPtr> ignoreHandlers)
        {
            IntPtr? windowHandle = null;
            while (windowHandle == null)
            {
                windowHandle = Process.GetProcesses()
                    .FirstOrDefault(process => process.ProcessName == processName
                        && process.MainWindowHandle != IntPtr.Zero
                        && !string.IsNullOrWhiteSpace(process.MainWindowTitle)
                        && !ignoreHandlers.Contains(process.MainWindowHandle))
                    ?.MainWindowHandle;
            }

            return windowHandle.Value;
        }
    }
}

cg-zhou
  • 528
  • 3
  • 6