• ImageMagick: win7 | win8 & uac (用户帐户控制) 注册表的一些事


    现在用win7,win8的人越来越多了, 程序在一些 win 7, win8 上运行会遇到一些之前没想过的兼容性问题。

    比如 64位系统运行32位程序时的注册表重定向,还有因为 uac (用户帐户控制)注册表的重定向等。

    ImageMagick 在安装的时候,相关数据写在 HKEY_LOCAL_MACHINE 下面, 这在 xp 系统下,一般不会出什么问题。

    但由于在 win7,win8上,由于64位系统或uac的问题,导致注册表的路径重定向, 特别是 uac 问题,要想将数据保存到HKEY_LOCAL_MACHINE 必须要管理员身份运行软件。

    经过一天多时间研究,一开始在网上找到一个办法,通过修改 ImageMagick 的环境变量,因为根据ImageMagick的源代码,module.c (537行)

    static MagickBooleanType GetMagickModulePath(const char *filename,

      MagickModuleType module_type,char *path,ExceptionInfo *exception)

    {

      char

        *module_path;

      assert(filename != (const char *) NULL);

      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);

      assert(path != (char *) NULL);

      assert(exception != (ExceptionInfo *) NULL);

      (void) CopyMagickString(path,filename,MaxTextExtent);

      module_path=(char *) NULL;

      switch (module_type)

      {

        case MagickImageCoderModule:

        default:

        {

          (void) LogMagickEvent(ModuleEvent,GetMagickModule(),

            "Searching for coder module file "%s" ...",filename);

          module_path = GetEnvironmentValue("MAGICK_CODER_MODULE_PATH");

    #if defined(MAGICKCORE_CODER_PATH)

          if (module_path == (char *) NULL)

            module_path=AcquireString(MAGICKCORE_CODER_PATH);

    #endif

    一开始,我在程序开头加了一句:putenv("MAGICK_CODER_MODULE_PATH=c:\imagemagick\modules\coders\"); //设置环境变量

    我以为这样设置后,ImageMagick就不会对注册表有依赖了,可谁知:

    printf("MAGICK_CODER_MODULE_PATH:%s ", getenv("MAGICK_CODER_MODULE_PATH")); //在我的程序中能正常显示的路径

    但是 GetEnvironmentValue("MAGICK_CODER_MODULE_PATH"); 返回的是 (null)

    我查看了 ImageMagick 的源代码,发现 GetEnvironmentValue() 其实调用的就是 putenv()

    可为什么返回的是  null ? 测试发现使用 putenv("MAGICK_CODER_MODULE_PATH=..."); 一点用没有。

    再继续研究ImageMagick源代码:

    module.c (634行)

    #if defined(MAGICKCORE_WINDOWS_SUPPORT)

        {

          const char

            *registery_key;

          unsigned char

            *key_value;

          /*

            Locate path via registry key.

          */

          switch (module_type)

          {

            case MagickImageCoderModule:

            default:

            {

              registery_key="CoderModulesPath";

              break;

            }

            case MagickImageFilterModule:

            {

              registery_key="FilterModulesPath";

              break;

            }

          }

          key_value=NTRegistryKeyLookup(registery_key);

          if (key_value == (unsigned char *) NULL)

            {

              ThrowMagickException(exception,GetMagickModule(),ConfigureError,

                "RegistryKeyLookupFailed","`%s'",registery_key);

              return(MagickFalse);

            }


    -------------------------------------------------------------------------------

    nt-base.c (1813行)

    MagickPrivate unsigned char *NTRegistryKeyLookup(const char *subkey)

    {

      char

        package_key[MaxTextExtent];

      DWORD

        size,

        type;

      HKEY

        registry_key;

      LONG

        status;

      unsigned char

        *value;

      /*

        Look-up base key.

      */

      (void) FormatLocaleString(package_key,MaxTextExtent,"SOFTWARE\%s\%s\Q:%d",

        MagickPackageName,MagickLibVersionText,MAGICKCORE_QUANTUM_DEPTH);

      (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),"%s",package_key);

      registry_key=(HKEY) INVALID_HANDLE_VALUE;

      status=RegOpenKeyExA(HKEY_LOCAL_MACHINE,package_key,0,KEY_READ,&registry_key);

      if (status != ERROR_SUCCESS)

        status=RegOpenKeyExA(HKEY_CURRENT_USER,package_key,0,KEY_READ,

          &registry_key);

      if (status != ERROR_SUCCESS)

        {

          registry_key=(HKEY) INVALID_HANDLE_VALUE;

          return((unsigned char *) NULL);

        }

    -------------------------------------------------------------------------------------

    原来 ImageMagick 搜索注册表的路径有个顺序,先搜索 HKEY_LOCAL_MACHINE, 再搜索 HKEY_CURRENT_USER

    看到这里,我想到一个办法,由于 uac 的问题导致普通用户无法写入设置 HKEY_LOCAL_MACHINE,但可以设置 HKEY_CURRENT_USER

    只需将相关的数据写入到 HKEY_CURRENT_USER, 这样就不需要管理员身份也能正常的运行了。

    经过测试,验证了我的这个想法,问题终于解决了,以后不用烦在 win7,win8上的兼容性问题了。

    2014-09-19

  • 相关阅读:
    Exception handling 异常处理的本质
    一个人运气不好怎么办?做什么事能够马上改变运气?
    autoreleasing on a thread
    Tagged Pointer
    Objective-C 引用计数原理
    oc引用计数原理-引用计数相关变化
    黑箱中的 retain 和 release
    黑幕背后的Autorelease
    自动释放池的前世今生 ---- 深入解析 autoreleasepool
    Exceptions and Errors on iOS
  • 原文地址:https://www.cnblogs.com/personnel/p/4585074.html
Copyright © 2020-2023  润新知