Register the manifest when Steam already lists the app key

Steam writes every VR app the user owns into its generated
steamapps.vrmanifest, installed or not. Whoever owns OVRAS on Steam
therefore always has steam.overlay.1009850 registered, as a steam:// URL
without a working directory, and --force-install-manifest failed with
"Could not find working directory of already installed application:
VRApplicationError_PropertyNotSet" (found on the Steam Frame).

Such an entry has no manifest file to remove, so OVRAS now leaves it
alone and adds its own manifest. Whether SteamVR accepts a second
manifest for the key, and which entry it then uses, is not documented:
logApplicationEntry() logs what SteamVR reports for the key after
installing, so a test on the Frame shows it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 23:25:57 +02:00
co-authored by Claude Opus 5.5
parent 317db6831d
commit ec82b5fead
4 changed files with 112 additions and 0 deletions
+61
View File
@@ -191,6 +191,29 @@ void reinstallApplicationManifest( const std::string manifestPath )
kStringSize,
&app_error );
// Steam lists every VR app the user owns in its generated
// steamapps.vrmanifest, installed or not, so whoever owns OVRAS on
// Steam has this key registered with a steam:// URL and no working
// directory. There is no manifest file to remove then: add ours next
// to it (installApplicationManifest() would skip the installed key).
if ( app_error == vr::VRApplicationError_PropertyNotSet )
{
qInfo() << "Key registered without a manifest file (e.g. by "
"Steam), not removing it";
const auto add_error = vr::VRApplications()->AddApplicationManifest(
manifestPath.c_str() );
if ( add_error != vr::VRApplicationError_None )
{
throw std::runtime_error(
"Could not add application manifest: "
+ std::string(
vr::VRApplications()->GetApplicationsErrorNameFromEnum(
add_error ) ) );
}
qInfo() << "Manifest Installed at: " << manifestPath;
return;
}
if ( app_error != vr::VRApplicationError_None )
{
throw std::runtime_error(
@@ -251,6 +274,43 @@ void forceRemoveApplicationManifest()
}
}
// Logs what SteamVR reports for OVRAS's app key, to show which entry it uses
// when several register the key (e.g. Steam's own, see
// reinstallApplicationManifest()).
void logApplicationEntry()
{
const auto property = []( vr::EVRApplicationProperty prop )
{
constexpr auto kStringSize = 1024;
char value[kStringSize] = { 0 };
auto error = vr::VRApplicationError_None;
vr::VRApplications()->GetApplicationPropertyString(
application_strings::applicationKey,
prop,
value,
kStringSize,
&error );
return error == vr::VRApplicationError_None
? QString( value )
: QString(
vr::VRApplications()->GetApplicationsErrorNameFromEnum(
error ) );
};
qInfo() << "SteamVR entry for" << application_strings::applicationKey
<< "- source:"
<< property( vr::VRApplicationProperty_Source_String )
<< "launch type:"
<< property( vr::VRApplicationProperty_LaunchType_String )
<< "working dir:"
<< property( vr::VRApplicationProperty_WorkingDirectory_String )
<< "binary:"
<< property( vr::VRApplicationProperty_BinaryPath_String )
<< "URL:" << property( vr::VRApplicationProperty_URL_String )
<< "auto-launch:"
<< vr::VRApplications()->GetApplicationAutoLaunch(
application_strings::applicationKey );
}
// Initializes OpenVR and calls the relevant manifest functions.
// The .vrmanifest is used by SteamVR however the exact functiontionality is not
// documented in the official documentation.
@@ -298,6 +358,7 @@ void forceRemoveApplicationManifest()
reinstallApplicationManifest( *manifestPath );
enableApplicationAutostart();
qInfo() << "Manifest reinstalled.";
logApplicationEntry();
}
else if ( removeManifest )
{