Skip to content

Commit f539d39

Browse files
committed
Add app id management and create shortcut
1 parent ab3e35e commit f539d39

File tree

5 files changed

+349
-10
lines changed

5 files changed

+349
-10
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
A Python library that provides useful functionality for managing Microsoft Windows systems.
44

5+
## Features
6+
7+
* App Model Id management for shortcuts and inside python applications to allow for taskbar grouping.
8+
* Finding, creating and moving shortcuts.
9+
* Pinning shortcuts to the taskbar and start menu.
10+
* Flashing a window to get a users attention.
511

612
## Shortcut management
713

@@ -36,3 +42,9 @@ Pinning/unpinning a shortcut to the taskbar:
3642
C:\blur\dev\casement>casement shortcut pin "C:\Users\Public\Desktop\My Shortcut.lnk" -t
3743
C:\blur\dev\casement>casement shortcut unpin "C:\Users\Public\Desktop\My Shortcut.lnk" -t
3844
```
45+
46+
# Installing
47+
48+
Casement can be installed by the standard pip command `pip install casement`.
49+
There is also an optional extras_require option `pip install casement[pil]` to
50+
allow creating shortcut icons by converting image files to .ico files.

casement/app_id.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import ctypes
2+
import os
3+
import pythoncom
4+
from ctypes import wintypes
5+
from win32com.propsys import propsys
6+
from win32com.shell import shellcon
7+
8+
9+
class AppId(object):
10+
@staticmethod
11+
def for_shortcut(shortcut):
12+
"""Gets the AppUserModel.ID for the given shortcut.
13+
14+
This will allow windows to group windows with the same app id on a shortcut
15+
pinned to the taskbar. Use :py:meth:`AppId.for_application` to set the
16+
app id for a running application.
17+
"""
18+
if os.path.exists(shortcut):
19+
# These imports won't work inside python 2 DCC's
20+
from win32com.propsys import propsys
21+
22+
# Original info from https://stackoverflow.com/a/61714895
23+
key = propsys.PSGetPropertyKeyFromName("System.AppUserModel.ID")
24+
store = propsys.SHGetPropertyStoreFromParsingName(shortcut)
25+
return store.GetValue(key).GetValue()
26+
27+
@staticmethod
28+
def set_for_shortcut(shortcut, app_id):
29+
"""Sets AppUserModel.ID info for a windows shortcut.
30+
31+
Note: This doesn't seem to work on a pinned taskbar shortcut. Set it on
32+
a desktop shortcut then pin that shortcut.
33+
34+
This will allow windows to group windows with the same app id on a shortcut
35+
pinned to the taskbar. Use :py:meth:`AppId.set_for_application` to set
36+
the app id for a running application.
37+
38+
Args:
39+
shortcut (str): The .lnk filename to set the app id on.
40+
app_id (str): The app id to set on the shortcut
41+
"""
42+
if os.path.exists(shortcut):
43+
# Original info from https://stackoverflow.com/a/61714895
44+
key = propsys.PSGetPropertyKeyFromName("System.AppUserModel.ID")
45+
store = propsys.SHGetPropertyStoreFromParsingName(
46+
shortcut, None, shellcon.GPS_READWRITE, propsys.IID_IPropertyStore
47+
)
48+
49+
new_value = propsys.PROPVARIANTType(app_id, pythoncom.VT_BSTR)
50+
store.SetValue(key, new_value)
51+
store.Commit()
52+
53+
@staticmethod
54+
def for_application():
55+
"""Returns the current Windows 7+ app user model id used for taskbar
56+
grouping."""
57+
58+
lp_buffer = wintypes.LPWSTR()
59+
app_user_model_id = (
60+
ctypes.windll.shell32.GetCurrentProcessExplicitAppUserModelID
61+
)
62+
app_user_model_id(ctypes.cast(ctypes.byref(lp_buffer), wintypes.LPWSTR))
63+
appid = lp_buffer.value
64+
ctypes.windll.kernel32.LocalFree(lp_buffer)
65+
return appid
66+
67+
@staticmethod
68+
def set_for_application(appid, prefix=None):
69+
"""Controls Windows taskbar grouping.
70+
71+
Specifies a Explicit App User Model ID that Windows 7+ uses to control
72+
grouping of windows on the taskbar. This must be set before any ui is
73+
displayed. The best place to call it is in the first widget to be displayed
74+
__init__ method.
75+
76+
See :py:meth:`AppId.set_for_shortcut` to set the app id on a windows shortcut.
77+
78+
Args:
79+
appid (str): The id of the application. Should use full camel-case.
80+
http://msdn.microsoft.com/en-us/library/dd378459%28v=vs.85%29.aspx#how
81+
prefix (str, optional): The prefix attached to the id.
82+
"""
83+
84+
# https://stackoverflow.com/a/27872625
85+
if prefix:
86+
appid = u'%s.%s' % (prefix, appid)
87+
return not ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(appid)

0 commit comments

Comments
 (0)