# =========================================================================== # 成套报价 CAD 插件 - 通用卸载脚本 # 自动检测 AutoCAD 并移除所有安装时写入的配置 # 用法:以管理员身份运行,或在 PowerShell 中执行本脚本 # =========================================================================== # --- 0. 环境与自检 --- $ErrorActionPreference = 'Stop' # $PSScriptRoot 在 -File 模式下可靠返回脚本所在目录(PS 3.0+) $scriptDir = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path -Parent $MyInvocation.MyCommand.Path } $scriptDir = $scriptDir.TrimEnd('\') # 统一去除尾部反斜杠,便于比较 # 检测是否管理员(写 HKLM 需要) $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if (-not $isAdmin) { Write-Host "[提示] 当前未以管理员身份运行,HKLM 注册表删除将自动提权。" -ForegroundColor Yellow Write-Host " acaddoc.lsp 和 TRUSTEDPATHS 无需管理员权限。" -ForegroundColor Yellow Write-Host "" } Write-Host "======================================================" -ForegroundColor Cyan Write-Host " 成套报价 CAD 插件卸载程序" -ForegroundColor Cyan Write-Host " 插件目录: $scriptDir" -ForegroundColor Cyan Write-Host "======================================================" -ForegroundColor Cyan Write-Host "" # --- 1. 检测已安装的 AutoCAD 版本 --- Write-Host "[1/4] 检测 AutoCAD 安装..." -ForegroundColor Green $acadInstalls = @() $regRoots = @( 'HKLM:\SOFTWARE\Autodesk\AutoCAD', 'HKLM:\SOFTWARE\WOW6432Node\Autodesk\AutoCAD' ) foreach ($root in $regRoots) { if (-not (Test-Path $root)) { continue } Get-ChildItem $root -ErrorAction SilentlyContinue | Where-Object { $_.PSChildName -match '^R\d+\.0$' } | ForEach-Object { $verKey = $_.PSPath $verNum = $_.PSChildName Get-ChildItem $verKey -ErrorAction SilentlyContinue | Where-Object { $_.PSChildName -match '^ACAD-\d+:\d+$' } | ForEach-Object { $langKey = $_.PSPath $props = Get-ItemProperty -Path $langKey -ErrorAction SilentlyContinue $loc = $props.AcadLocation $prod = $props.ProductName if ($loc -and (Test-Path $loc)) { $acadInstalls += [PSCustomObject]@{ Version = $verNum LangKey = $_.PSChildName Location = $loc Product = $prod HKLMKey = $langKey } } } } } if ($acadInstalls.Count -eq 0) { Write-Host "[警告] 未检测到已安装的 AutoCAD,无法清理注册表。" -ForegroundColor Yellow Write-Host " 如有手动残留的 acaddoc.lsp,请手动检查。" -ForegroundColor Yellow if (-not $env:CADCJ_SILENT) { Read-Host "按回车退出" } exit 0 } Write-Host "找到 $($acadInstalls.Count) 个 AutoCAD 安装:" -ForegroundColor Green for ($i = 0; $i -lt $acadInstalls.Count; $i++) { $a = $acadInstalls[$i] Write-Host (" [{0}] {1} ({2}) - {3}" -f $i, $a.Product, $a.Version, $a.Location) -ForegroundColor White } Write-Host "" # 若有多个,让用户选择 $target = $acadInstalls[0] if ($acadInstalls.Count -gt 1) { if ($env:CADCJ_SILENT) { Write-Host "[静默模式] 检测到多个 AutoCAD,默认选择第一个: $($target.Product)" -ForegroundColor Yellow } else { do { $sel = Read-Host "请选择要卸载的 AutoCAD 序号 (0-$($acadInstalls.Count - 1)),默认 0" if ([string]::IsNullOrWhiteSpace($sel)) { $sel = '0' } } until ($sel -match '^\d+$' -and [int]$sel -lt $acadInstalls.Count) $target = $acadInstalls[[int]$sel] } } Write-Host "" Write-Host ("目标: {0} ({1})" -f $target.Product, $target.Version) -ForegroundColor Cyan Write-Host "" # --- 2. 删除 HKLM 注册表 CADCJ 节点 --- Write-Host "[2/4] 删除 HKLM 自动加载注册表..." -ForegroundColor Green $hklmPath = $target.HKLMKey -replace '^HKLM:\\', '' $appsPath = "HKLM:\$hklmPath\Apps\CADCJ" if (-not (Test-Path $appsPath)) { Write-Host " HKLM 中无 CADCJ 节点,跳过" -ForegroundColor DarkGray } else { if ($isAdmin) { Remove-Item -Path $appsPath -Recurse -Force -ErrorAction SilentlyContinue if (-not (Test-Path $appsPath)) { Write-Host " 已删除 HKLM 注册表节点" -ForegroundColor Green } else { Write-Host " [警告] 删除失败,请检查权限" -ForegroundColor Yellow } } else { # 提权删除 $tmpPs1 = Join-Path $env:TEMP "cadcj_uninstall_hklm.ps1" $tmpContent = @" `$ErrorActionPreference = 'Stop' `$path = '$appsPath' if (Test-Path `$path) { Remove-Item -Path `$path -Recurse -Force } if (-not (Test-Path `$path)) { Write-Host ' HKLM 注册表节点已删除' } else { Write-Host ' [警告] 删除失败' } "@ $tmpContent | Out-File -FilePath $tmpPs1 -Encoding UTF8 -Force $p = Start-Process -FilePath "powershell.exe" -ArgumentList "-NoProfile","-ExecutionPolicy","Bypass","-File",$tmpPs1 -Verb RunAs -Wait -PassThru if ($p.ExitCode -eq 0) { Write-Host " 已删除 HKLM 注册表节点" -ForegroundColor Green } else { Write-Host " [警告] HKLM 删除失败(用户取消提权?)" -ForegroundColor Yellow } Remove-Item $tmpPs1 -Force -ErrorAction SilentlyContinue } } Write-Host "" # --- 3. 从所有 TRUSTEDPATHS 移除插件目录 --- Write-Host "[3/4] 移除受信任路径(TRUSTEDPATHS)..." -ForegroundColor Green $hkcuRoot = "HKCU:\SOFTWARE\Autodesk\AutoCAD\$($target.Version)\$($target.LangKey)" $targets = @() $topVar = Join-Path $hkcuRoot 'Variables' if (Test-Path $topVar) { $targets += $topVar } $profRoot = Join-Path $hkcuRoot 'Profiles' if (Test-Path $profRoot) { Get-ChildItem $profRoot -ErrorAction SilentlyContinue | ForEach-Object { $pv = Join-Path $_.PSPath 'Variables' if (Test-Path $pv) { $targets += $pv } } } $removedCount = 0 foreach ($t in $targets) { $cur = (Get-ItemProperty -Path $t -Name 'TRUSTEDPATHS' -ErrorAction SilentlyContinue).TRUSTEDPATHS if (-not $cur) { continue } # 分割后去除每段首尾空白,统一比较 $allParts = $cur.Split(';') | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' } $keepParts = $allParts | Where-Object { -not $_.Equals($scriptDir, [StringComparison]::OrdinalIgnoreCase) } $hasOurs = ($allParts | Where-Object { $_.Equals($scriptDir, [StringComparison]::OrdinalIgnoreCase) }).Count -gt 0 $shortName = $t -replace '.*\\Profiles\\','Profile\' -replace '\\Variables','' if (-not $hasOurs) { Write-Host " 未包含: $shortName 跳过" -ForegroundColor DarkGray continue } if ($keepParts.Count -eq 0) { # 全部都是本目录,删除整个值 Remove-ItemProperty -Path $t -Name 'TRUSTEDPATHS' -ErrorAction SilentlyContinue Write-Host " 已清空: $shortName" -ForegroundColor Green } else { $newVal = $keepParts -join ';' Set-ItemProperty -Path $t -Name 'TRUSTEDPATHS' -Value $newVal -Type String -Force Write-Host " 已移除: $shortName" -ForegroundColor Green } $removedCount++ } if ($removedCount -eq 0) { Write-Host " 无需修改(TRUSTEDPATHS 中未包含本目录)" -ForegroundColor DarkGray } Write-Host "" # --- 4. 清理 acaddoc.lsp 中的 CADCJ 加载逻辑 --- Write-Host "[4/4] 清理 acaddoc.lsp 自动加载脚本..." -ForegroundColor Green $acadDirName = Split-Path $target.Location -Leaf $roamingBase = Join-Path $env:APPDATA "Autodesk\$acadDirName\$($target.Version)\chs\Support" $installSupport = Join-Path $target.Location "Support" $candidateDirs = @($roamingBase, $installSupport) | Select-Object -Unique $supDir = $null foreach ($d in $candidateDirs) { if (Test-Path $d) { $supDir = $d; break } } if (-not $supDir) { Write-Host " 未找到 Support 目录,跳过" -ForegroundColor DarkGray } else { $lspPath = Join-Path $supDir 'acaddoc.lsp' if (-not (Test-Path $lspPath)) { Write-Host " acaddoc.lsp 不存在,跳过" -ForegroundColor DarkGray } else { # 读取(尝试 GB2312,失败则用默认编码) $content = $null try { $content = [System.IO.File]::ReadAllText($lspPath, [System.Text.Encoding]::GetEncoding('GB2312')) } catch { $content = Get-Content $lspPath -Raw -ErrorAction SilentlyContinue } if (-not $content) { Write-Host " acaddoc.lsp 为空或无法读取,跳过" -ForegroundColor DarkGray } elseif ($content -notmatch 'CADCJ|cadcj') { Write-Host " acaddoc.lsp 中无 CADCJ 加载逻辑,跳过" -ForegroundColor DarkGray } else { # 判断是否为纯 CADCJ 文件(以 ;;; CADCJ 开头或整个文件就是 CADCJ 块) # 移除 CADCJ 加载块(从 ;;; CADCJ 标记开始到 (princ) 结束) $pattern = '(?s)\s*;;; CADCJ.*?\(princ\)\s*' $newContent = [regex]::Replace($content, $pattern, "`r`n") # 清理多余空行 $newContent = $newContent -replace "(`r`n){3,}", "`r`n`r`n" $newContent = $newContent.TrimEnd() try { if ([string]::IsNullOrWhiteSpace($newContent)) { # 文件清空了,删除文件 Remove-Item $lspPath -Force Write-Host " 已删除: $lspPath(文件仅含 CADCJ 内容)" -ForegroundColor Green } else { # 保留其他内容,只移除 CADCJ 块 [System.IO.File]::WriteAllText($lspPath, $newContent + "`r`n", [System.Text.Encoding]::GetEncoding('GB2312')) Write-Host " 已清理 CADCJ 加载逻辑,保留其他内容: $lspPath" -ForegroundColor Green } } catch { # 写入失败时提权 Write-Host " 写入失败,尝试提权: $($_.Exception.Message)" -ForegroundColor Yellow $tmpLsp = Join-Path $env:TEMP 'cadcj_acaddoc_clean.lsp' if ([string]::IsNullOrWhiteSpace($newContent)) { $delCmd = "Remove-Item '$lspPath' -Force -ErrorAction SilentlyContinue" $p = Start-Process -FilePath "powershell.exe" -ArgumentList "-NoProfile","-Command",$delCmd -Verb RunAs -Wait -PassThru if ($p.ExitCode -eq 0) { Write-Host " 已删除(提权): $lspPath" -ForegroundColor Green } } else { [System.IO.File]::WriteAllText($tmpLsp, $newContent + "`r`n", [System.Text.Encoding]::GetEncoding('GB2312')) $copyCmd = "Copy-Item '$tmpLsp' '$lspPath' -Force" $p = Start-Process -FilePath "powershell.exe" -ArgumentList "-NoProfile","-Command",$copyCmd -Verb RunAs -Wait -PassThru if ($p.ExitCode -eq 0) { Write-Host " 已清理(提权): $lspPath" -ForegroundColor Green } } Remove-Item $tmpLsp -Force -ErrorAction SilentlyContinue } } } } Write-Host "" # --- 完成 --- Write-Host "======================================================" -ForegroundColor Cyan Write-Host " 卸载完成!" -ForegroundColor Green Write-Host "======================================================" -ForegroundColor Cyan Write-Host "" Write-Host "卸载摘要:" -ForegroundColor White Write-Host " AutoCAD: $($target.Product) ($($target.Version))" -ForegroundColor White Write-Host " HKLM 注册: 已删除 CADCJ 节点" -ForegroundColor White Write-Host " TRUSTEDPATHS: 已移除 $scriptDir" -ForegroundColor White Write-Host " acaddoc.lsp: 已清理 CADCJ 加载逻辑" -ForegroundColor White Write-Host "" Write-Host "插件文件本身未删除(cadcj.dll 等),如需彻底删除请手动移除目录:" -ForegroundColor Yellow Write-Host " $scriptDir" -ForegroundColor Yellow Write-Host "" if (-not $env:CADCJ_SILENT) { Read-Host "按回车退出" }