Runs specified MSI Installer via command line in silent mode. This is work in progress.
(
installer: Path,
install_dir: Path,
installer_input=None,
timeout=420,
check=True,
options: list | None = None,
)
| 439 | |
| 440 | |
| 441 | def _run_installer_msi( |
| 442 | installer: Path, |
| 443 | install_dir: Path, |
| 444 | installer_input=None, |
| 445 | timeout=420, |
| 446 | check=True, |
| 447 | options: list | None = None, |
| 448 | ): |
| 449 | """Runs specified MSI Installer via command line in silent mode. This is work in progress.""" |
| 450 | if not sys.platform.startswith("win"): |
| 451 | raise ValueError("Can only run .msi installers on Windows") |
| 452 | |
| 453 | # Translate NSIS-style options to MSI properties and collect MSI properties |
| 454 | msi_properties = [] |
| 455 | allusers = False |
| 456 | if options is None: |
| 457 | options = [] |
| 458 | for opt in options: |
| 459 | if opt == "/InstallationType=AllUsers": |
| 460 | allusers = True |
| 461 | elif opt == "/InstallationType=JustMe": |
| 462 | allusers = False |
| 463 | elif "=" in opt and not opt.startswith("/"): |
| 464 | # Direct MSI property (e.g., "OPTION_INITIALIZE_CONDA=1") |
| 465 | msi_properties.append(opt) |
| 466 | |
| 467 | cmd = [ |
| 468 | "msiexec.exe", |
| 469 | "/i", |
| 470 | str(installer), |
| 471 | "ALLUSERS=1" |
| 472 | if allusers |
| 473 | else "MSIINSTALLPERUSER=1", # For some reason tests fail on the CI system if "ALLUSERS=1" |
| 474 | *msi_properties, |
| 475 | "/qn", |
| 476 | ] |
| 477 | |
| 478 | # Prepare logging |
| 479 | post_install_log = install_dir / "install.log" |
| 480 | # Logging from MSI engine is handled separately |
| 481 | log_path = Path(os.environ.get("TEMP")) / (install_dir.name + "-install.log") |
| 482 | if log_path.exists(): |
| 483 | os.remove(log_path) |
| 484 | cmd.extend(["/L*V", str(log_path)]) |
| 485 | |
| 486 | # Run installer and handle errors/logs if necessary |
| 487 | try: |
| 488 | process = _execute(cmd, installer_input=installer_input, timeout=timeout, check=check) |
| 489 | except subprocess.CalledProcessError as e: |
| 490 | handle_exception_and_error_out( |
| 491 | InstallationFailure( |
| 492 | cmd=cmd, |
| 493 | returncode=e.returncode, |
| 494 | msi_log=log_path, |
| 495 | post_install_log=post_install_log, |
| 496 | ), |
| 497 | original_exception=e, |
| 498 | ) |
no test coverage detected