环境:只适用于PC
一:遇到的坑
Unity 提供了给我一套获取硬件信息的API 链接 蛮牛上的一篇帖子:链接
文中都提到了一个获取设备的唯一标识符
但是我可以明确告诉你 这个值会改变(过一段时间就会变 就是被他坑了)
查看api文档
是根据主板序列号.BIOS序列号.cpu信息.硬盘序列号.操作系统信息 来进行加密或者其他算法得出的,也许是某个东西会随着时间而改变 导致整个获取的标识符是会改变的(行不通 GG)
二:第二种方法还是坑
既然不能通过SystemInfo来获取标识符 那么就想着能不能用C#相关api来获取,为此就找到一篇帖子:链接
然后在Unity风风火火的Copy代码。。。。BUT~居然获取不了 我真b了狗,起初我以为是我添加引入System.Management不对,
因为添加的是unity下面的,以为是unity进行阉割了所以不能获取
然后又在操作系统文件夹找的整个dll,最后发现还是不对,报错显示
猜想可能是mono虚拟机不支持,咋办呢?
三:解决方案
首先声明整个解决方案有点不太爽。。。。
虽然unity不能 但是我们能用c#来获取 于是乎 我就写了一个控制台程序 把获取cpu序列号什么的都写进去,然后发现成功了
(再次证实unity mono不能获取)
ojxk,然后我将获取的写入到了一个文本,如下代码:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("start getserialnumber!!!");
//保存到当前路径
File.WriteAllText("pwd.txt", GetCpuID()+ GetDiskID());
Console.WriteLine("write end!!!");
Console.WriteLine(".......");
Console.WriteLine(".......");
}
/// <summary>
/// 获取cpu硬件信息
/// </summary>
/// <returns></returns>
private static string GetCpuID()
{
try
{
string cpuInfo = "";//cpu序列号
ManagementClass mc = new ManagementClass("Win32_Processor");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
cpuInfo = mo.Properties["ProcessorId"].Value.ToString();
}
moc = null;
mc = null;
return cpuInfo;
}
catch
{
return "unknow";
}
finally
{
}
}
/// <summary>
/// 获取硬盘ID
/// </summary>
/// <returns></returns>
private static string GetDiskID()
{
try
{
String HDid = "";
ManagementClass mc = new ManagementClass("Win32_DiskDrive");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
HDid = (string)mo.Properties["Model"].Value;
}
moc = null;
mc = null;
return HDid;
}
catch
{
return "unknow";
}
finally
{
}
}
}
然后将这个控制台程序编译的exe取出来
接着将整个exe放到unity的StreamingAsstens文件夹中
想到的思路是在Unity启动的时候 运行整个控制台程序 然后读取生成的txt里面的内容当作唯一标识符
(这里说明一下出现的问题 本来我是把那个控制台程序放在StreamingAsstes文件夹下面 想的是运行那个程序 能直接在StreamingAssets下面生产一个txt文件 结果发现不行 试了好几种路径 最后发现都会生产在发布后的exe同级文件夹路径下面)
代码:
using UnityEngine;
using sysDia = System.Diagnostics;
void Start()
{
string id = PlayerPrefs.GetString("xxxxx");
if (string.IsNullOrEmpty(id))
{
Debug.Log("PlayerPrefs没有id,启动GetSerialNumber程序");
sysDia.Process.Start(Application.streamingAssetsPath + "/GetSerialNumber.exe");
StartCoroutine(IEConfigPwd());
return;
}
else
{
}
}
private IEnumerator IEConfigPwd()
{
string pwdPath = "pwd.txt";
Debug.Log("检测正在获取写入");
//当有这个文档的时候
yield return new WaitUntil(() => File.Exists(pwdPath));
Debug.Log("写入成功");
Debug.Log("开始读取");
string pwdstr = File.ReadAllText(pwdPath);
bool havaID=false;
//这里自己做验证
//。。。。。
//。。。。。
if (haveID)
{
PlayerPrefs.SetString("xxxxx", pwdstr);
Debug.Log("获取成功!!!!!");
File.Delete(pwdPath);
}
else
{
Debug.Log("设备类型不一致!!!!!");
QuitExe();
}
}
大概思路就是这样了 我在这里写进了注册表 方便下一次启动的时候我可以直接从注册表获取整个值 就不用再次启动那个控制台程序了,如果有其他的好方法记得告诉我 我也是技术有限才这样搞~