pefi Posted December 9 Posted December 9 (edited) I can't find a better place - please move the topic if I missed it. Edit: TL,DR: how to cancel current command using pyautocad or win32com? Full version: I'm working an a simple code that takes info from excel and uses it to insert block(s) and change attribute values. The code works fine. I used a VBA version for a long time, but I decided to rewrite it due to speed problems in python using pyautocad and win32com libraries. I solved or safeguarded most of the problems, but I struggle to send double escape to cancel user input. The code is fully independent from user input and it does not need any user interaction. I want to prevent accidental typing into AutoCAD user prompt as it upsets the code. I can send double escape when there is nothing in the command prompt, but as soon as there is something there - the send command stops working, probably waiting for user input. Anyway - if there is anyone experienced with the python / AutoCAD integration I can prepare a sample code to show the problem. Edited December 9 by pefi add tldr Quote
SLW210 Posted December 9 Posted December 9 I moved your thread to the .NET, ObjectARX & VBA Forum. 1 Quote
Danielm103 Posted December 9 Posted December 9 I have some experience with python / AutoCAD integration with the wrappers I’m working on https://github.com/CEXT-Dan/PyRx Its all in process though, I don’t have much experience out of process though. Post a sample, I’ll try to help 1 Quote
pefi Posted December 9 Author Posted December 9 from pyautocad import Autocad import win32com.client print("Setting up pyautocad access...", end='') acad = Autocad(create_if_not_exists=True) print("done") print("Setting up win32com access...", end='') acad32 = win32com.client.Dispatch("AutoCAD.Application") print("done") print("Adding blank drawing...", end='') dwg = acad.Application.Documents.Add('') print("done") print("Sending a command with pyautocad...", end='') acad.doc.SendCommand("-PURGE\nAll\n\nN\n") print("done") print("Getting active document...", end='') ad = acad32.ActiveDocument print("done") print("Sending a command with win32com...", end='') ad.SendCommand("-PURGE\nAll\n\nN\n") print("done") If you run the code with AutoCAD closed or running it works fine as long as there is nothing typed in the command prompt. If there is something typed in the command prompt the code will fail with: Setting up pyautocad access...done Setting up win32com access...done Adding blank drawing...Traceback (most recent call last): File "C:/loop-generator/dwg-generator/error_demo.py", line 13, in <module> dwg = acad.Application.Documents.Add('') File "C:\Users\firsztp\AppData\Local\Programs\Python\Python313\Lib\site-packages\comtypes\client\dynamic.py", line 120, in __getattr__ dispid = self._comobj.GetIDsOfNames(name)[0] File "C:\Users\firsztp\AppData\Local\Programs\Python\Python313\Lib\site-packages\comtypes\automation.py", line 828, in GetIDsOfNames self.__com_GetIDsOfNames(riid_null, arr, len(names), lcid, ids) # type: ignore _ctypes.COMError: (-2147418111, 'Call was rejected by callee.', (None, None, None, 0, None)) Quote
pefi Posted December 9 Author Posted December 9 I'm testing a solution created after a session with an AI: import win32com.client import time # Create an instance of AutoCAD application acad = win32com.client.Dispatch("AutoCAD.Application") acad.Visible = True # Ensure AutoCAD is in focus shell = win32com.client.Dispatch("WScript.Shell") shell.AppActivate("AutoCAD") # Send the Escape key shell.SendKeys("{ESC}") # Allow a moment for the command to cancel time.sleep(1) Quote
Danielm103 Posted December 9 Posted December 9 Usually, the escape prefix is ‘^C^C’ as mentioned here, I.e. acad.doc.SendCommand("^C^C-PURGE…. ") https://www.keanw.com/2006/08/cancelling_an_a.html If a command is actually running, then there’s not much you can do because the document is most likely locked. However, you can test if AutoCAD is ready to except a command by using the Application.GetAcadState method https://help.autodesk.com/view/ACD/2024/ENU/?guid=GUID-0225808C-8C91-407B-990C-15AB966FFFA8 if you don’t need to be running out of process, and your version of CAD is compatible, you should try to run PyRx. It’s literally 100s of times faster than pyautocad. You get all or ActiveX and a big subset of ObjectArx 1 Quote
BIGAL Posted December 9 Posted December 9 (edited) Just a thought can you send this (chr 27) it is the escape key. Send character in Python. Edited December 10 by BIGAL Quote
pefi Posted December 11 Author Posted December 11 Thank you! I need to check closer PyRx...I have no clue about ActiveX or ObjectArx, but for the purpose of "insert block, replace attributes" should not be too hard to understand. Sending chr(27) was working only when there was blank prompt, I didn't try ^C, but the problem was not with what to send, but with the AutoCAD to accepting anything. P.S. I need to try ^C anyway.... Quote
pefi Posted December 11 Author Posted December 11 Replacing: self.acad.doc.SendCommand("_-INSERT" + " " + full_block_path + "\n" + "0,0,0" + "\n\n\n\n") with self.acad.doc.SendCommand("^C^C_-INSERT" + " " + full_block_path + "\n" + "0,0,0" + "\n\n\n\n") produces this: Command: ^C^C_-INSERT Unknown command "^C^C_-INSERT". Press F1 for help. Quote
Danielm103 Posted December 11 Posted December 11 “but with the AutoCAD to accepting anything.” then test IAcadState. state : Ax.IAcadState = theApp.GetAcadState() print(state.IsQuiescent) # True: AutoCAD is idle ActiveX is COM automation, this is what pyautocad and win32com use to communicate with AutoCAD. I used win32com’s makepy to generate the interface, then added converters to remove the need for variants. PyRx is in process, the procedure is load in a python script with PyLoad, then run it, a quick example import traceback from pyrx_impx import Rx, Ge, Gi, Db, Ap, Ed, Ax #creates a new command xdoit1 def PyRxCmd_xdoit1(): try: theApp = Ax.getApp() doc = theApp.ActiveDocument blk = doc.Blocks.Add([0, 0, 0], "MYBLOCK") blk.AddAttribute( 1, Ax.constants.acAttributeModeVerify, "New Prompt", [0, 0, 0], "NEW_TAG", "New Value", ) except Exception as err: traceback.print_exception(err) 1 Quote
Danielm103 Posted December 11 Posted December 11 24 minutes ago, pefi said: Replacing: self.acad.doc.SendCommand("_-INSERT" + " " + full_block_path + "\n" + "0,0,0" + "\n\n\n\n") with self.acad.doc.SendCommand("^C^C_-INSERT" + " " + full_block_path + "\n" + "0,0,0" + "\n\n\n\n") produces this: Command: ^C^C_-INSERT Unknown command "^C^C_-INSERT". Press F1 for help. Don’t use SendCommand, use the API axApp = Ax.getApp() path = "M:\\Dev\\Projects\\PyRxGit\\PySamples\\dwg\\18X36RP.dwg" ref = axApp.ActiveDocument.ModelSpace.InsertBlock((0, 0, 0), path, 1, 1, 1, 0) You may have to use APoint(0,0,0) Quote
pefi Posted December 11 Author Posted December 11 OK, but I also burst and purge, print to pdf using a custom command, so I need to use SendCommad anyway. I changed approach - try/except the whole drawing creation function and repeat after cleaning everything on any failure. Seems to be working. P.S. Digging into your bindings is something that I need to do - looks to good to stick with pyautocad or win32com. Do you mind adding an open source licence to your code in github? Quote
Danielm103 Posted December 11 Posted December 11 Note, Explode, PurgeAll and plot are all part of the API, accessible through pyautocad or win32com Quote Do you mind adding an open source licence to your code in github? I'll add it 1 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.