2010-02-18 8 views
3

J'implémente une application qui utilise COM dans l'interface ObjectARX d'AutoCAD pour automatiser les actions de dessin, telles qu'ouvrir et enregistrer sous. Selon la documentation, je devrais pouvoir appeler AcadDocument.SaveAs() et passer un nom de fichier, un "type de sauvegarde" et un paramètre de sécurité. La documentation indique explicitement que si la sécurité est NULL, aucune opération liée à la sécurité n'est tentée. Il ne donne cependant aucune indication sur le type d'objet correct à transmettre en tant que paramètre "save as type". J'ai essayé d'appeler SaveAs avec un nom de fichier et null pour les arguments restants, mais mon application se bloque sur cet appel de méthode et AutoCAD semble se bloquer - vous pouvez toujours utiliser le ruban mais ne pouvez rien faire avec la barre d'outils et ne peut pas fermer AutoCAD.SaveAs en suspension COM AutoCAD

J'ai l'impression que mes paramètres NULL causent du chagrin ici, mais la documentation manque cruellement au département COM/VBA. En fait, il dit que la classe AcadDocument n'a même pas de méthode SaveAs, ce qui est clairement le cas.

Est-ce que quelqu'un ici a implémenté la même chose? Des conseils? L'alternative est que j'utilise la méthode SendCommand() pour envoyer une commande _SAVEAS, mais mon application gère un lot de dessin et doit savoir a) si l'enregistrement échoue, et b) quand la sauvegarde est terminée (que je « m faire en écoutant l'événement EndSave)

EDIT

Voici le code tel que demandé -. tout qu'il fait est le lancement d'AutoCAD (ou la connexion à l'instance en cours d'exécution si elle est déjà en cours d'exécution), l'ouverture d'un existant dessin, puis enregistrez le document dans un nouvel emplacement (C: \ Scratch \ Document01B.dwg.)

using (AutoCad cad = AutoCad.Instance) 
{ 
    // Launch AutoCAD 
    cad.Launch(); 

    // Open drawing 
    cad.OpenDrawing(@"C:\Scratch\Drawing01.dwg"); 

    // Save it 
    cad.SaveAs(@"C:\Scratch\Drawing01B.dwg"); 
} 

Puis dans ma classe AutoCad (this._acadDocument est une instance de la classe AcadDocument.)

public void Launch() 
{ 
    this._acadApplication = null; 
    const string ProgramId = "AutoCAD.Application.18"; 

    try 
    { 
     // Connect to a running instance 
     this._acadApplication = (AcadApplication)Marshal.GetActiveObject(ProgramId); 
    } 
    catch (COMException) 
    { 
     /* No instance running, launch one */ 

     try 
     { 
      this._acadApplication = (AcadApplication)Activator.CreateInstance(
       Type.GetTypeFromProgID(ProgramId), 
       true); 
     } 
     catch (COMException exception) 
     { 
      // Failed - is AutoCAD installed? 
      throw new AutoCadNotFoundException(exception); 
     } 
    } 

    /* Listen for the events we need and make the application visible */ 
    this._acadApplication.BeginOpen += this.OnAcadBeginOpen; 
    this._acadApplication.BeginSave += this.OnAcadBeginSave; 
    this._acadApplication.EndOpen += this.OnAcadEndOpen; 
    this._acadApplication.EndSave += this.OnAcadEndSave; 

#if DEBUG 
    this._acadApplication.Visible = true; 
#else 
    this._acadApplication.Visible = false; 
#endif 

    // Get the active document 
    this._acadDocument = this._acadApplication.ActiveDocument; 
} 

public void OpenDrawing(string path) 
{ 
    // Request AutoCAD to open the document 
    this._acadApplication.Documents.Open(path, false, null); 

    // Update our reference to the new document 
    this._acadDocument = this._acadApplication.ActiveDocument; 
} 

public void SaveAs(string fullPath) 
{ 
    this._acadDocument.SaveAs(fullPath, null, null); 
} 
+0

Pouvez-vous montrer le code? – t0mm13b

+0

@ tommieb75: Ajouté à la question –

Répondre

0

J'ai réussi à résoudre ce problème de manière non optimale, très imparfaite, donc je serais toujours intéressé d'entendre si quelqu'un sait pourquoi la méthode SaveAs bloque AutoCAD et bloque mon application.

Voilà comment je l'ai fait:

Lors de l'ouverture d'un document ou la création d'un nouveau, éteignez les boîtes de dialogue ouvrir/enregistrer:

this._acadDocument.SetVariable("FILEDIA", 0); 

Lors de l'enregistrement d'un document, problème du passage de commande _SAVEAS dans « 2010 » comme le format et le nom du fichier (fullPath):

string commandString = string.Format(
    "(command \"_SAVEAS\" \"{0}\" \"{1}\") ", 
    "2010", 
    fullPath.Replace('\\', '/')); 

this._acadDocument.SendCommand(commandString); 

Lorsque vous quittez dialogue fichier tour AutoCAD demandant de retour sur (est probablement pas nécessaire mais juste fait sûr):

this._acadDocument.SetVariable("FILEDIA", 1); 
+0

@Andy: Ravi de vous entendre résolu ... façon bizarre de le faire! Ce qui est même surprenant, les docs n'ont pas averti ça !!!? !!! WTF! :) – t0mm13b

+0

Oui, la documentation a besoin d'une refonte massive. Heureusement, l'API .NET native a une documentation géniale, mais vous ne pouvez l'utiliser que dans AutoCAD - pas à partir d'une application externe comme j'essaie de le faire. Merci quand même. –

1

A en juger par le lien vers le forum de AutoDesk sur ce sujet, il semble que que vous avez besoin fermez l'objet après avoir sauvegardé ... et supprimez les null ... Si j'étais vous, j'emballerais le code dans les blocs try/catch pour vérifier et m'assurer qu'aucune exception n'est levée!

Je dois douter de l'utilisation de la clause using, comme vous êtes Launch sur une autre copie n'êtes-vous pas? c'est-à-dire dans les fonctions OpenDrawing et Save que vous utilisez this._acadApplication ou ai-je mal compris?

 
using (AutoCad cad = AutoCad.Instance) 
{ 
    try{ 
     // Launch AutoCAD 
     cad.Launch(); 

     // Open drawing 
     cad.OpenDrawing(@"C:\Scratch\Drawing01.dwg"); 

     // Save it 
     cad.SaveAs(@"C:\Scratch\Drawing01B.dwg"); 
    }catch(COMException ex){ 
     // Handle the exception here 
    } 
} 

public void Launch() 
{ 
    this._acadApplication = null; 
    const string ProgramId = "AutoCAD.Application.18"; 

    try 
    { 
     // Connect to a running instance 
     this._acadApplication = (AcadApplication)Marshal.GetActiveObject(ProgramId); 
    } 
    catch (COMException) 
    { 
     /* No instance running, launch one */ 

     try 
     { 
      this._acadApplication = (AcadApplication)Activator.CreateInstance(
       Type.GetTypeFromProgID(ProgramId), 
       true); 
     } 
     catch (COMException exception) 
     { 
      // Failed - is AutoCAD installed? 
      throw new AutoCadNotFoundException(exception); 
     } 
    } 

    /* Listen for the events we need and make the application visible */ 
    this._acadApplication.BeginOpen += this.OnAcadBeginOpen; 
    this._acadApplication.BeginSave += this.OnAcadBeginSave; 
    this._acadApplication.EndOpen += this.OnAcadEndOpen; 
    this._acadApplication.EndSave += this.OnAcadEndSave; 

#if DEBUG 
    this._acadApplication.Visible = true; 
#else 
    this._acadApplication.Visible = false; 
#endif 

    // Get the active document 
    // this._acadDocument = this._acadApplication.ActiveDocument; 
    // Comment ^^^ out? as you're instantiating an ActiveDocument below when opening the drawing? 
} 

public void OpenDrawing(string path) 
{ 
    try{ 
     // Request AutoCAD to open the document 
     this._acadApplication.Documents.Open(path, false, null); 

     // Update our reference to the new document 
     this._acadDocument = this._acadApplication.ActiveDocument; 
    }catch(COMException ex){ 
     // Handle the exception here 
    } 
} 

public void SaveAs(string fullPath) 
{ 
    try{ 
     this._acadDocument.SaveAs(fullPath, null, null); 
    }catch(COMException ex){ 
     // Handle the exception here 
    }finally{ 
     this._acadDocument.Close(); 
    } 
} 

Je pensais inclure des liens pour votre information.

Hope this helps, Respectueusement, Tom.

+0

Merci d'avoir essayé Tom. Aucune exception n'est levée - l'application est suspendue dans la méthode AcadDocument.SaveAs d'AutoCAD - elle bloque même AutoCAD et pas seulement mon application. Je ne peux pas enlever les NULL parce que la méthode SaveAs nécessite 3 paramètres, mais il n'y a pas de documentation me disant ce qu'il faut passer comme les 2 autres paramètres. Je ne peux pas non plus fermer le dessin car je dois continuer à travailler dessus une fois enregistré. –

+0

Non Je ne lance pas une autre copie d'AutoCAD, le code de la méthode Launch() utilise l'instance déjà exécutée (qui est ensuite référencée par _acadApplication). Lorsque vous lancez AutoCAD, il crée un document vierge dont vous avez besoin capable d'envoyer des commandes AutoCAD, donc la ligne que vous avez commentée est requise par mon application. Lorsque Documents.Open() est appelé, il crée un nouveau document et mon application fait référence à celui-ci au lieu du document vierge initial. –

+0

@Andy: C'est marrant, dans les liens que j'ai fournis, il y a un paramètre pour la sauvegarde ?! À moins que le COM ait changé pour la version plus récente d'AutoCAD - quelle version d'AutoCAD utilisez-vous réellement? – t0mm13b

2

De l'Autodesk discussion groups, il semble que le second paramètre est le type d'économiser et peut être nécessaire:

app = new AcadApplicationClass();
AcadDocument doc = app.ActiveDocument; doc.SaveAs("d:\Sam.dwg",AcSaveAsType.acR15_dwg,new Autodesk.AutoCAD.DatabaseServices.SecurityParameters());

Puisque vous êtes dans AutoCAD 2010, le type devrait être incrémenté à acR17_dwg ou acR18_dwg.

0

avec C# et COM, quand il y a des arguments optionnels, vous devez utiliser Type.Missing au lieu de null:

this._acadDocument.SaveAs(fullPath, Type.Missing, Type.Missing); 

Mais depuis Visual Studio 2010, vous pouvez simplement omettre les arguments optionnels:

this._acadDocument.SaveAs(fullPath); 
Questions connexes