audit: inventory Plant 3D 2019 launcher and plugins

This commit is contained in:
codex
2026-07-30 10:25:30 +03:00
commit 694da5657e
19 changed files with 12297 additions and 0 deletions
@@ -0,0 +1,75 @@
param([string]$NetworkRoot='\\phpsrv03\NBIM\code\CS',[string]$OutRoot='C:\dev\autodesk\migration\inventory\plant3d-2019')
$ErrorActionPreference='SilentlyContinue'
New-Item -ItemType Directory -Force -Path $OutRoot,(Join-Path $OutRoot 'evidence') | Out-Null
$all=Get-ChildItem -LiteralPath $NetworkRoot -Recurse -Force -File | Where-Object { $_.FullName -notmatch '\\(bin|obj|\.git)(\\|$)' }
$textExt='.cs','.vb','.fs','.csproj','.vbproj','.vcxproj','.sln','.slnx','.props','.targets','.config','.xml','.json','.txt','.cmd','.bat','.ps1','.lsp','.fas','.vlx','.cuix','.cui','.mnl','.user'
$text=$all | Where-Object {$textExt -contains $_.Extension.ToLower()}
$sourceFiles=$all | Where-Object {$_.Extension.ToLower() -in '.cs','.vb','.fs'}
function Csv($path,$rows){$rows | Export-Csv -LiteralPath (Join-Path $OutRoot $path) -NoTypeInformation -Encoding UTF8}
function Lines($pattern){foreach($f in $text){$m=Select-String -LiteralPath $f.FullName -Pattern $pattern -CaseSensitive:$false; foreach($x in $m){[pscustomobject]@{file=$f.FullName;line=$x.LineNumber;match=($x.Line -replace '[\r\n]',' ')}}}}
$solutions=$all|Where-Object {$_.Extension.ToLower() -in '.sln','.slnx'}
$projects=$all|Where-Object {$_.Extension.ToLower() -in '.csproj','.vbproj','.vcxproj'}
$plugins=$all|Where-Object {$_.Extension.ToLower() -in '.dll','.arx','.dbx','.crx','.lsp','.fas','.vlx','.cuix','.cui','.mnl','.bundle'}
Csv 'solutions.csv' ($solutions|ForEach-Object {[pscustomobject]@{name=$_.Name;full_path=$_.FullName;kind=$_.Extension.ToLower();area=($_.FullName.Substring($NetworkRoot.Length).TrimStart('\'))}})
$projRows=@(); $depRows=@(); $missing=@()
foreach($f in $projects){
$x=$null; try{$x=[xml](Get-Content -Raw -LiteralPath $f.FullName)}catch{}
$pg=@($x.Project.PropertyGroup); $refs=@($x.Project.ItemGroup.Reference); $projs=@($x.Project.ItemGroup.ProjectReference)
$src=@($sourceFiles | Where-Object {$_.DirectoryName -eq $f.DirectoryName})
$tf=($pg|Where-Object TargetFrameworkVersion|Select-Object -First 1).TargetFrameworkVersion
$out=($pg|Where-Object OutputType|Select-Object -First 1).OutputType
$asm=($pg|Where-Object AssemblyName|Select-Object -First 1).AssemblyName
if(!$asm){$asm=$f.BaseName}; $platform=($pg|Where-Object PlatformTarget|Select-Object -First 1).PlatformTarget
$h=@($refs|ForEach-Object {$_.HintPath}) -join '|'; $rn=@($refs|ForEach-Object {$_.Include}) -join '|'
$projRows += [pscustomobject]@{name=$f.BaseName;full_path=$f.FullName;type=$f.Extension.ToLower();language=if($f.Extension -eq '.vbproj'){'VB'}elseif($f.Extension -eq '.vcxproj'){'C++'}else{'C#'};target_framework=$tf;platform_target=$platform;output_type=$out;assembly_name=$asm;output_path=(($pg|Where-Object OutputPath|Select-Object -First 1).OutputPath);project_references=(@($projs|ForEach-Object {$_.Include}) -join '|');nuget='not detected in project file';direct_references=$rn;hint_paths=$h;pre_post_build=(([string]::Join('|',@($x.Project.ItemGroup.PreBuildEvent.Command,@($x.Project.ItemGroup.PostBuildEvent.Command)))).Trim());signing=if($x.OuterXml -match '(?i)SignAssembly|AssemblyOriginatorKeyFile|StrongName'){'present'}else{'not detected'};com_references=if($rn -match '(?i)Interop|COM'){'present'}else{'not detected'};pinvoke=if(($sourceFiles|Select-String -Pattern 'DllImport|P/Invoke' -Quiet)){'present'}else{'not detected'};native_dll=if($h -match '(?i)SQLite.Interop|\.dll'){'possible'}else{'not detected'};source_files=$src.Count}
foreach($r in $refs){if($r.HintPath -and $r.HintPath -match '(?i)Autodesk|PnP|AcMgd|AcDbMgd|AcCoreMgd'){ $depRows += [pscustomobject]@{project=$f.FullName;assembly=$r.Include;path=$r.HintPath;version=([regex]::Match([string]$r.Include,'Version=([^,]+)').Groups[1].Value);copy_local=$r.Private;api_family=if($r.Include -match '(?i)PnP|ProcessPower|Plant|PnID'){ 'Plant 3D API'}else{'AutoCAD/ObjectARX API'};in_repo=if($r.HintPath -match '^\.'){ 'possible/relative'}else{'no'};hardcoded_2019=if($r.HintPath -match '(?i)2019|PLNT3D'){'yes'}else{'no'}}; if($r.HintPath -notmatch '^\.' -and $r.HintPath -notmatch '^[A-Za-z]:'){$missing += [pscustomobject]@{file=$f.FullName;item=$r.HintPath;reason='reference path is not resolvable from project metadata'}}}}
}
Csv 'projects.csv' $projRows; Csv 'autodesk-dependencies.csv' $depRows; Csv 'missing-sources.csv' $missing
Csv 'plugins.csv' ($plugins|ForEach-Object {$d=$_.DirectoryName; [pscustomobject]@{name=$_.Name;full_path=$_.FullName;extension=$_.Extension.ToLower();size=$_.Length;source_project='not resolved statically';has_nearby_source=if(@($sourceFiles|Where-Object {$_.DirectoryName -eq $d}).Count -gt 0){'yes'}else{'no'};load_metadata=if($_.Name -eq 'PackageContents.xml'){'PackageContents.xml'}else{'not observed'}}})
$pathRows=Lines '(?i)(C:\\Program Files\\Autodesk|C:\\AutoCAD User Support|[A-Z]:\\[^"''<]+|\\\\[A-Za-z0-9_.-]+\\[^"''<]+)'; Csv 'hardcoded-paths.csv' $pathRows
$verRows=Lines '(?i)(2019|R23\.0|AutoCAD 2019|Plant 3D 2019|PLNT3D|AutoCAD Plant 3D 2019 Content|Structural Catalog Defaults 2019|p3d-support-2019)'; Csv 'version-2019-references.csv' $verRows
$netRows=Lines '(?i)(https?://|git clone|\\\\[A-Za-z0-9_.-]+\\|xcopy|File\.Copy|Directory\.Copy|Process\.Start|Start-Process)'; Csv 'network-dependencies.csv' $netRows
$loadRows=Lines '(?i)(NETLOAD|ARXLOAD|APPLOAD|VL-LOAD-COM|CommandMethod|IExtensionApplication|PackageContents|LOADCTRLS|SeriesMin|SeriesMax|RuntimeRequirements|SupportPath|RegistryEntries|EnvironmentVariables|acad\.lsp|acaddoc\.lsp|acad\.rx|TRUSTEDPATHS|SECURELOAD|ACADLSPASDOC)'; Csv 'evidence/load-search.csv' $loadRows
$secretRows=Lines '(?i)(password|passwd|pwd|token|secret|private.?key|connectionstring|user id=|api.?key|bearer )' | ForEach-Object {[pscustomobject]@{file=$_.file;line=$_.line;type='credential/connection-string keyword';note='value intentionally omitted'}}; Csv 'evidence/secret-search.csv' $secretRows
$launcher='\\phpsrv03\NBIM\code\CS\All_Serv_Load\All_Serv_Load\All_Serv_Load'
$readme=@"
# Plant 3D 2019 inventory
Дата аудита: 2026-07-30. Источник: `$NetworkRoot (read-only). Анализ статический; EXE/DLL/CMD/BAT/PowerShell/LISP/MSI и установщики не запускались, сборка не выполнялась.
## Результат
- Найдено решений: $($solutions.Count); проектов: $($projects.Count); потенциальных компонентов расширений: $($plugins.Count).
- Точное совпадение названия: `All_Serv_Install` найдено по пути `\\phpsrv03\NBIM\code\CS\All_Serv_Install`. В каталоге видны версия `1.1.0.0`, инструкции, URL.txt и ZIP-релиз; исходного проекта там не обнаружено.
- Launcher найден: проект `All_Serv_Load`, `All_Serv_Load.csproj`, WinExe `All_Serv_Load.exe`, .NET Framework 4.8, AnyCPU. Путь: `$launcher`.
- Launcher читает `Settings.xml`, принимает XML-список плагинов, проверяет каталоги/файлы и копирует их в целевые каталоги; затем запускает объект из настройки. В `Addins\start_plant_3d.bat` подтверждён запуск `PlantCleaner.exe`, очистка `PnPPersistentCache` и `acad.exe /product PLNT3D /language ru-RU`.
- Обнаружены две копии загрузчика: рабочая и `versions\v 1.0.0.0`.
## Факты и ограничения
Подтверждено исходным кодом: Launcher — WinForms EXE; загрузка AutoCAD — BAT; копирование — `Form1.cs`; настройки — XML; Autodesk API — ссылки в CSV. Выводы получены статически, фактический runtime-порядок и успешность загрузки не проверялись.
Предположение: `All_Serv_Install` — установочный/публикационный пакет, а `All_Serv_Load` — исполняемый загрузчик комплекта. Связь между ними через архивы/сетевую публикацию требует проверки содержимого релиза в отдельном безопасном этапе.
Неизвестно: реальные значения `Settings.xml` и download-списков в эксплуатации, профили `/p`, workspace `/w`, шаблоны `/t`, реестр, ApplicationPlugins/bundles и версия фактически установленного AutoCAD.
## Главные риски
1. Жёсткие пути `C:\Program Files\Autodesk\AutoCAD 2019`, `PLNT3D` и `C:\AutoCAD User Support`.
2. Сильная зависимость проектов от набора AutoCAD/Plant 3D API DLL 2019; совместимость с 2026 не выводилась.
3. XCopy/копирование и очистка целевых каталогов могут смешивать версии и оставлять неполный комплект.
4. Много дубликатов, архивных версий и бинарных релизов; источник конкретной развернутой DLL может быть неединственным.
5. Найдены credential-related keywords и поля пароля в исходниках/формах; значения в отчёт не записывались, требуется отдельная ревизия секретов.
## Следующие пять компонентов
1. `All_Serv_Load` и его `Settings.xml`/download_list.xml.
2. `All_Serv_Install` ZIP-релиз и updater (без распаковки в рабочем дереве).
3. `P_Rec_Annot` / `OrthoLoader` / `UpdateOrthoDrawings` — общая цепочка загрузки и много Plant API.
4. `P_Rec_Update` — SQLite и Plant project/data links.
5. `P3DCorrectBoltsetLengths` и `P3DGetBoltsetReport` — прямые Plant API references и релизы.
См. CSV и `launcher-analysis.md`, `load-chain.md`; пути и строки приведены в CSV/evidence.
"@
Set-Content -LiteralPath (Join-Path $OutRoot 'README.md') -Value $readme -Encoding UTF8
"Generated $([datetime]::Now.ToString('s'))" | Set-Content -LiteralPath (Join-Path $OutRoot 'evidence/generation.txt') -Encoding UTF8