C#判断VC库是否安装

前言

判断VC是否安装有两种方式

  • 通过软件的GUID判断,这种方式比较准确,但需要知道程序的GUID,推荐使用。
  • 通过注册表中卸载程序的名称判断,这种方式并不太可靠。

下载地址

https://learn.microsoft.com/zh-CN/cpp/windows/latest-supported-vc-redist?view=msvc-170#visual-studio-2010-vc-100-sp1-no-longer-supported

通过GUID方式

https://learn.microsoft.com/zh-cn/windows/win32/api/msi/nf-msi-msiqueryproductstatea?redirectedfrom=MSDN

返回值

含义
INSTALLSTATE_ABSENT 已为另一用户安装该产品。
INSTALLSTATE_ADVERTISED 该产品已播发,但未安装。
INSTALLSTATE_DEFAULT 已为当前用户安装该产品。
INSTALLSTATE_INVALIDARG 向该函数传递了无效参数。
INSTALLSTATE_UNKNOWN 该产品既未播发,也未安装。

工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// ReSharper disable InconsistentNaming
// ReSharper disable once InconsistentNaming
namespace env_monitor.Utils
{
using System.Runtime.InteropServices;

public class ZvcInstallCheckUtils
{
public static bool IsInstall(string msiid)
{
return GetProcuct(msiid) == INSTALLSTATE.INSTALLSTATE_DEFAULT;
}

[DllImport("msi.dll")]
private static extern INSTALLSTATE MsiQueryProductState(string product);

private static INSTALLSTATE GetProcuct(string product)
{
INSTALLSTATE state = MsiQueryProductState(product);
return state;
}
}

public enum INSTALLSTATE
{
INSTALLSTATE_NOTUSED = -7, // component disabled
INSTALLSTATE_BADCONFIG = -6, // configuration data corrupt
INSTALLSTATE_INCOMPLETE = -5, // installation suspended or in progress
INSTALLSTATE_SOURCEABSENT = -4, // run from source, source is unavailable
INSTALLSTATE_MOREDATA = -3, // return buffer overflow
INSTALLSTATE_INVALIDARG = -2, // invalid function argument
INSTALLSTATE_UNKNOWN = -1, // unrecognized product or feature
INSTALLSTATE_BROKEN = 0, // broken
INSTALLSTATE_ADVERTISED = 1, // advertised feature
INSTALLSTATE_REMOVED = 1, // component being removed (action state, not settable)
INSTALLSTATE_ABSENT = 2, // uninstalled (or action state absent but clients remain)
INSTALLSTATE_LOCAL = 3, // installed on local drive
INSTALLSTATE_SOURCE = 4, // run from source, CD or net
INSTALLSTATE_DEFAULT = 5, // use default, local or source
}
}

调用

1
2
var installstate = ZvcInstallCheckUtils.IsInstall("{1D8E6291-B0D5-35EC-8441-6616F567A0F7}");
Console.WriteLine(installstate);

VC的GUID

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
Visual C++ 2005 Redistributable Package (x86)
{A49F249F-0C91-497F-86DF-B2585E8E76B7}

Visual C++ 2005 Redistributable Package (x64)
{6E8E85E8-CE4B-4FF5-91F7-04999C9FAE6A}

Visual C++ 2005 Redistributable Package (ia64)
{03ED71EA-F531-4927-AABD-1C31BCE8E187}

Visual C++ 2005 SP1 Redistributable Package (x86)
{7299052B-02A4-4627-81F2-1818DA5D550D}

Visual C++ 2005 SP1 Redistributable Package (x64)
{071C9B48-7C32-4621-A0AC-3F809523288F}

Visual C++ 2005 SP1 Redistributable Package (ia64)
{0F8FB34E-675E-42ED-850B-29D98C2ECE08}

Visual C++ 2008 Redistributable Package (x86)
{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}

Visual C++ 2008 Redistributable Package (x64)
{350AA351-21FA-3270-8B7A-835434E766AD}

Visual C++ 2008 Redistributable Package (ia64)
{2B547B43-DB50-3139-9EBE-37D419E0F5FA}

Visual C++ 2008 SP1 Redistributable Package (x86)
{9A25302D-30C0-39D9-BD6F-21E6EC160475}

Visual C++ 2008 SP1 Redistributable Package (x86 9.0.30729.6161)
{9BE518E6-ECC6-35A9-88E4-87755C07200F}

Visual C++ 2008 SP1 Redistributable Package (x64)
{8220EEFE-38CD-377E-8595-13398D740ACE}

Visual C++ 2008 SP1 Redistributable Package (ia64)
{5827ECE1-AEB0-328E-B813-6FC68622C1F9}

Visual C++ 2010 Redistributable Package (x86)
{196BB40D-1578-3D01-B289-BEFC77A11A1E}

Visual C++ 2010 Redistributable Package (x64)
{DA5E371C-6333-3D8A-93A4-6FD5B20BCC6E}

Visual C++ 2010 Redistributable Package (ia64)
{C1A35166-4301-38E9-BA67-02823AD72A1B}

Visual C++ 2010 SP1 Redistributable Package (x86 10.0.40219)
{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}

Visual C++ 2010 SP1 Redistributable Package (x64)
{1D8E6291-B0D5-35EC-8441-6616F567A0F7}

Visual C++ 2010 SP1 Redistributable Package (ia64)
{88C73C1C-2DE5-3B01-AFB8-B46EF4AB41CD}

Visual C++ 2013 Redistributable Package (x86 12.0.21005)
{13A4EE12-23EA-3371-91EE-EFB36DDFFF3E} and {F8CFEB22-A2E7-3971-9EDA-4B11EDEFC185}

Visual C++ 2013 Redistributable Package (x64)
{929FBD26-9020-399B-9A7A-751D61F0B942} and {A749D8E6-B613-3BE3-8F5F-045C84EBA29B}

通过注册表方式

这种方式并不能准确找到,测试的时候我查找2010 x86可以找到,但是2010 x64的却找不到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
namespace env_monitor.Utils
{
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Win32;

public class ZvcInstallCheckByRegUtils
{
public static bool IsInstallVc(string[] keywords)
{
List<string> lists = new List<string>();
RegistryKey key = Registry.LocalMachine;
GetRegistry(
key,
@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall",
ref lists
);
if (lists.Count > 0)
{
string vcName = null;
foreach (var s1 in lists.Where(x => keywords.All(x.Contains)))
{
vcName = s1;
break;
}
Console.WriteLine(vcName);
return !string.IsNullOrEmpty(vcName);
}
return false;
}

private static void GetRegistry
(
RegistryKey keyR,
string str,
ref List<string> list
)
{
RegistryKey aimdir = keyR.OpenSubKey(str);
if (aimdir != null)
{
var subvalueNames = aimdir.GetValueNames();
foreach (string valueName in subvalueNames)
{
if (valueName.ToLower().Equals("displayname") || valueName.ToLower().Equals("productname"))
{
if (aimdir.GetValue(valueName) != null && aimdir.GetValue(valueName).ToString().ToLower().Contains("microsoft visual c++"))
{
list.Add(aimdir.GetValue(valueName).ToString());
}
}
}
var subkeyNames = aimdir.GetSubKeyNames();
foreach (string keyName in subkeyNames)
{
GetRegistry(
aimdir,
keyName,
ref list
);
}
}
}
}
}

注意这里之所以使用数组来过滤是因为微软的名称命名也太不规范了。

比如"Microsoft Visual C++ 2010 x86 Redistributable - 10.0.40219",2010和x86之间竟然是2个空格,所以使用数组来判断,不但包含2010,而且包含x86才算匹配上。

测试

1
2
3
4
5
6
7
8
var isInstall = ZvcInstallCheckByRegUtils.IsInstallVc(
new[]
{
"2010",
"x86"
}
);
Console.WriteLine(isInstall);