Getting the list of .NET-defined commands in AutoCAD
Here's an interesting question that came in from Kerry Brown:
Is there a way to determine the names of Commands loaded into Acad from assemblies ... either a global list or a list associated with a specific assembly ... or both :-)
I managed to put some code together to do this (although I needed to look into how AutoCAD does it to get some of the finer points). I chose to implement two types of command - one that gets the commands for all the loaded assemblies, and one that works for just the currently-executing assembly. The first one is quite slow, though - it takes time to query every loaded assembly - so I added a command that only queries assemblies with explicit CommandClass attributes.
I didn't write a command to get the commands defined by a specified assembly - that's been left as an exercise for the reader. :-)
Here is the C# code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Reflection;
using System.Collections.Specialized;
namespace GetLoadedCommands
{
public class Commands
{
[CommandMethod("TC")]
static public void ListCommandsFromThisAssembly()
{
// Just get the commands for this assembly
DocumentCollection dm =
Application.DocumentManager;
Editor ed =
dm.MdiActiveDocument.Editor;
Assembly asm =
Assembly.GetExecutingAssembly();
string[] cmds = GetCommands(asm, false);
foreach (string cmd in cmds)
{
ed.WriteMessage(cmd + "\n");
}
}
[CommandMethod("LCM")]
static public void ListMarkedCommands()
{
// Get the commands for all assemblies,
// but only those with explicit
// CommandClass attributes (much quicker)
StringCollection cmds = new StringCollection();
DocumentCollection dm =
Application.DocumentManager;
Editor ed =
dm.MdiActiveDocument.Editor;
Assembly[] asms =
AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly asm in asms)
{
cmds.AddRange(GetCommands(asm, true));
}
foreach (string cmd in cmds)
{
ed.WriteMessage(cmd + "\n");
}
}
[CommandMethod("LC")]
static public void ListCommands()
{
// Get the commands for all assemblies,
// marked or otherwise (much slower)
StringCollection cmds = new StringCollection();
DocumentCollection dm =
Application.DocumentManager;
Editor ed =
dm.MdiActiveDocument.Editor;
Assembly[] asms =
AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly asm in asms)
{
cmds.AddRange(GetCommands(asm, false));
}
foreach (string cmd in cmds)
{
ed.WriteMessage(cmd + "\n");
}
}
private static string[] GetCommands(
Assembly asm,
bool markedOnly
)
{
StringCollection sc = new StringCollection();
object[] objs =
asm.GetCustomAttributes(
typeof(CommandClassAttribute),
true
);
Type[] tps;
int numTypes = objs.Length;
if (numTypes > 0)
{
tps = new Type[numTypes];
for(int i=0; i < numTypes; i++)
{
CommandClassAttribute cca =
objs[i] as CommandClassAttribute;
if (cca != null)
{
tps[i] = cca.Type;
}
}
}
else
{
// If we're only looking for specifically
// marked CommandClasses, then use an
// empty list
if (markedOnly)
tps = new Type[0];
else
tps = asm.GetExportedTypes();
}
foreach (Type tp in tps)
{
MethodInfo[] meths = tp.GetMethods();
foreach (MethodInfo meth in meths)
{
objs =
meth.GetCustomAttributes(
typeof(CommandMethodAttribute),
true
);
foreach (object obj in objs)
{
CommandMethodAttribute attb =
(CommandMethodAttribute)obj;
sc.Add(attb.GlobalName);
}
}
}
string[] ret = new string[sc.Count];
sc.CopyTo(ret,0);
return ret;
}
}
}
And here's what happens when you run the various commands:
Command: TC
TC
LCM
LC
Command: LC
layer
TC
LCM
LC
Command: LCM
layer
Note: you'll see that our own module's command are not listed by LCM... if you add the CommandClass attribute, as mentioned in this earlier post, then they will be:
[assembly:
CommandClass(
typeof(GetLoadedCommands.Commands)
)
]
评论 (39)
zgEdYMNa
1*
1*
1*
1*
-1 OR 2+240-240-1=0+0+0+1
-1 OR 3+240-240-1=0+0+0+1
1'"
1����%2527%2522
@@3XutQ
0zUJLfBX
1*
1*
1*
1*
-1 OR 2+392-392-1=0+0+0+1
-1 OR 3+392-392-1=0+0+0+1
if(now()=sysdate(),sleep(15),0)
0'XOR(if(now()=sysdate(),sleep(15),0))XOR'Z
0"XOR(if(now()=sysdate(),sleep(15),0))XOR"Z
(select(0)from(select(sleep(15)))v)/*'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"*/
-1; waitfor delay '0:0:15' --
-1); waitfor delay '0:0:15' --
-1)); waitfor delay '0:0:15' --
1 waitfor delay '0:0:15' --
j3qc0q5D'; waitfor delay '0:0:15' --
B1qNiRbM'); waitfor delay '0:0:15' --
AsFgjhON')); waitfor delay '0:0:15' --
-5 OR 714=(SELECT 714 FROM PG_SLEEP(15))--
-5) OR 977=(SELECT 977 FROM PG_SLEEP(15))--
-1)) OR 418=(SELECT 418 FROM PG_SLEEP(15))--
rUN2pWjZ' OR 229=(SELECT 229 FROM PG_SLEEP(15))--
TLMRWn9O') OR 424=(SELECT 424 FROM PG_SLEEP(15))--
QMzVkFxV')) OR 514=(SELECT 514 FROM PG_SLEEP(15))--
*DBMS_PIPE.RECEIVE_MESSAGE(CHR(99)||CHR(99)||CHR(99),15)
'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||'
1'"
1����%2527%2522
@@DSe2I