RegQueryValueEx での REG_SZ 値の読取り

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
返信する
メッセージ
作成者
cv603

RegQueryValueEx での REG_SZ 値の読取り

#1 投稿記事 by cv603 »

ActiveBasic 4.21.00 で RegQueryValueEx を使った REG_SZ 値の読取りがうまくいきません。
DEBUG で見ると lpcbData は受け取っていますが lpData が受け取れないようです。
REG_DWORD は読取れます。また RegSetValueEx での書込みもできます。
うまく読取れる例示がありましたら教えて下さい。
xsb7
記事: 10
登録日時: 2006年3月01日(水) 13:54
連絡する:

#2 投稿記事 by xsb7 »

lpcbData には、あらかじめ用意されているバッファの長さが入れられていないと、RegQueryValueEx は、lpData を返しません。

一回目の RegQueryValueExで、lpcbData を取得してからメモリを確保したうえで、もう一度 RegQueryValueEx を呼んでデータ本体を取得してください。

間違っていたらごめんなさい。
cv603

いろいろ試してはいるんですが

#3 投稿記事 by cv603 »

メモリ確保はやっています。
------------------------
Dim hKey As HKEY
Dim phkResult As HKEY
Dim lpSubKey As String
Dim ValueName As String
Dim lpReserved As DWord
Dim RegType As DWord
Dim lpType As DWordPtr
Dim lpData As VoidPtr
Dim lpcbData As DWordPtr
Dim Company As String
Dim CompanyL As Long

hKey = HKEY_LOCAL_MACHINE
lpSubKey = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"

If RegOpenKeyEx(hKey, lpSubKey, 0, KEY_READ, phkResult) = ERROR_SUCCESS Then
ValueName = "RegisteredOrganization"
lpReserved = 0
RegType = REG_SZ
lpType = VarPtr(RegType)
lpData = VarPtr(Company)
lpcbData = VarPtr(CompanyL)

If RegQueryValueEx(phkResult,ValueName,lpReserved,lpType,lpData,lpcbData)= ERROR_SUCCESS Then
Company = String$(CompanyL," ")
If RegQueryValueEx(phkResult,ValueName,lpReserved,lpType,lpData,lpcbData)= ERROR_SUCCESS Then
Else Goto *Read_error
End If
Else Goto *Read_error
End If
End If
RegCloseKey(phkResult)
------------------------
エラーは出ないのですが Company には何も読み込まれていません。
CompanyL には文字数が入ってきます。
RegOpenKeyEx のパラメータを色々変えてみましたが(NULL指定とか)うまくいきません。
読取るレジストリの値が REG_DWORD の場合はうまくいくんですが。
hira
記事: 203
登録日時: 2005年5月31日(火) 20:14
お住まい: 兵庫県
連絡する:

Re: いろいろ試してはいるんですが

#4 投稿記事 by hira »

CompanyはString型なので、ポインタはStrPtr関数で取得します。[lpData = VarPtr(Company) の行のこと]
また、String型のポインタは文字列を代入するたびに変わります。そのため、別の変数にポインタを格納しておくのはオススメできません。引数に直接StrPtr関数で取得したポインタを指定するか、(コンパイルが通るなら)単純に文字列変数をそのまま引数に指定するほうが安全です。
※どうしても変数にポインタを格納する場合は、そのポインタを使う関数の直前にしておいたほうがいいでしょう
それから、データの長さだけがほしいときは、lpDataパラメータはNULLにしておいたほうがいいでしょう。

以上を踏まえると…

コード: 全て選択

Dim hKey As HKEY
Dim phkResult As HKEY
Dim lpSubKey As String
Dim ValueName As String
Dim lpReserved As DWord
Dim RegType As DWord
Dim lpType As DWordPtr
Dim lpcbData As DWordPtr
Dim Company As String
Dim CompanyL As Long

hKey = HKEY_LOCAL_MACHINE
lpSubKey = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"

If RegOpenKeyEx(hKey, lpSubKey, 0, KEY_READ, phkResult) = ERROR_SUCCESS Then
    ValueName = "RegisteredOrganization"
    lpReserved = 0
    RegType = REG_SZ
    lpType = VarPtr(RegType)
    lpcbData = VarPtr(CompanyL)
    If RegQueryValueEx(phkResult,ValueName,lpReserved,lpType,NULL,lpcbData)= ERROR_SUCCESS Then
        Company = String$(CompanyL," ")
        If RegQueryValueEx(phkResult,ValueName,lpReserved,lpType,StrPtr(Company),lpcbData)= ERROR_SUCCESS Then
        Else Goto *Read_error
        End If
    Else Goto *Read_error
    End If
End If
RegCloseKey(phkResult)
こんな感じでしょうか?(当方の環境で動作確認)
cv603

StrPtrを使うんですね

#5 投稿記事 by cv603 »

ありがとうございます。
String型の場合はStrPtr関数を使うんですね。
Win32プログラミング講座(Step28)とActiveBasicのHELPを見て、全ての型でVarPtrが使えるものと思い込んでいました。
ご指摘のとおりStrPtr(lpData)ではうまくいきました。
また、RegQueryValueEx では lpData として文字列変数をそのまま使うとうまくいきません。
エラーは出ませんが変数には読み込めませんでした。
RegSetValueEx では lpData として文字列変数をそのまま使ってもOKです。
このへんは仕様なんでしょうか。

56才、孫1人ですがプログラミング言語はまだ初心者です。
これからもよろしくお願いします。
hira
記事: 203
登録日時: 2005年5月31日(火) 20:14
お住まい: 兵庫県
連絡する:

Re: StrPtrを使うんですね

#6 投稿記事 by hira »

確かに、当方でも文字列変数を直接指定すると結果が取れませんでした。
以前はBytePtr引数だけでなくVoidPtr引数でもいけた気がしたんですが…。すみません、StrPtr使ってやってください(^^;;
どちらにしても、エラーにならないのはデバッグするときに無駄に時間を使わせますから、バグとして報告しておきます。
返信する