Skip to content

Commit 6f8a19b

Browse files
committed
Update to support Windbg from the App store. 2.2.13
1 parent 49601ba commit 6f8a19b

File tree

4 files changed

+89
-7
lines changed

4 files changed

+89
-7
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
## Current Changes
2-
* 2.2.12
3-
* Fix #22 - comtypes issue
2+
* 2.2.13
3+
* Improved discovery of Windbg installation detection. Works with App store installations now.

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ Pybag provides helper functions on top of Python bindings for Microsoft Debug En
77

88
## Installation
99

10-
Windows:
11-
12-
Install the Debugging Tools from the Windows SDK here: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/ Note that neither of the versions of WinDbg from the Microsoft App Store nor the stand-alone installer are currently supported.
10+
Install the Debugging Tools
11+
* From the Windows SDK here: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/
12+
* From the App Store
13+
* Directly: https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/#install-windbg-directly
1314

1415
```sh
15-
python setup.py install
16+
pip install pybag
1617
```
1718

1819
## Usage example
@@ -57,6 +58,8 @@ k.attach("net:port=50000,key=1.2.3.4")
5758

5859

5960
## Release History
61+
* 2.2.13
62+
* Improved discovery of Windbg installation detection. Works with App store installations now.
6063
* 2.2.12
6164
* Fix #22 - comtypes issue
6265
* 2.2.11

pybag/__init__.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,91 @@
11
import ctypes
2+
import pathlib
23
import platform
4+
import shutil
35
import os
46
import winreg
57

68
__all__ = ['UserDbg', 'KernelDbg', 'CrashDbg', 'DbgEng']
79

10+
def get_arch():
11+
if platform.architecture()[0] == '64bit':
12+
return 'amd64'
13+
else:
14+
return 'x86'
815

916
def append_arch(dbgroot):
1017
if platform.architecture()[0] == '64bit':
1118
return os.path.join(dbgroot, r'Debuggers\x64')
1219
else:
1320
return os.path.join(dbgroot, r'Debuggers\x86')
1421

22+
def create_cachedir(cachedir, _dbg_dir):
23+
'''Creates a cache of DLL files from WinDbg. Necessary for the version of WinDbg installed from
24+
the Microsoft Store, due to file permission issues.'''
25+
26+
# Create the cache directory.
27+
os.mkdir(cachedir)
28+
29+
# Copy the DLL files we need to the new cache dir.
30+
shutil.copy(os.path.join(_dbg_dir, "dbgeng.dll"), cachedir)
31+
shutil.copy(os.path.join(_dbg_dir, "dbghelp.dll"), cachedir)
32+
shutil.copy(os.path.join(_dbg_dir, "dbgmodel.dll"), cachedir)
33+
34+
# Create version.txt in the cache dir with the full filesystem path that we copied the DLLs from.
35+
# This way we can detect if the cache is stale and needs to be re-created (as the full source path
36+
# contains the WinDbg version number).
37+
with open(os.path.join(cachedir, "version.txt"), "w") as f:
38+
f.write(_dbg_dir)
39+
40+
41+
def get_appdir_cache():
42+
appdir = find_app_install()
43+
if not appdir:
44+
return appdir
45+
46+
# For versions of WinDbg installed from the Microsoft Store, we need to copy the DLL files we need
47+
# into a separate directory, otherwise permission problems will prevent us from loading them.
48+
# We'll copy them to a folder named "pybag_cache" in the user's home directory.
49+
cachedir = os.path.join(str(os.environ['LOCALAPPDATA']), "pybag_cache")
50+
if not os.path.isdir(cachedir):
51+
create_cachedir(cachedir, appdir)
52+
else:
53+
saved_dbgdir = ""
54+
with open(os.path.join(cachedir, "version.txt"), "r") as f:
55+
saved_dbgdir = f.read()
56+
# If the full filesystem path of WinDbg differs from where the contents of the cache dir were
57+
# obtained, then a newer version of WinDbg was installed on this system and the cache is stale.
58+
# In that case we will re-build the cache entirely using the new version.
59+
if saved_dbgdir != appdir:
60+
shutil.rmtree(cachedir)
61+
create_cachedir(cachedir, appdir)
62+
return cachedir
63+
64+
65+
def find_app_install():
66+
# Loop through the keys in this registry path. Any key names that refer to WinDbg likely correspond
67+
# to the install directory in C:\Program Files\WindowsApps\.
68+
packages_key = winreg.OpenKey(
69+
winreg.HKEY_CLASSES_ROOT,
70+
r"Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\PackageRepository\Packages")
71+
continue_flag = True
72+
i = 0
73+
while continue_flag:
74+
try:
75+
package_name = winreg.EnumKey(packages_key, i)
76+
if package_name.find("WinDbg") != -1 and package_name.find("_neutral_") == -1:
77+
dir = os.path.join("C:\\Program Files\\WindowsApps", package_name, get_arch())
78+
if os.path.exists(dir):
79+
winreg.CloseKey(packages_key)
80+
return dir
81+
except OSError: # No more subkeys exist.
82+
continue_flag = False
83+
84+
i += 1
85+
86+
winreg.CloseKey(packages_key)
87+
return ''
88+
1589

1690
def find_dbgdir():
1791
dbgdir = os.getenv('WINDBG_DIR')
@@ -33,6 +107,11 @@ def find_dbgdir():
33107
dbgdir = append_arch(dbgroot)
34108
if os.path.exists(dbgdir):
35109
return dbgdir
110+
111+
dbgdir = get_appdir_cache()
112+
if os.path.exists(dbgdir):
113+
return dbgdir
114+
36115
raise RuntimeError("Windbg install directory not found!")
37116

38117

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
README = (HERE / "README.md").read_text()
77

88
setup(name='Pybag',
9-
version='2.2.12',
9+
version='2.2.13',
1010
description='Python wrappers for DbgEng from Windbg',
1111
long_description=README,
1212
long_description_content_type="text/markdown",

0 commit comments

Comments
 (0)