关于C# winform唤起本地已安装应用程序(测试win10,win7可用)

摘要:
有三种可能的方法来调用本地安装的应用程序:第一种是打开本地快捷方式,它分为本地桌面快捷方式和“开始”菜单中的快捷方式。注意:您需要在此处将winform表单更改为64位应用程序,否则打开上述路径将被Microsoft重定向到以下32位目录。

想要唤起本地已安装应用程序,我想到的有三种可行的方法:

  第一种就是打开本地的快捷方式(有的应用可能没有快捷方式,但这种方法效率最高,可配合其他方法使用),快捷方式分为本地桌面快捷方式和开始菜单中的快捷方式两种。

  下面讲找出快捷方式路径的方法:

    本地桌面快捷方式:用户可能更改过默认的桌面路径,此时以前添加的快捷方式还在默认的c盘下路径,之后创建的快捷方式则会在新的桌面路径之下。

             因此我们首先获取到当前桌面的目录地址,代码如下:

string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);   //在path后面拼上 应用的名字.lnk 就是快捷方式的路径啦

               如果未更改过桌面目录,默认的c盘路径如下:

"C:UsersPublicDesktop" + appName + ".lnk"

    开始菜单的快捷方式:(默认主要有两种,在后面拼上应用的名字.lnk 就是快捷方式的路径啦)

C:ProgramDataMicrosoftWindowsStart MenuPrograms
C:UsersAdministratorAppDataRoamingMicrosoftWindowsStart MenuPrograms

  然后把打开对应路径下的文件就可以实现打开本地快捷方式啦。

  打开的方法主要有三种:(详情可查看此篇文章https://www.cnblogs.com/y-yp/p/8782641.html),我只是用了下面这种,原因是比较简单:

System.Diagnostics.Process.Start(@"C:UsersPublicDesktop" + appName + ".lnk");

  此方法打开失败会返回异常,因此要用try{}catch{}语句把上面四种可能的快捷方式遍历一遍,并使其忽略返回的异常信息。

  当然这种方法显然不是特别的完美,可在遍历完之后,未找到应用的情况下再去注册表中查找应用程序的可执行(.exe)文件的路径,也就是第二种方法。

  第二种就是查找注册表,找出应用程序的安装路径,然后运行其中的.exe文件,如下:

    由于win10和win7注册表结构有些不同,我们首先需要判断系统的版本,然后执行不同版本的代码即可:

1 Version currentVersion = Environment.OSVersion.Version;
2 Version compareToVersion = new Version("6.2");
3 if (currentVersion.CompareTo(compareToVersion) >= 0)
4 {
5     //win8及其以上版本的系统
6 }else{
7      // win7及其以下版本的系统
8 }

    win10主要在HKEY_CURRENT_USERSOFTWAREMicrosoftWindows NTCurrentVersionAppCompatFlagsCompatibility AssistantStore下,里面直接存放的就是.exe文件的路径,代码如下:

关于C# winform唤起本地已安装应用程序(测试win10,win7可用)第1张关于C# winform唤起本地已安装应用程序(测试win10,win7可用)第2张
 1 //win8及其以上版本的系统
 2 using (RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"SOFTWAREMicrosoftWindows NTCurrentVersionAppCompatFlagsCompatibility AssistantStore"))
 3 {
 4     if (key != null)
 5     {
 6         bool isFind = false;
 7         string[] sname = key.GetValueNames();
 8         for (int i = 0; i < sname.Length; i++)
 9         {
10             if (sname[i].ToString().Substring(0, 2) == "C:" || sname[i].ToString().Substring(0, 2) == "D:" || sname[i].ToString().Substring(0, 2) == "E:" || sname[i].ToString().Substring(0, 2) == "F:" || sname[i].ToString().Substring(0, 2) == "G:" || sname[i].ToString().Substring(0, 2) == "H:")
11 
12             //查到的注册表可能有SIGN.MEDIA=2CE47846 VS2010setup.exe,E:win10Operalauncher.exe,需要判断
13             {
14                 int ss = sname[i].ToString().LastIndexOf("\");
15                 string s = sname[i].ToString().Substring(ss, sname[i].Length - ss);
16                 string sss = s.Substring(1, s.Length - 1);
17                 if (sss == appName.Text.Trim() + ".exe")
18                 {
19                     MessageBox.Show(sname[i].ToString());
20                     try
21                     {
22                         System.Diagnostics.Process.Start(@sname[i].ToString());
23                         isFind = true;
24                         break;
25                     }
26                     catch {
27                         continue;
28                     }
29                 }
30             }
31         }
32         if(!isFind){
33             MessageBox.Show("未找到应用,换个名字试试吧!");
34         }
35     }
36 }
37 }
View Code

    win7主要有三个目录,里面存放的是有应用相关命名的文件夹,内部有个 InstallLocation 字符串,其值是文件的安装路径,需再拼上  .exe文件名 + “.exe”(特例:QQ需要先进入Bin目录下):

    HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionUninstall     此为64位应用的路径。

    注意:此处需要将winform窗体改为64位应用,否则打开上述路径会被微软重定向到下面32位的目录。操作如下:

      右键项目-->属性-->生成,勾选掉首选32位。  

      关于C# winform唤起本地已安装应用程序(测试win10,win7可用)第3张

    HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftWindowsCurrentVersionUninstall     此为32位应用的路径

    HKEY_CURRENT_USERSOFTWAREMicrosoftWindowsCurrentVersionUninstall

    代码如下,把三个路径都加以实现即可:

关于C# winform唤起本地已安装应用程序(测试win10,win7可用)第4张关于C# winform唤起本地已安装应用程序(测试win10,win7可用)第5张
 1 using (RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWAREWow6432NodeMicrosoftWindowsCurrentVersionUninstall", false))
 2 {
 3     if (key != null)
 4     {
 5         //foreach (string keyName in key.GetSubKeyNames())
 6         string[] SubK = key.GetSubKeyNames();
 7         MessageBox.Show("length:" + SubK.Length);
 8         for (int i = 0; i < SubK.Length; i++)
 9         {
10             //MessageBox.Show(SubK[i]);
11             using (RegistryKey key2 = key.OpenSubKey(appName.Text.Trim(), false))
12             {
13                 if (key2 != null)
14                 {
15                     string installLocation = key2.GetValue("InstallLocation", "").ToString();
16                     if (!string.IsNullOrEmpty(installLocation))
17                     {
18                         MessageBox.Show("路径:" + installLocation);
19                         try
20                         {
21                             System.Diagnostics.Process.Start(@installLocation + "\" + win7_txt.Text.Trim());
22                             isFind2 = true;
23                             break;
24                         }
25                         catch
26                         {
27                             MessageBox.Show("别循环!");
28                         }
29                     }
30                 }
31             }
32         }
33         if (!isFind2)
34         {
35             MessageBox.Show("未找到应用,换个名字试试吧!");
36         }
37     }
38 }
View Code

    第三种方法就是使用user32.dll提供的API:FindWindowA和ShowWindow,这种方法很简单,但是这个方法只能打开已经在后台运行的应用(如果有更好的API请大佬下方留言)。

    首先在CLASS在声明API与常量: 

1 [DllImport("user32.dll", EntryPoint = "FindWindowA")]
2 private extern static IntPtr FindWindowA(string lpClassName, string lpWindowName);
3 
4 [DllImport("user32.dll", EntryPoint = "ShowWindow", CharSet = CharSet.Auto)]
5 public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
6 public const int SW_SHOWMAXIMIZED = 3;
7 public const int SW_SHOWNORMAL = 4;

    然后调用即可:

 1 IntPtr hwnd = FindWindowA("WechatMainWndForPC", null);
 2 if (hwnd != IntPtr.Zero)
 3 {
 4     MessageBox.Show("找到窗口");
 5     ShowWindow(hwnd, 3);
 6 }
 7 else
 8 {
 9     MessageBox.Show("没有找到窗口");
10 }

    其中FindWindowA需要两个参数(目标窗口类名,目标窗口标题),返回一个窗口的句柄(整数型),其中本地已打开窗口的标题(通用,一次获取后面即可通过findWindowA调用,类名获取未找到方法,还请大佬可以指导一下)可用py脚本获取:

 1 #! /usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 from win32gui import *
 4 titles = set()
 5 def foo(hwnd,mouse):
 6  #去掉下面这句就所有都输出了,但是我不需要那么多
 7  if IsWindow(hwnd) and IsWindowEnabled(hwnd) and IsWindowVisible(hwnd):
 8   titles.add(GetWindowText(hwnd))
 9 EnumWindows(foo, 0)
10 lt = [t for t in titles if t]
11 lt.sort()
12 for t in lt:
13     print(t)

   然后ShowWindow中传入FindWindowA得到的句柄和窗口的显示命令两个参数即可。

   ShowWindow第二个参数:

    SW_HIDE 隐藏窗口,活动状态给令一个窗口 
    SW_MINIMIZE 最小化窗口,活动状态给令一个窗口 
    SW_RESTORE 用原来的大小和位置显示一个窗口,同时令其进入活动状态 
    SW_SHOW 用当前的大小和位置显示一个窗口,同时令其进入活动状态 
    SW_SHOWMAXIMIZED 最大化窗口,并将其激活 
    SW_SHOWMINIMIZED 最小化窗口,并将其激活 
    SW_SHOWMINNOACTIVE 最小化一个窗口,同时不改变活动窗口 
    SW_SHOWNA 用当前的大小和位置显示一个窗口,不改变活动窗口 
    SW_SHOWNOACTIVATE 用最近的大小和位置显示一个窗口,同时不改变活动窗口 
    SW_SHOWNORMAL 与SW_RESTORE相同 

免责声明:文章转载自《关于C# winform唤起本地已安装应用程序(测试win10,win7可用)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇linux 没有yum命令,安装yum命令的方法批量裁剪GIS数据(包含GDB,MDB,Shp)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

win10下安装npm&amp;amp;cnpm步骤

1.node官网下载安装包 2.分别输入node -v,npm -v检查是否完成 3.配置npm的全局模块的存放路径以及cache的路径,新建node_global和node_cache文件,以下是我的目录文件: D:Program Files odejs ode_global D:Program Files odejs ode_cache 4.对np...

让Win10字体变得像苹果电脑那样细腻

原文:https://zhuanlan.zhihu.com/p/262156983 字体显示效果,这点用过Mac的感受最明显,windows的字体相比苹果电脑总是有一种毛刺的感觉,而mac更顺滑,因为默认情况下,windows的字体显示效果的确没有mac那么好,这不是显示器或分辨率的问题,而是windows历史遗留下来的锅 明显看出win毛刺感更强 首先搜...

C# winform DataGridView 常见属性

C# winform DataGridView 属性说明① 取得或者修改当前单元格的内容 ② 设定单元格只读 ③ 不显示最下面的新行 ④ 判断新增行 ⑤ 行的用户删除操作的自定义 ⑥ 行、列的隐藏和删除 ⑦ 禁止列或者行的Resize ⑧ 列宽和行高以及列头的高度和行头的宽度的自动调整 ⑨ 冻结列或行 ⑩ 列顺序的调整 ⑪ 行头列头的单元格⑫ 剪切板的操作...

解决win10系统与服务器远程连接明明密码正确却显示身份验证错误问题

升级至win10 最新版本10.0.17134,远程桌面连接Window Server时报错信息如下: 出现身份验证错误,要求的函数不正确,这可能是由于CredSSP加密Oracle修正。 解决方法: 运行 gpedit.msc 本地组策略: 计算机配置>管理模板>系统>凭据分配>加密Oracle修正 选择启用并选择易受攻击。...

C#winform 窗体缩放自适应

1. 首先在窗体上放上一个Panel容器,并将容器的Dock属性设为Fill,即所有的控件都放在了这个容器里。 usingSystem; usingSystem.Collections.Generic; usingSystem.Drawing; usingSystem.Text; usingSystem.Windows.Forms; namesp...

winform窗体 【打开多个窗体、窗体之间传值、打开唯一窗体】

1、打开多个窗体 2、窗体之间的传值 3打开唯一窗体 Form1中btn1按钮点击show出Form2,当Form2处于开启状态时,再次点击btn1不会继续弹出窗体,而是将焦点定位至已开启的Form2上;当Form2关闭后,再次点击btn1则会show出一个新的Form2; Form1: //创建一个全局集合,用来放置已经show出的窗体对象 L...