Creating a Subprocess Inside Game

I need to use another program inside UE4.

Is there an unreal way of starting a subprocess and running a program?

Do you need to communicate with this process with pipes?

Yes. I will send it some commands and it will send me answers

Yes, it is a good place to start.

Thank you

The simplest way to create a sub-process from within the Engine is to use FPlatformProcess::CreateProc().

If you need to monitor the external process and/or capture its output, take a look at FMonitoredProcess instead. There are several examples in the code base.

If your program is written using the UE4 framework (Azarus’ answer for details), you can use the Messaging system with the UdpMessaging plug-in for communication between the Engine and your external process. Take a look at UnrealFrontendMain.cpp to see how your program needs to be initialized in order to use Messaging. It is not straightforward, but you should be able to figure it out: enable the TaskGraph system, load the Messaging module, load the UdpMessaging module or add full initialization of the plug-in system.

Come back here if you get stuck :slight_smile:

I got stuck. :slight_smile:

I choosed FMonitoredProcess class. I see it has OnOutput() function to get outputs from process. But i couldn’t find a function to send it a message.

How can i do that?

EDIT: I need to send it messages regularly. It is a chess engine by the way

Well, i have went ahead and looked very carefully how FMonitoredProcess is working.

I realized it is intended for one time run and finish class.

So i searched other ways to do it a lot, but couldn’t find any.

Currently i am trying to write a class using FMonitoredProcess as a starting point. Looking at how it is made, i am creating my own. Hope everything goes well

There is currently no API for sending data to the process via FMonitoredProcess, sorry. I started to write some initial code (FMonitoredProcess.ReadPipe), but it is not finished and not exposed. The main missing piece is to have an API that does the actual writing, i.e. FPlatformProcess::WritePipe(), which does not yet exist and would have to be implemented for all platforms.

If you want to implement it yourself, feel free to send me a pull request on GitHub. Otherwise you’ll have to wait until I have time for it. I will put it on my to-do list, but don’t hold your breath :slight_smile:

Yeah, i am working on that. I implemented WritePipe() function for win, mac, linux. Going to add it for android and ios but got to learn android ndk first. Also i don’t have much time at the moment so it is going to be done very late.

I also am working on an interactive process class, which will not be one time run and finish. :slight_smile:

Oh, that’s great! If you already have Win, Mac and Linux, you can already submit it. I don’t know if it makes sense on iOS and Android anyway, so we will probably just leave those implementations empty. I can add the boilerplate for those platforms if you don’t want to deal with it :slight_smile:

Android and iOS implementation is crucial for our teams chess game.

Ok, if Android and iOS is not a must. Then i am going to make a pull request in a few days. Sorry, i don’t have much time because i have to study final exams.

Hi~
I know it’s a old question, but I have fell in trouble with this function.
In my VR program, I want to open another VR game, when I use this function, my original program is closed!
It’s not what I want, and the new VR game can’t get the HMD control,
I don’t know how to deal with it, if you have any idea please tell me, Thanks very much.

Also, I use the WaitForProc, It can only pause the original program, and the new VR game can’t get the HMD control either, it is not useful at all,

thanks a lot

Hi man

I am not sure what you want to do with that other vr game, but there are two ways to start a new subprocess.

First is FMonitoredProcess. If you use FMonitoredProcess you can start a program with a task in mind and have it done. You should receive outputs if the process is designed to send messages.

Second is FInteractiveProcess, which starts the program and never terminates it as long as you don’t want to. Also you can send commands and can receive reply through this system if the process is designed to send messages. NOTE: If you use this method please know that it is buggy as of 4.12, but will be fixed by 4.13 i hope. Look at here https://github.com/EpicGames/UnrealEngine/pull/2650

By the way if you explain what you want to do a bit more detailed, i may help more. Also it seems to me you are at the wrong place. Because only people who would need these two methods are either engine coders or chess game developers such as me.

Thanks for your messages, could you recommend a place to find examples of the process above? Have had a hard couple days finding ones that work. Specifically at this point, I’d love an example of defining the callback function that is run OnOutput, and processing the output the process returns via stdout. Thanks again

Here is an example:

First bind OnOutput with a function you created

CEProcess->OnOutput().BindUObject(this, &ACECommunication::OnProcessOutput);

Then create the necessery functionality inside your function

void ACECommunication::OnProcessOutput(const FString &Message)
{
	int32 From = Message.Find("bestmove ");
	if (From >= 0)
	{
		EngineResponseLastLine = Message;
		OnBestMoveReceived.Broadcast();
		return;
	}

	From = Message.Find("uciok");
	if(From >= 0)
	{
		SendCommandToCE("ucinewgame");
		return;
	}

	From = Message.Find("Stockfish 7 by ");
	if(From >= 0)
	{
		SendCommandToCE("uci");
		return;
	}
}

Thanks very much, that is part of what I’m looking for, but still having some problems. Basically, I’m trying to have use FMonitoredProcess to let me execute SQLite queries on another thread and return id’s of matching rows over stdout. Let me show you what I have so far:

// Called when the game starts or when spawned
void AActiveStarRegistry::HandleOutput(FString msg)
{
	dbDebug(TEXT("OUTPUT RECEIVED"));
}

// Called when the game starts or when spawned
void AActiveStarRegistry::HandleCompleted(int32 code)
{
	dbDebug(TEXT("DONE"));
}

// Called from blueprint
int32 AActiveStarRegistry::RunQuery()
{
	dbDebug(TEXT("Running query..."));

	const FString query = TEXT("\"SELECT id FROM stars\"");
	
	FMonitoredProcess testProc = FMonitoredProcess(TEXT("F:\\UnrealProjects\\StarChamber\\StarChamber_Alpha\\Content\\Subprocesses\\DummyDB.exe"), query, true);
	testProc.OnOutput().BindUObject(this, &AActiveStarRegistry::HandleOutput);
	testProc.OnCompleted().BindUObject(this, &AActiveStarRegistry::HandleCompleted);
	testProc.Launch();
	
	return (int32)testProc.IsRunning();
}

The above code compiles properly, and doesn’t seem to throw any errors. I get a “1” returned from the IsRunning() method, but the Output and Completed handlers are never called no matter what I try. I tried the arrow notation you specified above and it throws an error, also changing the string handler to “const FString &msg” throws errors as well. I’m using engine 4.12.5, and DummyDB.exe just prints the numbers 0 - 9 out one line at a time to stdout, so I know nothing’s failing there.

Are there any other syntax errors you see above? Would you be willing to share more of your implementation? I’ve been unable to find any example code that shows the whole process start to finish for getting output from a command line tool.

Thanks again! Can’t wait to get this part done so I can start actually working on the game :slight_smile:

OK, I’ve got it working! Thanks again for your help. Here is the relevant code for anyone following along, these methods were added to a standard Actor C++ template, no additional header libraries are necessary. In this case, I pass a query to a command line tool as an argument, and then each line the tool returns will be passed to the OnProcessOutput function as a string, and the exit code (aka return value of the main() function in the command line tool) is passed to the function OnProcessCompleted as an int:

// Called when the subprocess receives data
void AActiveStarRegistry::OnProcessOutput(FString msg)
{
	
}

// Called when the subprocess completes
void AActiveStarRegistry::OnProcessCompleted(int32 exitCode)
{
	
}

// Called when the game starts or when spawned
int32 AActiveStarRegistry::RunQuery()
{
	// build the query string we'll send to our separate query processor
	const FString query = FString::Printf(TEXT("\"SELECT id FROM data WHERE id BETWEEN %f and %f\""), qOffset, qLimit);
	
	// create a monitored process instance using our query
	FMonitoredProcess *testProc = new FMonitoredProcess(TEXT("F:\\UnrealProjects\\StarChamber\\StarChamber_Alpha\\Content\\Subprocesses\\SQLiteQueryProcess.exe"), query, true);
	
	// bind listeners to output and completion events
	testProc->OnOutput().BindUObject(this, &AActiveStarRegistry::OnProcessOutput);
	testProc->OnCompleted().BindUObject(this, &AActiveStarRegistry::OnProcessCompleted);
	
	// launch the process
	testProc->Launch();
	
	return (int32)testProc->IsRunning();
}

And here are the methods I added to the actor’s header file:

	UFUNCTION(BlueprintCallable, Category = "DB")
	int32 RunQuery();

	void OnProcessOutput(FString msg);

	void OnProcessCompleted(int32 exitCode);

When I call RunQuery from a blueprint, it passes the query string generated from local variables to the executable, which returns a list of ids that match that query. The query itself is on a separate thread, so it doesn’t block execution while processing. Also, because we are streaming from stdout, we recieve results as they happen, rather than waiting for them all to be buffered and then returned in one chunk.

One question I do have if anybody knows: how do you do relative links in the URL field for FMonitoredProcess? How do you determine a path to something in project content?

Its good you got it working however i have a few suggestions for you.

  1. Never use “\”, instead use “/” for paths. Even on Windows platforms. And yes it won’t cause any problem and will work fine

  2. Dont hardcode your paths if possible, that seems a horrible method. Better find another way to deal with these things

Well i am not sure if there is a way, but i don’t think so.

First of all these two methods are created for pipe messaging, which is nothing more then text messages, with processes.

Secondly, i am not sure of this one, it seems to me like what you want is to create an emulater which you can play certain games… somehow. I doubt UE4 is designed in such a way.

But i am just guessing things, you should still make some research

Thanks for your messages, may be it’s not the key point.
For example, I create a program which is running on Vive named OpenApp, and I create a function which can open another VRGame, such as ZenBlade.
When I run the program, first the ZenBlade can’t be controlled by Vive, there is no input, the Vive doesn’t connect with the game. Second my program OpenApp is auto closed, it obviously isn’t what I want.
So I try some ways to deal with it, the most effective way is I run under code.

UGameplayStatics::GetPlayerController(inWorld, 0)->ConsoleCommand("quit");
procHandler = FPlatformProcess::CreateProc(*AppPath, nullptr, true, false, false, nullptr, 0, nullptr, nullptr);

It will make OpenApp release the connection with Vive, and close itself. But the ZenBlade can correctly get the connection with Vive and be played with VR.
Is there any way can prevent my OpenApp do not quit, and I can also open and play the ZenBlade with Vive, and when I quit the ZenBlade, I can return to the OpenApp. It seems not a big issue, but it really doesn’t work at all.
I search the steamVR plugins, it seems doesn’t have any way to deal with it.
May be what I say is a little confused, it is really a simple question.
Thanks for your answer again, my English is really pool. I wish my expression doesn’t confuse you:)