Author Topic: Auto Netloading when debugging  (Read 2414 times)

0 Members and 1 Guest are viewing this topic.

bargool

  • Guest
Auto Netloading when debugging
« on: December 31, 2011, 08:47:49 AM »
Hi guys, I'm bored to netload while debugging and I'm using SharpDevelop with AutoCAD x64, so this way doesn't work for me (SharpDevelop cannot debug x64 applications :-().
And I invented my own wheel.
How to use:
You making appsettings.xml in folder with assembly:
Code: [Select]
<?xml version="1.0" encoding="utf-8"?>
<Settings>
  <ProjectDirectory>C:\PROGGING\</ProjectDirectory>
</Settings>
ProjectDirectory is your working directory.
Then netload your assembly. Next time just type "an".

Initializing app:
Code: [Select]
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;

//Autodesk
using acad = Autodesk.AutoCAD.ApplicationServices.Application;

namespace Bargool.Acad.AutoNetload
{
   /// <summary>
   /// Initialization of AutoNetload
   /// </summary>
   public class Initialization : IExtensionApplication
   {
      void IExtensionApplication.Initialize()
      {
         acad.DocumentManager.DocumentLockModeChanged
            += new DocumentLockModeChangedEventHandler(CommandClass.NetLoaded);
         // Reading path where our developing projects can found
         CommandClass.ReadProjectsPath();
      }

      void IExtensionApplication.Terminate()
      {
      }
   }
}
And the routine class:
Code: [Select]
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;
using System.Xml.Linq;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using acad = Autodesk.AutoCAD.ApplicationServices.Application;

[assembly:CommandClass(typeof(Bargool.Acad.AutoNetload.CommandClass))]

namespace Bargool.Acad.AutoNetload
{
   /// <summary>
   /// There is routine to work with autonetloading
   /// </summary>
   public class CommandClass
   {
      static string projectsDir; // the root directory of all our developing projects
     
      /// <summary>
      /// Handler for event DocumentLockModeChanged
      /// </summary>
      public static void NetLoaded(object sender, DocumentLockModeChangedEventArgs e)
      {
         Document dwg = e.Document;
         if (e.GlobalCommandName.ToUpper() == "NETLOAD")
         {
            e.Veto();
            // Unregistering this handler
            acad.DocumentManager.DocumentLockModeChanged
               -= new DocumentLockModeChangedEventHandler(NetLoaded);
            // Register handler for AssemblyLoad event
            AppDomain.CurrentDomain.AssemblyLoad
               += new AssemblyLoadEventHandler(AppDomain_CurrentDomain_AssemblyLoad);
            dwg.SendStringToExecute("_netload\n", true, false, false);
         }
      }
     
      /// <summary>
      /// Method getting assembly path from appsettings.xml and loading it
      /// </summary>
      [CommandMethod("an")]
      public void RestoreNetLoad()
      {
         try
         {
            // Getting appsettings.xml
            XDocument cfg = GetAppsettings();
            // Getting assembly from previous netload
            string assemblyToLoadPath = cfg.Descendants("AssemblyPath").First().Value;
            // If AssemblyPath in cfg is proper - loading it
            if (assemblyToLoadPath.ToUpper().StartsWith(projectsDir))
            {
               Assembly.LoadFrom(assemblyToLoadPath);
               acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(
                  "\nAssembly {0} loaded", assemblyToLoadPath);
            }
            else
            {
               string s = "\nError in appsettings.xml\nCorrect it:\n"+
                  "AssemblyPath have to start with ProjectDirectory there";
               acad.ShowAlertDialog(s);
            }
         }
         catch (XmlException xmlex)
         {
            acad.ShowAlertDialog(
               String.Format(
                  "\nError while loading appsettings.xml:\n{0}",
                  xmlex.Message));
         }
         catch (IOException ioex)
         {
            acad.ShowAlertDialog(
               String.Format(
                  "\nError while loading assembly:\n{0}",
                  ioex.Message));
         }
         catch (System.Exception ex)
         {
            acad.ShowAlertDialog(
               String.Format("\nError:\n{0}", ex.Message));
         }
      }
     
      /// <summary>
      /// Handler for AssemblyLoad event
      /// </summary>
      static void AppDomain_CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
      {
         // If loaded assembly in our projects dir, writing it to appsettings.xml
         if (args.LoadedAssembly.Location.ToUpper().StartsWith(projectsDir))
         {
            // Unregistering from AssemblyLoad event
            AppDomain.CurrentDomain.AssemblyLoad -=
               new AssemblyLoadEventHandler(AppDomain_CurrentDomain_AssemblyLoad);
            WriteLoadedAssembly(args.LoadedAssembly.Location);
         }
      }
     
      /// <summary>
      /// Writing appsettings.xml with path to AssemblyPath node
      /// </summary>
      /// <param name="path">path to write to AssemblyPath node</param>
      static void WriteLoadedAssembly(string path)
      {
         // Getting current assembly directory
         string assemblyPath =
            Path.GetDirectoryName(
               Assembly.GetAssembly(new CommandClass().GetType())
               .Location);
         try
         {
            XDocument appsettings =
               new XDocument(
                  new XElement("Settings",
                               new XElement("ProjectDirectory", projectsDir),
                               new XElement("AssemblyPath", path)));
            appsettings.Save(Path.Combine(assemblyPath, "appsettings.xml"));
         }
         catch (XmlException xmlex)
         {
            acad.ShowAlertDialog(
               String.Format(
                  "\nError while writing appsettings.xml:\n{0}", xmlex.Message));
         }
         catch (System.Exception ex)
         {
            acad.ShowAlertDialog(
               String.Format("\nError:\n{0}", ex.Message));
         }
      }
     
      /// <summary>
      /// Reading directory where our developing projects have to be
      /// </summary>
      public static void ReadProjectsPath()
      {
         XDocument cfg = GetAppsettings();
         try
         {
            projectsDir = cfg.Descendants("ProjectDirectory").First().Value.ToUpper();
         }
         catch (XmlException xmlex)
         {
            acad.ShowAlertDialog(
               String.Format(
                  "\nError while reading ProjectDirectory from appsettings.xml:\n{0}",
                  xmlex.Message));
         }
      }
     
      /// <summary>
      /// Getting XML document with setting for app
      /// </summary>
      /// <returns>XML document with setting for app</returns>
      static XDocument GetAppsettings()
      {
         string assemblyPath =
            Path.GetDirectoryName(
               Assembly.GetAssembly(new CommandClass().GetType())
               .Location);
         XDocument cfg = null;
         try
         {
            cfg = XDocument.Load(Path.Combine(assemblyPath, "appsettings.xml"));
         }
         catch (System.Exception ex)
         {
            acad.ShowAlertDialog(
               String.Format("\nError:\n{0}", ex.Message));
         }
         return cfg;
      }
   }
}
« Last Edit: January 11, 2012, 01:41:57 AM by bargool »

Odoshi

  • Guest
Re: Auto Netloading when debugging
« Reply #1 on: December 31, 2011, 12:15:59 PM »
You could also add a Loader key to AutoCAD's registry and the .NET DLL will load when AutoCAD starts.

Regards,
Mike

SGP2012

  • Guest
Re: Auto Netloading when debugging
« Reply #2 on: December 31, 2011, 06:12:48 PM »
Here's a blog post showing how to auto-register your demand load settings. After you've NETLOADed your DLL once, it will be automatic thenceforth:

http://through-the-interface.typepad.com/through_the_interface/2009/05/creating-demand-loading-entries-automatically-for-your-autocad-application-using-net.html

Or you could create a (new in AutoCAD 2012) Autoloader bundle - http://through-the-interface.typepad.com/through_the_interface/2011/05/adn-devcast-episode-6-autoloader.html.




gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Auto Netloading when debugging
« Reply #3 on: December 31, 2011, 07:03:00 PM »
I think the OP was talking about NETLOAD while debugging.

I purposed two ways in this reply but they are (almost the second) related to Visual Studio.

I do not know anything about SharpDevelop debugging but perhaps the LISP way may be adapted.
Speaking English as a French Frog

bargool

  • Guest
Re: Auto Netloading when debugging
« Reply #4 on: January 02, 2012, 04:10:38 AM »
Yes gile, you are right! Keyword is while debugging.
SharpDevelop cannot even start x64 application, so script way doesn't work.
Your LISP way means that dwg-file is in debug folder of your project, isn't it? (I don't know LISP, it's just my suggestion)
In my solution I just write to xml-file the folder where all my projects stored, in sub-folders

bargool

  • Guest
Re: Auto Netloading when debugging
« Reply #5 on: January 11, 2012, 01:43:08 AM »
I changed in topic post:
Code: [Select]
Assembly asm = Assembly.LoadFile(assemblyToLoadPath);
AppDomain.CurrentDomain.Load(asm.GetName());
to
Code: [Select]
Assembly.LoadFrom(assemblyToLoadPath); because if you use in your application assemblies that didn't load to AutoCAD - with previous variant you will have reflection error