最近VBをはじめた者ですが、宜しければ教えてください。
windows API のRegSetValueExを使いたく、
HP上にあるサンプルソースをダウンロードして、実行しましたが、
'値を設定する
Ret = RegSetValueEx(nHandle, Text1.Text, 0, REG_SZ, Text2.Text, nLeng)
の部分でretに5が設定され、レジストリ登録が出来ません。
ちなみにレジストリキーの設定(RegCreateKeyEx)はうまく設定できました。
家のOSはXPになります。
単に実行だけではなく、事前に他の処理が必要なのでしょうか?
よろしくお願いします。
はい、事前に(前後に)準備が要ります。
レジのオープン&クローズ処理が必要です。
INIファイルで十分なので、自分もあまりレジを触ったことないので、
間違ってたらすいません。
'RegOpenKeyEx=>レジストリのキーを開く
'<引数>
'hKey: Rootキー(定数HKEY××参照)
'lpSubKey: Subキー
'ulOptions: 常に0
'samDesired: 常に1
'phkResult: 開いたキーのハンドルを受取る変数
'@戻り値@
'正常終了のとき ERROR_SUCCESS
Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long
'RegCloseKey=>レジストリのハンドルを閉じる
'<引数>
'hKey: レジストリのハンドル
'@戻り値@
'なし
Private Declare Function RegCloseKey Lib "ADVAPI32" (ByVal hKey As Long) As Long
'RegSetValueEx=>レジストリの値名、値を設定する
'<引数>
'hKey:RegOpenKeyExで取得したハンドル
'lpValueName:値名
'Reserved:常に0
'dwType:定数(REG_××参照)
'lpData:値を示す文字列
'cbData:値を示す文字列の文字数
'
'<戻り値>
'正常終了のとき ERROR_SUCCESS
Private Declare Function RegSetValueEx Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, ByVal lpData As Any, ByVal cbData As Long) As Long
'<注>RegSetValueExの引数「lpData」の前にByValをつけています。
'ほかにもやり方がありますが、ByValを書くだけなのでこの方法をとりました。
'--->REG_DWORDを使う時はByValを消さないと使用できません(REG_DWORDは使わないと思いますが・・・)
'ルートキー
Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_CONFIG = &H80000005
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_DYN_DATA = &H80000006
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_PERFORMANCE_DATA = &H80000004
Const HKEY_USERS = &H80000003
Const ERROR_SUCCESS = 0
'値のタイプ
Const REG_SZ = 1
'Const REG_DWORD = 4
Private Sub Command1_Click()
Dim Ret As Long
Dim Rootkey As String
Dim Subkey As String
Dim nHandle As Long
Dim nLeng As Long
Rootkey = HKEY_CURRENT_USER
Subkey = "Software"
nLeng = Len(Text2.Text)
'ハンドル確保
Ret = RegOpenKeyEx(Rootkey, Subkey, 0, 1, nHandle)
'値を設定する
Ret = RegSetValueEx(nHandle, Text1.Text, 0, REG_SZ, Text2.Text, nLeng)
'ハンドルを閉じる
Call RegCloseKey(nHandle)
'エラーの確認
If Ret = ERROR_SUCCESS Then
MsgBox "正常に設定しました"
Else
MsgBox "正常に設定できませんでした"
End If
End Sub
こんな感じでどうでしょうか?
okuさんレスありがとうございます。
何回かソース見直しましたが、問題なさそうでした。
定数の部分は省きますが、ソースは以下の感じになります。
Private Function set_key() As String
Dim Ret As Long
Dim nHandle As Long
Dim nLeng As Long
Dim atai As String
Dim SA As SECURITY_ATTRIBUTES
Dim Disposition As Long
Const Rootkey = HKEY_LOCAL_MACHINE
Const SubKey = "Software\\abcd\\efg"
atai = "abccc"
nLeng = Len(atai)
call RegCreateKeyEx(Rootkey, SubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, SA, nHandle ,Disposition)
Call RegCloseKey(nHandle)
If Disposition = REG_OPENED_EXISTING_KEY Then
set_key = "同じキーが存在するので作成できませんでした"
Exit Function
End If
Ret = RegOpenKeyEx(Rootkey, SubKey, 0, 1, nHandle)
Ret = RegSetValueEx(nHandle, "abcdef",0, REG_SZ, atai, nLeng)
Call RegCloseKey(nHandle)
If Ret = ERROR_SUCCESS Then
set_key = "正常に設定しました"
Else
set_key = "正常に設定できませんでした"
End If
end function
やはり、RegSetValueExのコール部のretに5が代入されてうまく出来ませんでした。。。
ソースのおかしなところがあればご教授お願いします。
> RegCreateKeyEx(Rootkey, SubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, SA, nHandle ,Disposition)
KEY_CREATE_SUB_KEYをKEY_ALL_ACCESSにすれば,
そのままRegSetValueExへ渡せますよ。
#正確には,KEY_SET_VALUE。
あと,SAは不要。ByVal 0&を渡しておけばよいです。
#細かいセキュリティ設定するなら別ですが。
> Ret = RegOpenKeyEx(Rootkey, SubKey, 0, 1, nHandle)
これは,定数を使うと,
Ret = RegOpenKeyEx(Rootkey, Subkey, 0, KEY_QUERY_VALUE, nHandle)
ですから,このnHandleは読み込み専用です。
よって,RegSetValueExで書き込めないのは当然です。
RegOpenKeyExを使うなら,
Ret = RegOpenKeyEx(Rootkey, Subkey, 0, KEY_ALL_ACCESS, nHandle)
のように必要なアクセス手段を指定する必要があります。
嘘ついてたみたいですね。申し訳m(__)m
恥ずかしい(^_^;)
いえいえ、okuさんの言うとおりに変更しましたらうまくいきましたよ。
KEY_ALL_ACCESSは以下のように求めました。
Public Const READ_CONTROL = &H20000
Public Const KEY_QUERY_VALUE = &H1
Public Const KEY_SET_VALUE = &H2
Public Const KEY_CREATE_SUB_KEY = &H4
Public Const KEY_ENUMERATE_SUB_KEYS = &H8
Public Const KEY_NOTIFY = &H10
Public Const KEY_CREATE_LINK = &H20
Public Const KEY_ALL_ACCESS = KEY_QUERY_VALUE + KEY_SET_VALUE + KEY_CREATE_SUB_KEY + KEY_ENUMERATE_SUB_KEYS + KEY_NOTIFY + KEY_CREATE_LINK + READ_CONTROL
あと、質問ついでですが、REG_SZのデータはセット及び取得ができますが、
REG_DWORDは設定のみ可能で、取得が出来ません(強制終了)。
申し訳ありませんが、知恵をお貸し下さい。
'キーをオープンしてハンドルを得る
Call RegOpenKeyEx(ROOTKEY, SUBKEY, 0, KEY_ALL_ACCESS, nHandle)
key = 0
'HensuはRegOpenKeyExで開いたキーのハンドル
Call RegQueryValueExstr(nHandle, key_name, 0, REG_DWORD, key, Len(key))
'ハンドルを閉じる
Call RegCloseKey(nHandle)
すみません、okuさんとYuOさんと混合させてしまいました。
失礼しました。
RegQueryValueExの宣言は,
LONG WINAPI RegQueryValueEx(HKEY hKey, LPTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);
です。
これをVBの宣言に直すと,
Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (
ByVal hKey As Long, ByVal strValueName As String, ByRef lpReserved As Long,
ByRef lngType As Long, lpData As Any, ByRef cbData As Long) As Long
となります。
#冗長ですが,ByRefを付けました。
つまり,種別は取得されるものであって,指定するものではないです。
よって,
Dim lngType As Long, cbData As Long
Dim Result As Long
cbData = Len(key)
Result = RegQueryValueEx(nHandle, key_name, ByVal 0&, lngType, key, cbData)
If Result <> ERROR_SUCCESS Then
Rem エラー時の処理
End If
のような形式になります。
そうそう,フラグを+で足すのはやめた方がよいです。
Const KEY_ALL_ACCESS As Long = KEY_QUERY_VALUE Or KEY_SET_VALUE Or ...
としましょう。
度々申し訳ありません。
何度も確認を行いましたが、未だにうまくいきませんでした。
宜しければもう少しお力添えをお願いします。
Public Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long
Public Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal strValueName As String, ByRef lpReserved As Long, ByVal lngType As Long, lpData As Any, ByRef cbData As Long) As Long
Public Const REG_DWORD = 4
Public Const KEY_QUERY_VALUE = &H1
Public Const HKEY_LOCAL_MACHINE = &H80000002
Const ROOTKEY = HKEY_LOCAL_MACHINE
Const SUBKEY = "Software\\ABCD\\EFG"
Private Function get_reg(key_name As String) As String
Dim key As Long
Dim nHandle As Long
Dim length As Long
Dim Ret As Long
length = Len(key)
'キーをオープンしてハンドルを得る
Ret = RegOpenKeyEx(ROOTKEY, SUBKEY, 0, KEY_QUERY_VALUE, nHandle)
key = 0
'HensuはRegOpenKeyExで開いたキーのハンドル
Ret = RegQueryValueEx(nHandle, key_name, 0, REG_DWORD, key, length)
'ハンドルを閉じる
Call RegCloseKey(nHandle)
get_reg = key
End Function
このソースでRegQueryValueExが87を返します。(RegOpenKeyExは0を)
レジストリには、値が既に登録されており、regeditにて確認もしております。
申し訳ありませんが、よろしくお願いします。
Private Function get_reg(key_name As String) As String
↓
Private Function get_reg(key_name As String) As Long
ですね。すみません。
しかし、今回の問題とは関係なさそうです。
Public Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" _
(ByVal hKey As Long, ByVal strValueName As String, ByVal lpReserved As Long, _
ByRef lngType As Long, lpData As Any, ByRef cbData As Long) As Long
いろいろ試した結果、
この宣言方法で上手く出来るようになりました。
いろいろご迷惑をおかけしましたが、凄く充実感に溢れています。
ご指導のありがとうございました。
解決が付いていますが根本的なところがまったくわかっていないようなので書きます。
まず,RegQueryValueExの引数は,順に,
・HKEY hKey (in)
目的の値が存在するキーのハンドル。入力。
・LPCTSTR lpValueName (in)
目的の値の名前。入力。
#ヘルプの誤植のことを忘れていたので,前回LPTSTRとしていました。
・LPDWORD lpReserved
予約された引数。NULLを渡すこと。
#VBだと,ByRefでByVal 0&を渡すことで対応。
・LPDWORD lpType (out)
値の種類を受け取る変数へのポインタ。出力。
・LPBYTE lpData (out)
値のデータを受け取るバイト列の先頭へのポインタ。出力。
・LPDWORD lpcbData (in/out)
入力としてlpDataのバッファサイズを渡し,
実際に使ったデータを出力として受けるための変数へのポインタ。入出力。
となっています。
私が書いたコードをよく読んでください。
REG_DWORDを指定しているようですが,全く意味がないです。
ちなみに,
> このソースでRegQueryValueExが87を返します。
は,
>87 : ERROR_INVALID_PARAMETER
>パラメータに誤りがあります。
という内容のエラーです。
ツイート | ![]() |