Files
AppUpgrade/UpgradeThread.cpp
2026-07-13 10:02:53 +08:00

923 lines
22 KiB
C++

//---------------------------------------------------------------------------
#include <vcl.h>
#include <System.Hash.hpp>
#include <System.IOUtils.hpp>
#include <wininet.h>
#include <Tlhelp32.h>
#include <vector>
#include "UpgradeThread.h"
#pragma hdrstop
#pragma package(smart_init)
#pragma comment(lib, "wininet")
//---------------------------------------------------------------------------
#define UPDATE_APP_NAME "AppUpgrade.exe"
#define MD5_FILE_NAME "filemd5.lst"
//#define GLOBAL_VAR_FILE "glbvrf.cnf"
//#define DEFAULT_SERVER "23.236.66.46:88" //"127.0.0.1" //
#define GLOBAL_VAR_VERSION 0x03
extern String MAIN_APP_NAME;
typedef struct tGVFHeader{
char head[4];
WORD idSoftware;
WORD iUpdate;
tGVFHeader(){
head[0] = 'G';
head[1] = 'V';
head[2] = 'F';
head[3] = GLOBAL_VAR_VERSION;
iUpdate = 0;
}
} TGVFHEADER;
typedef struct tGetUrlParam
{
char server[128];
int idSoft;
int errCode;
HINTERNET hSession,
hRequest;
int sizeOut;
char *dataOut;
tGetUrlParam(){
memset( this, 0, sizeof(tGetUrlParam) );
};
} TGetUrlParam;
typedef struct tDownloadParam
{
char url[256];
char filename[256];
HWND hWnd;
int errCode;
HINTERNET hSession,
hRequest;
tDownloadParam(){
memset( this, 0, sizeof(tDownloadParam) );
};
} TDownloadParam;
using namespace std;
//---------------------------------------------------------------------------
DWORD WINAPI GetUrlProc(LPVOID args)
{
TGetUrlParam* param = (TGetUrlParam*)args;
param->hSession = InternetOpen( L"RookIE/1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
if( param->hSession ){
String api = L"http://" + (String)param->server + L"/Api/getUpgradeUrl?sid=" + IntToStr(param->idSoft);
param->hRequest = InternetOpenUrl( param->hSession, api.c_str(), NULL, 0,
INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_RELOAD|INTERNET_FLAG_PRAGMA_NOCACHE, 0 );
if( param->hRequest ){
int pos = 0;
DWORD dwByteRead = 0;
char szBuffer[1024];
ZeroMemory(szBuffer, sizeof(szBuffer));
ZeroMemory(param->dataOut, param->sizeOut);
// 循环读取缓冲区内容直到结束
while( InternetReadFile(param->hRequest, szBuffer, sizeof(szBuffer), &dwByteRead) && dwByteRead > 0){
if( pos + dwByteRead > param->sizeOut ){
param->errCode = ERROR_SIZE;
break;
}
// 复制输出数据
memcpy( param->dataOut+pos, szBuffer, dwByteRead );
pos += dwByteRead;
// 清空缓冲区以备下一次读取
ZeroMemory(szBuffer, sizeof(szBuffer));
}
param->dataOut[pos] = 0;
param->sizeOut = pos;
}
else
param->errCode = ERROR_INTERNET_REQ;
}
else
param->errCode = ERROR_INTERNET_OPEN;
return 0;
}
DWORD WINAPI DownloadProc(LPVOID args)
{
TDownloadParam* param = (TDownloadParam*)args;
param->hSession = InternetOpen( L"RookIE/1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
if( param->hSession ){
param->hRequest = InternetOpenUrl( param->hSession, ((String)param->url).c_str(), NULL, 0,
INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_RELOAD|INTERNET_FLAG_PRAGMA_NOCACHE, 0 );
if( param->hRequest ){
int pos = 0;
DWORD dwAllBytes = 0,
dwSize = 4;
if( param->hWnd ){
HttpQueryInfo( param->hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER,
&dwAllBytes, &dwSize, NULL );
}
FILE* fp = fopen( param->filename, "wb" );
if( fp ){
char szBuffer[2048] = "\0";
DWORD dwByteRead = 0, dwReceived = 0;
ZeroMemory(szBuffer, sizeof(szBuffer));
// 循环读取缓冲区内容直到结束
while (InternetReadFile(param->hRequest, szBuffer, sizeof(szBuffer), &dwByteRead) && dwByteRead > 0){
fwrite( szBuffer, 1, dwByteRead, fp );
if( param->hWnd ){
//显示进度
dwReceived += dwByteRead;
int pos = (int)( dwReceived * 100.0 / dwAllBytes + 0.5 );
SendMessage( param->hWnd, UM_PROGRESS, 1, pos );
}
// 清空缓冲区以备下一次读取
ZeroMemory(szBuffer, sizeof(szBuffer));
}
fclose( fp );
if( dwReceived==dwAllBytes ){
SendMessage( param->hWnd, UM_PROGRESS, 1, 100 );
param->errCode = 0;
}
else
param->errCode = ERROR_FILE_SIZE;
}
else
param->errCode = ERROR_OPEN_FILE;
}
else
param->errCode = ERROR_INTERNET_REQ;
}
else
param->errCode = ERROR_INTERNET_OPEN;
return 0;
}
//---------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
__fastcall TUpgradeThread::TUpgradeThread(bool CreateSuspended, int mode, int sid, String sVar, HWND hWnd)
: TThread(CreateSuspended)
{
m_iMode = mode;
m_idSoft = sid;
m_hWnd = hWnd;
m_lstFile = NULL;
m_bUpdateSelf = false;
m_AppPath = TPath::GetFullPath(ExtractFilePath(Application->ExeName));
m_PathName = m_AppPath + MAIN_APP_NAME;
// m_Server = DEFAULT_SERVER;
m_hSema = CreateSemaphore( NULL, 0, 1, NULL );
m_GlobalFile = m_AppPath + sVar;// GLOBAL_VAR_FILE;
}
//---------------------------------------------------------------------------
void __fastcall TUpgradeThread::Cancel()
{
Terminate();
ReleaseSemaphore( m_hSema, 1, NULL );
}
//---------------------------------------------------------------------------
void __fastcall TUpgradeThread::Execute()
{
int ret = 0;
//获取列表文件
//对比文件MD5码=>更新列表
//下载更新列表中的文件
if( m_iMode==3 ){
Sleep(1000); //等待app完全退出
if( UpdateFiles() ){
RegUpdateFlag( 0 );
RestartApp();
}
}
else if( m_iMode==1 ){
MakeMD5File();
}
else{
String strText, strProg1, strProg2;
//清空目录
ClearUpdateDir();
Randomize();
if( m_hWnd ){
strText = "正在获取更新列表";
SendMessage( m_hWnd, UM_SHOWTEXT, 0, (LPARAM)strText.c_str() );
strProg1 = L"——";
SendMessage( m_hWnd, UM_SHOWTEXT, 1, (LPARAM)strProg1.c_str() );
strProg2 = L"正在下载列表文件";
SendMessage( m_hWnd, UM_SHOWTEXT, 2, (LPARAM)strProg2.c_str() );
}
String umdfile = GetUpdateMD5File();
if( umdfile.Length()>0 && !Terminated ){
if( m_hWnd ){
strText = "正在检查更新列表";
SendMessage( m_hWnd, UM_SHOWTEXT, 0, (LPARAM)strText.c_str() );
}
TStringList* ufnLst = new TStringList;
int ret = GetUpdateFileList( umdfile, ufnLst );
if( ret==0 && !Terminated ){
int count = ufnLst->Count;
if( count > 0 ){
if( m_hWnd ){
strText = "正在下载更新文件";
SendMessage( m_hWnd, UM_SHOWTEXT, 0, (LPARAM)strText.c_str() );
}
for( int i=0; i<count && !Terminated; i++ ){
if( m_hWnd ){
strProg1 = L"文件数 " + IntToStr( i ) + L"/" + IntToStr( count );
SendMessage( m_hWnd, UM_SHOWTEXT, 1, (LPARAM)strProg1.c_str() );
int pos = (int)( i*100.0/count + 0.5 );
SendMessage( m_hWnd, UM_PROGRESS, 0, pos );
strProg2 = L"当前下载文件 " + (*ufnLst)[i];
SendMessage( m_hWnd, UM_SHOWTEXT, 2, (LPARAM)strProg2.c_str() );
}
// String ufn = (*ufnLst)[i];
if( !(*ufnLst)[i].CompareIC( UPDATE_APP_NAME ) )
m_bUpdateSelf = true;
int ran = Random( 1000000 );
String url = m_UpdateUrl + (*ufnLst)[i];
url += "?" + IntToStr( ran );
ret = DownloadFile( url, (*ufnLst)[i] );
if( ret!=0 )
break;
}
if( ret==0 ){
if( m_hWnd ){
SendMessage( m_hWnd, UM_PROGRESS, 0, 100 );
}
if( m_iMode==2 || m_bUpdateSelf ){
RegUpdateFlag( 1 );
}
if( m_iMode==0 ){
if( UpdateFiles() )
RestartApp();
}
}
}
else{
if( m_hWnd ){
strText = "未发现需要更新的文件";
SendMessage( m_hWnd, UM_SHOWTEXT, 0, (LPARAM)strText.c_str() );
}
}
}
delete ufnLst;
}
else
ret = ERROR_FILELIST_GET;
}
if( !Terminated && m_hWnd )
PostMessage( m_hWnd, UM_COMPLETE, ret, 0 );
}
//---------------------------------------------------------------------------
bool __fastcall TUpgradeThread::MakeMD5File()
{
String strText, strProg1, strProg2;
if( m_hWnd ){
strText = "正在生成MD5校验文件";
SendMessage( m_hWnd, UM_SHOWTEXT, 0, (LPARAM)strText.c_str() );
}
m_lstFile = new TStringList();
m_lstMD5 = new TStringList();
if( GetFileList( m_lstFile ) ){
String fname = m_AppPath + MD5_FILE_NAME;
FILE* fp = fopen( ((AnsiString)fname).c_str(), "wb" );
if( fp ){
for( int i=0; i<m_lstFile->Count && !Terminated; i++ ){
if( m_hWnd ){
strProg1 = L"文件数 " + IntToStr( i )
+ L"/" + IntToStr( m_lstFile->Count );
SendMessage( m_hWnd, UM_SHOWTEXT, 1, (LPARAM)strProg1.c_str() );
int pos = (int)( i*100.0/m_lstFile->Count + 0.5 );
SendMessage( m_hWnd, UM_PROGRESS, 0, pos );
strProg2 = L"当前文件 " + (*m_lstFile)[i];
SendMessage( m_hWnd, UM_SHOWTEXT, 2, (LPARAM)strProg2.c_str() );
}
String md5;
if( !GenerateFileMD5( (*m_lstFile)[i], md5 ) )
break;
if( m_hWnd )
SendMessage( m_hWnd, UM_PROGRESS, 1, 100 );
char text[256];
sprintf( text, "%s\t%s\n",
((AnsiString)(*m_lstFile)[i]).c_str(),
((AnsiString)md5).c_str() );
fwrite( text, 1, strlen(text), fp );
}
if( !Terminated && m_hWnd )
SendMessage( m_hWnd, UM_PROGRESS, 0, 100 );
fclose( fp );
}
}
delete m_lstFile;
delete m_lstMD5;
m_lstFile = NULL;
return !Terminated;
}
//---------------------------------------------------------------------------
bool __fastcall TUpgradeThread::GenerateFileMD5( String fname, String& md5 )
{
String strName = m_AppPath + fname;
THashMD5* pMD5 = new THashMD5();
TFileStream* fs = new TFileStream( strName, fmOpenRead | fmShareDenyNone );
fs->Position = 0;
int sizeBuf = 1024 * 1024;
char* buf = (char*)malloc( sizeBuf );
while( !Terminated && fs->Position < fs->Size ){
if( fs->Position + sizeBuf > fs->Size )
sizeBuf = fs->Size - fs->Position;
fs->ReadBuffer( buf, sizeBuf );
pMD5->Update( buf, sizeBuf );
if( m_hWnd ){
//显示进度
int pos = (int)( fs->Position * 100.0 / fs->Size + 0.5 );
SendMessage( m_hWnd, UM_PROGRESS, 1, pos );
}
}
if( !Terminated ){
md5 = pMD5->HashAsString();
}
free( buf );
delete fs;
delete pMD5;
return !Terminated;
}
//---------------------------------------------------------------------------
int __fastcall TUpgradeThread::DownloadFile( String url, String filename )
{
int ret = -1;
String path = m_AppPath + L"upgrade\\";
if(!DirectoryExists(path, false))
ForceDirectories(path);
DeleteUrlCacheEntry(url.c_str());
path += filename;
for( int i=0; i<3; i++ ){ //尝试3次
TDownloadParam param;
param.hWnd = m_hWnd;
strcpy( param.url, ((AnsiString)url).c_str() );
strcpy( param.filename, ((AnsiString)path).c_str() );
DWORD id;
HANDLE hThread = CreateThread( NULL, 0, DownloadProc, &param, 0, &id );
if( hThread ){
HANDLE aHandle[2] = { m_hSema, hThread };
DWORD dwRet = WaitForMultipleObjects( 2, aHandle, FALSE, INFINITE );
if( param.hRequest )
InternetCloseHandle( param.hRequest );
if( param.hSession )
InternetCloseHandle( param.hSession );
WaitForSingleObject( hThread, 200 );
CloseHandle( hThread );
if( dwRet==WAIT_OBJECT_0 ) //用户退出
break;
else if( dwRet==WAIT_OBJECT_0+1 ){ //线程正常退出
if( param.errCode==0 ){
ret = 0;
break;
}
else if( param.errCode==ERROR_OPEN_FILE )
break;
}
}
}
return ret;
}
//---------------------------------------------------------------------------
bool __fastcall TUpgradeThread::GetFileList( TStringList* pList )
{
TSearchRec sr;
int iAttr = 0;
String strPath = m_AppPath;
if( FindFirst(strPath + L"*.*", iAttr, sr)==0 ){
do{
if( !(iAttr & faDirectory) /*iAttr & faNormal*/
//&& !sr.Name.Pos(".log")
//&& !sr.Name.Pos(".txt")
//&& !sr.Name.Pos(".ico")
//&& !sr.Name.Pos(".cnf")
//&& !sr.Name.Pos("agcdstdt")
&& !sr.Name.Pos(".lst")){
pList->Add( sr.Name );
}
}
while( !Terminated && FindNext(sr)==0 );
FindClose(sr);
}
return !Terminated;
}
//---------------------------------------------------------------------------
String __fastcall TUpgradeThread::GetUpdateMD5File()
{
String locFile;
m_UpdateUrl = GetUpdateURL();
if( m_UpdateUrl.Length()>0 ){
int ran = Random( 1000000 );
String url = m_UpdateUrl + MD5_FILE_NAME;
url += "?" + IntToStr( ran );
int ret = DownloadFile( url, MD5_FILE_NAME );
if( ret==0 ){
locFile = m_AppPath + L"upgrade/" + MD5_FILE_NAME;
}
}
return locFile;
}
//---------------------------------------------------------------------------
int __fastcall TUpgradeThread::GetServers( TStringList* pList )
{
char szBuffer[2048] = "";
// bool bSave = false;
FILE* fp = NULL;
//读取文件配置
fp = fopen( ((AnsiString)m_GlobalFile).c_str(), "rb" );
if( fp ){
TGVFHEADER header;
header.idSoftware = m_idSoft;
int ret = fread( (void*)szBuffer, 1, sizeof(header), fp );
if( ret==sizeof(header) && !memcmp(szBuffer, header.head, sizeof(header.head)) ){
fseek( fp, 0, SEEK_END );
int size = ftell( fp ) - sizeof(header);
if( size>2048 )
size = 2048;
fseek( fp, sizeof(header), SEEK_SET );
fread( szBuffer, 1, size, fp );
char srvs[1024] = "";
char *tokenPtr=strtok(szBuffer,"\n");
while( tokenPtr ){
if( strstr(tokenPtr, "srv=") ){
strcpy( srvs, tokenPtr+4 );
break;
}
tokenPtr=strtok(NULL,"\n");
}
if( strlen(srvs) ){
char *tkn = strtok( srvs, ";" );
while( tkn!=NULL ){
pList->Add( tkn );
tkn = strtok(NULL, ";");
}
}
}
fclose( fp );
}
// else{
// pList->Add( m_Server );
// }
return 0;
}
//---------------------------------------------------------------------------
String __fastcall TUpgradeThread::GetUpdateURL()
{
String url;
TStringList* pServers = new TStringList;
GetServers( pServers );
for( int i=0; i<pServers->Count; i++ ){
int sizeOut = 2048;
char dataOut[2048];
TGetUrlParam param;
param.idSoft = m_idSoft;
param.sizeOut = sizeOut;
param.dataOut = dataOut;
strcpy( param.server, ((AnsiString)(*pServers)[i]).c_str() );
DWORD id;
HANDLE hThread = CreateThread( NULL, 0, GetUrlProc, &param, 0, &id );
if( hThread ){
HANDLE aHandle[2] = { m_hSema, hThread };
DWORD dwRet = WaitForMultipleObjects( 2, aHandle, FALSE, 10000 );
if( param.hRequest )
InternetCloseHandle( param.hRequest );
if( param.hSession )
InternetCloseHandle( param.hSession );
WaitForSingleObject( hThread, 200 );
CloseHandle( hThread );
if( dwRet==WAIT_OBJECT_0 ) //用户退出
break;
else if( dwRet==WAIT_OBJECT_0+1 && param.errCode==0 ){ //线程正常退出
if(dataOut[0]=='\"' && dataOut[param.sizeOut-1]=='\"')
dataOut[param.sizeOut-1] = 0;
char* p = strstr( dataOut, "url:" );
if( p ){
m_Server = (*pServers)[i];
char* str = p+4;
url = L"http://" + m_Server + L"/" + str;
break;
}
}
}
}
delete pServers;
return url;
}
//---------------------------------------------------------------------------
int __fastcall TUpgradeThread::GetUpdateFileList( String ufile, TStringList* ufnLst )
{
int err = 0;
String lfname = m_AppPath + MD5_FILE_NAME;
FILE *ufp = fopen( ((AnsiString)ufile).c_str(), "rb" ),
*lfp = fopen( ((AnsiString)lfname).c_str(), "rb" );
if( !ufp ){
err = -1;
goto exit_line;
}
else if( !lfp ){
if( !MakeMD5File() || !(lfp=fopen( ((AnsiString)lfname).c_str(), "rb" )) ){
err = -2;
goto exit_line;
}
}
{
char lbuf[4096] = "",
ubuf[4096] = "";
fseek( lfp, 0, SEEK_END );
fseek( ufp, 0, SEEK_END );
int lsize = ftell( lfp );
int usize = ftell( ufp );
if(usize==0)
goto exit_line;
fseek( lfp, 0, SEEK_SET );
fseek( ufp, 0, SEEK_SET );
fread( lbuf, 1, lsize, lfp );
fread( ubuf, 1, usize, ufp );
fclose( lfp );
fclose( ufp );
lfp = ufp = NULL;
TStringList *lfnLst = new TStringList,
*lmdLst = new TStringList,
*umdLst = new TStringList;
char *tokenPtr=strtok(lbuf,"\n");
while( tokenPtr ){
char* pos = strstr( tokenPtr, "\t" );
if( pos ){
char buf[256];
memcpy( buf, tokenPtr, pos-tokenPtr );
buf[pos-tokenPtr] = 0;
lfnLst->Add( buf );
lmdLst->Add( pos+1 );
}
tokenPtr=strtok(NULL,"\n");
}
tokenPtr=strtok(ubuf,"\n");
while( tokenPtr ){
char* pos = strstr( tokenPtr, "\t" );
if( pos ){
char buf[256];
memcpy( buf, tokenPtr, pos-tokenPtr );
buf[pos-tokenPtr] = 0;
ufnLst->Add( buf );
umdLst->Add( pos+1 );
}
tokenPtr=strtok(NULL,"\n");
}
String strProg1, strProg2;
int count = ufnLst->Count;
for( int i=ufnLst->Count-1; i>=0; i-- ){
if( m_hWnd ){
strProg1 = L"文件数 " + IntToStr( count-i-1 ) + L"/" + IntToStr(count);
SendMessage( m_hWnd, UM_SHOWTEXT, 1, (LPARAM)strProg1.c_str() );
int pos = (int)( (count-i-1)*100.0/count + 0.5 );
SendMessage( m_hWnd, UM_PROGRESS, 0, pos );
strProg2 = L"当前比对文件 " + (*ufnLst)[i];
SendMessage( m_hWnd, UM_SHOWTEXT, 2, (LPARAM)strProg2.c_str() );
}
int count2 = lfnLst->Count;
for( int j=lfnLst->Count-1; j>=0; j-- ){
if( m_hWnd ){
int pos = (int)( (count2-j)*100.0/count2 + 0.5 );
SendMessage( m_hWnd, UM_PROGRESS, 1, pos );
}
// String ufn = (*ufnLst)[i],
// lfn = (*lfnLst)[j];
if( !(*ufnLst)[i].CompareIC( (*lfnLst)[j] ) ){
// String umd = (*umdLst)[i],
// lmd = (*lmdLst)[j];
if( !(*umdLst)[i].CompareIC( (*lmdLst)[j] ) ){
ufnLst->Delete( i );
umdLst->Delete( i );
}
lfnLst->Delete( j );
lmdLst->Delete( j );
break;
}
}
}
delete lfnLst;
delete lmdLst;
delete umdLst;
}
exit_line:
if( ufp )
fclose( ufp );
if( lfp )
fclose( lfp );
return err;
}
//---------------------------------------------------------------------------
int __fastcall TUpgradeThread::RegUpdateFlag( int iUpdate )
{
FILE* fp = fopen( ((AnsiString)m_GlobalFile).c_str(), "r+b" );
if( fp ){
TGVFHEADER header;
header.idSoftware = m_idSoft;
header.iUpdate = iUpdate;
fseek( fp, 0, SEEK_SET );
fwrite( (void*)&header, sizeof(header), 1, fp );
fclose( fp );
}
return 0;
}
//---------------------------------------------------------------------------
int __fastcall TUpgradeThread::ClearUpdateDir()
{
TSearchRec sr;
int iAttr = 0;
String strPath = m_AppPath + L"upgrade\\";
if( FindFirst(strPath + L"*.*", iAttr, sr)==0 ){
do{
if( !(iAttr & faDirectory) ){
DeleteFile( strPath + sr.Name );
}
}
while( FindNext(sr)==0 );
FindClose(sr);
}
return 0;
}
//---------------------------------------------------------------------------
bool __fastcall TUpgradeThread::UpdateFiles()
{
bool bSuccess = true;
TSearchRec sr;
int iAttr = 0;
String strPath = m_AppPath + L"upgrade\\";
//先关闭主程序
StopApp();
Sleep(1000); //等待app完全退出
if( FindFirst(strPath + L"*.*", iAttr, sr)==0 ){
do{
if( !(iAttr & faDirectory) && sr.Name.CompareIC(UPDATE_APP_NAME) ){
String fOld = strPath + sr.Name,
fNew = m_AppPath + sr.Name;
if( !MoveFileEx( fOld.c_str(), fNew.c_str(), MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH ) ){
bSuccess = false;
break;
}
}
}
while( FindNext(sr)==0 );
FindClose(sr);
}
return bSuccess;
}
//---------------------------------------------------------------------------
int __fastcall TUpgradeThread::RestartApp()
{
//启动主程序
HANDLE hToken = NULL,
hTokenDup = NULL;
if(OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken)){
if(DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS,NULL, SecurityIdentification,
TokenPrimary, &hTokenDup)){
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si,sizeof(STARTUPINFO));
ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = NULL;
si.lpReserved = NULL;
si.lpTitle = NULL;
si.cbReserved2 = NULL;
si.lpReserved2 = NULL;
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL;
String command = "\"" + m_AppPath + MAIN_APP_NAME + "\"";
CreateProcessAsUser(hTokenDup,NULL,command.c_str(),NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
}
}
return 0;
}
//---------------------------------------------------------------------------
bool __fastcall TUpgradeThread::StopApp()
{
HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS,0 ); //获取进程快照
if( hSnapshot ){
DWORD idProcess = 0;
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof( PROCESSENTRY32 );
if(!Process32First( hSnapshot, &pe32 )){ //指向第一个进程
CloseHandle(hSnapshot);
return false;
}
do{
if( lstrcmpi( pe32.szExeFile, MAIN_APP_NAME.c_str() )==0 ){ //查找进程
if( SameModulePath( pe32.th32ProcessID )){
idProcess = pe32.th32ProcessID;
break;
}
}
}
while( Process32Next(hSnapshot, &pe32) ); // 循环直到取不到进程
if( idProcess ){
HANDLE hApp= OpenProcess( PROCESS_ALL_ACCESS, FALSE, idProcess ); //根据进程ID获取程序的句柄
if( hApp ){
if( WaitForSingleObject( hApp, 2000 )==WAIT_TIMEOUT )// 等待程序关闭2秒
TerminateProcess( hApp, 0 );
CloseHandle( hApp );
}
}
CloseHandle( hSnapshot );
}
return true;
}
//---------------------------------------------------------------------------
#define PSAPI_VERSION 1
#include <psapi.h>
#pragma comment(lib,"psapi")
bool __fastcall TUpgradeThread::SameModulePath(DWORD dwPID)
{
TCHAR sFilename[MAX_PATH];
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPID);
if (hProcess == NULL)
return false;
bool bSame = false;
HMODULE hModule;
DWORD cbNeeded;
if (EnumProcessModules(hProcess, &hModule, sizeof(hModule), &cbNeeded)){
if (GetModuleFileNameEx(hProcess, hModule, sFilename, MAX_PATH)){
if(wcslen(sFilename)>0){
String sFullName = TPath::GetFullPath(sFilename);
if( !m_PathName.CompareIC( sFilename ) )
bSame = true;
}
}
}
else{
DWORD size = MAX_PATH;
if (QueryFullProcessImageName(hProcess, 0, sFilename, &size)){
if( !m_PathName.CompareIC( sFilename ) )
bSame = true;
}
}
CloseHandle(hProcess);
return bSame;
}
//---------------------------------------------------------------------------