Rama's Extra Blueprint Nodes for UE5, No C++ Required!


:star2: Get Text From Any :racehorse: :dash: Running .EXE on Your Computer! :sparkling_heart:

URamaVictoryPluginCreateProcessPipe Object :zap: is Born! :zap:


:zap: Below is a picture of me capturing the output of a .exe on my computer, a video compression tool, HandBrake! :zap:

The output of STDOUT of the .exe is coming directly into UE4, :rose: using only Blueprints! :rose:

I’ve made a new version of the Victory Plugin ( 4.27 (win32, win64 only) in original post ) !

This new version allows you to create a :rose: Very Special :rose: URamaVictoryPluginCreateProcessPipe to capture your Process output, if the Process is outputting to STDOUT (console window) or STDERR

  1. Construct the RamaVictoryPluginCreateProcessPipe object

  2. Pass it into VictoryCreateProc

  3. Call ReadFromPipe on the object periodically to get updates from your process

  4. When done, please call ClosePipe on the object, and null the reference to the object (I call ClosePipe inside of object BeginDestroy, but might as well :zap: take initiative :zap: yourself and close the actual OS pipe yourself immediately, rather than waiting for Garbage Collection)


Relevant UE4 C++ Code


.h

/** 
	Made With Love By  for Use with @VictoryCreateProc
	So that you can receive feedback from your processes.
	
	♥
	
	
*/
UCLASS(Blueprintable,BlueprintType)
class URamaVictoryPluginCreateProcessPipe : public UObject
{
	GENERATED_BODY()
public:
	 
	UFUNCTION(BlueprintCallable, Category = "Joy Flow")
	bool CreatePipe();
	
	UFUNCTION(BlueprintCallable, Category = "Joy Flow")
	void ClosePipe();
	
	/** 
		This has exec pins because it is an expensive action and the output is saved/cached on the output pin, whereas a Pure node would repeat the action many times, each time node is accessed.
		
		@Return false if the pipes were not created yet
		
		♥  
	*/
	UFUNCTION(BlueprintCallable, Category = "Joy Flow")
	bool ReadFromPipe(FString& PipeContents);
	
	UFUNCTION(BlueprintPure, Category = "Joy Flow")
	bool PipeIsValid();
	
public:
	void* ReadPipe = nullptr;
	void* WritePipe = nullptr;
	
	virtual void BeginDestroy() override;
};

.cpp

bool URamaVictoryPluginCreateProcessPipe::CreatePipe()
{
	if(PipeIsValid())
	{
		//Ignore repeat creates without a close inbetween <3 
		return true;
	}
	return FPlatformProcess::CreatePipe( ReadPipe, WritePipe );
}
void URamaVictoryPluginCreateProcessPipe::ClosePipe()
{
	if(PipeIsValid())
	{
		FPlatformProcess::ClosePipe(ReadPipe, WritePipe);
		ReadPipe = nullptr;
		WritePipe = nullptr;
	}
}
bool URamaVictoryPluginCreateProcessPipe::ReadFromPipe(FString& PipeContents)
{
	PipeContents = "";
	
	if(!PipeIsValid()) 
	{
		return false;
	}
	PipeContents = FPlatformProcess::ReadPipe(ReadPipe);
	return true;
}
bool URamaVictoryPluginCreateProcessPipe::PipeIsValid()
{
	return ReadPipe != nullptr && WritePipe != nullptr;
}

void URamaVictoryPluginCreateProcessPipe::BeginDestroy()
{
	Super::BeginDestroy();
	//~~~~~~~~~~~~~~~~~~~~
	
	//Close pipe if it was still open! ♥ 
	ClosePipe();
}

:heart:

1 Like