From 94d004c40d179c2127a4f53ab21fea0200b0b83f Mon Sep 17 00:00:00 2001 From: TantalusDrive <236701476+TantalusDrive@users.noreply.github.com> Date: Thu, 20 Nov 2025 20:58:16 +0100 Subject: [PATCH 01/10] Add PowerShell script for advanced AMD OpenCL fix This PowerShell script extends the batch version with more advanced detection features: - Builds upon the batch version by supporting more complex registry queries - Handles both 32-bit and 64-bit environments with improved accuracy - Detects and registers multiple versioned DLLs automatically - Performs full PATH scan to locate hidden or unregistered drivers - Prevents duplicate entries and ensures clean registry state - Provides clearer diagnostic output and error reporting --- amdocl-fix.ps1 | 141 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 amdocl-fix.ps1 diff --git a/amdocl-fix.ps1 b/amdocl-fix.ps1 new file mode 100644 index 0000000..4998334 --- /dev/null +++ b/amdocl-fix.ps1 @@ -0,0 +1,141 @@ +# Run as Administrator +$roots = @( + "HKLM:\SOFTWARE\Khronos\OpenCL\Vendors", # 64-bit + "HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors" # 32-bit +) + +# Directories to scan (more complete than just System32) +$scanDirs = @( + "$env:WINDIR\System32", + "$env:WINDIR\SysWOW64", + "$env:WINDIR\System32\DriverStore\FileRepository" +) + +# Error flag +$hadErrors = $false + +function Get-DllBitness { + param([string]$Path) + try { + $fs = [System.IO.File]::Open($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read) + $br = New-Object System.IO.BinaryReader($fs) + $fs.Seek(0x3C, 'Begin') | Out-Null + $peOffset = $br.ReadInt32() + $fs.Seek($peOffset + 4, 'Begin') | Out-Null + $machine = $br.ReadUInt16() + $br.Close(); $fs.Close() + switch ($machine) { + 0x8664 { return 64 } # AMD64 + 0x014C { return 32 } # I386 + default { return $null } + } + } catch { return $null } +} + +function Safe-RemoveItemProperty { + param($Path,$Name) + try { + Remove-ItemProperty -Path $Path -Name $Name -Force + } catch { + Write-Host "Warning: failed to remove $Name" -ForegroundColor Yellow + $global:hadErrors = $true + } +} + +function Safe-NewItemProperty { + param($Path,$Name,$Value) + try { + New-ItemProperty -Path $Path -Name $Name -Value $Value -PropertyType DWord -Force | Out-Null + } catch { + Write-Host "Warning: failed to register $Name" -ForegroundColor Yellow + $global:hadErrors = $true + } +} + +function Register-OpenCLDLL { + param ( + [string]$dllPath + ) + if (-not (Test-Path $dllPath)) { return } + + $sig = Get-AuthenticodeSignature $dllPath + if ($sig.Status -ne 'Valid') { return } + + $bit = Get-DllBitness -Path $dllPath + if ($bit -eq 64) { + $rootKey = $roots[0] + } elseif ($bit -eq 32) { + $rootKey = $roots[1] + } else { + return + } + + $exists = (Get-ItemProperty -Path $rootKey -ErrorAction SilentlyContinue).PSObject.Properties.Name -contains $dllPath + if (-not $exists) { + Safe-NewItemProperty $rootKey $dllPath 0 + Write-Host "Added ($bit-bit): $dllPath" -ForegroundColor Cyan + } +} + +# 1) Cleanup +foreach ($root in $roots) { + Write-Host "`nAnalyzing: $root" -ForegroundColor Cyan + $entries = Get-ItemProperty -Path $root -ErrorAction SilentlyContinue + if ($entries) { + foreach ($property in $entries.PSObject.Properties) { + $dllPath = $property.Name + if ($dllPath -notlike "*amdocl*.dll") { continue } + + if (-not (Test-Path $dllPath)) { + Write-Host "Removed: $dllPath (missing file)" -ForegroundColor Red + Safe-RemoveItemProperty $root $dllPath + continue + } + + $sig = Get-AuthenticodeSignature $dllPath + if ($sig.Status -ne 'Valid') { + Write-Host "Removed: $dllPath (invalid signature)" -ForegroundColor Red + Safe-RemoveItemProperty $root $dllPath + continue + } + + # Move if registered under the wrong hive + $bit = Get-DllBitness -Path $dllPath + $shouldRoot = if ($bit -eq 64) { $roots[0] } elseif ($bit -eq 32) { $roots[1] } else { $null } + if ($shouldRoot -and ($root -ne $shouldRoot)) { + if (-not (Test-Path $shouldRoot)) { + Write-Host "Warning: destination hive not found, skipping $dllPath" -ForegroundColor Yellow + continue + } + Write-Host "Moving ($bit-bit) from wrong hive: $dllPath" -ForegroundColor Yellow + Safe-RemoveItemProperty $root $dllPath + $existsDest = (Get-ItemProperty -Path $shouldRoot -ErrorAction SilentlyContinue).PSObject.Properties.Name -contains $dllPath + if (-not $existsDest) { + Safe-NewItemProperty $shouldRoot $dllPath 0 + } + } else { + Write-Host "OK: $dllPath" -ForegroundColor Green + } + } + } else { + Write-Host "Key not found or empty." -ForegroundColor Yellow + } +} + +# 2) Rebuild from common locations (avoids duplicates, respects bitness) +Write-Host "`nRebuilding missing entries..." -ForegroundColor Cyan +foreach ($dir in $scanDirs) { + if (-not (Test-Path $dir)) { continue } + Get-ChildItem -Path $dir -Filter "amdocl*.dll" -Recurse -ErrorAction SilentlyContinue | + Sort-Object { $_.VersionInfo.FileVersionRaw } -Descending -ErrorAction SilentlyContinue | + ForEach-Object { + Register-OpenCLDLL -dllPath $_.FullName + } +} + +# Final message +if ($hadErrors) { + Write-Host "`nScript finished with warnings or errors." -ForegroundColor Yellow +} else { + Write-Host "`nScript finished successfully." -ForegroundColor Green +} From 6bb266d7c89904beac13ad4b27e0978c3a0cb537 Mon Sep 17 00:00:00 2001 From: TantalusDrive <236701476+TantalusDrive@users.noreply.github.com> Date: Thu, 20 Nov 2025 21:12:47 +0100 Subject: [PATCH 02/10] Add header to amdocl-fix.ps1 with credits, license, and feature overview --- amdocl-fix.ps1 | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/amdocl-fix.ps1 b/amdocl-fix.ps1 index 4998334..c44f7c9 100644 --- a/amdocl-fix.ps1 +++ b/amdocl-fix.ps1 @@ -1,3 +1,28 @@ +# PowerShell script to detect and register AMD OpenCL ICDs +# +# Original batch concept: Patrick Trumpis (https://github.com/ptrumpis/OpenCL-AMD-GPU) +# PowerShell implementation and extensions: TantalusDrive (https://github.com/TantalusDrive) +# +# Licensed under the MIT License. +# See LICENSE file in the repository root for full terms. +# +# This script builds upon the original batch solution by providing +# a more flexible and robust implementation in PowerShell. It is +# designed to improve detection and registration of AMD OpenCL ICDs +# across different environments, while keeping the process transparent +# and maintainable. +# +# Features: +# - Support for versioned DLLs (e.g. amdocl64_*.dll) +# - SysWOW64 registry handling for 32/64-bit consistency +# - PATH scan to locate hidden or unregistered drivers +# - Prevention of duplicate registry entries +# - Cleaner output and improved error handling +# +# Tested on a couple of dated AMD GPUs (R5 M330, R5 M430), feedback and contributions are welcome. + + + # Run as Administrator $roots = @( "HKLM:\SOFTWARE\Khronos\OpenCL\Vendors", # 64-bit From bca46ff1155b40a4e163462c128976d8ff6bb4f0 Mon Sep 17 00:00:00 2001 From: TantalusDrive <236701476+TantalusDrive@users.noreply.github.com> Date: Thu, 20 Nov 2025 21:26:23 +0100 Subject: [PATCH 03/10] Update README.md - Added section describing the new PowerShell script (amdocl-fix.ps1) and its extended features - Included instructions for running the script (right-click method and command line) --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index a5c69bc..0c52eab 100644 --- a/README.md +++ b/README.md @@ -9,15 +9,35 @@ It will scan your system for *OpenCL Installable Client Driver (ICD)* files by A - amdocl12cl64.dll - amdocl32.dll - amdocl64.dll +- versioned variants (e.g. amdocl_*.dll, amdocl64_*.dll) ## Usage 1. Make sure to have the latest [AMD drivers](https://www.amd.com/en/support) installed 2. Download and execute `amdocl.bat` 3. Run the file as **Administrator** (Right click file and select `Run as Administrator`) +## PowerShell version +A new PowerShell script (`amdocl-fix.ps1`) extends the batch version with additional features. + +### How to run +1. Download `amdocl-fix.ps1` and place it in a folder of your choice. +2. Make sure to run it as **Administrator**: + - Right‑click the file → **Run with PowerShell** → confirm the UAC prompt. + - Alternatively, open PowerShell as Administrator and run: + ```powershell + cd "C:\path\to\folder" + .\amdocl-fix.ps1 + ``` + +## Compatibility +- Windows 7, 8, 8.1, 10, 11: fully supported +- Windows XP / Vista: script runs safely, but OpenCL drivers may not be present +The script also includes improvements such as handling SysWOW64, safer PATH scanning, clean output when registry keys are missing, correct handling of versioned DLLs, and avoiding duplicate entries + ## Notes Inspired by StackOverflow https://stackoverflow.com/a/28407851 --- © 2023 [Patrick Trumpis](https://github.com/ptrumpis) +© 2025 [TantalusDrive](https://github.com/TantalusDrive) (Additional improvements and PowerShell version) From 5bba4a83df0510012d2d9aecf5e4fb0260941332 Mon Sep 17 00:00:00 2001 From: TantalusDrive <236701476+TantalusDrive@users.noreply.github.com> Date: Thu, 20 Nov 2025 22:51:12 +0100 Subject: [PATCH 04/10] Add optional unsigned DLL support and update header - Introduced AllowUnsigned parameter (default true) to optionally allow AMD OpenCL DLLs without valid signatures during cleanup and registration, preventing accidental removal of valid unsigned ICDs. - Added Is-SignatureAcceptable function to centralize signature validation logic with AllowUnsigned support. - Updated script header and description to accurately reflect full functionality. --- amdocl-fix.ps1 | 195 +++++++++++++++++++++++++++---------------------- 1 file changed, 106 insertions(+), 89 deletions(-) diff --git a/amdocl-fix.ps1 b/amdocl-fix.ps1 index c44f7c9..515defa 100644 --- a/amdocl-fix.ps1 +++ b/amdocl-fix.ps1 @@ -1,4 +1,4 @@ -# PowerShell script to detect and register AMD OpenCL ICDs +# PowerShell script to manage and fix AMD OpenCL ICDs # # Original batch concept: Patrick Trumpis (https://github.com/ptrumpis/OpenCL-AMD-GPU) # PowerShell implementation and extensions: TantalusDrive (https://github.com/TantalusDrive) @@ -6,49 +6,48 @@ # Licensed under the MIT License. # See LICENSE file in the repository root for full terms. # -# This script builds upon the original batch solution by providing -# a more flexible and robust implementation in PowerShell. It is -# designed to improve detection and registration of AMD OpenCL ICDs -# across different environments, while keeping the process transparent -# and maintainable. -# -# Features: -# - Support for versioned DLLs (e.g. amdocl64_*.dll) -# - SysWOW64 registry handling for 32/64-bit consistency -# - PATH scan to locate hidden or unregistered drivers -# - Prevention of duplicate registry entries -# - Cleaner output and improved error handling +# This PowerShell script extends the original batch by safely cleaning up +# invalid or misplaced registry entries and coherently registering AMD +# OpenCL DLLs in the correct 32-bit or 64-bit hive, and providing detailed status output. +# By default, unsigned DLLs are allowed to prevent accidental removal. # # Tested on a couple of dated AMD GPUs (R5 M330, R5 M430), feedback and contributions are welcome. +param( + [switch]$AllowUnsigned = $true +) - -# Run as Administrator +# AMD OpenCL registry hives $roots = @( - "HKLM:\SOFTWARE\Khronos\OpenCL\Vendors", # 64-bit - "HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors" # 32-bit + "HKLM:\SOFTWARE\Khronos\OpenCL\Vendors", # 64-bit + "HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors" # 32-bit ) -# Directories to scan (more complete than just System32) +# Standard AMD directories scanned for OpenCL ICDs $scanDirs = @( "$env:WINDIR\System32", "$env:WINDIR\SysWOW64", "$env:WINDIR\System32\DriverStore\FileRepository" ) -# Error flag $hadErrors = $false function Get-DllBitness { param([string]$Path) try { - $fs = [System.IO.File]::Open($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read) + $fs = [System.IO.File]::Open($Path, 'Open', 'Read', 'Read') $br = New-Object System.IO.BinaryReader($fs) + + # Read PE header offset $fs.Seek(0x3C, 'Begin') | Out-Null $peOffset = $br.ReadInt32() + + # Read machine field $fs.Seek($peOffset + 4, 'Begin') | Out-Null $machine = $br.ReadUInt16() + $br.Close(); $fs.Close() + switch ($machine) { 0x8664 { return 64 } # AMD64 0x014C { return 32 } # I386 @@ -57,110 +56,128 @@ function Get-DllBitness { } catch { return $null } } -function Safe-RemoveItemProperty { - param($Path,$Name) +function Safe-Remove { + param($root,$name) try { - Remove-ItemProperty -Path $Path -Name $Name -Force - } catch { - Write-Host "Warning: failed to remove $Name" -ForegroundColor Yellow - $global:hadErrors = $true - } + Remove-ItemProperty -Path $root -Name $name -Force + } catch { $global:hadErrors = $true } } -function Safe-NewItemProperty { - param($Path,$Name,$Value) +function Safe-Add { + param($root,$name) try { - New-ItemProperty -Path $Path -Name $Name -Value $Value -PropertyType DWord -Force | Out-Null - } catch { - Write-Host "Warning: failed to register $Name" -ForegroundColor Yellow - $global:hadErrors = $true + New-ItemProperty -Path $root -Name $name -Value 0 -PropertyType DWord -Force | Out-Null + } catch { $global:hadErrors = $true } +} + +function Is-SignatureAcceptable { + param($sig, $AllowUnsigned) + + if ($sig.Status -eq 'Valid') { return $true } + if ($AllowUnsigned -and ($sig.Status -eq 'NotSigned' -or $sig.Status -eq 'Unknown')) { + return $true } + return $false } function Register-OpenCLDLL { - param ( - [string]$dllPath - ) + param([string]$dllPath, [switch]$AllowUnsigned) + if (-not (Test-Path $dllPath)) { return } - $sig = Get-AuthenticodeSignature $dllPath - if ($sig.Status -ne 'Valid') { return } + $sig = Get-AuthenticodeSignature -FilePath $dllPath + if (-not (Is-SignatureAcceptable $sig $AllowUnsigned)) { return } - $bit = Get-DllBitness -Path $dllPath - if ($bit -eq 64) { - $rootKey = $roots[0] - } elseif ($bit -eq 32) { - $rootKey = $roots[1] - } else { - return - } + $bit = Get-DllBitness $dllPath + if ($bit -eq 64) { $root = $roots[0] } + elseif ($bit -eq 32) { $root = $roots[1] } + else { return } + + $exists = (Get-ItemProperty -Path $root -ErrorAction SilentlyContinue).PSObject.Properties | + Where-Object { $_.Name -eq $dllPath } - $exists = (Get-ItemProperty -Path $rootKey -ErrorAction SilentlyContinue).PSObject.Properties.Name -contains $dllPath if (-not $exists) { - Safe-NewItemProperty $rootKey $dllPath 0 + Safe-Add $root $dllPath Write-Host "Added ($bit-bit): $dllPath" -ForegroundColor Cyan } } -# 1) Cleanup +# ---------------------------------------------------------- +# 1) SAFE CLEANUP +# ---------------------------------------------------------- + foreach ($root in $roots) { + Write-Host "`nAnalyzing: $root" -ForegroundColor Cyan + $entries = Get-ItemProperty -Path $root -ErrorAction SilentlyContinue - if ($entries) { - foreach ($property in $entries.PSObject.Properties) { - $dllPath = $property.Name - if ($dllPath -notlike "*amdocl*.dll") { continue } - - if (-not (Test-Path $dllPath)) { - Write-Host "Removed: $dllPath (missing file)" -ForegroundColor Red - Safe-RemoveItemProperty $root $dllPath - continue - } + if (-not $entries) { + Write-Host "No entries found or key missing." + continue + } - $sig = Get-AuthenticodeSignature $dllPath - if ($sig.Status -ne 'Valid') { - Write-Host "Removed: $dllPath (invalid signature)" -ForegroundColor Red - Safe-RemoveItemProperty $root $dllPath - continue - } + foreach ($prop in $entries.PSObject.Properties) { - # Move if registered under the wrong hive - $bit = Get-DllBitness -Path $dllPath - $shouldRoot = if ($bit -eq 64) { $roots[0] } elseif ($bit -eq 32) { $roots[1] } else { $null } - if ($shouldRoot -and ($root -ne $shouldRoot)) { - if (-not (Test-Path $shouldRoot)) { - Write-Host "Warning: destination hive not found, skipping $dllPath" -ForegroundColor Yellow - continue - } - Write-Host "Moving ($bit-bit) from wrong hive: $dllPath" -ForegroundColor Yellow - Safe-RemoveItemProperty $root $dllPath - $existsDest = (Get-ItemProperty -Path $shouldRoot -ErrorAction SilentlyContinue).PSObject.Properties.Name -contains $dllPath - if (-not $existsDest) { - Safe-NewItemProperty $shouldRoot $dllPath 0 - } - } else { - Write-Host "OK: $dllPath" -ForegroundColor Green + $dll = $prop.Name + if ($dll -notlike "*amdocl*.dll") { continue } + + if (-not (Test-Path $dll)) { + Write-Host "Removed: $dll (file missing)" -ForegroundColor Yellow + Safe-Remove $root $dll + continue + } + + $sig = Get-AuthenticodeSignature -FilePath $dll + if (-not (Is-SignatureAcceptable $sig $AllowUnsigned)) { + Write-Host "Removed: $dll (invalid signature)" -ForegroundColor Yellow + Safe-Remove $root $dll + continue + } + + $bit = Get-DllBitness $dll + if ($bit -eq $null) { + Write-Host "Removed: $dll (bitness not detectable)" -ForegroundColor Yellow + Safe-Remove $root $dll + continue + } + + $correctRoot = if ($bit -eq 64) { $roots[0] } else { $roots[1] } + + if ($correctRoot -ne $root) { + Write-Host "Fixed hive mismatch ($bit-bit): $dll" -ForegroundColor Yellow + Safe-Remove $root $dll + + $existsDest = (Get-ItemProperty -Path $correctRoot -ErrorAction SilentlyContinue).PSObject.Properties | + Where-Object { $_.Name -eq $dll } + + if (-not $existsDest) { + Safe-Add $correctRoot $dll } + continue } - } else { - Write-Host "Key not found or empty." -ForegroundColor Yellow + + Write-Host "OK: $dll" -ForegroundColor Green } } -# 2) Rebuild from common locations (avoids duplicates, respects bitness) -Write-Host "`nRebuilding missing entries..." -ForegroundColor Cyan +# ---------------------------------------------------------- +# 2) COHERENT REBUILD (improved) +# ---------------------------------------------------------- + +Write-Host "`nRebuilding..." -ForegroundColor Cyan + foreach ($dir in $scanDirs) { if (-not (Test-Path $dir)) { continue } + Get-ChildItem -Path $dir -Filter "amdocl*.dll" -Recurse -ErrorAction SilentlyContinue | Sort-Object { $_.VersionInfo.FileVersionRaw } -Descending -ErrorAction SilentlyContinue | ForEach-Object { - Register-OpenCLDLL -dllPath $_.FullName + Register-OpenCLDLL -dllPath $_.FullName -AllowUnsigned:$AllowUnsigned } } -# Final message if ($hadErrors) { - Write-Host "`nScript finished with warnings or errors." -ForegroundColor Yellow + Write-Host "`nCompleted with warnings." -ForegroundColor Yellow } else { - Write-Host "`nScript finished successfully." -ForegroundColor Green + Write-Host "`nCompleted successfully." -ForegroundColor Green } From 8265ffb6895b0eeb1fa30ce9f0f5c86bbe0c023f Mon Sep 17 00:00:00 2001 From: TantalusDrive <236701476+TantalusDrive@users.noreply.github.com> Date: Thu, 20 Nov 2025 23:13:02 +0100 Subject: [PATCH 05/10] Wait for user input after script completion --- amdocl-fix.ps1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/amdocl-fix.ps1 b/amdocl-fix.ps1 index 515defa..64625d2 100644 --- a/amdocl-fix.ps1 +++ b/amdocl-fix.ps1 @@ -181,3 +181,5 @@ if ($hadErrors) { } else { Write-Host "`nCompleted successfully." -ForegroundColor Green } + +Read-Host "Press Enter to exit" From 4b166f422cd2a1c77680aa0efe8d83ae5247e7be Mon Sep 17 00:00:00 2001 From: TantalusDrive <236701476+TantalusDrive@users.noreply.github.com> Date: Thu, 20 Nov 2025 23:33:40 +0100 Subject: [PATCH 06/10] Improve batch script: SysWOW64 scan, PATH scan, versioned DLLs, error handling - Added SysWOW64 scan in Fast Scan phase for complete 32-bit driver detection. - Improved Full Scan to iterate PATH directories safely using pushd/popd. - Extended DLL validation to handle versioned AMD OpenCL DLLs (e.g., amdocl64_*, amdocl_*). - Enhanced bitness detection and root key assignment (prefer explicit 64-bit, fallback to 32-bit). - Added informative messages for missing keys, already registered DLLs, and errors during registry updates. - Updated privilege check to use 'net session' for reliability. - Improved script header and inline comments for clarity and maintainability. --- amdocl.bat | 158 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 92 insertions(+), 66 deletions(-) diff --git a/amdocl.bat b/amdocl.bat index 3849f61..749c183 100644 --- a/amdocl.bat +++ b/amdocl.bat @@ -1,59 +1,55 @@ @echo off cls -echo OpenCL Driver (ICD) Fix for AMD GPU's -echo By Patrick Trumpis (https://github.com/ptrumpis/OpenCL-AMD-GPU) +echo OpenCL Driver (ICD) Fix for AMD GPUs +echo Original work by Patrick Trumpis (https://github.com/ptrumpis/OpenCL-AMD-GPU) +echo Improvements by TantalusDrive (https://github.com/TantalusDrive) +REM SysWOW64 handling, PATH scan, versioned DLLs, duplicate prevention echo Inspired by https://stackoverflow.com/a/28407851 echo: echo: ->nul 2>&1 "%SYSTEMROOT%\System32\cacls.exe" "%SYSTEMROOT%\System32\config\system" && ( - goto :run -) || ( +REM ============================================================ +REM Privilege check +REM ============================================================ +net session >nul 2>&1 +if %errorlevel% neq 0 ( echo Execution stopped echo ================= echo This script requires administrator rights. echo Please run it again as administrator. echo You can right click the file and select 'Run as administrator' - echo: pause exit /b 1 ) -:run SETLOCAL EnableDelayedExpansion SET ROOTKEY64=HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenCL\Vendors SET ROOTKEY32=HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors -echo Currently installed OpenCL Client Driver's - 64bit +echo Currently installed OpenCL Client Drivers - 64bit echo ================================================== -for /f "tokens=1,*" %%A in ('reg query %ROOTKEY64%') do ( - echo %%A - %%B -) +reg query %ROOTKEY64% >nul 2>&1 && ( + for /f "tokens=1,*" %%A in ('reg query %ROOTKEY64%') do echo %%A - %%B +) || echo (none) echo: -echo Currently installed OpenCL Client Driver's - 32bit +echo Currently installed OpenCL Client Drivers - 32bit echo ================================================== -for /f "tokens=1,*" %%A in ('reg query %ROOTKEY32%') do ( - echo %%A - %%B -) -echo: - +reg query %ROOTKEY32% >nul 2>&1 && ( + for /f "tokens=1,*" %%A in ('reg query %ROOTKEY32%') do echo %%A - %%B +) || echo (none) echo: -echo This script will now attempt to find and install unregistered OpenCL AMD drivers from Windows (Fast Scan). -:askUserFastScan +echo This script will now attempt to find and install unregistered OpenCL AMD drivers (Fast Scan). set "INPUT=" set /P "INPUT=Do you want to continue? (Y/N): " -if /I "!INPUT!" == "Y" ( - echo: +if /I "!INPUT!"=="Y" ( echo: goto :scanFilesFast -) else if /I "!INPUT!" == "N" ( - goto :exit ) else ( - goto :askUserFastScan + goto :exit ) :scanFilesFast @@ -61,41 +57,41 @@ echo Running AMD OpenCL Driver Auto Detection echo ======================================== echo: -echo Scanning '%SYSTEMROOT%\system32' for 'amdocl*.dll' files, please wait... -echo: +echo Scanning '%SYSTEMROOT%\System32' for 'amdocl*.dll' files... +cd /d %SYSTEMROOT%\System32 +call :registerMissingClientDriver -cd /d %SYSTEMROOT%\system32 +echo: +echo Scanning '%SYSTEMROOT%\SysWOW64' for 'amdocl*.dll' files... +cd /d %SYSTEMROOT%\SysWOW64 call :registerMissingClientDriver echo: echo Fast Scan complete. echo: -echo: -echo This script will now attempt to find and install any unregistered OpenCL AMD drivers found on your computer (Full Scan). - -:askUserFullScan +echo This script will now attempt a Full Scan (PATH). set "INPUT=" set /P "INPUT=Do you want to continue? (Y/N): " -if /I "!INPUT!" == "Y" ( - echo: - echo: +if /I "!INPUT!"=="Y" ( goto :scanFilesFull -) else if /I "!INPUT!" == "N" ( - goto :complete ) else ( - goto :askUserFullScan + goto :complete ) - :scanFilesFull -echo Now scanning your PATH for 'amdocl*.dll' files, please wait... +echo Now scanning your PATH for 'amdocl*.dll' files... echo: for %%A in ("%path:;=";"%") do ( if "%%~A" neq "" ( - cd /d %%A - call :registerMissingClientDriver + if exist "%%~A\" ( + pushd "%%~A" >nul 2>&1 + if !ERRORLEVEL! == 0 ( + call :registerMissingClientDriver + popd + ) + ) ) ) @@ -104,50 +100,80 @@ echo Full Scan complete. echo: :complete -echo: echo Done. -echo: pause +goto :exit :exit exit /b 0 +REM ============================================================ +REM Register missing client drivers +REM ============================================================ :registerMissingClientDriver -for /r %%f in (amdocl*dll) do ( - set FILE="%%~dpnxf" +for /r %%f in (amdocl*.dll) do ( + set FILE=%%~dpnxf + set NAME=%%~nxf + + REM Accept fixed names and versioned variants (only real AMD files) + set "VALID=" + if /I "!NAME!"=="amdocl.dll" ( + set "VALID=1" + ) else if /I "!NAME!"=="amdocl64.dll" ( + set "VALID=1" + ) else if /I "!NAME!"=="amdocl12cl.dll" ( + set "VALID=1" + ) else if /I "!NAME!"=="amdocl12cl64.dll" ( + set "VALID=1" + ) else ( + REM Versioned variants used by AMD releases + echo !NAME! | findstr /C:"amdocl64_" >nul && set "VALID=1" + echo !NAME! | findstr /C:"amdocl_" >nul && set "VALID=1" + ) - for %%A in (amdocl.dll amdocl12cl.dll amdocl12cl64.dll amdocl32.dll amdocl64.dll) do ( - if "%%~nxf"=="%%A" ( - echo Found: !FILE! + if defined VALID ( + echo Found: !FILE! - echo !FILE! | findstr /C:"_amd64_" >nul + REM Bitness detection (prefer explicit 64, otherwise default to 32) + if /I "!NAME!"=="amdocl64.dll" ( + set "ROOTKEY=!ROOTKEY64!" + ) else if /I "!NAME!"=="amdocl12cl64.dll" ( + set "ROOTKEY=!ROOTKEY64!" + ) else ( + echo !NAME! | findstr /C:"amdocl64_" >nul if !ERRORLEVEL! == 0 ( set "ROOTKEY=!ROOTKEY64!" ) else ( - set FILE_BIT=!FILE:~-7,-5! - if !FILE_BIT! == 64 ( - set "ROOTKEY=!ROOTKEY64!" - ) else ( - set "ROOTKEY=!ROOTKEY32!" - ) + REM Default to 32-bit if not matched above + set "ROOTKEY=!ROOTKEY32!" ) + ) - reg query !ROOTKEY! >nul 2>&1 - if !ERRORLEVEL! neq 0 ( - reg add !ROOTKEY! /f + REM Ensure root key exists + reg query !ROOTKEY! >nul 2>&1 + if !ERRORLEVEL! neq 0 ( + reg add !ROOTKEY! /f >nul 2>&1 + if !ERRORLEVEL! == 0 ( echo Added Key: !ROOTKEY! + ) else ( + echo ERROR: Failed to add key !ROOTKEY! ) + ) - reg query !ROOTKEY! /v !FILE! >nul 2>&1 - - if !ERRORLEVEL! neq 0 ( - reg add !ROOTKEY! /v !FILE! /t REG_DWORD /d 0 /f >nul 2>&1 - - if !ERRORLEVEL! == 0 ( - echo Installed: !FILE! - ) + REM Register DLL if missing + reg query !ROOTKEY! /v "!FILE!" >nul 2>&1 + if !ERRORLEVEL! neq 0 ( + reg add !ROOTKEY! /v "!FILE!" /t REG_DWORD /d 0 /f >nul 2>&1 + if !ERRORLEVEL! == 0 ( + echo Registered: !FILE! + ) else ( + echo ERROR: Failed to register !FILE! ) + ) else ( + echo Already present: !FILE! ) ) + REM Reset VALID for next iteration + set "VALID=" ) goto :eof From 4eada8a7ae23920db4f0e5c28915247cf637f407 Mon Sep 17 00:00:00 2001 From: TantalusDrive <236701476+TantalusDrive@users.noreply.github.com> Date: Thu, 20 Nov 2025 23:45:01 +0100 Subject: [PATCH 07/10] Update README.md Layout adjustments and polished compatibility section --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0c52eab..7ed485c 100644 --- a/README.md +++ b/README.md @@ -12,14 +12,12 @@ It will scan your system for *OpenCL Installable Client Driver (ICD)* files by A - versioned variants (e.g. amdocl_*.dll, amdocl64_*.dll) ## Usage +## Batch script 1. Make sure to have the latest [AMD drivers](https://www.amd.com/en/support) installed 2. Download and execute `amdocl.bat` 3. Run the file as **Administrator** (Right click file and select `Run as Administrator`) -## PowerShell version -A new PowerShell script (`amdocl-fix.ps1`) extends the batch version with additional features. - -### How to run +## PowerShell script 1. Download `amdocl-fix.ps1` and place it in a folder of your choice. 2. Make sure to run it as **Administrator**: - Right‑click the file → **Run with PowerShell** → confirm the UAC prompt. @@ -32,12 +30,12 @@ A new PowerShell script (`amdocl-fix.ps1`) extends the batch version with additi ## Compatibility - Windows 7, 8, 8.1, 10, 11: fully supported - Windows XP / Vista: script runs safely, but OpenCL drivers may not be present -The script also includes improvements such as handling SysWOW64, safer PATH scanning, clean output when registry keys are missing, correct handling of versioned DLLs, and avoiding duplicate entries +The script ensures proper detection and registration of AMD OpenCL drivers on Windows, including handling SysWOW64, scanning the PATH safely, registering versioned DLLs, and avoiding duplicate entries. ## Notes Inspired by StackOverflow https://stackoverflow.com/a/28407851 --- -© 2023 [Patrick Trumpis](https://github.com/ptrumpis) +© 2023 [Patrick Trumpis](https://github.com/ptrumpis) © 2025 [TantalusDrive](https://github.com/TantalusDrive) (Additional improvements and PowerShell version) From a892340df941372dd3e92d60673b0ae172013045 Mon Sep 17 00:00:00 2001 From: TantalusDrive <236701476+TantalusDrive@users.noreply.github.com> Date: Thu, 20 Nov 2025 23:53:18 +0100 Subject: [PATCH 08/10] Add compatibility note about PowerShell requirements --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ed485c..b617b92 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,8 @@ It will scan your system for *OpenCL Installable Client Driver (ICD)* files by A ``` ## Compatibility -- Windows 7, 8, 8.1, 10, 11: fully supported +- Windows 10, 11: fully supported +- Windows 7, 8, 8.1: batch script fully supported; PowerShell script (`amdocl-fix.ps1`) requires PowerShell 5.1 or newer - Windows XP / Vista: script runs safely, but OpenCL drivers may not be present The script ensures proper detection and registration of AMD OpenCL drivers on Windows, including handling SysWOW64, scanning the PATH safely, registering versioned DLLs, and avoiding duplicate entries. From 0c330998ab0fa16831d0fbdf7a77abcf22fe3507 Mon Sep 17 00:00:00 2001 From: TantalusDrive <236701476+TantalusDrive@users.noreply.github.com> Date: Fri, 21 Nov 2025 00:34:40 +0100 Subject: [PATCH 09/10] Update README.md Fixed layout issues and moved detailed infos from compatiblity to a more proper section. --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b617b92..6ffdc70 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,10 @@ It will scan your system for *OpenCL Installable Client Driver (ICD)* files by A - amdocl12cl64.dll - amdocl32.dll - amdocl64.dll -- versioned variants (e.g. amdocl_*.dll, amdocl64_*.dll) +- versioned variants (e.g. amdocl_\*.dll, amdocl64_\*.dll) + +The scripts ensure proper detection and registration of the drivers, including handling SysWOW64, scanning the PATH safely, registering versioned DLLs and avoiding duplicate entries. +The PowerShell version additionally verifies DLL signatures, detects 32/64-bit bitness more reliably, safely cleans up or moves invalid entries, handles DriverStore and versioned DLLs intelligently and provides more detailed error reporting and status output. ## Usage ## Batch script @@ -31,7 +34,6 @@ It will scan your system for *OpenCL Installable Client Driver (ICD)* files by A - Windows 10, 11: fully supported - Windows 7, 8, 8.1: batch script fully supported; PowerShell script (`amdocl-fix.ps1`) requires PowerShell 5.1 or newer - Windows XP / Vista: script runs safely, but OpenCL drivers may not be present -The script ensures proper detection and registration of AMD OpenCL drivers on Windows, including handling SysWOW64, scanning the PATH safely, registering versioned DLLs, and avoiding duplicate entries. ## Notes Inspired by StackOverflow https://stackoverflow.com/a/28407851 From be1e0fe8fe48b6d10714bc6f16eda2098fe01f4e Mon Sep 17 00:00:00 2001 From: TantalusDrive <236701476+TantalusDrive@users.noreply.github.com> Date: Thu, 27 Nov 2025 04:05:17 +0100 Subject: [PATCH 10/10] Add VersionInfo filtering and PATH scan - Only DLLs with VersionInfo are now registered, improving safety (previously, all matching files were considered) - Added optional scan of directories in system PATH for extended support of custom/unofficial DLLs - Registry cleanup, bitness and signature checks, and duplicate prevention remain unchanged - Improved user messages and scan feedback --- amdocl-fix.ps1 | 87 ++++++++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 52 deletions(-) diff --git a/amdocl-fix.ps1 b/amdocl-fix.ps1 index 64625d2..3a7bb22 100644 --- a/amdocl-fix.ps1 +++ b/amdocl-fix.ps1 @@ -17,13 +17,11 @@ param( [switch]$AllowUnsigned = $true ) -# AMD OpenCL registry hives $roots = @( - "HKLM:\SOFTWARE\Khronos\OpenCL\Vendors", # 64-bit - "HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors" # 32-bit + "HKLM:\SOFTWARE\Khronos\OpenCL\Vendors", + "HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors" ) -# Standard AMD directories scanned for OpenCL ICDs $scanDirs = @( "$env:WINDIR\System32", "$env:WINDIR\SysWOW64", @@ -37,20 +35,14 @@ function Get-DllBitness { try { $fs = [System.IO.File]::Open($Path, 'Open', 'Read', 'Read') $br = New-Object System.IO.BinaryReader($fs) - - # Read PE header offset $fs.Seek(0x3C, 'Begin') | Out-Null $peOffset = $br.ReadInt32() - - # Read machine field $fs.Seek($peOffset + 4, 'Begin') | Out-Null $machine = $br.ReadUInt16() - $br.Close(); $fs.Close() - switch ($machine) { - 0x8664 { return 64 } # AMD64 - 0x014C { return 32 } # I386 + 0x8664 { return 64 } + 0x014C { return 32 } default { return $null } } } catch { return $null } @@ -58,21 +50,18 @@ function Get-DllBitness { function Safe-Remove { param($root,$name) - try { - Remove-ItemProperty -Path $root -Name $name -Force - } catch { $global:hadErrors = $true } + try { Remove-ItemProperty -Path $root -Name $name -Force } + catch { $global:hadErrors = $true } } function Safe-Add { param($root,$name) - try { - New-ItemProperty -Path $root -Name $name -Value 0 -PropertyType DWord -Force | Out-Null - } catch { $global:hadErrors = $true } + try { New-ItemProperty -Path $root -Name $name -Value 0 -PropertyType DWord -Force | Out-Null } + catch { $global:hadErrors = $true } } function Is-SignatureAcceptable { param($sig, $AllowUnsigned) - if ($sig.Status -eq 'Valid') { return $true } if ($AllowUnsigned -and ($sig.Status -eq 'NotSigned' -or $sig.Status -eq 'Unknown')) { return $true @@ -82,95 +71,71 @@ function Is-SignatureAcceptable { function Register-OpenCLDLL { param([string]$dllPath, [switch]$AllowUnsigned) - if (-not (Test-Path $dllPath)) { return } - $sig = Get-AuthenticodeSignature -FilePath $dllPath if (-not (Is-SignatureAcceptable $sig $AllowUnsigned)) { return } - $bit = Get-DllBitness $dllPath if ($bit -eq 64) { $root = $roots[0] } elseif ($bit -eq 32) { $root = $roots[1] } else { return } - $exists = (Get-ItemProperty -Path $root -ErrorAction SilentlyContinue).PSObject.Properties | Where-Object { $_.Name -eq $dllPath } - if (-not $exists) { Safe-Add $root $dllPath - Write-Host "Added ($bit-bit): $dllPath" -ForegroundColor Cyan + Write-Host "[+ $bit bit] Added: $dllPath" -ForegroundColor Cyan } } -# ---------------------------------------------------------- -# 1) SAFE CLEANUP -# ---------------------------------------------------------- - +# Registry cleanup: remove invalid, missing, or misplaced entries foreach ($root in $roots) { - Write-Host "`nAnalyzing: $root" -ForegroundColor Cyan - $entries = Get-ItemProperty -Path $root -ErrorAction SilentlyContinue if (-not $entries) { Write-Host "No entries found or key missing." continue } - foreach ($prop in $entries.PSObject.Properties) { - $dll = $prop.Name if ($dll -notlike "*amdocl*.dll") { continue } - if (-not (Test-Path $dll)) { - Write-Host "Removed: $dll (file missing)" -ForegroundColor Yellow + Write-Host "Removed: $dll (file not found)" -ForegroundColor Yellow Safe-Remove $root $dll continue } - $sig = Get-AuthenticodeSignature -FilePath $dll if (-not (Is-SignatureAcceptable $sig $AllowUnsigned)) { Write-Host "Removed: $dll (invalid signature)" -ForegroundColor Yellow Safe-Remove $root $dll continue } - $bit = Get-DllBitness $dll if ($bit -eq $null) { - Write-Host "Removed: $dll (bitness not detectable)" -ForegroundColor Yellow + Write-Host "Removed: $dll (architecture not detected)" -ForegroundColor Yellow Safe-Remove $root $dll continue } - $correctRoot = if ($bit -eq 64) { $roots[0] } else { $roots[1] } - if ($correctRoot -ne $root) { - Write-Host "Fixed hive mismatch ($bit-bit): $dll" -ForegroundColor Yellow + Write-Host "Moved ($bit bit): $dll" -ForegroundColor Yellow Safe-Remove $root $dll - $existsDest = (Get-ItemProperty -Path $correctRoot -ErrorAction SilentlyContinue).PSObject.Properties | Where-Object { $_.Name -eq $dll } - if (-not $existsDest) { Safe-Add $correctRoot $dll } continue } - Write-Host "OK: $dll" -ForegroundColor Green } } -# ---------------------------------------------------------- -# 2) COHERENT REBUILD (improved) -# ---------------------------------------------------------- - -Write-Host "`nRebuilding..." -ForegroundColor Cyan +# Register all valid DLLs found in each directory (no duplicates) +Write-Host "`nRegistering all valid AMD OpenCL DLLs from standard directories..." -ForegroundColor Cyan foreach ($dir in $scanDirs) { if (-not (Test-Path $dir)) { continue } - Get-ChildItem -Path $dir -Filter "amdocl*.dll" -Recurse -ErrorAction SilentlyContinue | - Sort-Object { $_.VersionInfo.FileVersionRaw } -Descending -ErrorAction SilentlyContinue | + Where-Object { $_.VersionInfo.FileVersionRaw } | ForEach-Object { Register-OpenCLDLL -dllPath $_.FullName -AllowUnsigned:$AllowUnsigned } @@ -179,7 +144,25 @@ foreach ($dir in $scanDirs) { if ($hadErrors) { Write-Host "`nCompleted with warnings." -ForegroundColor Yellow } else { - Write-Host "`nCompleted successfully." -ForegroundColor Green + Write-Host "`nCompleted." -ForegroundColor Green +} + +# Optional PATH scan +Write-Host "`nDo you want to include an extended scan of system PATH directories? (Recommended only for custom or unofficial DLLs)" -ForegroundColor Yellow +$input = Read-Host "Type Y to scan, anything else to skip" +if ($input -eq 'Y' -or $input -eq 'y') { + Write-Host "`nNote: DLLs found in PATH may be unofficial or obsolete." -ForegroundColor Magenta + $pathDirs = ($env:PATH -split ';' | Where-Object { Test-Path $_ }) + foreach ($dir in $pathDirs) { + Get-ChildItem -Path $dir -Filter "amdocl*.dll" -Recurse -ErrorAction SilentlyContinue | + Where-Object { $_.VersionInfo.FileVersionRaw } | + ForEach-Object { + Register-OpenCLDLL -dllPath $_.FullName -AllowUnsigned:$AllowUnsigned + } + } + Write-Host "`nPATH scan completed." -ForegroundColor Cyan +} else { + Write-Host "`nPATH scan skipped." } Read-Host "Press Enter to exit"