Skip to content

Commit

Permalink
Merge branch 'develop' into bugfix/170-handle-webaction-event-status
Browse files Browse the repository at this point in the history
  • Loading branch information
iLLiCiTiT committed Oct 11, 2024
2 parents dde6d4a + 0e6b7f1 commit 60769ad
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 121 deletions.
35 changes: 0 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,41 +26,6 @@ Usage of shim:

Shim is installed with AYON launcher, or on first run of AYON launcher. It is installed to app data which is based on OS, or to `{AYON_LAUNCHER_LOCAL_DIR}/shim/` directory if `AYON_LAUNCHER_LOCAL_DIR` environment variable is set.

Windows installation requires admin privileges, you'll be prompted for them on installation of AYON launcher.

<details>

<summary>Windows registry</summary>

You can register custom uri protocol scheme `ayon-launcher://` by adding following registry keys:
It uses default shim executable path `%LOCALAPPDATA%\Ynput\AYON\shim\ayon.exe`.

```
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\ayon-launcher]
"URL Protocol"=""
[HKEY_CLASSES_ROOT\ayon-launcher\DefaultIcon]
@=hex(2):25,00,4c,00,4f,00,43,00,41,00,4c,00,41,00,50,00,50,00,44,00,41,00,54,\
00,41,00,25,00,5c,00,59,00,6e,00,70,00,75,00,74,00,5c,00,41,00,59,00,4f,00,\
4e,00,5c,00,73,00,68,00,69,00,6d,00,5c,00,61,00,79,00,6f,00,6e,00,2e,00,65,\
00,78,00,65,00,00,00
[HKEY_CLASSES_ROOT\ayon-launcher\shell]
[HKEY_CLASSES_ROOT\ayon-launcher\shell\open]
[HKEY_CLASSES_ROOT\ayon-launcher\shell\open\command]
@=hex(2):25,00,4c,00,4f,00,43,00,41,00,4c,00,41,00,50,00,50,00,44,00,41,00,54,\
00,41,00,25,00,5c,00,59,00,6e,00,70,00,75,00,74,00,5c,00,41,00,59,00,4f,00,\
4e,00,5c,00,73,00,68,00,69,00,6d,00,5c,00,61,00,79,00,6f,00,6e,00,2e,00,65,\
00,78,00,65,00,20,00,22,00,25,00,31,00,22,00,00,00
```

</details>

> [!CAUTION]
> Shim on macOs is installed to `/Applications/AYON.app`. To be able to use it in automation which waits for AYON launcher to finish then you have to use full path to executable `/Applications/AYON.app/Contents/MacOS/ayon`.
Expand Down
112 changes: 27 additions & 85 deletions common/ayon_common/_windows_register_scheme.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import os
import sys
import json
import subprocess
import tempfile

import winreg

SCRIPT_PATH = os.path.abspath(__file__)
PROTOCOL_NAME = "ayon-launcher"
_REG_ICON_PATH = "\\".join([PROTOCOL_NAME, "DefaultIcon"])
_REG_COMMAND_PATH = "\\".join([PROTOCOL_NAME, "shell", "open", "command"])
USER_CLASSES_PATH = "\\".join(["SOFTWARE", "Classes"])
PROTOCOL_PATH = "\\".join([USER_CLASSES_PATH, PROTOCOL_NAME])
_REG_ICON_PATH = "\\".join([PROTOCOL_PATH, "DefaultIcon"])
_REG_COMMAND_PATH = "\\".join([PROTOCOL_PATH, "shell", "open", "command"])


def _reg_exists(root, path):
Expand All @@ -26,69 +25,18 @@ def _reg_exists(root, path):
return False


def _update_reg_in_subprocess(shim_icon_path, shim_command):
import win32con
import win32process
import win32event
import pywintypes
from win32comext.shell.shell import ShellExecuteEx
from win32comext.shell import shellcon

with tempfile.NamedTemporaryFile(
prefix="ayon_reg", mode="w", delete=False
) as tmp:
tmp.write(json.dumps({
"icon": shim_icon_path,
"command": shim_command
}))
tmp_path = tmp.name

executable = sys.executable
command = subprocess.list2cmdline(
["--skip-bootstrap", SCRIPT_PATH, tmp_path]
)
try:
process_info = ShellExecuteEx(
nShow=win32con.SW_SHOWNORMAL,
fMask=shellcon.SEE_MASK_NOCLOSEPROCESS,
lpVerb="runas",
lpFile=executable,
lpParameters=command,
lpDirectory=os.path.dirname(executable)
def _update_reg(shim_icon_path, shim_command):
with winreg.CreateKeyEx(
winreg.HKEY_CURRENT_USER,
PROTOCOL_PATH,
access=winreg.KEY_WRITE
) as key:
winreg.SetValueEx(
key, "URL Protocol", 0, winreg.REG_SZ, ""
)

except pywintypes.error:
# User cancelled UAC dialog
return False

process_handle = process_info["hProcess"]
win32event.WaitForSingleObject(process_handle, win32event.INFINITE)
returncode = win32process.GetExitCodeProcess(process_handle)
if returncode != 0:
return False

with open(tmp_path, "r") as stream:
data = json.load(stream)
return data.get("success", False)


def _update_reg(shim_icon_path, shim_command, force_current_process=False):
try:
with winreg.CreateKeyEx(
winreg.HKEY_CLASSES_ROOT,
PROTOCOL_NAME,
access=winreg.KEY_WRITE
) as key:
winreg.SetValueEx(
key, "URL Protocol", 0, winreg.REG_SZ, ""
)
except PermissionError:
if force_current_process:
raise RuntimeError("Failed to set registry keys")
return _update_reg_in_subprocess(shim_icon_path, shim_command)

with winreg.CreateKeyEx(
winreg.HKEY_CLASSES_ROOT,
winreg.HKEY_CURRENT_USER,
_REG_ICON_PATH,
access=winreg.KEY_WRITE
) as key:
Expand All @@ -97,7 +45,7 @@ def _update_reg(shim_icon_path, shim_command, force_current_process=False):
)

with winreg.CreateKeyEx(
winreg.HKEY_CLASSES_ROOT,
winreg.HKEY_CURRENT_USER,
_REG_COMMAND_PATH,
access=winreg.KEY_WRITE
) as key:
Expand All @@ -108,18 +56,24 @@ def _update_reg(shim_icon_path, shim_command, force_current_process=False):


def _needs_update(shim_icon_path, shim_command):
# If 'USER_CLASSES_PATH' is not available, then the protocol
# is not registered. Probably running as service.
# 'HKEY_CURRENT_USER\SOFTWARE\Classes'
if not _reg_exists(winreg.HKEY_CURRENT_USER, USER_CLASSES_PATH):
return False

# Validate existence of all required registry keys
if (
not _reg_exists(winreg.HKEY_CLASSES_ROOT, PROTOCOL_NAME)
or not _reg_exists(winreg.HKEY_CLASSES_ROOT, _REG_ICON_PATH)
or not _reg_exists(winreg.HKEY_CLASSES_ROOT, _REG_COMMAND_PATH)
not _reg_exists(winreg.HKEY_CURRENT_USER, PROTOCOL_PATH)
or not _reg_exists(winreg.HKEY_CURRENT_USER, _REG_ICON_PATH)
or not _reg_exists(winreg.HKEY_CURRENT_USER, _REG_COMMAND_PATH)
):
return True

# Check if protocol has set version
with winreg.OpenKey(
winreg.HKEY_CLASSES_ROOT,
PROTOCOL_NAME,
winreg.HKEY_CURRENT_USER,
PROTOCOL_PATH,
0,
winreg.KEY_READ
) as key:
Expand All @@ -128,7 +82,7 @@ def _needs_update(shim_icon_path, shim_command):
return True

with winreg.OpenKey(
winreg.HKEY_CLASSES_ROOT,
winreg.HKEY_CURRENT_USER,
_REG_ICON_PATH,
0,
winreg.KEY_READ
Expand All @@ -141,7 +95,7 @@ def _needs_update(shim_icon_path, shim_command):
return True

with winreg.OpenKey(
winreg.HKEY_CLASSES_ROOT,
winreg.HKEY_CURRENT_USER,
_REG_COMMAND_PATH,
0,
winreg.KEY_READ
Expand Down Expand Up @@ -175,15 +129,3 @@ def set_reg(shim_path: str) -> bool:
if _needs_update(shim_icon_path, shim_command):
return _update_reg(shim_icon_path, shim_command)
return True


if __name__ == "__main__":
json_path = sys.argv.pop(-1)
with open(json_path, "r") as stream:
data = json.load(stream)
shim_command = data["command"]
shim_icon_path = data["icon"]
_update_reg(shim_icon_path, shim_command, True)
data["success"] = True
with open(json_path, "w") as stream:
json.dump(data, stream)
13 changes: 12 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ QtPy = "^2.3.0"
pywin32 = { version = "301", markers = "sys_platform == 'win32'" }
python3-xlib = { version="*", markers = "sys_platform == 'linux'"}
distro = { version="^1.9.0", markers = "sys_platform == 'linux'"}
pip = "24.0"

[tool.poetry.dev-dependencies]
flake8 = "^6.0"
Expand Down

0 comments on commit 60769ad

Please sign in to comment.