Skip to content

Instantly share code, notes, and snippets.

@pkcpkc
Created November 2, 2025 09:33
Show Gist options
  • Select an option

  • Save pkcpkc/5cbe2a622282bd10023e7a59879fa9bd to your computer and use it in GitHub Desktop.

Select an option

Save pkcpkc/5cbe2a622282bd10023e7a59879fa9bd to your computer and use it in GitHub Desktop.
Re-download and replace DLLs for CrossOver compatibility
#!/bin/bash
set -e
# === FUNCTIONS ===
select_bottle() {
local bottles_dir="$HOME/Library/Application Support/CrossOver/Bottles"
echo "Scanning for CrossOver bottles..."
if [[ ! -d "$bottles_dir" ]]; then
echo "❌ CrossOver bottles directory not found at:"
echo " $bottles_dir"
echo "Is CrossOver installed for this user?"
exit 1
fi
bottles=()
for b in "$bottles_dir"/*; do
[ -d "$b" ] || continue
bottles+=("$(basename "$b")")
done
if [[ ${#bottles[@]} -eq 0 ]]; then
echo "❌ No bottles found."
exit 1
fi
echo
echo "Available CrossOver bottles:"
i=1
for b in "${bottles[@]}"; do
echo " $i) $b"
i=$((i + 1))
done
echo
while true; do
read -rp "Select bottle number: " selection
if [[ "$selection" =~ ^[0-9]+$ ]] && ((selection >= 1 && selection <= ${#bottles[@]})); then
BOTTLE_NAME="${bottles[$((selection - 1))]}"
break
else
echo "Invalid choice. Please enter a number between 1 and ${#bottles[@]}."
fi
done
echo "✅ Selected bottle: ${BOTTLE_NAME}"
}
check_deps() {
command -v curl >/dev/null 2>&1 || {
echo "curl is required (preinstalled on macOS)"
exit 1
}
command -v cabextract >/dev/null 2>&1 || {
echo "cabextract is required. Install with: brew install cabextract"
exit 1
}
}
cleanup() {
local arch=$1
rm -f "vc_redist.${arch}.exe"
rm -rf 0 a{0..11} u{0..31}
}
backup() {
local timestamp
timestamp=$(date +%s)
for dll in ucrtbase concrt140 msvcp140 vcamp140 vccorlib140 vcomp140 vcruntime140; do
if [ -f "${dll}.dll" ]; then
mv "${dll}.dll" "${dll}.dll.bak-${timestamp}"
echo "Backed up ${dll}.dll → ${dll}.dll.bak-${timestamp}"
fi
done
}
restore_backups() {
local dir=$1
cd "${dir}" || { echo "Directory not found: ${dir}"; return; }
shopt -s nullglob
for bak in *.bak-*; do
orig="${bak%%.bak-*}"
mv "$bak" "${orig}.dll"
echo "Restored ${bak} → ${orig}.dll"
done
shopt -u nullglob
}
download_and_replace() {
local arch=$1
curl -LO "https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.${arch}.exe"
cabextract "vc_redist.${arch}.exe"
cabextract a10
}
replace_dlls() {
local dir=$1
local arch=$2
cd "${dir}" || { echo "Directory not found: ${dir}"; exit 1; }
backup
cleanup "$arch"
download_and_replace "$arch"
cleanup "$arch"
}
usage() {
echo "Usage:"
echo " $0 Replace DLLs (default mode)"
echo " $0 --revert Restore backed-up DLLs"
}
# === MAIN ===
check_deps
select_bottle
BOTTLE_PATH="$HOME/Library/Application Support/CrossOver/Bottles/${BOTTLE_NAME}"
SINS2_WIN_DIR="${BOTTLE_PATH}/drive_c/windows"
SINS2_WIN_SYS32_DIR="${SINS2_WIN_DIR}/system32"
SINS2_WIN_SYS64_DIR="${SINS2_WIN_DIR}/syswow64"
if [[ ! -d "${SINS2_WIN_DIR}" ]]; then
echo "❌ Invalid bottle or missing Windows directory: ${SINS2_WIN_DIR}"
exit 1
fi
if [[ "$1" == "--revert" ]]; then
echo "🔁 Reverting DLL changes in bottle: ${BOTTLE_NAME}"
restore_backups "${SINS2_WIN_SYS32_DIR}"
restore_backups "${SINS2_WIN_SYS64_DIR}"
echo "✅ Reversion complete."
exit 0
fi
echo "⚙️ Replacing DLLs in bottle: ${BOTTLE_NAME}"
replace_dlls "${SINS2_WIN_SYS32_DIR}" x64
replace_dlls "${SINS2_WIN_SYS64_DIR}" x86
echo "✅ Replacement complete."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment