I had a VBA routine that worked using SENDCOMMAND.
my VB.NET version does not work using SENDCOMMAND (well, it does work, just not at the right time).
I've looking into the problem I have found that SENDCOMMAND is asynchronous in the document context but not in the application context. What does that mean? There is document.editor.SENDCOMMAND, but no application.SENDCOMMAND (or is there?).
So I tried using acedcommand (&/or acedcmd) but i'm getting an IDE error saying "AcEdCommand' is not accessible in this context because it is 'Friend' "
what is the proper syntax or methodology for using acedcommand?
Solved! Go to Solution.
I had a VBA routine that worked using SENDCOMMAND.
my VB.NET version does not work using SENDCOMMAND (well, it does work, just not at the right time).
I've looking into the problem I have found that SENDCOMMAND is asynchronous in the document context but not in the application context. What does that mean? There is document.editor.SENDCOMMAND, but no application.SENDCOMMAND (or is there?).
So I tried using acedcommand (&/or acedcmd) but i'm getting an IDE error saying "AcEdCommand' is not accessible in this context because it is 'Friend' "
what is the proper syntax or methodology for using acedcommand?
Solved! Go to Solution.
Solved by _gile. Go to Solution.
Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"
Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"
Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Thanks for the link, but my C knowledge is very weak, I'm using VB.
what does this do:
private static extern int acedCmd(System.IntPtrvlist);
is it declaring a integer variable named acedcmd? no, not with an arguement.
so is it prototyping a function named acedcmd that has an arguement in the form of a system.intptrvlist type and returns an integer? & the intptrvlist is essentially the list of strings that you want to send?
but isn't acedcmd aldready a function?
Thanks for the link, but my C knowledge is very weak, I'm using VB.
what does this do:
private static extern int acedCmd(System.IntPtrvlist);
is it declaring a integer variable named acedcmd? no, not with an arguement.
so is it prototyping a function named acedcmd that has an arguement in the form of a system.intptrvlist type and returns an integer? & the intptrvlist is essentially the list of strings that you want to send?
but isn't acedcmd aldready a function?
[DllImport("acad.exe", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedCmd")] private static extern int acedCmd(System.IntPtr vlist);
The whole of the above is the code needed for PInvoke of acedCmd. The attribute (stuff between []) is the import of the command and it decorates the private static extern int acedCmd(System.IntPtr vlist) so the acedCmd is available in your code.
The System.IntPtr vlist is actually a result buffer that is created a few lines below:
ResultBuffer rb = new ResultBuffer(); // RTSTR = 5005 rb.Add(new TypedValue(5005, "_.INSERT")); // start the insert command acedCmd(rb.UnmanagedObject);
After you have the PInvoke and extern declared you can use the acedCmd as above, the result buffer holds a string (code 5005) and in this case the string is the insert command. This is how the acedCmd is used, you cant just send it a string directly, you need to use result buffers.
If you look at the documentation for result buffer you will see the different codes and how they work. If you google PInvoke you can get more details on how it works and what exactly is going on.
From the documentation the returned int:
The return value of acedCmd() does not indicate the success or failure of a command. The function usually returns RTNORM. It returns RTCAN if the user cancels the command by pressing [Ctrl]+[C] or [Ctrl]+[Break]. It returns RTERROR or RTREJ to indicate a failure of undefined origin, not a command failure.
RTNORM and RTCAN etc are integers defined somewhere else as constants in the ObjectARX files. Not sure off the top of my head where though.
One more edit, the private static extern int acedCmd(System.IntPtr vlist)
You see the System.IntPtr vlist in there, and from the documentation above you read:
int acedCmd(const struct resbuf * rbp);
[DllImport("acad.exe", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedCmd")] private static extern int acedCmd(System.IntPtr vlist);
The whole of the above is the code needed for PInvoke of acedCmd. The attribute (stuff between []) is the import of the command and it decorates the private static extern int acedCmd(System.IntPtr vlist) so the acedCmd is available in your code.
The System.IntPtr vlist is actually a result buffer that is created a few lines below:
ResultBuffer rb = new ResultBuffer(); // RTSTR = 5005 rb.Add(new TypedValue(5005, "_.INSERT")); // start the insert command acedCmd(rb.UnmanagedObject);
After you have the PInvoke and extern declared you can use the acedCmd as above, the result buffer holds a string (code 5005) and in this case the string is the insert command. This is how the acedCmd is used, you cant just send it a string directly, you need to use result buffers.
If you look at the documentation for result buffer you will see the different codes and how they work. If you google PInvoke you can get more details on how it works and what exactly is going on.
From the documentation the returned int:
The return value of acedCmd() does not indicate the success or failure of a command. The function usually returns RTNORM. It returns RTCAN if the user cancels the command by pressing [Ctrl]+[C] or [Ctrl]+[Break]. It returns RTERROR or RTREJ to indicate a failure of undefined origin, not a command failure.
RTNORM and RTCAN etc are integers defined somewhere else as constants in the ObjectARX files. Not sure off the top of my head where though.
One more edit, the private static extern int acedCmd(System.IntPtr vlist)
You see the System.IntPtr vlist in there, and from the documentation above you read:
int acedCmd(const struct resbuf * rbp);
yeah, looks like I might have to. The thing is that I already have a fully functional VBA routine that has a lot going on. To match the funtionality of VPLAYER, I'm going to have to do a great deal of additional work involving searching layertables & retrieving IDs. Just a lot of extra work to replicate something that already works in VBA. + the viewport object's methods don't cover all of the functinality of VPLAYER, therefore I have to write additional alogorithms to replicate the functionality that my VBA routine provided via VPLAYER.
It is rather irritating.
VB.NET, for me, is like using a jet fighter to go to the store to get some beer instead of using a car (VBA), when you have a car that runs & you know how to drive very well, but someone (microsoft) won't let you drive it anymore.
yeah, looks like I might have to. The thing is that I already have a fully functional VBA routine that has a lot going on. To match the funtionality of VPLAYER, I'm going to have to do a great deal of additional work involving searching layertables & retrieving IDs. Just a lot of extra work to replicate something that already works in VBA. + the viewport object's methods don't cover all of the functinality of VPLAYER, therefore I have to write additional alogorithms to replicate the functionality that my VBA routine provided via VPLAYER.
It is rather irritating.
VB.NET, for me, is like using a jet fighter to go to the store to get some beer instead of using a car (VBA), when you have a car that runs & you know how to drive very well, but someone (microsoft) won't let you drive it anymore.
I agree.
By my side, to get some beers at the store, I'd rather use AutoLISP with which you can easily script native commands.
Anyway, here's a little helper to use acedCmd with managed code (inspired by Tony Tanzillo's CommandLine (thanks again to him).
The Command method build the resultbuffer with the passed arguments.
EDIT: with A2013, replace "acad.exe" with "accore.dll" in the DllImport attribute arguments.
C#
[System.Security.SuppressUnmanagedCodeSecurity] [DllImport("acad.exe", EntryPoint = "acedCmd", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] extern static private int acedCmd(IntPtr resbuf); /// <summary> /// Call an AutoCAD command (runs synchronously). /// </summary> /// <param name="args">The command name followed by command inputs.</param> public static void Command(params object[] args) { ResultBuffer resbuf = new ResultBuffer(); foreach (object obj in args) { switch (obj.GetType().Name) { case "String": resbuf.Add(new TypedValue((int)LispDataType.Text, obj)); break; case "Int16": resbuf.Add(new TypedValue((int)LispDataType.Int16, obj)); break; case "Int32": resbuf.Add(new TypedValue((int)LispDataType.Int32, obj)); break; case "Double": resbuf.Add(new TypedValue((int)LispDataType.Double, obj)); break; case "Point2d": resbuf.Add(new TypedValue((int)LispDataType.Point2d, obj)); break; case "Point3d": resbuf.Add(new TypedValue((int)LispDataType.Point3d, obj)); break; case "ObjectId": resbuf.Add(new TypedValue((int)LispDataType.ObjectId, obj)); break; case "ObjectId[]": foreach (ObjectId id in (ObjectId[])obj) resbuf.Add(new TypedValue((int)LispDataType.ObjectId, id)); break; case "ObjectIdCollection": foreach (ObjectId id in (ObjectIdCollection)obj) resbuf.Add(new TypedValue((int)LispDataType.ObjectId, id)); break; case "SelectionSetDelayMarshalled": case "SelectionSetFullyMarshalled": resbuf.Add(new TypedValue((int)LispDataType.SelectionSet, obj)); break; default: throw new InvalidOperationException("Unsupported type in Command() method"); } } acedCmd(resbuf.UnmanagedObject); }
VB
<System.Security.SuppressUnmanagedCodeSecurity()> _ <DllImport("acad.exe", EntryPoint:="acedCmd", CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.Cdecl)> _ Private Shared Function acedCmd(resbuf As IntPtr) As Integer End Function '''<summary> ''' Call an AutoCAD command (runs synchronously). ''' </summary> ''' <param name="args">The command name followed by command inputs.</param> Public Shared Sub Command(ParamArray args As Object()) Dim resbuf As New ResultBuffer() For Each obj As Object In args Select Case obj.GetType().Name Case "String" resbuf.Add(New TypedValue(CInt(LispDataType.Text), obj)) Exit Select Case "Int16" resbuf.Add(New TypedValue(CInt(LispDataType.Int16), obj)) Exit Select Case "Int32" resbuf.Add(New TypedValue(CInt(LispDataType.Int32), obj)) Exit Select Case "Double" resbuf.Add(New TypedValue(CInt(LispDataType.[Double]), obj)) Exit Select Case "Point2d" resbuf.Add(New TypedValue(CInt(LispDataType.Point2d), obj)) Exit Select Case "Point3d" resbuf.Add(New TypedValue(CInt(LispDataType.Point3d), obj)) Exit Select Case "ObjectId" resbuf.Add(New TypedValue(CInt(LispDataType.ObjectId), obj)) Exit Select Case "ObjectId[]" For Each id As ObjectId In DirectCast(obj, ObjectId()) resbuf.Add(New TypedValue(CInt(LispDataType.ObjectId), id)) Next Exit Select Case "ObjectIdCollection" For Each id As ObjectId In DirectCast(obj, ObjectIdCollection) resbuf.Add(New TypedValue(CInt(LispDataType.ObjectId), id)) Next Exit Select Case "SelectionSetDelayMarshalled", "SelectionSetFullyMarshalled" resbuf.Add(New TypedValue(CInt(LispDataType.SelectionSet), obj)) Exit Select Case Else Throw New InvalidOperationException("Unsupported type in Command() method") End Select Next acedCmd(resbuf.UnmanagedObject) End Sub
Using examples (VB):
Draws a line.
Command("_.line", New Point3d(10.0, 20.0, 0.0), New Point3d(80.0, 50.0, 0.0), "")
Freezes the "0" layer in the selected viewport.
Command("_.vplayer", "_freeze", "0", "_select", "\", "", "")
Note:
- an empty string ("") means a validation (Enter)
- an anti-slash ("\" with VB or "\\" with C#) means a pause for user input.
I agree.
By my side, to get some beers at the store, I'd rather use AutoLISP with which you can easily script native commands.
Anyway, here's a little helper to use acedCmd with managed code (inspired by Tony Tanzillo's CommandLine (thanks again to him).
The Command method build the resultbuffer with the passed arguments.
EDIT: with A2013, replace "acad.exe" with "accore.dll" in the DllImport attribute arguments.
C#
[System.Security.SuppressUnmanagedCodeSecurity] [DllImport("acad.exe", EntryPoint = "acedCmd", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] extern static private int acedCmd(IntPtr resbuf); /// <summary> /// Call an AutoCAD command (runs synchronously). /// </summary> /// <param name="args">The command name followed by command inputs.</param> public static void Command(params object[] args) { ResultBuffer resbuf = new ResultBuffer(); foreach (object obj in args) { switch (obj.GetType().Name) { case "String": resbuf.Add(new TypedValue((int)LispDataType.Text, obj)); break; case "Int16": resbuf.Add(new TypedValue((int)LispDataType.Int16, obj)); break; case "Int32": resbuf.Add(new TypedValue((int)LispDataType.Int32, obj)); break; case "Double": resbuf.Add(new TypedValue((int)LispDataType.Double, obj)); break; case "Point2d": resbuf.Add(new TypedValue((int)LispDataType.Point2d, obj)); break; case "Point3d": resbuf.Add(new TypedValue((int)LispDataType.Point3d, obj)); break; case "ObjectId": resbuf.Add(new TypedValue((int)LispDataType.ObjectId, obj)); break; case "ObjectId[]": foreach (ObjectId id in (ObjectId[])obj) resbuf.Add(new TypedValue((int)LispDataType.ObjectId, id)); break; case "ObjectIdCollection": foreach (ObjectId id in (ObjectIdCollection)obj) resbuf.Add(new TypedValue((int)LispDataType.ObjectId, id)); break; case "SelectionSetDelayMarshalled": case "SelectionSetFullyMarshalled": resbuf.Add(new TypedValue((int)LispDataType.SelectionSet, obj)); break; default: throw new InvalidOperationException("Unsupported type in Command() method"); } } acedCmd(resbuf.UnmanagedObject); }
VB
<System.Security.SuppressUnmanagedCodeSecurity()> _ <DllImport("acad.exe", EntryPoint:="acedCmd", CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.Cdecl)> _ Private Shared Function acedCmd(resbuf As IntPtr) As Integer End Function '''<summary> ''' Call an AutoCAD command (runs synchronously). ''' </summary> ''' <param name="args">The command name followed by command inputs.</param> Public Shared Sub Command(ParamArray args As Object()) Dim resbuf As New ResultBuffer() For Each obj As Object In args Select Case obj.GetType().Name Case "String" resbuf.Add(New TypedValue(CInt(LispDataType.Text), obj)) Exit Select Case "Int16" resbuf.Add(New TypedValue(CInt(LispDataType.Int16), obj)) Exit Select Case "Int32" resbuf.Add(New TypedValue(CInt(LispDataType.Int32), obj)) Exit Select Case "Double" resbuf.Add(New TypedValue(CInt(LispDataType.[Double]), obj)) Exit Select Case "Point2d" resbuf.Add(New TypedValue(CInt(LispDataType.Point2d), obj)) Exit Select Case "Point3d" resbuf.Add(New TypedValue(CInt(LispDataType.Point3d), obj)) Exit Select Case "ObjectId" resbuf.Add(New TypedValue(CInt(LispDataType.ObjectId), obj)) Exit Select Case "ObjectId[]" For Each id As ObjectId In DirectCast(obj, ObjectId()) resbuf.Add(New TypedValue(CInt(LispDataType.ObjectId), id)) Next Exit Select Case "ObjectIdCollection" For Each id As ObjectId In DirectCast(obj, ObjectIdCollection) resbuf.Add(New TypedValue(CInt(LispDataType.ObjectId), id)) Next Exit Select Case "SelectionSetDelayMarshalled", "SelectionSetFullyMarshalled" resbuf.Add(New TypedValue(CInt(LispDataType.SelectionSet), obj)) Exit Select Case Else Throw New InvalidOperationException("Unsupported type in Command() method") End Select Next acedCmd(resbuf.UnmanagedObject) End Sub
Using examples (VB):
Draws a line.
Command("_.line", New Point3d(10.0, 20.0, 0.0), New Point3d(80.0, 50.0, 0.0), "")
Freezes the "0" layer in the selected viewport.
Command("_.vplayer", "_freeze", "0", "_select", "\", "", "")
Note:
- an empty string ("") means a validation (Enter)
- an anti-slash ("\" with VB or "\\" with C#) means a pause for user input.
how can I use LISP functions or custom commands with that Tony's method?
I can't figure that out
how can I use LISP functions or custom commands with that Tony's method?
I can't figure that out
thanks, it works for commands, but I can't find the right syntax for functions
i used a workaround, where i defined a command that just calls the function i need
thanks, it works for commands, but I can't find the right syntax for functions
i used a workaround, where i defined a command that just calls the function i need
in 2014, for the Case ObjectId[],
this line is givng a run time error (unsupported type in command() method )"
resbuf.Add(New TypedValue(CInt(LispDataType.ObjectId), id)
Not sure if this case ever woked in previous versions. This is a for a new routine for civil 3d featurelines
in 2014, for the Case ObjectId[],
this line is givng a run time error (unsupported type in command() method )"
resbuf.Add(New TypedValue(CInt(LispDataType.ObjectId), id)
Not sure if this case ever woked in previous versions. This is a for a new routine for civil 3d featurelines
so actually my problem was that I was sending a 3d point object to the _aeccbreakfeatureline command, which expects a station, so it nothing to do with the code in question.
so actually my problem was that I was sending a 3d point object to the _aeccbreakfeatureline command, which expects a station, so it nothing to do with the code in question.
Can't find what you're looking for? Ask the community or share your knowledge.