Created
September 16, 2021 19:33
-
-
Save Erquint/a1b89aab864c94dc468fd106c4c1ed15 to your computer and use it in GitHub Desktop.
This script will enumerate processes hogging DS4 device stream handle, try to free the handle by temporarily unloading known hogs detected running, start DS4W and load the unloaded hogs back.
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
# Ruby 2.6.6 | |
# PowerShell 7.1 | |
# SysInternals Handle 4.22 | |
# DS4W 2.1.8 | |
require 'set' | |
$task_heap = Set.new | |
if (ARGV & ['--help', '-h']).any? | |
puts "This script will enumerate processes hogging DS4 device stream handle, | |
try to free the handle by temporarily unloading known hogs detected running, | |
start DS4W and load the unloaded hogs back. | |
Commands (multiple allowed, combining isn't): | |
\e[33m--help\e[0m or \e[33m-h\e[0m To print this help message and unload. | |
\e[33m-nv-on\e[0m To start NvContainerLocalSystem service and unload. | |
\e[33m-nv-off\e[0m To stop NvContainerLocalSystem service before continuing. | |
\e[33m-s-on\e[0m To start Steam and unload. | |
\e[33m-s-off\e[0m To terminate Steam before continuing. | |
\e[33m--manual\e[0m or \e[33m-m\e[0m To only enumerage and unload. Overrides other commands. | |
\e[33m--quick\e[0m or \e[33m-q\e[0m To skip precautions." | |
return | |
end | |
if (ARGV & ['--manual', '-m']).any? | |
$task_heap.add ?m | |
else | |
if ARGV.include? '-nv-on' | |
load_nv | |
$task_heap.add ?l | |
elsif ARGV.include? '-nv-off' | |
unload_nv | |
end | |
if ARGV.include? '-s-on' | |
load_steam | |
$task_heap.add ?l | |
elsif ARGV.include? '-s-off' | |
unload_steam | |
end | |
if (ARGV & ['--quick', '-q']).any? | |
$task_heap.add ?W | |
else | |
$task_heap.add ?w | |
end | |
$task_heap.add ?e | |
end | |
def unload_steam | |
system 'powershell Stop-Process -Name "steam"' | |
end | |
def load_steam | |
system ('powershell Start-Process -FilePath ' + `powershell (Get-ItemProperty -Path "HKLM:\\SOFTWARE\\Wow6432Node\\Valve\\Steam").InstallPath`.chomp + '\steam.exe -ArgumentList "-silent"') | |
end | |
def unload_nv | |
system 'powershell Stop-Service "NvContainerLocalSystem"' | |
end | |
def load_nv | |
system 'powershell Start-Service "NvContainerLocalSystem"' | |
end | |
def load_ds4w | |
system ('powershell Start-Process -FilePath E:\Programs\Emulators\DS4Windows\DS4Windows.exe') | |
end | |
PS_script = "Get-PnpDevice -Class 'HIDClass' ` | |
-InstanceId 'HID\\VID_054C&PID_0BA0*' -PresentOnly | | |
Get-PnpDeviceProperty -KeyName 'DEVPKEY_Device_PDOName' | | |
Select-Object -ExpandProperty 'Data' | | |
Format-Table -HideTableHeaders".gsub! /((?: `)?\n)/, ' ' | |
def flush_bush string_bush | |
if string_bush[:branches].size > 0 | |
puts string_bush[:root], string_bush[:branches] | |
if string_bush[:root].downcase.include? "steam" | |
$task_heap.add ?s | |
elsif string_bush[:root].downcase.include? "system" | |
$task_heap.add ?n | |
elsif string_bush[:root].downcase.include? "dwm" | |
$task_heap.add ?d | |
else | |
$task_heap.add ?p | |
end | |
end | |
end | |
def enumerate_hogging_processes | |
IO.popen('powershell -nologo', 'r+') do |stream| | |
stream.puts './handle64 -nobanner -a', 'Exit' | |
string_bush = {root: '', branches: []} | |
while in_line = stream.gets do | |
if !!(matches = /^(.+?) pid\: (\d+)/.match in_line) | |
# Process node | |
flush_bush string_bush | |
string_bush[:root] = in_line | |
string_bush[:branches] = [] | |
elsif !!(matches = /^ +?(\w+?)\: File .*? (#{Regexp.quote(Device_handle)})/.match in_line) | |
# Device handle node | |
string_bush[:branches] << in_line | |
end | |
end | |
flush_bush string_bush | |
end | |
end | |
def process_task_heap | |
until $task_heap.empty? | |
if $task_heap.include? ?l | |
puts 'No enumeration after loading programs.' | |
$task_heap = $task_heap & [?S, ?N] | |
end | |
if $task_heap.include? ?m | |
puts 'Manual mode engaged. Enumerating only.' | |
$task_heap = [?e].to_set | |
end | |
if $task_heap.include? ?e | |
enumerate_hogging_processes | |
$task_heap.delete ?e | |
end | |
if $task_heap.include? ?p | |
puts 'Panic: not an automated case.' | |
return | |
end | |
if $task_heap.include? ?d | |
puts "Ignoring DWM. It doesn't tend to interfere." | |
$task_heap.delete ?d | |
end | |
if $task_heap.include? ?s | |
puts 'Temporarily unloading Steam.' | |
unload_steam | |
$task_heap.add ?S | |
$task_heap.delete ?s | |
end | |
if $task_heap.include? ?n | |
puts 'Temporarily unloading NvContainerLocalSystem.' | |
unload_nv | |
$task_heap.add ?N | |
$task_heap.delete ?n | |
end | |
if ($task_heap & [?w, ?W]).any? | |
puts 'Loading DS4W.' | |
load_ds4w | |
if $task_heap.include? ?w | |
puts 'Turn on the controller, switch back here and press [ENTER].', | |
'This is a precautionary measure.' , | |
"If you are certain it isn't required — hit [ENTER] immediately.", | |
'We still might have temporarily-unloaded programs to load back up.' | |
system 'PAUSE' | |
end | |
$task_heap = $task_heap ^ ($task_heap & [?w, ?W]) | |
end | |
if $task_heap.include? ?S | |
puts 'Loading Steam back.' | |
load_steam | |
$task_heap.delete ?S | |
elsif $task_heap.include? ?N | |
puts 'Loading NvContainerLocalSystem back.' | |
load_nv | |
$task_heap.delete ?N | |
end | |
end | |
end | |
IO.popen('powershell -nologo', 'r+') do |stream| | |
out_string = String.new | |
stream.puts PS_script, 'Exit' | |
while in_line = stream.gets do | |
out_string << in_line | |
end | |
Device_handle = out_string.split("\n")[-2] | |
end | |
puts 'Device handle: ' + Device_handle, 'Users:' | |
process_task_heap |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment