cdinten 发表于 2014-11-11 22:45:42

获取ARX文件路径

本帖最后由 cdinten 于 2014-11-11 22:49 编辑

使用ObjectARX开发的插件,可能并不只有ARX文件,还会有其他的一些数据库文件、图片等资源文件,通常这些文件会和ARX文件放在同一个目录下,但是在AutoCAD加载了ARX文件之后,如何定位获取这些文件的路径呢?如果是dll文件,在DllMain函数的第一个参数就是其模块句柄,而ARX的入口函数AcRxEntryPoint中并没有带这个参数,只能自己想办法了。这里提供了几种获取ARX文件路径的方法:
void GetMyPath()
{
    ACHAR path=L"";
    HMODULE hMe;
    //ARX文件的名称
    hMe=GetModuleHandle(L"ArxHello.arx");
    if(hMe==NULL)
    {
      acutPrintf(L"\n获取模块句柄失败\n");
      return;
    }
    GetModuleFileName(hMe,path,MAX_PATH);
    //文件的绝对路径
    acutPrintf(L"\n%s\n",path);
    //文件所在文件夹
    ACHAR* pt=wcsrchr(path,L'\\');
    *(pt+1)='\0';
    acutPrintf(L"\n%s\n",path);
}
这个函数需要windows.h头文件的支持,实际上是调用了系统API,但是这个函数有个小问题,就是GetModuleHandle函数中的参数,必须是我们的ARX文件名,一旦ARX文件被重命名,这个函数就回调用失败,出现“获取模块句柄失败”的提示。另一个根号的方法是,使用增强版的获取模块句柄函数,这个系统API就是GetModuleHandleEx,可以在无需知道ARX文件名的情况下获取文件路径,但是使用时要格外小心,先贴一个出来给大家看看:
void GetMyPath()
{
ACHAR path=L"";
HMODULE hMe;
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,(ACHAR*)GetMyPath,&hMe);
if(hMe==NULL)
{
acutPrintf(L"\n获取模块句柄失败\n");
return;
}
GetModuleFileName(hMe,path,MAX_PATH);
//文件的绝对路径
acutPrintf(L"\n%s\n",path);
//文件所在文件夹
ACHAR* pt=wcsrchr(path,L'\\');
*(pt+1)='\0';
acutPrintf(L"\n%s\n",path);
}
这个函数运行之后也能获取路径,而且无论我们的ARX改成什么名字,放在哪里,都能正确显示路径。但是有个问题就是,运行过该函数之后,再使用命令将ARX卸载,虽然AutoCAD提示是成功卸载了,但是ARX文件还是被AutoCAD打开,似乎有内存没有被释放,试图删除ARX文件会失败,不知道是怎么回事吧?因为GetModuleHandleEx中出现了问题。仔细阅读了MSDN中的相关条款,GetModuleHandleEx在调用的时候,会让引用计数器加1,所以第一个参数才有GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,就是不让引用计数器加1,因此,如果不带该标志位的话,虽然AutoCAD看似卸载了该动态链接库文件,但是该动态链接库的引用计数还是1,所以,确实删不掉。找到了问题之后,解决起来就方便多了,这里有两种方式可供选择:A. 将GetModuleHandleEx的第一个参数改为6(也就是GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)B. GetModuleHandleEx的参数保持不变,在GetModuleFileName函数之后,加一句“FreeLibrary(hMe);”,也就是释放库函数。

最后,借个宝地做做广告,本人的博客:http://379910987.blog.163.com/ ,不定期发布一些个人学习二次开发和Windows编程相关的文章,和大家共同交流讨论,也请大家不吝赐教,共同进步。

netthree 发表于 2014-12-31 20:14:53

写的不错,赞一个!

三水合一 发表于 2015-1-1 10:32:27

恩,不错,赞一个

shellon 发表于 2015-1-3 18:16:48

太棒了,解决了大问题,谢谢楼主。

wxd20130610 发表于 2015-1-4 13:37:16

太好了,针对问题能够找到本质。

Gu_xl 发表于 2015-1-4 14:57:45

CString ArxPath = acedGetAppName();
或者:
ACHAR modulePath;
DWORD pathLength = GetModuleFileName(_hdllInstance, modulePath, 512);
CString ArxPath=modulePath;

对你动情 发表于 2015-8-27 10:08:41

页: [1]
查看完整版本: 获取ARX文件路径