Scanning for Python

Comments

7 comments

  • Christian Ullrich

    The scan is performed by the target service running as SYSTEM. It does not detect the Python installation because its Uninstall key is in HKCU of the user that Deploy used to install it, and that user profile is not typically loaded. If, however, the user profile _is_ loaded, Inventory finds the installation just fine.

    So how can I make sure that the Deploy target user's profile is loaded (as in, HKU\S-1-* exists) when Inventory runs?

    0
    Comment actions Permalink
  • Jackson, Jared

    Hey Christian,

    I am no python expert, and I might be misunderstanding your post, but I am asked to install it in our labs frequently.

    When installing 3.5, I use the .exe installer.  It ends up looking something like this...

    "\\NetworkPath\python-3.5.1-amd64.exe" /quiet InstallAllUsers=1

    Is that comparable to how you are installing it?

     

    0
    Comment actions Permalink
  • Jackson, Jared

    I use SCCM for software/hardware inventory.  We have not moved over to PDQ Inventory, so I am unfamiliar with it at this point.  However, with my installation method, SCCM is able to pick up on the installation of Python and I can run queries for install/update collections.  Maybe I am just misunderstanding your issue, but I figured I would throw out my installation method to see if that would help at all.

    0
    Comment actions Permalink
  • Colby Bouma

    If you add this as a PowerShell step to your Python installer package it will move the Registry entries and the uninstaller to the standard locations. You can also run it as a separate package to clean up existing installations.

    Note: The uninstaller does not delete these once you have moved them. It's not a problem, it's just stuff that gets left behind.

    $Uninstall_Entries = Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*" | Where-Object { $_.DisplayName -like "Python*" }

    ForEach ( $Uninstall_Entry in $Uninstall_Entries ) {

        $GUID = $Uninstall_Entry.PSChildName
        $Registry_Path = "Software\Microsoft\Windows\CurrentVersion\Uninstall\$GUID"
        Write-Output "GUID: $GUID"

        # Move the Registry entries to HKEY_LOCAL_MACHINE
        Move-Item "HKCU:\$Registry_Path" "HKLM:\$Registry_Path"
        $Uninstall_Entry = Get-ItemProperty "HKLM:\$Registry_Path"

        # Move the uninstaller to the normal global location
        $Uninstaller_Path = "$env:LOCALAPPDATA\Package Cache\$GUID"
        Move-Item "$Uninstaller_Path" "$env:SystemRoot\Installer\$GUID"

        # Update the Registry entries with the new path of the uninstaller
        ForEach ( $Property in "BundleCachePath", "DisplayIcon", "QuietUninstallString", "UninstallString" ) {

            $Updated_Property = $Uninstall_Entry.$Property.Replace("$env:LOCALAPPDATA\Package Cache", "$env:SystemRoot\Installer")
            Set-ItemProperty -Force -Path "HKLM:\$Registry_Path" -Name "$Property" -Value "$Updated_Property"

        }

    }
    0
    Comment actions Permalink
  • Christian Ullrich

    Colby, thank you for this idea. I think it would be better to copy the entries than to move them, so that the originals are still there for an upgrade installation to notice. In principle, since it's all MSI under the hood anyway, it should work regardless.

    Jared, yes, that is the same as what I am doing. The only difference is that I have the "InstallAllUsers" in the optional XML file rather than on the command line. I don't know how SCCM manages to see the existing installation, but my guess is that it does deployment and inventory as the same user. [Update: Or rather, that SCCM inventories as the same user PDQ Deploy installs as.]

    There has also been a Python bug about this HKLM/HKCU confusion, in which I seem to be tilting at windmills because nobody else considers it important at all: https://bugs.python.org/issue25166

    0
    Comment actions Permalink
  • Colby Bouma

    You're right, copying would be a better idea. Also, you can use the original installer to uninstall, so if the uninstaller gets deleted it shouldn't matter.

    One thing I forgot to mention is that when you uninstall you need to delete the copied/moved registry entry manually or it will look like Python is still installed.

    0
    Comment actions Permalink
  • Christian Ullrich

    So I did something else entirely. I wrote a minimal Windows service that does nothing but wait for the Inventory scan service to stop before stopping itself. The key is that this service is configured to run as the same user that Deploy uses for installations, so starting the service loads the appropriate user profile, and Inventory can then scan it.

    One scheduled task later, my service starts instantly when Inventory begins a scan (Service Control Manager event 7045, "new service installed", with a filter that matches only the PDQ Inventory scanner service).

    This works absolutely perfectly, at least on 7 and 10. As of now, my service has won the race condition between it starting and Inventory scanning for applications every single time (out of perhaps 50). I don't think there can be a proper synchronization between the two because Inventory only installs its service when it wants to scan and deletes it immediately after the scan; this makes it impossible to make the scanner service dependent on mine.

    0
    Comment actions Permalink

Please sign in to leave a comment.