#==============================================================================
# ■ API相关操作 版本1.0
#------------------------------------------------------------------------------
# 此脚本目前只适用于RGSS3。
# 在使用之前,请详阅使用方法及备注,否则造成系统或档案损坏后果请自行承担。
#------------------------------------------------------------------------------
# 这个脚本可以帮助你:
# 1.转换字串的编码。
# 2.读取、写入INI档,对应系统编码和Unicode编码。
# 3.对注册表进行建立、修改、读取、删除键和值项,对应系统编码。
# 这个脚本的放置位置:main以上,尽量在自订脚本的最高处,原始脚本以下。
#------------------------------------------------------------------------------
# 困难度:极高
# 撰写者:白羽ゆりな(abc1236762)
# 工作室:RMGTW工作室 [url]http://rmgtw.eu.org/[/url]
#------------------------------------------------------------------------------
# 更新日志:
# 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.所有的代码页可以参考以下网址
# [url]https://msdn.microsoft.com/library/windows/desktop/dd317756.aspx[/url]
# 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.关于操昨时传回的错误代码,可以参考以下网址
# [url]https://msdn.microsoft.com/library/windows/desktop/ms681381.aspx[/url]
# ●注4:关于操作注册表的注意事项
# 1.此脚本只提供系统编码当作操作注册表的编码方式,因此:
# (1) 键、值项及其值含系统编码不允许字元的操作可能会找不到名称、路径。
# (2) 取得值项时,如其值的类别与字串相关,系统编码不允许字元将会表'?'。
# (3) 新增键或值项时,如果含系统编码不允许字元将会以'?'代替。
# 2.在建立、开启键后,如果对里面的值项操作完毕或不进行任何操昨时,一定要
# 进行关闭动作,否则如果发生问题,后果自行负责!
# 3.更多关于注册表的操作,可以参考以下网址
# [url]https://msdn.microsoft.com/library/windows/desktop/ms724871.aspx[/url]
# [url]https://msdn.microsoft.com/library/windows/desktop/ms724875.aspx[/url]
# 3.关于操昨时传回的错误代码,可以参考以下网址
# [url]https://msdn.microsoft.com/library/windows/desktop/ms681381.aspx[/url]
# ●注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
# 详阅:[url]https://msdn.microsoft.com/library/windows/desktop/ms724897.aspx[/url]
# ●注8:此处的dwOptions可以为
# 符号 对应值
# :REG_OPTION_NON_VOLATILE 0x0000
# :REG_OPTION_VOLATILE 0x0001
# :REG_OPTION_CREATE_LINK 0x0002
# :REG_OPTION_BACKUP_RESTORE 0x0004
# 详阅:[url]https://msdn.microsoft.com/library/windows/desktop/ms724897.aspx[/url]
# ●注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))
# 详阅:[url]https://msdn.microsoft.com/library/windows/desktop/ms724884.aspx[/url]
#------------------------------------------------------------------------------
# 本脚本以创用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[i].is_a?(String)
_lpData += lpData[i].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[i].is_a?(Integer)
raise("lpData Value Error") if lpData[i] < 0 || lpData[i] > 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