Dynamics AX Blog - Seite 35

SID für einen Active-Directory-User auslesen

Wer schon einmal eine Applikation inkl. Datenbank von einer Netzwerk-Domäne in eine andere übertragen hat, der kennt vielleicht die Situation. Man hat die Applikation und die Datenbank eingerichtet, kann sich in Dynamics AX aber nicht anmelden und erhält die Fehlermeldung:

You are not recognized user of Dynamics AX. Please contact your system administrator

Die Ursache dafür ist, daß in der Tabelle UserInfo - das ist jene Tabelle wo die AD-Benutzer verwaltet werden - natürlich noch die Benutzer der Ursprungsdomäne hinterlegt sind. Im einfachsten Fall ändert man in dieser Tabelle den Eintrag für den Administrator, indem man die Felder NetworkDomain, NetworkAlias und SID entsprechend ändert. NetworkDomain und NetworkAlias sind selbsterklärend, woher bekommt man aber die SID?

Eine einfache Internet-Recherche nach "GET SID" liefert einige Möglichkeiten, weniger bekannt ist aber, daß auch Dynamics AX 2009 selbst eine Methode zur Verfügung stellt, um die SID für einen Benutzer auszulesen.

Jetzt braucht man also nur noch ein anderes, bereits lauffähiges AX, wo man sich anmelden und den Job absetzen kann ;-)

static void getUserSid(Args _args)
{
    ;
    info(new xAxaptaUsermanager().getUserSid('h.schweda', 'schweda.net'));
}

 
 

Bearbeiten von Formularfeldern beschränken II

Sollen in einem Formular nur bestimmte Felder zur Bearbeitung freigegeben sein, kann man die Eigenschaft allowEdit sämtlicher Felder der DataSource der Tabelle entsprechend umsetzen.

Einfacher geht’s mit folgendem Codebeispiel, welches in der init-Methode der DataSource eingebunden wurde und - im konkreten Fall in der Tabelle SalesLine - nur bei einem einzigen Feld die Bearbeitung erlaubt.

Im Gegensatz zu einem früher veröffentlichten Beitrag mit dem gleichen Thema werden bei diesem Codebeispiel auch Array-Felder korrekt berücksichtigt.

public void init()
{
    FormDataObject  fdo;
    int             f;
    SysDictTable    sysDictTable;
    MapEnumerator   fdoMapEnumerator;
    ;
    sysDictTable = new SysDictTable(tablenum(SalesLine));
    for(f=1;f<=sysDictTable.fieldCnt();f++)
    {
        fdoMapEnumerator = new MapEnumerator(formDataSourceArrayFieldExtObjects(salesLine_ds, sysDictTable.fieldCnt2Id(f)));
        while (fdoMapEnumerator.moveNext())
        {
            fdo = fdoMapEnumerator.currentValue();
            if(fdo)
            {
                fdo.allowEdit(false);
            }
        }
    }

    fdo = salesLine_ds.object(fieldnum(SalesLine, QtyOrdered));
    fdo.allowEdit(true);
}

Getestet in Dynamics AX 2009


 
 

Datensatzvorlagen ermitteln

Wer einmal in die Verlegenheit kommt, ermitteln zu müssen ob für eine bestimmte Tabelle Datensatzvorlagen vorhanden sind, für den kann folgendes Code-Beispiel hilfreich sein.

Im Beispiel wird ermittelt, wieviele Benutzer- bzw. Unternehmensvorlagen es für die Tabelle InventTable gibt und ob der aktuelle Benutzer sich den Vorlagendialog anzeigen lässt, wenn er/sie einen neuen Artikel anlegt.

static void SysRecordTemplatesActive(Args _args)
{
    tableId tableId = tableNum(inventTable);
    common common = new sysdictTable(tableId).makeRecord();
    SysRecordTemplateStorageUser storageUser       = SysRecordTemplateStorage::newCommon(common, SysRecordTemplateType::User);
    SysRecordTemplateStorageCompany storageCompany = SysRecordTemplateStorage::newCommon(common, SysRecordTemplateType::Company);
    sysRecordTemplateSelect sysRecordTemplateSelect;
    container userTemplates;
    container companyTemplates;
    ;
    // Liste der Vorlagen
    userTemplates = storageUser.get();
    info(strFmt("Anzahl Benutzervorlagen für Tabelle %1: %2", new sysdictTable(tableId).label(),
                                                              conLen(userTemplates)));

    companyTemplates = storageCompany.get();
    info(strFmt("Anzahl Unternehmensvorlagen für Tabelle %1: %2", new sysdictTable(tableId).label(), 
                                                                  conLen(companyTemplates)));
    
    // Soll der aktive Benutzer nach Vorlagen gefragt werden?
    sysRecordTemplateSelect = SysRecordTemplateSelect::newTableId(tableId);
    sysRecordTemplateSelect.load();
    
    info(strFmt("Datensatzvorlagen für die Tabelle %1 in Verwendung: %2", new sysdictTable(tableId).label(),
                                                                          enum2str(sysRecordTemplateSelect.parmPrompt()))); 
}

 
 

Berichte lassen sich nicht über die Stapelverarbeitung ausführen

Wenn bei einem Benutzer der Register Stapel beim Aufruf eines Berichtes nicht angezeigt wird, kann dies u.U. daran liegen, daß der Benutzer keine oder unzureichende Berechtigung für den Sicherheitsschlüssel Stapelverarbeitungsbericht (SecurityKey BatchReport) hat.


 


 
 

Projekte nach einem bestimmten Objekt durchsuchen

Nachstehender Job durchsucht alle Projekte nach einem bestimmten Element des AOT.

Dafür wird ein Dialog verwendet, wo man lediglich den Namen und den Typ des zu suchenden Elementes angeben muss. Außerdem kann man noch einstellen, ob auch die privaten Projektknoten durchsucht werden sollen.

static void findObjectWithinProjects(Args _args)
{
    UtilElementType utilElementType        = UtilElementType::Table;
    Name            objectName             = 'custTable';
    boolean         includePrivateProjects = false;
    Dialog          dialog;
    DialogField     df_objectName;
    DialogField     df_utilElementType;
    DialogField     df_privateProjects;
    container       conProjects;
    int             c;
    TreeNode                treeNodeRoot;
    SysOperationProgress    sysOperationProgress;
    UtilElementType         utilElementTypeSelection;    

    #Aot
    #TreeNodeSysNodeType
    #AviFiles
    #define.objectNameField("Name of object")
    #define.utilElementTypeField("Type of object")

    void findChildNodes(TreeNode _treeNodeParent, ProjectNode _projectNode, str _objectName)
    {
        TreeNode            treeNode;
        TreeNodeIterator    treeNodeIterator;

        ; 
        treeNodeIterator = _treeNodeParent.AOTiterator();
        treeNode = treeNodeIterator.next();
        while (treeNode)
        {
            if (treeNode.AOTgetNodeType() == #NT_PROJECT_GROUP)
            {
                findChildNodes(treeNode, _projectNode, _objectName);
            }
            else if (treeNode.AOTname() like _objectName)
            {
                utilElementTypeSelection = str2enum(utilElementTypeSelection, enum2str(utilElementType)); 
                if (!utilElementType || treeNode.applObjectType() == utilElementTypeSelection)
                {
                    if (!confind(conProjects, _projectNode.AOTname()))
                    {
                        conProjects = conins(conProjects, conlen(conProjects)+1, _projectNode.AOTname());
                    } 
                    return;
                }
            } 
            treeNode.treeNodeRelease();
            treeNode = treeNodeIterator.next();
        }
    }
    void loopProjectsNode(TreeNode _treeNode)
    {
        ProjectNode projectNode;
        TreeNode treeNodeProject; 

        if (_treeNode)
        {
            treeNodeProject = _treeNode.AOTfirstChild();
            while (treeNodeProject)
            {
                projectNode = treeNodeProject; 
                sysOperationProgress.setText(projectNode.name()); 
                findChildNodes(projectNode.loadForInspection(), treeNodeProject, objectName); 
                treeNodeProject = treeNodeProject.AOTnextSibling();
            }
        }
    }
    ; 
    dialog = new Dialog();
    dialog.caption("Find projects containing specific object");
    df_objectName      = dialog.addField(Types::String, #objectNameField);
    df_utilElementType = dialog.addField(typeid(UtilElementType), #utilElementTypeField);
    df_privateProjects = dialog.addField(typeid(NoYesId), "Include Private projects"); 
    df_objectName.value(objectName);
    df_utilElementType.value(utilElementType);
    df_privateProjects.value(includePrivateProjects); 
    if( !dialog.run())
    {
        return;
    } 
    objectName             = df_objectName.value();
    utilElementType        = df_utilElementType.value();
    includePrivateProjects = df_privateProjects.value(); 
    if (objectName == '*' || objectName == '')
    {
        throw error(strfmt("@SYS26332", #objectNameField));
    } 
    setprefix(strfmt("Projects containing %1 '%2'", utilElementType, objectName)); 

    startLengthyOperation(); 

    sysOperationProgress = new SysOperationProgress();
    sysOperationProgress.setCaption("Searching");
    sysOperationProgress.setAnimation(#AviSearch); 

    // Private projects
    if(includePrivateProjects)
    {
        loopProjectsNode(SysTreeNode::getPrivateProject());
    }
    // Shared projects
    loopProjectsNode(SysTreeNode::getSharedProject()); 
    sysOperationProgress.kill();
    endLengthyOperation(); 

    // List projects
    for(c=1;c<=conlen(conProjects);c++)
    {
        info(conpeek(conProjects, c));
    }
}

Wer eine etwas komfortablere Möglichkeit vorzieht, der kann sich bei Firma Loncar Technologies Inc. ein entsprechendes XPO herunterladen und ins AX einspielen. Auf Basis dieses XPOs ist auch obiger Job entstanden.

https://www.loncartechnologies.com/download.php


 
 

Berechtigung eines Benutzers für einen Sicherheitsschlüssel abfragen

Mit diesem Stückchen Code kann man in Dynamics AX prüfen, welche Berechtigung ein Benutzer für einen bestimmten Sicherheitsschlüssel (Securitykey) hat.

static void GetSecurityKeyAccess4User(Args _args)
{
    Dictionary          Dictionary = new Dictionary();
    securityKeyId       securityKeyId;
    SecurityKeySet      securityKeySet = new SecurityKeySet();
    UserId              userId = 'user1';
    SelectableDataArea  dataArea = 'ceu';
    AccessType          accessType;
    ;

    securityKeyId = Dictionary.securityKeyName2Id("BatchReport");

    securityKeySet.loadUserRights(userId, dataArea);

    AccessType = securityKeySet.access(securityKeyId);

    info(enum2str(AccessType));
}

 
 

AX 2012: Having-Clause über addHavingFilter

Ein neues Feature von Dynamics AX 2012 ist, daß man nun bei einem Query auch eine HAVING-Clause hinzufügen kann.

Diese Bedingung dient dazu, berechnete Werte einer GROUP BY-Clause in der WHERE-Clause berücksichtigen zu können. Dieses Feature habe ich in der Vergangenheit vor allem dazu gerne verwendet, wenn es darum ging über eine SQL-Abfrage doppelte (bzw. vielfache) Datensätze in einer Tabelle zu finden. In den bisherigen Versionen von Dynamics AX war dieses Unterfangen über X++ nur etwas umständlich abzubilden.


 
 
Seiten « 1 ... 32 33 34 35 36 37 38 ... 53 » 

 

 
 
 
Beiträge des aktuellen Monats
Juni 2025
MoDiMiDoFrSaSo
 1
2345678
9101112131415
16171819202122
23242526272829
30 
 
© 2006-2025 Heinz Schweda | Impressum | Kontakt | English version | Mobile Version
Diese Webseite verwendet Cookies, um Benutzern einen besseren Service anzubieten. Wenn Sie weiterhin auf der Seite bleiben, stimmen Sie der Verwendung von Cookies zu.  Mehr dazu