Can't get parentHWND command line option to work

Posted this in Answers, but got no response, not sure if this is the more appropriate place:

I downloaded the EmbeddedWindow.zip linked in -parentHWND option on the command line info page: Unity - Manual: Command-line arguments
I followed the ReadMe exactly:

  • Open Unity project
  • Build Windows Standalone application to Export directory, and name the executable as Child.exe
  • Run Container.exe in Export directory
  • You should see Windows Standalone application running inside Container application

I also just downloaded Unity 4.6.0f3.

But it doesn’t work. When I run Container.exe, it pops up the start page, where I choose Windowed and 640x480 resolution, but when I click the Play! button, it just opens in its own Window, not inside the Container.exe app (which is running).

Is this even working? Information on it seems scarce on the forums here and on the web. Has anyone successfully used this?

It also seems weird that the example appends the Container.exe file location to the arguments:

process.StartInfo.Arguments = "-parentHWND " + panel1.Handle.ToInt32() + " " + Environment.CommandLine;

But no amount of playing around with the arguments (I tried making the handle hex, adding 0x in front, etc) made it work.

That’s what you can expect.
It’s not possible to run an other exe embedded in a screen (like in a VM).
The information you need to check is “Process”.
See here (e.g.):

That’s not what the example, provided by Unity, is doing. It is only setting window parenting.

Anyway, playing around more, I solved my problem. Apparently, this feature is only available in 4.5.5p1. It is not in 4.6.0. I installed 4.5.5p1, and the unity player correctly shows up on the form of the other application.

The bummer is that going back to 4.5.5p1 seems to have wiped out my entire project.

Maybe this is what you are after:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace RunExeInernal
{
    public partial class Form1 : Form
    {

        [DllImport("user32.dll")]
        static extern IntPtr SetParent(IntPtr hwc, IntPtr hwp);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Process calcProc = Process.Start("calc.exe");
            Thread.Sleep(500); // give the process some time to start
            calcProc.WaitForInputIdle();
            SetParent(calcProc.MainWindowHandle, this.Handle);
        }

        private void button2_Click(object sender, EventArgs e)
        {

            Process npProc = Process.Start("notepad.exe");
            Thread.Sleep(400); // give the process some time to start
            npProc.WaitForInputIdle();
            SetParent(npProc.MainWindowHandle, this.Handle);

        }
    }
}

That might work, and allow me to use the latest Unity. I’ll give it a try. Although in other tests, MainWindowHandle isn’t always reliable, I should be able to find it by enumerating the desktop windows.

In case anyone’s interested, the thing I’m using this for is an application that implements a standard Windows user interface and Unity inside a separate window that puts a custom border around the Unity window. I could run the Unity as popup, always find it and move it along with my window, and add a bunch of code to make sure it always appears above the custom border window, etc. But setting the Unity window as a child of the custom border window is just much easier when moving the window around, switching between applications, minimizing, etc.

Alright, SetParent is working. One thing I noticed is that in the EmbeddedExample.zip provided by unity, if I run my Unity scene, it crashes when closing. So I fixed that too. I was also able to restore my project lost when switching versions around by deleting the Library folder and re-loading it twice. I then committed the changes I had to version control (won’t make the mistake again of not doing that before switching Unity versions).

Here’s a breakdown of what I did. This more or less gives the same behavior of -parentHWND in versions that don’t have it. Most of these functions are Win32 functions, so you can either P/Invoke them or use C++ or other unmanaged code:

In the window that hosts (is the parent of) the Unity window, when you want to launch the Unity app:

  • Call the SetWinEventHook function and create an out-of-context hook for EVENT_OBJECT_CREATE
  • Start up the process, use the -popupwindow argument, and keep a copy of the handle

In the event callback/delegate:

  • I used the undocumented Win32 IsTopLevelWindow function to filter out a bunch of windows

  • Test the window name (GetWindowText) for the name of the Unity application you’re looking for (it’s the name seen at the top when you run the standalone player without -popupwindow)

  • When found, call SetParent, setting your window as the parent

  • Call MoveWindow to place it where you want it on the parent

  • Unhook the event hook

Cleanup. The Unity window doesn’t like to close with another app as the parent for some reason - even if I closed it while my app was still running. It would crash, and in different locations each time.

  • I put this code in OnFormClosing for my window containing the Unity window.
  • Call ShowWindow(SW_HIDE) to hide the window so it isn’t seen jumping to the desktop
  • Call SetParent again setting it to null (desktop)
  • Call PostMessage to the Unity window with message WM_SYSCOMMAND, wParam = SC_CLOSE to close the Unity window

All in all, it works. The Unity window follows my parent when it moves, minimizes when it minimizes, is always “on top” of my window, etc. Everything you’d expect from a child window. Keep in mind, it still need focus to get keyboard events, etc.

EDITED: Working on this some more, I found a way to close it without the process staying around.

1 Like

Hi BobearQSI,
I would be interested in hearing your thoughts about doing the same if not similar thing in Unity 5.

Thanks.

The solution I ended up with (detailed in my last post) is essentially application agnostic. Although Unity did require specific commands to shut down properly.

I would assume it would all work the same with Unity 5, although I can’t upgrade at the present time to check if shutdown works the same.

I know this post is old, but does anybody got it to work with Unity 5?
Any code snippet would be welcomed too :smile:
Thanks!