Search code examples
node.jswindowsexecremote-desktopmultiple-monitors

Start external exe with node.js on second monitor


Do you know, if it's possible to start a software on a specific monitor? And how this can be done?

I have a node.js server on my computer (windows 10) and I need to start some external software (I can't change code in that external software, because I only have the exe-file). The final application should work on a setup with a real monitor and a second fake monitor. On the first monitor is a browser window in full screen. There is a start and stop button (they work already) to start and stop the external software. On the second monitor (not visible) should start the external software. If everything works this way, I can connect per remote on that computer and look at the second screen. There I can use the external software. And on the Monitor (1) of that computer is always only the browser window visible.

To test I use notepad.exe as the external software. If I click start, the software opens on my main monitor (1) but it should start on the second monitor.

Thanks for your help.


Solution

  • It looks like, it's not possible to do that directly. But if you start from node.js a little helper program it's not that difficult. You can start it with execFile() look at: nodejs docs

    I made a little C# console application with following functions:

        [DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
        public static extern IntPtr SetForegroundWindow(IntPtr hWnd);
    
        [DllImport("user32.dll", EntryPoint = "ShowWindow")]
        public static extern bool ShowWindow(IntPtr hWnd, int cmdShow);
    
        [DllImport("user32.dll", SetLastError = true)]
        internal static extern bool MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
    

    Then I iterated through System.Windows.Forms.Screen.AllScreens and started with Process my executable. From Process I got the MainWindowHandle and with that, it's possible to set the window on the screen you want.

     static void Main(string[] args)
        {
            if (args.Length == 1 && args[0].Equals("h"))
            {
                Console.Out.WriteLine("Command: [displayName] [executable] [arguments for executable]");
                return;
            }
    
            if (args.Length < 2)
            {
                Console.Out.WriteLine("arguments not correct. Should be: [displayName] [executable1] [arguments for executable]");
                return;
            }
    
            foreach (var screen in Screen.AllScreens)
            {
                Console.Out.WriteLine(screen.DeviceName);
                if (screen.DeviceName.Equals(args[0]))
                {
                    var process = new Process();
    
                    process.StartInfo.FileName = args[1];
                    string[] arguments = args.Skip(2) as string[];
                    if (arguments != null) process.StartInfo.Arguments = string.Join(" ", arguments);
    
                    process.Start();
    
                    var hwnd = process.MainWindowHandle;
                    Console.Out.WriteLine("while get process.MainWindowHandle");
                    while (!process.HasExited)
                    {
                        process.Refresh();
                        if (process.MainWindowHandle.ToInt32() != 0)
                        {
                            hwnd = process.MainWindowHandle;
                            break;
                        }
                    }
                    Console.Out.WriteLine("windowHandle: " + hwnd);
    
                    MoveWindow(hwnd, screen.WorkingArea.X, screen.WorkingArea.Y, screen.WorkingArea.Width, screen.WorkingArea.Height, true);
                    ShowWindow(hwnd, SwMaximize);
                    SetForegroundWindow(hwnd);
                    // Waits here for the process to exit.
                    process.WaitForExit();
                    return;
                }
            }
            Console.Out.WriteLine("screen not found: " + args[0]);
        }
    }