2014-06-24 17 views
11

Ho cercato una buona ora e non ho ancora trovato qualcosa che possa essere d'aiuto. Sto lavorando per aprire AutoCAD dall'API .NET in VS2013 utilizzando C#, ma per qualche motivo, non riesco mai ad avviare AutoCAD. Sto utilizzando il seguente codice:Come posso aprire AutoCAD 2015 tramite l'API .NET

using System; 
using System.Runtime.InteropServices; 

using Autodesk.AutoCAD.Interop; 
using Autodesk.AutoCAD.Runtime; 
using Autodesk.AutoCAD.ApplicationServices; 

namespace IOAutoCADHandler 
{ 
    public static class ACADDocumentManagement 
    { 
     [CommandMethod("ConnectToAcad")] 
     public static void ConnectToAcad() 
     { 

      AcadApplication acAppComObj = null; 
      // no version number so it will run with any version 
      const string strProgId = "AutoCAD.Application"; 

      // Get a running instance of AutoCAD 
      try 
      { 
       acAppComObj = (AcadApplication)Marshal.GetActiveObject(strProgId); 
      } 
      catch // An error occurs if no instance is running 
      { 
       try 
       { 
        // Create a new instance of AutoCAD 
        acAppComObj = (AcadApplication)Activator.CreateInstance(Type.GetTypeFromProgID(strProgId), true); 
       } 
       catch //// STOPS HERE 
       { 
        // If an instance of AutoCAD is not created then message and exit 
        // NOTE: always shows this box and never opens AutoCAD 
        System.Windows.Forms.MessageBox.Show("Instance of 'AutoCAD.Application'" + 
                 " could not be created."); 

        return; 
       } 
      } 

      // Display the application and return the name and version 
      acAppComObj.Visible = true; 
      System.Windows.Forms.MessageBox.Show("Now running " + acAppComObj.Name + 
               " version " + acAppComObj.Version); 

      // Get the active document 
      AcadDocument acDocComObj; 
      acDocComObj = acAppComObj.ActiveDocument; 

      // Optionally, load your assembly and start your command or if your assembly 
      // is demandloaded, simply start the command of your in-process assembly. 
      acDocComObj.SendCommand("(command " + (char)34 + "NETLOAD" + (char)34 + " " + 
            (char)34 + @"C:\Users\Administrator\Documents\All Code\main-libraries\IOAutoCADHandler\bin\Debug\IOAutoCADHandler.dll" + (char)34 + ") "); 

      acDocComObj.SendCommand("DRAWCOMPONENT"); 
     } 
    } 

Purtroppo, si ferma sempre al nidificato catch dichiarazione e visualizza sempre la finestra di popup senza aprire AutoCAD. Qualche suggerimento su come rendere almeno AutoCAD aperto per me?

EDIT: Messaggio di errore
][1

+0

Non sei molto preciso su quale sia il problema esatto. Ad ogni modo, un paio di suggerimenti: cambia le istruzioni "catch" in "catch (Exception e1)" e "catch (Exception e2)". Eseguire il programma sotto il debugger di Visual Studio e inserire i breakpoint sulla prima istruzione in ogni clausola catch. Quando viene rilevata l'eccezione dovresti essere in grado di vedere il tipo esatto dell'eccezione, e questo dovrebbe (si spera) darti qualche indizio. – RenniePet

+0

@RenniePet Sì, l'ho capito e ho incluso l'output dell'errore. – Archer

+0

È sul primo o secondo fermo? – RenniePet

risposta

-3
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 

namespace Tekkit 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

       //make sure to add last 2 using statements 
       ProcessStartInfo start = new ProcessStartInfo("calc.exe");        
       Process.Start(start);//starts the process 

     } 
    } 
} 
+4

Sì ... ma ottenere in seguito l'oggetto di automazione dall'istanza in esecuzione non è banale (è necessario ripetere ripetutamente la tabella degli oggetti globali finché non viene visualizzato ciò che si sta cercando). Manca anche il codice che ottiene il percorso del processo cercando la sua chiave LocalServer32 nel registro. E il flag '-Embedding' che il server remoto di DCOM passa all'applicazione quando viene avviato in modo normale tramite COM. – Cameron

+0

Peggio di iterare attraverso la tabella, il ROT registra solo la prima istanza avviata. Quindi se hai più sessioni aperte, sarai in grado di lavorare solo con il primo ea quel punto chissà quale è. In realtà lo uso in uno dei miei prodotti, ma se una sessione è già aperta o sono aperte più sessioni, chiedo all'utente e passa da lì. Non gioco con esso. – bjhuffine

0

ho aprire l'applicazione in modo molto diretto. Innanzitutto, assicurati di fare riferimento alla libreria dei tipi corretta. Quello che sto usando è AutoCAD 2014 Type Library, che si trova all'indirizzo: c: \ Programmi \ File comuni \ Autodesk Shared \ acax19enu.tlb

Per inizializzare l'applicazione:

using AutoCAD; 

namespace test 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     AutoCAD.AcadApplication app; 

     app = new AcadApplication(); 

     app.Visible = true; 

     Console.Read(); 
    } 
} 
} 
2

Il problema che si è stai codificando (correttamente) nell'interfaccia di interoperabilità di AutoCAD. Vi consiglio di non farlo (a causa di possibili modifiche alla versione).

L'altro problema è che la documentazione per i plug-in AutoCAD che utilizza il più recente .net api è per i plugin quando AutoCAD è già in esecuzione.

Il problema finale potrebbe essere che l'ID del programma di AutCAD è un mistero. Ho fatto in modo di renderlo un'impostazione configurabile, ma di default in "AutoCAD.Application", che prenderà l'AutoCAD.Application attualmente registrata sul computer di produzione. Se ci sono più versioni installate sulla macchina e vuoi essere specifiche, puoi aggiungere il numero di versione (che dovrai ricercare) al ProgID come: "AutoCAD.Application.19" o "AutoCAD.Application" .20 "per il 2015.

Per il primo problema, una tecnica consiste nell'utilizzare le dinamiche per gli oggetti AutoCad, in particolare per la creazione di istanze. Ho usato l'API ObjectARX per creare la mia applicazione in un progetto fittizio e quindi passare alla dinamica quando sono soddisfatto delle proprietà e dei nomi dei metodi.

in un'applicazione .NET autonoma che inizia AutoCAD si potrebbe usare qualcosa come:

// I comment these out in production 
//using Autodesk.AutoCAD.Interop; 
//using Autodesk.AutoCAD.Interop.Common; 
//... 
//private static AcadApplication _application; 
private static dynamic _application; 
static string _autocadClassId = "AutoCAD.Application"; 

private static void GetAutoCAD() 
{ 
    _application = Marshal.GetActiveObject(_autocadClassId); 
} 

private static void StartAutoCad() 
{ 
    var t = Type.GetTypeFromProgID(_autocadClassId, true); 
    // Create a new instance Autocad. 
    var obj = Activator.CreateInstance(t, true); 
    // No need for casting with dynamics 
    _application = obj; 
} 

public static void EnsureAutoCadIsRunning(string classId) 
{ 
    if (!string.IsNullOrEmpty(classId) && classId != _autocadClassId) 
     _autocadClassId = classId; 
    Log.Activity("Loading Autocad: {0}", _autocadClassId); 
    if (_application == null) 
    { 
     try 
     { 
      GetAutoCAD(); 
     } 
     catch (COMException ex) 
     { 
      try 
      { 
       StartAutoCad(); 
      } 
      catch (Exception e2x) 
      { 
       Log.Error(e2x); 
       ThrowComException(ex); 
      } 
     } 
     catch (Exception ex) 
     { 
      ThrowComException(ex); 
     } 
    } 
} 
0

Quando ci sono diverse versioni di AutoCAD installati su un computer, la creazione di un'istanza con la "AutoCAD.Application" ProgID sarà eseguire l'ultima versione avviata su questo computer dall'utente corrente. Se la versione degli assembly di interoperabilità utilizzata non corrisponde alla versione che viene avviata, viene visualizzato System.InvalidCastException con un HRESULT 0x80004002 (E_NOINTERFACE).

Nel vostro caso specifico, il {070AA05D-DFC1-4E64-8379-432269B48B07} IID nel messaggio di errore è il GUID per l'interfaccia AcadApplication in R19 64-bit (AutoCAD 2013 & 2014). Quindi c'è un AutoCAD 2013 o 2014 che sta iniziando, e non puoi lanciare questo oggetto COM su un tipo 2015 perché 2015 è R20 (non compatibile con i binari).

Per evitare ciò, è possibile aggiungere una versione specifica al ProgID (come "AutoCAD.Application.20" per AutoCAD 2015 (R20.0) a 2016 (R20.1)) per avviare la versione corrispondente ai propri assiemi di interoperabilità oppure puoi utilizzare l'associazione tardiva (ad esempio rimuovere i tuoi riferimenti ad Autodesk.AutoCAD.Interop * e usa la parola chiave dynamic invece dei tipi di AutoCAD).

Nell'ultimo caso, si perderà il completamento automatico, ma il programma funzionerà con tutte le versioni di AutoCAD.

Controllare anche 32-bit vs 64-bit perché gli assembly TypeLib/Interop non sono uguali.