.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Editor confliction from Winform.

5 REPLIES 5
SOLVED
Reply
Message 1 of 6
genosyde
970 Views, 5 Replies

Editor confliction from Winform.

Hello. Everyone
I am always thanks for the help of the forum experts.
And I also make a new questions.
I am developing with Winform and .net.
The Question concerned AutoCad.Editor's memory crash by the sended event from Winform.
If I choose OK in the Editor's dialog, there is no problem.
However, if I cancel the Editor dialog by pressing ESC key on the CAD screen,
AutoCad goes memory crash and shows a horrible error window.

To prevent this,
using(doc.LockDocument()){
}
I used the dock.LockDocument() method in using() statment, but I couldn't prevent the crash.

In particular, when using the AudoCad.Editor in Winform, I am curious if there is an End Process that I must perform.
And I'm curious about why such a memory crash occurs, and what is the principle of the Editor.

 

Have a nice day and be healthy. ^^

Labels (1)
  • API
5 REPLIES 5
Message 2 of 6
norman.yuan
in reply to: genosyde

It is very difficult for me to make meaningful sense from your description. For example, what is "Editor dialog"? Locking document does not necessarily prevent AutoCAD from crash, its necessity depends on what context your code runs in (Application or Document context).

 

You might want to describe what you want the code to do and show the code, and indicate which line of the code causes the crash (if you ever stepped through your code in debug, you should be able to tell that).

Norman Yuan

Drive CAD With Code

EESignature

Message 3 of 6
genosyde
in reply to: norman.yuan

Sorry, I attatch my code.

 

//  Button Click Event

private void button_Trigger_Click(object sender, EventArgs e)
{
try
{
Button cBtn = sender as Button;

Excution exec = new Excution();
exec.IamCost(cBtn);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
}

 

//  CMD Excution

[CommandMethod("IamCost")]
public void IamCost(System.Windows.Forms.Button cBtn)
{

Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;

using (Transaction trfirst = db.TransactionManager.StartTransaction())
{
Editor ed = doc.Editor;

 

try
{
using (doc.LockDocument()) 
{

PromptPointResult ppr = ed.GetPoint("\nPick a Point.");
if (ppr.Status != PromptStatus.OK)
return;

.

.//Do somthing

.

 

}

}

}

 

Above a Red Statement is my problem.

If I hit my ESC Keyboard on AutoCad Screen, it goes to memory crash.

The Editor points PromptPointResult.

Message 4 of 6
norman.yuan
in reply to: genosyde

The method decorated with [CommandMethod(...)] should not have argument. As matter of fact, if the method is not static/Shared (as yours), if you run the command at command line ("IamCost"), AutoCAD will raise error (if the command method is static, having an argument would not raise error, but the argument would always be null). So, you need to remove the argument from the command method.

 

Then, you did not post code to show how the win form is displayed, and it is modeless or modal dialog. It is quite basic and important to understand the difference of modal and modeless dialog/window in conjunction with understanding code running context Application or document context. 

 

 

Norman Yuan

Drive CAD With Code

EESignature

Message 5 of 6
genosyde
in reply to: norman.yuan

First, Run Cmd on Pannel Icon

        [CommandMethod("SHOWCOSTFORM")]
        public void MainFormShow()
        {
            Form_Main mf = new Form_Main();
            mf.Show();
        }

 

 

Second,

Upper Cmd executed, It show a Form window.

Then Button Click Event is below.

        private void button_Trigger_Click(object sender, EventArgs e)
        {
            try
            {
                Button cBtn = sender as Button;

                Excution exec = new Excution();
                exec.IamCost();
                //exec.ExecuteContext();
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.ToString());
            }
        }

 

 

 

 

Third,

I used many PromptResult And one OverKill Cmd.

After OverKill Cmd, I hit keyboard ESC, then my API goes to hell memory crash.

So, I tried check AutoCad dll's Properties.

- accoremgd, localcopy : false

- acdbmgd, localcopy : false

- acmgd, localcopy : false

I use .NetFrameWork 4.7 and VS 2017.

 

            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            using (Transaction trfirst = db.TransactionManager.StartTransaction())
            {
                Editor ed1st = doc.Editor;
                Editor ed = doc.Editor;
                try
                {
                    using (doc.LockDocument())  //  모달리스 폼에 필요함
                    {
                        //  AutoCad 포커스
                        Autodesk.AutoCAD.Internal.Utils.SetFocusToDwgView();
Transaction trOverKill = db.TransactionManager.StartTransaction();
                        PromptSelectionResult selection;
                        Point3d resultPoint = new Point3d();

                        PromptPointResult ppr = ed.GetPoint("\nPick a Point on Screen.");
                        if (ppr.Status == PromptStatus.Cancel)
                            return;

                        resultPoint = ppr.Value;

                        //  형태별 객체 담기 후 OVERKILL
                        using (trOverKill)
                        {
                            var filter = new SelectionFilter(new[]
                            {
                                new TypedValue(-4, "<OR"),
                                new TypedValue(0, "ARC,CIRCLE,ELLIPSE,LINE,LWPOLYLINE,SPLINE,POINT"),
                                new TypedValue(-4, "<AND"),
                                new TypedValue(0, "POLYLINE"), // polylines 2d or 3d
                                new TypedValue(-4, "<NOT"), // but not meshes
                                new TypedValue(-4, "&"),
                                new TypedValue(70, 112),
                                new TypedValue(-4, "NOT>"),
                                new TypedValue(-4, "AND>"),
                                new TypedValue(-4, "OR>"),
                                //new TypedValue(0, "TEXT,MTEXT"), // only DBText or MText
                                //new TypedValue(410, "Model")     // in model space
                            });

                            PromptSelectionOptions pso = new PromptSelectionOptions();
                            pso.MessageForAdding = "Drag objects on AutoScreen.)";
                            selection = ed.GetSelection(pso, filter);
                            if (selection.Status != PromptStatus.OK)
                                return;

                            ed.WriteMessage("\nOVERKILL 실행!");
                            ed.Command("_-overkill", selection.Value, "", "");

                        Transaction tr = db.TransactionManager.StartTransaction();
                        using (tr)
                        {
                            //  소재명, 소재 정보를 선택 안했을 시 실행
                            PromptSelectionOptions pso = new PromptSelectionOptions();
                            if (multiTextList == null || multiTextList.Count == 0)
                            {
                                //  Get Text
                                TypedValue[] tvs = new[]
                                {
                                    new TypedValue(0, "TEXT,MTEXT"), // only DBText or MText
                                    new TypedValue(410, "Model")     // in model space
                                };
                                SelectionFilter filter = new SelectionFilter(tvs);


                                pso.MessageForAdding = "Pick a Text.";
                                selection = ed.GetSelection(pso, filter);
                                if (selection.Status != PromptStatus.OK)
                                    return;
                                foreach (ObjectId id in selection.Value.GetObjectIds())
                                {
                                    try
                                    {
                                        Entity tmpEnt = (Entity)tr.GetObject(id, OpenMode.ForRead);
                                        if (tmpEnt.GetType() == typeof(MText))
                                            multiTextList.Add(tmpEnt);
                                    }
                                    catch (System.Exception ex)
                                    {

                                    }
                                }
                            }


                            PromptStringOptions psoLossApply = new PromptStringOptions("Bla Bla Bla?(y/n)");
                            PromptResult psrLossApply = ed.GetString(psoLossApply);
                            if (psrLossApply.Status == PromptStatus.OK)
                            {
                                if (psrLossApply.StringResult.ToString().Replace(" ","").Length == 0) materialCostApply = true;
                                else if (psrLossApply.StringResult.ToUpper().Contains("Y")) materialCostApply = true;
                                else if (psrLossApply.StringResult.ToUpper().Contains("N")) materialCostApply = false;
                            }    
.
.
.
// Do more question to user by use a PromptResult
                        

 

Finally, I attatch Error log, But it's korean.

final error log says JIT Debugging and request changing machine.config's setting.

I can't find machine.config file in my vs solution.

 

please, let me know what's the problem.

thanks.

 

 

 

-------------------------- log

************** JIT 디버깅 **************
JIT(Just In Time) 디버깅을 사용하려면 이 응용 프로그램 또는 컴퓨터의
config 파일(machine.config)의 jitDebugging 값을
system.windows.forms 섹션에 설정해야 합니다.
또한 응용 프로그램은 디버깅할 수 있도록 컴파일되어야
합니다.

예:

<configuration>
<system.windows.forms jitDebugging="true" />
</configuration>

JIT 디버깅을 사용하면 처리되지 않은 모든 예외는
이 대화 상자에서 처리되지 않고 컴퓨터에 등록된 JIT
디버거에 보내집니다.

Message 6 of 6
norman.yuan
in reply to: genosyde

Here are some critiques to your code:

 

1. You DO NOT show dialog/window, be it Win Form, or WPF, with Form[Window].Show()/ShowDialog() in AutoCAD .NET add-in. You should use overloaded Application.ShowModal[Modeless]Dislog[Window]() methods.

 

2. Creating new instance of floating/modeless form whenever user execute user command "SHOWCOSTFORM" is bad idea: if user keep hit "Enter", the command would repeatedly create/show new forms all floating on top of AutoCAD. I

 

3. Using modeless form needs extra care to coding, it is rather advanced coding skill. Do you really need the form to be modeless (floating)? Is the data showing on the UI related to the active document? If it is, what happens if the user switch to another document (because the form is modeless, so, user can change active document)? the data on the form obviously need to reflect the newly activated document, or you need to hide the form so user does not see data from previous document while facing a different document. Usually, when using modeless form out of necessity, the form should be instantiated as singleton object and live in the AutoCAD session once instantiated.

 

4. If user interaction with the form, such as button_Clcik, to execute your code that does something with AutoCAD, the code is executed in Application context, where you CANNOT call Editor.Command() (as you did in your code). To do something with modeless form is to use Document.SendTextToExecute() to excute your code wrapped in CommandMethod.

 

5. I do not see/understand why you need to use multiply nested transactions (up to 3 levels of nesting!) in your code

 

Anyway, assume you are sure you must use modeless form, here are the skeleton of code I put together out head with NotePad (thus, no syntax check):

 

This is the CommandClass:

public class Execution
{
  private static Form_Main _form=null;

  [CommandMethod("ShowForm", CommandFlags.Session)]
  public static void ShowMainForm()
  {
    if (_form==null)
    {
      _form=new Form_Main()
    }
    Application.ShowModelessDialog(_form)
  }

  [CommandMethod("DoWork")]
  public static void DoMyWork()
  {
    var doc=Application.DocumentManager.MdiActiveDocument;
    var ed = doc.Editor;

    // If you need get some user inputs from the form, 
    // for code execition, you can do it here
    // var data1=_form.XXXXX;
    // var data2=_form.YYYYY;
    
    // Do whatever, including calling Editor.Command()
  }
}

  As you can see, the form is declared as static. And following codes in the form's code behind do:

 

1. Make sure the form is not closed but invisible, when user tries to close the form, thus keep the form instance as singleton:

private void Form_Closing(object sender, FormClosingEventArgs e)
{
  e.Cancel=true;
  this.Visibile=false;
}

 

2. When user clicks the button to let your code do the work, it uses SendTextToExecute() to execute the command "DoWork", which could also be executed at command line, of course:

 

private void button_Trigger_Click(object sender, EventArgs e)
{
  var doc=Application.DocumentManager.MdiActiveDocument;
  doc.SendStringToExection("DoWork ",true, false, false);
}

 

I'd strongly suggest you to pay attention/study on the differences of using modeless or modal form. The issue you have is mainly because of showing the form as modeless and using the wrong method to show it (i.e. using Form.Show()).

 

Norman Yuan

Drive CAD With Code

EESignature

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report