Last active
December 6, 2022 08:16
-
-
Save hyblocker/e25f39fe693ad1cac70fe999f681a274 to your computer and use it in GitHub Desktop.
Null driver enabler
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
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
cnlohr salutes you.