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;
        }

 

源码

posted @ 2021-08-04 17:04  _MrZhu  阅读(79)  评论(0)    收藏  举报