2

I'm trying to mark my drawing before I programmatically insert a block so that I can programmatically undo the action if it only partially completes because of an error. Right now that insert method looks like this

public void askForInsertionPoint
{
StateManagementExtensions.MarkPosition();
try
{
    PromptPointResult pr = ed.GetPoint("\nSelect insertion point: ");
    Point3d insPt = pr.Value;
}
catch(Exception e)
{
 //TODO handle exception with undo
}
}

MarkPosition is defined as

public static void MarkPosition()
{
doc.SendStringToExecute("MARKPOS ", true, false, true);
}

Finally, sending MARKPOS to the command line as i do above calls this method

[CommandMethod("MARKPOS")]
public void MarkPosition()
{
Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
ed.Command("UNDO", "M");
}

The pointprompt somehow beats the MARKPOS call to the AutoCAD commandline so it tries to enter MARKPOS as the insertion point instead of pausing the C# method to wait for MARKPOS to execute as a command. How do I signal the program to wait and execute the MARKPOS command before prompting for the insertion point? I've tried Thread.sleep() after the SendStringToExecute call and that didn't work.

Nick Gilbert
  • 4,159
  • 8
  • 43
  • 90
  • Why don't you call `MarkPosition` directly? (or perhaps `ed.Command("UNDO", "M");`?) – crashmstr Apr 02 '15 at 18:57
  • Because doing that raises an eInvalidInput exception for some reason – Nick Gilbert Apr 02 '15 at 19:39
  • I mostly work with RealDWG now, but could you use a [Transaction](http://docs.autodesk.com/ACD/2010/ENU/AutoCAD%20.NET%20Developer's%20Guide/index.html?url=WS73099cc142f48755-5c83e7b1120018de8c0-3c0.htm,topicNumber=d0e54861) instead of setting an undo mark? – crashmstr Apr 02 '15 at 19:50

2 Answers2

2

Wrap your function in a Transaction. If the Transaction doesn't commit then nothing will have to be rolled back.

If you want to be a perfectionist, store the current view location at the start of the routine so you can reset the zoom/location after your command.

Miiir
  • 731
  • 1
  • 9
  • 12
  • Correct. Commands executed with SendStringToExecute are asynchronous and are not invoked until the .NET command has ended. That's why the pointprompt is shown first. Use the transaction to handle it inside the code. If you want the User to have a Undo option, then a quick and dirty method is to make your own function also start from the sendstring to execute after a undo mark. – Alain Apr 07 '15 at 06:58
  • I can't just count on the nature of transactions because I want to do combinations of multiple transactions and non-transaction methods and roll them all back if there is a failure at any point – Nick Gilbert Apr 07 '15 at 14:56
  • 1
    The nature of transactions is quite predictable, where as the nature of sendStringtoExecute isn't :-). In My opinion there's nothing wrong with nesting your transactions and adding your "non transaction methods" inside a transaction. – Alain Apr 08 '15 at 06:19
  • You could try using TopTransaction to encapsualte the lot in one undo step: http://spiderinnet1.typepad.com/blog/2012/06/autocad-net-toptransaction-use-and-its-pros-cons.html – CAD bloke Apr 15 '15 at 13:50
0

Call one command inside another will require the first to be Transparent

[CommandMethod("nameHere", CommandFlags.Transparent)]

But as the SendStringToExecute is async, you still have problems... You'll probably need to use Editor.Commad instead.

Augusto Goncalves
  • 8,493
  • 2
  • 17
  • 44