void MsiGetPropertyByOpenPackage()
{
MSIHANDLE msiHandle = NULL;
UINT uiOpenState;
TCHAR* szMsiFileName= _T("C:\\Program Files (x86)\\远为软件\\virnos client\\SWar.msi");
uiOpenState = MsiOpenPackage(szMsiFileName, &msiHandle);
if (ERROR_SUCCESS != uiOpenState)
{
// error
return;
}
TCHAR* szValueBuf = NULL;
DWORD cchValueBuf = 0;
UINT uiState =MsiGetProperty(msiHandle, TEXT("ProductName"), TEXT(""), &cchValueBuf);
if (ERROR_MORE_DATA == uiState)
{
++cchValueBuf;
szValueBuf = new TCHAR(cchValueBuf);
if (szValueBuf)
{
uiState = MsiGetProperty(msiHandle, TEXT("ProductName"), szValueBuf, &cchValueBuf);
}
}
MsiCloseHandle(msiHandle);
}
调用MsiOpenPackage函数来获取MSIHANDLE值,然后就可以获取属性值,MsiOpenPackage使用的时候会打开msi文件,会看到程序运行时的界面,再调用MsiCloseHandle(hInstall)函数就关闭msi文件,也会看到msi程序运行界面消失。用该方法的时候就会看到有msi瞬间闪现安装界面,体验感觉不好
因此使用MsiOpenDatabase打开msi文件,然后再获取,后面相继使用MsiDatabaseOpenView,MsiViewExecute,MsiViewFetch,MsiRecordGetString等方法,
使用MsiCloseHandle关闭打开的msi句柄。
BOOL GetMsiPropertyProductVersion(CString strMsiName, CString &strVer )
{
USES_CONVERSION;
MSIHANDLE hMsiHandle = NULL;
UINT uiStatus = MsiOpenDatabase(strMsiName, MSIDBOPEN_READONLY, &hMsiHandle);
if (ERROR_SUCCESS != uiStatus)
{
return FALSE;
}
MSIHANDLE hView = NULL;
MsiDatabaseOpenView(hMsiHandle, _T("SELECT * FROM Property WHERE Property = 'ProductVersion'"), &hView);
MSIHANDLE hRecord = NULL;
MsiViewExecute(hView, hRecord);
if (MsiViewFetch(hView, &hRecord) == ERROR_SUCCESS)
{
TCHAR szName[MAX_PATH]={0};
TCHAR szValue[MAX_PATH]={0};
DWORD dwStringLen = MAX_PATH;
MsiRecordGetString(hRecord, 1, szName, &dwStringLen);
dwStringLen = MAX_PATH;
MsiRecordGetString(hRecord, 2, szValue, &dwStringLen );
printf("%s\t:%s\r\n", T2A(szName), T2A(szValue));
strVer = szValue;
MsiCloseHandle(hView);
MsiCloseHandle(hMsiHandle);
return TRUE;
}
MsiCloseHandle(hView);
MsiCloseHandle(hMsiHandle);
return FALSE;
}
UINT GetMsiAllProperty(CString strMsiName )
{
USES_CONVERSION;
MSIHANDLE hMsiHandle = NULL;
UINT uiStatus = MsiOpenDatabase(strMsiName, MSIDBOPEN_READONLY, &hMsiHandle);
if (ERROR_SUCCESS != uiStatus)
{
return uiStatus;
}
MSIHANDLE hView = NULL;
MsiDatabaseOpenView(hMsiHandle, _T("SELECT * FROM Property"), &hView);
MSIHANDLE hRecord = NULL;
MsiViewExecute(hView, hRecord);
while(MsiViewFetch(hView, &hRecord) == ERROR_SUCCESS)
{
TCHAR szValueBuf[MAX_PATH]={0};
TCHAR Source[MAX_PATH]={0};
DWORD dwStringLen = MAX_PATH;
MsiRecordGetString(hRecord, 1, szValueBuf, &dwStringLen);
dwStringLen = MAX_PATH;
MsiRecordGetString(hRecord, 2, Source, &dwStringLen );
printf("%s\t:%s\r\n", T2A(szValueBuf), T2A(Source));
}
MsiCloseHandle(hView);
MsiCloseHandle(hMsiHandle);
return 1;
}
例如实际的配置文档内容
创建DLL文件build.bat内容
call vs6.bat
@echo off
nmake -nologo -f makefile-InstallUtility clean
nmake -nologo -f makefile-InstallUtility
del ufutils.dll
rename InstallUtility.dll ufutils.dll
rem copy ufutils.dll ..\Lib\Resource\ufutils.dll
echo buildding completed!
pause
vs6.bat 文件内容
"c:\Program Files\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT"
InstallUtility.def 内容
; InsatllUtility.def : Declares the module parameters for the DLL.
LIBRARY "InstallUtility"
DESCRIPTION 'InstallUtility Windows Dynamic Link Library'
EXPORTS
; Explicit exports can go here
RollbackBackupFiles@1
ExcuteDBEnginSys@2
CompareFilesDate @3
ExcuteApp @4
ExcuteRegServer @5
RemoveAllFiles @6
CreateBinaryFile @7
SetRegPolicyScopeValue @8
ExcuteSqlLiteSys @9
UninstallExcuteEnginSys @10
InstallUtility.cpp 文件内容
// ++
//
// UFIDA Ltd. inc.
//
// Copyright (C) Microsoft UFIDA, 2006
//
// File:
// InstallUtility.cpp
//
// Date:
// Apr.29.2006
//
// Note:
// U8安装程序辅助扩展工具,提供程序反安装
// 原始文件还原的功能
//
// ++
#pragma warning (disable:4786 4530)
#include <windows.h>
#include <stdlib.h>
#include <tchar.h>
#include <Msi.h>
#include <Msiquery.h>
#include <set>
#include <string>
#include <fstream>
#include "Shlwapi.h"
#include "RpcDce.h"
#include <time.h>
#include <stdio.h>
#include "rpcdce.h"
#pragma comment(lib, "Msi.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "Advapi32.lib")
#pragma comment(lib, "rpcrt4.lib")
#define PROPERTYNAME_DEPENDLIST _T("dependlist")
#define PROPERTYNAME_PATCHREGROOT _T("patchregroot")
#define PROPERTYNAME_CURBACKDIR _T("currbak")
#define PROPERTYNAME_ABC _T("[#file.2D0F7A40_6082_42CA_B2B5_546AA2DB9CB0]")
#define RELEASE(p) if (p) {\
delete [] (p); \
(p) = NULL; \
}
#define INSTALLMESSAGE_FATALEXIT 0x00000000L
#define MAX_BUFFER 512
#import "com\\Comadmin.dll" no_namespace
using namespace std;
//#import "com\\Comadmin.dll" no_namespace
//
// Global Variant Define
//
TCHAR* g_lpszBackupFilesPath = NULL; // 保存备份原始文件的目录
BOOL g_fNeedReBoot = FALSE; // 是否需要重新启动操作系统
MSIHANDLE g_hInstall = NULL;
long eMessageType = INSTALLMESSAGE_INFO;
TCHAR* g_spid = NULL; // 问题号
TCHAR* g_dbEnginPath = NULL; // 数据库引擎
TCHAR* g_sqllitepathinfoPath = NULL; // 导入SQLLITE文件信息
TCHAR* g_exerunPath = NULL; // 获取EXE 运行路径,卸载完后的。
set<string> g_setupfilesets; //声明集合
void Log2Msi(LPCTSTR lpszMsg, ...)
{
TCHAR szBuffer[2048] = {0};
va_list list;
va_start(list, lpszMsg);
wvsprintf(szBuffer, lpszMsg, list);
va_end(list);
OutputDebugString(szBuffer);
PMSIHANDLE hRec = ::MsiCreateRecord(2);
::MsiRecordSetString(hRec, 0, szBuffer);
::MsiProcessMessage(g_hInstall, (tagMSIMESSAGE)eMessageType, hRec);
::MsiCloseHandle(hRec);
}
//
//
//
//
LPTSTR getProperty(MSIHANDLE hInstall, LPCTSTR lpszPropertyName)
{
TCHAR* szCAData = NULL;
DWORD cchCAData = 0;
UINT uiState = ERROR_SUCCESS;
//
// 尝试获取属性的长度,然后分配内存
//
uiState = ::MsiGetProperty(hInstall, lpszPropertyName, _T(""), &cchCAData);
if (uiState == ERROR_MORE_DATA)
{
//
// 分配内存
//
szCAData = new TCHAR[++cchCAData];
//
// 得到属性值
//
uiState = ::MsiGetProperty(hInstall, lpszPropertyName, szCAData, &cchCAData);
if (uiState != ERROR_SUCCESS)
{
//
// 失败释放内存,返回失败
//
RELEASE(szCAData)
}
}
return szCAData;
}
//
// getBackupFilesPath
//
// 从安装包中获取备份文件目录
//
BOOL getBackupFilesPath(MSIHANDLE hInstall)
{
TCHAR* szCAData = NULL;
DWORD cchCAData = 0;
UINT uiState = ERROR_SUCCESS;
g_lpszBackupFilesPath = getProperty(hInstall, PROPERTYNAME_CURBACKDIR);
return (g_lpszBackupFilesPath != NULL);
}
//
// RegisterDllOcx
//
// 注册COM组件
//
BOOL RegisterDllOcx(LPCTSTR lpszFile)
{
BOOL fRet = FALSE;
HRESULT (STDAPICALLTYPE * lpDllEntryPoint)(void);
HINSTANCE hInst = LoadLibraryEx(lpszFile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (hInst != NULL)
{
(FARPROC&)lpDllEntryPoint = GetProcAddress(hInst, _T("DllRegisterServer"));
if (lpDllEntryPoint != NULL)
{
if (FAILED((*lpDllEntryPoint)()))
Log2Msi(_T("CCA- RegisterDllOcx!DllRegisterServer failed, LastError:0x%08X file:%s"),GetLastError(), lpszFile);
else
fRet = TRUE;
}
else
Log2Msi(_T("CCA- RegisterDllOcx!Could't find dll entry,DllRegisterServer file:%s"),lpszFile);
}
else
Log2Msi(_T("CCA- RegisterDllOcx!Could't load file:%s"),lpszFile);
FreeLibrary(hInst);
return fRet;
}
bool IsVista(void)
{
OSVERSIONINFOEX osvi = {0};
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
::GetVersionEx((LPOSVERSIONINFO)&osvi);
//return false;
return osvi.dwMajorVersion >= 6;
}
DWORD RunCommand(LPCTSTR lpApplicationName, LPTSTR lpCommandLine,WORD nCmdShow,DWORD dwInterval)
{
TCHAR commandLine[1024] = {0};
wsprintf(commandLine, _T("\"%s\" %s"), lpApplicationName, lpCommandLine);
Log2Msi(_T("CCA- GetProcessReturn(%s ) !"), commandLine );
STARTUPINFO si = {0};
si.cb = sizeof(si);
si.dwFlags |= STARTF_USESHOWWINDOW;
//si.wShowWindow = SW_HIDE;
si.wShowWindow=nCmdShow;
PROCESS_INFORMATION pi;
DWORD dwExitCode = -1;
DWORD dwResult=-1;
BOOL flag = ::CreateProcess(NULL,
commandLine,
NULL,NULL,FALSE,0,NULL,NULL,&si, &pi);
if (flag)
{
::CloseHandle(pi.hThread);
dwResult=::WaitForSingleObject(pi.hProcess, dwInterval);
::GetExitCodeProcess(pi.hProcess, &dwExitCode);
::CloseHandle(pi.hProcess);
}
else
{
dwExitCode = GetLastError();
}
Log2Msi(_T("CCA- GetProcessReturn(%s exitcode: %d Result:%d) !"), commandLine, dwExitCode,dwResult );
return dwExitCode;
}
/*
废弃,不再使用,可以外挂一个支持提升权限的程序,使用此程序作为中介,再提升其他程序
DWORD RunShellExecuteEx(LPCTSTR lpApplicationName, LPTSTR lpCommandLine,WORD nCmdShow,DWORD dwInterval)
{
//Log2Msi(_T("CCA- RunShellExecute(%s %s ) !"), lpApplicationName,lpCommandLine);
TCHAR commandLine[1024] = {0};
wsprintf(commandLine, _T("\"%s\" %s"), lpApplicationName, lpCommandLine);
Log2Msi(_T("CCA- RunShellExecute(%s ) !"), commandLine );
DWORD dwExitCode = -1;
SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = GetForegroundWindow();
ShExecInfo.lpVerb =_T("runas");
ShExecInfo.lpFile = lpApplicationName;
ShExecInfo.lpParameters = lpCommandLine;
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = nCmdShow;
ShExecInfo.hInstApp = NULL;
BOOL flag = ShellExecuteEx(&ShExecInfo);
if( flag )
{
::WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
::GetExitCodeProcess(ShExecInfo.hProcess, &dwExitCode);
::CloseHandle(ShExecInfo.hProcess);
}
else
{
dwExitCode = ::GetLastError();
}
Log2Msi(_T("CCA- RunShellExecute(%s %s exitcode: %d) !"), lpApplicationName,lpCommandLine, dwExitCode );
return dwExitCode;
}
*/
DWORD RunShellExecute(LPCTSTR lpApplicationName, LPTSTR lpCommandLine,WORD nCmdShow,DWORD dwInterval)
{
//Log2Msi(_T("CCA- RunShellExecute(%s %s ) !"), lpApplicationName,lpCommandLine);
TCHAR commandLine[1024] = {0};
wsprintf(commandLine, _T("\"%s\" %s"), lpApplicationName, lpCommandLine);
Log2Msi(_T("CCA- RunShellExecute(%s ) !"), commandLine );
DWORD dwExitCode = -1;
/*
SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = GetForegroundWindow();
ShExecInfo.lpVerb =_T("runas");
ShExecInfo.lpFile = lpApplicationName;
ShExecInfo.lpParameters = lpCommandLine;
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = nCmdShow;
ShExecInfo.hInstApp = NULL;
BOOL flag = ShellExecuteEx(&ShExecInfo);
*/
HANDLE hPToken;
HANDLE hUserTokenDup;
PROCESS_INFORMATION pi;
STARTUPINFO si;
LUID luid;
TOKEN_PRIVILEGES tp;
DWORD dwSessionId;
//获取当前token值 GetCurrentProcess()
//TOKEN_DUPLICATE
BOOL bResult=::OpenProcessToken(::GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
| TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID
| TOKEN_READ | TOKEN_WRITE,
&hPToken);
if (!bResult)
{
Log2Msi(_T("CCA- OpenProcessToken(%s %s exitcode: %d) !"), lpApplicationName,lpCommandLine, ::GetLastError() );
}
if ( !LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &luid ) )
{
dwExitCode = ::GetLastError();
Log2Msi(_T("CCA- LookupPrivilegeValue(%s %s exitcode: %d) !"), lpApplicationName,lpCommandLine, dwExitCode );
}
else{
tp.PrivilegeCount =1;
tp.Privileges[0].Luid =luid;
tp.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;
}
// MAXIMUM_ALLOWED SecurityAnonymous
if (bResult)
{
bResult=DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED ,
0, // token attributes
SecurityIdentification,//SecurityAnonymous
TokenPrimary
,&hUserTokenDup);
}
if (!bResult)
{
Log2Msi(_T("CCA- DuplicateTokenEx(%s %s exitcode: %d) !"), lpApplicationName,lpCommandLine, ::GetLastError() );
}
//Adjust Token privilege
SetTokenInformation(hUserTokenDup,
TokenSessionId,(void*)&dwSessionId,sizeof(DWORD));
if (!AdjustTokenPrivileges(hUserTokenDup,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,NULL))
{
dwExitCode = ::GetLastError();
Log2Msi(_T("CCA- AdjustTokenPrivileges(%s %s exitcode: %d) !"), lpApplicationName,lpCommandLine, dwExitCode );
}
if (bResult)
{
// 使用CreateProcessAsUser来采用当前进程的token值来模拟运行.
// Initialize the STARTUPINFO structure.
ZeroMemory(&si, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(pi));
si.cb= sizeof(STARTUPINFO);
si.dwFlags|=STARTF_USESHOWWINDOW;
si.wShowWindow=nCmdShow;
bResult =CreateProcessAsUser(
hUserTokenDup, // client's access token
NULL, // file to execute
commandLine, // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
0, // creation flags
NULL, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);
}
if( bResult )
{
::WaitForSingleObject(pi.hProcess ,dwInterval);
::GetExitCodeProcess(pi.hProcess , &dwExitCode);
if (pi.hThread != INVALID_HANDLE_VALUE)
CloseHandle(pi.hThread);
::CloseHandle(pi.hProcess );
if (hPToken != INVALID_HANDLE_VALUE)
CloseHandle(hPToken);
if (hUserTokenDup != INVALID_HANDLE_VALUE)
CloseHandle(hUserTokenDup);
}
else
{
dwExitCode = ::GetLastError();
Log2Msi(_T("CCA- CreateProcessAsUser(%s %s exitcode: %d) !"), lpApplicationName,lpCommandLine, dwExitCode );
}
//RunShellExecuteEx(_T("C:\\Users\\u8plat\\AppData\\Local\\Temp\\ufmsi\\reg.exe"),commandLine,nCmdShow,dwInterval);
Log2Msi(_T("CCA- RunShellExecute(%s %s exitcode: %d) !"), lpApplicationName,lpCommandLine, dwExitCode );
return dwExitCode;
}
DWORD GetProcessReturn(LPCTSTR lpApplicationName, LPTSTR lpCommandLine,WORD nCmdShow,DWORD dwInterval =INFINITE)
{
if (IsVista())
return RunShellExecute(lpApplicationName,lpCommandLine,nCmdShow,dwInterval);
else
return RunCommand(lpApplicationName,lpCommandLine,nCmdShow,dwInterval);
}
//得到BinaryFile的绝对路径 nCreateFile=0 不创建文件 =1 创建文件
void BinaryFileTempPath(MSIHANDLE hInstall,LPCTSTR lpszBinaryFielName,LPTSTR szTempFile,WORD nCreateFile=0)
{
Log2Msi("GetBinaryFile Relative Path %s",szTempFile);
Log2Msi("GetBinaryFile Relative Path %s",lpszBinaryFielName);
UINT uRes = 0;
TCHAR szTempPath[MAX_PATH];
TCHAR szTempFile1[MAX_PATH];
//TCHAR szTempFile[MAX_PATH];
ZeroMemory(szTempPath, sizeof(szTempPath));
// get path to the temp directory
DWORD dwRes = GetTempPath(MAX_PATH, szTempPath);
ZeroMemory(szTempFile, sizeof(szTempFile));
ZeroMemory(szTempFile1, sizeof(szTempFile1));
/*
if (dwRes)
uRes = GetTempFileName(szTempPath, _T("uf"), 0, szTempFile);
if (!dwRes || !uRes)
{
Log2Msi(_T("GetTempFileName failed"));
return ;
}
wsprintf (szTempFile, _T("%s.exe"), szTempFile);
*/
//add .exe extension to the name of the temp file
if(szTempPath[lstrlen(szTempPath)-1] == '\\')
wsprintf(szTempPath, _T("%sufmsi"),szTempPath);
else
wsprintf(szTempPath, _T("%s\\ufmsi"),szTempPath);
if (PathFileExists(szTempPath) == FALSE)
{
if (!CreateDirectory(szTempPath, NULL) )
{
Log2Msi(_T("CreateDirectory failed"));
}
}
Log2Msi("%s",szTempPath);
Log2Msi("%s.exe",lpszBinaryFielName);
wsprintf (szTempFile, _T("%s\\%s.exe"),szTempPath, lpszBinaryFielName);
//添加兼容性注册表。
HKEY hKey = NULL;
char* szVal=_T("WINSRV03SP1");
DWORD dwSize = _tcslen(szVal) * sizeof(TCHAR);
LPCTSTR lpKey = _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers");
DWORD dwAccess = KEY_ALL_ACCESS;
//RegCreateKeyEx(hRootKey, lpszRegPath, 0, NULL, REG_OPTION_NON_VOLATILE, dwAccess, NULL, &hKey, NULL)
GetLongPathName(szTempFile,szTempFile1,MAX_PATH);
if (::RegCreateKeyEx(HKEY_CURRENT_USER,lpKey,NULL,NULL,REG_OPTION_NON_VOLATILE, dwAccess,NULL, &hKey,NULL)== ERROR_SUCCESS )
{
Log2Msi("GetLongPathName:%s",szTempFile1);
if (::RegSetValueEx(hKey,szTempFile1,NULL,REG_SZ,(CONST BYTE*)szVal,dwSize) == ERROR_SUCCESS )
{
Log2Msi(_T("Set Register Success HKEY_CURRENT_USER\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"));
}
//if (::RegSetValueEx(hKey,szTempFile,NULL,REG_SZ,(CONST BYTE*)szVal,dwSize) == ERROR_SUCCESS )
//{
// Log2Msi(_T("Set Register Success Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"));
//}
RegCloseKey(hKey);
hKey = NULL;
}
if (::RegCreateKeyEx(HKEY_LOCAL_MACHINE,lpKey,NULL,NULL,REG_OPTION_NON_VOLATILE, dwAccess,NULL, &hKey,NULL)== ERROR_SUCCESS )
{
Log2Msi("GetLongPathName:%s",szTempFile1);
if (::RegSetValueEx(hKey,szTempFile1,NULL,REG_SZ,(CONST BYTE*)szVal,dwSize) == ERROR_SUCCESS )
{
Log2Msi(_T("Set Register Success HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"));
}
/*
if (::RegSetValueEx(hKey,szTempFile,NULL,REG_SZ,(CONST BYTE*)szVal,dwSize) == ERROR_SUCCESS )
{
Log2Msi(_T("Set Register Success Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"));
}
*/
RegCloseKey(hKey);
hKey = NULL;
}
Log2Msi(szTempFile);
// create the actual temp file and get its handle. We'll use the handle to write data to
// this file.
// Get handle to msi database
if(nCreateFile==0)
{
Log2Msi(_T("nCreateFile==0 不创建文件"));
return;
}
if(PathFileExists(szTempFile) != FALSE)
{
DeleteFile(szTempFile);
Log2Msi(_T("删除老的文件,让新的文件可以覆盖:%s"),szTempFile);
}
PMSIHANDLE hDB;
hDB = MsiGetActiveDatabase(hInstall);
if (NULL == hDB)
{
Log2Msi(_T("MsiGetActiveDatabase failed"));
//return szTempFile;
return ;
}
// prepare query to retrieve the WDS setup binary from the MSI package.
PMSIHANDLE hView;
TCHAR cmdText[512] = {0};
//wsprintf(cmdText, _T("SELECT `Data` FROM `Binary` WHERE `Name` = 'gacutil' "), lpszBinaryFielName);//WHERE `Name` = 'gacutil'
wsprintf(cmdText, _T("SELECT `Data` FROM `Binary` WHERE `Name` = '%s' "), lpszBinaryFielName);//WHERE `Name` = 'gacutil'
if (ERROR_SUCCESS != MsiDatabaseOpenView(hDB,
cmdText,
&hView)
||
ERROR_SUCCESS != MsiViewExecute(hView, 0))
{
// add code for logging the failure if needed
Log2Msi(_T("MsiDatabaseOpenView:%s failed"),cmdText);
//return szTempFile;
return ;
}
// Fetch data from query result
PMSIHANDLE hRec;
uRes = MsiViewFetch(hView, &hRec);
if (uRes != ERROR_SUCCESS)
{
// add code for logging the failure if needed
Log2Msi(_T("MsiViewFetch failed:%s error:%d"),cmdText,uRes);
//return szTempFile;
return ;
}
// extract binary data from windows desktop search setup record
HANDLE hFile = 0;
hFile = CreateFile(szTempFile, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
// add code for logging the failure if needed
Log2Msi(_T("CreateFile:%s failed"),szTempFile);
//return szTempFile;
return ;
}
char szBuff[MAX_BUFFER*2];
DWORD dwBuffSize;
DWORD dwBytesWritten;
do {
// Extract binary data to buffer
dwBuffSize = MAX_BUFFER*2;
uRes = MsiRecordReadStream(hRec, 1, szBuff, &dwBuffSize);
if (ERROR_SUCCESS != uRes)
{
// add code for logging the failure if needed
Log2Msi(_T("MsiRecordReadStream failed"));
break;
}
if(dwBuffSize)
{
// write the chunk of the binary data to disk
if ( !WriteFile(hFile, szBuff, dwBuffSize, &dwBytesWritten, NULL) )
{
// add code for logging the failure if needed
Log2Msi(_T("WriteFile failed"));
break;
}
}
}
while (dwBuffSize > 0);
CloseHandle(hFile);
::MsiViewClose(hView);
::MsiCloseHandle(hRec);
::MsiCloseHandle(hDB);
Log2Msi(_T("szTempFile:%s"),szTempFile);
return ;
}
void rollbackSingleFile(LPCTSTR src)
{
TCHAR* pBuffer = NULL;
DWORD cchData = 0;
UINT uiState = ERROR_SUCCESS;
const TCHAR* szStep = _T("#");
TCHAR pszLine[MAX_PATH] = {0};
TCHAR* pszShortName= NULL;
TCHAR* pszFileKey = NULL;
TCHAR* pszFlag = NULL;
TCHAR pszFullFileKey[MAX_PATH+1] = {0};
//TCHAR pszFullFileKey[MAX_PATH+1] = {0};
lstrcpy(pszLine, src);
pszShortName = _tcstok(pszLine, szStep);
pszFileKey = _tcstok(NULL, szStep);
pszFlag = _tcstok(NULL, szStep);
if (pszShortName == NULL || pszFileKey == NULL)
{
Log2Msi(_T("CCA- Invalid Parameters!"));
return;
}
Log2Msi(_T("CCA- Rollback Single File Begin"));
for (LPTSTR pszFetoh=pszFileKey; pszFetoh != NULL && *pszFetoh != _T('\0'); pszFetoh++)
{
if ((*pszFetoh) == _T('-'))
(*pszFetoh) = _T('_');
}
wsprintf(pszFullFileKey, _T("[#%s]"), pszFileKey);
PMSIHANDLE hRec = ::MsiCreateRecord(1);
::MsiRecordSetString(hRec, 0, pszFullFileKey);
uiState = ::MsiFormatRecord(g_hInstall, hRec, _T(""), &cchData);
if (uiState == ERROR_MORE_DATA)
{
pBuffer = new TCHAR[++cchData];
uiState = ::MsiFormatRecord(g_hInstall, hRec, pBuffer, &cchData);
if (uiState == ERROR_SUCCESS)
{
//
// 构造源文件全路径
//
TCHAR szSourceFilePath[MAX_PATH+1] = {0};
wsprintf(szSourceFilePath, _T("%s%s"), g_lpszBackupFilesPath, src);
//
// 还原文件
//
if (!MoveFileEx(szSourceFilePath, pBuffer, MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
{
Log2Msi(_T("CCA- MoveFileEx(%s,%s) failed! 0x%08X"), szSourceFilePath, pBuffer, GetLastError());
//
// 移动文件失败,可能的原因是文件正在使用,要求重新启动操作系统
// 以便在重起后,移动文件
TCHAR dir[_MAX_DIR];
_tsplitpath(pBuffer,NULL,dir,NULL,NULL);
if (PathFileExists(dir) == FALSE && CreateDirectory(dir, NULL))
{
if (!MoveFileEx(szSourceFilePath, pBuffer, MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
{
Log2Msi(_T("CCA- MoveFileEx(%s,%s) failed! 0x%08X"), szSourceFilePath, pBuffer, GetLastError());
g_fNeedReBoot = TRUE;
MoveFileEx(szSourceFilePath, pBuffer, MOVEFILE_DELAY_UNTIL_REBOOT | MOVEFILE_REPLACE_EXISTING);
}
}
else
{
g_fNeedReBoot = TRUE;
MoveFileEx(szSourceFilePath, pBuffer, MOVEFILE_DELAY_UNTIL_REBOOT | MOVEFILE_REPLACE_EXISTING);
}
}
else
Log2Msi(_T("CCA- MoveFileEx(%s,%s) successed!"), szSourceFilePath, pBuffer);
if (pszFlag != NULL)
{
if ((pszFlag[0] == _T('R') || pszFlag[0] == _T('r')) && (pszFlag[1] == _T('G') || pszFlag[1] == _T('g')))
{
//
// 注册COM组件,失败写入日志, 直接调用DllRegisterServer将COM信息写入注册表
//
if(RegisterDllOcx(pBuffer))
Log2Msi(_T("CCA- RegisterDllOcx(%s) successed!"), szSourceFilePath);
}
if ((pszFlag[0] == _T('G') || pszFlag[0] == _T('g')) && (pszFlag[1] == _T('C') || pszFlag[1] == _T('c')))
{
//
// 注册到GAC中,失败写入日志,直接调用gacutil将dll信息写入GAC中
//
TCHAR strCommandLine[MAX_PATH+1] = {0};
//wsprintf(strCommandLine,_T("-i %s -f"),pBuffer);
wsprintf(strCommandLine,_T("-ir \"%s\" OPAQUE \"UFIDA U8 CUSTOM\" \"UFIDA U8 INSTALL\" -f"),pBuffer);
TCHAR strTmpFile[MAX_PATH];
BinaryFileTempPath(g_hInstall,_T("gacutil"),strTmpFile,1);
if (GetProcessReturn(
strTmpFile,strCommandLine, SW_HIDE)==0)
{
DeleteFile(strTmpFile);
Log2Msi(_T("CCA- GetProcessReturn(gacutil.exe,%s) successed!"), strCommandLine );
}
}
}
}
}
RELEASE(pBuffer)
MsiCloseHandle(hRec);
Log2Msi(_T("CCA- Rollback Single File End"));
}
//
//
//
//
BOOL rollbackFiles(LPCTSTR lpszPath)
{
TCHAR szFullPath[MAX_PATH+1] = {0};
TCHAR szSourceFile[MAX_PATH+1] = {0}; // 源文件路经
TCHAR szDestFile[MAX_PATH+1] = {0}; // 目标文件路经
UINT nFlag = 0; // 处理类型
WIN32_FIND_DATA FindFileData;
HANDLE hFind = NULL;
lstrcpy(szFullPath, lpszPath);
lstrcat(szFullPath, _T("*.*"));
Log2Msi(_T("CCA- ReadBackFiles Begin!"));
hFind = FindFirstFile(szFullPath, &FindFileData);
if (hFind != INVALID_HANDLE_VALUE)
{
while (1)
{
Log2Msi(_T("CCA- Process file:%s!"), FindFileData.cFileName);
if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
rollbackSingleFile(FindFileData.cFileName);
}
if (!FindNextFile(hFind, &FindFileData))
break;
}
}
Log2Msi(_T("CCA- ReadBackFiles End!"));
return TRUE;
}
//
// RollbackBackupFiles
//
// 尝试着还原安装前已经备份的原始文件
//
UINT __stdcall RollbackBackupFiles(MSIHANDLE hInstall)
{
//
// 假设不需要重新启动操作系统
//
g_fNeedReBoot = FALSE;
g_hInstall = hInstall;
Log2Msi(_T("CCA- RollbackBackupFiles Begin!"));
if (getBackupFilesPath(hInstall))
rollbackFiles(g_lpszBackupFilesPath);
//
// clean up
//
RELEASE(g_lpszBackupFilesPath);
//
// 通知安装包反安装完成后,因为一些文件无法覆盖,
// 需要重新启动操作系统
//
if (g_fNeedReBoot)
{
::MsiSetProperty(hInstall, _T("REBOOT"), _T("Force"));
}
Log2Msi(_T("CCA- RollbackBackupFiles End!"));
return ERROR_SUCCESS;
}
UINT __stdcall SetRegPolicyScopeValue(MSIHANDLE hInstall)
{
g_hInstall=hInstall;
Log2Msi(_T("SetRegPolicyScopeValue Start!"));
HKEY hKey = NULL;
DWORD dwVal = 1;
DWORD dwSize = sizeof(dwVal);
TCHAR lpKey[] = _T("SOFTWARE\\Policies\\Microsoft\\windows\\safer\\codeidentifiers");
DWORD dwAccess = KEY_ALL_ACCESS;
//HKLM SOFTWARE\\Policies\\Microsoft\\windows\\safer\\codeidentifiers integer PolicyScope 00000001
//RegCreateKeyEx(hRootKey, lpszRegPath, 0, NULL, REG_OPTION_NON_VOLATILE, dwAccess, NULL, &hKey, NULL)
if ( ::RegCreateKeyEx( HKEY_LOCAL_MACHINE,lpKey,NULL,NULL,REG_OPTION_NON_VOLATILE, dwAccess,NULL, &hKey,NULL) != ERROR_SUCCESS )
{
Log2Msi(_T("SetRegPolicyScopeValue CreateKey Failed!"));
return FALSE;
}
if ( ::RegSetValueEx( hKey,_T("PolicyScope"),NULL,REG_DWORD,(LPBYTE)&dwVal,dwSize) != ERROR_SUCCESS )
{
RegCloseKey(hKey);
hKey = NULL;
Log2Msi(_T("SetRegPolicyScopeValue SetValue Failed!"));
return FALSE;
}
if (hKey)
{
RegCloseKey(hKey);
hKey = NULL;
}
Log2Msi(_T("SetRegPolicyScopeValue Suc!"));
Log2Msi(_T("net stop msiserver start !"));
TCHAR strCommandLine[MAX_PATH+1] = {0};
wsprintf(strCommandLine,_T(" stop msiserver"));
GetProcessReturn(_T("net.exe"),strCommandLine, SW_SHOW,60000);
Log2Msi(_T("net stop msiserver end !"));
Log2Msi(_T("net start msiserver start !"));
TCHAR strCommandLinestart[MAX_PATH+1] = {0};
wsprintf(strCommandLinestart,_T(" start msiserver"));
GetProcessReturn(_T("net.exe"),strCommandLinestart, SW_SHOW,60000);
Log2Msi(_T(" net start msiserver end !"));
return TRUE;
}
//
// DependChecked
//
// 补丁依赖性检查
//
UINT __stdcall DependChecked(MSIHANDLE hInstall)
{
TCHAR* szCAData = NULL;
TCHAR* szRegPath = NULL;
TCHAR* szCurr = NULL;
BOOL fChecked = FALSE;
TCHAR szBuffer[1024] = {0};
UINT uiRet = ERROR_SUCCESS;
// Log2Msi(_T("CCA- DependChecked Start!"));
//uiRet = ERROR_INSTALL_USEREXIT;
return uiRet;
szCAData = getProperty(hInstall, PROPERTYNAME_DEPENDLIST);
szRegPath = getProperty(hInstall, PROPERTYNAME_PATCHREGROOT);
if ((szCAData != NULL || szRegPath != NULL) && lstrlen(szCAData) > 0)
{
szCurr = szCAData;
for (LPTSTR p=szCAData; *p != _T('\0'); p++)
{
if (*p == _T(','))
{
*p = _T('\0');
wsprintf(szBuffer, _T("%s\\%%s"), szRegPath, szCurr);
Log2Msi(_T("CCA- DependCheck %s"), szBuffer);
if (lstrlen(szBuffer) > 0)
{
HKEY hKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
{
fChecked = TRUE;
break;
}
RegCloseKey(hKey);
}
szCurr = p+1;
}
}
}
if (fChecked)
{
eMessageType = INSTALLMESSAGE_FATALEXIT;
Log2Msi(_T("[ProductName] 无法安装,因为相关补丁[dependlist]不存在"));
eMessageType = INSTALLMESSAGE_INFO;
uiRet = ERROR_INSTALL_USEREXIT;
}
//::MsiSetProperty(hInstall, _T("DependChecked"), (fChecked ? _T("1") : _T("0")));
Log2Msi(_T("CCA- DependChecked End!"));
return uiRet;
}
//得到补丁的问题号
BOOL getSPIDValue(MSIHANDLE hInstall)
{
g_spid = getProperty(hInstall, _T("SPID") );
return (g_spid != NULL);
/*
TCHAR* szCAData = NULL;
DWORD cchCAData = 0;
UINT uiState = ERROR_SUCCESS;
//
// 尝试获取属性的长度,然后分配内存
//
uiState = ::MsiGetProperty(hInstall, _T("SPID"), _T(""), &cchCAData);
if (uiState == ERROR_MORE_DATA)
{
//
// 分配内存
//
g_spid = new TCHAR[++cchCAData];
//
// 得到属性值
//
uiState = ::MsiGetProperty(hInstall, _T("SPID"), g_spid, &cchCAData);
if (uiState != ERROR_SUCCESS)
{
//
// 失败释放内存,返回失败
//
RELEASE(g_spid)
return FALSE;
}
return TRUE;
}
else
{
return FALSE;
}
*/
}
//得到DBEnginSys的路径
BOOL DBEnginSysPath(MSIHANDLE hInstall)
{
/*
TCHAR* szCAData = NULL;
DWORD cchCAData = 0;
DWORD cchData = 0;
UINT uiState = ERROR_SUCCESS;
TCHAR* pBuffer = NULL;
*/
TCHAR* pBuffer = NULL;
pBuffer= getProperty(hInstall, _T("TARGETDIR") );
if (pBuffer != NULL)
{
g_dbEnginPath = new TCHAR[MAX_PATH];
if(pBuffer[lstrlen(pBuffer)-1] == '\\') //删除结尾的'\'
wsprintf(g_dbEnginPath, _T("%s%s"), pBuffer,"Admin\\UFDBTMP\\DBEnginSys.exe");
else
wsprintf(g_dbEnginPath, _T("%s%s"), pBuffer,"\\Admin\\UFDBTMP\\DBEnginSys.exe");
}
RELEASE(pBuffer);
return (g_dbEnginPath != NULL);
//
// 尝试获取属性的长度,然后分配内存
//
/*
uiState = ::MsiGetProperty(hInstall, _T("DBEnginSysPath"), _T(""), &cchCAData);
if (uiState == ERROR_MORE_DATA)
{
//
// 分配内存
//
pBuffer = new TCHAR[++cchCAData];
//
// 得到属性值
//
uiState = ::MsiGetProperty(hInstall, _T("DBEnginSysPath"), pBuffer, &cchCAData);
if (uiState != ERROR_SUCCESS)
{
//
// 失败释放内存,返回失败
//
//TCHAR szError[1024] = {0};
//wsprintf(szError, _T("%d %s"), uiState, pBuffer);
//OutputDebugString(szError);
RELEASE(pBuffer);
return FALSE;
}
//OutputDebugString(pBuffer);
}
PMSIHANDLE hRec = ::MsiCreateRecord(1);
::MsiRecordSetString(hRec, 0, pBuffer);
uiState = ::MsiFormatRecord(hInstall, hRec, _T(""), &cchData);
if (uiState == ERROR_MORE_DATA)
{
g_dbEnginPath = new TCHAR[++cchData];
uiState = ::MsiFormatRecord(hInstall, hRec, g_dbEnginPath, &cchData);
if (uiState != ERROR_SUCCESS)
{
RELEASE(pBuffer)
RELEASE(g_dbEnginPath);
return FALSE;
}
//OutputDebugString(g_dbEnginPath);
}
RELEASE(pBuffer)
MsiCloseHandle(hRec);
return TRUE;
*/
}
//得到DSetPatchInfoToSqlLite的路径
BOOL DSetPatchInfoToSqlLitePath(MSIHANDLE hInstall)
{
TCHAR* pBuffer = NULL;
pBuffer= getProperty(hInstall, _T("TARGETDIR") );
if (pBuffer != NULL)
{
g_sqllitepathinfoPath = new TCHAR[MAX_PATH];
if(pBuffer[lstrlen(pBuffer)-1] == '\\') //删除结尾的'\'
wsprintf(g_sqllitepathinfoPath, _T("%s%s"), pBuffer,"3rdPrograms\\UFFileInformation\\SetPatchInfoToSqlLite.exe");
else
wsprintf(g_sqllitepathinfoPath, _T("%s%s"), pBuffer,"\\3rdPrograms\\UFFileInformation\\SetPatchInfoToSqlLite.exe");
}
RELEASE(pBuffer);
return (g_sqllitepathinfoPath != NULL);
}
//得到DSetPatchInfoToSqlLite的路径
BOOL DSetPatchInfoToSqlLitePathUninstall(MSIHANDLE hInstall)
{
TCHAR* pBuffer = NULL;
pBuffer= getProperty(hInstall, _T("TARGETDIR") );
if (pBuffer != NULL)
{
g_exerunPath = new TCHAR[MAX_PATH];
if(pBuffer[lstrlen(pBuffer)-1] == '\\') //删除结尾的'\'
wsprintf(g_exerunPath, _T("%s%s"), pBuffer,"3rdPrograms\\UFFileInformation\\SetPatchInfoToSqlLiteUninstall.exe");
else
wsprintf(g_exerunPath, _T("%s%s"), pBuffer,"\\3rdPrograms\\UFFileInformation\\SetPatchInfoToSqlLiteUninstall.exe");
}
RELEASE(pBuffer);
return (g_exerunPath != NULL);
}
/*
//临时增加的方法,执行U8Login.msi的卸载操作
UINT __stdcall ExcuteU8LoginMSI(MSIHANDLE hInstall)
{
Log2Msi(_T("CCA- ExcuteU8LoginMSI") );
CoInitialize(NULL);
BOOL bRet = FALSE;
try
{
_bstr_t bAppName = _bstr_t(_T("U8Login"));
ICOMAdminCatalogPtr spCatalog("COMAdmin.COMAdminCatalog");
ICatalogCollectionPtr spApplications;
spApplications = spCatalog->GetCollection (L"Applications");
spApplications->Populate ();
LONG count = 0;
spApplications->get_Count(&count);
for(INT i=0;i<count;i++)
{
HRESULT hr;
ICatalogObject* pObject = NULL;
hr = spApplications->get_Item(i,(IDispatch**)&pObject);
if(hr==S_OK)
{
VARIANT vName;
pObject->get_Name(&vName);
_bstr_t bName = _bstr_t(vName.bstrVal);
if(bName==bAppName)
{
spApplications->Remove(i);
}
pObject->Release();
}
}
HRESULT hr = spApplications->SaveChanges();
bRet = SUCCEEDED(hr);
}
catch(_com_error& err)
{
Log2Msi(_T("ComPlus U8login error: %s!"),err.Description());
}
catch(...)
{
Log2Msi(_T("ComPlus U8login error, LastError:0x%08X "),GetLastError());
}
CoUninitialize();
return ERROR_SUCCESS;
}
*/
//
//执行数据库引擎,
UINT __stdcall ExcuteDBEnginSys(MSIHANDLE hInstall)
{
//
g_hInstall=hInstall;
DWORD flag = -1;
TCHAR* pDBServer = NULL;
pDBServer= getProperty(hInstall, _T("FDBC") );
//如果不是数据库服务器不需要执行脚本
if (pDBServer == NULL || lstrlen(pDBServer)== 0)
{
RELEASE(pDBServer);
return ERROR_SUCCESS;
}
RELEASE(pDBServer);
if (getSPIDValue(hInstall) && DBEnginSysPath(hInstall))
{
TCHAR strCommandLine[MAX_PATH+1] = {0};
wsprintf(strCommandLine,_T("-q -n:%s"),g_spid);
OutputDebugString(strCommandLine);
OutputDebugString(g_dbEnginPath);
flag =GetProcessReturn(g_dbEnginPath,strCommandLine,SW_SHOW);
if (flag==0)
{
::MsiSetProperty(hInstall, _T("EXCUTEDBENGINSYS"), _T("1"));
OutputDebugString("EXCUTEDBENGINSYS:1");
}
else
{
::MsiSetProperty(hInstall, _T("EXCUTEDBENGINSYS"), _T("0"));
OutputDebugString("EXCUTEDBENGINSYS:0");
}
}
RELEASE(g_spid);
RELEASE(g_dbEnginPath);
return ERROR_SUCCESS;
}
void _stdcall CreateGUID(LPTSTR str)
{
GUID guid;
unsigned char* p;
::CoInitialize(NULL);
::CoCreateGuid(&guid);
::UuidToString(&guid, &p);
_stprintf(str, _T("{%s%}"), (char*)p);
_strupr(str);
::RpcStringFree(&p);
::CoUninitialize();
}
//添加卸载后注册表 GUID
BOOL SetSmartClientGUIDRegister(MSIHANDLE hInstall)
{
g_hInstall=hInstall;
OutputDebugString("SetSmartClientGUIDRegister Start!");
Log2Msi(_T("SetSmartClientGUIDRegister Start!"));
HKEY hKey = NULL;
//char* szVal=_T("WINSRV03SP1");
TCHAR buff [256] = {0};
CreateGUID(buff);
//char* szVal = getProperty(hInstall, _T("ProductCode") );
char* szVal=buff;
DWORD dwSize = _tcslen(szVal) * sizeof(TCHAR);
TCHAR lpKey[] = _T("SOFTWARE\\Ufsoft\\WF\\V8.700\\Install\\SmartGuid");
DWORD dwAccess = KEY_ALL_ACCESS;
//[HKEY_LOCAL_MACHINE\SOFTWARE\Ufsoft\WF\V8.700\Install\SmartGuid]
//"smartclient"="150661EA-AF70-4038-8E5C-F2C80BFE1D6B"
if ( ::RegCreateKeyEx( HKEY_LOCAL_MACHINE,lpKey,NULL,NULL,REG_OPTION_NON_VOLATILE, dwAccess,NULL, &hKey,NULL) != ERROR_SUCCESS )
{
OutputDebugString("SetSmartClientGUIDRegister CreateKey Failed!");
Log2Msi(_T("SetSmartClientGUIDRegister CreateKey Failed!"));
return FALSE;
}
if ( ::RegSetValueEx( hKey,_T("smartclient"),NULL,REG_SZ,(CONST BYTE*)szVal,dwSize) != ERROR_SUCCESS )
{
RegCloseKey(hKey);
hKey = NULL;
OutputDebugString("SetSmartClientGUIDRegister SetValue Failed!");
Log2Msi(_T("SetSmartClientGUIDRegister SetValue Failed!"));
return FALSE;
}
if (hKey)
{
RegCloseKey(hKey);
hKey = NULL;
}
Log2Msi(_T("SetSmartClientGUIDRegister Suc!"));
return TRUE;
}
//安装前执行文件信息导入数据库引擎, SetPatchInfoToSqlLite.exe
UINT __stdcall ExcuteSqlLiteSys(MSIHANDLE hInstall)
{
g_hInstall=hInstall;
DWORD flag = -1;
OutputDebugString("ExcuteSqlLiteSys");
if ( getSPIDValue(hInstall) && DSetPatchInfoToSqlLitePath(hInstall))
{
TCHAR strCommandLine[MAX_PATH+1] = {0};
wsprintf(strCommandLine,_T("-install %s"),g_spid);
OutputDebugString(strCommandLine);
OutputDebugString(g_sqllitepathinfoPath);
flag =GetProcessReturn(g_sqllitepathinfoPath,strCommandLine,SW_SHOW);
if (flag==0)
{
::MsiSetProperty(hInstall, _T("EXCUTESQLLITESYS"), _T("1"));
OutputDebugString("EXCUTESQLLITESYS:1");
//设置注册表。
DWORD dwExitCode = -1;
try
{
SetSmartClientGUIDRegister(hInstall);
}
catch(...)
{
dwExitCode=::GetLastError();
Log2Msi(_T("SetSmartClientGUIDRegister error, LastError:0x%08X "),dwExitCode);
}
}
else
{
::MsiSetProperty(hInstall, _T("EXCUTESQLLITESYS"), _T("0"));
OutputDebugString("EXCUTESQLLITESYS:0");
}
}
RELEASE(g_spid);
RELEASE(g_sqllitepathinfoPath);
return ERROR_SUCCESS;
}
//安装后执行EXE SetPatchInfoToSqlLite.exe
UINT __stdcall UninstallExcuteEnginSys(MSIHANDLE hInstall)
{
//设置注册表。
DWORD dwExitCode = -1;
try
{
SetSmartClientGUIDRegister(hInstall);
}
catch(...)
{
dwExitCode=::GetLastError();
Log2Msi(_T("Remove SetSmartClientGUIDRegister error, LastError:0x%08X "),dwExitCode);
}
g_hInstall=hInstall;
DWORD flag = -1;
OutputDebugString("UninstallExcuteEnginSys");
if (getSPIDValue(hInstall) && DSetPatchInfoToSqlLitePathUninstall(hInstall))
{
TCHAR strCommandLine[MAX_PATH+1] = {0};
wsprintf(strCommandLine,_T("-uninstall %s"),g_spid);
OutputDebugString(strCommandLine);
OutputDebugString(g_exerunPath);
flag =GetProcessReturn(g_exerunPath,strCommandLine,SW_SHOW);
if (flag==0)
{
::MsiSetProperty(hInstall, _T("EXCUTEEXESYS"), _T("1"));
OutputDebugString("EXCUTEEXESYS:1");
}
else
{
::MsiSetProperty(hInstall, _T("EXCUTEEXESYS"), _T("0"));
OutputDebugString("EXCUTEEXESYS:0");
}
}
RELEASE(g_spid);
RELEASE(g_exerunPath);
return ERROR_SUCCESS;
}
LONG GetFileDateTime(LPCTSTR fileName,tm& filetm)
{
WIN32_FILE_ATTRIBUTE_DATA fileData;
BOOL result = ::GetFileAttributesEx(fileName, GetFileExInfoStandard, &fileData);
if (result == FALSE)
{
//OutputDebugString(_T("GetFileAttributesEx call false"));
return ::GetLastError();
}
FILETIME filetime = fileData.ftLastWriteTime;
SYSTEMTIME systime;
FILETIME localtime;
::FileTimeToLocalFileTime(&filetime, &localtime);
::FileTimeToSystemTime(&localtime, &systime);
filetm.tm_year = systime.wYear- 1900;
filetm.tm_mon = systime.wMonth - 1;
filetm.tm_mday = systime.wDay;
filetm.tm_hour = systime.wHour;
filetm.tm_min = systime.wMinute;
filetm.tm_sec = systime.wSecond;
filetm.tm_isdst=-1;
// wsprintf(buf, _T("%4d%02d%02d%02d%02d%02d"),systime.wYear, systime.wMonth, systime.wDay
// ,systime.wHour, systime.wMinute, systime.wSecond);
return 0;
}
//
// CompareFileDateTime
//
// 比较安装盘文件和系统已经存在文件的新旧,srcFileName指安装包的文件,desFileName指本机已经存在的文件
//
LONG CompareFileDateTime(LPCTSTR srcFileName, LPCTSTR desFileName,LPCTSTR remove)
{
LPTSTR srcTime = _tcsrchr(srcFileName, _T('.'));
srcTime++;
//TCHAR desTime[15]={0};
struct tm destm;
//if (desFileName==NULL ||lstrlen(desFileName)==0) return -1;
//如果文件名查找不到,采用默认策略,不处理,目前出现的问题是放到GAC的文件,在本地没有副本
Log2Msi(_T("desFileName %s!"),desFileName);
//if (desFileName==NULL ||lstrlen(desFileName)==0) return -1;
if (desFileName==NULL ||lstrlen(desFileName)==0) return 1;
LONG hr = ::GetFileDateTime(desFileName, destm);
//如果 remove=ALL 删除文件。
if (remove != NULL && lstrlen(remove)!= 0 && _tcscmp(remove,_T("ALL"))==0)
{
if (hr != 0) //卸载安装包的时候,虽然本机文件出错,但安装包的文件一定不能安装
{
return -1;
}
}
else
{
if (hr != 0) //如果本机文件出错,要求安装包的文件一定要安装
return 1;
}
struct tm srctm;
time_t srctimet,destimet;
_stscanf(srcTime," %4d%02d%02d%02d%02d%02d",&srctm.tm_year,&srctm.tm_mon,&srctm.tm_mday,&srctm.tm_hour,&srctm.tm_min,&srctm.tm_sec);
srctm.tm_year=srctm.tm_year-1900;
srctm.tm_mon=srctm.tm_mon-1;
srctm.tm_isdst =-1;
srctimet=mktime(&srctm);
destimet=mktime(&destm);
//srcTime[12] = _T('\0');
//desTime[12] = _T('\0');
//result=srctimet(MSI包中的文件的日期)-destimet(本地计算机上已经存在的文件的日期)
double result =difftime(srctimet,destimet);
if ( result > -61.0 && result < 61.0)
{
return 0;
}
else
{
return (LONG)result;
}
//return _tcscmp(srcTime, desTime);
}
//
// GetSetupFileSets
//得到需要安装的文件集合
//
//
void GetSetupFileSets(MSIHANDLE hInstall)
{
TCHAR* setupfilepath=NULL;
TCHAR* spid=NULL;
TCHAR* pBuffer = NULL;
pBuffer= getProperty(hInstall, _T("TARGETDIR") );
if (pBuffer != NULL)
{
setupfilepath = new TCHAR[MAX_PATH];
spid = getProperty(hInstall, _T("SPID") );
if (spid != NULL)
{
if(pBuffer[lstrlen(pBuffer)-1] == '\\') //删除结尾的'\'
wsprintf(setupfilepath, _T("%s%s%s%s"), pBuffer,_T("Installer\\"),spid,_T(".config"));
else
wsprintf(setupfilepath, _T("%s%s%s%s"), pBuffer,_T("\\Installer\\"),spid,_T(".config"));
}
OutputDebugString(_T("setupfilepath%s"));
OutputDebugString(setupfilepath);
}
RELEASE(pBuffer);
RELEASE(spid);
char SetupFile[255];
ifstream fin(setupfilepath);
if (fin)
{
while(fin.getline(SetupFile, 255))
{
g_setupfilesets.insert(_strlwr(SetupFile));
}
}
RELEASE(setupfilepath);
}
//对于那些需要保留老状态的情况,需要区分安装和卸载两种情况
void RetainComponentState(MSIHANDLE hInstall,LPCTSTR lpszComponentName,LPCTSTR remove,LPCTSTR srcfilePath)
{
if (remove != NULL && lstrlen(remove)!= 0 && _tcscmp(remove,_T("ALL"))==0)
{
::MsiSetComponentState(hInstall,lpszComponentName,INSTALLSTATE_ABSENT);
Log2Msi(_T("remove=ALL,uninstalled.%s"),srcfilePath);
}
else
{
Log2Msi(_T("retain old state:%s"),srcfilePath);
}
}
//
// CompareFileDate
//
// 解决安装盘文件和系统已经存在文件的新旧问题,如果系统已经存在文件的修改日期较新,则不覆盖
//
UINT __stdcall CompareFilesDate(MSIHANDLE hInstall)
{
g_hInstall=hInstall;
//Log2Msi(_T("CCA- CompareFilesDate Begin!"));
UINT uiState = ERROR_SUCCESS;
PMSIHANDLE hRecordprop=NULL;
TCHAR* remove = NULL;
TCHAR* comparedate = NULL;//是否需要比较文件日期.="N",不进行日期对比 缺省情况下进行日期对比
TCHAR* depend = NULL;//是否是依赖安装=1 依赖安装 =0 完全安装 缺省情况下完全安装
TCHAR* caremove = NULL;
PMSIHANDLE hDB=NULL;
PMSIHANDLE hViewprop=NULL;
comparedate= getProperty(hInstall, _T("CACOMPAREDATE") );
depend= getProperty(hInstall, _T("CADEPEND") );
caremove= getProperty(hInstall, _T("CAREMOVE") );
Log2Msi(_T("property CACOMPAREDATE:%s CADEPEND:%s"),comparedate,depend);
//不需要日期对比,且不是依赖安装,直接退出函数.提高效率
if (comparedate != NULL && lstrlen(comparedate)!= 0 && _tcscmp(comparedate,_T("N"))==0)
{
if (depend == NULL || lstrlen(depend)== 0 ||_tcscmp(depend,_T("0"))==0)
{
return ERROR_SUCCESS;
}
}
remove= getProperty(hInstall, _T("REMOVE") );
//依赖安装
if (depend != NULL && _tcscmp(depend,_T("1"))==0)
{
GetSetupFileSets(hInstall);//获得需要安装的文件集合
}
hDB = ::MsiGetActiveDatabase(hInstall);
::MsiDatabaseOpenView(hDB,
_T("SELECT * FROM `File`"), &hViewprop);
::MsiViewExecute(hViewprop, 0);
while (::MsiViewFetch(hViewprop, &hRecordprop) != ERROR_NO_MORE_ITEMS)
{
DWORD cchData = 0;
DWORD ccData = 0;
TCHAR srcfilePath[MAX_PATH]={0};
ccData=sizeof(srcfilePath) ;
::MsiRecordGetString(hRecordprop, 1, srcfilePath, &ccData);
OutputDebugString(srcfilePath);
TCHAR componentName[MAX_PATH]={0};
ccData=sizeof(componentName) ;
::MsiRecordGetString(hRecordprop, 2, componentName, &ccData);
TCHAR pszFullFileKey[MAX_PATH+3] = {0};
wsprintf(pszFullFileKey, _T("[#%s]"), srcfilePath);
PMSIHANDLE hRec = ::MsiCreateRecord(1);
::MsiRecordSetString(hRec, 0, pszFullFileKey);
uiState = ::MsiFormatRecord(hInstall, hRec, _T(""), &cchData);
if (uiState == ERROR_MORE_DATA)
{
TCHAR* desfilePath = new TCHAR[++cchData];
uiState = ::MsiFormatRecord(hInstall, hRec, desfilePath, &cchData);
if (uiState != ERROR_SUCCESS)
{
RELEASE(desfilePath);
return ERROR_SUCCESS;
}
Log2Msi(_T("desfilePath:%s"),desfilePath);
//安装依赖文件
if (depend != NULL && _tcscmp(depend,_T("1"))==0)
{
set<string>::iterator it = g_setupfilesets.find(_strlwr(desfilePath));
if( g_setupfilesets.size()==0 ||it != g_setupfilesets.end() ) //等于end就是没有找到
{
//::MsiGetComponentState(hInstall,componentName,&piInstalled,&piAction);
//Log2Msi(_T("Get Component %s State.%d %d"),srcfilePath,piInstalled,piAction);
//不比较日期 comparedate=N
if (comparedate != NULL && lstrlen(comparedate)!= 0 && _tcscmp(comparedate,_T("N"))==0)
{
//Log2Msi(_T("not compare date.retain old state:%s"),srcfilePath);
//保留老的状态。
RetainComponentState(hInstall,componentName,remove,srcfilePath);
}
else
{
LONG flag=CompareFileDateTime(srcfilePath,desfilePath,remove);
//=符号,强制覆盖,为了修改安装,不卸载文件使用
if(flag<0)
{
if (remove != NULL && lstrlen(remove)!= 0 && _tcscmp(remove,_T("ALL"))==0
&& caremove != NULL && lstrlen(caremove)!= 0 &&_tcscmp(caremove,_T("NO"))==0
&& flag!=-1)
{
//INSTALLSTATE_LOCAL ==The component is installed locally.
::MsiSetComponentState(hInstall,componentName,INSTALLSTATE_LOCAL);
//如果本地文件比安装盘文件新,则不允许安装盘卸载此文件
Log2Msi(_T("flag<0,don't remove1.%s"),srcfilePath);
}
else
{
//INSTALLSTATE_ABSENT==The component is not installed.
::MsiSetComponentState(hInstall,componentName,INSTALLSTATE_ABSENT);
Log2Msi(_T("flag<0,uninstalled1.%s"),srcfilePath);
}
//Log2Msi(_T("flag<0,uninstalled.%s"),srcfilePath);
}
else if(flag==0)
{
//Log2Msi(_T("flag>=0.retain old state:%s"),srcfilePath);
//如果remove=all 执行 INSTALLSTATE_ABSENT 不处理;安装不处理。
RetainComponentState(hInstall,componentName,remove,srcfilePath);
}
else
{
//保留老的状态。
Log2Msi(_T("flag>0.retain old state:%s"),srcfilePath);
}
}
}
else
{
//此组件不安装 INSTALLSTATE_ABSENT==The component is not installed.
::MsiSetComponentState(hInstall,componentName,INSTALLSTATE_ABSENT);
Log2Msi(_T("this file doesn't exist in config file ,uninstalled.%s"),srcfilePath);
}
}
//不是依赖安装
else
{
LONG flag=CompareFileDateTime(srcfilePath,desfilePath,remove);
//本地文件比较新
if(flag<0)
{
//卸载
if (remove != NULL && lstrlen(remove)!= 0 && _tcscmp(remove,_T("ALL"))==0
&& caremove != NULL && lstrlen(caremove)!= 0 &&_tcscmp(caremove,_T("ALL"))==0
&& flag!=-1)
{
//如果本地文件比安装盘文件新,替换安装到本地新的文件。
::MsiSetComponentState(hInstall,componentName,INSTALLSTATE_LOCAL);
//如果本地文件比安装盘文件新,则不允许安装盘卸载此文件
Log2Msi(_T("flag<0,don't remove2.%s"),srcfilePath);
}
else
{
//如果是安装,不安装此文件 保持本地文件新的。
::MsiSetComponentState(hInstall,componentName,INSTALLSTATE_ABSENT);
Log2Msi(_T("flag<0,uninstalled2.%s"),srcfilePath);
}
//::MsiSetComponentState(hInstall,componentName,INSTALLSTATE_ABSENT);
//Log2Msi(_T("flag<0,uninstalled.%s"),srcfilePath);
}
else if (flag==0)
{
//Log2Msi(_T("flag>=0.retain old state:%s"),srcfilePath);
//如果remove=all 执行 INSTALLSTATE_ABSENT 保留老的状态 相反替换。
RetainComponentState(hInstall,componentName,remove,srcfilePath);
}
else
{
Log2Msi(_T("flag>0.retain old state:%s"),srcfilePath);
}
}
RELEASE(desfilePath)
}
::MsiCloseHandle(hRec);
}
::MsiViewClose(hViewprop);
::MsiCloseHandle(hRecordprop);
::MsiCloseHandle(hDB);
RELEASE(remove);
RELEASE(comparedate);
RELEASE(depend);
RELEASE(caremove);
//Log2Msi(_T("CCA- CompareFilesDate End!"));
return ERROR_SUCCESS;
}
//得到File的绝对路径
void FilePath(MSIHANDLE hInstall,LPCTSTR lpszFileKey,LPTSTR szFilePath)
{
TCHAR pszFullFileKey[MAX_PATH+3] = {0};
UINT uiState = ERROR_SUCCESS;
DWORD cchData = 0;
wsprintf(pszFullFileKey, _T("[#%s]"), lpszFileKey);
PMSIHANDLE hRec = ::MsiCreateRecord(1);
::MsiRecordSetString(hRec, 0, pszFullFileKey);
uiState = ::MsiFormatRecord(hInstall, hRec, _T(""), &cchData);
if (uiState == ERROR_MORE_DATA)
{
uiState = ::MsiFormatRecord(hInstall, hRec, szFilePath, &cchData);
if (uiState == ERROR_SUCCESS)
{
Log2Msi(_T("szFilePath:%s"),szFilePath);
}
}
}
//卸载COm+服务,即使文件丢失也可以
DWORD UninstallCOMPLUS(LPCTSTR lpApplicationName)
{
DWORD dwExitCode = -1;
CoInitialize(NULL);
BOOL bRet = FALSE;
try
{
_bstr_t bAppName = _bstr_t(lpApplicationName);
ICOMAdminCatalogPtr spCatalog("COMAdmin.COMAdminCatalog");
ICatalogCollectionPtr spApplications;
spApplications = spCatalog->GetCollection (L"Applications");
spApplications->Populate ();
LONG count = 0;
spApplications->get_Count(&count);
for(INT i=0;i<count;i++)
{
HRESULT hr;
ICatalogObject* pObject = NULL;
hr = spApplications->get_Item(i,(IDispatch**)&pObject);
if(hr==S_OK)
{
VARIANT vName;
pObject->get_Name(&vName);
_bstr_t bName = _bstr_t(vName.bstrVal);
if(bName==bAppName)
{
spApplications->Remove(i);
}
pObject->Release();
}
}
HRESULT hr = spApplications->SaveChanges();
bRet = SUCCEEDED(hr);
}
catch(_com_error& err)
{
dwExitCode=err.WCode();
//dwExitCode=_com_error::WCodeToHRESULT(err.WCode());
Log2Msi(_T("Remove %s ComPlus error: %s!"),err.Description());
}
catch(...)
{
dwExitCode=::GetLastError();
Log2Msi(_T("Remove %s ComPlus error, LastError:0x%08X "),lpApplicationName,dwExitCode);
}
CoUninitialize();
return dwExitCode;
}
//安装结束,执行注册GAC等操作,通过属性传递相应的参数
/*
UINT __stdcall ExcuteApp(MSIHANDLE hInstall)
{
TCHAR* filepath = NULL;
TCHAR* remove = NULL;
g_hInstall=hInstall;
Log2Msi(_T("CCA- ExcuteApp"));
DWORD flag = -1;
filepath= getProperty(hInstall, _T("file_gacutil") );
Log2Msi(_T("CCA- ExcuteApp%s"),filepath);
const TCHAR* szStep = _T("#");
TCHAR* pszFileKey = NULL;
remove= getProperty(hInstall, _T("REMOVE") );
//如果查找不到,不需要处理
if (filepath != NULL && lstrlen(filepath)!= 0)
{
//TCHAR pszFullFileKey[MAX_PATH+1] = {0};
pszFileKey = _tcstok(filepath, szStep);
TCHAR strTmpFile[MAX_PATH];
BinaryFileTempPath(hInstall,_T("gacutil"),strTmpFile);
while (pszFileKey != NULL)
{
// 注册到GAC中,失败写入日志,直接调用gacutil将dll信息写入GAC中
//
TCHAR strCommandLine[MAX_PATH+1] = {0};
TCHAR strFilePath[MAX_PATH];
FilePath(hInstall,pszFileKey,strFilePath);
if (remove != NULL && lstrlen(remove)!= 0 && _tcscmp(remove,_T("ALL"))==0)
{
TCHAR fname[MAX_PATH];
_tsplitpath(strFilePath,NULL,NULL,fname,NULL);
wsprintf(strCommandLine,_T("-ur \"%s\" OPAQUE \"UFIDA U8 CUSTOM\" \"UFIDA U8 INSTALL\" -f"),fname);
GetProcessReturn(strTmpFile,strCommandLine, SW_HIDE,60000);
}
else
{
wsprintf(strCommandLine,_T("-ir \"%s\" OPAQUE \"UFIDA U8 CUSTOM\" \"UFIDA U8 INSTALL\" -f "),strFilePath);
if (PathFileExists(strFilePath) != FALSE)
{
Log2Msi(_T("GetProcessReturn PathFileExists true"));
GetProcessReturn(strTmpFile,strCommandLine, SW_HIDE,60000);
}
}
//Log2Msi(_T("CCA- GetProcessReturn(gacutil.exe,%s) successed!"), strCommandLine );
pszFileKey = _tcstok(NULL, szStep);
}
//DeleteFile(strTmpFile);
}
RELEASE(filepath);
if (remove == NULL || lstrlen(remove)== 0 || _tcscmp(remove,_T("ALL"))!=0)
{
filepath= getProperty(hInstall, _T("file_regasm") );
//如果查找不到,不需要处理
if (filepath != NULL && lstrlen(filepath)!= 0)
{
pszFileKey = _tcstok(filepath, szStep);
TCHAR strTmpFile[MAX_PATH];
BinaryFileTempPath(hInstall,_T("RegAsm"),strTmpFile);
while (pszFileKey != NULL)
{
TCHAR strCommandLine[MAX_PATH+1] = {0};
TCHAR strFilePath[MAX_PATH];
FilePath(hInstall,pszFileKey,strFilePath);
if (PathFileExists(strFilePath) != FALSE)
{
wsprintf(strCommandLine,_T("\"%s\" /codebase /silent"),strFilePath);
GetProcessReturn(strTmpFile,strCommandLine, SW_HIDE,60000);
}
//if (GetProcessReturn(strTmpFile,strCommandLine, SW_HIDE)==0)
// Log2Msi(_T("CCA- GetProcessReturn(RegAsm.exe,%s) successed!"), strCommandLine );
pszFileKey = _tcstok(NULL, szStep);
}
//DeleteFile(strTmpFile);
}
RELEASE(filepath);
filepath= getProperty(hInstall, _T("file_regasm40") );
//如果查找不到,不需要处理
if (filepath != NULL && lstrlen(filepath)!= 0)
{
pszFileKey = _tcstok(filepath, szStep);
TCHAR strTmpFile[MAX_PATH];
BinaryFileTempPath(hInstall,_T("RegAsm40"),strTmpFile);
while (pszFileKey != NULL)
{
TCHAR strCommandLine[MAX_PATH+1] = {0};
TCHAR strFilePath[MAX_PATH];
FilePath(hInstall,pszFileKey,strFilePath);
if (PathFileExists(strFilePath) != FALSE)
{
wsprintf(strCommandLine,_T("\"%s\" /codebase /silent"),strFilePath);
GetProcessReturn(strTmpFile,strCommandLine, SW_HIDE,60000);
}
//if (GetProcessReturn(strTmpFile,strCommandLine, SW_HIDE)==0)
// Log2Msi(_T("CCA- GetProcessReturn(RegAsm.exe,%s) successed!"), strCommandLine );
pszFileKey = _tcstok(NULL, szStep);
}
//DeleteFile(strTmpFile);
}
RELEASE(filepath);
}
filepath= getProperty(hInstall, _T("file_regsvcs") );
//filepath= getProperty(hInstall, _T("CustomActionData") );
Log2Msi(_T("CCA- ExcuteApp-regsvcs%s"),filepath);
//如果查找不到,不需要处理
if (filepath != NULL && lstrlen(filepath)!= 0)
{
pszFileKey = _tcstok(filepath, szStep);
TCHAR strTmpFile[MAX_PATH];
BinaryFileTempPath(hInstall,_T("RegSvcs"),strTmpFile);
//wsprintf(strTmpFile,_T("C:\\U8SOFT\\RegSvcs.exe"));
while (pszFileKey != NULL)
{
// 注册到complus中,失败写入日志,直接调用regsvcs将dll信息写入com+中
//
TCHAR strCommandLine[MAX_PATH+1] = {0};
TCHAR strFilePath[MAX_PATH];
FilePath(hInstall,pszFileKey,strFilePath);
if (remove != NULL && lstrlen(remove)!= 0 && _tcscmp(remove,_T("ALL"))==0)
{
TCHAR drive[_MAX_DRIVE];
TCHAR dir[_MAX_DIR];
TCHAR fname[_MAX_FNAME];
TCHAR tlbfilePath[_MAX_PATH];
_tsplitpath(strFilePath,drive, dir, fname, NULL);
UninstallCOMPLUS(fname);
_tmakepath(tlbfilePath,drive, dir, fname, _T("tlb") );
DeleteFile(tlbfilePath);
}
else
{
if (PathFileExists(strFilePath) != FALSE)
{
wsprintf(strCommandLine,_T("/fc /quiet \"%s\" "),strFilePath);
GetProcessReturn(strTmpFile,strCommandLine, SW_HIDE);
}
}
pszFileKey = _tcstok(NULL, szStep);
}
//DeleteFile(strTmpFile);
}
RELEASE(filepath);
RELEASE(remove);
return ERROR_SUCCESS;
}
*/
UINT __stdcall ExcuteApp(MSIHANDLE hInstall)
{
TCHAR* filepath = NULL;
TCHAR* ProcessEXE = NULL;
TCHAR* CustomActionData = NULL;
TCHAR* remove = NULL;
TCHAR* strFilePath= NULL;
const TCHAR* szStepSpace = _T(" ");
const TCHAR* szStep = _T("|");
TCHAR* pszFileKey = NULL;
g_hInstall=hInstall;
Log2Msi(_T("CCA- ExcuteApp"));
DWORD flag = -1;
filepath = new TCHAR[MAX_PATH*50];
ProcessEXE = new TCHAR[MAX_PATH];
remove= new TCHAR[MAX_PATH];
CustomActionData=getProperty(hInstall, _T("CustomActionData") );
Log2Msi(_T("CCA- ExcuteApp CustomActionData:%s"),CustomActionData);
if (CustomActionData != NULL && lstrlen(CustomActionData)!= 0)
{
pszFileKey = _tcstok(CustomActionData, szStepSpace);
//Log2Msi(_T("CCA- ExcuteApp pszFileKey:%s"),pszFileKey);
while (pszFileKey != NULL)
{
if (_tcsstr(pszFileKey,_T("/REMOVE="))!=NULL)
{
_tcscpy(remove,pszFileKey+8);
Log2Msi(_T("CCA- ExcuteApp remove:%s"),remove);
}
if (_tcsstr(pszFileKey,_T("/EXE=")) != NULL)
{
_tcscpy(ProcessEXE,pszFileKey+5);
Log2Msi(_T("CCA- ExcuteApp ProcessEXE:%s"),ProcessEXE);
}
if (_tcsstr(pszFileKey,_T("/FILEPATH=")) != NULL)
{
_tcscpy(filepath,pszFileKey+10);
Log2Msi(_T("CCA- ExcuteApp filepath:%s"),filepath);
}
pszFileKey = _tcstok(NULL, szStepSpace);
Log2Msi(_T("CCA- ExcuteApp pszFileKey:%s"),pszFileKey);
}
}
//TCHAR strFilePath[MAX_PATH];
//如果查找不到,不需要处理
if (filepath != NULL && lstrlen(filepath)!= 0)
{
strFilePath = _tcstok(filepath, szStep);
TCHAR strTmpFile[MAX_PATH];
Log2Msi(_T("GetRegisterExe: %s"),ProcessEXE);
BinaryFileTempPath(hInstall,ProcessEXE,strTmpFile,0);
Log2Msi(_T("GetRegisterExe: %s %s"),strTmpFile,ProcessEXE);
while (strFilePath != NULL)
{
// 注册到GAC中,失败写入日志,直接调用gacutil将dll信息写入GAC中
//
TCHAR strCommandLine[MAX_PATH+1] = {0};
if (ProcessEXE != NULL && lstrlen(ProcessEXE)!= 0 && _tcscmp(ProcessEXE,_T("gacutil"))==0)
{
if (remove != NULL && lstrlen(remove)!= 0 && _tcscmp(remove,_T("ALL"))==0)
{
TCHAR fname[MAX_PATH];
_tsplitpath(strFilePath,NULL,NULL,fname,NULL);
wsprintf(strCommandLine,_T("-ur \"%s\" OPAQUE \"UFIDA U8 CUSTOM\" \"UFIDA U8 INSTALL\" -f"),fname);
GetProcessReturn(strTmpFile,strCommandLine, SW_HIDE,60000);
}
else
{
wsprintf(strCommandLine,_T("-ir \"%s\" OPAQUE \"UFIDA U8 CUSTOM\" \"UFIDA U8 INSTALL\" -f "),strFilePath);
if (PathFileExists(strFilePath) != FALSE)
{
Log2Msi(_T("GetProcessReturn PathFileExists true"));
GetProcessReturn(strTmpFile,strCommandLine, SW_HIDE,60000);
}
}
}
if (ProcessEXE != NULL && lstrlen(ProcessEXE)!= 0 && _tcscmp(ProcessEXE,_T("RegAsm"))==0)
{
if (remove == NULL || lstrlen(remove)== 0 || _tcscmp(remove,_T("ALL"))!=0)
{
if (PathFileExists(strFilePath) != FALSE)
{
wsprintf(strCommandLine,_T("\"%s\" /codebase /silent"),strFilePath);
Log2Msi(_T("Ready to Register: %s"),strCommandLine);
GetProcessReturn(strTmpFile,strCommandLine, SW_HIDE,60000);
Log2Msi(_T("End to Register: %s %s"),strTmpFile,strCommandLine);
}
}
}
//v4.0.30319版本呢的RegAsm.exe生成TLB注册信息
if (ProcessEXE != NULL && lstrlen(ProcessEXE)!= 0 && _tcscmp(ProcessEXE,_T("RegAsm40"))==0)
{
if (remove == NULL || lstrlen(remove)== 0 || _tcscmp(remove,_T("ALL"))!=0)
{
if (PathFileExists(strFilePath) != FALSE)
{
wsprintf(strCommandLine,_T("\"%s\" /codebase /silent"),strFilePath);
Log2Msi(_T("Ready to Register: %s"),strCommandLine);
GetProcessReturn(strTmpFile,strCommandLine, SW_HIDE,60000);
Log2Msi(_T("End to Register: %s %s"),strTmpFile,strCommandLine);
}
}
}
if (ProcessEXE != NULL && lstrlen(ProcessEXE)!= 0 && _tcscmp(ProcessEXE,_T("RegSvcs"))==0)
{
if (remove != NULL && lstrlen(remove)!= 0 && _tcscmp(remove,_T("ALL"))==0)
{
TCHAR drive[_MAX_DRIVE];
TCHAR dir[_MAX_DIR];
TCHAR fname[_MAX_FNAME];
TCHAR tlbfilePath[_MAX_PATH];
_tsplitpath(strFilePath,drive, dir, fname, NULL);
UninstallCOMPLUS(fname);
_tmakepath(tlbfilePath,drive, dir, fname, _T("tlb") );
DeleteFile(tlbfilePath);
}
else
{
if (PathFileExists(strFilePath) != FALSE)
{
wsprintf(strCommandLine,_T("/fc /quiet \"%s\" "),strFilePath);
GetProcessReturn(strTmpFile,strCommandLine, SW_HIDE);
}
}
}
strFilePath = _tcstok(NULL, szStep);
}
}
RELEASE(filepath);
RELEASE(ProcessEXE);
RELEASE(CustomActionData);
RELEASE(remove);
RELEASE(strFilePath);
return ERROR_SUCCESS;
}
//安装结束,对于COM组件(EXE),使用/RegServer或-RegServer注册,通过属性传递相应的参数
//或者对于一些注册不成功的COM,使用regsvr32注册
UINT __stdcall ExcuteRegServer(MSIHANDLE hInstall)
{
g_hInstall=hInstall;
DWORD flag = -1;
TCHAR* filepath_regserver = NULL;
TCHAR* filepath_regsvr32 = NULL;
TCHAR* CustomActionData = NULL;
TCHAR* remove = NULL;
const TCHAR* szStep = _T("|");
//const TCHAR* szStepSpace = _T("\t");//\t
const TCHAR* szStepSpace = _T(" ");//
TCHAR* pszFileKey = NULL;
TCHAR* strFilePath =NULL;
filepath_regserver = new TCHAR[MAX_PATH*50];
filepath_regsvr32 = new TCHAR[MAX_PATH*50];
remove= new TCHAR[MAX_PATH];
CustomActionData=getProperty(hInstall, _T("CustomActionData") );
Log2Msi(_T("CCA- ExcuteApp CustomActionData:%s"),CustomActionData);
if (CustomActionData != NULL && lstrlen(CustomActionData)!= 0)
{
pszFileKey = _tcstok(CustomActionData, szStepSpace);
while (pszFileKey != NULL)
{
if (_tcsstr(pszFileKey,_T("/REMOVE="))!=NULL)
{
_tcscpy(remove,pszFileKey+8);
}
if (_tcsstr(pszFileKey,_T("/REGSERVER=")) != NULL)
{
_tcscpy(filepath_regserver,pszFileKey+11);
}
if (_tcsstr(pszFileKey,_T("/REGSVR=")) != NULL)
{
_tcscpy(filepath_regsvr32,pszFileKey+8);
}
pszFileKey = _tcstok(NULL, szStepSpace);
}
}
if (remove == NULL || lstrlen(remove)== 0 || _tcscmp(remove,_T("ALL"))!=0)
{
//如果查找不到,不需要处理
if (filepath_regserver != NULL && lstrlen(filepath_regserver)!= 0)
{
strFilePath = _tcstok(filepath_regserver, szStep);
while (strFilePath != NULL)
{
int retval;
retval=PathFileExists(strFilePath);
if (retval==1 )
{
GetProcessReturn(strFilePath,_T("/RegServer"), SW_HIDE);
}
strFilePath = _tcstok(NULL, szStep);
}
}
}
//如果查找不到,不需要处理
if (filepath_regsvr32 != NULL && lstrlen(filepath_regsvr32)!= 0)
{
strFilePath = _tcstok(filepath_regsvr32, szStep);
while (strFilePath != NULL)
{
TCHAR strCommandLine[MAX_PATH+1] = {0};
if (remove != NULL && lstrlen(remove)!= 0 && _tcscmp(remove,_T("ALL"))==0)
{
TCHAR fname[MAX_PATH];
TCHAR ext[_MAX_EXT];
TCHAR dllfilePath[_MAX_PATH];
_tsplitpath(strFilePath,NULL,NULL,fname,ext);
_tmakepath(dllfilePath,NULL,NULL, fname, ext);
wsprintf(strCommandLine,_T("/u /s \"%s\" "),dllfilePath);
GetProcessReturn(_T("RegSvr32.exe"),strCommandLine, SW_HIDE);
}
else
{
int retval;
retval=PathFileExists(strFilePath);
if (retval==1 )
{
wsprintf(strCommandLine,_T("/s \"%s\" "),strFilePath);
GetProcessReturn(_T("RegSvr32.exe"),strCommandLine, SW_HIDE);
}
}
strFilePath = _tcstok(NULL, szStep);
}
}
RELEASE(filepath_regserver);
RELEASE(filepath_regsvr32);
RELEASE(strFilePath);
RELEASE(pszFileKey);
RELEASE(remove);
return ERROR_SUCCESS;
}
/*
UINT __stdcall ExcuteRegServer(MSIHANDLE hInstall)
{
g_hInstall=hInstall;
DWORD flag = -1;
TCHAR* filepath = NULL;
TCHAR* remove = NULL;
const TCHAR* szStep = _T("#");
TCHAR* pszFileKey = NULL;
remove= getProperty(hInstall, _T("REMOVE") );
if (remove == NULL || lstrlen(remove)== 0 || _tcscmp(remove,_T("ALL"))!=0)
{
filepath= getProperty(hInstall, _T("file_regserver") );
//如果查找不到,不需要处理
if (filepath != NULL && lstrlen(filepath)!= 0)
{
pszFileKey = _tcstok(filepath, szStep);
while (pszFileKey != NULL)
{
TCHAR strFilePath[MAX_PATH];
FilePath(hInstall,pszFileKey,strFilePath);
int retval;
retval=PathFileExists(strFilePath);
if (retval==1 )
{
GetProcessReturn(strFilePath,_T("/RegServer"), SW_HIDE);
}
pszFileKey = _tcstok(NULL, szStep);
}
}
}
filepath= getProperty(hInstall, _T("file_regsvr32") );
//如果查找不到,不需要处理
if (filepath != NULL && lstrlen(filepath)!= 0)
{
pszFileKey = _tcstok(filepath, szStep);
while (pszFileKey != NULL)
{
TCHAR strCommandLine[MAX_PATH+1] = {0};
TCHAR strFilePath[MAX_PATH];
FilePath(hInstall,pszFileKey,strFilePath);
if (remove != NULL && lstrlen(remove)!= 0 && _tcscmp(remove,_T("ALL"))==0)
{
TCHAR fname[MAX_PATH];
TCHAR ext[_MAX_EXT];
TCHAR dllfilePath[_MAX_PATH];
_tsplitpath(strFilePath,NULL,NULL,fname,ext);
_tmakepath(dllfilePath,NULL,NULL, fname, ext);
wsprintf(strCommandLine,_T("/u /s \"%s\" "),dllfilePath);
GetProcessReturn(_T("RegSvr32.exe"),strCommandLine, SW_HIDE);
}
else
{
int retval;
retval=PathFileExists(strFilePath);
if (retval==1 )
{
wsprintf(strCommandLine,_T("/s \"%s\" "),strFilePath);
GetProcessReturn(_T("RegSvr32.exe"),strCommandLine, SW_HIDE);
}
}
pszFileKey = _tcstok(NULL, szStep);
}
}
RELEASE(filepath);
RELEASE(pszFileKey);
RELEASE(remove);
return ERROR_SUCCESS;
}
*/
//
//
//
// 解决安装盘清除文件速度慢的问题
//
UINT __stdcall RemoveAllFiles(MSIHANDLE hInstall)
{
g_hInstall=hInstall;
UINT uiState = ERROR_SUCCESS;
UINT uiState1 = ERROR_SUCCESS;
PMSIHANDLE hDB=NULL;
PMSIHANDLE hViewprop=NULL;
PMSIHANDLE hRecordprop=NULL;
//TCHAR* remove = NULL;
INSTALLSTATE piInstalled;
INSTALLSTATE piAction;
//remove= getProperty(hInstall, _T("REMOVE") );
hDB = ::MsiGetActiveDatabase(hInstall);
::MsiDatabaseOpenView(hDB,
_T("SELECT * FROM `File`"), &hViewprop);
::MsiViewExecute(hViewprop, 0);
uiState1=::MsiViewFetch(hViewprop, &hRecordprop);
Log2Msi(_T("MsiViewFetch uiState1:%d"),uiState1);
//while(uiState1!= ERROR_NO_MORE_ITEMS && uiState1== ERROR_SUCCESS )
while(uiState1== ERROR_SUCCESS )
{
DWORD cchData = 0;
DWORD ccData = 0;
TCHAR componentName[MAX_PATH]={0};
ccData=sizeof(componentName) ;
::MsiRecordGetString(hRecordprop, 2, componentName, &ccData);
uiState=::MsiGetComponentState(hInstall,componentName,&piInstalled,&piAction);
Log2Msi(_T("Get Component %s State.%d %d"),componentName,piInstalled,piAction);
if (uiState == ERROR_SUCCESS && piInstalled ==INSTALLSTATE_LOCAL && piAction ==INSTALLSTATE_ABSENT)
{
TCHAR srcfilePath[MAX_PATH]={0};
ccData=sizeof(srcfilePath) ;
::MsiRecordGetString(hRecordprop, 1, srcfilePath, &ccData);
TCHAR pszFullFileKey[MAX_PATH+3] = {0};
wsprintf(pszFullFileKey, _T("[#%s]"), srcfilePath);
PMSIHANDLE hRec = ::MsiCreateRecord(1);
::MsiRecordSetString(hRec, 0, pszFullFileKey);
uiState = ::MsiFormatRecord(hInstall, hRec, _T(""), &cchData);
if (uiState == ERROR_MORE_DATA)
{
WCHAR* desfilePath = new WCHAR[++cchData];
uiState = ::MsiFormatRecordW(hInstall, hRec, desfilePath, &cchData);
if (uiState != ERROR_SUCCESS)
{
RELEASE(desfilePath);
return ERROR_SUCCESS;
}
if( DeleteFileW(desfilePath) == FALSE)
{
Log2Msi(_T("CCA- RemoveAllFiles(%s) failed! 0x%08X"), desfilePath, GetLastError());
MoveFileExW(desfilePath,NULL,MOVEFILE_DELAY_UNTIL_REBOOT);
}
RELEASE(desfilePath)
}
::MsiCloseHandle(hRec);
}
uiState1=MsiViewFetch(hViewprop, &hRecordprop);
Log2Msi(_T("MsiViewFetch state:%d"),uiState1);
}
::MsiViewClose(hViewprop);
::MsiCloseHandle(hRecordprop);
::MsiCloseHandle(hDB);
return ERROR_SUCCESS;
}
//
//判断MSI包是否允许执行;从11.0之后的补丁只允许在ISD中执行,不能手工安装(zhengzy)
//不用了。
UINT __stdcall MSICanInstall(MSIHANDLE hInstall)
{
OutputDebugString(_T("begin MSICanInstall"));
TCHAR* pBuffer = NULL;
pBuffer= getProperty(hInstall, _T("TARGETDIR") );
TCHAR szPath[MAX_PATH + 1];
ZeroMemory(szPath,sizeof(szPath));
if (pBuffer != NULL)
{
if(pBuffer[lstrlen(pBuffer)-1] == '\\') //删除结尾的'\'
wsprintf(szPath, _T("%s%s"), pBuffer,"PatchInstall.txt");
else
wsprintf(szPath, _T("%s%s"), pBuffer,"\\PatchInstall.txt");
}
RELEASE(pBuffer);
char szSrc[1024];
DWORD dwBytesRead = 0;
ZeroMemory(szSrc,sizeof(szSrc));
int dwSize = sizeof(szSrc);
BOOL bRight = FALSE;
/*
try
{
CStdioFile dsFile;
CFileException ex;
if(dsFile.Open(szPath, CFile::modeRead | CFile::shareDenyNone | CFile::typeText , &ex) == TRUE)
{
dsFile.Read(szSrc, dwSize);
dsFile.Close();
if(lstrcmp(szSrc, "ISD") == 0)
{
bRight = TRUE;
}
else
{
bRight = FALSE;
}
}
else
{
bRight = FALSE;
}
}
catch(CFileException e)
{
char log[1024];
ZeroMemory(log,sizeof(log));
ex.GetErrorMessage(log, 1024);
OutputDebugString(log);
}
*/
HANDLE hFile;
hFile = CreateFile(szPath, // open MYFILE.TXT
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // no security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE)
{
bRight = FALSE;
}
else
{
if (ReadFile(hFile, szSrc, dwSize, &dwBytesRead, NULL))
{
if(lstrcmp(szSrc, "ISD") == 0)
{
bRight = TRUE;
}
else
{
bRight = FALSE;
}
}
CloseHandle(hFile);
}
if(bRight == FALSE)
{
::MsiSetProperty(hInstall, _T("MSICANINSTALL"), _T("0"));
}
else
{
::MsiSetProperty(hInstall, _T("MSICANINSTALL"), _T("1"));
}
return ERROR_SUCCESS;
}
//
//
//
// 生成临时文件,因为defer的custom action不能使用binary table,所以提前生成这些文件
//
UINT __stdcall CreateBinaryFile(MSIHANDLE hInstall)
{
g_hInstall=hInstall;
TCHAR strTmpFile[MAX_PATH];
Log2Msi(_T("CCA- CreateBinaryFile!"));
BinaryFileTempPath(hInstall,"gacutil",strTmpFile,1);
Log2Msi(_T("CCA- CreateBinaryFile!%s"),strTmpFile);
BinaryFileTempPath(hInstall,"RegAsm",strTmpFile,1);
BinaryFileTempPath(hInstall,"RegAsm40",strTmpFile,1);
BinaryFileTempPath(hInstall,"RegSvcs",strTmpFile,1);
return ERROR_SUCCESS;
}