none
Windows10+VB2017でWin32APIが呼び出せない。 RRS feed

  • 質問

  • Windows10+VB2017でWin32APIが呼び出せません。
    最終的にはRegQueryValueExを呼び出し、Internet ExplorerによりDownload Folderに設定されているフォルダを特定したいと考えているのですが、これに先立ちInternet ExplorerのキーをオープンするRegOpenKeyExが起動せず、悩んでいます。
    下記のSubを起動すると、サブキーのオープンに失敗しました、とのメッセージと共に、エラーコード87で終了してしまいます。
    このエラーはパラメーターが間違っているときに発生するようですが、API宣言の引数の型はLong型からInteger型に変更してありますし、呼び出しの際の型もInteger型からShort型に変更してあります。
    これ以上はどこを修正すればいいのか分かりません。どうすればよいのでしょうか?
    p.s.
    本フォーラムにて、類似する質問を見つけましたが、System.Text.StringBuilderが使われていたりと、私では理解できない構文が使われていたため、改めて質問させていただきます。
    https://social.msdn.microsoft.com/Forums/ja-JP/888cc88a-4533-438e-a704-d69b82cfac15/vb2005win32apigetprinterdriverdirectory?forum=vbgeneralja

    Option Explicit On
    Public Class Form1
        Private Const HKEY_CURRENT_USER = &H80000001    '現在のユーザーの設定に対するHKEY_USERのリンク
        Private Const KEY_CREATE_LINK = &H20            '他のサブキーへのシンボリックリンクの作成を許可
        Private Const KEY_CREATE_SUB_KEY = &H4          'サブキーの作成を許可
        Private Const KEY_ENUMERATE_SUB_KEYS = &H8      'サブキーの列挙を許可
        Private Const KEY_NOTIFY = &H10                 '変更通知を有効にする(WIN95は未対応)
        Private Const KEY_QUERY_VALUE = &H1             'サブキーの値の参照を許可
        Private Const KEY_SET_VALUE = &H2               'サブキーの書き込みを許可
        'KEY_CREATE_SUB_KEY + KEY_SET_VALUE
        Private Const KEY_WRITE = ((STANDARD_RIGHTS_WRITE Or KEY_SET_VALUE Or
          KEY_CREATE_SUB_KEY) And (Not SYNCHRONIZE))
        'KEY_EXECUTE + KEY_NOTIFY
        Private Const KEY_READ = ((STANDARD_RIGHTS_READ Or KEY_QUERY_VALUE Or
          KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY) And (Not SYNCHRONIZE))
        Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" _
          (ByVal hKey As Integer, ByVal lpSubKey As String,
           ByVal ulOptions As Integer, ByVal samDesired As Integer, phkResult As Integer) As Integer
     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
         Dim hKeyResult As Short                      'キーハンドル
            Dim SubKey As String                         'サブキー
            Dim ret As Short                             '戻り値
            '----------------------------------
            'オープンするサブキーの設定
            SubKey = "Software\Microsoft\Internet Explorer\Main"
            'レジストリのサブキーのオープン(読み込みのみ)
            ret = RegOpenKeyEx(HKEY_CURRENT_USER, SubKey, 0,
                               KEY_READ, hKeyResult)
            If ret <> ERROR_SUCCESS Then
                TextBox1.Text = "サブキーのオープンに失敗しました。" & ret
            Else
                TextBox1.Text = "成功!"
            End If
        End Sub
    End Class
    2017年10月6日 2:31

回答

  • そもそもレジストリにアクセスするなら、Microsoft.Win32.RegistryクラスおよびMicrosoft.Win32.RegistryKeyクラスを使用したほうがいいかと思います。
    • 編集済み Hongliang 2017年10月6日 2:39
    • 回答としてマーク ノラネコ 2017年10月6日 6:37
    2017年10月6日 2:39
  • Hongliangさんの指摘の通りですが、コード自体の問題点としては

     Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" _
        (ByVal hKey As Integer, ByVal lpSubKey As String,
         ByVal ulOptions As Integer, ByVal samDesired As Integer, phkResult As Integer) As Integer

    VB6.0以前とVB.NET以降とでは既定の引き渡しの方法が変更されています。ByVal、ByRefどちらも指定しない場合、VB6.0ではByRefとして動作しますが、VB.NET以降ではByValとして動作します。参考にされたのはVB6.0コードでしょうか、引数phkResultの指定が不正になっています。正しくはByRefを指定する必要があります。

    その他の問題点として、Alias "RegOpenKeyExA"を指定するのであれば併せてAnsiも指定すべきです。もしくはAliasの指定を削除してもかまいません。また引数hKeyとphkResultの型はネイティブではHKEYですのでVB.NETではIntegerではなくIntPtrです。

    • 回答としてマーク ノラネコ 2017年10月6日 6:37
    2017年10月6日 3:41

すべての返信

  • そもそもレジストリにアクセスするなら、Microsoft.Win32.RegistryクラスおよびMicrosoft.Win32.RegistryKeyクラスを使用したほうがいいかと思います。
    • 編集済み Hongliang 2017年10月6日 2:39
    • 回答としてマーク ノラネコ 2017年10月6日 6:37
    2017年10月6日 2:39
  • Hongliangさんの指摘の通りですが、コード自体の問題点としては

     Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" _
        (ByVal hKey As Integer, ByVal lpSubKey As String,
         ByVal ulOptions As Integer, ByVal samDesired As Integer, phkResult As Integer) As Integer

    VB6.0以前とVB.NET以降とでは既定の引き渡しの方法が変更されています。ByVal、ByRefどちらも指定しない場合、VB6.0ではByRefとして動作しますが、VB.NET以降ではByValとして動作します。参考にされたのはVB6.0コードでしょうか、引数phkResultの指定が不正になっています。正しくはByRefを指定する必要があります。

    その他の問題点として、Alias "RegOpenKeyExA"を指定するのであれば併せてAnsiも指定すべきです。もしくはAliasの指定を削除してもかまいません。また引数hKeyとphkResultの型はネイティブではHKEYですのでVB.NETではIntegerではなくIntPtrです。

    • 回答としてマーク ノラネコ 2017年10月6日 6:37
    2017年10月6日 3:41
  • ご回答ありがとうございます。

    教えていただいたMicrosoft.Win32.Registryクラス、Microsoft.Win32.RegistryKeyクラスに加え、

    My.Computer.Registryを利用してみようと思います。

    どうもありがとうございます。

    2017年10月6日 6:19
  • ご回答ありがとうございます。

    どうやらお気づきになっているようですが、僕はVB5を主に使用していた者です。

    Win32APIの利用において、ご指摘されているような引数の型の変化などがあったことは全く知りませんでした。

    前レスでHongliangさんに教えていただいたクラス群で目的が達せられないような場合には、再度改めてWin32APIの呼び出しの方法を教えていただきたいと思います。

    どうもありがとうございました。

    2017年10月6日 6:32