Run external executable with GUI button

I tried to create a blueprint function using C++, but failed.
The function is not visible in the blueprint.

RunExternalTest.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "RunExternalTest.h"

//Sets default values
ARunExternalTest::ARunExternalTest()
{
	// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void ARunExternalTest::BeginPlay()
{
	Super::BeginPlay();

}

// Called every frame
void ARunExternalTest::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

/// <summary>
/// Execute external file
/// </summary>

UFUNCTION(BlueprintCallable, Category = "ControlExternalFiles")
void ARunExternalTest::RunExternalExeFile(const FString& AppPath, bool& Result, int& ProcessId)
{
	//Process ID
	uint32 OutProcessId = 0;
	ProcessId = 0;

	Result = false;

	//Execute file
	FProcHandle Proc = FPlatformProcess::CreateProc(*AppPath, NULL, true, false, false, &OutProcessId, -1, nullptr, nullptr);

	if (Proc.IsValid())
	{
		//If executed, return True to Result
		ProcessId = OutProcessId;
		Result = true;
	}
	else {
		//If it does not run, rerun with administrator privileges
		Result = FPlatformProcess::ExecElevatedProcess(*AppPath, NULL, nullptr);
	}
}

/// <summary>
/// Close the running external file
/// </summary>
UFUNCTION(BlueprintCallable, Category = "ControlExternalFiles")
void ARunExternalTest::TerminateExternalProgram(const int& ProcessId, bool& IsRunning)
{
	//Receive ProcHandle as Uint
	uint32 ProcessIdUint = ProcessId;
	FProcHandle Proc = FPlatformProcess::OpenProcess(ProcessIdUint);

	//Check if it is running
	IsRunning = FPlatformProcess::IsProcRunning(Proc);
	if (IsRunning)
	{
		//Close if running
		FPlatformProcess::TerminateProc(Proc);
		FPlatformProcess::CloseProc(Proc);
	}
}

/// <summary>
/// Check file execution
/// </summary>
UFUNCTION(BlueprintCallable, Category = "ControlExternalFiles")
void ARunExternalTest::GetExecutableName(const FString& FileName, bool& result)
{
	FStringName = FileName;
	result = FPlatformProcess::IsApplicationRunning(*Name);
}

RunExternalTest.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "RunExternalTest.generated.h"

UCLASS()
class MAIN_API ARunExternalTest : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ARunExternalTest();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UFUNCTION(BlueprintCallable, Category = "ControlExternalFiles")
		void RunExternalExeFile(const FString& AppPath, bool& Result, int& ProcessId);

	UFUNCTION(BlueprintCallable, Category = "ControlExternalFiles")
		void TerminateExternalProgram(const int& ProcessId, bool& IsRunning);

	UFUNCTION(BlueprintCallable, Category = "ControlExternalFiles")
		void GetExecutableName(const FString& FileName, bool& result);

};

the UFUNCTION() decorator/mark-up only needs to be in the declaration (the .h file)
-a const int& will be an integer of size 32 or 64 depending on architecture, and the suggestion by the engine is to specify the size of int to be int32 to increase consistency between platforms. and for a function argument needing to be passed by reference or pointer means that it will be accessible by both the receiver, and the caller upon completion, and marking it const means that it is immutable by the receiver. the short version is “if it is a integral data type (no bigger then int64) and the value shall be maintained by the caller, then just let it be passed by copy/value” const int& ProcessID → int32 ProcessID (unless you really really need a value outside of [-2.4 billion, 2.4 billion]
-if you are going to return a bool (this is my perception for the intent of bool& IsRunning) then let it be the return type. the function is void so it can have a return type it also allows for things like if(TerminateExternalProgram()) to be done inline as apposed to be split up across other lines and having to make a floating bool temp just to pass into the function with size of int read as a bool. though a boolean return of TerminateExternalProgram() would probably be something more like “IsStillRunning”

if you give the class a member variable as public decorated/marked-up with
UPROPERTY(BlueprintReadWrite)
does that show up in the blueprint (this is to test if the class is being compiled into the binaries for reflection in the first place)

try creating a

public:
UFUNCTION(BlueprintCallable)
void MyCallableFunction(){}

and see if you can find that pulling off a reference to one of these objects.

1 Like