# cf-info v1.3 — Compact summary of 1C configuration root # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)][Alias('Path')][string]$ConfigPath, [ValidateSet("overview","brief","full")] [string]$Mode = "overview", [Alias('Name')] [ValidateSet("home-page")] [string]$Section, [int]$Limit = 150, [int]$Offset = 0, [string]$OutFile ) $ErrorActionPreference = 'Stop' [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 # --- Output helper (always collect, paginate at the end) --- $script:lines = @() function Out([string]$text) { $script:lines += $text } # --- Resolve path --- if (-not [System.IO.Path]::IsPathRooted($ConfigPath)) { $ConfigPath = Join-Path (Get-Location).Path $ConfigPath } # Directory -> find Configuration.xml if (Test-Path $ConfigPath -PathType Container) { $candidate = Join-Path $ConfigPath "Configuration.xml" if (Test-Path $candidate) { $ConfigPath = $candidate } else { Write-Host "[ERROR] No Configuration.xml found in directory: $ConfigPath" exit 1 } } if (-not (Test-Path $ConfigPath)) { Write-Host "[ERROR] File not found: $ConfigPath" exit 1 } # --- Load XML --- [xml]$xmlDoc = Get-Content -Path $ConfigPath -Encoding UTF8 $ns = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable) $ns.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses") $ns.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core") $ns.AddNamespace("xr", "http://v8.1c.ru/8.3/xcf/readable") $ns.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance") $ns.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema") $ns.AddNamespace("app", "http://v8.1c.ru/8.2/managed-application/core") $mdRoot = $xmlDoc.SelectSingleNode("/md:MetaDataObject", $ns) if (-not $mdRoot) { Write-Host "[ERROR] Not a valid 1C metadata XML file (no MetaDataObject root)" exit 1 } $cfgNode = $mdRoot.SelectSingleNode("md:Configuration", $ns) if (-not $cfgNode) { Write-Host "[ERROR] No element found" exit 1 } $version = $mdRoot.GetAttribute("version") $propsNode = $cfgNode.SelectSingleNode("md:Properties", $ns) $childObjNode = $cfgNode.SelectSingleNode("md:ChildObjects", $ns) # --- Helpers --- function Get-MLText($node) { if (-not $node) { return "" } $item = $node.SelectSingleNode("v8:item/v8:content", $ns) if ($item -and $item.InnerText) { return $item.InnerText } return "" } function Get-PropText([string]$propName) { $n = $propsNode.SelectSingleNode("md:$propName", $ns) if ($n -and $n.InnerText) { return $n.InnerText } return "" } function Get-PropML([string]$propName) { $n = $propsNode.SelectSingleNode("md:$propName", $ns) return (Get-MLText $n) } # --- Type name maps (canonical order, 44 types) --- $typeOrder = @( "Language","Subsystem","StyleItem","Style", "CommonPicture","SessionParameter","Role","CommonTemplate", "FilterCriterion","CommonModule","CommonAttribute","ExchangePlan", "XDTOPackage","WebService","HTTPService","WSReference", "EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption", "FunctionalOptionsParameter","DefinedType","CommonCommand","CommandGroup", "Constant","CommonForm","Catalog","Document", "DocumentNumerator","Sequence","DocumentJournal","Enum", "Report","DataProcessor","InformationRegister","AccumulationRegister", "ChartOfCharacteristicTypes","ChartOfAccounts","AccountingRegister", "ChartOfCalculationTypes","CalculationRegister", "BusinessProcess","Task","IntegrationService" ) $typeRuNames = @{ "Language"="Языки"; "Subsystem"="Подсистемы"; "StyleItem"="Элементы стиля"; "Style"="Стили" "CommonPicture"="Общие картинки"; "SessionParameter"="Параметры сеанса"; "Role"="Роли" "CommonTemplate"="Общие макеты"; "FilterCriterion"="Критерии отбора"; "CommonModule"="Общие модули" "CommonAttribute"="Общие реквизиты"; "ExchangePlan"="Планы обмена"; "XDTOPackage"="XDTO-пакеты" "WebService"="Веб-сервисы"; "HTTPService"="HTTP-сервисы"; "WSReference"="WS-ссылки" "EventSubscription"="Подписки на события"; "ScheduledJob"="Регламентные задания" "SettingsStorage"="Хранилища настроек"; "FunctionalOption"="Функциональные опции" "FunctionalOptionsParameter"="Параметры ФО"; "DefinedType"="Определяемые типы" "CommonCommand"="Общие команды"; "CommandGroup"="Группы команд"; "Constant"="Константы" "CommonForm"="Общие формы"; "Catalog"="Справочники"; "Document"="Документы" "DocumentNumerator"="Нумераторы"; "Sequence"="Последовательности"; "DocumentJournal"="Журналы документов" "Enum"="Перечисления"; "Report"="Отчёты"; "DataProcessor"="Обработки" "InformationRegister"="Регистры сведений"; "AccumulationRegister"="Регистры накопления" "ChartOfCharacteristicTypes"="ПВХ"; "ChartOfAccounts"="Планы счетов" "AccountingRegister"="Регистры бухгалтерии"; "ChartOfCalculationTypes"="ПВР" "CalculationRegister"="Регистры расчёта"; "BusinessProcess"="Бизнес-процессы" "Task"="Задачи"; "IntegrationService"="Сервисы интеграции" } # --- Read panel layout (Ext/ClientApplicationInterface.xml) --- $script:panelNames = @{ "cbab57f2-a0f3-4f0a-89ea-4cb19570ab75" = "Открытых" "b553047f-c9aa-4157-978d-448ecad24248" = "Разделов" "13322b22-3960-4d68-93a6-fe2dd7f28ca3" = "Избранного" "c933ac92-92cd-459d-81cc-e0c8a83ced99" = "История" "b2735bd3-d822-4430-ba59-c9e869693b24" = "Функций" } function Get-PanelsLayout { $configDir = [System.IO.Path]::GetDirectoryName($ConfigPath) $caiPath = Join-Path (Join-Path $configDir "Ext") "ClientApplicationInterface.xml" if (-not (Test-Path $caiPath)) { return $null } try { [xml]$caiDoc = Get-Content -Path $caiPath -Encoding UTF8 } catch { return $null } if (-not $caiDoc.DocumentElement) { return $null } $caiNs = New-Object System.Xml.XmlNamespaceManager($caiDoc.NameTable) $caiNs.AddNamespace("ca", "http://v8.1c.ru/8.2/managed-application/core") $layout = [ordered]@{ top=@(); left=@(); right=@(); bottom=@(); declared=@() } foreach ($side in @("top","left","right","bottom")) { foreach ($sideEl in $caiDoc.DocumentElement.SelectNodes("ca:$side", $caiNs)) { $slot = @() foreach ($u in $sideEl.SelectNodes(".//ca:panel/ca:uuid", $caiNs)) { $key = $u.InnerText.Trim() $nm = if ($script:panelNames.Contains($key)) { $script:panelNames[$key] } else { "?$key" } $slot += $nm } if ($slot.Count -gt 0) { $layout[$side] += ,$slot } } } foreach ($pd in $caiDoc.DocumentElement.SelectNodes("ca:panelDef", $caiNs)) { $key = $pd.GetAttribute("id") $nm = if ($script:panelNames.Contains($key)) { $script:panelNames[$key] } else { "?$key" } $layout.declared += $nm } return $layout } function Format-LayoutSlots($slots) { # slots is array of arrays (each inner array = one side-tag's panels, may be 1+) # Single inner array, single panel -> just name # Single inner array, multiple panels -> "Стек(a, b)" # Multiple inner arrays -> separate entries joined by " | " if (-not $slots -or $slots.Count -eq 0) { return "" } $parts = @() foreach ($slot in $slots) { if ($slot.Count -eq 1) { $parts += $slot[0] } else { $parts += ("Стек(" + ($slot -join ", ") + ")") } } return ($parts -join " | ") } $script:panelLayout = Get-PanelsLayout # --- Read home page layout (Ext/HomePageWorkArea.xml) --- function Get-HomePageLayout { $configDir = [System.IO.Path]::GetDirectoryName($ConfigPath) $hpPath = Join-Path (Join-Path $configDir "Ext") "HomePageWorkArea.xml" if (-not (Test-Path $hpPath)) { return $null } try { [xml]$hpDoc = Get-Content -Path $hpPath -Encoding UTF8 } catch { return $null } if (-not $hpDoc.DocumentElement) { return $null } $hpNs = New-Object System.Xml.XmlNamespaceManager($hpDoc.NameTable) $hpNs.AddNamespace("hp", "http://v8.1c.ru/8.3/xcf/extrnprops") $hpNs.AddNamespace("xr", "http://v8.1c.ru/8.3/xcf/readable") $result = [ordered]@{ template = ""; left = @(); right = @() } $tmplNode = $hpDoc.DocumentElement.SelectSingleNode("hp:WorkingAreaTemplate", $hpNs) if ($tmplNode) { $result.template = $tmplNode.InnerText.Trim() } foreach ($colName in @("LeftColumn","RightColumn")) { $colNode = $hpDoc.DocumentElement.SelectSingleNode("hp:$colName", $hpNs) if (-not $colNode) { continue } $items = @() foreach ($item in $colNode.SelectNodes("hp:Item", $hpNs)) { $f = $item.SelectSingleNode("hp:Form", $hpNs) $h = $item.SelectSingleNode("hp:Height", $hpNs) $visNode = $item.SelectSingleNode("hp:Visibility", $hpNs) $common = $true $roles = @() if ($visNode) { $cn = $visNode.SelectSingleNode("xr:Common", $hpNs) if ($cn) { $common = ($cn.InnerText.Trim() -eq "true") } foreach ($v in $visNode.SelectNodes("xr:Value", $hpNs)) { $roles += @{ name = $v.GetAttribute("name"); value = ($v.InnerText.Trim() -eq "true") } } } $items += [ordered]@{ form = if ($f) { $f.InnerText.Trim() } else { "" } height = if ($h) { [int]$h.InnerText.Trim() } else { 10 } common = $common roles = $roles } } if ($colName -eq "LeftColumn") { $result.left = $items } else { $result.right = $items } } return $result } $script:homePage = Get-HomePageLayout # --- Support state (Ext/ParentConfigurations.bin) --- # Decodes the 1C support-state file. See docs/1c-support-state-spec.md. # Returns $null on absent/error; else hashtable: State='absent'|'removed'|'parsed', # G (0=editing on, 1=off), K (vendor configs), Vendors @(@{Vendor;Name;Version}), # Counts @(locked, editable, removed) by f1 — record tally (K>1 counts each # vendor block separately); only computed when G=0. function Read-SupportState([string]$binPath) { try { if (-not (Test-Path $binPath)) { return @{ State = 'absent' } } $bytes = [System.IO.File]::ReadAllBytes($binPath) if ($bytes.Length -le 32) { return @{ State = 'removed' } } $startIdx = 0 if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { $startIdx = 3 } $text = [System.Text.Encoding]::UTF8.GetString($bytes, $startIdx, $bytes.Length - $startIdx) $h = [regex]::Match($text, '^\{6,(\d+),(\d+),') if (-not $h.Success) { return $null } $G = [int]$h.Groups[1].Value $K = [int]$h.Groups[2].Value if ($K -eq 0) { return @{ State = 'removed' } } # Vendor descriptors: ...,"ver","vendor","name",count, $vendors = @() $vRe = [regex]'"((?:[^"]|"")*)","((?:[^"]|"")*)","((?:[^"]|"")*)",\d+,' foreach ($m in $vRe.Matches($text)) { $vendors += @{ Version = ($m.Groups[1].Value -replace '""','"') Vendor = ($m.Groups[2].Value -replace '""','"') Name = ($m.Groups[3].Value -replace '""','"') } } # Per-object counts only matter when editing is enabled (G=0); when G=1 the # whole config is read-only and stored f1 values are the inactive default. $counts = $null if ($G -eq 0) { $counts = @(0, 0, 0) # Object records: f1,0,uuidLocal[,uuidVendor] — flags precede the uuid. $rRe = [regex]'([0-2]),0,[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' foreach ($m in $rRe.Matches($text)) { $counts[[int]$m.Groups[1].Value]++ } } return @{ State = 'parsed'; G = $G; K = $K; Vendors = $vendors; Counts = $counts } } catch { return $null } } function Get-SupportLines { $configDir = [System.IO.Path]::GetDirectoryName($ConfigPath) $binPath = Join-Path (Join-Path $configDir "Ext") "ParentConfigurations.bin" $st = Read-SupportState $binPath $out = @() if (-not $st -or $st.State -eq 'absent') { if ($cfgExtPurpose) { $out += "Поддержка: расширение (CFE), правки свободны" } else { $out += "Поддержка: не на поддержке (своя конфигурация)" } return $out } if ($st.State -eq 'removed') { $out += "Поддержка: снята с поддержки полностью" return $out } $out += "Поддержка: на поддержке" if ($st.G -eq 0) { $out += " Возможность изменения: включена" $out += " Объектов: на замке $($st.Counts[0]) / редактируется $($st.Counts[1]) / снято $($st.Counts[2])" } else { $out += " Возможность изменения: выключена — вся конфигурация read-only (правки заблокированы)" } $out += " Конфигураций поставщика: $($st.K)" if ($st.K -gt 1) { foreach ($v in $st.Vendors) { $out += " Поставщик: $($v.Vendor) — $($v.Name) $($v.Version)" } } return $out } function Format-HomePageItem($it, [bool]$detailed) { $badges = @() $badges += "h=$($it.height)" if (-not $it.common) { $badges += "скрыта" } if ($it.roles.Count -gt 0) { if ($detailed) { $badges += "роли: $($it.roles.Count)" } else { $badges += "+$($it.roles.Count) ролей" } } $tail = if ($badges.Count -gt 0) { " (" + ($badges -join ", ") + ")" } else { "" } return " $($it.form)$tail" } # --- Count objects in ChildObjects --- $objectCounts = [ordered]@{} $totalObjects = 0 if ($childObjNode) { foreach ($child in $childObjNode.ChildNodes) { if ($child.NodeType -ne 'Element') { continue } $typeName = $child.LocalName if (-not $objectCounts.Contains($typeName)) { $objectCounts[$typeName] = 0 } $objectCounts[$typeName] = $objectCounts[$typeName] + 1 $totalObjects++ } } # --- Read key properties --- $cfgName = Get-PropText "Name" $cfgSynonym = Get-PropML "Synonym" $cfgVersion = Get-PropText "Version" $cfgVendor = Get-PropText "Vendor" $cfgCompat = Get-PropText "CompatibilityMode" $cfgExtCompat = Get-PropText "ConfigurationExtensionCompatibilityMode" $cfgExtPurpose = Get-PropText "ConfigurationExtensionPurpose" $cfgDefaultRun = Get-PropText "DefaultRunMode" $cfgScript = Get-PropText "ScriptVariant" $cfgDefaultLang = Get-PropText "DefaultLanguage" $cfgDataLock = Get-PropText "DataLockControlMode" $dash = [char]0x2014 $cfgModality = Get-PropText "ModalityUseMode" $cfgIntfCompat = Get-PropText "InterfaceCompatibilityMode" $cfgAutoNum = Get-PropText "ObjectAutonumerationMode" $cfgSyncCalls = Get-PropText "SynchronousPlatformExtensionAndAddInCallUseMode" $cfgDbSpaces = Get-PropText "DatabaseTablespacesUseMode" $cfgWindowMode = Get-PropText "MainClientApplicationWindowMode" # --- BRIEF mode --- if ($Mode -eq "brief" -and -not $Section) { $synPart = if ($cfgSynonym) { " $dash `"$cfgSynonym`"" } else { "" } $verPart = if ($cfgVersion) { " v$cfgVersion" } else { "" } $compatPart = if ($cfgCompat) { " | $cfgCompat" } else { "" } Out "Конфигурация: ${cfgName}${synPart}${verPart} | $totalObjects объектов${compatPart}" } # --- OVERVIEW mode --- if ($Mode -eq "overview" -and -not $Section) { $synPart = if ($cfgSynonym) { " $dash `"$cfgSynonym`"" } else { "" } $verPart = if ($cfgVersion) { " v$cfgVersion" } else { "" } Out "=== Конфигурация: ${cfgName}${synPart}${verPart} ===" Out "" # Key properties Out "Формат: $version" if ($cfgVendor) { Out "Поставщик: $cfgVendor" } if ($cfgVersion) { Out "Версия: $cfgVersion" } foreach ($l in (Get-SupportLines)) { Out $l } Out "Совместимость: $cfgCompat" Out "Режим запуска: $cfgDefaultRun" Out "Язык скриптов: $cfgScript" Out "Язык: $cfgDefaultLang" Out "Блокировки: $cfgDataLock" Out "Модальность: $cfgModality" Out "Интерфейс: $cfgIntfCompat" Out "" # Panel layout (if file exists) if ($script:panelLayout) { $hasPlaced = $false foreach ($s in @("top","left","right","bottom")) { if ($script:panelLayout[$s].Count -gt 0) { $hasPlaced = $true; break } } if ($hasPlaced) { Out "--- Раскладка панелей ---" foreach ($s in @("top","left","right","bottom")) { if ($script:panelLayout[$s].Count -gt 0) { Out " $($s.PadRight(7)) $(Format-LayoutSlots $script:panelLayout[$s])" } } Out "" } } # Home page layout (brief summary) if ($script:homePage) { $ln = $script:homePage.left.Count $rn = $script:homePage.right.Count Out "--- Начальная страница ---" Out " Шаблон: $($script:homePage.template)" Out " LeftColumn: $ln, RightColumn: $rn (детали: -Section home-page)" Out "" } # Object counts table Out "--- Состав ($totalObjects объектов) ---" Out "" $maxTypeLen = 0 foreach ($typeName in $typeOrder) { if ($objectCounts.Contains($typeName)) { $ruName = $typeRuNames[$typeName] if ($ruName.Length -gt $maxTypeLen) { $maxTypeLen = $ruName.Length } } } if ($maxTypeLen -lt 10) { $maxTypeLen = 10 } foreach ($typeName in $typeOrder) { if ($objectCounts.Contains($typeName)) { $count = $objectCounts[$typeName] $ruName = $typeRuNames[$typeName] $padded = $ruName.PadRight($maxTypeLen) Out " $padded $count" } } } # --- Drill-down: -Section home-page --- if ($Section -eq "home-page") { if (-not $script:homePage) { Out "Файл Ext/HomePageWorkArea.xml не найден" } else { Out "=== Начальная страница: $cfgName ===" Out "" Out "Шаблон: $($script:homePage.template)" Out "" foreach ($side in @(@("LeftColumn","left"), @("RightColumn","right"))) { $items = $script:homePage[$side[1]] $lbl = $side[0] if ($items.Count -eq 0) { Out "${lbl}: —"; Out ""; continue } Out "${lbl} ($($items.Count)):" foreach ($it in $items) { Out (Format-HomePageItem $it $true) foreach ($r in $it.roles) { $rval = if ($r.value) { "true" } else { "false" } Out " $($r.name): $rval" } } Out "" } } } # --- FULL mode --- if ($Mode -eq "full" -and -not $Section) { $synPart = if ($cfgSynonym) { " $dash `"$cfgSynonym`"" } else { "" } $verPart = if ($cfgVersion) { " v$cfgVersion" } else { "" } Out "=== Конфигурация: ${cfgName}${synPart}${verPart} ===" Out "" # --- Section: Identification --- Out "--- Идентификация ---" Out "UUID: $($cfgNode.GetAttribute('uuid'))" Out "Имя: $cfgName" if ($cfgSynonym) { Out "Синоним: $cfgSynonym" } $cfgComment = Get-PropText "Comment" if ($cfgComment) { Out "Комментарий: $cfgComment" } $cfgPrefix = Get-PropText "NamePrefix" if ($cfgPrefix) { Out "Префикс: $cfgPrefix" } if ($cfgVendor) { Out "Поставщик: $cfgVendor" } if ($cfgVersion) { Out "Версия: $cfgVersion" } foreach ($l in (Get-SupportLines)) { Out $l } $cfgUpdateAddr = Get-PropText "UpdateCatalogAddress" if ($cfgUpdateAddr) { Out "Каталог обн.: $cfgUpdateAddr" } Out "" # --- Section: Modes --- Out "--- Режимы работы ---" Out "Формат: $version" Out "Совместимость: $cfgCompat" Out "Совм. расширений: $cfgExtCompat" Out "Режим запуска: $cfgDefaultRun" Out "Язык скриптов: $cfgScript" Out "Блокировки: $cfgDataLock" Out "Автонумерация: $cfgAutoNum" Out "Модальность: $cfgModality" Out "Синхр. вызовы: $cfgSyncCalls" Out "Интерфейс: $cfgIntfCompat" Out "Табл. пространства: $cfgDbSpaces" Out "Режим окна: $cfgWindowMode" Out "" # --- Section: Language, roles, purposes --- Out "--- Назначение ---" Out "Язык по умолч.: $cfgDefaultLang" # UsePurposes $purposeNode = $propsNode.SelectSingleNode("md:UsePurposes", $ns) if ($purposeNode) { $purposes = @() foreach ($val in $purposeNode.SelectNodes("v8:Value", $ns)) { $purposes += $val.InnerText } if ($purposes.Count -gt 0) { Out "Назначения: $($purposes -join ', ')" } } # DefaultRoles $rolesNode = $propsNode.SelectSingleNode("md:DefaultRoles", $ns) if ($rolesNode) { $roles = @() foreach ($item in $rolesNode.SelectNodes("xr:Item", $ns)) { $roles += $item.InnerText } if ($roles.Count -gt 0) { Out "Роли по умолч.: $($roles.Count)" foreach ($r in $roles) { Out " - $r" } } } # Booleans $useMF = Get-PropText "UseManagedFormInOrdinaryApplication" $useOF = Get-PropText "UseOrdinaryFormInManagedApplication" Out "Управл.формы в обычн.: $useMF" Out "Обычн.формы в управл.: $useOF" Out "" # --- Section: Panel layout --- if ($script:panelLayout) { Out "--- Раскладка панелей ---" foreach ($s in @("top","left","right","bottom")) { $slots = $script:panelLayout[$s] if ($slots.Count -gt 0) { Out " $($s.PadRight(7)) $(Format-LayoutSlots $slots)" } else { Out " $($s.PadRight(7)) —" } } if ($script:panelLayout.declared.Count -gt 0) { Out " объявлено: $($script:panelLayout.declared -join ', ')" } Out "" } # --- Section: Home page (brief summary) --- if ($script:homePage) { $ln = $script:homePage.left.Count $rn = $script:homePage.right.Count Out "--- Начальная страница ---" Out " Шаблон: $($script:homePage.template)" Out " LeftColumn: $ln, RightColumn: $rn (детали: -Section home-page)" Out "" } # --- Section: Storages & default forms --- Out "--- Хранилища и формы по умолчанию ---" $storageProps = @("CommonSettingsStorage","ReportsUserSettingsStorage","ReportsVariantsStorage","FormDataSettingsStorage","DynamicListsUserSettingsStorage","URLExternalDataStorage") foreach ($sp in $storageProps) { $val = Get-PropText $sp if ($val) { Out " ${sp}: $val" } } $formProps = @("DefaultReportForm","DefaultReportVariantForm","DefaultReportSettingsForm","DefaultReportAppearanceTemplate","DefaultDynamicListSettingsForm","DefaultSearchForm","DefaultDataHistoryChangeHistoryForm","DefaultDataHistoryVersionDataForm","DefaultDataHistoryVersionDifferencesForm","DefaultCollaborationSystemUsersChoiceForm","DefaultConstantsForm","DefaultInterface","DefaultStyle") foreach ($fp in $formProps) { $val = Get-PropText $fp if ($val) { Out " ${fp}: $val" } } Out "" # --- Section: Info --- $cfgBrief = Get-PropML "BriefInformation" $cfgDetail = Get-PropML "DetailedInformation" $cfgCopyright = Get-PropML "Copyright" $cfgVendorAddr = Get-PropML "VendorInformationAddress" $cfgInfoAddr = Get-PropML "ConfigurationInformationAddress" if ($cfgBrief -or $cfgDetail -or $cfgCopyright -or $cfgVendorAddr -or $cfgInfoAddr) { Out "--- Информация ---" if ($cfgBrief) { Out "Краткая: $cfgBrief" } if ($cfgDetail) { Out "Подробная: $cfgDetail" } if ($cfgCopyright) { Out "Copyright: $cfgCopyright" } if ($cfgVendorAddr) { Out "Сайт поставщика: $cfgVendorAddr" } if ($cfgInfoAddr) { Out "Адрес информ.: $cfgInfoAddr" } Out "" } # --- Section: Mobile functionalities --- $mobileFunc = $propsNode.SelectSingleNode("md:UsedMobileApplicationFunctionalities", $ns) if ($mobileFunc) { $enabledFuncs = @() $disabledFuncs = @() foreach ($func in $mobileFunc.SelectNodes("app:functionality", $ns)) { $fName = $func.SelectSingleNode("app:functionality", $ns) $fUse = $func.SelectSingleNode("app:use", $ns) if ($fName -and $fUse) { if ($fUse.InnerText -eq "true") { $enabledFuncs += $fName.InnerText } else { $disabledFuncs += $fName.InnerText } } } $totalFunc = $enabledFuncs.Count + $disabledFuncs.Count Out "--- Мобильные функциональности ($totalFunc, включено: $($enabledFuncs.Count)) ---" if ($enabledFuncs.Count -gt 0) { foreach ($f in $enabledFuncs) { Out " [+] $f" } } foreach ($f in $disabledFuncs) { Out " [-] $f" } Out "" } # --- Section: InternalInfo --- $internalInfo = $cfgNode.SelectSingleNode("md:InternalInfo", $ns) if ($internalInfo) { $contained = $internalInfo.SelectNodes("xr:ContainedObject", $ns) Out "--- InternalInfo ($($contained.Count) ContainedObject) ---" foreach ($co in $contained) { $classId = $co.SelectSingleNode("xr:ClassId", $ns).InnerText $objectId = $co.SelectSingleNode("xr:ObjectId", $ns).InnerText Out " $classId -> $objectId" } Out "" } # --- Section: ChildObjects (full list) --- Out "--- Состав ($totalObjects объектов) ---" Out "" foreach ($typeName in $typeOrder) { if (-not $objectCounts.Contains($typeName)) { continue } $count = $objectCounts[$typeName] $ruName = $typeRuNames[$typeName] Out " $ruName ($typeName): $count" # Collect names for this type $names = @() foreach ($child in $childObjNode.ChildNodes) { if ($child.NodeType -eq 'Element' -and $child.LocalName -eq $typeName) { $names += $child.InnerText } } foreach ($n in $names) { Out " $n" } } } # --- Pagination and output --- $total = $script:lines.Count if ($Offset -gt 0 -or $Limit -lt $total) { $start = [Math]::Min($Offset, $total) $end = [Math]::Min($start + $Limit, $total) $page = $script:lines[$start..($end - 1)] $result = ($page -join "`n") if ($end -lt $total) { $result += "`n`n... ($end of $total lines, use -Offset $end to continue)" } } else { $result = ($script:lines -join "`n") } Write-Host $result if ($OutFile) { $utf8Bom = New-Object System.Text.UTF8Encoding $true [System.IO.File]::WriteAllText($OutFile, $result, $utf8Bom) Write-Host "`nWritten to: $OutFile" }