.NET

Reply
Distinguished Contributor
alex_b
Posts: 399
Registered: ‎08-15-2003
Message 1 of 24 (738 Views)

Retrieve Command names from ARX file

738 Views, 23 Replies
11-04-2012 06:41 PM

Hi,

 

I'm looking for a way of retrieving command names defined in an arx/dbx file, and doing it from an external process (i.e. without loading the file into AutoCAD).

Ditto for checking the Acad version the arx was compiled for.

Any pointers will be much appreciated.

 

Thanks in advance

 

alex

Moderator
Alexander.Rivilis
Posts: 1,431
Registered: ‎04-09-2008
Message 2 of 24 (727 Views)

Re: Retrieve Command names from ARX file

11-05-2012 05:29 AM in reply to: alex_b

Alex!

Without loading arx-file into AutoCAD you can not retrieve it's commands. More over arx-application can define/undefine commands real-time. 


Пожалуйста не забывайте про Утвердить в качестве решения! Утвердить в качестве решения и Give Kudos!Баллы
Please remember to Accept Solution! Accept as Solution and Give Kudos!Kudos

Distinguished Contributor
alex_b
Posts: 399
Registered: ‎08-15-2003
Message 3 of 24 (720 Views)

Re: Retrieve Command names from ARX file

11-05-2012 08:00 AM in reply to: Alexander.Rivilis

Why not?

 

This is exactly what AutoCAD does: it reads the file, retrieves the command strings and adds them to its commands table, etc. This is of course very simplistic but I think it is possible, having the right knowledge about the inner workings, string encoding etc.

I did it for ,NET plug-ins; of course it's easier with Reflection but...

 

alex

Employee
artc2
Posts: 216
Registered: ‎06-08-2010
Message 4 of 24 (715 Views)

Re: Retrieve Command names from ARX file

11-05-2012 08:10 AM in reply to: alex_b

AutoCAD does NOT read the file and retreive the command strings.  The command strings are provided to AutoCAD by the application as it is initializing.  The applications uses calls to .AcEdCommandStack::addCommand() to register the command strings with AutoCAD.  And, as Alexander has pointed out, commands can be registered and unregistred at any point while the application is loaded, so even if you were to read the file and somehow get the command strings, you would not know if/when those command strings would be registered with AutoCAD.

Distinguished Contributor
alex_b
Posts: 399
Registered: ‎08-15-2003
Message 5 of 24 (705 Views)

Re: Retrieve Command names from ARX file

11-05-2012 10:44 AM in reply to: artc2

Art

I stand corrected

>>..so even if you were to read the file and somehow get the command strings, you would not know if/when those command strings would be registered with AutoCAD.

I could live with that. I need them for cataloguing purposes, not for using them inside AutoCAD.

Is there a way to get the command strings?

What about checking the Acad version the arx was compiled for?

Thanks

alex

Moderator
Alexander.Rivilis
Posts: 1,431
Registered: ‎04-09-2008
Message 6 of 24 (696 Views)

Re: Retrieve Command names from ARX file

11-05-2012 11:08 AM in reply to: alex_b

alex_b wrote:

Art

I stand corrected

>>..so even if you were to read the file and somehow get the command strings, you would not know if/when those command strings would be registered with AutoCAD.

I could live with that. I need them for cataloguing purposes, not for using them inside AutoCAD.

Is there a way to get the command strings?

What about checking the Acad version the arx was compiled for?

Thanks

alex


Alex!
As far as I remember you using ObjectARX 12 years ago.  That is why I think you have to know that in order to register command arx application must call appropriate function. Without this calling AutoCAD do not know about command.

So there are NO methods to identify commands in arx-file.

Moreover there are NO (official) methods to identify for which version of AutoCAD arx-file was compiled.  

 


Пожалуйста не забывайте про Утвердить в качестве решения! Утвердить в качестве решения и Give Kudos!Баллы
Please remember to Accept Solution! Accept as Solution and Give Kudos!Kudos

Distinguished Contributor
alex_b
Posts: 399
Registered: ‎08-15-2003
Message 7 of 24 (691 Views)

Re: Retrieve Command names from ARX file

11-05-2012 11:57 AM in reply to: Alexander.Rivilis

Alexander

 

A for your memory. It is indeed 12 years, but I think at the time it was ADS not OARX. Nice of you to remember.

To the topic:

I know that inside AutoCAD the arx has to call addCommand() in order to let Acad 'know' about it.

But, what I'm looking for is just retrieving the command name strings using an out-of-process aplication.

The strings must be somwhere in the arx file, maybe encoded, but surely they can be found.

Ditto info about Acad version. The arx (or Acad) surely check version compatibility when the arx is loaded.

Granted the above info is not Officially published, but..

I'd hate to give up at this early stage.

 

alex

 

Mentor
khoa.ho
Posts: 219
Registered: ‎09-15-2011
Message 8 of 24 (675 Views)

Re: Retrieve Command names from ARX file

11-05-2012 05:18 PM in reply to: alex_b

Alex,

I also thought there should be a way to read ARX (native DLL) file using .NET, so I jumped to find the solution right after work.

To read a native DLL file, we should use the way Windows works now is to use method LoadLibrary/LoadLibraryEx (defined in kernel32.dll). This will return a pointer for the loaded native DLL file. From there, we use GetProcAddress (and something else) to read defined methods (and other info) in the native DLL file.

ARX file has two special methods: acrxGetApiVersion and acrxEntryPoint. So they could be starting points to find ARX version and stored command names. ObjectARX uses acedRegCmds->addCommand inside method acrxEntryPoint() to add a new AutoCAD command, so it may be something we hope to find from there.

The following code has the problem of using delegates of acrxGetApiVersion and acrxEntryPoint in .NET. I don't know exactly their signatures (found from DllImport) so it does not work now. However, it does read an ARX file and return pointers of acrxGetApiVersion and acrxEntryPoint for us to get started.

We should create a new console application in Visual Studio and copy the following code to Program.cs

 

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace AcadReflection
{
    class Program
    {
        /// <summary>
        /// To load the dll - dllFilePath dosen't have to be const - so I can read path from registry
        /// </summary>
        /// <param name="dllFilePath">file path with file name</param>
        /// <param name="hFile">use IntPtr.Zero</param>
        /// <param name="dwFlags">What will happend during loading dll
        /// <para>DONT_RESOLVE_DLL_REFERENCES = 0x00000001</para>
        /// <para>LOAD_LIBRARY_AS_DATAFILE = 0x00000002</para>
        /// <para>LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008</para>
        /// <para>LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010</para>
        /// </param>
        /// <returns>Pointer to loaded Dll</returns>
        [DllImport("kernel32")]
        private static extern IntPtr LoadLibraryEx(string dllFilePath, IntPtr hFile, uint dwFlags);

        /// <summary>
        /// To get function pointer from loaded dll 
        /// </summary>
        /// <param name="dllPointer">Pointer to Dll witch was returned from LoadLibraryEx</param>
        /// <param name="functionName">Function name with you want to call</param>
        /// <returns>Pointer to function</returns>
        [DllImport("kernel32", CharSet = CharSet.Ansi)]
        public extern static IntPtr GetProcAddress(IntPtr dllPointer, string functionName);

        private delegate string GetApiVersionAddress();
        private delegate int GetEntryPointAddress(int msg, IntPtr appId);

        static void Main(string[] args)
        {
            try
            {
                string assemblyFile = @"C:\Program Files\Autodesk\AutoCAD 2013\acblock.arx";

                // Load a native DLL file without loading dependencies
                IntPtr dllPointer = LoadLibraryEx(assemblyFile, IntPtr.Zero, 0x00000001);
                if (dllPointer == IntPtr.Zero)
                    throw new Win32Exception();

                IntPtr apiVersionAddress = GetProcAddress(dllPointer, "acrxGetApiVersion");
                if (apiVersionAddress == IntPtr.Zero)
                    throw new Win32Exception();

                IntPtr entryPointAddress = GetProcAddress(dllPointer, "acrxEntryPoint");
                if (entryPointAddress == IntPtr.Zero)
                    throw new Win32Exception();

                try
                {
                    var apiVersionAddressFunction = (GetApiVersionAddress)Marshal.GetDelegateForFunctionPointer(apiVersionAddress, typeof(GetApiVersionAddress));
                    var version = apiVersionAddressFunction();

                    var entryPointAddressFunction = (GetEntryPointAddress)Marshal.GetDelegateForFunctionPointer(entryPointAddress, typeof(GetEntryPointAddress));
                    var entryPoint = entryPointAddressFunction(1, IntPtr.Zero);
                }
                catch (AccessViolationException ex)
                {
                }
            }
            catch (Exception ex)
            {
            }
        }
    }
}

 

-Khoa

 

Distinguished Contributor
alex_b
Posts: 399
Registered: ‎08-15-2003
Message 9 of 24 (622 Views)

Re: Retrieve Command names from ARX file

11-06-2012 06:52 PM in reply to: khoa.ho

Khoa

 

THanks for replying.

I confess that the code you wrote is too advanced for me; I do not understand how you would get the parameter values of the call to acedRegCmds->addCommand() from inside acrxEntryPoint(), nor how we can get the return value of the call to acrxGetApiVersion().

Could you explain it a bit more?

Anyway, the signatures are:

[enum]AcRx::AppRetCode acrxEntryPoint([enum] AcRx::AppMsgCode msg, void* pkt)

acrxGetApiVersion(): can't get the signature (PRIVATE)

 

Thank you

 

alex

 NB

I found this on Google:

http://hi.baidu.com/qazqqcyq/item/35669b415875a88d833ae134

It looks like what we're trying to do.

I only I could read Chinese.

Mentor
khoa.ho
Posts: 219
Registered: ‎09-15-2011
Message 10 of 24 (605 Views)

Re: Retrieve Command names from ARX file

11-07-2012 07:39 AM in reply to: alex_b

Alex,

 

AutoCAD uses AcEdCommandStack reactor in the native DLL accore.dll (A2013) and other reference calls somewhere in acdbxx.dll to add and remove commands. So the .NET console app will not work without importing necessary methods from those C++ assemblies. It is a big challenge so I will check again after work.

 

-Khoa

Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.