获取windows已安装程序

c++

Posted by YiMiTuMi on November 3, 2022

获取windows已安装程序

主要是从注册表中获取。根据系统位数不同有两个路径。

32位系统:

HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall

64位系统:

HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall

控制面板中的卸载程序显示的是能卸载、更改和修复的,而设置–应用与功能中显示的是除系统安装之外的软件。

程序 SoftWareInfo.cpp:

#include 头文件自己找一下

WINBASEAPI
BOOL
WINAPI
Wow64DisableWow64FsRedirection (__out PVOID *OldValue);

WINBASEAPI
BOOL
WINAPI
Wow64RevertWow64FsRedirection ( __in PVOID OlValue);

//保存数据结构体
class CSoftInfo
{
public:
	wchar_t strDisplayName[EFFSOFT_MAX_PATH];
	wchar_t strDisplayVersion[EFFSOFT_MAX_PATH];
	wchar_t strPublisher[EFFSOFT_MAX_PATH];
	wchar_t strInstallLocation[EFFSOFT_MAX_PATH];
	wchar_t strInstallDate[18];
	CSoftInfo()
	{
		memset(this,0, sizeof(*this));
	}
};


//判断系统是否是64位
BOOL Is64BitOs()
{
	static BOOL isWow64 = FALSE;
	static BOOL valid = FALSE;
	typedef BOOL (__stdcall *LPFN_ISWOW64PROCESS ) (HANDLE hProcess,PBOOL Wow64Process);
	LPFN_ISWOW64PROCESS fnIsWow64Process;
#ifdef _WIN64
	return TRUE;
#endif
	if (valid)
		return isWow64;

	fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandleA("kernel32"), "IsWow64Process");

	if (fnIsWow64Process != NULL)
		if (!fnIsWow64Process (GetCurrentProcess(), &isWow64))
			isWow64 = FALSE;

	valid = TRUE;
	return isWow64;
}

//遍历软件
BOOL GetAllInstallSoftware(list<CSoftInfo> &softset, HKEY hKeyRoot, TCHAR* m_SubKey, DWORD dwAccess)
{
	HKEY m_key,m_key2; 

	TCHAR m_name[200],m_displayname[200],szVersion[200],uninstall[200],szPublisher[200],szLocation[200],szUninstallString[200];
	TCHAR szInstallDate[18]={0};
	DWORD m_namelen=200,m_displaynamelen=200, szVersionlen=200, iPublisherLen, iLocation, iIntalldateLen, iUninstallString; 
	DWORD m_attr=REG_BINARY|REG_DWORD|REG_EXPAND_SZ|REG_MULTI_SZ|REG_NONE|REG_SZ; 
		

	if (RegOpenKeyEx(hKeyRoot,m_SubKey,0,dwAccess,&m_key) !=ERROR_SUCCESS) 
	{
		return FALSE;
	}  


	int m_index =0;
	while (RegEnumKeyEx(m_key,m_index,m_name,&m_namelen,0,NULL,NULL,0)!=ERROR_NO_MORE_ITEMS) 
	{ 
	
		if (wcscmp(m_name,_T("")) != 0)
		{ 
			//如果找到了,分别在枚举下面有没有DISPLAYNAME,以便得到软件名称 
			wcscpy(uninstall,m_SubKey); 
			wcscat(uninstall,L"\\"); 
			wcscat(uninstall,m_name); // 连接到下一层 

			m_displaynamelen=sizeof(m_displayname); 
			memset(m_displayname,0,sizeof(m_displayname)); 

			szVersionlen=sizeof(szVersion);// 
			memset(szVersion,0,sizeof(szVersion));

			iPublisherLen = sizeof(szPublisher);
			memset(szPublisher,0,sizeof(szPublisher));

			iLocation = sizeof(szLocation);
			memset(szLocation, 0, sizeof(szLocation));

			iIntalldateLen = sizeof(szInstallDate);
			memset(szInstallDate, 0, sizeof(szInstallDate));

			iUninstallString = sizeof(szUninstallString);
			memset(szUninstallString, 0, sizeof(szUninstallString));
			

			//再打开,查找软件显示现实名称和卸载命令行 
			if (RegOpenKeyEx(hKeyRoot,uninstall,0,dwAccess,&m_key2)==ERROR_SUCCESS) 
			{ 
				
				if (FALSE) 
				{
					//显示全部安装软件
				}
				else if (TRUE)
				{
					//显示用户安装软件--设置--应用与功能显示的

					//排除系统软件
					DWORD dwSystemComponent = 0;
					DWORD dwReSystemComponent = REG_DWORD;
					RegQueryValueEx(m_key2,L"SystemComponent", 0, &m_attr, LPBYTE(&dwSystemComponent), &dwReSystemComponent); //系统组件

					DWORD dwWindowsInstaller = 0;
					DWORD dwReWindowsInstaller = REG_DWORD;
					RegQueryValueEx(m_key2,L"WindowsInstaller", 0, &m_attr, LPBYTE(&dwWindowsInstaller), &dwReWindowsInstaller); //系统安装

					if ((dwSystemComponent == 1) && (dwWindowsInstaller == 1))
					{
						RegCloseKey(m_key2);
						m_namelen=sizeof(m_name); 
						memset(m_name,0,m_namelen); 
						m_index++;
						continue;
					}
				}
				else if (FALSE)
				{
					//显示允许卸载、移动、修改的软件 -- 控制面板卸载软件显示的

					DWORD dwSystemComponent = 0;
					DWORD dwReSystemComponent = REG_DWORD;
					RegQueryValueEx(m_key2,L"SystemComponent", 0, &m_attr, LPBYTE(&dwSystemComponent), &dwReSystemComponent);

					DWORD dwWindowsInstaller = 0;
					DWORD dwReWindowsInstaller = REG_DWORD;
					RegQueryValueEx(m_key2,L"WindowsInstaller", 0, &m_attr, LPBYTE(&dwWindowsInstaller), &dwReWindowsInstaller);

					if ((dwSystemComponent == 1) && (dwWindowsInstaller == 1))
					{
						RegCloseKey(m_key2);
						m_namelen=sizeof(m_name); 
						memset(m_name,0,m_namelen); 
						m_index++;
						continue;
					}

					DWORD dwNoRemove = 0;
					DWORD dwReNoRemove = REG_DWORD;
					RegQueryValueEx(m_key2,L"NoRemove", 0, &m_attr, LPBYTE(&dwNoRemove), &dwReNoRemove); //禁止卸载

					DWORD dwNoModify = 0;
					DWORD dwReNoModify = REG_DWORD;
					RegQueryValueEx(m_key2,L"NoModify", 0, &m_attr, LPBYTE(&dwNoModify), &dwReNoModify); //禁止修改

					DWORD dwNoRepair = 0;
					DWORD dwReNoRepair = REG_DWORD;
					RegQueryValueEx(m_key2,L"NoRepair", 0, &m_attr, LPBYTE(&dwNoRepair), &dwReNoRepair); //禁止修改
				
					if ((dwNoRemove == 1) && (dwNoModify == 1) && (dwNoRepair == 1))
					{
						RegCloseKey(m_key2);
						m_namelen=sizeof(m_name); 
						memset(m_name,0,m_namelen); 
						m_index++;
						continue;
					}

					//卸载路径
					wchar_t szwUninstall[EFFSOFT_MAX_PATH];
					memset(szwUninstall, 0, EFFSOFT_MAX_PATH);	
					RegQueryValueEx(m_key2,L"UninstallString",0,&m_attr,LPBYTE(szUninstallString),&iUninstallString);
					SAFE_COPY_W(szwUninstall, szUninstallString);
					CString strUninstall = szwUninstall;
					if (strUninstall.IsEmpty())
					{
						RegCloseKey(m_key2);
						m_namelen=sizeof(m_name); 
						memset(m_name,0,m_namelen); 
						m_index++;
						continue;
					}
				}
				
				RegQueryValueEx(m_key2,L"DisplayName",0,&m_attr,LPBYTE(m_displayname),&m_displaynamelen); 
				RegQueryValueEx(m_key2,L"DisplayVersion",0,&m_attr,LPBYTE(szVersion),&szVersionlen); 
				RegQueryValueEx(m_key2,L"Publisher",0,&m_attr,LPBYTE(szPublisher),&iPublisherLen); 
				RegQueryValueEx(m_key2,L"InstallLocation",0,&m_attr,LPBYTE(szLocation),&iLocation); 
				RegQueryValueEx(m_key2,L"InstallDate",0,&m_attr,LPBYTE(szInstallDate),&iIntalldateLen); 

				if (wcscmp(m_displayname,_T("")) !=0) 
				{//找到软件名或者反安装信息了 

					//LOGINFO("installed software:%s", m_displayname);
					CSoftInfo info;
					SAFE_COPY_W(info.strDisplayName, m_displayname);
					SAFE_COPY_W(info.strPublisher,szPublisher);
					SAFE_COPY_W(info.strInstallLocation , szLocation);
					SAFE_COPY_W(info.strDisplayVersion , szVersion);
					SAFE_COPY_W(info.strInstallDate, szInstallDate);
					softset.push_back(info);
				} 

				RegCloseKey(m_key2);
			} 

		} 
		m_namelen=sizeof(m_name); 
		memset(m_name,0,m_namelen); 
		m_index++;
	}

	RegCloseKey(m_key); 

	
	return TRUE;
}

//取消重定位
BOOL RegeditFindInstallSoftware(list<CSoftInfo> &softset)
{
	PVOID OldValue; 
	HINSTANCE hlibrary; 
	typedef int (__stdcall * Wow64DisableWow64FsRedirection)(LPVOID); 
	typedef int (__stdcall * Wow64RevertWow64FsRedirection)(LPVOID); 
	Wow64DisableWow64FsRedirection f_Wow64DisableWow64FsRedirection = NULL; 
	Wow64RevertWow64FsRedirection f_Wow64RevertWow64FsRedirection = NULL; 
	//链接当前DLL,因为函数在当前DLL中
	hlibrary = LoadLibrary(_T("Kernel32.dll"));
	//在当前DLL中遍历调用的函数
	f_Wow64DisableWow64FsRedirection = (Wow64DisableWow64FsRedirection) GetProcAddress(hlibrary, ("Wow64DisableWow64FsRedirection")); 

	if (f_Wow64DisableWow64FsRedirection  && (Is64BitOs()))
	{
		//但前函数存在
		f_Wow64DisableWow64FsRedirection(&OldValue);
		int i = GetLastError();
		

		//禁用重定向
		f_Wow64RevertWow64FsRedirection = (Wow64RevertWow64FsRedirection) GetProcAddress(hlibrary, ("Wow64RevertWow64FsRedirection")); 
		////////////////////////////
		
		DWORD dwAccess = KEY_ALL_ACCESS;

		TCHAR szSubKey32[255]=_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"); 
		GetAllInstallSoftware(softset, HKEY_LOCAL_MACHINE, szSubKey32, dwAccess);
		
		/*
		if(Is64BitOs())
		{	
			TCHAR szSubKey64[255]=_T("SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"); 
			GetAllInstallSoftware(softset, HKEY_LOCAL_MACHINE, szSubKey64, dwAccess);
		}
		*/

		////////////////////////////
		//恢复重定向
		if(f_Wow64RevertWow64FsRedirection)
		{
			f_Wow64RevertWow64FsRedirection (OldValue);
		} 
	}
	return TRUE;
}

//另一种方法
BOOL GetAllInstallSoftware(list<CSoftInfo>  &softset, HKEY hKeyRoot)
{
	HKEY m_key,m_key2; 
	TCHAR m_SubKey[255]=_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"); 
	
	TCHAR m_name[200],m_displayname[200],szVersion[200],uninstall[200],szPublisher[200],szLocation[200],szUninstall[200];
	TCHAR szInstallDate[18]={0};
	DWORD m_namelen=200,m_displaynamelen=200, szVersionlen=200, iPublisherLen, iLocation, iIntalldateLen, iUninstall; 
	DWORD m_attr=REG_BINARY|REG_DWORD|REG_EXPAND_SZ|REG_MULTI_SZ|REG_NONE|REG_SZ; 

	DWORD dwAccess = KEY_ALL_ACCESS;		

	int m_endi=0;
	if (Is64BitOs())
	{		
		m_endi=1;
	}
	for(int i = 0; i <=m_endi; i++)
	{	
		dwAccess = KEY_ALL_ACCESS;		
		if (Is64BitOs()&&(i==0))
		{							
			dwAccess|= KEY_WOW64_64KEY;				
		}
		else if (Is64BitOs()&&(i==1))
		{		
			dwAccess|= KEY_WOW64_32KEY;	

		}else
		{
			//dwAccess|= KEY_WOW64_32KEY;		  //32位系统
		}
		

		if (RegOpenKeyEx(hKeyRoot, m_SubKey, 0, dwAccess, &m_key) !=ERROR_SUCCESS) 
		{
			return FALSE;
		} 


		int m_index =0;
		while (RegEnumKeyEx(m_key,m_index,m_name,&m_namelen,0,NULL,NULL,0)!=ERROR_NO_MORE_ITEMS) 
		{ 
			if (wcscmp(m_name,_T("")) != 0) 
			{
				 //如果找到了,分别在枚举下面有没有DISPLAYNAME,以便得到软件名称 
				wcscpy(uninstall,m_SubKey); 
				wcscat(uninstall,L"\\"); 
				wcscat(uninstall,m_name); // 连接到下一层 

				m_displaynamelen=sizeof(m_displayname); 
				memset(m_displayname,0,sizeof(m_displayname)); 

				szVersionlen=sizeof(szVersion);// 
				memset(szVersion,0,sizeof(szVersion));

				iPublisherLen = sizeof(szPublisher);
				memset(szPublisher,0,sizeof(szPublisher));

				iLocation = sizeof(szLocation);
				memset(szLocation, 0, sizeof(szLocation));

				iIntalldateLen = sizeof(szInstallDate);
				memset(szInstallDate, 0, sizeof(szInstallDate));

				iUninstall = sizeof(szUninstall);
				memset(szUninstall, 0, sizeof(szUninstall));

				//再打开,查找软件显示现实名称和谢载命令行 
				//if (RegOpenKeyEx(hKeyRoot,uninstall,0,KEY_ALL_ACCESS,&m_key2)==ERROR_SUCCESS) 
				if (RegOpenKeyEx(hKeyRoot,uninstall,0,dwAccess,&m_key2)==ERROR_SUCCESS) 
				{	

					//排除
					if (FALSE) 
					{
						//显示全部安装软件
					}
					else if (TRUE)
					{
						//显示用户安装软件 -- 设置--应用与功能显示的
						
						//排除系统软件
						DWORD dwSystemComponent = 0;
						DWORD dwReSystemComponent = REG_DWORD;
						RegQueryValueEx(m_key2,L"SystemComponent", 0, &m_attr, LPBYTE(&dwSystemComponent), &dwReSystemComponent);

						DWORD dwWindowsInstaller = 0;
						DWORD dwReWindowsInstaller = REG_DWORD;
						RegQueryValueEx(m_key2,L"WindowsInstaller", 0, &m_attr, LPBYTE(&dwWindowsInstaller), &dwReWindowsInstaller);

						if ((dwSystemComponent == 1) && (dwWindowsInstaller == 1))
						{
							RegCloseKey(m_key2);
							m_namelen=sizeof(m_name); 
							memset(m_name,0,m_namelen); 
							m_index++;
							continue;
						}
					}
					else if (FALSE)
					{
						//显示允许卸载、移动、修改的软件 -- 控制面板卸载软件显示的

						DWORD dwSystemComponent = 0;
						DWORD dwReSystemComponent = REG_DWORD;
						RegQueryValueEx(m_key2,L"SystemComponent", 0, &m_attr, LPBYTE(&dwSystemComponent), &dwReSystemComponent);

						DWORD dwWindowsInstaller = 0;
						DWORD dwReWindowsInstaller = REG_DWORD;
						RegQueryValueEx(m_key2,L"WindowsInstaller", 0, &m_attr, LPBYTE(&dwWindowsInstaller), &dwReWindowsInstaller);

						if ((dwSystemComponent == 1) && (dwWindowsInstaller == 1))
						{
							RegCloseKey(m_key2);
							m_namelen=sizeof(m_name); 
							memset(m_name,0,m_namelen); 
							m_index++;
							continue;
						}

						DWORD dwNoRemove = 0;
						DWORD dwReNoRemove = REG_DWORD;
						RegQueryValueEx(m_key2,L"NoRemove", 0, &m_attr, LPBYTE(&dwNoRemove), &dwReNoRemove); //禁止卸载

						DWORD dwNoModify = 0;
						DWORD dwReNoModify = REG_DWORD;
						RegQueryValueEx(m_key2,L"NoModify", 0, &m_attr, LPBYTE(&dwNoModify), &dwReNoModify); //禁止修改

						DWORD dwNoRepair = 0;
						DWORD dwReNoRepair = REG_DWORD;
						RegQueryValueEx(m_key2,L"NoRepair", 0, &m_attr, LPBYTE(&dwNoRepair), &dwReNoRepair); //禁止修改
					
						if ((dwNoRemove == 1) && (dwNoModify == 1) && (dwNoRepair == 1))
						{
							RegCloseKey(m_key2);
							m_namelen=sizeof(m_name); 
							memset(m_name,0,m_namelen); 
							m_index++;
							continue;
						}

						//卸载路径
						wchar_t szwUninstall[EFFSOFT_MAX_PATH];
						memset(szwUninstall, 0, EFFSOFT_MAX_PATH);	
						RegQueryValueEx(m_key2,L"UninstallString",0,&m_attr,LPBYTE(szUninstall),&iUninstall);
						SAFE_COPY_W(szwUninstall, szUninstall);
						CString strUninstall = szwUninstall;
						if (strUninstall.IsEmpty())
						{
							RegCloseKey(m_key2);
							m_namelen=sizeof(m_name); 
							memset(m_name,0,m_namelen); 
							m_index++;
							continue;
						}
					}
					
					RegQueryValueEx(m_key2,L"Publisher",0,&m_attr,LPBYTE(szPublisher),&iPublisherLen); 
					RegQueryValueEx(m_key2,L"DisplayName",0,&m_attr,LPBYTE(m_displayname),&m_displaynamelen); 
					RegQueryValueEx(m_key2,L"DisplayVersion",0,&m_attr,LPBYTE(szVersion),&szVersionlen); 
					RegQueryValueEx(m_key2,L"InstallLocation",0,&m_attr,LPBYTE(szLocation),&iLocation); 
					RegQueryValueEx(m_key2,L"InstallDate",0,&m_attr,LPBYTE(szInstallDate),&iIntalldateLen); 

					if (wcscmp(m_displayname,_T("")) !=0) 
					{
						//找到软件名或者反安装信息了 
						CSoftInfo info;
						SAFE_COPY_W(info.strDisplayName, m_displayname);
						SAFE_COPY_W(info.strPublisher, szPublisher);
						SAFE_COPY_W(info.strInstallLocation, szLocation);
						SAFE_COPY_W(info.strDisplayVersion, szVersion);
						SAFE_COPY_W(info.strInstallDate, szInstallDate);
						softset.push_back(info);
					} 

					RegCloseKey(m_key2);
				} 

			} 
			m_namelen=sizeof(m_name); 
			memset(m_name,0,m_namelen); 
			m_index++;
		} 
	
		RegCloseKey(m_key); 
	}

	return TRUE;
}


//Mian函数调用
int main()
{

	//方法1
	list<CSoftInfo> softset;
	wstring strText;

	RegeditFindInstallSoftware(softset);
	
	list<CSoftInfo>::iterator iter = softset.begin();
	for (; iter != softset.end(); iter++)
	{
		wstring strTemp;
		strTemp = iter->strDisplayName;

		strText += strTemp;
		strText += ";";
	}

	//方法2
	list<CSoftInfo> setSoftInfo2;
	GetAllInstallSoftware(setSoftInfo2, HKEY_LOCAL_MACHINE);


	return 0;
}

我提供了2中方法都可以,其中用到的几个重要的注册表项:

SystemComponent 系统组件

WindowsInstaller windows安装

NoRemove = 1  禁止卸载

NoModify = 1  禁止修改

NoRepair = 1  禁止修复

其中控制面板中的卸载软件显示的是过滤后的,只有当:

(NoRemove == 0) || (NoModify == 0) || (NoRepair == 0) == 1 

(dwSystemComponent == 0) && (dwWindowsInstaller == 0) == 1

UninstallString(注册表项卸载路径)不为空的时候。

这三条都成立后显示的才是控制面板中的卸载软件中显示一样的。