Autodesk.Internal.Windows.HideableDialogSettingsDictionary

Autodesk.Internal.Windows.HideableDialogSettingsDictionary

Jedimaster
Collaborator Collaborator
2,399 Views
13 Replies
Message 1 of 14

Autodesk.Internal.Windows.HideableDialogSettingsDictionary

Jedimaster
Collaborator
Collaborator

I have a batch routine written in vb.net that will process multiple drawing files. I need to disable some of the nuisance warning dialogs. They uses to be handled by HideWarningDialogs and MoreHideWarningDialogs,not any more. I know AutoCAD saves the settings in FixedProfile.aws. I tried coping the file from the network not an easy way to disable the dialogs.

 

From http://adndevblog.typepad.com/autocad/2013/07/disable-task-dialogs-programmatically.html I have found the  HideableDialogSettingsDictionary

 

Dim HideDic As Autodesk.Internal.Windows.HideableDialogSettingsDictionary = Autodesk.Windows.TaskDialog.HideableDialogSettingsDictionary

 

The following allows to get the value

HideDic.GetResult("MainFrame.CommandLineHideWindow")

 

The following allows you to edit an existing value. If you set to 0 it removes the override all together.

HideDic.SetResult("MainFrame.CommandLineHideWindow", 6)

 

I have tried HideDic.Add it requires the name sting and the the setting value  if I use the integer it says it cannot convert integer to Autodesk.Internal.Windows.HideableDialogSettings.

 

Thanks in advance into any insight.

0 Likes
Accepted solutions (1)
2,400 Views
13 Replies
Replies (13)
Message 2 of 14

Jedimaster
Collaborator
Collaborator

I Figured it out. You have to build the setting.

 

Dim CmdLin As New Autodesk.Internal.Windows.HideableDialogSettings
CmdLin.Id = "MainFrame.CommandLineHideWindow
CmdLin.Result = 6
HideDic.Add(CmdLin)

Autodesk.AutoCAD.Internal.Windows.ProfileManager.SaveHideableDialogSettingsDictionary()

0 Likes
Message 3 of 14

ActivistInvestor
Mentor
Mentor

@Jedimaster wrote:

I have a batch routine written in vb.net that will process multiple drawing files. I need to disable some of the nuisance warning dialogs. They uses to be handled by HideWarningDialogs and MoreHideWarningDialogs,not any more. I know AutoCAD saves the settings in FixedProfile.aws. I tried coping the file from the network not an easy way to disable the dialogs.

 

From http://adndevblog.typepad.com/autocad/2013/07/disable-task-dialogs-programmatically.html I have found the  HideableDialogSettingsDictionary

 

Dim HideDic As Autodesk.Internal.Windows.HideableDialogSettingsDictionary = Autodesk.Windows.TaskDialog.HideableDialogSettingsDictionary

 

The following allows to get the value

HideDic.GetResult("MainFrame.CommandLineHideWindow")

 

The following allows you to edit an existing value. If you set to 0 it removes the override all together.

HideDic.SetResult("MainFrame.CommandLineHideWindow", 6)

 

I have tried HideDic.Add it requires the name sting and the the setting value  if I use the integer it says it cannot convert integer to Autodesk.Internal.Windows.HideableDialogSettings.

 

Thanks in advance into any insight.


Add() requires a string key (which you can get from Autodesk.AutoCAD.Internal.AcadTaskDialogs), and an instance of a HideableDialogSettings object. You have to create a new instance of the class and set its properties, and pass that as the second argument to Add().

 

However, doing it that way is the most-difficult solution.

 

The easy solution is to set all of the 'nuisance' to be hidden through the UI, and then create a copy of FixedProfile.aws, and use that copy when you do batch processing (temporarily rename the current FixedProfile.aws and replace it with the copy that has all of the desired settings for the dialogs). Then do your batch processing, and when you're done just swap the FixedProfile.aws with the old one that's used for normal editing.

0 Likes
Message 4 of 14

ActivistInvestor
Mentor
Mentor

@Jedimaster wrote:

I Figured it out. You have to build the setting.

 

Dim CmdLin As New Autodesk.Internal.Windows.HideableDialogSettings
CmdLin.Id = "MainFrame.CommandLineHideWindow
CmdLin.Result = 6
HideDic.Add(CmdLin)

Autodesk.AutoCAD.Internal.Windows.ProfileManager.SaveHideableDialogSettingsDictionary()


You didn't figure it out, because every dialog requires a different value for the Result property, and they have different meanings.

 

For example, the Missing SHX Dialog can have two possible values for the Result property:

 

     1001:  Don't show the dialog, and prompt the user to select an alternate .SHX file for each missing SHX file.

     1002:  Don't show the dialog, and ignore missing SHX files.

 

Obviously, you wouldn't want AutoCAD to prompt for missing SHX files when you do batch processing, so for this dialog, the Result would have to be set to 1002, but the Result property value has different ranges for each hideable dialog, and each value has a different meaning, some (like the 1001 value for the Missing SHX File dialog) you can't use for batch processing. 

 

For each hideable dialog, the range of allowed values and the meaning of each allowed value is different.

 

So as I mentioned, rather than reverse-engineer the allowable range of values and the meaning of each, for the Result property of every hideable dialog, you can just set all of the dialogs to be hidden through the UI and then create a copy of FixedProfile.aws, and use that for batch processing.

 

 

0 Likes
Message 5 of 14

Jedimaster
Collaborator
Collaborator

I understand that this will not shut off all hideable dialog boxes. I also understand that I still have to retrieve information from FixedProfile.aws.

It is not a silver bullet, but I have solved for what I need right now, and the following works on my machine.

 

Dim HideDic As Autodesk.Internal.Windows.HideableDialogSettingsDictionary = Autodesk.Windows.TaskDialog.HideableDialogSettingsDictionary

' Check to make sure the item does not already exist
If HideDic.GetResult("MainFrame.CommandLineHideWindow") = 0 Then

 

  ' Build the HideableDialogSettings from FixedProfile.aws.
  Dim CmdLin As New Autodesk.Internal.Windows.HideableDialogSettings
  CmdLin.Application = ""
  CmdLin.Id = "MainFrame.CommandLineHideWindow"     'Here's the string looking for
  CmdLin.Title = "Command Line – Close Window"
  CmdLin.Category = "Command Line"
  CmdLin.Result = 6

 

  ' Create Entry
  HideDic.Add(CmdLin)  'There are 3 acceptable versions syntax to add 
End If

 

'Save the dictionary

Autodesk.AutoCAD.Internal.Windows.ProfileManager.SaveHideableDialogSettingsDictionary()

 

If you know of a universal or a simpler solution I would love to know.

 

0 Likes
Message 6 of 14

ActivistInvestor
Mentor
Mentor
Accepted solution

@Jedimaster wrote:

I understand that this will not shut off all hideable dialog boxes. I also understand that I still have to retrieve information from FixedProfile.aws.

It is not a silver bullet, but I have solved for what I need right now, and the following works on my machine.

 

Autodesk.AutoCAD.Internal.Windows.ProfileManager.SaveHideableDialogSettingsDictionary()

 

If you know of a universal or a simpler solution I would love to know.

 


The simplest solution I can think if is the one I described above. Get the dialogs to appear while using AutoCAD, and then tell it to hide them.

 

Then, make a copy of FixedProfile.aws, and use that copy when you do batch processing. It can't be any more simpler than that.

0 Likes
Message 7 of 14

_Serge
Contributor
Contributor

I know the subject has been marked as solved but I would like to provide additional information. 3 days ago, I wrote something on Fenton’s page. I don’t except any comments since the page was written in 2013. I’ll take some key elements here.

 

All the information you need to accomplish your goal is in the AcTaskDialogs.dll file that is located in the acad.exe directory. This file is only a resources file. It contains a dictionary which contains 5 embedded file. The embedded file you need is hideabletaskdialogs.baml (hereafter the BAML file or simply BAML). It is a XML compatible file.

 

The ideal way to read the BAML is programmatically because the content changes from one version of AutoCAD to another (and so is the FixedProfile.aws file). For example, in AutoCAD 2010, only 94 dialog boxes where listed. In AutoCAD 2021, it’s 149. To avoid entering in the technical details and to make a long story short, to access this BAML file, I recommend you to use ILSpy.exe which is available from the Microsoft store. From the ILSPy window, you can easily view and copy the contents of the BAML. You could then create your own embedded resource file in your VB project. It’s faster but the only problem, as mentioned, you will need a different BAML for every version of AutoCAD you have to support.

 

Please find a short excerpt from the BAML file (the localized one):

 

 

 

 

 

<ResourceDictionary ... >
   ...
    <td:TaskDialog x:Key="MainFrame.CommandLineHideWindow" 
      x:Uid="TaskDialog_1" AllowDialogCancellation="True" 
      VerificationHandlerData="Command Line" 
      VerificationText="Always close the Command Line window" 
      DefaultButton="6" ... / >

   ...

   <td:TaskDialog x:Key="MText.UnsavedChanges" 
      x:Uid="TaskDialog_3" AllowDialogCancellation="True" 
      VerificationHandlerData="Multiline Text" 
      VerificationText="Always perform my current choice" 
      DefaultButton="1001" ... / >

 

 

 

 

 

As we can foresee, the DefaultButton attribute may take one of the following values: 1, 5, 6, 7, 8, 1001, 1002 and 2001. I am not sure that the value 6 constitutes the universal panacea, but so much the better if it is the case. Since today I don't have enough drawings to get these dialogs and prove that the DefaultButton is also the value that avoids their opening, I can only speculate. Feeding the HideableDialogSettingsDictionary dictionary with the 149 possible dialogs works very well and the FixedProfile.aws is properly updated.

 

I will appreciate any comments.

 

0 Likes
Message 8 of 14

SENL1362
Advisor
Advisor

Thanks for pointing us in this direction.

Loading the Acad release dependent AcTaskDialogs.dll resources seems to be not that difficult and can be done without ILSpy.

[CommandMethod("TestLoadAndStoreTaskDialogResources")] 
        public static void LoadAndStoreTaskDialogResources()
        {
            Document doc = null;
            Editor ed = null;
            Database db = null;

            var acTaskDialogsFilename = "AcTaskDialogs.dll";
            var outPath = Path.GetTempPath();  //Store output XAML Textfiles

            try
            {
                doc = AcadApp.DocumentManager.MdiActiveDocument;
                ed = doc.Editor;
                db = doc.Database;

                var acadArgs = Environment.GetCommandLineArgs();            //C:\program..\acad.exe /product [product code]
                var acadExePathname = acadArgs[0];                          //C:\Program Files\Autodesk\AutoCAD 2021\acad.exe
                var acadExePath = Path.GetDirectoryName(acadExePathname);   //C:\Program Files\Autodesk\AutoCAD 2021
                var acTaskDialogsPathname = Path.Combine(acadExePath, acTaskDialogsFilename);

                ed.WriteMessage($"Loading resources from: {acTaskDialogsPathname}\n");
                var acTaskDialogAssy = Assembly.LoadFile(acTaskDialogsPathname);
                using (var acTaskDialogStrm = acTaskDialogAssy.GetManifestResourceStream(acTaskDialogAssy.GetName().Name + ".g.resources"))
                {
                    using (var acTaskDialogResRdr = new ResourceReader(acTaskDialogStrm))
                    {
                        foreach (DictionaryEntry acTaskRes in acTaskDialogResRdr)
                        {
                            var resFilename = acTaskRes.Key.ToString();
                            ed.WriteMessage($"\t Extract: {resFilename}\n");
                            //Let's try all resources, not only hideabletaskdialogs.baml 
                            if (resFilename.EndsWith(".BAML", StringComparison.OrdinalIgnoreCase))
                            {
                                var acTaskXamlSb = new StringBuilder();
                                XmlWriterSettings xmlWrSet = new XmlWriterSettings
                                {
                                    Indent = true,
                                    OmitXmlDeclaration = false
                                };
                                var xmlWr = XmlWriter.Create(acTaskXamlSb, xmlWrSet);
                                var xmlSerMan = new XamlDesignerSerializationManager(xmlWr);
                                using (var acTaskBml = new Baml2006Reader((Stream)acTaskRes.Value))
                                {
                                    try  //catches: Source property has already been set on ResourceDictionary
                                    {
                                        using (var acTaskXaml = new XamlObjectWriter(acTaskBml.SchemaContext))
                                        {
                                            while (acTaskBml.Read())
                                            {
                                                acTaskXaml.WriteNode(acTaskBml);
                                            }

                                            ed.WriteMessage($"\t Convert to XAML, waiting....\n");
                                            System.Windows.Markup.XamlWriter.Save(acTaskXaml.Result, xmlSerMan);
                                            var xamlStr = acTaskXamlSb.ToString();
                                            var xamlFilename = Path.ChangeExtension(resFilename, ".xaml");
                                            var xamlPathname = Path.Combine(outPath, xamlFilename);
                                            File.WriteAllText(xamlPathname, xamlStr);
                                            ed.WriteMessage($"\t Save: {xamlFilename}@{outPath}\n");
                                        }
                                    }
                                    catch (System.Exception ex)
                                    {
                                        ed.WriteMessage($"\t Error: {ex.Message}\n");
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage(ex.Message);
            }
        }

 

SENL1362_1-1590576549475.png

 

SENL1362_0-1590576517619.png

 

Message 9 of 14

SENL1362
Advisor
Advisor

SENL1362_0-1590580067170.png

 

SENL1362_1-1590580291879.png

 

0 Likes
Message 10 of 14

SENL1362
Advisor
Advisor

And for the other AutoCAD Vertical (Map) users, another resource DLL to look into among others is

SENL1362_0-1590583890229.png

 

Message 11 of 14

_Serge
Contributor
Contributor

Thank you so much. Together, we will go further. I’m still not finished with this project so I may come back later for more informations/comments.

 

I mentioned ILSpy to make a story short. I did almost as you’ve done but I was uncertain about the consequences of bypassing AutoCAD loading one of its dll and also what would append if you execute the routine twice (this mean trying to reload the dll). You can add a Static flag to avoid this. So, I created a domain in which I loaded the file and I release the domain when it’s done.

 

' Assuming acTaskDialogsPathname can be the same as yours, namely
' C:\Program Files\Autodesk\AutoCAD 2021\AcTaskDialogs.dll
Dim path As String = Application.StartupPath
Dim setup As AppDomainSetup = AppDomain.CurrentDomain.SetupInformation
setup.PrivateBinPath = Path
setup.ShadowCopyFiles = "false"
Dim NomDomaine As String = "MyDomain"
Dim domain As AppDomain = AppDomain.CreateDomain(NomDomaine, Nothing, setup)
Dim assy As Assembly = Assembly.LoadFile(acTaskDialogsPathname)
. . .
AppDomain.Unload(domain)

 

I thought I had harvested all the cases for a vanilla AutoCAD but no. I Drag&Drop some of my problematic drawings and got at least 5 cases that came from nowhere. So, it’s gonna be a long and winding road. The caption in the following excerpt are in French but with the ID, you can deduct the meaning without translating.

<HideableDialog 
   id="Acad.UnresolvedFontFiles" 
   title="Fichiers SHX manquants" 
   . . .  
</HideableDialog>
<HideableDialog 
   id="Acad.UnresolvedReferenceFiles" 
   title="Références - Fichiers introuvables"" 
   . . .  
</HideableDialog>
<HideableDialog 
   id="AecUiBase.PreviousVersionOpen" 
   title="Ouvrir le dessin - Objets AEC d'une version antérieure""" 
   . . .  
</HideableDialog>
<HideableDialog 
   id="AecUiBase.SavingToPreviousVersion" 
   title="Enregistrement du dessin - Conflit de versions"
   . . .  
</HideableDialog>
<HideableDialog 
   id="DWGRecovery.DrawingRecovery" 
   title="Récupération du dessin"
   . . .  
</HideableDialog>

 

My approach now is the following. A dialog box (a different one of course) helps the user to choose which the dialog to hide or unhide. A TreeView has 2 nodes.

  1. The first one to encapsulate the AcTaskDialogs nodes having a mandatory attribute AllowDialogCancellation="True".
  2. The second node encapsulates the other cases (the exceptions). I have a second exe file that has a System.IO.FileSystemWatcher to spy the modifications in the FixedProfile.aws file. The latter is only updated when AutoCAD closes. Doing so, I can build a satellite file or an equivalent of a App.Config file for the exceptions. I use the PostBuildEvent to copy back this satellite file in the dll directory.

First node:

2020-05-27 11_40_59-Masquage des boites de tâches intempestives.png

 

Second node:

2020-05-27 11_18_05-Masquage des boites de tâches intempestives.png

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Some of the BAML nodes do not have the attribute AllowDialogCancellation="True". This Print Screen is a clear case (this may be not the exact translation: “The sheet set association is lost. What do you want to do?”). You can’t avoid this dialog if you face the problem. That’s why they are not listed in the first node.

 

2020-05-26 20_11_41-Gestionnaire du jeu de feuilles – Association de jeux perdue.png

 

Message 12 of 14

SENL1362
Advisor
Advisor

Nice cooperation!

I was wondering what more resource (dll) files may be of interest. Extending the code a bit made me harvesting all the files, see attachment for the complete.

Also improved the Embedded Resource handling(*.BAMP, *.GIF, *.TIF)

...
var bamlFileName = "HideableTaskDialogs";
...
var dllPathnames = Directory.GetFiles(acadExePath, "*.dll", SearchOption.AllDirectories);
...

                       var acDllAssy = Assembly.LoadFile(dllPathname);
                        var acResourceNames = acDllAssy.GetManifestResourceNames();
                        if (acResourceNames != null)
                        {
                            ed.WriteMessage($"Evaluate resources from: [{nDll}]: {dllPathname}\n");
                            foreach (var acResourceName in acResourceNames)
                            {
                                var acResourceInfo = acDllAssy.GetManifestResourceInfo(acResourceName);
                                ed.WriteMessage($"\t Processing resource: {acResourceName}\n");
                                using (var acResourceStrm = acDllAssy.GetManifestResourceStream(acResourceName)) // acResourceAssy.GetName().Name + ".g.resources"))
                                {
                                    using (var acResRdr = new ResourceReader(acResourceStrm))
                                    {
                                        foreach (DictionaryEntry acRes in acResRdr)   //*.BAML, *.Gif, *.Tif ...
                                        {
                                            var acResFilename = acRes.Key.ToString();
                                            //if (acResFilename.EndsWith(".BAML", StringComparison.OrdinalIgnoreCase))
                                            if (acResFilename.StartsWith(bamlFileName, StringComparison.OrdinalIgnoreCase))
...

 

It's processing 2025! dll's in my AutoCAD Map 2019 (including RasterDesign), but only 5 seems to contain HideableTaskDialogs.

SENL1362_0-1590603324767.png

This code is far from finished but there seems to be a problem in the .NET framework (...XML parsing...)when multiple runs have executed.

 

 

 

 

 

0 Likes
Message 13 of 14

SENL1362
Advisor
Advisor
You might me right about reloading these dll's. After a few executions AutoCAD will crash and VS complaining about XML parsing...
0 Likes
Message 14 of 14

_Serge
Contributor
Contributor

Thank you for the update. I'll get a look on the other dll.


About the reloading problem, try the domain as shown before. I made a loop of 50 iterations and had no problems (and it was greased lightning).


Also, someone could alternatively use the concept of a "PreferredFile" choosing between the global AcTaskDialogs.dll and the localized AcTaskDialogs.resources.dll with IO.Directory.GetFiles(AcadPath, "AcTaskDialogs*.*", SearchOption.AllDirectories). The localized file, if exists, will be in a directory such as "fr-FR", "de-DE", es-ES".

0 Likes