// lyfzRename.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "rename.h" #include #include #include "PARAMETERS.h" #ifdef _DEBUG #define new DEBUG_NEW #endif HMODULE g_hCurModule = NULL; TCHAR g_szCurModulePath[MAX_PATH] = {0}; TCHAR g_szFna[MAX_PATH] = {0}; BOOL GetDebugPriv(); void WriteTextLog(const TCHAR *format, ...); string GetFileVersion(const string &strFilePath); bool GetFileVersion(IN const TCHAR *fname, IN HMODULE hModule, OUT WORD *pBuffer); bool GetProductVersion(IN const TCHAR *fname, IN HMODULE hModule, OUT WORD *pBuffer); void getopt(PARAMETERS & params, int argc, char ** argv); // 唯一的应用程序对象 CWinApp theApp; using namespace std; int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; TCHAR szDrive[_MAX_DRIVE] = { 0 }; TCHAR szDir[_MAX_DIR] = { 0 }; TCHAR szFna[_MAX_DIR] = { 0 }; TCHAR szExt[_MAX_DIR] = { 0 }; ::GetModuleFileName(NULL, g_szCurModulePath, sizeof(g_szCurModulePath) / sizeof(TCHAR)); _tsplitpath_s(g_szCurModulePath, szDrive, szDir, g_szFna, szExt); _tcscpy_s(g_szCurModulePath, szDrive); _tcscat_s(g_szCurModulePath, szDir); GetDebugPriv(); // 初始化 MFC 并在失败时显示错误 if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { // TODO: 更改错误代码以符合您的需要 _tprintf(_T("错误: MFC 初始化失败\n")); nRetCode = 1; } else { // 获取参数; PARAMETERS params; getopt(params, argc, argv); #ifdef _DEBUG WriteTextLog(_T("%ld, %ld,%s,%s"),params.dwProcId, params.killproc, params.NewVerPath.c_str(), params.OldVerPath.c_str()); #endif if ( params.dwProcId != 0) { // 等待进程退出; DWORD dwTargetProId = 0; HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, params.dwProcId); if ( hProc != NULL) { if ( params.killproc ) {//结束进程; TerminateProcess(hProc, 0); Sleep(500); } else { // 等待线程结束; WaitForSingleObject(hProc, INFINITE); CloseHandle(hProc); } } if (!PathFileExists(params.NewVerPath.c_str())) { exit(0); } #if 0//以主程序为升级包的处理方法; // 删除旧版本文件; DeleteFile(params.OldVerPath.c_str()); // 移动文件; MoveFile(params.NewVerPath.c_str(), params.OldVerPath.c_str()); if ( params.killproc ) { // 启动程序; CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);//某些情况下要初始化COM才能使用ShellExecuteEx; SHELLEXECUTEINFO stuExecInfo = { 0 }; DWORD dwExitCode = STILL_ACTIVE; stuExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); stuExecInfo.lpFile = params.OldVerPath.c_str(); stuExecInfo.nShow = SW_SHOW; stuExecInfo.lpVerb = _T("open"); stuExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI; if (!ShellExecuteEx(&stuExecInfo)) { DWORD dwError = GetLastError(); WriteTextLog(_T("ShellExecuteEx Error=%ld"), dwError); return -1; } HANDLE hProcess = stuExecInfo.hProcess; if ( hProcess != NULL ) { //WaitForSingleObject(hProcess,INFINITE);//不等待结束; CloseHandle(hProcess); } } #else//以安装包为升级包的处理方法;//可以选择静默安装安装包; if ( params.killproc ) { // 启动程序; CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);//某些情况下要初始化COM才能使用ShellExecuteEx; SHELLEXECUTEINFO stuExecInfo = { 0 }; DWORD dwExitCode = STILL_ACTIVE; CString strParameters = _T("/S"); stuExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); stuExecInfo.lpFile = params.NewVerPath.c_str(); stuExecInfo.nShow = SW_SHOW; //stuExecInfo.lpParameters = strParameters;//不静默安装; stuExecInfo.lpVerb = _T("open"); stuExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI; if (!ShellExecuteEx(&stuExecInfo)) { DWORD dwError = GetLastError(); WriteTextLog(_T("ShellExecuteEx Error=%ld"), dwError); return -1; } HANDLE hProcess = stuExecInfo.hProcess; if ( hProcess != NULL ) { CloseHandle(hProcess); } } #endif } } return nRetCode; } void getopt(PARAMETERS & params, int argc, char ** argv) { std::string cmd = ""; for ( argc > 0; argc--; argv++ ) { if ( _tcsicmp(*argv, _T("--pid")) == 0) { cmd = _T("--pid"); } else if (_tcsicmp(*argv, _T("--oldpath")) == 0) { cmd = _T("--oldpath"); } else if (_tcsicmp(*argv, _T("--newpath")) == 0) { cmd = _T("--newpath"); } else if (_tcsicmp(*argv, _T("--killproc")) == 0) { cmd = _T("--killproc"); } else { if ( _tcsicmp(cmd.c_str(), _T("--pid")) == 0) { params.dwProcId = atoi(*argv); } else if (_tcsicmp(cmd.c_str(), _T("--oldpath")) == 0) { params.OldVerPath = *argv; } else if (_tcsicmp(cmd.c_str(), _T("--newpath")) == 0) { params.NewVerPath = *argv; } else if (_tcsicmp(cmd.c_str(), _T("--killproc")) == 0) { params.killproc = atoi(*argv); } cmd = ""; } } } //2.获得其他exe或dll的版本信息 string GetFileVersion(const string &strFilePath) { DWORD dwSize; DWORD dwRtn; string szVersion; //获取版本信息大小 dwSize = GetFileVersionInfoSize(strFilePath.c_str(),NULL); DWORD dwErr = GetLastError(); if (dwSize == 0) { return ""; } char *pBuf; pBuf= new char[dwSize + 1]; if(pBuf == NULL) return ""; memset(pBuf, 0, dwSize + 1); //获取版本信息 dwRtn = GetFileVersionInfo(strFilePath.c_str(),NULL, dwSize, pBuf); if(dwRtn == 0) { return ""; } LPVOID lpBuffer = NULL; UINT uLen = 0; //版本资源中获取信息 dwRtn = VerQueryValue(pBuf, TEXT("\\StringFileInfo\\080404b0\\FileVersion"), //0804中文 //04b0即1252,ANSI //可以从ResourceView中的Version中BlockHeader中看到 //可以测试的属性 /* CompanyName FileDescription FileVersion InternalName LegalCopyright OriginalFilename ProductName ProductVersion Comments LegalTrademarks PrivateBuild SpecialBuild */ &lpBuffer, &uLen); if(dwRtn == 0) { return ""; } szVersion = (char*)lpBuffer; delete pBuf; return szVersion; } // hModule 模块句柄 NULL表示当前模块; bool GetFileVersion(IN const TCHAR *fname, IN HMODULE hModule, OUT WORD *pBuffer) { //TCHAR fname[MAX_PATH]; VS_FIXEDFILEINFO *pVi = NULL; DWORD dwHandle = 0; string str; int size = GetFileVersionInfoSize(fname, &dwHandle); if (size > 0) { BYTE *buffer = new BYTE[size]; memset(buffer,0,size); if (GetFileVersionInfo(fname, dwHandle, size, buffer)) { if (VerQueryValue(buffer, _T("\\"), (LPVOID *)&pVi, (PUINT)&size)) { pBuffer[0] = HIWORD(pVi->dwFileVersionMS); pBuffer[1] = LOWORD(pVi->dwFileVersionMS); pBuffer[2] = HIWORD(pVi->dwFileVersionLS); pBuffer[3] = LOWORD(pVi->dwFileVersionLS); delete []buffer; return true; } } delete []buffer; } return false; } bool GetProductVersion(IN const TCHAR *fname, IN HMODULE hModule, OUT WORD *pBuffer) { //TCHAR fname[MAX_PATH]; VS_FIXEDFILEINFO *pVi = NULL; DWORD dwHandle = 0; string str; int size = GetFileVersionInfoSize(fname, &dwHandle); if (size > 0) { BYTE *buffer = new BYTE[size]; memset(buffer,0,size); if (GetFileVersionInfo(fname, dwHandle, size, buffer)) { if (VerQueryValue(buffer, _T("\\"), (LPVOID *)&pVi, (PUINT)&size)) { pBuffer[0] = HIWORD(pVi->dwProductVersionMS); pBuffer[1] = LOWORD(pVi->dwProductVersionMS); pBuffer[2] = HIWORD(pVi->dwProductVersionLS); pBuffer[3] = LOWORD(pVi->dwProductVersionLS); delete []buffer; return true; } } delete []buffer; } return false; } BOOL GetDebugPriv() { // 返回的访问令牌指针; HANDLE hToken; // 接收所返回的制定特权名称的信息; LUID sedebugnameValue; // 新特权信息的指针(结构体); TOKEN_PRIVILEGES tkp; DWORD dwCurProcId = GetCurrentProcessId(); // 要修改访问权限的进程句柄; HANDLE hCurProc; hCurProc = ::OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwCurProcId ); if ( !::OpenProcessToken( hCurProc,TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) ) { DWORD dwError = GetLastError(); //CString strError; //strError.Format("升级包提权失败,错误码=%d",dwError); //AfxMessageBox(strError); return FALSE; } if ( ! ::LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) ) { DWORD dwError = GetLastError(); //CString strError; /// strError.Format("升级包提权失败,错误码=%d",dwError); //AfxMessageBox(strError); CloseHandle( hToken ); return FALSE; } tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = sedebugnameValue; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!::AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) ) { DWORD dwError = GetLastError(); //CString strError; //strError.Format("升级包提权失败,错误码=%d",dwError); //AfxMessageBox(strError); CloseHandle( hToken ); return FALSE; } CloseHandle(hCurProc); CloseHandle(hToken); return TRUE; } /************************************************************************/ /* 函数:WriteTextLog[7/28/2009 Jeff]; /* 描述:写文本日志; /* 参数:; /* [IN] :; /* 返回:void; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ void WriteTextLog(const TCHAR *format, ...) { // 解析出日志路径; TCHAR szlogpath[MAX_PATH] = { 0 }; _stprintf_s(szlogpath, _T("%s%s.txt"), g_szCurModulePath, g_szFna); // 打开或创建文件; FILE *fp = NULL; //if (_taccess(szlogpath, 0) != -1) #ifndef UNICODE if (_access(szlogpath, 0) != -1) #else if (_taccess(szlogpath, 0) != -1) #endif {// 存在; fp = _tfopen(szlogpath, _T("a+")); // 移动到末尾; fseek(fp, 0, SEEK_END); } else {// 不存在; fp = _tfopen(szlogpath, _T("w+")); } if ( fp == NULL ) return; // 格式化前设置语言区域; TCHAR* old_locale = _tcsdup(_tsetlocale(LC_CTYPE, NULL)); _tsetlocale(LC_CTYPE, _T("chs"));//设定中文; // 格式化日志内容; va_list args = NULL; int len = 0; TCHAR *buffer = NULL; va_start(args, format); // _vscprintf doesn't count. terminating '\0' len = _vsctprintf(format, args) + 1; buffer = (TCHAR*)malloc(len * sizeof(TCHAR)); _vstprintf_s(buffer, len, format, args); // 将日志内容输入到文件中; // 获取今年年份; __time64_t gmt = time(NULL);// 获取当前日历时间(1900-01-01开始的Unix时间戳); struct tm gmtm = {0}; localtime_s(&gmtm, &gmt); // 时间戳转成本地时间; _ftprintf(fp, _T("%04d-%02d-%02d %02d:%02d:%02d %s\n"), gmtm.tm_year+1990, gmtm.tm_mon+1, gmtm.tm_mday, gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec, buffer); // 关闭文件,释放资源并设置回原语言区域; free(buffer); fclose(fp); _tsetlocale(LC_CTYPE, old_locale); free(old_locale);//还原区域设定; }