param( [string]$Server = $env:ONEC_SQL_SERVER, [string]$Database = $env:ONEC_SQL_DATABASE, [string]$User = $env:ONEC_SQL_USER, [string]$Password = $env:ONEC_SQL_PASSWORD, [string]$OutputPath = $env:ONEC_SQL_EXPORT_PATH, [int]$CommandTimeoutSeconds = 0 ) Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" if (-not $Server) { throw "Server is required. Use -Server or ONEC_SQL_SERVER." } if (-not $Database) { throw "Database is required. Use -Database or ONEC_SQL_DATABASE." } if (-not $User) { throw "User is required. Use -User or ONEC_SQL_USER." } if (-not $Password) { throw "Password is required. Use -Password or ONEC_SQL_PASSWORD." } if (-not $OutputPath) { throw "OutputPath is required. Use -OutputPath or ONEC_SQL_EXPORT_PATH." } $resolvedOutput = [System.IO.Path]::GetFullPath($OutputPath) $binaryOutput = Join-Path $resolvedOutput "binary" New-Item -ItemType Directory -Force -Path $binaryOutput | Out-Null function Convert-ToSafeName { param([string]$Value) if (-not $Value) { return "empty" } $safe = $Value -replace '[\\/:*?"<>|]', '_' if ($safe.Length -gt 80) { $safe = $safe.Substring(0, 80) } return $safe } $connectionString = "Server=$Server;Database=$Database;User ID=$User;Password=$Password;Encrypt=False;TrustServerCertificate=True;Application Name=Codex 1C SQL Extensions Export;" $connection = [System.Data.SqlClient.SqlConnection]::new($connectionString) $command = $connection.CreateCommand() $command.CommandTimeout = $CommandTimeoutSeconds $command.CommandText = "SELECT * FROM dbo.[_ExtensionsInfo] ORDER BY [_ExtName]" $rows = @() try { $connection.Open() $reader = $command.ExecuteReader() try { $rowIndex = 0 while ($reader.Read()) { $rowIndex++ $row = [ordered]@{ row_index = $rowIndex columns = [ordered]@{} } $extName = "" for ($i = 0; $i -lt $reader.FieldCount; $i++) { if ($reader.GetName($i) -eq "_ExtName" -and -not $reader.IsDBNull($i)) { $extName = [string]$reader.GetValue($i) break } } $safeExtName = Convert-ToSafeName $extName for ($i = 0; $i -lt $reader.FieldCount; $i++) { $columnName = $reader.GetName($i) if ($reader.IsDBNull($i)) { $row.columns[$columnName] = $null continue } $value = $reader.GetValue($i) if ($value -is [byte[]]) { $binaryName = "{0:D3}_{1}_{2}.bin" -f $rowIndex, $safeExtName, (Convert-ToSafeName $columnName) $binaryPath = Join-Path $binaryOutput $binaryName [System.IO.File]::WriteAllBytes($binaryPath, $value) $row.columns[$columnName] = [ordered]@{ type = "binary" bytes = $value.Length path = $binaryPath } continue } $row.columns[$columnName] = $value } $rows += [pscustomobject]$row } } finally { if ($reader -ne $null) { $reader.Dispose() } } } finally { if ($connection -ne $null) { $connection.Dispose() } } $result = [pscustomobject]@{ schema = "onec_sql_extensions_info_export.v1" table = "_ExtensionsInfo" output_path = $resolvedOutput row_count = $rows.Count rows = $rows } $jsonPath = Join-Path $resolvedOutput "extensions-info.json" $result | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $jsonPath -Encoding UTF8 $result | ConvertTo-Json -Depth 5