AutoCAD only works with one file when trying to plot multiple files using plugin written in C# .NET. How to solve it?

StackOverflow https://stackoverflow.com/questions/14369604

  •  16-01-2022
  •  | 
  •  

Question

everybody!

I wrote this code:

// (C) Copyright 2013 by  
//
using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.PlottingServices;
using AutoCAD;

// This line is not mandatory, but improves loading performances
[assembly: CommandClass(typeof(AutoCAD_CSharp_plug_in2.MyCommands))]

namespace AutoCAD_CSharp_plug_in2
{

// This class is instantiated by AutoCAD for each document when
// a command is called by the user the first time in the context
// of a given document. In other words, non static data in this class
// is implicitly per-document!
public class MyCommands
{
    static String[] arquivos = new String[] 
    {
        "C:/Users/igor.okuyama/Desktop/IS-PRS-0355-2047-0453_0_001.dxf",
        "C:/Users/igor.okuyama/Desktop/IS-PRS-0355-2047-0453_0_002.dxf"
    };
    static int count = arquivos.Length;
    static String arq = arquivos[count - 1];

    void MdiActiveDocument_CommandEnded(object sender, CommandEventArgs e)
    {
        Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n count:" + count.ToString() + "  " + e.GlobalCommandName + "\n");
        if (e.GlobalCommandName == "CONVERSOR")
        {
            //((AcadDocument)Application.DocumentManager.MdiActiveDocument.GetAcadDocument()).SendCommand("OPENFILE ");
            Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n terminei conversor: " + arq + "\n");
            Application.DocumentManager.MdiActiveDocument.SendStringToExecute("OPENFILE\n", true, false, true);
        }
        else if (e.GlobalCommandName == "OPENFILE")
        {
            //((AcadDocument)Application.DocumentManager.MdiActiveDocument.GetAcadDocument()).SendCommand("PLOTTOPDF ");
            Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n terminei openfile: " + arq + "\n");
            Application.DocumentManager.MdiActiveDocument.SendStringToExecute("PLOTTOPDF\n", true, false, true);
        }
        else if (e.GlobalCommandName == "PLOTTOPDF")
        {
            Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n terminei plottopdf: " + arq + "\n");
            //((AcadDocument)Application.DocumentManager.MdiActiveDocument.GetAcadDocument()).SendCommand("CLOSEFILE ");
            Application.DocumentManager.MdiActiveDocument.SendStringToExecute("CLOSEFILE\n", true, false, true);
        }
        else if (e.GlobalCommandName == "CLOSEFILE")
        {
            Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n terminei closefile: " + arq + "\n");
            count--;
            if (count > 0)
            {
                arq = arquivos[count - 1];
                //((AcadDocument)Application.DocumentManager.MdiActiveDocument.GetAcadDocument()).SendCommand("CONVERSOR ");
                Application.DocumentManager.MdiActiveDocument.SendStringToExecute("CONVERSOR\n", true, false, true);
            }
        }
    }


    [CommandMethod("OPENFILE", CommandFlags.Session)]
    public void OpenFile()
    {
        Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("OPENFILE ACIONADO. Arq: "+arq);
        Document doc = Application.DocumentManager.Open(arq);
        if (!doc.IsActive)
        {
            AcadDocument aDoc = (AcadDocument)doc.GetAcadDocument();
            aDoc.Activate();
        }
        //Application.DocumentManager.MdiActiveDocument.CommandEnded -= new CommandEventHandler(MdiActiveDocument_CommandEnded);
        //Application.DocumentManager.MdiActiveDocument.CommandEnded += new CommandEventHandler(MdiActiveDocument_CommandEnded);

    }

    [CommandMethod("CLOSEFILE", CommandFlags.Session)]
    public void CloseFile()
    {
        Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("CLOSEFILE ACIONADO. Arq: " + arq);
        Application.DocumentManager.MdiActiveDocument.CloseAndDiscard();
        //Application.DocumentManager.MdiActiveDocument.CommandEnded -= new CommandEventHandler(MdiActiveDocument_CommandEnded);
        //Application.DocumentManager.MdiActiveDocument.CommandEnded += new CommandEventHandler(MdiActiveDocument_CommandEnded);
    }

    [CommandMethod("PLOTTOPDF", CommandFlags.Session)]
    public void PlotToPDF()
    {
        short bgPlot = (short)Application.GetSystemVariable("BACKGROUNDPLOT");

        //set the BACKGROUNDPLOT = 0 temporarily.
        Application.SetSystemVariable("BACKGROUNDPLOT", 0);
        Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("PLOTFILE ACIONADO. Arq: " + arq);
        Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n + Um plot simples. " + "\n");

        Document doc =

          Application.DocumentManager.MdiActiveDocument;

        Editor ed = doc.Editor;

        Database db = doc.Database;

        Transaction tr =

          db.TransactionManager.StartTransaction();

        using (tr)
        {

            // We'll be plotting the current layout

            BlockTableRecord btr = CreateBlockTableRecord(db, tr);

            Layout lo = CreateLayout(tr, btr);

            PlotInfo pi = ConfigurePlotInfo(btr);

            PlotSettings ps = CreatePlotSettings(lo);

            CreatePlotSettings(ps);

            LinkPlotInfoToPlotSettings(pi, ps);

            // A PlotEngine does the actual plotting

            // (can also create one for Preview)

            if (PlotFactory.ProcessPlotState ==

                ProcessPlotState.NotPlotting)
            {

                PlotEngine pe =

                  PlotFactory.CreatePublishEngine();

                using (pe)
                {

                    // Create a Progress Dialog to provide info

                    // and allow thej user to cancel

                    PlotProgressDialog ppd =

                      new PlotProgressDialog(false, 1, true);

                    using (ppd)
                    {

                        ppd.set_PlotMsgString(

                          PlotMessageIndex.DialogTitle,

                          "Custom Plot Progress"

                        );

                        ppd.set_PlotMsgString(

                          PlotMessageIndex.CancelJobButtonMessage,

                          "Cancel Job"

                        );

                        ppd.set_PlotMsgString(

                          PlotMessageIndex.CancelSheetButtonMessage,

                          "Cancel Sheet"

                        );

                        ppd.set_PlotMsgString(

                          PlotMessageIndex.SheetSetProgressCaption,

                          "Sheet Set Progress"

                        );

                        ppd.set_PlotMsgString(

                          PlotMessageIndex.SheetProgressCaption,

                          "Sheet Progress"

                        );

                        ppd.LowerPlotProgressRange = 0;

                        ppd.UpperPlotProgressRange = 100;

                        ppd.PlotProgressPos = 0;

                        // Let's start the plot, at last

                        ppd.OnBeginPlot();

                        ppd.IsVisible = true;

                        pe.BeginPlot(ppd, null);

                        // We'll be plotting a single document
                        Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(doc.Name);
                        AcadDocument ppp = (AcadDocument)doc.GetAcadDocument(); //ou GetAcadDocument()
                        String nome_arq = ppp.Name;
                        nome_arq = nome_arq.Remove(nome_arq.Length - 4, 4);

                        pe.BeginDocument(

                              pi,

                              doc.Name,

                              null,

                              1,

                              true, // Let's plot to file

                              "c:\\" + nome_arq

                            );

                            // Which contains a single sheet

                            ppd.OnBeginSheet();

                            ppd.LowerSheetProgressRange = 0;

                            ppd.UpperSheetProgressRange = 100;

                            ppd.SheetProgressPos = 0;

                            PlotPageInfo ppi = new PlotPageInfo();

                            pe.BeginPage(

                              ppi,

                              pi,

                              true,

                              null

                            );

                            pe.BeginGenerateGraphics(null);

                            pe.EndGenerateGraphics(null);

                            // Finish the sheet

                            pe.EndPage(null);

                            ppd.SheetProgressPos = 100;

                            ppd.OnEndSheet();

                            // Finish the document

                            pe.EndDocument(null);


                        // And finish the plot

                        ppd.PlotProgressPos = 100;

                        ppd.OnEndPlot();

                        pe.EndPlot(null);

                    }

                }

            }

            else
            {

                ed.WriteMessage(

                  "\nAnother plot is in progress."

                );

            }

        }


    }

    private static void LinkPlotInfoToPlotSettings(PlotInfo pi, PlotSettings ps)
    {
        // We need to link the PlotInfo to the

        // PlotSettings and then validate it

        pi.OverrideSettings = ps;

        PlotInfoValidator piv =

          new PlotInfoValidator();

        piv.MediaMatchingPolicy =

          MatchingPolicy.MatchEnabled;

        piv.Validate(pi);
    }

    private static void CreatePlotSettings(PlotSettings ps)
    {
        // The PlotSettingsValidator helps

        // create a valid PlotSettings object

        PlotSettingsValidator psv =

          PlotSettingsValidator.Current;

        // We'll plot the extents, centered and

        // scaled to fit

        psv.SetPlotType(

          ps,

          Autodesk.AutoCAD.DatabaseServices.PlotType.Extents

        );

        psv.SetUseStandardScale(ps, true);

        psv.SetStdScaleType(ps, StdScaleType.ScaleToFit);

        psv.SetPlotCentered(ps, true);

        // We'll use the standard DWF PC3, as

        // for today we're just plotting to file

        psv.SetPlotConfigurationName(

          ps,

          "DWG To PDF.pc3",

          "ANSI_A_(8.50_x_11.00_Inches)"

        );
    }

    private static PlotSettings CreatePlotSettings(Layout lo)
    {
        // We need a PlotSettings object

        // based on the layout settings

        // which we then customize

        PlotSettings ps =

          new PlotSettings(lo.ModelType);

        ps.CopyFrom(lo);
        return ps;
    }

    private static PlotInfo ConfigurePlotInfo(BlockTableRecord btr)
    {
        // We need a PlotInfo object

        // linked to the layout

        PlotInfo pi = new PlotInfo();

        pi.Layout = btr.LayoutId;
        return pi;
    }

    private static Layout CreateLayout(Transaction tr, BlockTableRecord btr)
    {
        Layout lo =

          (Layout)tr.GetObject(

            btr.LayoutId,

            OpenMode.ForRead

          );
        return lo;
    }

    private static BlockTableRecord CreateBlockTableRecord(Database db, Transaction tr)
    {
        BlockTableRecord btr =

          (BlockTableRecord)tr.GetObject(

            db.CurrentSpaceId,

            OpenMode.ForRead

          );
        return btr;
    }


    [CommandMethod("CONVERSOR", CommandFlags.Session)]
    public void Conversor()
    {
        //Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
        //PromptStringOptions pso = new PromptStringOptions("");
        //pso.AllowSpaces = true;
        //PromptResult res = ed.GetString("\nEnterName:");
        //diretorio = res.StringResult;
        //Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("diretorio" + diretorio);
        Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("CONVERSOR ACIONADO. Arq: " + arq);
        Application.DocumentManager.MdiActiveDocument.CommandEnded += new CommandEventHandler(MdiActiveDocument_CommandEnded);

    }

}

}

As you can see here, it is a state machine that has four states: CONVERSOR, OPEN, PLOTTOPDF, CLOSE. I read N files in the disk and stay in this loop through states until there is no mroe file to be processing. I expected all dxfs files converted to pdf. When i running this for just one file, it works properly. The problem is this:

Imagine i go through CONVERSOR -> OPEN -> PLOTTOPDF -> CLOSE in the first file. AutoCAD opens the file, switch the active document and i can't enter in CLOSE state and then my machine state stops in PLOTTOPDF state. (Even the first file is not closed, but is converted to pdf properly). Anyone can help with this? I think the problem is that when I open a new file, the active document changes and AutoCAD loses itself in seeing if a command has finished or not.

Was it helpful?

Solution

The layout must be current in order to be plotted. So you have to make a call to:

Application.DocumentManager.MdiActiveDocument = doc;
LayoutManager.Current.CurrentLayout = layoutName;

Otherwise, the name of the method CreateLayout is wrong. You are not creating a layout, you just get it.

And I don't understand why you are using COM in order to get the name of the document.

AcadDocument ppp = (AcadDocument)doc.GetAcadDocument();
String nome_arq = ppp.Name;
nome_arq = nome_arq.Remove(nome_arq.Length - 4, 4);

Can be replaced by:

nome_arq = System.IO.Path.GetFileNameWithoutExtension(doc.Name);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top