mirror of
https://github.com/norohind/AudioControl.git
synced 2025-04-12 05:00:01 +03:00
59 lines
1.9 KiB
Python
59 lines
1.9 KiB
Python
import ctypes
|
|
from ctypes import wintypes as w
|
|
import array
|
|
from functools import lru_cache
|
|
from psutil import Process
|
|
import traceback
|
|
|
|
|
|
ver = ctypes.WinDLL('version')
|
|
ver.GetFileVersionInfoSizeW.argtypes = w.LPCWSTR, w.LPDWORD
|
|
ver.GetFileVersionInfoSizeW.restype = w.DWORD
|
|
ver.GetFileVersionInfoW.argtypes = w.LPCWSTR, w.DWORD, w.DWORD, w.LPVOID
|
|
ver.GetFileVersionInfoW.restype = w.BOOL
|
|
ver.VerQueryValueW.argtypes = w.LPCVOID, w.LPCWSTR, ctypes.POINTER(w.LPVOID), w.PUINT
|
|
ver.VerQueryValueW.restype = w.BOOL
|
|
|
|
|
|
def get_file_description(filepath: str) -> str:
|
|
# https://stackoverflow.com/questions/42604493/verqueryvaluew-issue-python-3
|
|
size = ver.GetFileVersionInfoSizeW(filepath, None)
|
|
if not size:
|
|
raise RuntimeError('version info not found')
|
|
|
|
res = ctypes.create_string_buffer(size)
|
|
if not ver.GetFileVersionInfoW(filepath, 0, size, res):
|
|
raise RuntimeError('GetFileVersionInfoW failed')
|
|
|
|
buf = w.LPVOID()
|
|
length = w.UINT()
|
|
# Look for codepages
|
|
if not ver.VerQueryValueW(res, r'\VarFileInfo\Translation', ctypes.byref(buf), ctypes.byref(length)):
|
|
raise RuntimeError('VerQueryValueW failed to find translation')
|
|
|
|
if length.value == 0:
|
|
raise RuntimeError('no code pages')
|
|
|
|
codepages = array.array('H', ctypes.string_at(buf.value, length.value))
|
|
codepage = codepages[:2]
|
|
# Extract information
|
|
if not ver.VerQueryValueW(
|
|
res,
|
|
rf'\StringFileInfo\{codepage[0]:04x}{codepage[1]:04x}\FileDescription',
|
|
ctypes.byref(buf),
|
|
ctypes.byref(length)
|
|
):
|
|
raise RuntimeError('VerQueryValueW failed to find file version')
|
|
|
|
return ctypes.wstring_at(buf.value, length.value - 1)
|
|
|
|
|
|
@lru_cache
|
|
def get_app_name(app_process: Process) -> str:
|
|
try:
|
|
return get_file_description(app_process.exe())
|
|
|
|
except Exception:
|
|
traceback.print_exc()
|
|
return app_process.name()
|