Skip to content

Instantly share code, notes, and snippets.

@tigerhawkvok
Last active December 11, 2023 00:53
Show Gist options
  • Save tigerhawkvok/aad3f184b37bb869df5bd337d4b4c22e to your computer and use it in GitHub Desktop.
Save tigerhawkvok/aad3f184b37bb869df5bd337d4b4c22e to your computer and use it in GitHub Desktop.
Get the installation path for a package installed by Chocolatey
#!python3
"""
Script and function to get the path of a chocolatey install
matching the `pathComponent`, or, if none provided, the
last installed path.
@author Philip Kahn
@date 20230614
@license MIT
@url https://gist.github.com/tigerhawkvok/aad3f184b37bb869df5bd337d4b4c22e
"""
import subprocess
import re
from pathlib import Path
import warnings
from typing import Optional
import argparse
# cSpell:words choco
def getChocoInstalledPath(pathComponent:Optional[str]= None) -> Path:
"""
Spawn a subprocess to get the last installed path of a chocolatey package.
Parameters
----------
pathComponent : Optional[str]
A known path component of the path to be found.
If `None`, the last installed path is returned.
Returns
-------
Path
Raises
------
ValueError
"""
if pathComponent == "":
pathComponent = None
# TODO be clever about Chocolatey install path
command = """(Get-Content "$env:PROGRAMDATA\chocolatey\logs\choco.summary.log") -match 'Software installed to'"""
if pathComponent is None:
command += " | Select-Object -Last 1"
result = subprocess.run(["powershell", "-Command", command], capture_output= True, text= True, encoding= "utf-8", shell= True, check= True)
stdout = result.stdout
if pathComponent is not None:
# Search for the path component
found = False
for entry in reversed(stdout.splitlines()):
# Search most recent first
if pathComponent in entry:
stdout = entry
found = True
break
if not found:
raise ValueError(f"No path found containing substring `{pathComponent}`")
# A single candidate line has been found
output = re.search(r"Software installed to '(.*)'", stdout)
if output is not None:
# Do some path validation
outPath = Path(output.group(1))
if outPath.exists():
if not outPath.is_dir():
warnings.warn("The path found is not a directory")
return outPath
warnings.warn("The path found does not exist")
return outPath
raise ValueError("No path found")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description= "Get the path of a chocolatey install matching the pathComponent, or, if none provided, the last installed path")
parser.add_argument('pathComponent', type= str, nargs= '?',
help='a known path component of the path to be found')
args = parser.parse_args()
print(getChocoInstalledPath(args.pathComponent))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment