查看: 2885|回复: 1

[RMVA发布] [RGSS3]API相关操作 1.0 INI档、注册表、转换编码

[复制链接]
梦石
0
星屑
235
在线时间
78 小时
注册时间
2010-7-1
回帖
46
发表于 2015-2-23 17:32:41 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 abc1236762 于 2015-2-23 17:40 编辑

这是我花4天左右熬夜呕心沥血之作
这脚本可以:
1.转换字串的编码。
2.读取、写入INI档,对应系统编码和Unicode(UTF-16LE)编码。
3.对注册表进行建立、修改、读取、删除键和值项,对应系统编码。
之后还会陆续增加其他的功能,预计有对视窗的操作及取得时间等。

因为牵扯到了String.encode等方法,所以目前只适用于RGSS3。

如果有BUG,请将你用了哪些方法/函数,怎么用的,得到了那些结果回报给我,不然我会很难修正脚本。

也请各位高手指教指教,谢谢。


[pre lang="ruby" file="API.rb"]#==============================================================================
# ■ API相关操作 版本1.0
#------------------------------------------------------------------------------
#  此脚本目前只适用于RGSS3。
#  在使用之前,请详阅使用方法及备注,否则造成系统或档案损坏后果请自行承担。
#------------------------------------------------------------------------------
#  这个脚本可以帮助你:
#  1.转换字串的编码。
#  2.读取、写入INI档,对应系统编码和Unicode编码。
#  3.对注册表进行建立、修改、读取、删除键和值项,对应系统编码。
#  这个脚本的放置位置:main以上,尽量在自订脚本的最高处,原始脚本以下。
#------------------------------------------------------------------------------
#  困难度:极高
#  撰写者:白羽ゆりな(abc1236762)
#  工作室:RMGTW工作室 http://rmgtw.eu.org/
#------------------------------------------------------------------------------
#  更新日志:
#   1.0 2015/02/23 初版公开。
#------------------------------------------------------------------------------
#  使用方法:
#  ■转换编码的部分
#   ●String.conv(from, to) 将字串从来源编码转换至欲输出的编码。(*1)
#    from :字串来源编码的代码页,资料型别为整数或符号。(*2)
#    to   :欲输出编码的代码页,资料型别为整数或符号。(*2)
#    avoid:为真能降低输出额外乱码的机率,资料型别为布林值,选填项,预设为真。
#    例:
#     "foobar".conv(65001, 932) 等价于
#     "foobar".conv(:UTF_8, :Shift_JIS)
#   ●String.to_uni([usesys]) 将字串从UTF-8转换至UTF-16
#    usesys:是否使用内建功能取代,选填项预设为真。
#    例:
#     "foobar".to_uni 等价于
#     "foobar".conv(:UTF_8, :UTF_16LE)
#   ●String.to_utf8([usesys]) 将字串从UTF-16转换至UTF-8
#    usesys:是否使用内建功能取代,选填项预设为真。
#   ●String.to_ansi() 将字串从UTF-8转换至系统编码
#  ■INI档的操作部分(*3)
#   ●INI.get(lpAppName, lpKeyName, [lpDefault[, nSize]]) 取得指定位置的参数
#    传回取得的值,失败时传回预设值。
#    lpAppName:欲取得参数所在的节,资料型别为字串。
#    lpKeyName:欲取得参数所在的参数名称,资料型别为字串。
#    lpDefault:预设值,欲取得的参数不存在时输出此,资料型别为字串,选填项。
#    nSize    :缓冲区大小,必须不小于参数的长度,资料型别为整数,选填项。
#    例:
#     INI.get("Foo", "Bar")
#   ●INI.set(lpAppName, lpKeyName, lpString) 设定指定位置的参数
#    传回整数,失败时传回0。
#    lpAppName:欲设定参数所在的节,资料型别为字串。
#    lpKeyName:欲设定参数所在的参数名称,资料型别为字串。
#    lpString :欲设定参数值,资料型别为字串。
#    例:
#     INI.set("Foo", "Bar", "Foobar")
#  ■注册表的操作部分(*4)
#   ●Registry.new() 初始化Registry类别,此动作为必要
#   ●Registry.open(hKey, lpSubKey[, dwOptions]) 开启指定的键
#    传回错误代码,成功时传回0。
#    hKey     :键的基底位置,资料型别为符号或整数。(*5)
#    lpSubKey :键的延伸位置,资料型别为字串。(*6)
#    dwOptions:开启键的选项,资料型别为符号或整数,选填项,预设为0。(*7)
#   ●Registry.create(hKey, lpSubKey[, dwOptions]) 新增指定的键
#    成功时传回字串,失败时传回错误代码。
#    成功时,如果原本没有键,是新增的动作,传回"REG_CREATED_NEW_KEY"
#            如果原本存在键,是开启的动作,传回"REG_OPENED_EXISTING_KEY"
#    hKey     :键的基底位置,资料型别为符号或整数。(*5)
#    lpSubKey :键的延伸位置,资料型别为字串。(*6)
#    dwOptions:开启键的选项,资料型别为符号或整数,选填项,预设为0。(*8)
#   ●Registry.remove(hKey, lpSubKey) 删除指定的键
#    传回错误代码,成功时传回0。
#    hKey     :键的基底位置,资料型别为符号或整数。(*5)
#    lpSubKey :键的延伸位置,资料型别为字串。(*6)
#   ●Registry.close  关闭已指定的键
#    传回错误代码,成功时传回0。
#   ●Registry.get(lpValueName) 取得已指定的键中指定的值项
#    传回得到的值,失败时传回空(nil)。(9)
#    lpValueName:欲查询值项的名称,资料型别为字串。
#   ●Registry.set(lpValueName, lpData[, dwType]) 设定已指定的键中指定的值项
#    传回错误代码,成功时传回0。
#    lpValueName:欲设定值项的名称,资料型别为字串。
#    lpData     :欲设定值项的值,资料型别因值项的类型(dwType)不同而不同。(*9)
#    dwType     :欲设定值项的类型,资料型别为符号或整数,选填项,
#                 预设为原本的类型,值项不存在时如没有设定会为:REG_NONE(0)。(*9)
#   ●Registry.delete(lpValueName) 删除已指定的键中指定的值项
#    传回错误代码,成功时传回0。
#    lpValueName:欲删除值项的名称,资料型别为字串。
#   注册表的范例:
#   > reg = Registry.new() # 初始化Registry
#   > reg.open(:HKEY_CURRENT_USER, "Software\\Enterbrain\\RGSS3")
#     # 开启HKEY_CURRENT_USER\Software\Enterbrain\RGSS3键
#   > reg.set("ButtonAssign", [0] * 25) # 设定ButtonAssign为指定的值
#   > value = reg.get("ButtonAssign") # 取得ButtonAssign的值传回value
#     # => [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
#   > reg.set("test", "test", :REG_SZ)
#     # 因为在开启的键中没有test值项,所以会建立一个,且其值为"test"
#   > reg.delete("test") # 删除刚刚建立的test值项
#   > reg.close() # 在操作完这键或是要换其他键时,记得关闭此键
#   > reg.create(:HKEY_CURRENT_USER, "Software\\Enterbrain\\RGSS3\\new")
#     # 如果在那位置不存在,则会新增键,否则开启
#   > reg.close() # 建立完键后不进行任何操作,请关闭。
#   > reg.remove(:HKEY_CURRENT_USER, "Software\\Enterbrain\\RGSS3\\new")
#     # 移除刚刚建立的键HKEY_CURRENT_USER\Software\Enterbrain\RGSS3\new
#     # 如果不再用reg操作注册表,可以进行以下动作:
#   > reg = nil; GC.start
#------------------------------------------------------------------------------
#  备注:
#   ●注1:请勿使用UTF-16BE(代码页1201)以及UTF-32等作为来源或输出编码。
#   ●注2:关于代码页:
#    1.所有的代码页可以参考以下网址
#     https://msdn.microsoft.com/library/windows/desktop/dd317756.aspx
#    2.from和to可用,以预先设定好的符号如下
#     符号       编码名称         对应代码页
#     :ACP       ANSI(系统编码) 0
#     :Shift_JIS Shift-JIS        932
#     :GB2312    GB2312           936
#     :BIG5      BIG5             950
#     :UTF_16LE  UTF-16LE         1200
#     :UTF_8     UTF-8            65001
#   ●注3:关于操作INI档的注意事项
#    1.如果没有特殊需求,请尽量不要使用Unicode当作操作INI档的编码方式。
#     即使在编码转换的部分已经针对了输出多余的垃圾字串做了对应的措施,但在操
#     作INI档时使用Unicode当作编码方式时,可能发生以下状况:
#     (1) 档名不符合预期,例如你想设定的值会储存在与原档名不同的档案中。
#     (2) 节、参数名称、参数值的取得不符合预期,可能会有垃圾字串。
#     (3) 发生无法设定或取得的情况,原因是名称、路径错误,代码123。
#     以上方法皆没有替代方案,唯一只有使用系统编码才可以避免,而相对的:
#     (1) 使用系统编码操作INI档,可以正常读写以系统编码和UTF-16LE的INI档。
#     (2) 在系统编码无法容许的字元,皆会以'?'存在,包含设定或取得。
#     (3) 不过包含在系统编码无法中容许字元的路径也可以正常读写。
#    2.在设定INI档的值时,如果没有找到指定的INI档,则会新增一个。
#    3.关于操昨时传回的错误代码,可以参考以下网址
#     https://msdn.microsoft.com/library/windows/desktop/ms681381.aspx
#   ●注4:关于操作注册表的注意事项
#    1.此脚本只提供系统编码当作操作注册表的编码方式,因此:
#     (1) 键、值项及其值含系统编码不允许字元的操作可能会找不到名称、路径。
#     (2) 取得值项时,如其值的类别与字串相关,系统编码不允许字元将会表'?'。
#     (3) 新增键或值项时,如果含系统编码不允许字元将会以'?'代替。
#    2.在建立、开启键后,如果对里面的值项操作完毕或不进行任何操昨时,一定要
#     进行关闭动作,否则如果发生问题,后果自行负责!
#    3.更多关于注册表的操作,可以参考以下网址
#     https://msdn.microsoft.com/library/windows/desktop/ms724871.aspx
#     https://msdn.microsoft.com/library/windows/desktop/ms724875.aspx
#    3.关于操昨时传回的错误代码,可以参考以下网址
#     https://msdn.microsoft.com/library/windows/desktop/ms681381.aspx
#   ●注5:此处的hKey可以为
#    符号                     代表值
#    :HKEY_CLASSES_ROOT       0x80000000
#    :HKEY_CURRENT_USER       0x80000001
#    :HKEY_LOCAL_MACHINE      0x80000002
#    :HKEY_USERS              0x80000003
#    :HKEY_CURRENT_CONFIG     0x80000005
#   ●注6:此处的lpSubKey在表示位置字串时,'\'必须标示为'\\'。
#   ●注7:此处的dwOptions可以为
#    符号                     对应值
#    :REG_OPTION_NON_VOLATILE 0x0000
#    :REG_OPTION_OPEN_LINK    0x0008
#    详阅:https://msdn.microsoft.com/library/windows/desktop/ms724897.aspx
#   ●注8:此处的dwOptions可以为
#    符号                       对应值
#    :REG_OPTION_NON_VOLATILE   0x0000
#    :REG_OPTION_VOLATILE       0x0001
#    :REG_OPTION_CREATE_LINK    0x0002
#    :REG_OPTION_BACKUP_RESTORE 0x0004
#    详阅:https://msdn.microsoft.com/library/windows/desktop/ms724897.aspx
#   ●注9:对应值项的类型(dwType),需设定或取得的值的资料型别如下
#    dwType的符号                    对应值 值的资料型别
#    :REG_NONE                       0      另外说明
#    :REG_SZ                         1      String
#    :REG_EXPAND_SZ                  2      String
#    :REG_BINARY                     3      Array(Integer(0~255))
#    :REG_DWORD                      4      Integer(0~4294967295)
#    :REG_DWORD_LITTLE_ENDIAN        4      Integer(0~4294967295)
#    :REG_DWORD_BIG_ENDIAN           5      Integer(0~4294967295)
#    :REG_LINK                       6      String
#    :REG_MULTI_SZ                   7      Array(String)
#    :REG_RESOURCE_LIST              8      Array(Integer(0~255))
#    :REG_FULL_RESOURCE_DESCRIPTOR   9      Array(Integer(0~255))
#    :REG_RESOURCE_REQUIREMENTS_LIST 10     Array(Integer(0~255))
#    :REG_QWORD                      11     Integer(0~18446744073709551615)
#    :REG_QWORD_LITTLE_ENDIAN        11     Integer(0~18446744073709551615)
#    :REG_NONE的值的资料型别:输入为以上出现过的,输出为Array(Integer(0~255))
#    详阅:https://msdn.microsoft.com/library/windows/desktop/ms724884.aspx
#------------------------------------------------------------------------------
#  本脚本以创用CC 姓名标示-非商业性-禁止改作 4.0 国际 授权条款释出。
#==============================================================================

#==============================================================================
# ■ 预先设定
#==============================================================================
module RMGTW
  # 预设参数(在未指定预设参数时,输入或输出此参数,必须是字串)
  DefaultValue = ""
  # 预设缓冲区大小(在未指定缓冲区大小时,使用这数值来当作缓冲区大小)
  DefaultnSize = 400
  # INI档的位置
  INIPath = "./Game.ini"
  # INI档使用的编法方式是否为Unicode(UTF-16LE)
  #  只有VX Ace的INI档用的了UTF-16LE当作编码方式。
  #  为true的风险请阅备注的注4。
  INIUseUni = false
  # 当功能失败时时是否回报错误。
  Debug = true
  # 当回报错误时,是否弹出错误讯息,否则在主控台显示。
  RaiseError = true
end

#==============================================================================
# ■ NativeMethods
#------------------------------------------------------------------------------
#  这个模组用来定义原生方法。
# 没有用到的都是之后新增功能时会用到的。
#==============================================================================
module NativeMethods
  #--------------------------------------------------------------------------
  # ● 处理视窗的API
  #--------------------------------------------------------------------------
  FindWindow    =
    Win32API.new('user32',    'FindWindow',  'PP', 'L')
  GetSystemMenu =
    Win32API.new('user32', 'GetSystemMenu',  'LL', 'L')
  RemoveMenu    =
    Win32API.new('user32',    'RemoveMenu', 'LLL', 'L')
  #--------------------------------------------------------------------------
  # ● 转换编码的API
  #--------------------------------------------------------------------------
  MultiByteToWideChar =
    Win32API.new('kernel32', 'MultiByteToWideChar',   'LLPLPL', 'L')
  WideCharToMultiByte =
    Win32API.new('kernel32', 'WideCharToMultiByte', 'LLPLPLPP', 'L')
  #--------------------------------------------------------------------------
  # ● 控制INI档的API
  #--------------------------------------------------------------------------
  GetPrivateProfileStringA   =
    Win32API.new('kernel32',    'GetPrivateProfileStringA', 'PPPPLP', 'L')
  GetPrivateProfileStringW   =
    Win32API.new('kernel32',    'GetPrivateProfileStringW', 'PPPPLP', 'L')
  WritePrivateProfileStringA =
    Win32API.new('kernel32',  'WritePrivateProfileStringA',   'PPPP', 'L')
  WritePrivateProfileStringW =
    Win32API.new('kernel32',  'WritePrivateProfileStringW',   'PPPP', 'L')
  #--------------------------------------------------------------------------
  # ● 控制注册表的键的API
  #--------------------------------------------------------------------------
    RegOpenKeyEx   =
    Win32API.new('advapi32',   'RegOpenKeyEx',     'LPLLP', 'L')
  RegCreateKeyEx =
    Win32API.new('advapi32', 'RegCreateKeyEx', 'LPLPLLPPP', 'L')
  RegDeleteKeyEx =
    Win32API.new('advapi32', 'RegDeleteKeyEx',      'LPLL', 'L')
  RegCloseKey    =
    Win32API.new('advapi32',    'RegCloseKey',         'L', 'L')
  #--------------------------------------------------------------------------
  # ● 控制注册表的值项的API
  #--------------------------------------------------------------------------
  RegQueryValueEx =
    Win32API.new('advapi32', 'RegQueryValueEx', 'LPPPPP', 'L')
  RegSetValueEx   =
    Win32API.new('advapi32',   'RegSetValueEx', 'LPLLPL', 'L')
  RegDeleteValue  =
    Win32API.new('advapi32',  'RegDeleteValue',     'LP', 'L')
  #--------------------------------------------------------------------------
  # ● 其他API
  #--------------------------------------------------------------------------
  GetLocalTime =
    Win32API.new('kernel32', 'GetLocalTime', 'P', 'V')
  GetLastError =
    Win32API.new('kernel32', 'GetLastError', 'V', 'L')
end

#==============================================================================
# ■ String
#------------------------------------------------------------------------------
#  这个类别定义了资料型别String。
#==============================================================================
class String
  #--------------------------------------------------------------------------
  # ● 防范NativeMethods
  #--------------------------------------------------------------------------
  include NativeMethods
  #--------------------------------------------------------------------------
  # ● 定义常用的编码代码
  #--------------------------------------------------------------------------
  CP = {
  :ACP      =>    0, :Shift_JIS =>   932, :GB2312 => 936, :BIG5 => 950,
  :UTF_16LE => 1200, :UTF_8     => 65001
  }
  #--------------------------------------------------------------------------
  # ● 定义转换字串编码的输出
  #--------------------------------------------------------------------------
  def conv(from, to, avoid = true)
    str0 = _conv(from, to)
    str1 = _conv(from, to)
    str2 = _conv(from, to)
    while (str0 != str1 || str0 != str2) && avoid do
      str0 = _conv(from, to)
      str1 = _conv(from, to)
      str2 = _conv(from, to)
    end
    return str0
  end
  #--------------------------------------------------------------------------
  # ● 定义转换字串编码
  #--------------------------------------------------------------------------
  def _conv(from, to)
    from = from.is_a?(Symbol) ? CP[from] : from
    to   =   to.is_a?(Symbol) ? CP[to]   : to
    if from != CP[:UTF_16LE]
      length = MultiByteToWideChar.call(from, 0, self, -1, nil, 0)
      buffer = "\0".encode("UTF-16LE") * length
      MultiByteToWideChar.call(from, 0, self, -1, buffer, length)
      wide_str = buffer.chop
      return wide_str if to == CP[:UTF_16LE]
    end
    wide_str = self if wide_str.nil?
    encoding = to == CP[:UTF_8] ? "UTF-8" : "ASCII-8BIT"
    length = WideCharToMultiByte.call(to, 0, wide_str, -1, nil, 0, nil, nil)
    buffer = "\0".encode(encoding) * length
    WideCharToMultiByte.call(to, 0, wide_str, -1, buffer, length, nil, nil)
    multi_str = buffer.chop
    return multi_str
  end
  #--------------------------------------------------------------------------
  # ● 定义转换字串从UTF-8至UTF-16LE
  #--------------------------------------------------------------------------
  def to_uni(usesys = true)
    return conv(:UTF_8, :UTF_16LE) unless usesys
    self.encode("UTF-16LE")
  end
  #--------------------------------------------------------------------------
  # ● 定义转换字串从UTF-16LE至UTF-8
  #--------------------------------------------------------------------------
  def to_utf8(usesys = true)
    return conv(:UTF_16LE, :UTF_8) unless usesys
    self.encode("UTF-8")
  end
  #--------------------------------------------------------------------------
  # ● 定义转换字串从UTF-8至系统编码
  #--------------------------------------------------------------------------
  def to_ansi
    return conv(:UTF_8, :ACP)
  end
  #--------------------------------------------------------------------------
  # ● 设定权限
  #--------------------------------------------------------------------------
  private :_conv
end

#==============================================================================
# ■ INI
#------------------------------------------------------------------------------
#  这个模组用来操作INI档。
#==============================================================================
module INI
  #--------------------------------------------------------------------------
  # ● 防范NativeMethods
  #--------------------------------------------------------------------------
  include NativeMethods
  #--------------------------------------------------------------------------
  # ● 定义取得在INI档中指定的值
  #--------------------------------------------------------------------------
  def self.get(lpAppName, lpKeyName,
    lpDefault = RMGTW::DefaultValue, nSize = RMGTW::DefaultnSize)
    if RMGTW::INIUseUni
      zero = "\0".encode("UTF-16LE")
      lpReturnedString = zero * nSize
      error = GetPrivateProfileStringW.call(
        lpAppName.to_uni, lpKeyName.to_uni,
        lpDefault.to_uni, lpReturnedString, nSize,
        RMGTW::INIPath.to_uni)
      Error.show("INI取得值", error) if error == 0 && RMGTW::Debug
      return lpReturnedString.delete(zero).to_utf8
    else
      zero = "\0".encode("ASCII-8BIT")
      lpReturnedString = zero * nSize
      error = GetPrivateProfileStringA.call(
        lpAppName.to_ansi, lpKeyName.to_ansi,
        lpDefault.to_ansi, lpReturnedString, nSize,
        RMGTW::INIPath.to_ansi)
      Error.show("INI取得值", error) if error == 0 && RMGTW::Debug
      return lpReturnedString.delete(zero).conv(:ACP, :UTF_8)
    end
  end
  #--------------------------------------------------------------------------
  # ● 定义设定在INI档中指定的值
  #--------------------------------------------------------------------------
  def self.set(lpAppName, lpKeyName, lpString)
    if RMGTW::INIUseUni
      error = WritePrivateProfileStringW.call(
        lpAppName.to_uni, lpKeyName.to_uni,
        lpString.to_uni, RMGTW::INIPath.to_uni)
    else
      error = WritePrivateProfileStringA.call(
        lpAppName.to_ansi, lpKeyName.to_ansi,
        lpString.to_ansi, RMGTW::INIPath.to_ansi)
    end
    Error.show("INI设定值", error) if error == 0 && RMGTW::Debug
    return error
  end
end

#==============================================================================
# ■ Registry
#------------------------------------------------------------------------------
#  这个类别用来操作注册表。
#==============================================================================
class Registry
  #--------------------------------------------------------------------------
  # ● 防范NativeMethods
  #--------------------------------------------------------------------------
  include NativeMethods
  #--------------------------------------------------------------------------
  # ● 物件初始化
  #--------------------------------------------------------------------------
  def initialize
    @hKey = nil
    @lpType = nil
    @lpcbData = nil
  end
  #--------------------------------------------------------------------------
  # ● 键的操作:开启指定的键并取得其控制代码
  #--------------------------------------------------------------------------
  def open(hKey, lpSubKey, dwOptions = :REG_OPTION_NON_VOLATILE)
    phkResult = [0].pack('L')
    hKey = hKey.is_a?(Symbol) ? H[hKey] : hKey
    dwOptions = dwOptions.is_a?(Symbol) ? H[dwOptions] : dwOptions
    error = RegOpenKeyEx.call(hKey, lpSubKey.to_ansi, dwOptions,
      H[:KEY_ALL_ACCESS] | H[:KEY_WOW64_32KEY], phkResult)
    @hKey = phkResult.unpack('L')[0]
    Error.show("注册表开启键", error) if error != 0 && RMGTW::Debug
    return error
  end
  #--------------------------------------------------------------------------
  # ● 键的操作:建立新的键并取得其控制代码
  #--------------------------------------------------------------------------
  def create(hKey, lpSubKey, dwOptions = :REG_OPTION_NON_VOLATILE)
    phkResult = [0].pack('L')
    lpdwDisposition = [0].pack('L')
    hKey = hKey.is_a?(Symbol) ? H[hKey] : hKey
    dwOptions = dwOptions.is_a?(Symbol) ? H[dwOptions] : dwOptions
    error = RegCreateKeyEx.call(hKey, lpSubKey.to_ansi, 0, nil, dwOptions,
      H[:KEY_ALL_ACCESS] | H[:KEY_WOW64_32KEY], nil, phkResult,
      lpdwDisposition)
    @hKey = phkResult.unpack('L')[0]
    lpdwDisposition = lpdwDisposition.unpack('L')[0]
    if error == 0
      if lpdwDisposition = H[:REG_CREATED_NEW_KEY]
        return :REG_CREATED_NEW_KEY.id2name
      elsif lpdwDisposition = H[:REG_OPENED_EXISTING_KEY]
        return :REG_OPENED_EXISTING_KEY.id2name
      end
    else
      Error.show("注册表新增键", error) if error != 0 && RMGTW::Debug
      return error
    end
  end
  #--------------------------------------------------------------------------
  # ● 键的操作:删除指定的的键
  #--------------------------------------------------------------------------
  def remove(hKey, lpSubKey)
    hKey = hKey.is_a?(Symbol) ? H[hKey] : hKey
    error = RegDeleteKeyEx.call(hKey, lpSubKey.to_ansi,
      H[:KEY_WOW64_32KEY], 0)
    Error.show("注册表删除键", error) if error != 0 && RMGTW::Debug
    return error
  end
  #--------------------------------------------------------------------------
  # ● 键的操作:关闭已开启的键
  #--------------------------------------------------------------------------
  def close
    error = RegCloseKey.call(@hKey)
    @hKey = nil
    @lpType = nil
    @lpcbData = nil
    Error.show("注册表关闭键", error) if error != 0 && RMGTW::Debug
    return error
  end
  #--------------------------------------------------------------------------
  # ● 值项的操作:取得已指定的键中指定值项的种类和长度
  #--------------------------------------------------------------------------
  def query(lpValueName)
    lpType = [0].pack('L')
    lpcbData = [0].pack('L')
    error = RegQueryValueEx.call(@hKey, lpValueName.to_ansi, 0,
      lpType, 0, lpcbData)
    @lpType = lpType
    @lpcbData = lpcbData
    Error.show("注册表的键中取得值项", error) if error != 0 && RMGTW::Debug
  end
  #--------------------------------------------------------------------------
  # ● 值项的操作:从已指定的键中取得指定值项的值
  #--------------------------------------------------------------------------
  def get(lpValueName)
    query(lpValueName)
    lpData = "\0".encode("ASCII-8BIT") * @lpcbData.unpack('L')[0]
    error = RegQueryValueEx.call(@hKey, lpValueName.to_ansi,
      0, @lpType, lpData, @lpcbData)
    Error.show("注册表的键中取得值项的值", error) if error != 0 && RMGTW::Debug
    return nil if error != 0
    case @lpType.unpack('V')[0]
    when H[:REG_DWORD], H[:REG_DWORD_LITTLE_ENDIAN]
      return lpData.unpack('V')[0]
    when H[:REG_DWORD_BIG_ENDIAN]
      return lpData.unpack('N')[0]
    when H[:REG_QWORD], H[:REG_QWORD_LITTLE_ENDIAN]
      return lpData.unpack('Q')[0]
    when H[:REG_SZ], H[:REG_EXPAND_SZ], H[:REG_LINK]
      return lpData.chop.conv(:ACP, :UTF_8)
    when H[:REG_MULTI_SZ]
      return lpData.chop.split(%r{(\0)})
        .delete_if { |s| s == "\0" }
        .collect { |s| s.conv(:ACP, :UTF_8) }
    else
      return lpData.unpack('C*')
    end
  end
  #--------------------------------------------------------------------------
  # ● 值项的操作:从已指定的键中设定指定值项的值
  #--------------------------------------------------------------------------
  def set(lpValueName, lpData, dwType = 0)
    if dwType == 0
      query(lpValueName) if @lpType == nil
      dwType = @lpType.unpack('V')[0]
    else
      dwType = dwType.is_a?(Symbol) ? H[dwType] : dwType
    end
    if dwType == H[:REG_NONE]
      if lpData.is_a?(Integer)
        if lpData >= 0 && lpData <= 0xFFFFFFFF
          dwType = H[:REG_DWORD]
        elsif lpData >= 0 && lpData <= 0xFFFFFFFFFFFFFFFF
          dwType = H[:REG_QWORD]
        elsif lpData < 0 || lpData > 0xFFFFFFFFFFFFFFFF
          raise("lpData Value Error")
        end
      elsif lpData.is_a?(String)
        dwType = H[:REG_SZ]
      elsif lpData.is_a?(Array)
        if lpData[0].is_a?(Integer)
          dwType = H[:REG_BINARY]
        elsif lpData[0].is_a?(String)
          dwType = H[:REG_MULTI_SZ]
        else
          raise("lpData Type Error")
        end
      elsif lpData != nil
        raise("lpData Type Error")
      end
      dwType_none = true
    end
    case dwType
    when H[:REG_DWORD], H[:REG_DWORD_LITTLE_ENDIAN], H[:REG_DWORD_BIG_ENDIAN]
      raise("lpData Type Error") unless lpData.is_a?(Integer)
      if lpData < 0 || lpData > 0xFFFFFFFF
        raise("lpData Value Error")
      end
      _lpData = [
        lpData / 0x1 % 0x100,
        lpData / 0x100 % 0x100,
        lpData / 0x10000 % 0x100,
        lpData / 0x1000000 % 0x100
      ]
      _lpData.reverse if dwType == H[:REG_DWORD_LITTLE_ENDIAN]
      lpData = _lpData.pack("CCCC").force_encoding("ASCII-8BIT")
    when H[:REG_QWORD], H[:REG_QWORD_LITTLE_ENDIAN]
      raise("lpData Type Error") unless lpData.is_a?(Integer)
      if lpData < 0 || lpData > 0xFFFFFFFFFFFFFFFF
        raise("lpData Value Error")
      end
      _lpData = [
        lpData / 0x1 % 0x100,
        lpData / 0x100 % 0x100,
        lpData / 0x10000 % 0x100,
        lpData / 0x1000000 % 0x100,
        lpData / 0x100000000 % 0x100,
        lpData / 0x10000000000 % 0x100,
        lpData / 0x1000000000000 % 0x100,
        lpData / 0x100000000000000 % 0x100
      ]
      lpData = _lpData.pack("CCCCCCCC").force_encoding("ASCII-8BIT")
    when H[:REG_SZ], H[:REG_EXPAND_SZ], H[:REG_LINK]
      raise("lpData Type Error") unless lpData.is_a?(String)
      lpData = lpData.conv(:UTF_8, :ACP)
      lpData += "\0".encode("ASCII-8BIT")
    when H[:REG_MULTI_SZ]
      raise("lpData Type Error") unless lpData.is_a?(Array)
      _lpData = ""
      for i in 0..(lpData.length - 1)
        raise("lpData Type Error") unless lpData.is_a?(String)
        _lpData += lpData.conv(:UTF_8, :ACP)
        _lpData += "\0".encode("ASCII-8BIT")
      end
      lpData = _lpData + "\0".encode("ASCII-8BIT")
    else
      if lpData != nil
        for i in 0..(lpData.length - 1)
          raise("lpData Type Error") unless lpData.is_a?(Integer)
          raise("lpData Value Error") if lpData < 0 || lpData > 0xFF
        end
        lpData = lpData.pack('C*').force_encoding("ASCII-8BIT")
      end
    end
    cbData = lpData.nil? ? 0 : lpData.size
    dwType = H[:REG_NONE] if dwType_none
    error = RegSetValueEx.call(@hKey, lpValueName.to_ansi, 0,
      dwType, lpData, cbData)
    Error.show("注册表的键中设定值项", error) if error != 0 && RMGTW::Debug
    return error
  end
  #--------------------------------------------------------------------------
  # ● 值项的操作:从已指定的键中删除指定的值项
  #--------------------------------------------------------------------------
  def delete(lpValueName)
    error = RegDeleteValue.call(@hKey, lpValueName)
    Error.show("注册表的键中删除值项", error) if error != 0 && RMGTW::Debug
    return error
  end
  #--------------------------------------------------------------------------
  # ● 设定权限
  #--------------------------------------------------------------------------
  private :query
  #--------------------------------------------------------------------------
  # ● 定义常数
  #--------------------------------------------------------------------------
  H = {
    :HKEY_CLASSES_ROOT        => 0x80000000,
    :HKEY_CURRENT_USER        => 0x80000001,
    :HKEY_LOCAL_MACHINE       => 0x80000002,
    :HKEY_USERS               => 0x80000003,
    :HKEY_PERFORMANCE_DATA    => 0x80000004,
    :HKEY_CURRENT_CONFIG      => 0x80000005,
   
    :REG_NONE                       => 0,
    :REG_SZ                         => 1,
    :REG_EXPAND_SZ                  => 2,
    :REG_BINARY                     => 3,
    :REG_DWORD                      => 4,
    :REG_DWORD_LITTLE_ENDIAN        => 4,
    :REG_DWORD_BIG_ENDIAN           => 5,
    :REG_LINK                       => 6,
    :REG_MULTI_SZ                   => 7,
    :REG_RESOURCE_LIST              => 8,
    :REG_FULL_RESOURCE_DESCRIPTOR   => 9,
    :REG_RESOURCE_REQUIREMENTS_LIST => 10,
    :REG_QWORD                      => 11,
    :REG_QWORD_LITTLE_ENDIAN        => 11,
   
    :KEY_QUERY_VALUE        => 0x0001,
    :KEY_SET_VALUE          => 0x0002,
    :KEY_CREATE_SUB_KEY     => 0x0004,
    :KEY_ENUMERATE_SUB_KEYS => 0x0008,
    :KEY_NOTIFY             => 0x0010,
    :KEY_CREATE_LINK        => 0x0020,
    :KEY_READ               => 0x20019,
    :KEY_WRITE              => 0x20006,
    :KEY_EXECUTE            => 0x20019,
    :KEY_ALL_ACCESS         => 0xF003F,
    :KEY_WOW64_32KEY        => 0x0200,
    :KEY_WOW64_64KEY        => 0x0100,
   
    :REG_OPTION_NON_VOLATILE   => 0x0000,
    :REG_OPTION_VOLATILE       => 0x0001,
    :REG_OPTION_CREATE_LINK    => 0x0002,
    :REG_OPTION_BACKUP_RESTORE => 0x0004,
    :REG_OPTION_OPEN_LINK      => 0x0008,
   
    :REG_CREATED_NEW_KEY     => 1,
    :REG_OPENED_EXISTING_KEY => 2
  }
end

#==============================================================================
# ■ Error
#------------------------------------------------------------------------------
#  这个模组用来显示错误讯息。
#==============================================================================
module Error
  #--------------------------------------------------------------------------
  # ● 防范NativeMethods
  #--------------------------------------------------------------------------
  include NativeMethods
  #--------------------------------------------------------------------------
  # ● 定义显示错误讯息
  #--------------------------------------------------------------------------
  def self.show(errstr, errcode)
    url = "https://msdn.microsoft.com/library/windows/desktop/ms681381.aspx"
    errcode = GetLastError.call() if errcode == 0
    msg = sprintf("在%s发生错误,错误代码:%i,请至下列网址查询",
      errstr, errcode)
    if RMGTW::RaiseError
      raise(sprintf("%s\n%s", msg, url))
    else
      p(msg); p(url)
    end
  end
end[/pre]

点评

GetLastError反馈的错误信息可以用FormatMessage的,不过这样也很清楚-  发表于 2015-2-23 21:54
LZ你去重写一个ruby附加库的注册表不就行了, 而且还有源代码参考  发表于 2015-2-23 17:55
梦石
0
星屑
235
在线时间
78 小时
注册时间
2010-7-1
回帖
46
 楼主| 发表于 2015-2-23 21:08:04 | 显示全部楼层
我的程度還沒到那,而且其實需要的功能不會是全部的API,不過還是有參考一下啦
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部