vJoy Reboot Fix: A Registry Deep Dive with Claude Code
vJoy kept dying after every reboot. I had a startup fix that should have handled it, but something wasn't right. Time to go deeper.
The Setup
The X52 Pro Configurator already had an auto-fix built in — detect a missing vJoy device on startup, re-create it, restart the service. It worked if you clicked the button. But after a clean reboot? Dead silence. vJoy gone. Every time.
I'd been living with it. Open the configurator, click "Fix vJoy", accept the UAC prompt, wait, done. But that's not shipping software. That's a workaround pretending to be a feature.
Today I sat down with Claude Code and decided to actually find the root cause.
The Diagnostic
First thing — stop guessing and start measuring. I needed a snapshot of every layer in the vJoy stack before touching anything. Claude Code wrote a diagnostic script that checks eight layers in one pass:
- vJoy installation — where is vJoyConfig.exe?
- Service status — is the vJoy kernel driver running?
- Device accessibility — can pyvjoy open device 1?
- vJoyConfig state — what does the tool itself report?
- Registry — HIDCLASS — what device entries exist?
- Registry — service config — how is the service configured?
- HidHide status — is cloaking active, is the X52 hidden?
- X52 HID detection — can we see the physical hardware?
No guesswork, no "try this and see." Run one script, get the full picture.
The result was immediate and clear:
vJoy Service Status
STATE: 1 STOPPED
WIN32_EXIT_CODE: 1077 (0x435)
Service running: False
Exit code 1077 means "the service has not been started since the last boot."
The Root Cause
Services\vjoy
Start: 3 (type=4)
Type: 1
ImagePath: \SystemRoot\System32\drivers\vjoy.sys
Start type 3 — manual. The vJoy service is a kernel driver, and it's set to only start when something explicitly asks for it. After a reboot, nothing asks. So it sits there, dormant, while every game and configurator that depends on it fails silently.
The fix is one registry value: change Start from 3 to 2 (automatic). One DWORD. That's it.
The whole "vJoy dies after reboot" problem that plagues every forum thread and GitHub issue about vJoy? It's a service start type. Three bytes in the registry.
The Naming Problem
With the service fix in place, I wanted to brand the virtual device. In joy.cpl (Game Controllers), vJoy shows up as the generic "vJoy Device". I wanted it to say "indigo-Nx x52Pro Configurator."
Windows has a FriendlyName value in the HIDCLASS registry that controls what Device Manager shows. We set that — Device Manager updated. But joy.cpl? Still "vJoy Device."
This is where Claude Code earned its keep.
I asked it to find where joy.cpl actually reads the device name. Within seconds it was scanning the Joystick OEM registry:
HKLM\...\Joystick\OEM\VID_1234&PID_BEAD
(no OEMName set)
So we wrote OEMName to that key. Reopened joy.cpl. Still "vJoy Device."
Something else was overriding it.
The HKCU Discovery
Claude Code dug into HKEY_CURRENT_USER and found the answer:
HKCU\System\CurrentControlSet\Control\MediaProperties\
PrivateProperties\Joystick\OEM\VID_1234&PID_BEAD
OEMName: vJoy Device
Windows creates a per-user copy of the joystick OEM data the first time a device is seen. After that, HKCU always wins over HKLM. You can write to HKLM all day — joy.cpl reads HKCU first.
This isn't documented anywhere obvious. Microsoft's own docs talk about the HKLM path. Every Stack Overflow answer about changing joystick names points to HKLM. They're all wrong — or at least incomplete.
The fix: write to HKCU first (no admin needed), then HKLM as a fallback for new users.
oem_subpath = r"System\CurrentControlSet\Control\...\VID_1234&PID_BEAD"
for hive in (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE):
try:
key = winreg.OpenKey(hive, oem_subpath, 0, winreg.KEY_SET_VALUE)
winreg.SetValueEx(key, "OEMName", 0, winreg.REG_SZ, name)
winreg.CloseKey(key)
except Exception:
pass
Close joy.cpl. Reopen it. "indigo-Nx x52Pro Configurator." Done.
Claude Code as a Debug Tool
Here's the thing — I could have found all of this manually. Registry Editor, sc query, trial and error, Stack Overflow tabs. It would have taken an afternoon. Maybe longer, because the HKCU override isn't in any obvious documentation.
With Claude Code, the entire process — from "vJoy is broken" to "here's a branded, auto-starting, fully documented fix" — took under an hour. And I got:
- A diagnostic script that checks eight layers of the stack in one pass
- A fix script that handles service config, device creation, and branding in one elevated run
- Documentation covering every registry path, every gotcha, every edge case
- A reusable reference for branding any future device in joy.cpl
Claude Code didn't just search for answers. It ran the commands, read the output, changed direction when something didn't work, and found the undocumented HKCU override by systematically checking every registry hive. That's not autocomplete — that's a research partner with access to your actual system.
If you're doing any kind of Windows driver work, hardware debugging, or registry archaeology, Claude Code running in your terminal is genuinely the fastest path from "something's wrong" to "here's exactly why, and here's the fix."
The Summary
| Problem | Root Cause | Fix | |---|---|---| | vJoy dies after reboot | Service Start type = 3 (manual) | Set to 2 (automatic) | | joy.cpl shows "vJoy Device" | HKCU OEMName overrides HKLM | Write OEMName to HKCU first | | Device Manager shows generic name | No FriendlyName set | Write FriendlyName to HIDCLASS |
Three registry values. That's all it was. But knowing which three, and where — that's the hard part. And that's where having an AI that can actually run commands on your system and reason about the results makes all the difference.
Registry Quick Reference
For anyone building custom joystick/controller tools on Windows:
| What | Where |
|---|---|
| joy.cpl name (per-user) | HKCU\System\CurrentControlSet\Control\MediaProperties\PrivateProperties\Joystick\OEM\VID_xxxx&PID_xxxx → OEMName |
| joy.cpl name (system) | HKLM\SYSTEM\CurrentControlSet\Control\MediaProperties\PrivateProperties\Joystick\OEM\VID_xxxx&PID_xxxx → OEMName |
| Device Manager name | HKLM\SYSTEM\CurrentControlSet\Enum\ROOT\HIDCLASS\xxxx → FriendlyName |
| Service start type | HKLM\SYSTEM\CurrentControlSet\Services\vjoy → Start (DWORD: 2=auto, 3=manual) |
HKCU always wins for OEMName. Write there first.
Debugged with Claude Code. Published at indigo-nx.com.