Author Topic: Add to the CUIX "LISP Files" section using .NET (AutoCAD 2014)  (Read 7940 times)

0 Members and 1 Guest are viewing this topic.

matinau

  • Guest
Is it possible to add lisp files to the CUI "LISP Files" section using .NET?

I can get the collection using:
var csMain = new CustomizationSection(Application.GetSystemVariable("MENUNAME"));
LspFileCollection lspFiles = csMain.MenuGroup.LspFiles;

And this to add my lisp to the collection:
lspFiles.Add(lispFile);

Unfortunately the changes are not saved and no lisps are loaded?

csMain.Save(); doesn’t make any difference.
« Last Edit: May 12, 2014, 04:12:24 AM by matinau »

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Add to the CUI "LISP Files" section using .NET
« Reply #1 on: May 12, 2014, 02:07:32 AM »
Is it possible to add lisp files to the CUI "LISP Files" section using .NET?
Two variants:
Code - C#: [Select]
  1. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  2. using Cst = Autodesk.AutoCAD.Customization;
  3. ...
  4. // variant 1: LINQ to XML
  5. String extension = ".cui";
  6. String menu_file = cad.GetSystemVariable("MENUNAME") + extension;
  7. XElement xml = XElement.Load(menu_file);
  8. String menuGroupName = "ACAD";
  9. XElement xmlMenuRoot = xml.Elements("MenuGroup").First(n =>
  10.   n.Attribute("Name").Value == menuGroupName).Element("MenuRoot");
  11. String lispFileName = @"C:\Users\andrey\Desktop\file_1.lsp";
  12. xmlMenuRoot.Add(new XElement("LSPFile", lispFileName));
  13. xml.Save(menu_file);
  14.  
  15. // variant 2: AutoCAD .NET API
  16. var csMain = new Cst.CustomizationSection(menu_file, menuGroupName,
  17.   false, false);
  18. Cst.LspFileCollection lspFiles = csMain.MenuGroup.LspFiles;
  19. String lispFile2Name = @"C:\Users\andrey\Desktop\file_2.lsp";
  20. lspFiles.Add(lispFile2Name);
  21. csMain.Save();
  22. ...
It works for the AutoCAD 2009. Newer AutoCAD versions use the CUIX as I remember.
« Last Edit: May 12, 2014, 02:18:32 AM by Andrey Bushman »

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Add to the CUI "LISP Files" section using .NET
« Reply #2 on: May 12, 2014, 02:19:00 AM »
I edited my code (add the second variant). Both works (was checked in AutoCAD 2009 x86 Enu SP3).

matinau

  • Guest
Re: Add to the CUI "LISP Files" section using .NET
« Reply #3 on: May 12, 2014, 02:39:12 AM »
thanks Andy, unfortunately I can't get either approach to work. I'm using AutoCAD 2014. The XML method returns a read error and the second method completes but still no changes are saved. The CustomizationSection also appears to be slightly different i.e. there's no matching definition for cst.CustomizationSection.(menuFile, menugroup, false, false)

matinau

  • Guest
Re: Add to the CUI "LISP Files" section using .NET
« Reply #4 on: May 12, 2014, 02:42:12 AM »
the closest match has an additional "string[] PartsToLoad"

new cst.CustomizationSection(menuFile, Cui.MenuName, false, false, string[] PartsToLoad);

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Add to the CUI "LISP Files" section using .NET
« Reply #5 on: May 12, 2014, 03:19:32 AM »
Quote
The XML method returns a read error
Because the CUI is the text file (XML format), but the CUIX file is an archive. You can't use the LINQ to XML for the CUIX. In your first message you wrote about the CUI. So I thought you use the old AutoCAD version.

It is strange: the mouse's right button click on the parent item ("ACAD" on the screen) in the remote debug mode get the exception:

Quote
PInvokeStackImbalance occurred
Message: Помощник отладки управляемого кода "PInvokeStackImbalance" обнаружил неполадку в "C:\Program Files\Autodesk\AutoCAD 2014\acad.exe".
Additional information: A call to PInvoke function 'AcCustomize!Autodesk.AutoCAD.Customization.UserDataUtil::GetACADUserDataCacheLangPath' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

Without [remote?] debug mode an exception is not occur.

For AutoCAD 2014 I try it:

Code - C#: [Select]
  1. String extension = ".CUIX";
  2. String menu_file = cad.GetSystemVariable("MENUNAME") + extension;
  3. String menuGroupName = "ACAD";
  4. String lispFileName = @"C:\Users\andrey\Desktop\file_1.lsp";
  5. var csMain = new Cst.CustomizationSection(menu_file, menuGroupName, false,
  6.                 false, new String[]{});
  7. Cst.LspFileCollection lspFiles = csMain.MenuGroup.LspFiles;
  8. lspFiles.Add(lispFileName);
  9. Boolean result = csMain.Save(); // true

The "result" variable has the "true" value, but nothing happens. I don't know why. It is interesting for me too. Tell me, if you will find the decision. Maybe it is AutoCAD .NET API bug (I don't know).
« Last Edit: May 12, 2014, 03:23:19 AM by Andrey Bushman »

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Add to the CUI "LISP Files" section using .NET
« Reply #6 on: May 12, 2014, 03:58:54 AM »
For AutoCAD 2014 it works (I editing the CUIX archive in my code):

Code - C#: [Select]
  1. using System.IO.Compression;
  2. ...
  3. String archive_extension = ".CUIX";
  4. String itemFileName = "LSPFiles.cui";
  5. String menu_file = cad.GetSystemVariable("MENUNAME") + archive_extension;
  6. String lispFileName = @"C:\Users\andrey\Desktop\file_1.lsp";
  7.  
  8. using (ZipArchive archive = ZipFile.Open(menu_file, ZipArchiveMode.Update)) {
  9.                 ZipArchiveEntry entity = archive.GetEntry(itemFileName);
  10.                 String fn = Path.Combine(Environment.GetFolderPath(
  11.                                 Environment.SpecialFolder.MyDocuments), Path.GetRandomFileName());
  12.                 entity.ExtractToFile(fn);
  13.                 XElement xml = XElement.Load(fn);
  14.                 xml.Add(new XElement("LSPFile", lispFileName));
  15.                 xml.Save(fn);
  16.                 entity.Delete();
  17.                 archive.CreateEntryFromFile(fn, itemFileName);
  18.                 File.Delete(fn);
  19. }
  20. ...
« Last Edit: May 12, 2014, 04:06:28 AM by Andrey Bushman »

matinau

  • Guest
Re: Add to the CUI "LISP Files" section using .NET
« Reply #7 on: May 12, 2014, 04:11:48 AM »
Apologises for the miss-direction it's a force of habit referring to CUIX as CUI... I'll update.

Your last post looks impressive! I will try it out tomorrow at work. Thanks so much for help, I would never have come up with that method on my own.

Will let you know whether I have any luck my end.

Locke

  • Guest
Re: Add to the CUIX "LISP Files" section using .NET (AutoCAD 2014)
« Reply #8 on: May 12, 2014, 08:29:58 AM »
ZipArchive is only available under System.IO.Compression in .NET 4.5 and later.  Therefore you can also use System.IO.Packaging on earlier releases to work with your .CUIX. Note however Microsoft screwed up the IDisposable implementation with System.IO.Packaging.Package, so make sure you actually close the package manually even inside a Using statement.

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Add to the CUIX "LISP Files" section using .NET (AutoCAD 2014)
« Reply #9 on: May 12, 2014, 08:45:05 AM »
Thank you for useful notice. I used DotNetZip often in the past, also. It has good help file with the samples.
Code - C#: [Select]
  1. using Ionic.Zip;
  2. ...
  3. // Variant 4: DotNetZipLib using.
  4. String archive_extension = ".CUIX";
  5. String itemFileName = "LSPFiles.cui";
  6. String menu_file = cad.GetSystemVariable(
  7.   "MENUNAME") + archive_extension;
  8. String lispFileName =
  9.    @"C:\Users\andrey\Desktop\file_1.lsp";
  10. using(ZipFile zip = new ZipFile(menu_file)) {
  11.   String fn = Path.Combine(Environment
  12.     .GetFolderPath(Environment.SpecialFolder
  13.     .MyDocuments), itemFileName);
  14.   ZipEntry e = zip[itemFileName];
  15.   e.Extract(Path.GetDirectoryName(fn),
  16.     ExtractExistingFileAction.OverwriteSilently);
  17.   XElement xml = XElement.Load(fn);
  18.   xml.Add(new XElement("LSPFile", lispFileName));
  19.   xml.Save(fn);
  20.   zip.RemoveEntry(itemFileName);
  21.   zip.AddFile(fn, "./");
  22.   zip.Save();
  23.   File.Delete(fn);
  24. }
« Last Edit: May 12, 2014, 09:31:40 AM by Andrey Bushman »

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: Add to the CUIX "LISP Files" section using .NET (AutoCAD 2014)
« Reply #10 on: May 12, 2014, 10:08:22 AM »
Would it be easier to create/append to the MNL file instead?
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Add to the CUIX "LISP Files" section using .NET (AutoCAD 2014)
« Reply #11 on: May 12, 2014, 10:11:25 AM »
Would it be easier to create/append to the MNL file instead?
Depends on circumstances, in my opinion.

matinau

  • Guest
Re: Add to the CUIX "LISP Files" section using .NET (AutoCAD 2014)
« Reply #12 on: May 12, 2014, 08:41:31 PM »
Superb! I ended up using the Ionic.Zip since still using .NET 4. Everything works, the only slight issue is that when the code adds the LISP Files for the first time they don't actually get loaded. upon restart everything works great. If you have any ideas around this I be keen to hear them.

Also, I experienced issues using the .MNL approach in-conjunction with the Autoloader, namely due to calls to command not yet loaded.

Thanks again for all your help

matinau

  • Guest
Re: Add to the CUIX "LISP Files" section using .NET (AutoCAD 2014)
« Reply #13 on: May 12, 2014, 08:57:22 PM »
Figured out the loading issue, just need to reload the main menu on change.
Application.LoadMainMenu(csMain.CUIFileName);

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Add to the CUIX "LISP Files" section using .NET (AutoCAD 2014)
« Reply #14 on: May 12, 2014, 11:56:56 PM »
Also you can load LISP files through the Application.Invoke() method. It exists for AutoCAD 2011 and newer.

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Add to the CUI "LISP Files" section using .NET
« Reply #15 on: May 13, 2014, 02:34:19 AM »
The "result" variable has the "true" value, but nothing happens. I don't know why. It is interesting for me too. Tell me, if you will find the decision. Maybe it is AutoCAD .NET API bug (I don't know).

Yes, this is a bug of AutoCAD .NET API. It works fine:

Code - C#: [Select]
  1. String extension = ".CUIX";
  2. String menu_file = cad.GetSystemVariable("MENUNAME") + extension;
  3. String menuGroupName = "ACAD";
  4. String lispFileName = @"C:\Users\andrey\Desktop\file_1.lsp";
  5. var csMain = new Cst.CustomizationSection(menu_file, menuGroupName, false,
  6.   false, new String[] { });
  7. Cst.LspFileCollection lspFiles = csMain.MenuGroup.LspFiles;
  8. lspFiles.Add(lispFileName);
  9. Boolean result = false;
  10. // result = csMain.Save(); // "true", but nothing happen
  11. result = csMain.SaveAs(menu_file); // "true" and works fine

I remember a similar problem for the Database.Save() method too (exception occured). Autodesk don't love the "Save" methods...
« Last Edit: May 13, 2014, 02:37:27 AM by Andrey Bushman »

matinau

  • Guest
Re: Add to the CUIX "LISP Files" section using .NET (AutoCAD 2014)
« Reply #16 on: May 13, 2014, 05:46:04 AM »
You gotta be kidding!!! So simple. Well if anything I've learnt a lot from this post! Thanks man

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Add to the CUIX "LISP Files" section using .NET (AutoCAD 2014)
« Reply #17 on: May 13, 2014, 05:53:07 AM »

Thanks Andrey.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Add to the CUIX "LISP Files" section using .NET (AutoCAD 2014)
« Reply #18 on: May 13, 2014, 05:58:43 AM »
Welcome.