Download

Error packaging HoloLens2 project when adding WinRT

I am trying to add WinRT so I can get access to those capabilities (e.g., saving files on the HoloLens2). My project packages and runs great on the PC and HL2. However, when I add the lines for the “Build.cs” file specified in the documentation the project runs fine on the PC and connected to the HL2 but the packaging fails at the following step:

  • [1/9] SharedPCH.Engine.Exceptions.ShadowErrors.Cpp17.cpp.

The generated log files are shown below.
Log.txt (25.1 KB)
UBT-viper_ar_hololensGame-HoloLens-Shipping.txt (28.6 KB)

Note: At this stage I am not trying to save to the HL2. I’m just step-by-step trying to get to the point where I can do that.

I really have no idea where to go from here so I cast my lure into the murky depths of the forum. Thanks for any help you may be able to provide.

Things I’ve tried:

  • [SOLVED] fatal error C1853 on Plugin Packaging only - #16 by erol_demirci
    • “Deleting Build, Intermediate, Saved and Visual Studio .sln file then rebuilding”
    • Delete “\UE_4.26\Engine\Intermediate\Build\Win64\UE4Editor\Development\Engine\SharedPCH.Engine.h.pch”… this file didn’t exist in that location nor, it seems, on my computer at all… Is this the issue??? Did find some other *.pch files in Intermediate folder but those did get deleted already.
    • Moving project from Documents folder… My project is not in that folder.
    • Removed Windows 10 SDK (10.0.18362.0) using VS Installer - the 10.0.19041.0 was still installed. Then deleted Build, Intermediate, Saved and Visual Studio .sln file then rebuilt. Then went to Project Settings>Platform>HoloLens>Toolchain>Windows 10 SDK Version and selected 10.0.19041.0. Still failing :frowning: .

UPDATE:
After some communication with Microsoft, there appears that the issue may be something related to Visual Studio. The following commit was found on the UE4 repo and may be a work around:
Fix compilation error when using C++17 due to workaround for Visual S… · EpicGames/UnrealEngine@b69d5dc (github.com)

To test I grabbed 4.27 Preview 2 and rebuilt my project. The packaging step now proceeds past the error above :grinning_face_with_smiling_eyes: … but… now UXTools may be causing things to fail… :frowning: … so not fixed but progress… stay tuned…

Update 2:
With the help of Joe from Microsoft, my colleague Tom, and some patches from the Unreal folks I think I’ve got a save feature working well enough for prototypes. Below is an attempt to document what worked. Hopefully I didn’t miss something.

Tested using UE4.27 and UXTools 0.12x-UE4.27

  • note UE4.27 corrected some issue that prevents this from working in earlier versions
  • This lets one use the built-in UE save function: FFileHelper::SaveStringArrayToFile
  1. In the project build.cs file add the following
		// Added to attempt to enable saving on the hololens
		// https://docs.microsoft.com/en-us/windows/mixed-reality/develop/unreal/unreal-winRT?tabs=426
		if (Target.Platform == UnrealTargetPlatform.Win64 || Target.Platform == UnrealTargetPlatform.HoloLens)
		{
			// These parameters are mandatory for winrt support
			bEnableExceptions = true;
			bUseUnity = false;
			CppStandard = CppStandardVersion.Cpp17;
			PublicSystemLibraries.AddRange(new string[] { "shlwapi.lib", "runtimeobject.lib" });
			PrivateIncludePaths.Add(Path.Combine(Target.WindowsPlatform.WindowsSdkDir,
												"Include",
												Target.WindowsPlatform.WindowsSdkVersion,
												"cppwinrt"));

		}
  1. In the cpp file where the save file function is used add the following:
// start winrt headers
#if (PLATFORM_WINDOWS || PLATFORM_HOLOLENS) 
//Before writing any code, you need to disable common warnings in WinRT headers
#pragma warning(disable : 5205 4265 4268 4946)

#include "Windows/AllowWindowsPlatformTypes.h"
#include "Windows/AllowWindowsPlatformAtomics.h"
#include "Windows/PreWindowsApi.h"

#include <unknwn.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Storage.h>

#include "Windows/PostWindowsApi.h"
#include "Windows/HideWindowsPlatformAtomics.h"
#include "Windows/HideWindowsPlatformTypes.h"
#endif
  1. The way I then set up my save function was as follows. For me this is a blueprint function that I use in my Blueprints. Note this function will work both on the computer, connected to the Hololens from the computer, and via packaged projects solely on the Hololens.

.h file

	UFUNCTION(BlueprintCallable, Category = "File Utilities")
		static bool SaveStringArrayToFile(FString SaveDirectory, FString FileName, TArray<FString> SaveText, bool bAllowOverWriting = false, bool bAppend = false);

.cpp file

bool UBPFL_FileUtilities::SaveStringArrayToFile(FString SaveDirectory, FString FileName, TArray<FString> SaveText, bool bAllowOverWriting, bool bAppend)
{
    SaveDirectory += "\\" + FileName;

    #if (PLATFORM_HOLOLENS) 
    try
    {
        std::string localPath = winrt::to_string(winrt::Windows::Storage::ApplicationData::Current().LocalFolder().Path());
        auto localFolder = winrt::Windows::Storage::ApplicationData::Current().LocalFolder();

        localFolder.CreateFolderAsync(L"SavedData");

        // When saving to hololens grab only the actual filename and force save in the specified folder
        int32 iName;
        FileName.FindLastChar(TEXT('/'), iName);

        FString savePathHL = UTF8_TO_TCHAR(localPath.c_str());
        SaveDirectory = savePathHL + "\\SavedData\\" + FileName.RightChop(iName + 1);
    }
    catch (winrt::hresult_error const& ex)
    {
        UE_LOG(LogTemp, Warning, TEXT("error %s"), ex.message().c_str());
    }
    #endif

    if (!bAppend)
    {
        if (!bAllowOverWriting)
        {
            if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*SaveDirectory))
            {
                return false;
            }
        }
    }

    if (bAppend)
    {
        return FFileHelper::SaveStringArrayToFile(SaveText, *SaveDirectory, FFileHelper::EEncodingOptions::AutoDetect, &IFileManager::Get(), FILEWRITE_Append);
    }
    return FFileHelper::SaveStringArrayToFile(SaveText, *SaveDirectory);
}

Some notes:

  • localFolder.Path() returns an hstring (trying to call c_str() on it just would return the first character… weird). Thus an issue I ran into was needing to convert that first to std::string and then c_str and then finally to FString. The way that worked was to define localPath and then use that rather than localFolder.Path() directly. If I didn’t define a separate variable then I just got errors. IDK. shrug.
  • There are a lot of restrictions on where you can save on the Hololens. The only way I could easily save files was to save it in the folder of the running app. Tried lots of things to save elsewhere but perhaps I just missed somethign. Anyways, this creates a folder and saved everything linked to this function in that “SavedData” folder. To access the location from the Windows Portal go the File Explorer and then navigate to LocalAppData\YOURAPPPROJECT\LocalState\SavedData
  • The part of iName and FileName has to do with how I was formatting inputs. Letting users use relative directories on the computer but forcing a specific location on the Hololens.

I think that is it. Looking back it doesn’t look too terrible but that’s how things are. When you’re done they don’t seem so bad and you wonder why it took so long. Haha. Cheers!