Skip to content

Instantly share code, notes, and snippets.

@santaklouse
Last active July 21, 2025 14:22
Show Gist options
  • Save santaklouse/a137ee51692b74d4cf2cc1bb68ed64ef to your computer and use it in GitHub Desktop.
Save santaklouse/a137ee51692b74d4cf2cc1bb68ed64ef to your computer and use it in GitHub Desktop.
unlimited CrossOver trial (MacOS)

Run it in console for permanent install :

bash -c "$(curl -fsSL https://gist.github.com/santaklouse/a137ee51692b74d4cf2cc1bb68ed64ef/raw/install.sh?token=$(date +%s))"

After install script will fix crossover as well as expired bottles (Thanks to @djsmax).

#!/usr/bin/env bash
# checck if pidof exists
PIDOF="$(which pidof)"
# and if not - install it
(test "${PIDOF}" && test -f "${PIDOF}") || brew install pidof
# find app in default paths
CO_PWD=~/Applications/CrossOver.app/Contents/MacOS
test -d "${CO_PWD}" || CO_PWD=/Applications/CrossOver.app/Contents/MacOS
test -d "${CO_PWD}" || (echo 'unable to detect app path. exiting...' && exit)
PWD="${CO_PWD}"
cd "${PWD}"
PROC_NAME='CrossOver'
# get all pids of CrossOver
pids=(`pgrep "${PROC_NAME}"`, `pidof "${PROC_NAME}"`, `ps -Ac | grep -m1 "${PROC_NAME}" | awk '{print $1}'`)
pids=`echo ${pids[*]}|tr ',' ' '`
# kills CrossOver process if it is running
[ "${pids}" ] && kill -9 `echo "${pids}"` > /dev/null 2>&1
# wait until app finish
sleep 3
# make the current date RFC3339-encoded string representation in UTC time zone
DATETIME=`date -u -v -3H '+%Y-%m-%dT%TZ'`
# modify time in order to reset trial
plutil -replace FirstRunDate -date "${DATETIME}" ~/Library/Preferences/com.codeweavers.CrossOver.plist
plutil -replace SULastCheckTime -date "${DATETIME}" ~/Library/Preferences/com.codeweavers.CrossOver.plist
# show tooltip notification
/usr/bin/osascript -e "display notification \"trial fixed: date changed to ${DATETIME}\""
# reset all bottles
for file in ~/Library/Application\ Support/CrossOver/Bottles/*/.{eval,update-timestamp}; do rm -rf "${file}";done
# and after this execute original crossover
echo "${PWD}" > /tmp/co_log.log
"$($PWD/CrossOver.origin)" >> /tmp/co_log.log
#!/usr/bin/env bash
# find app in default paths
CO_PWD=~/Applications/CrossOver.app/Contents/MacOS
test -d "${CO_PWD}" || CO_PWD=/Applications/CrossOver.app/Contents/MacOS
test -d "${CO_PWD}" || (echo 'unable to detect app path. exiting...' && exit)
PWD="${CO_PWD}"
cd "${PWD}"
PROC_NAME='CrossOver'
# get all pids of CrossOver
pids=(`pgrep "${PROC_NAME}"`, `pidof "${PROC_NAME}"`, `ps -Ac | grep -m1 "${PROC_NAME}" | awk '{print $1}'`)
pids=`echo ${pids[*]}|tr ',' ' '`
# kills CrossOver process if it is running
[ "${pids}" ] && kill -9 `echo "${pids}"` > /dev/null 2>&1
TIMESTAMP=$(date +%s)
FIX_FILE_LINK="https://gist.github.com/santaklouse/a137ee51692b74d4cf2cc1bb68ed64ef/raw/CrossOver.sh?token=${TIMESTAMP}"
if [ -f CrossOver.origin ]; then
echo 'already installed. update and exit.'
echo "$(curl -fsSL ${FIX_FILE_LINK})" > CrossOver
exit
fi;
test -f CrossOver.origin || mv CrossOver CrossOver.origin
echo "$(curl -fsSL ${FIX_FILE_LINK})" > CrossOver
chmod +x CrossOver
echo 'Done. Please open CrossOver '
#!/usr/bin/env bash
# find app in default paths
CO_PWD=~/Applications/CrossOver.app/Contents/MacOS
test -d "${CO_PWD}" || CO_PWD=/Applications/CrossOver.app/Contents/MacOS
test -d "${CO_PWD}" || (echo 'unable to detect app path. exiting...' && exit)
PWD="${CO_PWD}"
cd "${PWD}"
PROC_NAME='CrossOver'
# get all pids of CrossOver
pids=(`pgrep "${PROC_NAME}"`, `pidof "${PROC_NAME}"`, `ps -Ac | grep -m1 "${PROC_NAME}" | awk '{print $1}'`)
pids=`echo ${pids[*]}|tr ',' ' '`
# kills CrossOver process if it is running
[ "${pids}" ] && kill -9 `echo "${pids}"` > /dev/null 2>&1
if [ -f CrossOver.origin ]; then
echo 'original file found. Roll it back and exit.'
mv CrossOver.origin CrossOver
exit
fi;
echo 'original file not found.'
@fleetimee
Copy link

I improved the python script by DakshG07 to automatically detect all bottles, but it will still ask for confirmation before it deletes any files

#!/usr/bin/env python3
import os
import shutil
import re
import plistlib
from datetime import datetime

print("Resetting Crossover FirstRunDate...")
# Set os path
userPath = os.path.expanduser('~')

# Open plist
with open(f'{userPath}/Library/Preferences/com.codeweavers.CrossOver.plist', 'rb') as f:
    pl = plistlib.load(f)


# Set first run date to correct time
pl['FirstRunDate'] = datetime.now()

# Save plist
with open(f'{userPath}/Library/Preferences/com.codeweavers.CrossOver.plist', 'wb') as f:
    plistlib.dump(pl, f)

print("Resetting Crossover bottles...")
# Get all of the bottles in the bottles directory
path = os.path.expanduser("~/Library/Application Support/CrossOver/Bottles/")
bottles = [ f.name for f in os.scandir(path) if f.is_dir() ]
for bottle in bottles:
    # Define paths
    regfile = os.path.expanduser(f"~/Library/Application Support/CrossOver/Bottles/{bottle}/system.reg")
    bakfile = regfile + ".bak"

    # Create backup
    shutil.copy2(regfile, bakfile)
    print(f"Backup created: {bakfile}")

    # Compile the regex pattern
    pattern = re.compile(r"\[Software\\\\CodeWeavers\\\\CrossOver\\\\cxoffice\] [0-9]*")

    # Read the file and search for match line
    with open(regfile, 'r') as f:
        lines = f.readlines()

    match_line_num = None
    for i, line in enumerate(lines):
        if pattern.search(line):
            match_line_num = i
            break

    # If match is found
    if match_line_num is not None:
        print(f"Match found at line {match_line_num + 1}.")
        for line in lines[match_line_num:match_line_num + 5]:
            print(line, end='')

        resp = input("Do you want to delete these lines (delete to reset bottle)? (y/n): ").strip().lower()
        if resp == 'y':
            new_lines = lines[:match_line_num] + lines[match_line_num + 5:]
            with open(regfile, 'w') as f:
                f.writelines(new_lines)
            print("Lines deleted.")
        else:
            print("Deletion canceled.")
    else:
        print("No match found.")

    print("CrossOver trial reset.")

thank you

@grrrrrrrrlklklklklk
Copy link

Alternatively if you dont want to use scripts, you can just download "prefs editor", open it, search for crossover, click on it, and change "first run date" to whenever you want it to and the trial will start on that day.

Beware that your bottles will have to be redownloaded, at least from my very basic knowledge

@DevanshIcarus
Copy link

Beware that your bottles will have to be redownloaded, at least from my very basic knowledge
Well then how to save bottles then πŸ˜„

@xVc323
Copy link

xVc323 commented Jul 15, 2025

Script here β€” resets trial, bottle reset included (experimental).

Still works πŸ‘€
Resets bottles and everything.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment