- ベストアンサー
コンピュータ内で一意な識別子を作る方法
- コンピュータ内で一意な識別子を作るためには、ユーザーID、OSシリアルナンバー、MACアドレスなど複数の要素を組み合わせることが有効です。
- ユーザーIDはレジストリのHKEY_USERS\S-?-?-??-???に格納されていますが、複数存在する場合があります。
- MACアドレスの場合、NICが複数刺さっている場合でも、プライマリの検出方法を使用することで一意な値を取得できます。
- みんなの回答 (13)
- 専門家の回答
質問者が選んだベストアンサー
『ほぼ確実』がどの程度【確実】を求めているのかが問題となります。 エミュレータ(VirtualPCやVMWareなど)環境ではMacアドレスをユーザが設定することが当然のように行われます。 「Macアドレスは世界中で一意」というのは建前です。 「グローバルネットワーク上に存在するすべてのコンピュータのコンピュータ/ユーザごとに【確実に】一意なIDの自動割り当て、自動認証、同一IDの自動再割り当てする技術」は現在存在しません。 この技術の発明を待っているシステムがたくさんあり、それができれば特許で大もうけできるくらいの発明になります。 現在の技術ではサーバーで生成した一意なIDをユーザごとに保存させるくらいしか【確実な】方法はありません。 質問が「ネットワーク上」となっており、「ネットワークセグメント上」でないため、グローバルネットワークを想定しています。 ネットワークセグメント内でよいのであれば、Macアドレスが使えますがMacアドレスは普遍ではありません。
その他の回答 (12)
> ちなみ皆さんVBおっしゃいますが、VB.NETなのですよ~。 手抜きな方法を提案します。(^^; VB6.0、または、Office のVBAで書いたコードをVB.NETのアップグレードエンジンで変換し、ウォーニングが出た箇所のみ手作業で修正。(^^; この方法だと、最適なコードが生成できないのが泣き所です。旧VBでは複雑なコードを書かないと実現できなかった機能が.NETでは1行で済んでしまう、といったケースもあり、ムダなコードが大量に発生する可能性があります。 ヘルプやドキュメントを調べるのがめんどくさいときに威力を発揮するソリューションです。(おい
お礼
はい、以前それをやったことがあり、大量の構文エラーが。 しかもコンポーネントなどを使っている場合、それも別に取り込まれるし・・・。 だから1から勉強しようと思ってるのですよ。 ライブラリがぜんぜん違うんで、どういう関数を使うべきなのかとかわからないときに、一応自動変換されたコードも参考にはなりますがね。
- osamuy
- ベストアンサー率42% (1231/2878)
No.2の続き。 プログラムインストール時に、一度だけ、UUIDを生成し、それを種として、MD5やSHAでIDを計算するという手もあります。 Windows NT/2000/XPなら、ユーザには必ずSIDが付与されていて、これもUUIDと同じような計算をしてますので、こいつを種にする手もあります。
お礼
一応、一度作ったIDは設定ファイルが破棄されない限り作り直しません。 ただ、設定ファイルが消されてしまったときに、できるだけ以前と同じIDを作りたいので、なるべく不変なソースを選びたいのです。
- terra5
- ベストアンサー率34% (574/1662)
MACアドレスは一般的には固定で唯一です。 通常はハードウェアレベルで固定で、ソフトで変更できるものではありません。 ただし、例外は存在します。 設定可能なハードウェアは存在します。 通常は一意と考えて問題ないでしょう。 多分、既に出てきているMACアドレス以外のものよりはましでしょう。 CではMACアドレス持ってくるプログラムは作りましたが、VBは分かりません(^^;
お礼
とりあえず、ユーザーに表面的に見せるものではないので、どれだけ長くなってもいいかなと。 だから、MAC以外のものも組み合わせようと思います。 ちなみ皆さんVBおっしゃいますが、VB.NETなのですよ~。 レジストリとかAPIなら言語に依存しない部分だからいいんですがw
> ユーザー名とコンピュータ名をいれて、それらが変わる危険性を含めるよりは、ユーザーID、OSプロダクトID、MACアドレスの3つで行ったほうが良いかな。 Windows XP、Office XP のユーザーIDは概ねそのような方法で生成しているようです。 (詳しいことは知りませんが)
お礼
ぅゎ・・・じゃあユーザーIDを入れる意味がないかな。 でも、コンピュータ内やドメイン内でユーザーIDは一意だから、少なくともプロダクトIDに依存しない何かが含まれているはずだからw
- yamahanian
- ベストアンサー率46% (7/15)
#5です。 ちょっと話はずれてしまいますが・・・ MACアドレスとは、上位層のプロトコル(TCP/IPやNetBEUI)に関係なくネットワーク上でパケットを到達させるもっとも根底のアドレスです。 ネットワーク内でMACアドレスが重複する事は絶対にないです。 たとえ可能であってもそのネットワークは機能しません。
- 参考URL:
- http://www.allied-telesis.co.jp/cgi-bin/ysearch/esearch.cgi?kopt=3&kwd="MAC%A5%A2%A5%C9%A5%EC%A5%B9"
お礼
>ネットワーク内でMACアドレスが重複する事は絶対にないです いえ、だから違うネットワークだとどうなのかなと思いました。 プロキシを通した場合、ネットワークが遮断されてるようなものですから、同じMACアドレスが存在できるのかと思ったんですが。 まあ、考えすぎですね。 でも、念のためMACアドレスとほかの値も組み合わせたいと思います。 ユーザー名とコンピュータ名をいれて、それらが変わる危険性を含めるよりは、ユーザーID、OSプロダクトID、MACアドレスの3つで行ったほうが良いかな。
> MACアドレスって、ソフトで変えられませんでしたっけ? 確か、可能なはずですが、通常の運用では考えられません。
お礼
プロバイダによってはMacアドレスを変更するように要求されるらしいんですが、まあ、MACアドレスとほかのものを組み合わせれば、まずかぶらないでしょう。
> 万人に使われることを想定しているので、固定IPと仮定はできません。 > それに、NAT環境で複数のマシンでグローバルIPを共有する場合は意味がないし、プロキシを通すことも考えており、まったくグローバルIPに触れられない場合、プライベートIPも意味がありません。 前提条件を最初に明示しないのは如何なものかと・・・。 # 回答者のコメントにケチを付けているようにも読み取れる。 MACアドレスの取得は下記の要領。 (VB6.0、Office 97/2000 VBAで動作確認済み) # 出典は失念。(Google等で検索すれば見つかるはず) # ちなみにこのAPIを知らなかったときは、CUIのユーティリティをShellでキックして、結果をテキストファイルにリダイレクトしたものを読み込む、というかなり非効率(おバカ)なことをやってました。(^^;; Option Explicit Private Declare Sub memmoveAL Lib "kernel32" Alias "RtlMoveMemory" (ByRef dst As Any, ByVal src As Long, ByVal num As Long) Private Declare Sub memset Lib "kernel32" Alias "RtlFillMemory" (ByRef dst As Any, ByVal length As Long, ByVal fill As Byte) Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long Private Declare Function GlobalHandle Lib "kernel32" (ByRef wMem As Any) As Long Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long 'Global Memory Flags Private Const GMEM_MOVEABLE As Long = &H2& Private Const GMEM_ZEROINIT As Long = &H40& Private Const GHND As Long = (GMEM_MOVEABLE Or GMEM_ZEROINIT) Private Type T_ADAPTER_STATUS adapter_address(5) As Byte rev_major As Byte reserved0 As Byte adapter_type As Byte rev_minor As Byte duration As Long frmr_recv As Long frmr_xmit As Long iframe_recv_err As Long xmit_aborts As Long xmit_success As Long recv_success As Long iframe_xmit_err As Long recv_buff_unavail As Long t1_timeouts As Long ti_timeouts As Long reserved1 As Long free_ncbs As Long max_cfg_ncbs As Long max_ncbs As Long xmit_buf_unavail As Long max_dgram_size As Long pending_sess As Long max_cfg_sess As Long max_sess As Long max_sess_pkt_size As Long name_count As Long End Type Private Const NCBNAMSZ As Long = 16 'absolute length of a net name Private Type T_NAME_BUFFER name_(NCBNAMSZ - 1) As Byte name_num As Byte name_flags As Byte End Type Private Type T_ASTAT adapt As T_ADAPTER_STATUS NameBuff(29) As T_NAME_BUFFER End Type Private Type T_NCB ncb_command As Byte ncb_retcode As Byte ncb_lsn As Byte ncb_num As Byte ncb_buffer As Long ncb_length As Integer ncb_callname(NCBNAMSZ - 1) As Byte ncb_name(NCBNAMSZ - 1) As Byte ncb_rto As Byte ncb_sto As Byte ncb_post As Long ncb_lana_num As Byte ncb_cmd_cplt As Byte ncb_reserve(9) As Byte ncb_event As Long End Type Private Const MAX_LANA As Long = 254 'lana's in range 0 to MAX_LANA inclusive Private Type LANA_ENUM length As Byte lana(MAX_LANA) As Byte End Type 'NCB Command codes Private Const NCBRESET As Byte = &H32 Private Const NCBASTAT As Byte = &H33 Private Const NCBENUM As Byte = &H37 Private Declare Function Netbios Lib "netapi32.dll" (ByRef pncb As Any) As Byte Public Function GetMacAddress() As String '自マシンのMACアドレスを取得する。 Dim strRet As String Dim Ncb As T_NCB Dim bytRetCode As Byte Dim lenum As LANA_ENUM Dim lngNcbLen As Long strRet = "" lngNcbLen = (4 * 3) + 2 + 11 memset Ncb, 0, lngNcbLen With Ncb .ncb_command = NCBENUM .ncb_length = 256 .ncb_buffer = GlobalAllocPtr(GHND, .ncb_length) End With bytRetCode = Netbios(Ncb) If bytRetCode = 0 Then memmoveAL lenum, Ncb.ncb_buffer, Ncb.ncb_length Dim Adapter As T_ASTAT Dim nAdpLen As Long Dim pAdpAdr As Long nAdpLen = ((22 * 4) + 5) + (18 * 30) pAdpAdr = GlobalAllocPtr(GHND, nAdpLen) If lenum.length > 0 Then memset Ncb, 0, lngNcbLen With Ncb .ncb_command = NCBRESET .ncb_lana_num = lenum.lana(0) End With bytRetCode = Netbios(Ncb) If bytRetCode = 0 Then memset Ncb, 0, lngNcbLen With Ncb .ncb_command = NCBASTAT .ncb_lana_num = lenum.lana(0) .ncb_callname(0) = Asc("*") memset .ncb_callname(1), Asc(" "), 15 .ncb_name(0) = 0 .ncb_buffer = pAdpAdr .ncb_length = nAdpLen End With bytRetCode = Netbios(Ncb) If bytRetCode = 0 Then memmoveAL Adapter, pAdpAdr, nAdpLen strRet = Right("00" & Hex(Adapter.adapt.adapter_address(0)), 2) & "-" & _ Right("00" & Hex(Adapter.adapt.adapter_address(1)), 2) & "-" & _ Right("00" & Hex(Adapter.adapt.adapter_address(2)), 2) & "-" & _ Right("00" & Hex(Adapter.adapt.adapter_address(3)), 2) & "-" & _ Right("00" & Hex(Adapter.adapt.adapter_address(4)), 2) & "-" & _ Right("00" & Hex(Adapter.adapt.adapter_address(5)), 2) End If End If End If GlobalFreePtr pAdpAdr End If GlobalFreePtr Ncb.ncb_buffer GetMacAddress = strRet End Function Private Function GlobalAllocPtr(ByVal flags As Long, ByVal cb As Long) As Long GlobalAllocPtr = GlobalLock(GlobalAlloc(flags, (cb))) End Function Private Function GlobalPtrHandle(ByVal lp As Long) As Long GlobalPtrHandle = GlobalHandle(lp) End Function Private Function GlobalUnlockPtr(ByVal lp As Long) As Long GlobalUnlockPtr = GlobalUnlock(GlobalPtrHandle(lp)) End Function Private Sub GlobalFreePtr(ByVal lp As Long) GlobalUnlockPtr lp GlobalFree GlobalPtrHandle(lp) End Sub
お礼
回答ありがとうございます。 >前提条件を最初に明示しないのは如何なものかと・・・。 IPは変わる可能性があるからだめだと断っているのに、固定IPなら大丈夫と回答するのは、#1さんのミスだと思います。 固定IPを使うという文は、すでにIPは変わる可能性があるという条件に違反してるではありませんか。 それにしてもすごい量のコードですね。 MACアドレスだけにこれほど必要とは・・・。 しかもグローバルメモリとか必要なんですね。 さて、.NETを勉強してこれを移植できるようにならないと・・・。
- yamahanian
- ベストアンサー率46% (7/15)
MACアドレスだけで十分だと思います。 世界中で一意です。
お礼
MACアドレスって、ソフトで変えられませんでしたっけ? ルータの設定でMacアドレスの変更ができるのはなんなのですか? 変更と言っても、ネットワーク内で重複すると整合が取れなくなるでしょうが、LAN内では同じMACアドレスが使えたりしないのでしょうか?
- rara_sun
- ベストアンサー率50% (271/539)
http://vbvbvb.com/jp/gtips/ ↓ http://vbvbvb.com/jp/gtips/0401/gRegQueryValueExProductID.html http://vbvbvb.com/jp/gtips/0251/gNetQueryDisplayInformation.html http://www.vbvbvb.com/jp/gtips/0901/gWSAAddressToString.html MACアドレスはわからなかったです。 ipconfig /all ではコマンドたたけば出るのですが・・。 >MACアドレスもNICが複数刺さっている場合のプライマリの検出方法など これは、探せなかったので、他の方におまかせ・・。 P.S. プログラマでもサンデプログラマでもないので、これで良いのかわからないのですが、興味本位で調べてみました・・。お役に立てれば・・。自分の勉強になるし・・ってプログラミングしないのに・・(笑)
お礼
VB.NETは勉強し始めたばかりなので、VB.NETでAPIを使って良いのかすらよくわかってないのですが、とりあえず、プロダクトIDの位置はわかりました。 シリアルナンバーじゃなくてプロダクトIDでしたね(汗。 ありがとうございました。
- arukamun
- ベストアンサー率35% (842/2394)
おはようございます。 uuidも一意だったと思います。 レジストリだと HKEY_LOCAL_MACHINE\SOFTWARE\Rpc\ UuidSequenceNumber だと思われます。
お礼
HKEY_LOCAL_MACHINE\SOFTWARE\にRpcがありません(汗。 UuidSequenceNumberも検索しましたがありませんでした。
- 1
- 2
お礼
やはり、MACアドレスは不変でもないし、一意でもないのですね。 でも頻繁に変わらないと思ったのですが、そうかVMとかだといつ変わるかわかりませんね・・・。 うーん、難しいです。 VMを切り捨てるか・・・。 だからかぶる可能性が少ないものを色々と組み合わせて・・・そうですね、確率論とか勉強してないんでわかりませんが、日本人口の1000分の1がこのソフトを使って、かぶる確立が数億分の1なら問題ないでしょうか。 ユーザIDとOSプロダクトIDとMACアドレス。 この3つでかなり重複確立は低くなると思うんですが、どうなんでしょう。