ImageMagick - MAGICK_CODER_MODULE_PATH 测试结果, 很受伤
//通过查看 ImageMagick 源代码 (F:\c常用软件\ImageMagick\ImageMagick-6.8.9-src\magick\module.c 662行) (F:\c常用软件\ImageMagick\ImageMagick-6.8.9-src\magick\string.c 1232行)
//首先会查找: module_path=GetEnvironmentValue("MAGICK_CODER_MODULE_PATH"); 也就是 -> getenv("MAGICK_CODER_MODULE_PATH"); 读取系统变量
整个测试分两部分, 首先测试通过设置[环境变量]:MAGICK_CODER_MODULE_PATH
注意:在 exe 源代码中通过 putenv() 或 SetEnvironmentVariable() 设置环境变量,在 dll(ImageMagick) 中是无法读取到的:
GetEnvironmentValue("MAGICK_CODER_MODULE_PATH") = NULL
https://stackoverflow.com/questions/25164478/setting-environmrnt-variables-for-dlls-in-ms-windows
https://stackoverflow.com/questions/5153547/environment-variables-are-different-for-dll-than-exe
//关于修改[环境变量]的说明
//putenv()用来改变或增加环境变量的内容。参数envvar的格式为envvar=value,如果该环境变量原先存在,则变量内容会依参数envvar改变,
//否则此参数内容会成为新的环境变量, 返回值: 执行成功则返回0,有错误发生则返回-1: 无法配置新的环境变量空间
//注意:设置的环境仅对程序本身有效(目测对进程中已经加载的dll也无效)。
//你在程序里做的改变不会反映到外部环境中,这是因为变量的值不会从子进程传播到父进程,这样做更安全。
//但是: 子进程继承父进程的环境变量 (默认情况下,子进程继承父进程环境变量内存块的一份拷贝)
//最后说明: 通过在 xp 和 win8.1 上测试表明:
//在 xp 下测试, 通过设置 MAGICK_CODER_MODULE_PATH (使用完整路径后), 不再需要 SetCurrentDirectory(app_folder_path); 就能正常的加载宝贝图片
//在 win8.1 下测试, 通过设置 MAGICK_CODER_MODULE_PATH (使用完整路径后), 在不使用 SetCurrentDirectory(app_folder_path); 的情况下, 还是发生错误:
//image.c unknow 916 NoDecodeDelegateForThisImageFormat 'JPEG' @ error/constitute.c/ReadImage/501
//从这个结果看, 在程序中设置 环境变量 MAGICK_CODER_MODULE_PATH 没任何意义, 与使用注册表的结果是一样的, 解决不了部分win8.1上只能在英文文件夹中运行软件.
/*
char *pMagickCoderModulePath = getenv("MAGICK_CODER_MODULE_PATH");
if(pMagickCoderModulePath == NULL)
{
char coders_gbk[] = "D:\\soft\\c\\....\\bin\\Release\\modules\\coders";
int coders_gbk_len = strlen(coders_gbk);
int coders_utf8_len = coders_gbk_len * 2;
char coders_utf8[coders_utf8_len];
size_t outedSize;
iconvStr("gbk", "utf-8", coders_gbk, coders_gbk_len, coders_utf8, coders_utf8_len, &outedSize);
char text[4096];
sprintf(text, "MAGICK_CODER_MODULE_PATH=%s", coders_utf8);
//putenv("MAGICK_CODER_MODULE_PATH=modules\\coders"); //也可以使用相对路径, 但必须 SetCurrentDirectory(app_folder_path);
putenv(text);
char exeFilePath[MAX_PATH];
int len = GetModuleFileName(NULL, exeFilePath, MAX_PATH); //Long,如执行成功,返回复制到lpFileName的实际字符数量, 零表示失败。
if(len > 0)
{
printf("exeFilePath:%s\n", exeFilePath);
int status = (int)ShellExecute(NULL, "open", exeFilePath, NULL, NULL, SW_SHOW); //使用默认程序打开
printf("status:%d\n", status);
//system("pause");
exit(0);
}
}
else
{
printf("MAGICK_CODER_MODULE_PATH:%s\n", getenv("MAGICK_CODER_MODULE_PATH"));
}
*/
然后测试通过注册表:
/*
[HKEY_CURRENT_USER\SOFTWARE\ImageMagick\6.8.9\Q:16]
"BinPath"="C:\\ImageMagick" //经过测试发现: BinPath 参数不必需, 可以没有
"ConfigurePath"="C:\\ImageMagick" //经过测试发现: ConfigurePath 参数不必需, 可以没有
"LibPath"="C:\\ImageMagick" //经过测试发现: LibPath 参数不必需, 可以没有
"CoderModulesPath"="C:\\ImageMagick\\modules\\coders" //经过测试发现: 这个路径要么是相对路径, 如果是绝对路径, 必须是 utf-8编码的
"FilterModulesPath"="C:\\ImageMagick\\modules\\filters" //经过测试发现: 这个路径要么是相对路径, 如果是绝对路径, 必须是 utf-8编码的
*/
//关于 CoderModulesPath 和 FilterModulesPath 参数, 在 xp 下, 使用完整路径(utf-8), 不再需要 SetCurrentDirectory(app_folder_path);
//但是在 win8.1 下测试, 使用完整路径(utf-8) 加载宝贝失败,错误信息:
//UnableToLoadModule 'C:\....\涓诲浘瑙嗛v6.0\modules\coders\IM_MOD_RL_JPEG_.dll:找不到指定的模块 (注: 涓诲浘瑙嗛 其实就是 中文文件夹的 utf-8编码
//这个错误信息看, 在 xp,2003系统下, ImageMagick 在加载dll的时候, 先将 utf-8 编码转换成 gbk, 然后就能能正常加载对应的dll文件
//但在 win8.1 下, 没有对 utf-8编码 进行转码, 直接加载, 导致 dll 找不到
//在 win8.1 下加上 SetCurrentDirectory(app_folder_path); 又能正常的加载宝贝了。
通过两种方式的测试结果可以看出:
ImageMagick 内部加载 coder module 的代码实现是很奇葩的。
不管是通过设置环境变量:MAGICK_CODER_MODULE_PATH,还是注册表项:CoderModulesPath
如果coders 使用经过 utf-8 编码后的完整路径, 在 xp, 2003 下,不需要 SetCurrentDirectory(app_folder_path); 就能正常的加载相关的dll,但是在 win8.1 下,必需 SetCurrentDirectory(app_folder_path);
并且在极少一部分 64位的 win8.1 下, 就算 SetCurrentDirectory(app_folder_path); 也不行,必须把整个软件放在[全是英文文件夹路径]中才能正常的加载dll处理图片。
使用相对路径:modules\coders 结合 SetCurrentDirectory(app_folder_path); 在极少部分64位的win8.1 上还是出现问题,必须存放在[全是英文文件夹路径]中才能正常的加载dll处理图片。
还有一种解决办法:
对 ImageMagick 的源代码进行重新编译,生成一个静态的链接库。
这样有可能会解决所有问题, 但是生成的exe文件会很大,至少 5M+
参考:http://blog.csdn.net/wwwsq/article/details/7352777
2015-04-16