Skip to content

Instantly share code, notes, and snippets.

@Kaylebor
Created October 8, 2025 16:45
Show Gist options
  • Select an option

  • Save Kaylebor/ceed84a840d81cd98ad5ebecbe35733c to your computer and use it in GitHub Desktop.

Select an option

Save Kaylebor/ceed84a840d81cd98ad5ebecbe35733c to your computer and use it in GitHub Desktop.
Repairs Wine URL handlers to ensure that Windows programs use the system browser to open URLs
#!/usr/bin/env bash
set -Eeuo pipefail
usage() {
cat <<USAGE
Usage: $(basename "$0") [--force] [--schemes list] [--filetypes list]
Ensures selected Wine URL protocol and file associations use winebrowser.
Options:
--force Overwrite existing handlers even if they point elsewhere.
--schemes list Comma-separated URL schemes to repair (default: http,https,ftp,mailto).
--filetypes list Comma-separated file types to repair (default: htmlfile,pdffile,xmlfile).
-h, --help Show this help.
USAGE
}
force=false
schemes=(http https ftp mailto)
filetypes=(htmlfile pdffile xmlfile)
while [[ $# -gt 0 ]]; do
case "$1" in
--force)
force=true
;;
--schemes)
[[ $# -ge 2 ]] || { echo "Missing argument for --schemes" >&2; exit 1; }
IFS=',' read -ra schemes <<<"$2"
shift
;;
--filetypes)
[[ $# -ge 2 ]] || { echo "Missing argument for --filetypes" >&2; exit 1; }
IFS=',' read -ra filetypes <<<"$2"
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
usage >&2
exit 1
;;
esac
shift
done
WINEPREFIX="${WINEPREFIX:-$HOME/.wine}"
WINEBIN="${WINEBIN:-wine}"
expected='"C:\\windows\\system32\\winebrowser.exe" "%1"'
extract_value() {
local key=$1
"$WINEBIN" reg query "$key" /ve 2>/dev/null \
| tr -d '\r' \
| awk -F 'REG_SZ' 'NF > 1 { sub(/^ +/, "", $2); print $2 }'
}
update_value() {
local key=$1
"$WINEBIN" reg add "$key" /ve /t REG_SZ /d "$expected" /f >/dev/null
}
repair_handler() {
local label=$1
local key=$2
local current
current=$(extract_value "$key")
if [[ -z "$current" ]]; then
echo "Setting $label handler (was missing)"
update_value "$key"
return
fi
if [[ "$current" == "$expected" ]]; then
echo "Leaving $label handler (already correct)"
return
fi
if [[ "$current" == *winebrowser.exe* && "$current" == *"%1"* ]]; then
echo "Leaving $label handler (custom but still uses winebrowser): $current"
return
fi
if [[ "$force" == true ]]; then
echo "Overwriting $label handler: $current"
update_value "$key"
else
echo "Skipping $label handler (custom value, use --force to override): $current"
fi
}
for scheme in "${schemes[@]}"; do
[[ -n "$scheme" ]] || continue
repair_handler "URL scheme '$scheme'" "HKCU\\Software\\Classes\\$scheme\\shell\\open\\command"
done
for filetype in "${filetypes[@]}"; do
[[ -n "$filetype" ]] || continue
repair_handler "File type '$filetype'" "HKCU\\Software\\Classes\\$filetype\\shell\\open\\command"
done
echo "Done. Verify with:"
echo " $WINEBIN reg query 'HKCU\\\\Software\\\\Classes\\\\https\\\\shell\\\\open\\\\command'"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment