winrt::hresult_class_not_registered using Unreal Engine 4

Zaratusa 1 Reputation point
2022-06-30T21:32:11.83+00:00

Hi,

I've followed the WinRT in Unreal tutorial to integrate the Vungle SDK for Windows to build a Win64 game with in-game ads in Unreal Engine 4.27.
Compiling and using WinRT functions, as well as loading the VungleSDK.winmd works fine, but calling a Vungle function causes a "class not registered" error.
Is there an extra step involved, when using the WinRT in Unreal tutorial for Win64 instead of HoloLens games?

packages.config file:

<?xml version="1.0" encoding="utf-8"?>  
<packages>  
  <package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />  
  <package id="Microsoft.VCRTForwarders.140" version="1.0.6" targetFramework="native" />  
  <package id="VungleSDK" version="6.11.0" targetFramework="native" />  
</packages>  

.Build.cs file:

// these parameters mandatory for winrt support  
bEnableExceptions = true;  
bUseUnity = false;  
CppStandard = CppStandardVersion.Cpp17;  
PublicSystemLibraries.AddRange(new string[] { "shlwapi.lib", "runtimeobject.lib" });  
  
// prepare everything for nuget  
string NugetFolder = Path.Combine(PluginDirectory, "Intermediate", "Nuget");  
Directory.CreateDirectory(NugetFolder);  
  
string BinariesSubFolder = Path.Combine("Binaries", "ThirdParty", Target.Type.ToString(), Target.Platform.ToString(), Target.Architecture);  
  
PrivateDefinitions.Add(string.Format("THIRDPARTY_BINARY_SUBFOLDER=\"{0}\"", BinariesSubFolder.Replace(@"\", @"\\")));  
  
string BinariesFolder = Path.Combine(PluginDirectory, BinariesSubFolder);  
Directory.CreateDirectory(BinariesFolder);  
  
ExternalDependencies.Add("packages.config");  
  
// download nuget  
string NugetExe = Path.Combine(NugetFolder, "nuget.exe");  
if (!File.Exists(NugetExe))  
{  
	using (System.Net.WebClient myWebClient = new System.Net.WebClient())  
	{  
		// we aren't focusing on a specific nuget version, we can use any of them but the latest one is preferable  
		myWebClient.DownloadFile(@"https://dist.nuget.org/win-x86-commandline/latest/nuget.exe", NugetExe);  
	}  
}  
  
// run nuget to update the packages  
{  
	var StartInfo = new System.Diagnostics.ProcessStartInfo(NugetExe, string.Format("install \"{0}\" -OutputDirectory \"{1}\"", Path.Combine(ModuleDirectory, "packages.config"), NugetFolder));  
	StartInfo.UseShellExecute = false;  
	StartInfo.CreateNoWindow = true;  
	var ExitCode = Utils.RunLocalProcessAndPrintfOutput(StartInfo);  
	if (ExitCode < 0)  
	{  
		throw new BuildException("Failed to get nuget packages.  See log for details.");  
	}  
}  
  
// get list of the installed packages, that's needed because the code should get particular versions of the installed packages  
string[] InstalledPackages = Utils.RunLocalProcessAndReturnStdOut(NugetExe, string.Format("list -Source \"{0}\"", NugetFolder)).Split(new char[] { '\r', '\n' });  
  
// winmd files of the packages  
List<string> WinMDFiles = new List<string>();  
  
// WinRT lib for some job  
string VunglePackage = InstalledPackages.FirstOrDefault(x => x.StartsWith("VungleSDK"));  
if (!string.IsNullOrEmpty(VunglePackage))  
{  
	string QRFolderName = VunglePackage.Replace(" ", ".");  
  
	// copying dll and winmd binaries to our local binaries folder  
	// !!!!! please make sure that you use the path of file! Unreal can't do it for you !!!!!  
	string WinMDFile = Path.Combine(NugetFolder, QRFolderName, @"lib\uap10.0\VungleSDK.winmd");  
	File.Copy(WinMDFile, Path.Combine(BinariesFolder, "VungleSDK.winmd"), true);  
  
	// also both both binaries must be in RuntimeDependencies  
	RuntimeDependencies.Add(Path.Combine(BinariesFolder, "VungleSDK.winmd"));  
  
	//add winmd file to the list for further processing using cppwinrt.exe  
	WinMDFiles.Add(WinMDFile);  
}  
  
if (Target.Platform == UnrealTargetPlatform.Win64)  
{  
	// Microsoft.VCRTForwarders.140 is needed to run WinRT dlls in Win64 platforms  
	string VCRTForwardersPackage = InstalledPackages.FirstOrDefault(x => x.StartsWith("Microsoft.VCRTForwarders.140"));  
	if (!string.IsNullOrEmpty(VCRTForwardersPackage))  
	{  
		string VCRTForwardersName = VCRTForwardersPackage.Replace(" ", ".");  
		foreach (var Dll in Directory.EnumerateFiles(Path.Combine(NugetFolder, VCRTForwardersName, "runtimes/win10-x64/native/release"), "*_app.dll"))  
		{  
			string newDll = Path.Combine(BinariesFolder, Path.GetFileName(Dll));  
			File.Copy(Dll, newDll, true);  
			RuntimeDependencies.Add(newDll);  
		}  
	}  
}  
  
// get WinRT package   
string CppWinRTPackage = InstalledPackages.FirstOrDefault(x => x.StartsWith("Microsoft.Windows.CppWinRT"));  
if (!string.IsNullOrEmpty(CppWinRTPackage))  
{  
	string CppWinRTName = CppWinRTPackage.Replace(" ", ".");  
	string CppWinRTExe = Path.Combine(NugetFolder, CppWinRTName, "bin", "cppwinrt.exe");  
	string CppWinRTFolder = Path.Combine(PluginDirectory, "Intermediate", CppWinRTName);  
	Directory.CreateDirectory(CppWinRTFolder);  
  
	// all downloaded winmd file with WinSDK to be processed by cppwinrt.exe  
	var WinMDFilesStringbuilder = new System.Text.StringBuilder();  
	foreach (var winmd in WinMDFiles)  
	{  
		WinMDFilesStringbuilder.Append(" -input \"");  
		WinMDFilesStringbuilder.Append(winmd);  
		WinMDFilesStringbuilder.Append("\"");  
	}  
  
	// generate winrt headers and add them into include paths  
	var StartInfo = new System.Diagnostics.ProcessStartInfo(CppWinRTExe, string.Format("{0} -optimize -input \"{1}\" -output \"{2}\"", WinMDFilesStringbuilder, Target.WindowsPlatform.WindowsSdkVersion, CppWinRTFolder));  
	StartInfo.UseShellExecute = false;  
	StartInfo.CreateNoWindow = true;  
	var ExitCode = Utils.RunLocalProcessAndPrintfOutput(StartInfo);  
	if (ExitCode < 0)  
	{  
		throw new BuildException("Failed to get generate WinRT headers.  See log for details.");  
	}  
  
	PrivateIncludePaths.Add(CppWinRTFolder);  
}  
else  
{  
	// fall back to default WinSDK headers if no winrt package in our list  
	PrivateIncludePaths.Add(Path.Combine(Target.WindowsPlatform.WindowsSdkDir, "Include", Target.WindowsPlatform.WindowsSdkVersion, "cppwinrt"));  
}  

Module:

void StartupModule() override  
{  
	const FString LibrariesDir = FPaths::ProjectPluginsDir() / "Vungle" / THIRDPARTY_BINARY_SUBFOLDER;  
	FPlatformProcess::PushDllDirectory(*LibrariesDir);  
  
	const FString DllName = "VungleSDK.winmd";  
	if (!FPlatformProcess::GetDllHandle(*DllName))  
	{  
		UE_LOG(LogVungle, Warning, TEXT("Dll \'%s\' can't be loaded from \'%s\'"), *DllName, *LibrariesDir);  
	}  
  
	FPlatformProcess::PopDllDirectory(*LibrariesDir);  
  
	init_apartment(apartment_type::single_threaded);  
  
	const FString InAppID = TEXT("Test");  
	std::string AppID = TCHAR_TO_UTF8(*InAppID);  
	auto instance = AdFactory::GetInstance(to_hstring(AppID));  
}  
Not Monitored
Not Monitored
Tag not monitored by Microsoft.
41,891 questions
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.