5 Replies Latest reply on Nov 15, 2011 11:50 AM by David Spektor

    EPDM Task to Print PDF from AutoCAD?

    Mathew Stevenson

      Can you make a tack to print a PDF file from an AutoCAD file when changing state or are Task only for SolidWorks files?

        • Re: EPDM Task to Print PDF from AutoCAD?
          Jeff Sweeney

          The Print and Convert tasks are only for SW. They could be modified to support other applications.

            • Re: EPDM Task to Print PDF from AutoCAD?
              Jim Sculley

              Jeff Sweeney wrote:

               

              The Print and Convert tasks are only for SW. They could be modified to support other applications.

              I think I would rather stick a fork in my eye.

               

              AutoCAD has its own extensive .NET API.  I have an EPDM C# add-in starting AutoCAD and publishing multiple DWG files as a single .PDF when drawings reach the 'Approved' state.  The tricky part was that I had to create a separate add-in for AutoCAD itself, and then use the ACAD SendCommand API call in the EPDM add-in to send a LISP command to the running AutoCAD instance to tell it to publish.  The LISP bit is required if you want to pass arguments to AutoCAD, such as what files to publish.

               

              AutoCAD .NET guide is here

               

              Jim S.

                • Re: EPDM Task to Print PDF from AutoCAD?
                  David Spektor

                  Hi Jim,

                   

                  I know this is an old thread but thought I would ask anyways.

                   

                  I am trying to do the same thing right now. I tried to add the Autocad methods inside the same class as the EPDM addin but when I do the addin does not excecute the onCmd method, any ideas why?


                  I am probably going to have to do it as you said and make it two seperate addins which is very frustrating. Do you have anymore tips or tricks that you wouldnt mind sharing for creating the ACAD addin(and linking the two)?

                   

                  Also just as a heads up I tried doing the PDF creation all in SW but because everything is done in Model Space I have no clue how to figure out proper scaling to bring it to 11X7 paper size. If anyone has any ideas I would much rather do this all in SW.

                   

                  I just want to throw it out there, I think the ACAD api support is bare bones, a bit confusing and I hate it. There its all been said.

                   

                  Thanks,

                  David

                    • Re: EPDM Task to Print PDF from AutoCAD?
                      Jim Sculley

                      David Spektor wrote:

                       

                      Hi Jim,

                       

                      I know this is an old thread but thought I would ask anyways.

                       

                      I am trying to do the same thing right now. I tried to add the Autocad methods inside the same class as the EPDM addin but when I do the addin does not excecute the onCmd method, any ideas why?


                      I am probably going to have to do it as you said and make it two seperate addins which is very frustrating. Do you have anymore tips or tricks that you wouldnt mind sharing for creating the ACAD addin(and linking the two)?

                       

                      Also just as a heads up I tried doing the PDF creation all in SW but because everything is done in Model Space I have no clue how to figure out proper scaling to bring it to 11X7 paper size. If anyone has any ideas I would much rather do this all in SW.

                       

                      I just want to throw it out there, I think the ACAD api support is bare bones, a bit confusing and I hate it. There its all been said.

                       

                      Thanks,

                      David

                       

                      I don't think the AutoCAD methods will work inside the EPDM add-in because they are running in separate processes.  I don't recall all the tests I did before implementing my current solution, but if I there was an easier way, I would like to think I would have discovered it.  My best advice for you is to create the AutoCAD add-in independently first.  In other words, create an AutoCAd add-in that you can run from inside AutoCAD.  Once you have that worknig the way you want, then you can make the link from EPDM.  Trying to debug across the link is extrememly difficult.

                       

                      My AutoCAD add-in uses the ObjectARX AutoCAD library which you can get from the AutoDesk site.  The specific libraries  I use are AcCui, AcDbMgd and AcMgd.  You need these as references in your project.  Similar to SolidWorks add-ins, your ACAD add-in has to be registered.  The users can do that from the ACAD command line if you set up your add-in correctly.  At the top of my add-in code (before the namespace declaration) is the line:

                       

                      [assembly: CommandClass(typeof(com.aquilex.wsi.epdm.publisher.autocad.AutoCADPublisher))]

                       

                      which lets ACAD know that this add-in includes commands that can be executed.  There are two comamnd methods in the add-in:

                       

                      [CommandMethod("RegisterAutoCADPublisher")]

                       

                              public void RegisterAutoCADPublisher()

                              {

                                  // Get the AutoCAD Applications key

                                  string sProdKey = HostApplicationServices.Current.RegistryProductRootKey;

                                  string sAppName = "AutoCADPublisher";

                                  RegistryKey regAcadProdKey = Registry.CurrentUser.OpenSubKey(sProdKey);

                                  string[] prodSubkeys = regAcadProdKey.GetSubKeyNames();

                                  Array.Sort(prodSubkeys);

                                  if (Array.BinarySearch(prodSubkeys, "Applications") < 0)

                                  {

                                      regAcadProdKey.CreateSubKey("Applications");

                                  }

                                  RegistryKey regAcadAppKey = regAcadProdKey.OpenSubKey("Applications", true);

                                  // Check to see if the "AutoCADPublisher" key exists

                                  string[] subKeys = regAcadAppKey.GetSubKeyNames();

                                  foreach (string subKey in subKeys)

                                  {

                                      // If the application is already registered, exit

                                      if (subKey.Equals(sAppName))

                                      {

                                          regAcadAppKey.Close();

                                          return;

                                      }

                                  }

                                  // Get the location of this module

                                  string sAssemblyPath = Assembly.GetExecutingAssembly().Location;

                                  // Register the application

                                  RegistryKey regAppAddInKey = regAcadAppKey.CreateSubKey(sAppName);

                                  regAppAddInKey.SetValue("DESCRIPTION", sAppName, RegistryValueKind.String);

                                  regAppAddInKey.SetValue("LOADCTRLS", 2, RegistryValueKind.DWord);

                                  regAppAddInKey.SetValue("LOADER", sAssemblyPath, RegistryValueKind.String);

                                  regAppAddInKey.SetValue("MANAGED", 1, RegistryValueKind.DWord);

                                  regAcadAppKey.Close();

                              }

                       

                              [CommandMethod("UnregisterAutoCADPublisher")]

                       

                              public void UnregisterAutoCADPublisher()

                              {

                                  // Get the AutoCAD Applications key

                                  string sProdKey = HostApplicationServices.Current.RegistryProductRootKey;

                                  string sAppName = "AutoCADPublisher";

                                  RegistryKey regAcadProdKey = Registry.CurrentUser.OpenSubKey(sProdKey);

                                  RegistryKey regAcadAppKey = regAcadProdKey.OpenSubKey("Applications", true);

                                  if (regAcadAppKey != null)

                                  {

                                      // Delete the key for the application

                                      regAcadAppKey.DeleteSubKeyTree(sAppName);

                                      regAcadAppKey.Close();

                                  }

                              }

                       

                      These add or remove the Windows regsitry entries to register or unregister the add-in.

                       

                      The method that receives communication from EPDM is declared like this:

                       

                      [LispFunction("publishPDF")]

                              public void publishPDF(ResultBuffer rbArgs)

                              {

                                     //...publishing code here

                              }

                       

                      The part in square braces tells ACAD that this method can be called as a LISP function from the command line.  My implementation expects the command to look like this:

                       

                      publishPDF "path_to_some_file_in_vault" "name_of_vault"

                       

                       

                      I need to get information from the EPDM vault, so I use:

                       

                      IEdmVault11 vault = (IEdmVault11)(new EdmVault5());

                      vault.LoginAuto(vaultName, 0);

                       

                      The actual publishing code looks like this:

                       

                      private void publishFiles(string wdpFilePath, List<IEdmFile5> filesToPublish)

                              {

                                  Publisher publisher = Acad.Application.Publisher;

                                  DsdData data = getDsdData(wdpFilePath, filesToPublish);

                                  PlotConfig pConfig = getPlotConfig();

                                  if (data == null || pConfig == null)

                                  {

                                      return;

                                  }

                                  publisher.PublishExecute(data, pConfig);

                              }

                       

                      You need to create a DsdData object and PlotConfig object to use the PublishExecute method.

                       

                      Once you have all that working, it is pretty easy to startup or connect to AutoCAD:

                       

                      try

                                  {

                                      AcadApplication acApp = (AcadApplication)Marshal.GetActiveObject("AutoCAD.Application.18");

                                  }

                                  catch (COMException cexA)

                                  {

                                      try

                                      {

                                          Type acType =Type.GetTypeFromProgID("AutoCAD.Application.18");

                                          acApp =(AcadApplication)Activator.CreateInstance(acType, true);

                                      }

                                      catch (COMException cexB)

                                      {

                                          MessageBox.Show("Cannot create AutoCAD.Application.18 instance for publishing.");

                                          return;

                                      }

                                  }

                       

                      And then you can use the SendCommand function:

                       

                      acApp.ActiveDocument.SendCommand(yourCommandString);

                       

                      All my PDF publishing code, which handles AutoCAD and SW files is about 1200 lines (including comments), so it isn't terribly complex.

                       

                       

                      Some gotchas:

                       

                            A.  You can't send commands to ACAD if no documents are open, so I open a dummy document if necessary and close it when I'm done.

                       

                           B.  I could not find an event in the ACAD API to tell me when publishing had finished.  I had to use a FileSystemWatcher to take action (check-in, transition, etc) once the PDF appeared.

                           

                           C.  If something goes wrong on the ACAD side, there may be no indication on the EPDM side, so I use some watchdog timers and such to make sure things don't get stuck.

                          

                           D.  Publishing isn't exactly speedy, so I use a separate thread to do the work.  This keeps the EPDM user inteface responsive while publishing is happening.

                       

                        

                      Jim S.