Skip to content

Instantly share code, notes, and snippets.

@santaklouse
Last active June 1, 2025 23:11
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.'
@romthebom7
Copy link

If anyone needs it, I'll drop the Python script I made in like 5 minutes that I've been using for little over a month. All this does is set the FirstRunDate to the current time. This doesn't fix effected bottles.

import plistlib
import os
from datetime import datetime

# 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.utcnow()

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

Where exactly would I use this code? I’m kinda dumb around software stuff

@DakshG07
Copy link

DakshG07 commented Jun 1, 2025

Here's a Python script that should completely reset the trial (I basically just put together what everyone has already sent before):

#!/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.utcnow()

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

print("Resetting Crossover bottles...")
while True:
    # Get bottle name
    bottle_name = input("Enter the bottle name: ")

    # Define paths
    regfile = os.path.expanduser(f"~/Library/Application Support/CrossOver/Bottles/{bottle_name}/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.")

    # Ask if we should continue
    resp = input("Do you want to reset another bottle? (y/n): ").strip().lower()
    if resp != 'y':
        print("CrossOver trial reset.")
        break

This will reset the Crossover trial and all the bottles. You should know the names of your bottles. To run it, save it as reset_crossover.py in a folder, and then open a terminal there and run python3 reset_crossover.py (the script should walk you through the rest).

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