Page Verwendung protokollieren (BC14)

2. Januar 2022 18:36

Hi,

wie kann ich sehen, welche Pages alles aufgerufen werden. Für die Reports habe ich es ja schon geschafft.
Habe zwar die Codeunit 700 gefunden, aber das funktioniert scheinbar nicht so einfach wie bei den Reports.

lg
stony

PS: und gutes neues JAHR

Re: Page Verwendung protokollieren (BC14)

3. Januar 2022 11:58

Für die Report-Aufrufe gab es unter NAV2009, NAV2009 SP1 und NAV2009 R2 die Möglichkeit, in der Codeunit 1 eine Funktion "OnReportRun" (mit einer ganz speziellen Funktions-ID) anzulegen.
Diese Funktion wurde auf jeden Fall vor dem Start des Reports ausgeführt, auch wenn dieser per C/AL-Befehl auf dem Standard-Drucker (statt auf dem Drucker laut Druckerauswahl-Tabelle) gedruckt wurde.
In allen anderen Versionen davor und danach besteht nur noch die Möglichkeit, über die Funktion FindPrinter eine entsprechende Protokollierung vorzunehmen, diese wird jedoch nicht aufgerufen, wenn der Report per C/AL-Befehl auf dem Standard-Drucker des Clients gedruckt werden soll.

Für andere Objektarten (wie z. B. Pages) gibt es so eine Möglichkeit nicht.

Es gäbe jedoch einen Workaround, wie man für Pages ein ähnliches Verhalten nachstellen könnte:
Schreibe dir eine Codeunit, welche für jede zu protokollierende Page per Event den OnPageRun-Trigger abonniert.
Dieses Event ruft dann deine Funktion zur Ausführungs-Protokollierung auf.

Du hast keine Lust, so viele Funktionen in der Codeunit anzulegen?
Dann schreibe dir doch eine Codeunit, welche dir die o. g. Codeunit als Textdatei zusammenbaut.
Diese importierst und kompilierst du dann.

Leider hat dieser Workaround einen kleinen Haken:
Du kannst nicht unendlich viele Funktionen in einer Codeunit haben.
Ich hatte mal diesen Trick verwendet, um über eine allgemeingültige Funktion den SourceRecord einer Page entsprechend einer Einrichtungstabelle filtern zu können.
Anfangs (als die Datenbank noch sehr nah am CRONUS-Standard war) funktionierte das, aber nachdem wir die Branchenlösung sowie ein paar AddOn-Module importiert hatten, hatte die Codeunit zuviele Funktionen, so dass unser NAV2017 "zu viele Handler" bemängelt hatte.
Wir haben die Codeunit zur Erstellung der Codeunit dann auf bestimmte Page-Types beschränkt, so dass wir nicht in die kritische Menge rutschten.

Eventuell könnte es helfen, wenn man die Codeunit dahingehend umstellt, dass sie automatisch eine Codeunit je PageType erzeugt, so dass die EventSubscriber auf mehrere Codeunits verteilt sind.

Hier eine zensierte Version unserer Codeunit-schreibenden Codeunit:
Code:
OnRun()
PageMetadata.RESET;
PageMetadata.SETFILTER(SourceTable,'<>%1',0);
PageMetadata.SETFILTER(
  PageType,'%1|%2|%3|%4|%5|%6|%7',
  PageMetadata.PageType::Card,PageMetadata.PageType::CardPart,
  PageMetadata.PageType::List,PageMetadata.PageType::ListPart,PageMetadata.PageType::ListPlus,
  PageMetadata.PageType::Document,PageMetadata.PageType::Worksheet);
IF PageMetadata.FINDSET(FALSE) THEN BEGIN
  ObjFilename 
:= FileMgt.SaveFileDialog('Speichern unter...','\\MyFileServer\NAV-Share\CU50009_Page_EventSubscriber.txt','');
  IF FileMgt.ServerFileExists(ObjFilename) THEN BEGIN
    FileMgt
.DeleteServerFile(ObjFilename);
  END;
  ObjFile.TEXTMODE := TRUE;
  ObjFile.WRITEMODE := TRUE;
  ObjFile.CREATE(ObjFilename,TEXTENCODING::MSDos);
  DlgMgt.Open('Creating Object File...','Object',PageMetadata.COUNT);
  CurrRec := 0;
  WriteObjHeader;
  REPEAT
    CurrRec 
+= 1;
    DlgMgt.Update(STRSUBSTNO('Page %1',PageMetadata.ID),CurrRec);
    WriteEvent;
  UNTIL PageMetadata.NEXT = 0;
  WriteObjFooter;
  DlgMgt.Close(FALSE);
  ObjFile.CLOSE;
END;

LOCAL WriteObjHeader()
ObjFile.WRITE('OBJECT Codeunit 50009 Page EventSubscr');
ObjFile.WRITE('{');
ObjFile.WRITE('  OBJECT-PROPERTIES');
ObjFile.WRITE('  {');
ObjFile.WRITE(STRSUBSTNO('    Date=%1;',FORMAT(TODAY,0,'<Year4,4>-<Month,2>-<Day,2>')));
ObjFile.WRITE(STRSUBSTNO('    Time=%1;',FORMAT(TIME,0,'<Hours24>:<Minutes>:<Seconds>')));  // We want the real Date and Time of the Codeunit creation.
ObjFile.WRITE('    Modified=Yes;');
ObjFile.WRITE(STRSUBSTNO('    Version List=NAVW110.%1.%2;',DATE2DMY(TODAY,3) MOD 100,FORMAT(TODAY,0,'<Week,2>')));
ObjFile.WRITE('  }');
ObjFile.WRITE('  PROPERTIES');
ObjFile.WRITE('  {');
ObjFile.WRITE('    OnRun=BEGIN');
ObjFile.WRITE('          END;');
ObjFile.WRITE('');
ObjFile.WRITE('  }');
ObjFile.WRITE('  CODE');
ObjFile.WRITE('  {');
ObjFile.WRITE('');

LOCAL WriteEvent()
IF NOT Object.GET(Object.Type::Page,'',PageMetadata.ID) THEN BEGIN
  EXIT
;
END;
IF NOT Object.GET(Object.Type::Table,'',PageMetadata.SourceTable) THEN BEGIN
  EXIT
;
END;

ObjFile.WRITE(STRSUBSTNO('    [EventSubscriber(Page,%1,OnOpenPageEvent)]',PageMetadata.ID));
ObjFile.WRITE(
  STRSUBSTNO(
    '    LOCAL PROCEDURE OnOpenPage%1%2@%3(VAR Rec@1000000000 : Record %4);',
    PageMetadata.ID,DELCHR(PageMetadata.Name,'=',' ,.;:-+*~°#!"§$%&/\|(){}[]<>'),
    1000000000 + PageMetadata.ID,PageMetadata.SourceTable));
ObjFile.WRITE('    VAR');
ObjFile.WRITE('      SysFunctions@1000000001 : Codeunit 50000;');
ObjFile.WRITE('      RecRef@1000000002 : RecordRef;');
ObjFile.WRITE('    BEGIN');
ObjFile.WRITE('      RecRef.GETTABLE(Rec);');
ObjFile.WRITE('      SysFunctions.LogPageExecution(RecRef);');
ObjFile.WRITE('      RecRef.SETTABLE(Rec);');
ObjFile.WRITE('    END;');
ObjFile.WRITE('');

LOCAL WriteObjFooter()
ObjFile.WRITE('    BEGIN');
ObjFile.WRITE('    {');
ObjFile.WRITE(
  STRSUBSTNO('      %1 TL Object created.',FORMAT(TODAY,0,'<Year4,4>-<Month,2>-<Day,2>')));
ObjFile.WRITE('');
ObjFile.WRITE('      Library for Page Event Subscribers');
ObjFile.WRITE('      Don''t place any C/AL code here! - Only external function calls allowed!');
ObjFile.WRITE('');
ObjFile.WRITE('      To recreate this Codeunit, run Codeunit 50010 "Recreate Page Events".');
ObjFile.WRITE('    }');
ObjFile.WRITE('    END.');
ObjFile.WRITE('  }');
ObjFile.WRITE('}');
ObjFile.WRITE('');