#!/usr/bin/env vpython3
# Copyright 2015 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Dumps a Windows shortcut's property bag to stdout.
This is required to confirm correctness of properties that aren't readily
available in Windows UI.
If you run into "ImportError: No module named pywintypes":
Run this script with vpython3 instead.
"""
import optparse
from pywintypes import IID
import sys
from win32com.propsys import propsys
from win32com.propsys import pscon
def BuildPKeyToNameMapping():
"""Returns a dict mapping PKey values (a tuple of an IID and an int) to their
names."""
# The pscon module contains a number of well-known PKey values. Scan through
# the module picking out anything that looks plausibly like a PROPERTYKEY (a
# tuple of a PyIID and an int), and map it to its name in the module.
return {item: name for (name, item) in pscon.__dict__.items() if (
isinstance(item, tuple) and
len(item) == 2 and
isinstance(item[1], int))}
def PrintShortcutProperties(shortcut_path, dump_all):
properties = propsys.SHGetPropertyStoreFromParsingName(shortcut_path)
print('Known properties (--dump-all for more):')
app_id = properties.GetValue(pscon.PKEY_AppUserModel_ID).GetValue()
print('\tAppUserModelId => "%s"' % app_id)
# Hard code PKEY_AppUserModel_IsDualMode as pscon doesn't support it.
PKEY_AppUserModel_IsDualMode = (IID('{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}'),
11)
dual_mode = properties.GetValue(PKEY_AppUserModel_IsDualMode).GetValue()
print('\tDual Mode => "%s"' % dual_mode)
# Dump all other properties with their raw ID if requested, add them above
# over time as we explicitly care about more properties, see propkey.h or
# pscon.py for a reference of existing PKEYs' meaning.
if dump_all:
key_to_name = BuildPKeyToNameMapping()
print('\nOther properties:')
for i in range(0, properties.GetCount()):
property_key = properties.GetAt(i)
# |property_key| is a tuple of an IID identifying the format and an int
# (a.k.a. a PROPERTYKEY struct). If this key is one of the predefined ones
# in the pscon module, display the name given to it by the module. If not,
# show the key's IID and int -- the viewer may be able to find it in
# propkey.h.
key_name = key_to_name.get(property_key, str(property_key))
property_value = properties.GetValue(property_key).GetValue()
print('\t%s => "%s"' % (key_name, property_value))
def main():
usage = 'usage: %prog [options] "C:\\Path\\To\\My Shortcut.lnk"'
parser = optparse.OptionParser(usage,
description="Dumps a shortcut's properties.")
parser.add_option('-a', '--dump-all', action='store_true', dest='dump_all',
default=False)
options, args = parser.parse_args()
if len(args) != 1:
parser.error('incorrect number of arguments')
PrintShortcutProperties(args[0], options.dump_all)
if __name__ == '__main__':
sys.exit(main())