Dynamics AX Blog - Dynamics AX 2009 - Beiträge vom November 2009

RSS-Feed dieser Version
Alle Felder einer Tabelle auflisten
22.11.2009Microsoft Dynamics AX (Axapta)
Kurzes Codebeispiel, wie man alle Felder einer Tabelle auflistet: static void ListFieldOfTable(Args _args)
{ dictTable dictTable; int currFieldId = 0; counter c = 0; ; dictTable = new dictTable(tableNum(custtable)); do { currFieldId = dictTable.fieldNext(currFieldId); info(dictTable.fieldName(currFieldId)); c++; } while (c < dictTable.fieldCnt()); }
|
Arbeiten mit dem aufrufenden Objekt einer Form (Caller)Nachstehende Methode enthält einige Snippets, die in einem Formular verwendet werden können, um in Dynamics AX diverse Funktionen/Methoden des Aufrufenden Objektes aufzurufen. Ändert man element.args() auf z.b. _args und übergibt der Methode diese als Parameter, kann die selbe Logik auch aus einer Klasse heraus verwendet werden. void workWithCallingRecord() { common common; object object; formDataSource formDataSource; formRun formRun; inventDim inventDim; salesTable salesTable; int i; ; // Call method from calling record if( element.args() && element.args().record() ) { common = element.args().record(); if(common.isFormDataSource()) { info(tableId2Name(common.TableId)); if(formDataSourceHasMethod(common.dataSource(), identifierStr("someMethod"))) { object = common.dataSource(); object.someMethod(); } } } // Call method from calling form if(element.args() && element.args().caller() && element.args().caller().handle() == className2Id('formRun')) { formRun = element.args().caller(); if(sysFormRun::hasMethod(formRun, identifierStr("someFormMethod"))) { object = formRun; object.someFormMethod(); } } // Get value from calling record if( element.args() && element.args().record() ) { common = element.args().record(); if(common.TableId == tableNum(salesTable)) { info(common.(fieldNum(salesTable, salesId))); } } // Get value from calling datasource (form with multiple datasources) if(element.args() && element.args().caller() && element.args().caller().handle() == className2Id('formRun')) { formRun = element.args().caller(); for (i = 0; i <= formRun.dataSourceCount(); i++) { formDataSource = formRun.datasource(i); if (formDataSource && formDataSource.table() == tablenum(inventDim)) // Search for specific table { inventDim = formDataSource.cursor(); break; } } if(inventDim) { info(inventDim.InventLocationId); } } // Change data in calling datasource if(element.args() && element.args().caller() && element.args().caller().handle() == className2Id('formRun')) { formRun = element.args().caller(); for (i = 0; i <= formRun.dataSourceCount(); i++) { formDataSource = formRun.datasource(i); if (formDataSource && formDataSource.table() == tablenum(salesTable)) // Search for specific table { salesTable = formDataSource.cursor(); break; } } if(salesTable) { // Update data salesTable.PurchOrderFormNum = "Some value"; salesTable.update(); } } // Refresh calling datasource if( element.args() && element.args().record() ) { common = element.args().record(); if(common.isFormDataSource()) { formDataSource = common.dataSource(); formDataSource.research(true); } } } |
Dynamics AX mit einem bestimmten Windowslogin starten
08.11.2009Microsoft Dynamics AX (Axapta)
Gegenüber früheren Versionen von Dynamics AX hat man - dank Integration des Active Directories - in AX 2009 kaum Möglichkeiten, die Anwendung als ein bestimmter Benutzer zu starten. Gerade dies ist aber notwendig, wenn man z.B. Änderungen in den Sicherheitseinstellungen/Berechtigungen überprüfen möchte. Für solche Fälle habe ich mir eine Batch-Datei (*.bat) geschrieben, die mir eine lokale AX-Installation mit einem bestimmten Windows-Login startet. Diese Batch-Datei öffnet ein Windows-Kommandozeilen-Fenster in welchem man zur Eingabe des Windows-Passworts aufgefordert wird. runas /user:domain\username "C:\Programme\Microsoft Dynamics AX\50\Client\Bin\Ax32.exe "C:\Programme\Microsoft Dynamics AX\50\MyConfigurationfile.axc"" Wenn man diese Befehlszeile direkt in der Eingabeaufforderung eingeben will, muss man den Befehl wie folgt leicht abwandeln: runas /user:domain\username "C:\Programme\Microsoft Dynamics AX\50\Client\Bin\Ax32.exe \"C:\Programme\Microsoft Dynamics AX\50\MyConfigurationfile.axc\"" Muss man ausser der Konfigurationsdatei noch weitere Parameter übergeben, kann man die Batch-Datei wie folgt erweitern: runas /user:domain\username "C:\Programme\Microsoft Dynamics AX\50\Client\Bin\Ax32.exe "C:\Programme\Microsoft Dynamics AX\50\MyConfigurationfile.axc" -aol=var -aolcode=j+eA4566458bsZReSO1Q==" Der selbe Befehl sähe, wenn man ihn über die Eingabeaufforderung eingeben wollte, wie folgt aus: runas /user:domain\username "C:\Programme\Microsoft Dynamics AX\50\Client\Bin\Ax32.exe \"C:\Programme\Microsoft Dynamics AX\50\MyConfigurationfile.axc\" -aol=var -aolcode=j+eA4566458bsZReSO1Q==" Alternativ dazu kann man sich auch der hier beschriebenen Lösung bedienen. Übrigens: Sollte die Konfigurationsdatei auf einem Netzlaufwerk liegen, so sollte man bei der Angabe des Dateipfades nicht dessen Laufwerksbuchstaben verwenden, sondern den vollen UNC-Pfad. Denn möglicherweise hat der Benutzer, mit dem ich die Applikation starten möchte, den einzelnen Netzwerklaufwerken andere Laufwerksbuchstaben zugewiesen als man selbst ;-) |
Geänderte oder neue Methoden von Klassen auflisten
01.11.2009Microsoft Dynamics AX (Axapta)
Im folgenden findet ihr einen Job, der in einer adaptierten Applikation alle Methoden von Klassen auflistet, die entweder erstellt wurden oder gegenüber dem Standard verändert wurden. static void ListChangedOrCreatedClassesMethods(Args _args) { SysDictClass SysDictClass; treeNode treeNode; treeNode treeNodeBase; treeNode treeNodeCustom; treeNode treeNodeClasses; UtilEntryLevel CurrentUtilEntryLevel; #AOT ; treeNodeClasses = TreeNode::findNode(#ClassesPath + #AOTRootPath); treeNodeClasses = treeNodeClasses.AOTfirstChild(); SysDictClass = new SysDictClass((treeNodeClasses.applObjectId())); setPrefix('List changed/created classes'); while(treeNodeClasses) { SysDictClass = new SysDictClass((treeNodeClasses.applObjectId())); setPrefix(SysDictClass.name()); treeNode = TreeNode::findNode(#ClassesPath + #AOTRootPath + SysDictClass.name() + #AOTRootPath); treeNode = treeNode.AOTfirstChild(); while(treeNode) { treeNodeBase = null; treeNodeCustom = null; // Partner if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::bup); if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::bus); // Solutions if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sl3); if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sl2); if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sl1); // Hotfix if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::hfx); // Microsoft if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::glp); if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::gls); if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::syp); if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sys); // Custom layers if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::vap); CurrentUtilEntryLevel = UtilEntryLevel::vap; } if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::var); CurrentUtilEntryLevel = UtilEntryLevel::var; } if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::cup); CurrentUtilEntryLevel = UtilEntryLevel::cup; } if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::cus); CurrentUtilEntryLevel = UtilEntryLevel::cus; } if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::usp); CurrentUtilEntryLevel = UtilEntryLevel::usp; } if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::usr); CurrentUtilEntryLevel = UtilEntryLevel::usr; } // Changed methods if(treeNodeBase) { if( treeNodeBase.AOTgetSource() != treeNode.AOTgetSource()) { warning(strFmt( "Method '%1' was changed in layer '%2'.", treeNode.treeNodeName(), enum2str(CurrentUtilEntryLevel))); } } // New created methods if( !treeNodeBase) { info(strFmt( "Method '%1' was created in layer '%2'.", treeNode.treeNodeName(), enum2str(CurrentUtilEntryLevel))); } treeNode = treeNode.AOTnextSibling(); } treeNodeClasses = treeNodeClasses.AOTnextSibling(); } } Ein ähnlicher Job der prinzipiell das Gleiche erledigt, allerdings für alle Tabellenmethoden, ist hier zu finden. |
Geänderte oder neue Methoden von Tabellen auflisten
01.11.2009Microsoft Dynamics AX (Axapta)
Im folgenden findet ihr einen Job, der in einer adaptierten AX 2009er-Applikation alle Tabellenmethoden auflistet, die entweder erstellt wurden oder gegenüber dem Standard verändert wurden. static void ListChangedOrCreatedTableMethods(Args _args) { SysDictTable SysDictTable; treeNode treeNode; treeNode treeNodeBase; treeNode treeNodeCustom; treeNode treeNodeTables; UtilEntryLevel CurrentUtilEntryLevel; #AOT ; treeNodeTables = TreeNode::findNode(#TablesPath + #AOTRootPath); treeNodeTables = treeNodeTables.AOTfirstChild(); setPrefix('List changed/created tablemethods'); while(treeNodeTables) { SysDictTable = SysDictTable::newTableId(tableName2Id(treeNodeTables.treeNodeName())); setPrefix(SysDictTable.name()); treeNode = TreeNode::findNode(#TablesPath + #AOTRootPath + SysDictTable.name() + #AOTRootPath + "Methods"); treeNode = treeNode.AOTfirstChild(); while(treeNode) { treeNodeBase = null; treeNodeCustom = null; // Partner if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::bup); if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::bus); // Solutions if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sl3); if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sl2); if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sl1); // Hotfix if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::hfx); // Microsoft if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::glp); if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::gls); if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::syp); if( !treeNodeBase) treeNodeBase = treeNode.getNodeInLayer(UtilEntryLevel::sys); // Custom layers if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::vap); CurrentUtilEntryLevel = UtilEntryLevel::vap; } if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::var); CurrentUtilEntryLevel = UtilEntryLevel::var; } if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::cup); CurrentUtilEntryLevel = UtilEntryLevel::cup; } if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::cus); CurrentUtilEntryLevel = UtilEntryLevel::cus; } if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::usp); CurrentUtilEntryLevel = UtilEntryLevel::usp; } if( !treeNodeCustom) { treeNodeCustom = treeNode.getNodeInLayer(UtilEntryLevel::usr); CurrentUtilEntryLevel = UtilEntryLevel::usr; } // Changed methods if(treeNodeBase) { if( treeNodeBase.AOTgetSource() != treeNode.AOTgetSource()) { warning(strFmt( "Method '%1' was changed in layer '%2'.", treeNode.treeNodeName(), enum2str(CurrentUtilEntryLevel))); } } // New created methods if( !treeNodeBase) { info(strFmt( "Method '%1' was created in layer '%2'.", treeNode.treeNodeName(), enum2str(CurrentUtilEntryLevel))); } treeNode = treeNode.AOTnextSibling(); } treeNodeTables = treeNodeTables.AOTnextSibling(); } } Ein ähnlicher Job der prinzipiell das Gleiche erledigt, allerdings für alle Klassenmethoden, ist hier zu finden. |
|
|
|
|
|
|
Daß man einen Mandanten/Unternehmen duplizieren kann, ist bekannt. Die Erfahrung der vergangenen Wochen hat mich in dem Zusammenhang folgendes gelehrt:
Um sicherzustellen, daß man der einzige Benutzer im System ist, sollte man alle anderen deaktivieren.
Außerdem sollte man vor dem Kopiervorgang ein Datenbank-Backup anlegen und nach der erfolgten Aktion den Quell- und Zielmandant hinsichltich doppelter Datensätze vergleichen. Hierfür kann man sich der Funktion "Anzahl der Datensätze" bedienen.