Mit diesem Skript ist das machbar (zumindest fĂĽr die AL-Dateien aus unserem Add-on, die alle noch eine Objekt-ID enthalten, funktioniert es einwandfrei
Die Dateien werden ausgehehend von dem Ordner, wo das Objektpaket liegt (das kann über ein Fenster ausgewählt werden)…
…in einem Unterordner SPLITBCOBJ erzeugt.
Bei der Dateinamenstruktur fĂĽr AL-Dateien kursieren ja mittlerweile verschiedene Varianten.
Im Skript werden weitgehend die Namensformatierungen des Txt2Al-Tools verwendet (nicht, weil ich die schön finde, sondern weil sie eben so sind, wie sie sind
- Code: Alles auswählen
function Split-ALObjectFile
{
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction']='Stop'
Function Get-FileName($initialDirectory)
{
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.initialDirectory = $initialDirectory
$OpenFileDialog.filter = "AL Object Files (*.al)|*.al"
$OpenFileDialog.ShowDialog() | Out-Null
$OpenFileDialog.filename
}
$inputfile = Get-FileName "C:\temp" # This is the default path in OpenFile window.
if ($inputfile -eq "") {throw 'Please select a file'}
[decimal]$filesize = ((Get-Item $inputfile).length/1MB)
$filesize =[math]::round($filesize,2)
$inputfile = resolve-path $inputfile
$WorkingFolder = Split-Path -Parent $inputfile
if (Test-path "$WorkingFolder\SPLITBCOBJ\")
{Remove-Item -path "$WorkingFolder\SPLITBCOBJ\" -Recurse -Force}
Write-Host "Splitting BC/NAV objects from $inputfile (Size: $filesize MB) to $WorkingFolder\SPLITBCOBJ\, this may take a while..." -ForegroundColor Yellow
$starttime = date
$Sr = new-object System.IO.StreamReader($inputfile,[system.text.encoding]::GetEncoding(65001))
[int]$ObjCnt = 0
[int]$TabCnt = 0
[int]$PagCnt = 0
[int]$RepCnt = 0
[int]$CodCnt = 0
[int]$XmlCnt = 0
[int]$QueCnt = 0
[int]$TabExtCnt = 0
[int]$PagExtCnt = 0
[int]$EnumCnt = 0
[int]$EnumExtCnt = 0
[int]$CtrlAddInCnt = 0
[int]$PagCstmCnt = 0
[int]$KeysCnt = 0
[int]$DotNetCnt = 0
[int]$ProfileCnt = 0
while (-not $Sr.EndOfStream)
{
$Currline = $sr.ReadLine()
if ($Currline.StartsWith('table ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('tableextension ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('page ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('pageextension ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('pagecustomization ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('report ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('query ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('codeunit ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('enum ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('enumextension ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('keys ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('profile ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('xmlport ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('dotnet ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('controladdin ')) {$NewObject = $True}
else {$NewObject = $false}
if ($NewObject)
{
$IsExtension = $false
$dblquotes = [char]34
[String]$ObjectChars = $Currline.Substring(0,5)
[String]$ObjectChar = $Currline.Substring(6,1)
write-host $currline
$IsExtension = ($Currline.indexof(' extends ') -gt 0)
if ($IsExtension)
{
$PosExtends = $Currline.indexof(' extends ')
if ($PosExtends -gt 0)
{
$ObjectExtendedName = $Currline.Substring($PosExtends+9)
$CleanObjectExtendedName = $ObjectExtendedName.TrimStart('"')
$CleanObjectExtendedName = $CleanObjectExtendedName.TrimEnd(' ')
$CleanObjectExtendedName = $CleanObjectExtendedName.TrimEnd('"')
$CleanObjectExtendedName = $CleanObjectExtendedName.Trim('/')
}
else
{$CleanObjectExtendedName = ''}
}
else
{$CleanObjectExtendedName = ''}
#write-host $ObjectChars
#write-host $ObjectChar
$PosFirstBlank = $Currline.indexof(' ')
$Currline2 = $Currline.Substring($PosFirstBlank+1)
$PosSecondBlank = $Currline2.indexof(' ')
if ($PosSecondBlank -ne 0)
{$ObjectName = $Currline2.Substring($PosSecondBlank+1)}
else
{$ObjectName = ''}
if ($ObjectName.Startswith('"'))
{
$CleanObjectName = $ObjectName.TrimStart('"')
$CleanObjectName = $CleanObjectName.TrimEnd(' ')
$CleanObjectName = $CleanObjectName.TrimEnd('"')
$CleanObjectName = $CleanObjectName.Trim('/')
}
else
{$CleanObjectName = $ObjectName.Trim('/')}
write-host $currline2
$ObjectLine = $currline.Split(' ')
$ObjCnt++
Switch ($ObjectChars)
{
'table' {
if (!$IsExtension)
{
$TabCnt++;$ObjectType = 'Table'
}
else
{
$TabExtCnt++;$ObjectType = 'TableExt'
}
}
'page ' {
$PagCnt++;$ObjectType = 'Page'}
'pagee' {$PagExtCnt++; $ObjectType = 'PageExt'}
'pagec' {$PagCstmCnt++;$ObjectType = 'PageCstm'}
'repor' {$RepCnt++;$ObjectType = 'Report'}
'codeu'{$CodCnt++;$ObjectType = 'Codeunit'}
'xmlpo' {$XmlCnt++;$ObjectType = 'XMLport'}
'enum ' {$enumCnt++;$ObjectType = 'Enum'}
'enume' {$enumExtCnt++;$ObjectType = 'EnumExt'}
'keys ' {$KeysCnt++;$ObjectType = 'Keys'}
'profi' {$ProfileCnt++;$ObjectType = 'Profile'}
'query ' {$QueCnt++;$ObjectType = 'Query'}
'dotnet ' {$DotNetCnt++;$ObjectType = 'DotNet'}
'controladdin ' {$CtrlAddinCnt++;$ObjectType = 'ControlAddin'}
}
if (!$IsExtension)
{
If (($ObjectLine[2] -eq '') -and ($CleanObjectName -eq ''))
{$ObjectFileName = $ObjectType + '.al'}
elseif (($ObjectLine[1] -ne '') -and ($CleanObjectName -eq ''))
{$ObjectFileName = $ObjectType + $ObjectLine[1] + '.al'}
elseif (($ObjectLine[1] -ne '') -and ($CleanObjectName -eq ''))
{$ObjectFileName = $ObjectType + $ObjectLine[1] + $CleanObjectName + '.al'}
else
{$ObjectFileName = $ObjectType + ' ' + $ObjectLine[1] + ' - ' + $CleanObjectName + '.al'}
}
else
{
$ObjectFileName = 'Modification - ' + $CleanObjectExtendedName + '(' + $ObjectType + ')' + '.al'
}
#write-host "Object Type: $Objecttype"
#write-host "Object Name: $CleanObjectName"
#write-host 'Object ID: ' $ObjectLine[1]
#write-host "Object Extended Name: $CleanObjectExtendedName"
$ObjectFileName = $ObjectFileName.replace('/','')
write-host "File Name: $ObjectFileName"
$Objectfile = New-Item -path "$WorkingFolder\SPLITBCOBJ\$ObjectFileName" -type file -force
$sw = new-object System.IO.Streamwriter($Objectfile,$false,[system.text.encoding]::GetEncoding(65001))
#IF (Test-Path $ObjectFile) {Remove-Item $ObjectFile}
}
if (-not $Currline.StartsWith('}'))
{$sw.writeline($Currline)}
else
{
$sw.writeline($Currline)
$sw.writeline()
$sw.Flush()
}
}
$endtime = date
$time = $endtime - $starttime
Write-Host "$ObjCnt BC/NAV objects splitted to $WorkingFolder\SPLITBCOBJ\ in $($time.Minutes)m:$($time.Seconds)s:$($time.Milliseconds)ms" -ForegroundColor Yellow
Write-Host "Tables: $TabCnt" -ForegroundColor Yellow
Write-Host "Table Extensions: $TabExtCnt" -ForegroundColor Yellow
Write-Host "Pages: $PagCnt" -ForegroundColor Yellow
Write-Host "Page Extensions: $PagExtCnt" -ForegroundColor Yellow
Write-Host "Page Customizations: $PagCstmCnt" -ForegroundColor Yellow
Write-Host "Reports: $RepCnt" -ForegroundColor Yellow
Write-Host "Codeunits: $CodCnt" -ForegroundColor Yellow
Write-Host "XMLPorts: $XMLCnt" -ForegroundColor Yellow
Write-Host "Queries: $QueCnt" -ForegroundColor Yellow
Write-Host "Enums: $EnumCnt" -ForegroundColor Yellow
Write-Host "Enum Extensions: $EnumExtCnt" -ForegroundColor Yellow
Write-Host "Keys: $KeysCnt" -ForegroundColor Yellow
Write-Host "ControlAddin: $CtrlAddinCnt" -ForegroundColor Yellow
Write-Host "Dotnet: $DotnetCnt" -ForegroundColor Yellow
Write-Host "Profiles: $ProfileCnt" -ForegroundColor Yellow
$sr.Close()
$sr.Dispose()
$sw.close()
$sw.Dispose()
Invoke-item "$WorkingFolder\SPLITBCOBJ\"
}
Split-ALObjectFile
AL-Pakete lassen sich so erzeugen (hier als Beispiel in C:\Temp)
- Code: Alles auswählen
$WorkingFolder = 'C:\Temp'
Get-Content $WorkingFolder\*.al -encoding UTF8 | Out-File $WorkingFolder\allobjects.al -encoding UTF8

