Skip to content

Instantly share code, notes, and snippets.

@d3dave
Last active December 28, 2023 22:09
Show Gist options
  • Save d3dave/03dcc04210fa3e45021026f9279254e1 to your computer and use it in GitHub Desktop.
Save d3dave/03dcc04210fa3e45021026f9279254e1 to your computer and use it in GitHub Desktop.
Download a ClickOnce application
#!/usr/bin/env python3
from bs4 import BeautifulSoup
import requests
import sys
from urllib.parse import urljoin
from pprint import pprint
from pathlib import Path
def usage():
print('Usage: getonce.py [application url]')
sys.exit(1)
if len(sys.argv) < 2:
usage()
application_url = sys.argv[1]
response = requests.get(application_url)
response.raise_for_status()
soup = BeautifulSoup(response.text, features="xml")
application_url = soup.find('deploymentProvider', codebase=True)['codebase']
install_dependent_assemblies = soup.find_all('dependentAssembly', codebase=True, dependencyType="install")
paths = [tag['codebase'] for tag in install_dependent_assemblies]
urls = [urljoin(application_url, path.replace('\\', '/')) for path in paths]
for url in urls:
response = requests.get(url)
response.raise_for_status()
if url.endswith('.manifest'):
manifest = BeautifulSoup(response.text, features="xml")
install_dependent_assemblies = manifest.find_all('dependentAssembly', codebase=True, dependencyType="install")
assembly_paths = [tag['codebase'] for tag in install_dependent_assemblies]
file_tags = manifest.find_all('file')
file_names = [tag['name'] for tag in file_tags]
deploy_urls = {(urljoin(url, path.replace('\\', '/')) + '.deploy'): path for path in file_names + assembly_paths}
output_dir = Path('output')
output_dir.mkdir()
for url, filename in deploy_urls.items():
response = requests.get(url)
response.raise_for_status()
(output_dir / filename).parent.mkdir(parents=True, exist_ok=True)
(output_dir / filename).write_bytes(response.content)
print(f'Downloaded {filename}')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment