Site icon DAXRunBase

Finding objects marked for deletion

During our code upgrade we have identified that the SysDeletedObjects configuration keys were still turned on. Also many DEL_-prefixed fields were being referred or used in various places. We had to come up with a way for finding objects marked for deletion.

The documentation gives you an idea of what to do with such elements.

https://docs.microsoft.com/en-us/dynamicsax-2012/appuser-itpro/delete-obsolete-application-objects

https://docs.microsoft.com/en-us/dynamicsax-2012/developer/best-practices-tables

The following job can produce a CSV file, which contains everything with the DEL_ prefix, their table property and layer information:

static void findDelObjectsinAOTTree(Args _args)
{
    #Properties
    #AOT
    int row;
 
    xRefReferences xRefReferences;
    xRefPaths      xrefPath;
    xRefNames      xrefNames;
    str 4          strMatch = 'DEL_';
    str 100        configKey;
    TreeNode       treeNode;
    TreeNodeIterator        treeNodeIterator;
    TreeNodeTraverser       treeNodeTraverser;
    str 30                  layerObject;
 
    int             i;
    SetEnumerator   setEnumerator;
    Set             layers;
    UtilEntryLevel  layerEnum;
 
    #File
    CommaTextIo commaTextIo;
    FileIOPermission permission;
    CustTable custTable;
    str fileName = @"D:\Temp\delobjectsinAOT.csv";
 
    MenuFunction                    mf;
 
    void findNodes(TreeNode _treeNodeLoc, boolean traverse = false)
    {
        treeNode = TreeNode::findNode(_treeNodeLoc.treeNodePath());
 
        treeNodeIterator = treeNode.AOTiterator();
 
        if (traverse)
        {
            treeNodeTraverser    = new TreeNodeTraverser(TreeNode::findNode(_treeNodeLoc.treeNodePath()));
 
            while (treeNodeTraverser.next())
            {
 
                treeNode = treeNodeTraverser.currentNode();
 
                if (treeNode && findProperty(treeNode.AOTgetProperties(), #PropertyName))
                {
                    if (subStr(treeNode.AOTgetProperty(#PropertyName), 0 , strLen(strMatch)) == strMatch)
                    {
                        if (treeNode && treeNode.TreeNodeType().isLayerAware())
                        {
                            //layerObject     = treeNode.AOTLayers().toString();
                            layers = treeNode.AOTLayers();
                            setEnumerator = layers.getEnumerator();
                            layerObject = '';
                            while (setEnumerator.moveNext())
                            {
                                layerEnum = SetEnumerator.current();
                                layerObject += enum2str(layerEnum);
                            }
                            setEnumerator = null;
                        }
 
                        if (findProperty(treeNode.AOTgetProperties(), #PropertyConfigurationKey))
                        {
                            commaTextIo.write(treeNode.treeNodePath(), treeNode.AOTgetProperty(#PropertyConfigurationKey), layerObject) ;
                            layerObject = '';
                        }
                        else
                        {
                            if (treeNode.AOTObjectNode())
                            {
                                commaTextIo.write(treeNode.treeNodePath(), '', layerObject) ;
                                layerObject = '';
                            }
                        }
                    }
                }
            }
        }
        else
        {
            while (treeNode)
            {
                if (treeNode && findProperty(treeNode.AOTgetProperties(), #PropertyName))
                {
                    if (treeNode && treeNode.TreeNodeType().isLayerAware())
                    {
                        //layerObject     = treeNode.AOTLayers().toString();
                        layers = treeNode.AOTLayers();
                        setEnumerator = layers.getEnumerator();
                        layerObject = '';
                        while (setEnumerator.moveNext())
                        {
                            layerEnum = SetEnumerator.current();
                            layerObject += enum2str(layerEnum);
                        }
                        setEnumerator = null;
                    }
 
                    if (subStr(treeNode.AOTgetProperty(#PropertyName), 0 , strLen(strMatch)) == strMatch)
                    {
                        if (findProperty(treeNode.AOTgetProperties(), #PropertyConfigurationKey))
                        {
                            commaTextIo.write(treeNode.treeNodePath(), treeNode.AOTgetProperty(#PropertyConfigurationKey), layerObject) ;
                            layerObject = '';
                        }
                        else
                        {
                            if (treeNode.AOTObjectNode())
                            {
                                commaTextIo.write(treeNode.treeNodePath(), '', layerObject) ;
                                layerObject = '';
                            }
                        }
                    }
                }
 
                treeNode = treeNodeIterator.next();
            }
        }
 
        treeNode = null;
        treeNodeIterator = null;
        treeNodeTraverser = null;
    }
 
    if (!isRunningOnServer())
    {
        mf = ClassFactory::makeObjectOnServer(classNum(MenuFunction));
        mf.objectType(MenuItemObjectType::Job);
        mf.object(funcName());
        mf.runOn(ClassRunMode::Server);
        mf.run();
       
        return;
    }
    else
    {
        info('running code on server side');
    }
 
    permission = new FileIOPermission(fileName,#io_write);
    permission.assert();
    commaTextIo = new CommaTextIo(fileName,#io_write);
    commaTextIo.outFieldDelimiter('|');
 
    treeNode = TreeNode::findNode(#AOTRootPath);
 
    treeNodeIterator = treeNode.AOTiterator();
    TreeNode = treeNodeIterator.next();
 
    findNodes(TreeNode::findNode(#TablesPath), true);
    findNodes(TreeNode::findNode(#ExtendedDataTypesPath));
    findNodes(TreeNode::findNode(#BaseEnumsPath));
    findNodes(TreeNode::findNode(#ViewsPath), true);
    findNodes(TreeNode::findNode(#TableMapsPath), true);
    findNodes(TreeNode::findNode(#FormsPath));
    findNodes(TreeNode::findNode(#ClassesPath));
    findNodes(TreeNode::findNode(#MenusPath));
    findNodes(TreeNode::findNode(#MenuItemsDisplayPath));
    findNodes(TreeNode::findNode(#MenuItemsOutputPath));
    findNodes(TreeNode::findNode(#MenuItemsActionPath));
    findNodes(TreeNode::findNode(#SecPrivilegesPath));
 
    info('Export has finished');
 
}

The final results looks like this after executing the job for finding objects marked for deletion:

Exit mobile version