PowerShell: Generate Symbol Reference fĂĽr AL (mit GUI)

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: Generate Symbol Reference fĂĽr AL (mit GUI)

Beitragvon Kowa » 23. Januar 2018 18:36

Das manuelle Generieren von Symbolen für AL ist ja bislang nur über die Kommandozeile möglich :roll: (Neuer Parameter für finsql.exe command=generatesymbolreference) .
[Nachtrag]: Das Cmdlet Compile-NavApplicationObject -GenerateSymbolReference -Recompile ist nun auch verfĂĽgbar, um diese bequemer zu erzeugen, Filter auf einzelne Objekte z.B. so setzen -Filter 'Type=Table;ID=50093'

Running C/SIDE and AL Side-by-Side
Mit diesem Skript mit Eingabefenster ist es deutlich einfacher, die Kommandozeile wird damit erzeugt und ausgefĂĽhrt. Der Objektfilter ist dabei optional. Vorher nicht vergessen, das neue Feld Enable loading application symbol references at server startup
ServerEnableSymbolReference.png
auf dem Server zu aktivieren und den Dienst danach neu zu starten.

Im Programmverzeichnis liegt nach Beendigung diese Datei, die aber leider kein Indiz fĂĽr eine korrekte Erzeugung ist, siehe hier :!: .
GenerateSymbols1.png




GenerateSymbols.png
GenerateSymbols.png (4.89 KiB) 4686-mal betrachtet


Der Beispielcode hier für das Fenster enthält übrigens einen Fehler (Script bzw. Global Scope der $x-Variablen fehlen), das ist im Skript natürlich korrigiert :wink: .

[Edit 11.02.18] FĂĽr noch mehr Komfort mit einer automatisch generierten Datenbankliste siehe diese Variante hier.

Für Business Central-Programmpfad (hier für Version 13 = Programmpfad …\130\…, für Folgeversionen entsprechend ändern)
Code: Alles auswählen
function GenerateSymbolsBC
{
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

    function GenerateSymbolsForDatabase
    {
        [CmdletBinding()]param (
            [String]$Server,
            [String]$Database,
        [String]$ObjectFilter)
        $NAVFolder = 'C:\Program Files (x86)\Microsoft Dynamics 365 Business Central\130\RoleTailored Client'
        if ($ObjectFilter -ne '')
        {$Command = """$NAVFolder\finsql.exe"" command=generatesymbolreference,servername=$Server,database=$Database,filter=$ObjectFilter"}
        else
        {$Command = """$NAVFolder\finsql.exe"" command=generatesymbolreference,servername=$Server,database=$Database"}
       
        Write-host $Command
        cmd /c $Command
    }


    $objForm = New-Object System.Windows.Forms.Form
    $objForm.Text = "Generate Symbols"
    $objForm.Size = New-Object System.Drawing.Size(300,300)
    $objForm.StartPosition = "CenterScreen"

    $objForm.KeyPreview = $True
    $objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") {$script:x=$objTextBox.Text;$script:x2=$objTextBox2.Text;$script:x3=$objTextBox3.Text;$objForm.Close()}})
    $objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
    {$objForm.Close()}})

    $OKButton = New-Object System.Windows.Forms.Button
    $OKButton.Location = New-Object System.Drawing.Size(75,220)
    $OKButton.Size = New-Object System.Drawing.Size(75,23)
    $OKButton.Text = "OK"
    $OKButton.Add_Click({$script:x=$objTextBox.Text;$script:x2=$objTextBox2.Text;$script:x3=$objTextBox3.Text;$objForm.Close()})
    $objForm.Controls.Add($OKButton)

    $CancelButton = New-Object System.Windows.Forms.Button
    $CancelButton.Location = New-Object System.Drawing.Size(150,220)
    $CancelButton.Size = New-Object System.Drawing.Size(75,23)
    $CancelButton.Text = "Cancel"
    $CancelButton.Add_Click({$objForm.Close()})
    $objForm.Controls.Add($CancelButton)

    #############
    $objLabel = New-Object System.Windows.Forms.Label
    $objLabel.Location = New-Object System.Drawing.Size(10,20)
    $objLabel.Size = New-Object System.Drawing.Size(280,20)
    $objLabel.Text = "Server"
    $objForm.Controls.Add($objLabel)

    $objTextBox = New-Object System.Windows.Forms.TextBox
    $objTextBox.Location = New-Object System.Drawing.Size(10,40)
    $objTextBox.Size = New-Object System.Drawing.Size(260,20)
    $objForm.Controls.Add($objTextBox)

    $objLabel2 = New-Object System.Windows.Forms.Label
    $objLabel2.Location = New-Object System.Drawing.Size(10,65)
    $objLabel2.Size = New-Object System.Drawing.Size(280,20)
    $objLabel2.Text = "Database"
    $objForm.Controls.Add($objLabel2)

    $objTextBox2 = New-Object System.Windows.Forms.TextBox
    $objTextBox2.Location = New-Object System.Drawing.Size(10,85)
    $objTextBox2.Size = New-Object System.Drawing.Size(260,20)
    $objForm.Controls.Add($objTextBox2)
 
    $objLabel3 = New-Object System.Windows.Forms.Label
    $objLabel3.Location = New-Object System.Drawing.Size(10,105)
    $objLabel3.Size = New-Object System.Drawing.Size(280,20)
    $objLabel3.Text = "Object Filter"
    $objForm.Controls.Add($objLabel3)

    $objTextBox3 = New-Object System.Windows.Forms.TextBox
    $objTextBox3.Location = New-Object System.Drawing.Size(10,125)
    $objTextBox3.Size = New-Object System.Drawing.Size(260,20)
    $objForm.Controls.Add($objTextBox3)


    $objForm.Topmost = $True

    $objForm.Add_Shown({$objForm.Activate()})
    [void] $objForm.ShowDialog()

    #Write-host "$x $x2 $x3"


    if (($x -ne '') -and ($x2 -ne '') -and ($x3 -eq ''))
    {GenerateSymbolsForDatabase -Server $x -Database $x2}
    elseif (($x -ne '') -and ($x2 -ne '') -and ($x3 -ne ''))
    {GenerateSymbolsForDatabase -Server $x -Database $x2 -ObjectFilter $x3}
    else
    {
        [System.Windows.Forms.MessageBox]::Show("Please enter server and database. Object Filter is an option.")
        Write-Error 'Please enter server and database. Object Filter is an option.'
    }
}
GenerateSymbolsBC

FĂĽr NAV-Programmpfad
Code: Alles auswählen
function GenerateSymbolsNAV
{
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

    function GenerateSymbolsForDatabase
    {
        [CmdletBinding()]param (
            [String]$Server,
            [String]$Database,
        [String]$ObjectFilter)
        $NAVFolder = 'C:\Program Files (x86)\Microsoft Dynamics NAV\110\RoleTailored Client'
        if ($ObjectFilter -ne '')
        {$Command = """$NAVFolder\finsql.exe"" command=generatesymbolreference,servername=$Server,database=$Database,filter=$ObjectFilter"}
        else
        {$Command = """$NAVFolder\finsql.exe"" command=generatesymbolreference,servername=$Server,database=$Database"}
       
        Write-host $Command
        cmd /c $Command
    }


    $objForm = New-Object System.Windows.Forms.Form
    $objForm.Text = "Generate Symbols"
    $objForm.Size = New-Object System.Drawing.Size(300,300)
    $objForm.StartPosition = "CenterScreen"

    $objForm.KeyPreview = $True
    $objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") {$script:x=$objTextBox.Text;$script:x2=$objTextBox2.Text;$script:x3=$objTextBox3.Text;$objForm.Close()}})
    $objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
    {$objForm.Close()}})

    $OKButton = New-Object System.Windows.Forms.Button
    $OKButton.Location = New-Object System.Drawing.Size(75,220)
    $OKButton.Size = New-Object System.Drawing.Size(75,23)
    $OKButton.Text = "OK"
    $OKButton.Add_Click({$script:x=$objTextBox.Text;$script:x2=$objTextBox2.Text;$script:x3=$objTextBox3.Text;$objForm.Close()})
    $objForm.Controls.Add($OKButton)

    $CancelButton = New-Object System.Windows.Forms.Button
    $CancelButton.Location = New-Object System.Drawing.Size(150,220)
    $CancelButton.Size = New-Object System.Drawing.Size(75,23)
    $CancelButton.Text = "Cancel"
    $CancelButton.Add_Click({$objForm.Close()})
    $objForm.Controls.Add($CancelButton)

    #############
    $objLabel = New-Object System.Windows.Forms.Label
    $objLabel.Location = New-Object System.Drawing.Size(10,20)
    $objLabel.Size = New-Object System.Drawing.Size(280,20)
    $objLabel.Text = "Server"
    $objForm.Controls.Add($objLabel)

    $objTextBox = New-Object System.Windows.Forms.TextBox
    $objTextBox.Location = New-Object System.Drawing.Size(10,40)
    $objTextBox.Size = New-Object System.Drawing.Size(260,20)
    $objForm.Controls.Add($objTextBox)

    $objLabel2 = New-Object System.Windows.Forms.Label
    $objLabel2.Location = New-Object System.Drawing.Size(10,65)
    $objLabel2.Size = New-Object System.Drawing.Size(280,20)
    $objLabel2.Text = "Database"
    $objForm.Controls.Add($objLabel2)

    $objTextBox2 = New-Object System.Windows.Forms.TextBox
    $objTextBox2.Location = New-Object System.Drawing.Size(10,85)
    $objTextBox2.Size = New-Object System.Drawing.Size(260,20)
    $objForm.Controls.Add($objTextBox2)
 
    $objLabel3 = New-Object System.Windows.Forms.Label
    $objLabel3.Location = New-Object System.Drawing.Size(10,105)
    $objLabel3.Size = New-Object System.Drawing.Size(280,20)
    $objLabel3.Text = "Object Filter"
    $objForm.Controls.Add($objLabel3)

    $objTextBox3 = New-Object System.Windows.Forms.TextBox
    $objTextBox3.Location = New-Object System.Drawing.Size(10,125)
    $objTextBox3.Size = New-Object System.Drawing.Size(260,20)
    $objForm.Controls.Add($objTextBox3)


    $objForm.Topmost = $True

    $objForm.Add_Shown({$objForm.Activate()})
    [void] $objForm.ShowDialog()

    #Write-host "$x $x2 $x3"


    if (($x -ne '') -and ($x2 -ne '') -and ($x3 -eq ''))
    {GenerateSymbolsForDatabase -Server $x -Database $x2}
    elseif (($x -ne '') -and ($x2 -ne '') -and ($x3 -ne ''))
    {GenerateSymbolsForDatabase -Server $x -Database $x2 -ObjectFilter $x3}
    else
    {
        [System.Windows.Forms.MessageBox]::Show("Please enter server and database. Object Filter is an option.")
        Write-Error 'Please enter server and database. Object Filter is an option.'
    }
}
GenerateSymbolsNAV


Tags: generatesymbolreference
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

ImplicitType=Integer

Beitragvon Kowa » 26. Januar 2018 11:15


Der dort erwähnte pauschale Startparameter generatesymbolreference=yes im Abschnitt Continuously generate symbols each time you compile objects in C/SIDE verursacht aktuell einen Bug, der aus dem Development Client exportierte C/AL-Code von Pages enthält dann bei Feldern die zusätzliche Zeile
Code: Alles auswählen
ImplicitType=Integer

die den erneuten Import verhindert. (Quelle)
Beispiel Page 1310
ImplicitType.png

ImplicitType
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

Variante mit Drilldown-Datenbankauswahl

Beitragvon Kowa » 12. Februar 2018 00:08

Diese Variante bietet mehr Eingabekomfort bei der Auswahl der Datenbank, erfordert dazu aber ein installiertes SQL Server Management Studio (SMO/Server Class).
Bei diesem Skript kann man nach Eingabe des Servernamens auf den Button "List Databases" klicken.
GenerateSymbolsSQLMgt1.png
GenerateSymbolsSQLMgt1.png (7.54 KiB) 4613-mal betrachtet

Dieser Klick ermittelt dann alle dortigen Datenbanken und listet diese in dem Drilldown (Combobox) des Databasefeldes auf, wo man die benötigte Datenbank dann auswählen kann.
GenerateSymbolsSQLMgt2.png
Auf das Erzeugen dieser Liste nur durch Klicken in das Feld bzw. wenn dieses den Fokus erhält, habe ich bewusst verzichtet, weil Tippfehler beim Serverfeld dann zu den bekannten längeren Suchaktionen nach einem nicht vorhandenen Server führen, die man aus den entsprechenden Feldern im NAV Development Environment ja leider nur allzugut kennt :roll: .


Code: Alles auswählen
function GenerateSymbolsSQLMgt
{
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    [void] [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")

    function GenerateSymbolsForDatabase
    {
        [CmdletBinding()]param (
            [String]$Server,
            [String]$Database,
        [String]$ObjectFilter)
        $NAVFolder = 'C:\Program Files (x86)\Microsoft Dynamics NAV\110\RoleTailored Client'
        if ($ObjectFilter -ne '')
        {$Command = """$NAVFolder\finsql.exe"" command=generatesymbolreference,servername=$Server,database=$Database,filter=$ObjectFilter"}
        else
        {$Command = """$NAVFolder\finsql.exe"" command=generatesymbolreference,servername=$Server,database=$Database"}
       
        Write-host $Command
        cmd /c $Command
    }


    function Get-DBList($server)
    {
       
        $script:DatabaseName  = @{}
        $srv = New-Object 'Microsoft.SqlServer.Management.Smo.Server' $server
   
        [int]$i = 0
        foreach($sqlDatabase in $srv.Databases)
        {
            $i++
            #[string]$ts = "$i"
            #write-host "$i,$sqlDatabase"
       
            $DatabaseName.Add($i,$sqlDatabase)
        }
        foreach($databaseID in $databasename.keys)
        {
   
            $DBname =  $databasename[$databaseID]
            $DBname2 = $DBname.ToString()
            $DBname2 = $DBname2.trimstart('[')
            $DBname2 = $DBname2.trimend(']')
            $IsSystemDatabase = ($DBname2 -like 'master') -or ($DBname2 -like 'tempdb') -or ($DBname2 -like  'model') -or ($DBname2 -like 'msdb') -or ($DBname2.startswith('ReportServer'))
            if (-not $IsSystemDatabase)
            {$comboBox1.Items.add($DBname2)}
        }

    }
    $objForm = New-Object System.Windows.Forms.Form
    $objForm.Text = "Generate Symbols"
    $objForm.Size = New-Object System.Drawing.Size(300,300)
    $objForm.StartPosition = "CenterScreen"

    $objForm.KeyPreview = $True
    $objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") {$script:x=$objTextBox.Text;$script:x2=$comboBox1.Text;$script:x3=$objTextBox3.Text;$objForm.Close()}})

    $objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
    {$objForm.Close()}})

   


    $OKButton = New-Object System.Windows.Forms.Button
    $OKButton.Location = New-Object System.Drawing.Size(95,220)
    $OKButton.Size = New-Object System.Drawing.Size(75,23)
    $OKButton.Text = "OK"
    $OKButton.Add_Click({$script:x=$objTextBox.Text;$script:x2=$ComboBox1.Text;$script:x3=$objTextBox3.Text;$objForm.Close()})
    $objForm.Controls.Add($OKButton)

    $GetDBButton = New-Object System.Windows.Forms.Button
    $GetDBButton.Location = New-Object System.Drawing.Size(5,220)
    $GetDBButton.Size = New-Object System.Drawing.Size(95,23)
    $GetDBButton.Text = "List databases"
    $GetDBButton.Add_Click({
            $script:x=$objTextBox.Text
            if ($script:x -ne '') {Get-DBlist($script:x)} else
            {[System.Windows.Forms.MessageBox]::Show("Please enter <servername>\<instance> in the server field.")}
    })
    $objForm.Controls.Add($GetDBButton)

    $CancelButton = New-Object System.Windows.Forms.Button
    $CancelButton.Location = New-Object System.Drawing.Size(165,220)
    $CancelButton.Size = New-Object System.Drawing.Size(75,23)
    $CancelButton.Text = "Cancel"
    $CancelButton.Add_Click({$objForm.Close()})
    $objForm.Controls.Add($CancelButton)

    #############
    $objLabel = New-Object System.Windows.Forms.Label
    $objLabel.Location = New-Object System.Drawing.Size(10,20)
    $objLabel.Size = New-Object System.Drawing.Size(280,20)
    $objLabel.Text = "Server"
    $objForm.Controls.Add($objLabel)

    $objTextBox = New-Object System.Windows.Forms.TextBox
   
    $objTextBox.Location = New-Object System.Drawing.Size(10,40)
    $objTextBox.Size = New-Object System.Drawing.Size(260,20)
    $objForm.Controls.Add($objTextBox)
   
   

    $objLabel2 = New-Object System.Windows.Forms.Label
    $objLabel2.Location = New-Object System.Drawing.Size(10,65)
    $objLabel2.Size = New-Object System.Drawing.Size(280,20)
    $objLabel2.Text = "Database"
    $objForm.Controls.Add($objLabel2)

   
    $script:comboBox1 = New-Object System.Windows.Forms.ComboBox
    $comboBox1.Location = New-Object System.Drawing.Size(10,85)
    $comboBox1.Size = New-Object System.Drawing.Size(260,20)
    $objForm.Controls.Add($comboBox1)

 
    $objLabel3 = New-Object System.Windows.Forms.Label
    $objLabel3.Location = New-Object System.Drawing.Size(10,105)
    $objLabel3.Size = New-Object System.Drawing.Size(280,20)
    $objLabel3.Text = "Object Filter"
    $objForm.Controls.Add($objLabel3)

    $objTextBox3 = New-Object System.Windows.Forms.TextBox
    $objTextBox3.Location = New-Object System.Drawing.Size(10,125)
    $objTextBox3.Size = New-Object System.Drawing.Size(260,20)
    $objForm.Controls.Add($objTextBox3)


    $objForm.Topmost = $True

    $objForm.Add_Shown({$objForm.Activate()})
    [void] $objForm.ShowDialog()

    #Write-host "$x $x2 $x3"


    if (($x -ne '') -and ($x2 -ne '') -and ($x3 -eq ''))
    {GenerateSymbolsForDatabase -Server $x -Database $x2}
    elseif (($x -ne '') -and ($x2 -ne '') -and ($x3 -ne ''))
    {GenerateSymbolsForDatabase -Server $x -Database $x2 -ObjectFilter $x3}
    else
    {
        [System.Windows.Forms.MessageBox]::Show("Please enter server and database. Object Filter is an option.")
        Write-Error 'Please enter server and database. Object Filter is an option.'
    }
}
GenerateSymbolsSQLMgt
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

Re: PowerShell: Generate Symbol Reference fĂĽr AL (mit GUI)

Beitragvon Kowa » 26. Februar 2019 11:55

Bei der navcommandresult.txt im Programmverzeichnis sollte man auch den Inhalt kontrollieren.
Diese kann nämlich auch Warnungen enthalten, die dann das Generieren von Symbols für bestimmte Objekte verhindern, so wie hier bei nicht mehr erlaubter UsageCategory in den RequestPages von Reports ab einem bestimmten Build (in diesem Fall BC CU 03).
FailedSymbolGeneration.png
Ein Fehlerprotokoll (Datei naverrorlog.txt an gleichem Ort) wird in solchen Fällen nicht erzeugt :roll: .
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