Friday, September 4, 2009

Un-install a program programmatically (C++ on Windows)

Ever wondered how a program is uninstalled when we remove a program from the control panel? Every installed program stores an uninstallString which is a command to un-install itself in the registry. If you can locate your program by searching for its name (I am using the name 'My Program' here), or if you know the product code, it really is a piece of cake....

Here is a sample program to search the registry for a program called My Program and uninstall it.

#include <iostream>
#include <algorithm>
#include <string>
#include <windows.h>
#include <winreg.h>
#include <iostream>
#include <cstdlib>

bool uninstallMyProgram(HKEY hRootKey,const wchar_t *wzKey);

bool search(HKEY hRootKey, const wchar_t *wzKey)
{
const int KeyNameBufferSize = 512;

LONG result = ERROR_SUCCESS;
TCHAR keyName[KeyNameBufferSize];
DWORD index = 0;
DWORD nameLength = KeyNameBufferSize;
FILETIME lastWriteTime;

HKEY hRegKey;
if(::RegOpenKeyEx(hRootKey, wzKey, 0L, KEY_READ , &hRegKey) != ERROR_SUCCESS)
return false;

while (result == ERROR_SUCCESS)
{
nameLength = KeyNameBufferSize;
result = ::RegEnumKeyEx(hRegKey, index, keyName,
&nameLength, 0, NULL, NULL, &lastWriteTime);

if (result == ERROR_SUCCESS)
{
std::wstring str = wzKey ;
str += keyName;
if(uninstallMyProgram(hRegKey, str.c_str()))
return true;
}

index++;
}
RegCloseKey(hRootKey);
return (result == ERROR_NO_MORE_ITEMS) ? true : false;
}

bool uninstallMyProgram(HKEY hRootKey,const wchar_t *wzKey)
{
const int KeyNameBufferSize = 1024;
wchar_t valueBuffer[ KeyNameBufferSize ];
valueBuffer[0]=0;

DWORD dwType = REG_SZ;
BYTE abValueDat[ KeyNameBufferSize ];
DWORD dwValDatLen = sizeof(abValueDat);
HKEY hKey;

if(::RegOpenKeyEx(HKEY_LOCAL_MACHINE, wzKey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
return false;

if(::RegQueryValueEx(hKey, L"DisplayName", 0L, &dwType, abValueDat, &dwValDatLen) != ERROR_SUCCESS)
return false;

wsprintf(valueBuffer,L"%s", (wchar_t*) abValueDat);
if(::_wcsnicmp(L"My Program", valueBuffer, 14) == 0)
{
wchar_t uninstallCommand[ KeyNameBufferSize ];
BYTE retValueDat [ KeyNameBufferSize ];
dwValDatLen = sizeof(retValueDat);

if(::RegQueryValueEx(hKey, L"UninstallString", 0L, &dwType, retValueDat, &dwValDatLen) == ERROR_SUCCESS)
{
::wsprintf(uninstallCommand,L"%s", (wchar_t*) retValueDat );
if(-1 == ::_wsystem(uninstallCommand)) //execute the command to uninstall My Program
{
RegCloseKey(hKey);
return false;
}
RegCloseKey(hKey);
return true;
}
}
RegCloseKey(hKey);
return false; //My Program is not installed
}

int main()
{
const wchar_t* path = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
bool removed = search( HKEY_LOCAL_MACHINE, path);
if(!removed)
removed = search( HKEY_CURRENT_USER, path);
}

0 comments: