PowerShell: Dokumentations-Trigger pflegen

Bild Tipps & Tricks zu den Dynamics NAV Versionen
Hier bitte keine Fragen stellen, sondern nur bereits vorhandene Tricks veröffentlichen.
Forumsregeln
Impressum • Community-Knigge • Nutzungsbedingungen • Datenschutzrichtlinie
Hier bitte keine Fragen stellen, sondern nur bereits vorhandene Tricks veröffentlichen.

PowerShell: Dokumentations-Trigger pflegen

Beitragvon Kowa » 18. Januar 2018 18:15

Mit diesem Skript kann man ein Objektpaket zerlegen (Bedienung und Arbeitsweise wie im Objektspitter, das hiesige Skript schreibt dabei den Ordner SPLITNAVOBJCPYRT statt SPLITNAVOBJ) und zusätzlich dabei für alle Objekte oben im Documentation-Trigger einen beliebigen Eintrag vornehmen, bspw. für die üblichen Copyrightzeilen. Falls oben und unten benötigt wird siehe nächster Beitrag.
FĂĽr Objekte, die bislang keinen Eintrag im Documentationtrigger hatten, wird dabei einer angelegt, das ist im Skript separat pflegbar.

Die Umarbeitung erfolgt in 2 Schritten.
1. Die Objekte werden gespittet und nicht vorhandene Trigger dabei gleich mit angelegt. FĂĽr Objekte mit bereits vorhandenem Trigger wird die Startzeile fĂĽr jedes Objekt getrennt ermittelt und in eine Hashtabelle geschrieben (deren Inhalt wird ausgegeben, das kann man ggf. abschalten, dazu diese Zeile$FilesWithDocTrigger.GetEnumerator() | Sort-Object Name) auskommentieren
2. Alle in der Hashtabelle aufgefĂĽhrten Objektdateien werden erneut gelesen und geschrieben und erhalten an der ermittelten Startposition des Triggers den gewĂĽnschten Zeileneinschub.
DocuTrigger2.png

DocuTrigger1.png


Versehentlich eingefĂĽgte (und eindeutig erkennbare) Zeilen kann man hiermit wieder entfernen.
FĂĽr das Zusammenstellen zum neuen Objektpaket kann man fĂĽr aktuelle Objekte dieses Skript verwenden. FĂĽr Forms und Dataports funktioniert das Join-Cmdlet von Microsoft leider nicht mehr, dann und auch sonst hilft dieses Tool weiter.

Code: Alles auswählen
function Split-NAVObjectFileWithDocuTrigger
{
    $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 = "NAV Object Files (*.txt)|*.txt"
        $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)
    $TotalLineCnt = $inputfile.count
   
    $inputfile = resolve-path $inputfile
    $WorkingFolder = Split-Path -Parent $inputfile
   

   
    if (Test-path "$WorkingFolder\SPLITNAVOBJCPYRT\")
    {Remove-Item -path "$WorkingFolder\SPLITNAVOBJCPYRT\" -Recurse -Force}

    Write-Host "Splitting NAV objects from $inputfile (Size: $filesize MB) to $WorkingFolder\SPLITNAVOBJCPYRT\, this may take a while..." -ForegroundColor Yellow
    $startime = date
   
   
    $fs= New-Object System.IO.FileStream($inputfile,"OpenOrCreate", "Read", "ReadWrite",8,"None")
    $Sr = new-object System.IO.StreamReader($fs,[system.text.encoding]::GetEncoding(850))

    [int]$ObjCnt = 0
    [int]$TabCnt = 0
    [int]$PagCnt = 0
    [int]$RepCnt = 0
    [int]$CodCnt = 0
    [int]$XmlCnt = 0
    [int]$ForCnt = 0
    [int]$DatCnt = 0
    [int]$QueCnt = 0
    [int]$MenCnt = 0
    [int]$PosCnt = 0

    $LastLine = ''
    $FilesWithDocTrigger = @{'File' = 'FilePos'}
    while (-not $Sr.EndOfStream)
    {
        $Currline = $sr.ReadLine()
        $fsr = $sr.BaseStream
        $posCnt++



        if ($Currline.StartsWith('OBJECT'))
        {
            $HasDocuTrigger  = $false   
            [String]$ObjectChar = $Currline.Substring(7,1)
            $ObjectLine = $currline.Split(' ')
            $ObjCnt++
            [int]$ObjposCnt = 0


            Switch ($ObjectChar)
            {
                'T' {$TabCnt++}
                'P' {$PagCnt++}
                'R' {$RepCnt++}
                'C' {$CodCnt++}
                'X' {$XmlCnt++}
                'F' {$ForCnt++}
                'D' {$DatCnt++}
                'Q' {$QueCnt++}
                'M' {$MenCnt++}
       
            }

            $ObjectFileName = $ObjectLine[1].Substring(0,3).ToUpper() + $ObjectLine[2] + ".TXT"
            $Objectfile = New-Item -path "$WorkingFolder\SPLITNAVOBJCPYRT\$ObjectFileName" -type file -force
            IF (Test-Path $ObjectFile) {Remove-Item $ObjectFile}
           
            $sw = new-object System.IO.Streamwriter($Objectfile,$false,[system.text.encoding]::GetEncoding(850))
        }
        $ObjposCnt++   
        if ($CurrLine -eq '    BEGIN')
        {
            $LastBeginPosInObj = $ObjposCnt
           
        }
        if (($Currline -eq '    END.') -and ($LastLine -eq '    BEGIN'))
        {   
            $sw.writeline('    {')
         
            $sw.writeline("      (c) Global Software Enterprises, all rights reserved" )
            $sw.writeline("      ------------------------------------------------")
            $sw.writeline()
            $sw.writeline('    }')
            $sw.writeline('    END.')
            $LastLine = $CurrLine
        }
         
        #
        elseif (($Currline -eq '    END.') -and ($LastLine -ne '    BEGIN'))
        {
            $sw.writeline($Currline)
            $Lastline = $CurrLine
            $HasDocuTrigger = $true

            [int]$SplitFileAtLine = $LastBeginPosinObj
 
        }
        elseif (-not $Currline.StartsWith('}'))
        {
            # normal line
 
           
            $sw.writeline($Currline)
            $Lastline = $CurrLine
 
        }
        else
        {
            # final line
            $sw.writeline($Currline)
            $Lastline = $CurrLine
            $sw.writeline()
           
            $sw.Flush()
           
            # End of splitted object file
            if ($HasDocuTrigger)
            {
                $FilesWithDocTrigger.Add($Objectfilename,$SplitFileAtLine)
                $ObjposCnt = 0
            }
   
        }

           


    }
           
   
    $endtime = date
    $time = $endtime - $startime
    Write-Host "$ObjCnt NAV objects splitted to $WorkingFolder\SPLITNAVOBJCPYRT\ in $($time.Minutes)m:$($time.Seconds)s:$($time.Milliseconds)ms" -ForegroundColor Yellow
    Write-Host "Tables: $TabCnt" -ForegroundColor Yellow
    Write-Host "Pages: $PagCnt" -ForegroundColor Yellow
    Write-Host "Reports: $RepCnt" -ForegroundColor Yellow
    Write-Host "Codeunits: $CodCnt" -ForegroundColor Yellow
    Write-Host "XMLPorts: $XMLCnt" -ForegroundColor Yellow
    Write-Host "MenuSuites: $MenCnt" -ForegroundColor Yellow
    if ($ForCnt -gt 0)
    {Write-Host "Forms: $ForCnt" -ForegroundColor Yellow}
    if ($DatCnt -gt 0)
    {Write-Host "Dataports: $DatCnt" -ForegroundColor Yellow}   
    $sr.Close()
    $sr.Dispose()
    $sw.close()
    $sw.Dispose()
    Write-Host "Files with existing documentation triggers  +++ Line number at top of trigger section" -ForegroundColor DarkYellow
    $FilesWithDocTrigger.GetEnumerator() | Sort-Object Name
    Start-Sleep -Seconds 2

    foreach($FilesWithDocTr in $FilesWithDocTrigger.Keys)
    {
        if (${FilesWithDocTr} -ne 'File')
        {
            #Write-Host "${FilesWithDocTr}: $($FilesWithDocTrigger.Item($FilesWithDocTr))"
            Write-Host "Adding new section to existing documentation trigger in ${FilesWithDocTr}" -ForegroundColor Yellow
            $sr2 = new-object System.IO.StreamReader("$WorkingFolder\SPLITNAVOBJCPYRT\$FilesWithDocTr",[system.text.encoding]::GetEncoding(850))
            $ObjectFileName2 = $FilesWithDocTr + ".tmp"
            $Objectfile2 = New-Item -path "$WorkingFolder\SPLITNAVOBJCPYRT\$ObjectFileName2"  -type file -force
            IF (Test-Path $ObjectFile2) {Remove-Item $ObjectFile2 -Force}
            $posCnt2 = 0       
            $sw2 = new-object System.IO.Streamwriter($Objectfile2,$false,[system.text.encoding]::GetEncoding(850))
            while (-not $Sr2.EndOfStream)
            {
                [int]$DocPosLine = $FilesWithDocTrigger.get_item($FilesWithDocTr)
                $Currline2 = $sr2.ReadLine()
                $posCnt2++
                if ($posCnt2 -ne ($DocPosLine + 2))
                {$sw2.writeline($Currline2)}
                else
                {
                    $sw2.writeline("      (c) Global Software Enterprises, all rights reserved")
                    $sw2.writeline("      ------------------------------------------------")
                    $sw2.writeline()
                    $sw2.writeline($Currline2)
                }
            }
            $sw2.close()
            $sw2.Dispose()
            $sr2.Close()
            $sr2.Dispose()
            Start-Sleep -Milliseconds 10
            IF (Test-Path "$WorkingFolder\SPLITNAVOBJCPYRT\$FilesWithDocTr") {Remove-Item "$WorkingFolder\SPLITNAVOBJCPYRT\$FilesWithDocTr" -Force}
            Start-Sleep -Milliseconds 10
            IF (Test-Path $ObjectFile2) {Rename-Item $ObjectFile2 -NewName "$WorkingFolder\SPLITNAVOBJCPYRT\$FilesWithDocTr" -Force}
            Start-Sleep -Milliseconds 10
        }
    }
    if ($sw2.BaseStream)
    {
        $sw2.close()
        $sw2.Dispose()
    }
    if ($sr2.BaseStream)
    {
        $sr2.Close()
        $sr2.Dispose()
    }
    Invoke-item "$WorkingFolder\SPLITNAVOBJCPYRT\"
   
}
GruĂź, Kai

Frage beantwortet? Schreibe bitte [Gelöst] vor den Titel des ersten Beitrags.
Bitte erst suchen, dann fragen. Bitte beachte den kleinen Community-Knigge.
Kein Support per PN, Mail, Messenger oder Telefon! DafĂĽr ist dieses Forum da.

Download: Dynamics NAV Object Text Explorer (Alternativlink). MVP Alumni
Benutzeravatar
Kowa
Moderator
Moderator
 
Beiträge: 7835
Registriert: 17. Juni 2005 17:32
Wohnort: Bremen
Realer Name: Kai Kowalewski
Arbeitsort: Osterholz-Scharmbeck
Bezug zu Microsoft Dynamics: Microsoft Partner
Microsoft Dynamics Produkt: Microsoft Dynamics 365
Microsoft Dynamics Version: BC, NAV 2018 bis Navision 2.01

Dokumentations-Trigger oben und unten pflegen

Beitragvon Kowa » 20. Januar 2018 01:04

Mit dieser Variante kann man sowohl oben als auch unten in einem vorhandenen Trigger einen Einschub vornehmen.
DocuTrigger2Sections.png

Mit der Variante $AddBottomSection oben im Skript kann man den unteren bei Bedarf auch abschalten. Das Skript arbeitet dann wie das obige, das ich zu Vergleichszwecken aber trotzdem dort stehen lasse.
Code: Alles auswählen
$AddBottomSection = $false

Der Ausgabetext passt sich dabei jeweils an, die Pluraloption kommt nur, wenn beide erzeugt werden.
DocuTrigger3.png

Code: Alles auswählen
function Split-NAVObjectFileWithDocuTrigger2
{
    $ErrorActionPreference = "Stop"
    $PSDefaultParameterValues['*:ErrorAction']='Stop'

    $AddBottomSection = $true
 
    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 = "NAV Object Files (*.txt)|*.txt"
        $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)
    #$TotalLineCnt = $inputfile.count
   
    $inputfile = resolve-path $inputfile
    $WorkingFolder = Split-Path -Parent $inputfile

    if (Test-path "$WorkingFolder\SPLITNAVOBJCPYRT\")
    {Remove-Item -path "$WorkingFolder\SPLITNAVOBJCPYRT\" -Recurse -Force}

    Write-Host "Splitting NAV objects from $inputfile (Size: $filesize MB) to $WorkingFolder\SPLITNAVOBJCPYRT\, this may take a while..." -ForegroundColor Yellow
    $startime = date
   
    $fs= New-Object System.IO.FileStream($inputfile,"OpenOrCreate", "Read", "ReadWrite",8,"None")
    $Sr = new-object System.IO.StreamReader($fs,[system.text.encoding]::GetEncoding(850))

    [int]$ObjCnt = 0
    [int]$TabCnt = 0
    [int]$PagCnt = 0
    [int]$RepCnt = 0
    [int]$CodCnt = 0
    [int]$XmlCnt = 0
    [int]$ForCnt = 0
    [int]$DatCnt = 0
    [int]$QueCnt = 0
    [int]$MenCnt = 0
    [int]$PosCnt = 0

    $LastLine = ''
    $FilesWithDocTrigger = @{}
    $FilesWithDocTriggerPeriodEnd = @{}
    while (-not $Sr.EndOfStream)
    {
        $Currline = $sr.ReadLine()
        #$fsr = $sr.BaseStream
        $posCnt++

        if ($Currline.StartsWith('OBJECT'))
        {
            $HasDocuTrigger  = $false   
            [String]$ObjectChar = $Currline.Substring(7,1)
            $ObjectLine = $currline.Split(' ')
            $ObjCnt++
            [int]$ObjposCnt = 0

            Switch ($ObjectChar)
            {
                'T' {$TabCnt++}
                'P' {$PagCnt++}
                'R' {$RepCnt++}
                'C' {$CodCnt++}
                'X' {$XmlCnt++}
                'F' {$ForCnt++}
                'D' {$DatCnt++}
                'Q' {$QueCnt++}
                'M' {$MenCnt++}
            }

            $ObjectFileName = $ObjectLine[1].Substring(0,3).ToUpper() + $ObjectLine[2] + ".TXT"
            $Objectfile = New-Item -path "$WorkingFolder\SPLITNAVOBJCPYRT\$ObjectFileName" -type file -force
            IF (Test-Path $ObjectFile) {Remove-Item $ObjectFile}
           
            $sw = new-object System.IO.Streamwriter($Objectfile,$false,[system.text.encoding]::GetEncoding(850))
        }
        $ObjposCnt++   
        if ($CurrLine -eq '    BEGIN')
        {
            $LastBeginPosInObj = $ObjposCnt
           
        }
        if ($CurrLine -eq '    END.')
        {
            $EndPeriodPosInObj = $ObjposCnt
           
        }
        if (($Currline -eq '    END.') -and ($LastLine -eq '    BEGIN'))
        {   
            # create new trigger
            $sw.writeline('    {')
            $sw.writeline("      (c) Global Software Enterprises, all rights reserved" )
            $sw.writeline("      ----------------------------------------------------")
            $sw.writeline()
            $sw.writeline('    }')
            $sw.writeline('    END.')
            $LastLine = $CurrLine
        }
         
        #
        elseif (($Currline -eq '    END.') -and ($LastLine -ne '    BEGIN'))
        {
            # existing trigger
            $sw.writeline($Currline)
            $Lastline = $CurrLine
            $HasDocuTrigger = $true

            [int]$SplitFileAtLine = $LastBeginPosinObj
 
        }
        elseif (-not $Currline.StartsWith('}'))
        {
            # normal line
            $sw.writeline($Currline)
            $Lastline = $CurrLine
        }
        else
        {
            # final line
            $sw.writeline($Currline)
            $Lastline = $CurrLine
            $sw.writeline()
           
            $sw.Flush()
           
            # End of splitted object file
            if ($HasDocuTrigger)
            {
                $FilesWithDocTrigger.Add($Objectfilename,$SplitFileAtLine)
                $FilesWithDocTriggerPeriodEnd.Add($Objectfilename,$EndPeriodPosInObj)
                $ObjposCnt = 0
            }
        }
    }
    $endtime = date
    $time = $endtime - $startime
    Write-Host "$ObjCnt NAV objects splitted to $WorkingFolder\SPLITNAVOBJCPYRT\ in $($time.Minutes)m:$($time.Seconds)s:$($time.Milliseconds)ms" -ForegroundColor Yellow
    Write-Host "Tables: $TabCnt" -ForegroundColor Yellow
    Write-Host "Pages: $PagCnt" -ForegroundColor Yellow
    Write-Host "Reports: $RepCnt" -ForegroundColor Yellow
    Write-Host "Codeunits: $CodCnt" -ForegroundColor Yellow
    Write-Host "XMLPorts: $XMLCnt" -ForegroundColor Yellow
    Write-Host "MenuSuites: $MenCnt" -ForegroundColor Yellow
    if ($ForCnt -gt 0)
    {Write-Host "Forms: $ForCnt" -ForegroundColor Yellow}
    if ($DatCnt -gt 0)
    {Write-Host "Dataports: $DatCnt" -ForegroundColor Yellow}   
    $sr.Close()
    $sr.Dispose()
    $sw.close()
    $sw.Dispose()
    Write-Host "Files with existing documentation triggers + Line number at top of trigger section" -ForegroundColor DarkYellow
    $FilesWithDocTrigger.GetEnumerator() | Sort-Object Name
    Start-Sleep -Seconds 3

    foreach($FilesWithDocTr in $FilesWithDocTrigger.Keys)
    {

 
        #Write-Host "${FilesWithDocTr}: $($FilesWithDocTrigger.Item($FilesWithDocTr))"
        if ($AddBottomSection) {$Plural = '(s)'}
        Write-Host "Adding new section$Plural to existing documentation trigger in ${FilesWithDocTr}" -ForegroundColor Yellow
        $sr2 = new-object System.IO.StreamReader("$WorkingFolder\SPLITNAVOBJCPYRT\$FilesWithDocTr",[system.text.encoding]::GetEncoding(850))
        $ObjectFileName2 = $FilesWithDocTr + ".tmp"
        $Objectfile2 = New-Item -path "$WorkingFolder\SPLITNAVOBJCPYRT\$ObjectFileName2"  -type file -force
        IF (Test-Path $ObjectFile2) {Remove-Item $ObjectFile2 -Force}
        $posCnt2 = 0       
        $sw2 = new-object System.IO.Streamwriter($Objectfile2,$false,[system.text.encoding]::GetEncoding(850))
        while (-not $sr2.EndOfStream)
        {
            [int]$DocPosLine = $FilesWithDocTrigger.get_item($FilesWithDocTr)
            [int]$DocPosEndLine = $FilesWithDocTriggerPeriodEnd.get_item($FilesWithDocTr)
            $Currline2 = $sr2.ReadLine()
            $posCnt2++
            if (($AddBottomSection) -and ($posCnt2 -eq ($DocPosEndLine -2)))
            {
                # bottom section
                $sw2.writeline($Currline2)
                $sw2.writeline("      ---------GLOBAL SOFTWARE ENTERPRISES---------")
                $sw2.writeline("      ---------ADDON MODULE VERSION----------------")
                $sw2.writeline("               XYZ   ABC    1.2.3")
               
            }
               
            elseif ($posCnt2 -ne ($DocPosLine + 2))
            {$sw2.writeline($Currline2)}
            else
            {
                # top section
                $sw2.writeline("      (c) Global Software Enterprises, all rights reserved")
                $sw2.writeline("      ------------------------------------------------")
                $sw2.writeline()
                $sw2.writeline($Currline2)

            }
        }
        $sw2.close()
        $sw2.Dispose()
        $sr2.Close()
        $sr2.Dispose()
        Start-Sleep -Milliseconds 10
        IF (Test-Path "$WorkingFolder\SPLITNAVOBJCPYRT\$FilesWithDocTr") {Remove-Item "$WorkingFolder\SPLITNAVOBJCPYRT\$FilesWithDocTr" -Force}
        Start-Sleep -Milliseconds 10
        IF (Test-Path $ObjectFile2) {Rename-Item $ObjectFile2 -NewName "$WorkingFolder\SPLITNAVOBJCPYRT\$FilesWithDocTr" -Force}
        Start-Sleep -Milliseconds 10
    }
    if ($sw2.BaseStream)
    {
        $sw2.close()
        $sw2.Dispose()
    }
    if ($sr2.BaseStream)
    {
        $sr2.Close()
        $sr2.Dispose()
    }
    Invoke-item "$WorkingFolder\SPLITNAVOBJCPYRT\"
   
}
GruĂź, Kai

Frage beantwortet? Schreibe bitte [Gelöst] vor den Titel des ersten Beitrags.
Bitte erst suchen, dann fragen. Bitte beachte den kleinen Community-Knigge.
Kein Support per PN, Mail, Messenger oder Telefon! DafĂĽr ist dieses Forum da.

Download: Dynamics NAV Object Text Explorer (Alternativlink). MVP Alumni
Benutzeravatar
Kowa
Moderator
Moderator
 
Beiträge: 7835
Registriert: 17. Juni 2005 17:32
Wohnort: Bremen
Realer Name: Kai Kowalewski
Arbeitsort: Osterholz-Scharmbeck
Bezug zu Microsoft Dynamics: Microsoft Partner
Microsoft Dynamics Produkt: Microsoft Dynamics 365
Microsoft Dynamics Version: BC, NAV 2018 bis Navision 2.01


ZurĂĽck zu NAV Tipps & Tricks

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast