WPF推荐的单例应用程序二
继续丰富《WPF单例应用程序》,编写一个类似Word的应用程序,思路与上一篇一致,主要添加以下几点功能变更:
(1)自定义指定格式文件:.testDoc后缀文件;
(2)注册表中注册文件拓展名.testDoc,并且关联SingleInstanceApplication.exe程序路径,实现双击.testDoc文件自动由SingleInstanceApplication.exe打开,与wold效果类似;
主要注意2点:
//1.注册新的拓展名 .testDoc string extension = ".testDoc"; string title = "SingleInstanceApplication"; string extensionDescription = "A Test Document"; FileRegistrationHelper.SetFileAssociation( extension, title + "." + extensionDescription);
public class FileRegistrationHelper { public static void SetFileAssociation(string extension, string progID) { // Create extension subkey SetValue(Registry.ClassesRoot, extension, progID); // Create progid subkey string assemblyFullPath = System.Reflection.Assembly.GetExecutingAssembly().Location.Replace("/", @"\"); StringBuilder sbShellEntry = new StringBuilder(); sbShellEntry.AppendFormat("\"{0}\" \"%1\"", assemblyFullPath); SetValue(Registry.ClassesRoot, progID + @"\shell\open\command", sbShellEntry.ToString()); StringBuilder sbDefaultIconEntry = new StringBuilder(); sbDefaultIconEntry.AppendFormat("\"{0}\",0", assemblyFullPath); SetValue(Registry.ClassesRoot, progID + @"\DefaultIcon", sbDefaultIconEntry.ToString()); // Create application subkey SetValue(Registry.ClassesRoot, @"Applications\" + Path.GetFileName(assemblyFullPath), "", "NoOpenWith"); } private static void SetValue(RegistryKey root, string subKey, object keyValue) { SetValue(root, subKey, keyValue, null); } private static void SetValue(RegistryKey root, string subKey, object keyValue, string valueName) { bool hasSubKey = ((subKey != null) && (subKey.Length > 0)); RegistryKey key = root; try { if (hasSubKey) key = root.CreateSubKey(subKey); key.SetValue(valueName, keyValue); } finally { if (hasSubKey && (key != null)) key.Close(); } } }
2.权限问题,操作注册表需要管理员权限才可以执行
(1)通过app.manifest设置 <requestedExecutionLevel level="highestAvailable" />
<?xml version="1.0" encoding="utf-8"?> <asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <assemblyIdentity version="1.0.0.0" name="MyApplication.app" /> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> <security> <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> <requestedExecutionLevel level="highestAvailable" /> </requestedPrivileges> <applicationRequestMinimum> <defaultAssemblyRequest permissionSetReference="Custom" /> <PermissionSet Unrestricted="true" ID="Custom" SameSite="site" /> </applicationRequestMinimum> </security> </trustInfo> </asmv1:assembly>
highestAvailable按当前账号能获取到的权限执行(能拿到的最大权限),而requireAdministrator则是当前用户必须是管理员权限才能运行。
如果当前账户是管理员账户的话,那么两者都是可以的通过提升权限来获取到管理员权限执行程序;而如果当前账户是Guest的话,那么highestAvailable则放弃提升权限而直接运行,而requireAdministrator则允许输入其他管理员账户的密码来提升权限。
(2)判断系统版本及运行权限处理注册表变更
protected override bool OnStartup( Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e) { string extension = ".testDoc"; string title = "SingleInstanceApplication"; string extensionDescription = "A Test Document"; //Vista之后版本才有UAC权限 Boolean afterVista = (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6); if (afterVista) { MessageBox.Show("afterVista"); //判断当前系统运行权限是不是管理员权限 var identity = WindowsIdentity.GetCurrent(); var principal = new WindowsPrincipal(identity); if (principal.IsInRole(WindowsBuiltInRole.Administrator)) { MessageBox.Show("管理员权限运行"); // 管理员权限运行才去操作注册表 FileRegistrationHelper.SetFileAssociation( extension, title + "." + extensionDescription); } else { MessageBox.Show("普通权限运行"); } } else { //Vista之前版本没有UAC安全控制,可以直接操作注册表 FileRegistrationHelper.SetFileAssociation( extension, title + "." + extensionDescription); } app = new WpfApp(); app.Run(); return false; }

浙公网安备 33010602011771号