Unity中對注冊表進行修改


問題背景:

PC端軟件開發,當我在Unity中的PlayerSetting中設置好分辨率,每次打包運行后會記憶上次退出時窗口的分辨率(記憶窗口狀態),導致下次打開時不是PlayerSetting中的初始設置,而是讀取注冊表記錄的數據。而我的需求時必須每次進去時都是指定的那個分辨率。

問題糾結點:

1.注冊表信息是否可刪,怎么獲取到刪除

2.也不能直接刪除整個項目的注冊表信息,因為有些數據我們必須記錄,所以必須找到具體的KEY.

解決方案:

在軟件退出時我們清除注冊表中分辨率的指定KEY。

具體過程:

1.查找操作目標:

我們的應用程序記錄在: 注冊表 ”計算機“ 中的HKEY_CURRENT_USER\Software中,是這樣的結構:

HKEY_CURRENT_USER\Software\Company Name\Product Name

通過查找,最后確定在這四項與Screen有關系。我們目標已經找到了,就是操作這四項。

2.獲取到該四項,退出時刪除該四項。

 1  //注冊表中屏幕相關Key
 2         private readonly string regeditScreenFullscreenModeKey = "Screenmanager Fullscreen mode_h3630240806";
 3         private readonly string regeditScreenResolutionHeightKey = "Screenmanager Resolution Height_h2627697771";
 4         private readonly string regeditScreenResolutionUseNativeKey = "Screenmanager Resolution Use Native_h1405027254";
 5         private readonly string regeditScreenResolutionWidthKey = "Screenmanager Resolution Width_h182942802";
 6 
 7     //注冊表當前工程項
 8         private StringBuilder regeditPathNode = new StringBuilder();
 9 
10         /// <summary>
11         /// 初始化
12         /// </summary>
13         public void OnSingletonInit()
14         {
15             regeditPathNode = regeditPathNode.Append("Software\\").Append(Application.companyName).Append("\\").Append(Application.productName);
16         }
17 
18  //清空注冊表數據
19             if (Utils.IsJudgeNode(regeditPathNode.ToString()))
20             {
21                 if (Utils.IsJudgeNodeKey(regeditPathNode.ToString(), regeditScreenFullscreenModeKey))
22                 {
23                     Utils.DeleteNodeKey(regeditPathNode.ToString(), regeditScreenFullscreenModeKey);
24                 }
25                 if (Utils.IsJudgeNodeKey(regeditPathNode.ToString(), regeditScreenResolutionHeightKey))
26                 {
27                     Utils.DeleteNodeKey(regeditPathNode.ToString(), regeditScreenResolutionHeightKey);
28                 }
29                 if (Utils.IsJudgeNodeKey(regeditPathNode.ToString(), regeditScreenResolutionUseNativeKey))
30                 {
31                     Utils.DeleteNodeKey(regeditPathNode.ToString(), regeditScreenResolutionUseNativeKey);
32                 }
33                 if (Utils.IsJudgeNodeKey(regeditPathNode.ToString(), regeditScreenResolutionWidthKey))
34                 {
35                     Utils.DeleteNodeKey(regeditPathNode.ToString(), regeditScreenResolutionWidthKey);
36                 }
37             }

       using Microsoft.Win32;
       using System.Collections.Generic;
       using UnityEngine;

/// <summary>
 2     /// 工具類
 3     /// </summary>
 4     public class Utils
 5     {
 6         #region 公有方法
 7 
 8         /// <summary>
 9         /// 判斷注冊信息節點是否存在
10         /// </summary>
11         /// <param name="key">"SOFTWARE\\Microsoft"格式</param>
12         /// <returns></returns>
13         public static bool IsJudgeNode(string key)
14         {
15             return (Registry.CurrentUser.OpenSubKey(key) != null);
16         }
17 
18         /// <summary>
19         /// 判斷注冊表節點內是否有某個KEY
20         /// </summary>
21         /// <param name="key">"SOFTWARE\\Microsoft"格式</param>
22         /// <param name="prop">傳入屬性的鍵值</param>
23         /// <returns></returns>
24         public static bool IsJudgeNodeKey(string key, string prop)
25         {
26             RegistryKey rsg = Registry.CurrentUser.OpenSubKey(key, true);
27             if (rsg != null)
28             {
29                 var obj = rsg.GetValue(prop);
30                 if (obj != null)
31                 {
32                     return true;
33                 }
34             }
35             return false;
36         }
37 
38         /// <summary>
39         /// 刪除指定節點指定鍵值
40         /// </summary>
41         /// <param name="key"></param>
42         /// <param name="prop"></param>
43         public static void DeleteNodeKey(string key, string prop)
44         {
45             RegistryKey rKey = Registry.CurrentUser;
46             RegistryKey software = rKey.OpenSubKey(key, true);
47             //刪除
48             software.DeleteValue(prop);
49             //完成讀取和修改數據后,應關閉該鍵
50             software.Close();
51         }
52 
53         #endregion
54     }

這個地方使用Registry和 RegistryKey類,這兩個類在 using Microsoft.Win32(命名空間提供兩種類型的類:處理由操作系統引發的事件的類和操作系統注冊表的類。)下,RegistryKey類可以用於完成對注冊表的所有操作,Registry是不能實例化的一個類。它的作用只是提供表示頂級鍵的RegistryKey實例,以便開始在注冊表中瀏覽。Registry是通過靜態屬性來提供這些實例的,這些屬性共有7個,分別是ClassesRoot、CurrentConfig、CurrentUser、DynData、LocalMachine、PerformanceData和 Users。

如何在注冊表的給定位置上打開一個注冊表項?Registry類沒有用戶可以使用的公共構造函數,也沒有任何可以直接通過鍵的名稱來訪問鍵的方法。但可以在相關的巢中從上至下瀏覽該鍵。如果要實例化一個RegistryKey對象,惟一的方式是從Registry的靜態屬性開始,向下瀏覽。例如,要讀取HKLM/Software/Microsoft鍵中的一些數據,可以使用下面的代碼獲得它的一個引用:

1 RegistryKey hklm = Registry.LocalMachine;
2 RegistryKey hkSoftware = hklm.OpenSubKey("Software");
3 RegistryKey hkMicrosoft = hkSoftware.OpenSubKey("Microsoft");
View Code

以上述方式訪問注冊表項是只讀訪問。如果要寫入該鍵(包括寫入其值,或創建和刪除其子鍵),就需要使用OpenSubKey的另一個重寫方法,該方法的第二個參數是bool類型,表示是否要對該鍵進行讀寫訪問。例如,如果要修改Microsoft鍵(並假定用戶是一個系統管理員,有修改該鍵的許可),就應編寫如下代碼:

1 RegistryKey hklm = Registry.LocalMachine;
2 RegistryKey hkSoftware = hklm.OpenSubKey("Software");
3 RegistryKey hkMicrosoft = hkSoftware.OpenSubKey("Microsoft", true);
4 
5 
6 //創建Key
7 RegistryKey hkMine = hkSoftware.CreateSubKey("MyOwnSoftware");

CreateSubKey()工作的方式:如果鍵不存在,它就創建這個鍵。但如果鍵已經存在,它就會返回一個表示該鍵的RegistryKey實例。這個方法采用這樣的工作方式的原因是用戶總是可以使用這個鍵。注冊表包含長期數據,例如Windows和各種應用程序的配置信息。因此用戶並不需要經常顯式地創建鍵。

更常見的是,應用程序需要確保某些數據在注冊表中是存在的。換言之,如果這些數據不存在,就要創建相關的鍵,但如果它們存在,就不需要做任何事。CreateSubKey()就可以完成這項任務。CreateSubKey()不會刪除任何數據。如果要刪除注冊表項,就需要顯式調用RegistryKey.Delete()方法,因此注冊表對於Windows是非常重要的。如果刪除了一些重要的鍵,就會中斷Windows的執行,此時就需要調試C#注冊表調用了

定位了要讀取或修改的注冊表項后,就可以使用SetValue() 或 GetValue()方法設置或獲取該鍵中的值。這兩個方法的參數都是一個字符串,其中字符串給出了值的名稱,SetValue()還需要一個包含值的信息的對象引用。這個參數定義為對象引用,實際上可以是任何一個類的引用。SetValue()根據所提供的類的類型,確定把值設置為REG_SZ、REG_DWORD,還是 REG_BINARY。例如:

1 RegistryKey hkMine = HkSoftware.CreateSubKey("MyOwnSoftware");
2 hkMine.SetValue("MyStringValue", "Hello World");
3 hkMine.SetValue("MyIntValue", 20);

這段代碼設置鍵包含兩個值:MyStringValue的類型是REG_SZ,而MyIntValue的類型是REG_DWORD,這里只考慮這兩種類型,在后面的示例中會使用它們。

RegistryKey.GetValue()的工作方式也是這樣。它返回一個對象引用,如果該方法檢測到值的類型為REG_SZ,就返回一個字符串引用,如果值的類型為REG_DWORD,就返回一個int型值。

但是注意:Unity中寫using Microsoft.Win32空間后,如果提示Win32API不存在。

解決方案:

1.右擊資源管理器窗口中項目的引用文件夾,選擇添加引用,選擇.Net選項卡

2.新建VS文件,以DLL庫的形式使用。

我這就是使用的dll庫形式引用的。到這就解決了上述問題。

 

ok,歡迎交流指正。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM