Friday, 20 December 2013

Listing all installed applications on Windows with python

The following code is a small script that contains the functions to query the installed software in the system which is very similar to the script found in WiLstPrd.vbs but using python instead of VB and ctypes.

this python script will show list of installed application on windows os.

# This scripts allows to get a list of all installed products in a windows
# machine. The code uses ctypes becuase there were a number of issues when
# trying to achieve the same win win32com.client
from collections import namedtuple
from ctypes import byref, create_unicode_buffer, windll
from ctypes.wintypes import DWORD
from itertools import count
 
# defined at http://msdn.microsoft.com/en-us/library/aa370101(v=VS.85).aspx
UID_BUFFER_SIZE = 39
PROPERTY_BUFFER_SIZE = 256 
ERROR_MORE_DATA = 234
ERROR_INVALID_PARAMETER = 87
ERROR_SUCCESS = 0
ERROR_NO_MORE_ITEMS = 259 
ERROR_UNKNOWN_PRODUCT = 1605 
 
# diff propoerties of a product, not all products have all properties
PRODUCT_PROPERTIES = [u'Language',
                      u'ProductName',
                      u'PackageCode',
                      u'Transforms',
                      u'AssignmentType',
                      u'PackageName',
                      u'InstalledProductName',
                      u'VersionString',
                      u'RegCompany',
                      u'RegOwner',
                      u'ProductID',
                      u'ProductIcon',
                      u'InstallLocation',
                      u'InstallSource',
                      u'InstallDate',
                      u'Publisher',
                      u'LocalPackage',
                      u'HelpLink',
                      u'HelpTelephone',
                      u'URLInfoAbout',
                      u'URLUpdateInfo',] 
 
# class to be used for python users :)
Product = namedtuple('Product', PRODUCT_PROPERTIES)
 
 
def get_property_for_product(product, property, buf_size=PROPERTY_BUFFER_SIZE):
    """Retruns the value of a fiven property from a product."""
    property_buffer = create_unicode_buffer(buf_size)
    size = DWORD(buf_size)
    result = windll.msi.MsiGetProductInfoW(product, property, property_buffer,
                                           byref(size))
    if result == ERROR_MORE_DATA:
        return get_property_for_product(product, property,
                2 * buf_size)
    elif result == ERROR_SUCCESS:
        return property_buffer.value
    else:
        return None
 
 
def populate_product(uid):
    """Return a Product with the different present data."""
    properties = []
    for property in PRODUCT_PROPERTIES:
        properties.append(get_property_for_product(uid, property))
    return Product(*properties) 
 
 
def get_installed_products_uids():
    """Returns a list with all the different uid of the installed apps."""
    # enum will return an error code according to the result of the app
    products = []
    for i in count(0):
        uid_buffer = create_unicode_buffer(UID_BUFFER_SIZE)
        result = windll.msi.MsiEnumProductsW(i, uid_buffer)
        if result == ERROR_NO_MORE_ITEMS:
            # done interating over the collection
            break
        products.append(uid_buffer.value)
    return products
 
 
def get_installed_products():
    """Returns a collection of products that are installed in the system."""
    products = []
    for puid in  get_installed_products_uids():
        products.append(populate_product(puid))
    return products 
 
 
def is_product_installed_uid(uid):
    """Return if a product with the given id is installed.
 
    uid Most be a unicode object with the uid of the product using
    the following format {uid}
    """
    # we try to get the VersisonString for the uid, if we get an error it means
    # that the product is not installed in the system.
    buf_size = 256
    uid_buffer = create_unicode_buffer(uid)
    property = u'VersionString'
    property_buffer = create_unicode_buffer(buf_size)
    size = DWORD(buf_size)
    result = windll.msi.MsiGetProductInfoW(uid_buffer, property, property_buffer,
                                           byref(size))
    if result == ERROR_UNKNOWN_PRODUCT:
        return False
    else:
        return True

apps=get_installed_products()
for app in apps:
    print app.InstalledProductName

The above code will allow a python developer to check which products are installed on Windows as well as to know if a product with the given UID is indeed installed.

Thanks

16 comments:

  1. Hey man!!!
    Nice Work!!
    That was what I was looking for.

    ReplyDelete
  2. There are still some software's which this script is not able to detect,
    what's the reason behind that??
    and is there any solutions for the same??

    ReplyDelete
    Replies
    1. Can you tell me which software or which type software it is not publishing?

      Delete
    2. Anything that is not published by Microsoft

      Delete
    3. Yes. it will publish the list of the software package which you can see in "Programes and features". it will not show which is installed by exe. Some exe package make for just dumping some files in to programs folder and setting path to that folder.

      Delete
  3. Hi Ashish,
    that's a great script, but it cannot get the all software in win10 64bit. do you have latest version of this script?

    ReplyDelete
  4. it is a great script for me. but it seems cannot get all applications in win10 64bit. do you have latest version of this script, Ashish?

    ReplyDelete
  5. does this script just get the application installed through MSI package? if the application was installed by .exe, it will not list them?

    ReplyDelete
    Replies
    1. Yes. it will publish the list of the software package which you can see in "Programes and features". it will not show which is installed by exe. Some exe package make for just dumping some files in to programs folder and setting path to that folder.

      Delete
  6. print app.y.InstalledProductName
    Attribute error: 'Product' object has no attribute y.

    This error occurs in my program. What to do ?

    ReplyDelete
    Replies
    1. i modified above script. Please check and let me know if u face any pbm.

      Delete
  7. Hi Ashish... Great work man!!!
    I am facing a problem here. Though the my program is visible in "Programs and Features", it is not showing the desired program name while executing the script. Is there any specific reason behind it? And also I could see there is a NoneType exception for certain programs. Can you please help me out with this.
    Thanks

    ReplyDelete
  8. Hi Ashish, Do you have script that writes this data in csv file format.

    ReplyDelete
    Replies
    1. you can save the output data in csv file in different ways. like save list of dictionary to csv file etc.. find the link below for reference.
      https://stackoverflow.com/questions/3086973/how-do-i-convert-this-list-of-dictionaries-to-a-csv-file

      http://tutorialspoint.com/How-to-save-a-Python-Dictionary-to-CSV-file

      Delete
  9. where can i find the output list in my pc??

    ReplyDelete
    Replies
    1. You can get the output in python console and ( control Panel-> Program & Features ) in your PC

      Delete