dポイントプレゼントキャンペーン実施中!

WindowsのプロダクトIDを取得する方法について

Active Basic 4.24.00を使用してプログラムを書いています。
(AB5はバグがあるためまだ使用していません。)

http://www.ruriplus.com/msaccess/tch/tch_036.html
上記のサイト様を参考に、WindowsのProduct IDを取得しようとしています。
(参考というより、コピペなのですが・・・)

しかし、きちんと取得してくれません。
AB用に以下のように書き直しました。

Function GetWinProductId() As String
Dim stSubKey As String
Dim stProductid As String
Dim hkeyRoot As HKEY
Dim lErr As Long
Dim OSVER As OSVERSIONINFO
Dim dummy As Long

stProductid=ZeroString(256)

OSVER.dwOSVersionInfoSize = Len(OSVER)
lErr = GetVersionEx(OSVER)
If lErr = 0 Then Exit Function

If OSVER.dwPlatformId = VER_PLATFORM_WIN32_NT Then
stSubKey = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
Else
stSubKey = "SOFTWARE\Microsoft\Windows\CurrentVersion"
End If

lErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, stSubKey, &0, KEY_READ, hkeyRoot)
If lErr <> 0 Then
MessageBox(0,"ERROR","1",0)
Exit Function
End If
lErr = RegQueryValueEx(hkeyRoot, "ProductId", &0, REG_SZ,stProductid, 256)
If lErr <> 0 Then
MessageBox(0,"ERROR","2",0)
Exit Function
End If
lErr = RegCloseKey(hkeyRoot)
If lErr <> 0 Then
MessageBox(0,"ERROR","3",0)
Exit Function
End If

GetWinProductId = Left$(stProductid, 255 /*InStr(1, stProductid, vbNullChar, vbBinaryCompare)*/)
End Function


MessageBox(0,GetWinProductId(),0,0)


Left$(stProductid, 255 /*InStr(1, stProductid, vbNullChar, vbBinaryCompare)*/)
この部分は、よく分からなかったので、とりあえず放置しています。
その前に、変数『stProductid』に値が帰ってこないのです。
(RegQueryValueExでエラーが返る。FormatMessageでエラーを見ると、正常終了している。・・・が、0以外の値が返ってくる)


すいませんが、ご存知の方、やり方をご教示ください。
お願いします。

A 回答 (4件)

ちょっと興味があって試してみました。



C++ で作成しました。

Win32 で作成し、Win7 (64bit) で実行すると "ProductId" はダメでした。
同じ実行ファイルを、XP (32bit) で実行すると正常に取得できました。
また、"ProductId" を "ProductName" に変えると、Win7 (64bit) でも正常に取得できました。


#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
OSVERSIONINFO osv;
HKEY hk;
LPTSTR pKeyName;
TCHAR szProductId[ 1000 ];
DWORD dwSize = 1000;
DWORD dwType = REG_SZ;
LONG result;

osv.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
GetVersionEx( &osv );

if( osv.dwPlatformId == VER_PLATFORM_WIN32_NT ) {
pKeyName = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
} else {
pKeyName = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion");
}
if( 0 == RegOpenKeyEx( HKEY_LOCAL_MACHINE, pKeyName, 0, KEY_QUERY_VALUE, &hk ) ) {

memset( szProductId, 0, dwSize );
result = RegQueryValueEx( hk, _T("ProductId"), 0, &dwType, ( LPBYTE )szProductId, &dwSize );
//result = RegQueryValueEx( hk, _T("ProductName"), 0, &dwType, ( LPBYTE )szProductId, &dwSize );
if( result == ERROR_SUCCESS ) {
MessageBox( NULL, szProductId, _T("Get Product ID"), MB_ICONINFORMATION );
} else {
MessageBox( NULL, _T("Error"), _T("Get Product ID"), MB_ICONEXCLAMATION );
}
RegCloseKey( hk );
}
return 0;
}

ところが、同じソースを X64 でビルドすると、Win7 (64bit) で正常に取得できました。

ん~、何なんでしょうね・・・。WOW64 が何か絡んでいそうですね。
    • good
    • 1
この回答へのお礼

>Win32 で作成し、Win7 (64bit) で実行すると "ProductId" はダメでした。
>同じ実行ファイルを、XP (32bit) で実行すると正常に取得できました。

おお、まったく同じ環境だ。

当方も同じ環境です。
Win 7 64bit
Win XP 32bit
で実験。
32bitコンパイラー使用しました。

>ところが、同じソースを X64 でビルドすると、Win7 (64bit) で正常に取得できました。
なんと!
それは気がつかなかった。
早速実験したところ、確かに64bitコンパイラーで実行すると、取得できました。


今、これをやっているのは、インストーラー的なものを作っていて、
再配布防止にプロダクトIDを中身にこっそり付け加えようという陰謀なのです。
しかし、64bitでコンパイルすると、32bitのパソコンで使えないのが困りますね・・・
出来れば32bitでコンパイルしたいです。
64bitでも動かせるので・・・

確かに、64bitに移りつつありますが、それでも32bitを使ってる方は多いです。
まだ32bitでコンパイルした方が無難ですね・・・


>WOW64 が何か絡んでいそうですね。
WOW64・・・何かで聞いたなぁ・・・なんでしたっけ・・・
といってググって理解。

確かに関係ありそう・・・?

でも、レジストリ(レジストリー?)の値を読み取るだけですし・・・
関係あるのでしょうか・・・?
悩まされます。

しかも取得できるのは、完全な個人情報(・・・というか、外部に漏れたらまずそうな情報)以外ですよね・・・
な~んか引っかかります・・・
権限が足りないのか・・・と思っても、完全管理者権限ですし・・・

何なのでしょう・・・?

お礼日時:2010/10/31 21:29

#2にも書いたように私はABの構文知りませんので


(PC自体には以前入れたけど使ってないし)
試しに挑戦しましたが結局アドレスの渡し方がわからず断念しました

また#2自体にもちょっと書き忘れてる部分がありました
(REG_SZそのまま渡してるのも間違い)

以下此方でVCにて確認したソースコードとなります
エラー処理など省いています

同じ内容が変換できてれば動くはずなので
動かないのであればどこかのパラメータが
正常に渡せていないんでしょうとしか言えません

自分が挫折した範囲では RegOpenKeyEx のhkeyRoot の
アドレス渡しの方法がわからず
  VarPtr(hkeyRoot) で書いても構文エラーになってお手上げ
適当にやってみて関数自体は正常終了するが
まともな値が得られていないような感じでした
  デバック方法すらどうやればいいのかよくわからないので
  違うかもしてませんが

他には見た限り \\ でなくて \ で動いてそうでした
(ABってそうなのねと ちなみに使ったのはVer4.23)

charstSubKey[256];
charstProductid[256];
HKEYhkeyRoot;
LONGlErr;
OSVERSIONINFOOSVER;
ULONGdummy;
ULONGdummy1;

memset(stProductid, 0, sizeof(stProductid));
OSVER.dwOSVersionInfoSize = sizeof(OSVER);
lErr = GetVersionEx(&OSVER);

if (OSVER.dwPlatformId == VER_PLATFORM_WIN32_NT)
 strcpy(stSubKey ,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
else
 strcpy(stSubKey , "SOFTWARE\\Microsoft\\Windows\\CurrentVersion");

lErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, stSubKey, 0, KEY_READ, &hkeyRoot);

dummy = REG_SZ;
dummy1 = sizeof(stProductid);
lErr = RegQueryValueEx(hkeyRoot, "ProductId", 0, &dummy,(unsigned char *)stProductid, &dummy1);

lErr = RegCloseKey(hkeyRoot);


今回まだそこまで行ってないですが実際レジストリに値が存在してることも
確認しないとダメでしょう
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

>以下此方でVCにて確認したソースコードとなります
>エラー処理など省いています
参考にさせていただきました。

自分が書き直したコードはエラーがなかったのですが、
どうしても値が読み取れず、とりあえず、ほかの値を指定して
取得してみると、見事取得。
(レジストリに値は存在しております。)

・・・ということは、ProductIdだけ取得できないのでしょうか?
書き忘れていましたが、当方、Windows 7 HPを使用しております。
7では防御されてしまうのでしょうか・・・?

お礼日時:2010/10/27 22:16

ABの構文は知らないので同様のことをVCで確認しました結果


気になった点を羅列します
1."SOFTWARE\Microsoft\Windows NT\CurrentVersion"
  文字列内 \ の表記は \\ のようにしないと
  エスケープ文字として誤認されませんか?
  ※ VCではコンパイルでエラーになってます

2.サンプルコードに間違いがあると思われます(以下2か所)
  RegOpenKeyEx(HKEY_LOCAL_MACHINE, stSubKey, 0&, KEY_READ, hkeyRoot)
  hkeyRootの値ではなくアドレス渡さないとダメ
  RegQueryValueEx(hkeyRoot, "ProductId", 0&, REG_SZ, ByVal stProductid, 255)
  255の値を渡すのではなくその値が入ってるアドレス渡さないとダメ
  ではないかと思います

  また下が ByVal stProductid と書くのであれば上が stSubKey ってのは
  おかしいのではないかと(どっちでも同じ意味になるならいいです)

3.RegQueryValueExでエラーになったときCloseしてないのが問題ではないか

上記3点
そのあたりを直して手元で確認した限りきちんと読めてます
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

とりあえず、一からチェックしていったところ、
RegQueryValueExの第四引数はNULL
第六引数は返ってくる値を受ける変数の指定みたいですね。
すいませんでした。

とりあえず、ABにエスケープはない(・・・見たことないだけか)ので、
エラーは出ませんし、これはないと思います。

しかし、アクセスエラーが出なくなったら、『指定されたファイルが見つかりません』と出ます。
Registory Editorで確認しても、値はあります。
これは何故なのでしょうか?
またまたすいませんが、再度ご教授ください。
何度やっても同じエラーで困っています。
よろしくお願いします。

お礼日時:2010/10/26 23:12

内容はちゃんと見てません


>(RegQueryValueExでエラーが返る。FormatMessageでエラーを見ると、
> 正常終了している。・・・が、0以外の値が返ってくる)

手元のMSDN見てみると
--------------
関数が失敗すると、WINERROR.H ヘッダファイルで定義された、0 以外のエラーコードが返ります。FORMAT_MESSAGE_FROM_SYSTEM フラグを指定して FormatMessage 関数を呼び出すと、エラーの一般的な説明が取得できます。
--------------
との記載があります  フラグ指定してますか?
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

>フラグ指定してますか?
すいません、GetLastError()使っていました。
早速戻り値を指定したところ、

『パラメーターが間違っています。』

と返ってきました。

・・・しかし、間違っている箇所が分かりません。
とりあえず、エラーが返ってきたのが、RegQueryValueEx関数です。

すいませんが、ご教授ください。

お礼日時:2010/10/23 23:25

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!