I am trying to silently send a synchronous Lisp command to autocad from c# code.
Here's how we send a Synchronous command to autocad.
string textToSend = $"(command-s \"_.-layout\" \"_t\" {filePath} {layoutName})";
object acadDoc = Application.DocumentManager.MdiActiveDocument.GetAcadDocument();
acadDoc.GetType().InvokeMember("SendCommand", BindingFlags.InvokeMethod, null, acadDoc, new[] { textToSend + "\n" });
The command works but the problem is that the command ends up in autocad's command line and clogs up the history of the drafters using our extensions.
We tried modifying system variables CMDECHO, CMDDIA, and NOMUTT without success
I looked at the InvokeMember parameters but didn't see anything that might affect the display of the command like there exists for the ActiveDocument.SendTextToExecute() asynchronous command.
How do we send synchronous Lisp commands to autocad from c# code silently?
Ps: The reason why I am not using WBlockCloneObjects() is because it makes our apps extremely unstable. I am not really interested in opening that whole can of worms in this issue, I'm only stating this to explain why I ended up with the solution from my question.
The title of my question was misleading. I didn't need to run lisp code silently, I needed to run commands in acad's command line silently. It just happened to be that acad's command line accepts lisp code so that's what I was using.
Instead of running lisp code, I used the method ActiveDocument.Editor.Command()
to send my command to autocad. This method is synchronous and is affected by the system variable cmdecho
.
I encountered a subsequent problem; because I was calling this method from a button in the banner with RelayCommand
, Editor.Command
was throwing the exception eInvalidInput
because I was in the Application context instead of the Document context.
The best way to handle this was to split my first method in two and call the second method with ActiveDocument.SendStringToExecute()
which uses the command line so I end up in the Document context. But because SendstringToExecute()
is async, I had to rework my method's logic a bit.
Here is the final result (simplified)
private Layout Layout;
private RelayCommand _Command_Test;
public RelayCommand Command_Test
{
get
{
if (_Command_Test == null)
{
_Command_Test = new RelayCommand(
(param) =>
{
FirstMethod();
},
(param) =>
{
return true;
}
);
}
return _Command_Test;
}
}
[CommandMethod("FirstMethod")]
public void FirstMethod()
{
// Many actions and processing
Layout = new Layout(/*With stuff*/);
Application.DocumentManager.MdiActiveDocument.SendStringToExecute("SecondMethod ", true, false, false);
}
[CommandMethod("SecondMethod")]
public void SecondMethod()
{
short cmdecho = (short)Application.GetSystemVariable("cmdecho");
Application.SetSystemVariable("cmdecho", 0);
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
ed.Command("_.-layout", "_t", Layout.FilePath, Layout.Name);
Application.SetSystemVariable("cmdecho", cmdecho);
// Actions that need to be ran after the command
}
CommandMethod
can't receive parameters, I had to store information in the fields of the class.