Skip to content

Instantly share code, notes, and snippets.

@hyblocker
Last active December 6, 2022 08:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hyblocker/e25f39fe693ad1cac70fe999f681a274 to your computer and use it in GitHub Desktop.
Save hyblocker/e25f39fe693ad1cac70fe999f681a274 to your computer and use it in GitHub Desktop.
Null driver enabler
using Microsoft.Win32;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
// Half the code was taken from Amethyst Installer because Amethyst Installer just works
namespace enable_null_driver {
public class OpenVrPaths {
public List<string> config { get; set; }
public List<string> external_drivers { get; set; }
public string jsonid { get; set; }
public List<string> log { get; set; }
public List<string> runtime { get; set; }
public int version { get; set; }
}
static class OpenVR {
private static string s_steamvrSettingsPath = null;
private static string s_openvrPathsPath = null;
private static OpenVrPaths s_openvrpaths = null;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static string GetSteamInstallDirectory() {
// Get Steam Directory from Registry, starting with 64-bit and falling back to 32-bit
string steamInstallDirectory = ( string ) Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Valve\Steam", "InstallPath", string.Empty);
if ( Directory.Exists(steamInstallDirectory) )
return steamInstallDirectory;
else {
steamInstallDirectory = ( string ) Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam", "InstallPath", string.Empty);
if ( Directory.Exists(steamInstallDirectory) )
return steamInstallDirectory;
}
Console.WriteLine($"Failed to locate Steam Install directory. Is Steam installed on this system?");
return string.Empty;
}
public static string RuntimePath() {
// Try reading openvrpaths, and grab the runtime field.
// From there: for each entry, try checking if the directory exists, and, if so, return it
if ( s_openvrpaths != null ) {
try {
for ( int i = 0; i < s_openvrpaths.runtime.Count; i++ ) {
if ( Directory.Exists(s_openvrpaths.runtime[i]) )
return s_openvrpaths.runtime[i];
}
} catch ( Exception ) {
Console.WriteLine($"Failed to fetch runtime argument from OpenVR Paths, is OpenVR Paths corrupt?");
}
}
// Disable vrpathreg
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Steam", "steamapps", "common", "SteamVR");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void ComputeSteamVRSettingsPath() {
if ( s_openvrpaths != null ) {
// Try getting SteamVR Settings from OpenVR Paths
for ( int i = 0; i < s_openvrpaths.config.Count; i++ ) {
if ( Directory.Exists(s_openvrpaths.config[i]) ) {
s_steamvrSettingsPath = Path.Combine(s_openvrpaths.config[i], "steamvr.vrsettings");
return;
}
}
}
// Fallback to Steam Directory
var steamInstallDirectory = GetSteamInstallDirectory();
if ( Directory.Exists(steamInstallDirectory) ) {
s_steamvrSettingsPath = Path.Combine(steamInstallDirectory, "config", "steamvr.vrsettings");
}
}
/// <summary>
/// Kills a long list of processes which are known to conflict with the installation process
/// due to them having a high chance of opening SteamVR during the install process.
/// </summary>
public static void TryKillingConflictingProcesses() {
// K2EX
ForceKillProcess("kinectv1process");
ForceKillProcess("kinectv2process");
ForceKillProcess("psmsprocess");
ForceKillProcess("kinecttovr");
// Amethyst
ForceKillProcess("amethyst");
ForceKillProcess("k2crashhandler");
// ALVR
ForceKillProcess("alvr launcher");
// PiTool
ForceKillProcess("pitool");
ForceKillProcess("pimaxclient");
// WMR
ForceKillProcess("MixedRealityPortal.Brokered");
ForceKillProcess("MixedRealityPortal");
ForceKillProcess("WUDFHost");
// Vive Wireless Software
ForceKillProcess("htcconnectionutility");
// Pico Neo Software
// @TODO: Pico Neo Software
// ForceKillProcess("htcconnectionutility");
// Revive
ForceKillProcess("reviveinjector");
ForceKillProcess("reviveoverlay");
// SteamVR
ForceKillProcess("vrmonitor");
ForceKillProcess("vrdashboard");
ForceKillProcess("vrserver");
ForceKillProcess("vrservice");
ForceKillProcess("vrserverhelper");
ForceKillProcess("vrcompositor");
ForceKillProcess("vrstartup");
ForceKillProcess("vrwebhelper");
ForceKillProcess("overlay_viewer");
ForceKillProcess("removeusbhelper");
ForceKillProcess("restarthelper");
ForceKillProcess("vrcmd");
ForceKillProcess("vrpathreg");
ForceKillProcess("vrprismhost");
ForceKillProcess("vrurlhandler");
// SteamVR Lighthouse devices
ForceKillProcess("vivelink");
ForceKillProcess("vivetools");
ForceKillProcess("vivebtdriver");
ForceKillProcess("vivebtdriver_win10");
ForceKillProcess("lighthouse_console");
ForceKillProcess("lighthouse_watchman_update");
ForceKillProcess("nrfutil");
// VirtualDesktop
ForceKillProcess("virtualdesktop.streamer");
// Oculus processes
ForceKillProcess("oculusclient");
ForceKillProcess("oculusdash");
// SteamVR (again, just for good measure)
ForceKillProcess("vrmonitor");
ForceKillProcess("vrdashboard");
ForceKillProcess("vrserver");
ForceKillProcess("vrservice");
ForceKillProcess("vrserverhelper");
ForceKillProcess("vrcompositor");
ForceKillProcess("vrstartup");
ForceKillProcess("vrwebhelper");
ForceKillProcess("overlay_viewer");
ForceKillProcess("removeusbhelper");
ForceKillProcess("restarthelper");
ForceKillProcess("vrcmd");
ForceKillProcess("vrpathreg");
ForceKillProcess("vrprismhost");
ForceKillProcess("vrurlhandler");
// SteamVR Lighthouse devices (for good measure)
ForceKillProcess("vivelink");
ForceKillProcess("vivetools");
ForceKillProcess("vivebtdriver");
ForceKillProcess("vivebtdriver_win10");
ForceKillProcess("lighthouse_console");
ForceKillProcess("lighthouse_watchman_update");
ForceKillProcess("nrfutil");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ForceKillProcess(string processName) {
var processes = Process.GetProcessesByName(processName);
if ( processes.Length > 0 ) {
// kill each process via taskkill.exe
foreach ( var process in processes ) {
// yes we use taskkill, I don't want to deal with all the bullshit of "bad PID" using the P/Invoke approach
// besides taskkill is garuanteed to be on the current install anyway
var taskkillProc = Process.Start(new ProcessStartInfo() {
FileName = "taskkill.exe",
Arguments = $"/F /T /PID {process.Id}",
WindowStyle = ProcessWindowStyle.Hidden,
CreateNoWindow = true
});
taskkillProc.WaitForExit(10000);
}
}
}
private static bool LoadOpenVrPaths(bool force = false) {
try {
if ( s_openvrpaths == null || force == true ) {
s_openvrPathsPath = Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "AppData", "Local", "openvr", "openvrpaths.vrpath"));
if ( !File.Exists(s_openvrPathsPath) ) {
Console.WriteLine("openvrpaths.vrpath doesn't exist on the current system... Is SteamVR installed, and has it been run at least once?");
s_openvrpaths = null;
return false;
}
string vrpathsTxt = File.ReadAllText(s_openvrPathsPath);
s_openvrpaths = JsonConvert.DeserializeObject<OpenVrPaths>(vrpathsTxt);
return true;
}
} catch { }
return false;
}
static void Main(string[] args) {
// Try locating the SteamVR folder
if ( LoadOpenVrPaths(true) ) {
ComputeSteamVRSettingsPath();
string steamvrNullDriverPath = Path.Combine(RuntimePath(), "drivers", "null", "resources", "settings", "default.vrsettings");
if ( !File.Exists(steamvrNullDriverPath) ) {
Console.WriteLine("Failed to locate null driver! Giving up!");
Console.WriteLine($"(Tried looking in {steamvrNullDriverPath})!");
Console.WriteLine("\n\nPress any key to exit...");
Console.ReadKey(false);
return;
}
if ( !File.Exists(s_steamvrSettingsPath) ) {
Console.WriteLine("Failed to locate steamvr.vrsettings! Giving up!");
Console.WriteLine($"(Tried looking in {s_steamvrSettingsPath})!");
Console.WriteLine("\n\nPress any key to exit...");
Console.ReadKey(false);
return;
}
dynamic nullManifest = JObject.Parse(File.ReadAllText(steamvrNullDriverPath));
dynamic steamvrSettings = JObject.Parse(File.ReadAllText(s_steamvrSettingsPath));
if ( nullManifest["driver_null"] == null )
nullManifest["driver_null"] = new JObject();
if ( steamvrSettings["steamvr"] == null )
steamvrSettings["steamvr"] = new JObject();
if ( steamvrSettings["driver_null"] == null )
steamvrSettings["driver_null"] = new JObject();
bool earlyExit = false;
bool doEnable = false;
bool isEnabled = false;
if ( nullManifest["driver_null"]["enable"] != null ) {
isEnabled = nullManifest["driver_null"]["enable"];
}
if ( steamvrSettings["driver_null"]["enable"] != null )
isEnabled = steamvrSettings["driver_null"]["enable"];
Console.WriteLine($"SteamVR Null Driver Tool\n\n");
Console.WriteLine($"Found SteamVR Settings at \"{s_steamvrSettingsPath}\"");
Console.WriteLine($"Found Null Driver at \"{steamvrNullDriverPath}\"");
if ( isEnabled ) {
Console.WriteLine($"Do you want to disable the null driver? (Y/N)");
string res;
bool requestInput = true;
while ( requestInput ) {
res = Console.ReadLine();
if ( res.Length < 1 ) continue;
switch ( res[0] ) {
case 'Y':
case 'y':
doEnable = false;
requestInput = false;
earlyExit = false;
break;
case 'N':
case 'n':
doEnable = true;
requestInput = false;
earlyExit = true;
break;
}
}
} else {
Console.WriteLine($"Do you want to enable the null driver? (Y/N)");
string res;
bool requestInput = true;
while ( requestInput ) {
res = Console.ReadLine();
if ( res.Length < 1 ) continue;
switch ( res[0] ) {
case 'y':
case 'Y':
doEnable = true;
requestInput = false;
earlyExit = false;
break;
case 'N':
case 'n':
doEnable = false;
requestInput = false;
earlyExit = true;
break;
}
}
}
if ( earlyExit ) {
Console.WriteLine("Quitting...");
Console.WriteLine("\n\nPress any key to exit...");
Console.ReadKey(false);
return;
}
Console.WriteLine("\n\n\n");
TryKillingConflictingProcesses();
// Now try force enabling the driver
steamvrSettings["steamvr"]["requireHmd"] = !doEnable;
steamvrSettings["steamvr"]["forcedDriver"] = doEnable ? "null" : "";
steamvrSettings["steamvr"]["activateMultipleDrivers"] = true;
if (doEnable) {
steamvrSettings["driver_null"]["blocked_by_safe_mode"] = false;
steamvrSettings["driver_null"]["enable"] = doEnable;
} else {
((JObject) steamvrSettings["driver_null"] ).Parent.Remove();
}
nullManifest["driver_null"]["enable"] = doEnable;
if ( steamvrSettings != null ) {
string newSteamVrSettingsContents = JsonConvert.SerializeObject(steamvrSettings, Formatting.Indented);
File.WriteAllText(s_steamvrSettingsPath, newSteamVrSettingsContents);
Console.WriteLine("Updated steamvr settings file!");
}
if ( nullManifest != null ) {
string newNullDriverManifestContents = JsonConvert.SerializeObject(nullManifest, Formatting.Indented);
File.WriteAllText(steamvrNullDriverPath, newNullDriverManifestContents);
Console.WriteLine("Updated null driver manifest file!");
}
}
Console.WriteLine("Done!\n\nPress any key to exit...");
Console.ReadKey(false);
}
}
}
@AuroraNemoia
Copy link

cnlohr salutes you.

@hyblocker
Copy link
Author

To compile: Install Newtonsoft.JSON, and run the binary as administrator as it most likely has to write to program files.

You might want to use IlMerge to generate a single binary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment