mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #23433 from twangboy/list_pkgs_fix
Obtain all software from the registry
This commit is contained in:
commit
55c3869861
1 changed files with 2 additions and 95 deletions
|
@ -25,7 +25,6 @@ except ImportError:
|
|||
import os
|
||||
import locale
|
||||
from distutils.version import LooseVersion # pylint: disable=E0611
|
||||
import re
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
|
@ -243,10 +242,6 @@ def list_pkgs(versions_as_list=False, **kwargs):
|
|||
if key in name_map:
|
||||
key = name_map[key]
|
||||
__salt__['pkg_resource.add_pkg'](ret, key, val)
|
||||
for key, val in _get_msi_software().iteritems():
|
||||
if key in name_map:
|
||||
key = name_map[key]
|
||||
__salt__['pkg_resource.add_pkg'](ret, key, val)
|
||||
|
||||
__salt__['pkg_resource.sort_pkglist'](ret)
|
||||
if not versions_as_list:
|
||||
|
@ -261,9 +256,7 @@ def _search_software(target):
|
|||
values added to the list passed in
|
||||
'''
|
||||
search_results = {}
|
||||
software = dict(
|
||||
list(_get_reg_software().items()) +
|
||||
list(_get_msi_software().items()))
|
||||
software = dict(_get_reg_software().items())
|
||||
for key, value in software.items():
|
||||
if key is not None:
|
||||
if target.lower() in key.lower():
|
||||
|
@ -271,56 +264,6 @@ def _search_software(target):
|
|||
return search_results
|
||||
|
||||
|
||||
def _get_msi_software():
|
||||
'''
|
||||
Uses powershell to search the msi product databases, returns a
|
||||
dict keyed on the product name as the key and the version as the
|
||||
value. If powershell is not available, returns `{}`
|
||||
'''
|
||||
win32_products = {}
|
||||
|
||||
# Don't use WMI to select from `Win32_product`, that has nasty
|
||||
# side effects. Use the `WindowsInstaller.Installer` COM object's
|
||||
# `ProductsEx`. Jumping through powershell because `ProductsEx` is
|
||||
# a get property that takes 3 arguments, and `win32com` can't call
|
||||
# that
|
||||
#
|
||||
# see https://github.com/saltstack/salt/issues/12550 for detail
|
||||
|
||||
# powershell script to fetch (name, version) from COM, and write
|
||||
# without word-wrapping. Attempting to target minimal powershell
|
||||
# versions
|
||||
ps = '''
|
||||
$msi = New-Object -ComObject WindowsInstaller.Installer;
|
||||
$msi.GetType().InvokeMember('ProductsEx', 'GetProperty', $null, $msi, ('', 's-1-1-0', 7))
|
||||
| select @{
|
||||
name='name';
|
||||
expression={$_.GetType().InvokeMember('InstallProperty', 'GetProperty', $null, $_, ('ProductName'))}
|
||||
},
|
||||
@{
|
||||
name='version';
|
||||
expression={$_.GetType().InvokeMember('InstallProperty', 'GetProperty', $null, $_, ('VersionString'))}
|
||||
}
|
||||
| Write-host
|
||||
'''.replace('\n', ' ') # make this a one-liner
|
||||
|
||||
ret = __salt__['cmd.run_all'](ps, shell='powershell', python_shell=True)
|
||||
# sometimes the powershell reflection fails on a single product,
|
||||
# giving us a non-zero return code AND useful output. Ignore RC
|
||||
# and just try to process stdout, which should empty if the cmd
|
||||
# failed.
|
||||
#
|
||||
# each line of output looks like:
|
||||
#
|
||||
# `@{name=PRD_NAME; version=PRD_VER}`
|
||||
pattern = r'@{name=(.+); version=(.+)}'
|
||||
for m in re.finditer(pattern, ret['stdout']):
|
||||
(prd_name, prd_ver) = m.groups()
|
||||
win32_products[prd_name] = prd_ver
|
||||
|
||||
return win32_products
|
||||
|
||||
|
||||
def _get_reg_software():
|
||||
'''
|
||||
This searches the uninstall keys in the registry to find
|
||||
|
@ -346,8 +289,7 @@ def _get_reg_software():
|
|||
|
||||
#attempt to corral the wild west of the multiple ways to install
|
||||
#software in windows
|
||||
reg_entries = dict(list(_get_user_keys().items()) +
|
||||
list(_get_machine_keys().items()))
|
||||
reg_entries = dict(_get_machine_keys().items())
|
||||
for reg_hive, reg_keys in reg_entries.items():
|
||||
for reg_key in reg_keys:
|
||||
try:
|
||||
|
@ -366,8 +308,6 @@ def _get_reg_software():
|
|||
reg_hive,
|
||||
prd_uninst_key,
|
||||
'WindowsInstaller')
|
||||
if windows_installer != 'Not Found' and windows_installer:
|
||||
continue
|
||||
|
||||
prd_name = _get_reg_value(
|
||||
reg_hive,
|
||||
|
@ -406,39 +346,6 @@ def _get_machine_keys():
|
|||
return machine_hive_and_keys
|
||||
|
||||
|
||||
def _get_user_keys():
|
||||
'''
|
||||
This will return the hive 'const' value and some registry keys where
|
||||
installed software information has been known to exist for the
|
||||
HKEY_USERS hive
|
||||
'''
|
||||
user_hive_and_keys = {}
|
||||
user_keys = []
|
||||
users_hive = win32con.HKEY_USERS
|
||||
#skip some built in and default users since software information in these
|
||||
#keys is limited
|
||||
skip_users = ['.DEFAULT',
|
||||
'S-1-5-18',
|
||||
'S-1-5-19',
|
||||
'S-1-5-20']
|
||||
sw_uninst_key = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
|
||||
reg_handle = win32api.RegOpenKeyEx(
|
||||
users_hive,
|
||||
'',
|
||||
0,
|
||||
win32con.KEY_READ)
|
||||
for name, num, blank, time in win32api.RegEnumKeyEx(reg_handle):
|
||||
#this is some identical key of a sid that contains some software names
|
||||
#but no detailed information about the software installed for that user
|
||||
if '_Classes' in name:
|
||||
break
|
||||
if name not in skip_users:
|
||||
usr_sw_uninst_key = "\\".join([name, sw_uninst_key])
|
||||
user_keys.append(usr_sw_uninst_key)
|
||||
user_hive_and_keys[users_hive] = user_keys
|
||||
return user_hive_and_keys
|
||||
|
||||
|
||||
def _get_reg_value(reg_hive, reg_key, value_name=''):
|
||||
'''
|
||||
Read one value from Windows registry.
|
||||
|
|
Loading…
Add table
Reference in a new issue