Сохранить как в COM висит AutoCAD - PullRequest
3 голосов
/ 18 февраля 2010

Я реализую приложение, которое использует COM в интерфейсе ObjectARX AutoCAD для автоматизации действий рисования, таких как открытие и сохранение как.

Согласно документации, я должен быть в состоянии вызвать AcadDocument.SaveAs () и передать имя файла, «сохранить как тип» и параметр безопасности. В документации прямо указано, что если безопасность имеет значение NULL, никакие операции, связанные с безопасностью, не предпринимаются. Однако он не дает никаких указаний на правильный тип объекта для передачи в качестве параметра «сохранить как тип».

Я пытался вызвать SaveAs с именем файла и нулем для оставшихся аргументов, но мое приложение зависает при вызове этого метода, и AutoCAD кажется сбойным - вы все еще можете использовать ленту, но ничего не можете сделать с панелью инструментов и можете закрыть AutoCAD.

У меня такое ощущение, что мои параметры NULL вызывают здесь горе, но документации в отделе COM / VBA очень не хватает. На самом деле в нем говорится, что класс AcadDocument даже не имеет метода SaveAs, что он явно делает.

Кто-нибудь здесь реализовывал то же самое? Любое руководство?

В качестве альтернативы я использую метод SendCommand () для отправки команды _SAVEAS, но мое приложение управляет партией чертежа и должно знать а), если сохранение не удается, и б), когда сохранение завершено (что я ' я делаю, слушая событие EndSave.)

EDIT

Вот требуемый код - все, что он делает, - запускает AutoCAD (или подключается к запущенному экземпляру, если он уже запущен), открывает существующий чертеж, а затем сохраняет документ в новом месте (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");
}

Затем в моем классе AutoCad (this._acadDocument является экземпляром класса 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);
}

Ответы [ 4 ]

2 голосов
/ 28 апреля 2010

Из дискуссионных групп Autodesk похоже, что вторым параметром является тип для сохранения как, и может потребоваться:

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

Поскольку вы находитесь в AutoCAD 2010, тип должен быть увеличен до acR17_dwg или acR18_dwg.

1 голос
/ 18 февраля 2010

Судя по ссылке на форум AutoDesk на эту тему, похоже, что вам нужно закрыть объект после сохранения ... и удалить ноль ... Если бы я был вами, яОберните код в блоки try / catch, чтобы проверить и убедиться, что нет исключений!

Я должен подвергнуть сомнению использование предложения using, поскольку вы Launchне так ли?т. е. в функциях OpenDrawing и Save, которые вы используете this._acadApplication, или я неправильно понял?

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();
    }
}

Думаю, я бы включил несколько ссылок для вашей информации.

Надеюсь, это поможет, С уважением, Том.

0 голосов
/ 19 августа 2015

В C # и COM, когда есть необязательные аргументы, вам нужно использовать Type.Missing вместо нуля:

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

Но начиная с Visual Studio 2010, вы можете просто опустить необязательные аргументы:

this._acadDocument.SaveAs(fullPath);
0 голосов
/ 18 февраля 2010

Мне удалось решить эту проблему неоптимальным, очень несовершенным способом, поэтому мне все равно было бы интересно узнать, знает ли кто-нибудь, почему метод SaveAs вызывает сбой AutoCAD и приводит к зависанию моего приложения.

Вот как я это сделал:

При открытии документа или создании нового отключите диалоговые окна открытия / сохранения:

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

При сохранении документа введите команду _SAVEAS, указав "2010" в качестве формата и имени файла (fullPath):

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

this._acadDocument.SendCommand(commandString);

При выходе из диалогового окна AutoCAD Turn File снова запрашивает (возможно, не обязательно, но просто проверяет):

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