Public/Repair-SACODIS.ps1
|
function Repair-SACODIS { <# .SYNOPSIS Uninstalls, cleans directory states, and reinstalls the Autodesk On-Demand Install Service (ODIS). .DESCRIPTION Resolves common ODIS installation failures (e.g., "Unable to install - An error occurred while preparing the installation") by performing a structured repair: 1. Kills active ODIS-related processes. 2. Runs the native uninstaller (RemoveODIS.exe) if present. 3. Stops and deletes the AdODISService. 4. Renames existing ODIS folders to preserve installer logs while preventing state reuse. 5. Downloads the latest AdODIS-installer.exe from Autodesk's servers. 6. Performs a silent reinstallation of the AdODIS service. .PARAMETER Silent Switch. Bypasses the confirmation prompt for headless/scripted execution. .EXAMPLE Repair-SACODIS .EXAMPLE Repair-SACODIS -Silent #> [CmdletBinding()] param ( [switch]$Silent ) $isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if (-not $isAdmin) { Write-Error "Repair-SACODIS must be run in an elevated Administrator session." return } if (-not $Silent) { Write-Host "`n==========================================================" -ForegroundColor Cyan Write-Host " AUTODESK ODIS INSTALLER REPAIR" -ForegroundColor Cyan Write-Host "==========================================================" -ForegroundColor Cyan Write-Host "This utility will perform the following actions:" -ForegroundColor Yellow Write-Host " 1. Terminate all active ODIS processes." -ForegroundColor Gray Write-Host " 2. Run the native ODIS uninstaller (if present)." -ForegroundColor Gray Write-Host " 3. Stop and delete the AdODISService." -ForegroundColor Gray Write-Host " 4. Rename old ODIS data and log paths to prevent reuse." -ForegroundColor Gray Write-Host " 5. Download the latest AdODIS-installer.exe from Autodesk." -ForegroundColor Gray Write-Host " 6. Perform a fresh, silent reinstall of ODIS." -ForegroundColor Gray Write-Host "----------------------------------------------------------" -ForegroundColor Cyan $Confirm = Read-Host "Proceed with ODIS installer repair? (y/N)" if ($Confirm -notmatch '^[yY](es)?$') { Write-Host "`nODIS repair cancelled by user." -ForegroundColor Yellow return } } $StopWatch = [System.Diagnostics.Stopwatch]::StartNew() $script:SACFailures = @() # --- Setup Logging --- $ToDate = Get-Date -Format 'yyyyMMdd_HHmmss' $BaseTemp = if (Test-Path "C:\temp") { "C:\temp" } else { $env:TEMP } $LogDir = Join-Path $BaseTemp "AutodeskODISRepair_$ToDate" New-Item -ItemType Directory -Path $LogDir -Force -ErrorAction SilentlyContinue | Out-Null $TranscriptLog = Join-Path $LogDir "ODISRepairTranscript.log" Start-Transcript -Path $TranscriptLog -Append -Force | Out-Null Write-SACMsg "Beginning Autodesk ODIS Repair Flow..." "Info" Write-SACMsg "Log directory initialized at: $LogDir" "Info" # 1. Kill active ODIS processes $ProcessesToKill = @("AdODIS", "AdODISService", "AdODISInstaller") Write-SACMsg "Terminating ODIS processes..." "Info" foreach ($proc in $ProcessesToKill) { $running = Get-Process -Name $proc -ErrorAction SilentlyContinue if ($running) { Write-SACMsg " Stopping running process: $proc" "Info" Stop-Process -Name $proc -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 1 } } # 2. Run native ODIS uninstaller if present $RemovePath = Join-Path $env:ProgramFiles "Autodesk\AdODIS\V1\RemoveODIS.exe" if (Test-Path $RemovePath) { Write-SACMsg "Executing native ODIS uninstaller: $RemovePath" "Info" try { $proc = Start-Process -FilePath $RemovePath -ArgumentList "--mode unattended" -Wait -PassThru -NoNewWindow -ErrorAction SilentlyContinue if ($proc.ExitCode -eq 0) { Write-SACMsg " [OK] Native uninstaller finished successfully." "Success" } else { Write-SACMsg " [!] Native uninstaller finished with exit code $($proc.ExitCode)." "Warning" } } catch { Write-SACMsg " [!] Failed to run native uninstaller: $($_.Exception.Message)" "Warning" } } else { Write-SACMsg "Native ODIS uninstaller (RemoveODIS.exe) not found. Skipping." "Info" } # 3. Stop and delete AdODISService $service = Get-Service -Name "AdODISService" -ErrorAction SilentlyContinue if ($service) { Write-SACMsg "Stopping and deleting AdODISService..." "Info" Stop-Service -Name "AdODISService" -Force -ErrorAction SilentlyContinue Start-Process sc.exe -ArgumentList "delete AdODISService" -Wait -NoNewWindow | Out-Null } # 4. Clean up / Rename old ODIS paths $PathsToRename = @( Join-Path $env:ProgramFiles "Autodesk\AdODIS", Join-Path $env:ProgramData "Autodesk\ODIS" ) # Gather user profiles AppData Local paths $UserProfilesBase = "C:\Users" if (Test-Path $UserProfilesBase) { Get-ChildItem -LiteralPath $UserProfilesBase -Directory -ErrorAction SilentlyContinue | ForEach-Object { $profileName = $_.Name if ($profileName -notmatch '^(Public|Default|Default User|All Users)$') { $PathsToRename += Join-Path $_.FullName "AppData\Local\Autodesk\ODIS" $PathsToRename += Join-Path $_.FullName "AppData\Local\Autodesk\AdODIS" } } } # Pre-delete the run lock file if present $LockFile = Join-Path $env:ProgramData "Autodesk\ODIS\AdODISInstaller.run.lock" if (Test-Path $LockFile) { Write-SACMsg "Removing ODIS installation lock file: $LockFile" "Info" Remove-Item -LiteralPath $LockFile -Force -ErrorAction SilentlyContinue } foreach ($path in $PathsToRename) { if (Test-Path -LiteralPath $path) { $bakPath = "${path}_bak_$ToDate" Write-SACMsg "Renaming directory: $path -> $(Split-Path $bakPath -Leaf)" "Info" try { Rename-Item -LiteralPath $path -NewName (Split-Path $bakPath -Leaf) -Force -ErrorAction Stop Write-SACMsg " [OK] Renamed successfully." "Success" } catch { Write-SACMsg " [!] Rename failed: $($_.Exception.Message). Attempting force deletion..." "Warning" try { Remove-Item -LiteralPath $path -Recurse -Force -ErrorAction Stop Write-SACMsg " [OK] Force deleted successfully." "Success" } catch { Write-SACMsg " [FAIL] Failed to delete ${path}: $($_.Exception.Message)" "Warning" $script:SACFailures += [PSCustomObject]@{ Component = "ODIS Path ($path)" Reason = "Locked/In-Use" } } } } } # 5. Download the latest AdODIS installer $InstallerUrl = "https://emsfs.autodesk.com/utility/odis/1/installer/latest/AdODIS-installer.exe" $LocalInstallerPath = Join-Path $env:TEMP "AdODIS-installer.exe" # Pre-clean local installer file if it somehow exists if (Test-Path $LocalInstallerPath) { Remove-Item -LiteralPath $LocalInstallerPath -Force -ErrorAction SilentlyContinue } Write-SACMsg "Downloading latest ODIS installer from Autodesk..." "Info" Write-SACMsg " URL: $InstallerUrl" "Info" $downloadSuccess = $false try { $ProgressPreference = 'SilentlyContinue' [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Invoke-WebRequest -Uri $InstallerUrl -OutFile $LocalInstallerPath -UseBasicParsing -ErrorAction Stop $downloadSuccess = $true Write-SACMsg " [OK] Download completed successfully." "Success" } catch { Write-SACMsg " [!] Invoke-WebRequest failed: $($_.Exception.Message). Trying WebClient fallback..." "Warning" try { $webClient = New-Object System.Net.WebClient $webClient.DownloadFile($InstallerUrl, $LocalInstallerPath) $downloadSuccess = $true Write-SACMsg " [OK] WebClient download completed successfully." "Success" } catch { Write-SACMsg " [FAIL] Download fallback failed: $($_.Exception.Message)" "Error" $script:SACFailures += [PSCustomObject]@{ Component = "ODIS Download" Reason = $_.Exception.Message } } } # 6. Perform a fresh, silent reinstall of ODIS if ($downloadSuccess -and (Test-Path $LocalInstallerPath)) { Write-SACMsg "Running fresh ODIS installation silently..." "Info" try { $proc = Start-Process -FilePath $LocalInstallerPath -ArgumentList "--mode unattended" -Wait -PassThru -NoNewWindow -ErrorAction Stop if ($proc.ExitCode -eq 0) { Write-SACMsg " [OK] Reinstallation completed successfully." "Success" } else { Write-SACMsg " [FAIL] Reinstallation failed with exit code $($proc.ExitCode)." "Error" $script:SACFailures += [PSCustomObject]@{ Component = "ODIS Installation Execution" Reason = "Exit code $($proc.ExitCode)" } } } catch { Write-SACMsg " [FAIL] Failed to execute ODIS installer: $($_.Exception.Message)" "Error" $script:SACFailures += [PSCustomObject]@{ Component = "ODIS Installation Execution" Reason = $_.Exception.Message } } # Clean up local installer Remove-Item -LiteralPath $LocalInstallerPath -Force -ErrorAction SilentlyContinue } else { Write-SACMsg "Skipping reinstallation step due to download failure." "Warning" } # 7. Verification check $InstalledExe = Join-Path $env:ProgramFiles "Autodesk\AdODIS\V1\AdODIS.exe" if (Test-Path $InstalledExe) { Write-SACMsg "Verification: ODIS successfully installed at $InstalledExe" "Success" } else { Write-SACMsg "Verification: ODIS executable not found at $InstalledExe!" "Error" if ($script:SACFailures.Count -eq 0) { $script:SACFailures += [PSCustomObject]@{ Component = "ODIS Verification" Reason = "AdODIS.exe missing post-install" } } } # --- Terminate & Output --- $ElapsedTime = "$($StopWatch.Elapsed.Minutes)m $($StopWatch.Elapsed.Seconds)s" $AttentionFile = Join-Path $LogDir "AttentionItems.txt" if ($script:SACFailures.Count -gt 0) { $content = @( "ODIS INSTALLER REPAIR - ITEMS REQUIRING ATTENTION", "Timestamp: $(Get-Date)", "Log Directory: $LogDir", "----------------------------------------------------------", "" ) foreach ($fail in $script:SACFailures) { $content += "[!] $($fail.Component)" $content += " Reason: $($fail.Reason)" $content += "" } $content | Out-File -FilePath $AttentionFile -Encoding utf8 -Force } $script:SACLastRunStatus = [PSCustomObject]@{ Operation = 'ODIS Repair' Criticals = $script:SACFailures.Count Warnings = 0 Elapsed = $ElapsedTime LogDir = $LogDir AttentionItems = if ($script:SACFailures.Count -gt 0) { $AttentionFile } else { $null } } Stop-Transcript | Out-Null if (-not $Silent) { Write-Host "`n==========================================================" -ForegroundColor Cyan if ($script:SACFailures.Count -eq 0) { Write-Host " ODIS INSTALLER REPAIR COMPLETED SUCCESSFULLY" -ForegroundColor Green } else { Write-Host " ODIS INSTALLER REPAIR COMPLETED WITH ERRORS" -ForegroundColor Red } Write-Host "==========================================================" -ForegroundColor Cyan Write-Host "Log directory: $LogDir" -ForegroundColor Gray Write-Host "Time elapsed: $ElapsedTime`n" -ForegroundColor Gray } return $script:SACLastRunStatus } |