項目 - 屬性 - 安全性,“使用ClickOnce”,修改app.mainfest,再取消“使用ClickOnce”
在XP/2003下調試得好好的程式,到了windows7下,卻抛出“不允許所請求的系統資料庫通路權”的異常,該異常就在讀寫系統資料庫時引發,例:
<a href="http://blog.csdn.net/wonsoft/article/details/6598407#">view plain</a>
public class Program
{
public static void SetAutoRun(string keyName, string filePath)
{
using (RegistryKey runKey = Registry.LocalMachine.OpenSubKey(@"software\microsoft\windows\currentversion\run", true))
{
runKey.SetValue(keyName, filePath);
runKey.Close();
}
}
static void Main()
string keyName = "TestAutoRun";
string fliePath = @"D:\CSharpProject\CSharp_Learn\MyDelegate.exe";
SetAutoRun(keyName, fliePath);
}
}
該程式如在windows 7下運作,需以管理者權限運作。
【方法一】
代碼通路安全性政策必須向使用 Microsoft.Win32.Registry 類通路系統資料庫的代碼授予 RegistryPermission。這個權限類型可以用于限制對特定系統資料庫項和子系統資料庫項的系統資料庫通路,還可以控制代碼讀取、寫入或建立系統資料庫項和已命名的值的能力。
要限制代碼對特定系統資料庫項的通路,可以使用帶 SecurityAction.PermitOnly 的 RegistryPermissionAttribute。下面的屬性確定代碼僅可以讀 HKEY_LOCAL_MACHINE\SOFTWARE 下面的 YourApp 系統資料庫項(及子項)。
要記錄代碼的權限要求,并確定在代碼通路安全性政策沒有授予它充分的系統資料庫通路權限時程式集無法加載,應當添加帶 SecurityAction.RequestMinimum 的程式集級 RegistryPermissionAttribute,如下面的示例所示。
【方法二】
添加 應用程式清單檔案,在其中加入
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC 清單選項
如果希望更改 Windows 使用者帳戶控制級别,請用以下節點之一替換
requestedExecutionLevel 節點。
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
如果您希望利用檔案和系統資料庫虛拟化提供
向後相容性,請删除 requestedExecutionLevel 節點。
-->
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
修改代碼,如下:
System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
System.Security.Principal.WindowsPrincipal principal = new System.Security.Principal.WindowsPrincipal( identity );
if(principal.IsInRole( System.Security.Principal.WindowsBuiltInRole.Administrator ))
{
// 修改系統資料庫
else
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = System.Windows.Forms.Application.ExecutablePath; // 擷取目前可執行檔案的路徑及檔案名
//以下 Args 為啟動本程式的對應的參數
startInfo.Arguments = String.Join( " ", Args );
startInfo.Verb = "runas";
System.Diagnostics.Process.Start( startInfo );
問題描述:
為了實作程式的自動啟動,我們會再系統資料庫中寫入相關資訊,實作代碼如下:
RegistryKey HKLM = Registry.LocalMachine;
RegistryKey Run = HKLM.CreateSubKey(@"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\");
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5SZsRGZp1mYfN3X0xWdhZWZk9CXzV2Zh1Wavw1M29CXsBXb09CXn9Gbi9CXuNmLt92YuEmbpNnLyU2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
但總提示如上圖的錯誤,困擾了我很久。編譯後的的exe以管理者身份運作沒有問題,為什麼呢?難道VS在調試的是沒有管理者身份(實際也沒有必要),百思不得其解。。。終于發現在win7用vs通路系統資料庫鍵HKEY_LOCAL_MACHINE沒有管理者身份是不行,但通路HKEY_CURRENT_USER可以,是以上面的代碼修改為:
RegistryKey HKLM = Registry.CurrentUser;
現在OK了。
參考:《Windows 7軟體開發示例:UAC、系統版本、權限》
嫁給Win7的必要條件
我們必須要給軟體添加的是系統版本檢測和安裝路徑選擇元素,為什麼要考慮它們呢?
必要條件1:檢測系統版本
必要條件2:适應使用者權限
Win7預設運作的是非管理者賬号,權限相對較小。而軟體的安裝程式會往包括系統盤的Program Files、Windows安裝目錄、系統資料庫中寫入一些資料(軟體在運作時可能會将一些使用者資料儲存到系統檔案夾或系統資料庫中),如果目前使用者的權限不夠,軟體就無法正常入駐Win7。
例如資料看似儲存成功,在寫入的地點卻找不到,或者登出切換到另一個Windows使用者時,無法找到儲存的資料。引起這類問題的根源是Win7的UAC機制,它降低了Windows使用者的預設權限,使得一些普通操作無法更改系統設定及系統保護的檔案夾。
小提示:軟體要結合系統某些功能時,需要調用相應的API。API調用得當否,對軟體運作非常關鍵,我們從下期開始結合Win7酷炫功能,單獨介紹如何正确的調用。Win7最新的API,有Win7特有的工作列個性化快捷菜單(Jump List)、程式圖示輪廓效果(Icon Overlay)、程式圖示進度條效果(Progress Bar)、标簽式縮略圖(Tabbed Thumbnail)和縮略圖工具欄(Thumbnail Toolbar)……
“婚禮”必要的元素
我們的軟體要順利嫁給Win7,在軟體中要添加以下的元素。
1.代碼檢測作業系統版本号
在軟體中添加判斷作業系統是Win7 或2008 Server的代碼:
C#
2.盡量将資料存儲在非系統盤
軟體不要預設安裝到系統盤,在編寫軟體安裝路徑時,要考慮這個。此外,還需要在軟體中添加修改讀寫系統資料庫的代碼,使用HKEY_CURRENT_USER\Software下的鍵值作為存儲資料的結點:
3.提高程式的運作權限
如果使用者使用了管理者身份進入系統,又希望把軟體安裝在系統盤,又該如何呢?需要判斷使用者權限的權限,簡單的解決方案是添加清單檔案。在可執行檔案夾中找到與可執行檔案相同名字且擴充名.manifest的檔案,輸入以下代碼即可: