- ベストアンサー
WindowsのプロダクトIDを取得する方法
- WindowsのプロダクトIDを取得する方法について解説します。
- Active Basic 4.24.00を使用してプログラムを書いており、WindowsのProduct IDを取得しようとしています。しかし、うまく取得できません。
- 関数GetWinProductIdを使用してProduct IDを取得する方法について質問しています。
- みんなの回答 (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 が何か絡んでいそうですね。
その他の回答 (3)
- koi1234
- ベストアンサー率53% (1866/3459)
#2にも書いたように私はABの構文知りませんので (PC自体には以前入れたけど使ってないし) 試しに挑戦しましたが結局アドレスの渡し方がわからず断念しました また#2自体にもちょっと書き忘れてる部分がありました (REG_SZそのまま渡してるのも間違い) 以下此方でVCにて確認したソースコードとなります エラー処理など省いています 同じ内容が変換できてれば動くはずなので 動かないのであればどこかのパラメータが 正常に渡せていないんでしょうとしか言えません 自分が挫折した範囲では RegOpenKeyEx のhkeyRoot の アドレス渡しの方法がわからず VarPtr(hkeyRoot) で書いても構文エラーになってお手上げ 適当にやってみて関数自体は正常終了するが まともな値が得られていないような感じでした デバック方法すらどうやればいいのかよくわからないので 違うかもしてませんが 他には見た限り \\ でなくて \ で動いてそうでした (ABってそうなのねと ちなみに使ったのはVer4.23) char stSubKey[256]; char stProductid[256]; HKEY hkeyRoot; LONG lErr; OSVERSIONINFO OSVER; ULONG dummy; ULONG dummy1; 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); 今回まだそこまで行ってないですが実際レジストリに値が存在してることも 確認しないとダメでしょう
お礼
ご回答ありがとうございます。 >以下此方でVCにて確認したソースコードとなります >エラー処理など省いています 参考にさせていただきました。 自分が書き直したコードはエラーがなかったのですが、 どうしても値が読み取れず、とりあえず、ほかの値を指定して 取得してみると、見事取得。 (レジストリに値は存在しております。) ・・・ということは、ProductIdだけ取得できないのでしょうか? 書き忘れていましたが、当方、Windows 7 HPを使用しております。 7では防御されてしまうのでしょうか・・・?
- koi1234
- ベストアンサー率53% (1866/3459)
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点 そのあたりを直して手元で確認した限りきちんと読めてます
お礼
ご回答ありがとうございます。 とりあえず、一からチェックしていったところ、 RegQueryValueExの第四引数はNULL 第六引数は返ってくる値を受ける変数の指定みたいですね。 すいませんでした。 とりあえず、ABにエスケープはない(・・・見たことないだけか)ので、 エラーは出ませんし、これはないと思います。 しかし、アクセスエラーが出なくなったら、『指定されたファイルが見つかりません』と出ます。 Registory Editorで確認しても、値はあります。 これは何故なのでしょうか? またまたすいませんが、再度ご教授ください。 何度やっても同じエラーで困っています。 よろしくお願いします。
- koi1234
- ベストアンサー率53% (1866/3459)
内容はちゃんと見てません >(RegQueryValueExでエラーが返る。FormatMessageでエラーを見ると、 > 正常終了している。・・・が、0以外の値が返ってくる) 手元のMSDN見てみると -------------- 関数が失敗すると、WINERROR.H ヘッダファイルで定義された、0 以外のエラーコードが返ります。FORMAT_MESSAGE_FROM_SYSTEM フラグを指定して FormatMessage 関数を呼び出すと、エラーの一般的な説明が取得できます。 -------------- との記載があります フラグ指定してますか?
お礼
ご回答ありがとうございます。 >フラグ指定してますか? すいません、GetLastError()使っていました。 早速戻り値を指定したところ、 『パラメーターが間違っています。』 と返ってきました。 ・・・しかし、間違っている箇所が分かりません。 とりあえず、エラーが返ってきたのが、RegQueryValueEx関数です。 すいませんが、ご教授ください。
お礼
>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・・・何かで聞いたなぁ・・・なんでしたっけ・・・ といってググって理解。 確かに関係ありそう・・・? でも、レジストリ(レジストリー?)の値を読み取るだけですし・・・ 関係あるのでしょうか・・・? 悩まされます。 しかも取得できるのは、完全な個人情報(・・・というか、外部に漏れたらまずそうな情報)以外ですよね・・・ な~んか引っかかります・・・ 権限が足りないのか・・・と思っても、完全管理者権限ですし・・・ 何なのでしょう・・・?