Unity 获取唯一标识符的问题解决方案

环境:只适用于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();
        }

    }


大概思路就是这样了 我在这里写进了注册表 方便下一次启动的时候我可以直接从注册表获取整个值 就不用再次启动那个控制台程序了,如果有其他的好方法记得告诉我 我也是技术有限才这样搞~

猜你喜欢

转载自blog.csdn.net/K20132014/article/details/79977444