C# 什么是好的唯一PC标识符?

C# 什么是好的唯一PC标识符?,c#,.net,guid,C#,.net,Guid,我一直在查看中的代码,发现它使用My.Computer.Name保存不应在计算机之间漫游的设置。但是,一个用户完全有可能拥有两台名称相同的电脑。例如,如果他们想在每台电脑上拥有相同的用户名,他们很可能最终拥有两台名为username-PC的电脑 识别不同PC的好方法有哪些?PC机是否有与之相关的GUI,或者我是否应该研究从某些硬件上提取序列号?我不在乎重新安装Windows后标识是否仍然存在 (我链接的教程在VB.Net中,但我正在用C#实现它)我认为在同一个域中不可能有两台同名的PC。您尝试过

我一直在查看中的代码,发现它使用
My.Computer.Name
保存不应在计算机之间漫游的设置。但是,一个用户完全有可能拥有两台名称相同的电脑。例如,如果他们想在每台电脑上拥有相同的用户名,他们很可能最终拥有两台名为username-PC的电脑

识别不同PC的好方法有哪些?PC机是否有与之相关的GUI,或者我是否应该研究从某些硬件上提取序列号?我不在乎重新安装Windows后标识是否仍然存在


(我链接的教程在VB.Net中,但我正在用C#实现它)

我认为在同一个域中不可能有两台同名的PC。您尝试过捕获域名吗?

请看这里:


您可以从注册表中获取一些唯一的数据。

每台计算机都有一个在正常情况下唯一的SID。

您可以使用的一件事是任何网络接口的MAC。您还可以组合多个信息源。如HDD序列号、mac、处理器类型,从中计算哈希值。

一些好的标识符:

  • MAC地址:很容易找到,而且通常是唯一的。但是,它很容易被欺骗/更改,因此这取决于它需要有多独特
  • CPU序列号:它在许多旧系统上不可用,但它在那里。退房它不会改变,但它绑定到一台计算机上
  • 硬盘序列号:可能不会更改,但如果硬盘出现故障,可能会造成麻烦。退房

如果您使用的是windows
HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft\windows NT\CurrentVersion\ProductId
,则每台计算机/每台windows安装都是唯一的。其中,与其他一些答案一样,MAC地址、Proc SN和HD SN在windows重新安装/双引导情况下保持不变。

使用网卡的MAC地址。它应该是独一无二的。不过,这是可以改变的。这取决于用户的恶意程度以及应用程序的关键程度

一些用于执行此操作的示例代码:

public string GetMACAddress() {
    ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
    ManagementObjectCollection moc = mc.GetInstances();

    string MACAddress = String.Empty;

    foreach (ManagementObject mo in moc) {
        if (MACAddress == String.Empty) { // only return MAC Address from first card
            if ((bool)mo["IPEnabled"] == true) MACAddress = mo["MacAddress"].ToString();
        }
        mo.Dispose();
    }

    return MACAddress;
}

这个问题的真正答案是:没有这样的事情

有几种“足够接近”的解决方案,但每一种都有自己的局限性

所有硬件ID-硬件更改。而且,在许多情况下,您可以更改这些标识符(例如,MAC欺骗)

正如我已经评论过的,SID也不是很好,因为如果计算机是从映像安装的,SID不会改变。SID是由windows安装生成的,如果未安装windows,而是从映像复制的,则SID不会更改(尽管由于-您不能指望这一点,因此通常会重新生成SID)

计算机名——正如前面提到的,它们应该是唯一的,但并没有以任何方式强制执行

您可以实现的另一个解决方案是生成您自己的唯一标识符并将其存储在本地(假设您可以这样做)。同样,如果您的计算机与应用程序一起成像,此解决方案将无法工作

对你来说,最好的解决方案实际上取决于你想要完成什么。 我在一个相当大的网络上也遇到了同样的问题,最好的解决方案就是计算机的名称。
如果您完全确定您的进程不会被映像,我将使用Guid生成一个唯一标识符,因为它可能是最安全的。

以下是唯一标识计算机的方法。 使用System.Management获取Win32_BIOS,您可以从计算机的BIOS获取唯一值

请参阅:Win32_BIOS类

使用类似的逻辑,您还可以单步执行“Win32_DiskDrive”; ; 并获取每个物理驱动器的“SerialNumber”。在这种情况下

    foreach (ManagementObject item in searcher.Get())

应查找多个项目

采用三个半唯一和半恒定的标识符。使用三分之二就足以确定身份的规则。更新偶尔出错的三分之一的注册数据

此链接中有一个示例代码,其中包含获取CPU和HD驱动器ID的完整注释:

将此dll添加到引用中

 System.Management.dll
对于CPU ID:

string cpuInfo = string.Empty;
ManagementClass mc = new ManagementClass("win32_processor");
ManagementObjectCollection moc = mc.GetInstances();

foreach (ManagementObject mo in moc)
{
     if (cpuInfo == "")
     {
          //Get only the first CPU's ID
          cpuInfo = mo.Properties["processorID"].Value.ToString();
          break;
     }
}
return cpuInfo;
对于硬盘驱动器ID(卷序列号):


在托管网络环境中,最好、最可靠的标识符可能是您创建的标识符,但也有一些缺点

一些(许多?)制造商提供了一个实用程序,允许您设置存储在固件中的资产标签。这可能是一个可引导的实用程序,也可能在Windows中运行,甚至可能内置在固件设置中。这个“标签”是一个任意的文本字符串,您可以设置为任何您想要的,然后使用和

string[]selectedProperties=newstring[]{“SMBIOSAssetTag”};
ObjectQuery封闭查询=新建SelectQuery(“Win32\u SystemEnclosure”,null,selectedProperties);
使用(ManagementObjectSearcher enclosureSearcher=新的ManagementObjectSearcher(enclosureQuery))
使用(ManagementObjectCollection-enclosureCollection=enclosureSearcher.Get())
{
foreach(enclosureCollection中的ManagementObject存储模块)
{
string assetTag=(string)enclosure.GetPropertyValue(“SMBIOSAssetTag”);
}
}
优点:

  • 您可以使用您想要的任何方案(例如合并日期、部门、递增整数、GUID等)
  • 您可以对所有机器使用一个方案,而不必处理特定于制造商的方案,而不考虑其制造商
  • 通过自己分配和跟踪标识符,您可以保证它们是唯一的。不依赖制造商设置的标识符意味着在制造商内部或制造商之间不存在重复的风险
  • 标识符存储在固件中,而不是硬盘上,因此它可以经受重新格式化、升级等操作,但也不会通过备份/成像/克隆进行复制。
  • string cpuInfo = string.Empty; ManagementClass mc = new ManagementClass("win32_processor"); ManagementObjectCollection moc = mc.GetInstances(); foreach (ManagementObject mo in moc) { if (cpuInfo == "") { //Get only the first CPU's ID cpuInfo = mo.Properties["processorID"].Value.ToString(); break; } } return cpuInfo;
    ManagementObject dsk = new ManagementObject(@"win32_logicaldisk.deviceid=""" + drive + @":""");
    dsk.Get();
    string volumeSerial = dsk["VolumeSerialNumber"].ToString();
    
    ManagementObjectCollection mbsList = null;
    ManagementObjectSearcher mos = new ManagementObjectSearcher("Select ProcessorID From Win32_processor");
    mbsList = mos.Get();
    string processorId = string.Empty;
    foreach (ManagementBaseObject mo in mbsList)
    {
        processorId = mo["ProcessorID"] as string;
    }
    
    mos = new ManagementObjectSearcher("SELECT UUID FROM Win32_ComputerSystemProduct");
    mbsList = mos.Get();
    string systemId = string.Empty;
    foreach (ManagementBaseObject mo in mbsList)
    {
        systemId = mo["UUID"] as string;
    }
    
    var compIdStr = $"{processorId}{systemId}";