windows c获取文件md5值确定是否改变

功能说明

在windows下做一些小工具的时候,希望做到根据配置文件来对pc做一些配置下发的操作(例如改主机名改网络等),这就需要做到每个一段时间检测配置文件,并执行相应配置,但是当我们配置文件没有修改时,就不需要做配置了,因此需要对配置文件进行md5检测判断文件是否有改变

获取md5值

此处是获取文件的md5值,文件名在new类的时候传入

BYTE* VeryAgent::getMd5()
{
       HANDLE hFile = CreateFile(mIniConfigPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
       if (hFile == INVALID_HANDLE_VALUE)//如果CreateFile调用失败
       {
              LOGD("CreateFile go wrong: %s", GetLastError());//提示CreateFile调用失败,并输出错误号。visual studio中可在“工具”>“错误查找”中利用错误号得到错误信息
              CloseHandle(hFile);
              return NULL;
       }
       HCRYPTPROV hProv = NULL;
       if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE)//获得CSP中一个密钥容器的句柄
       {
              LOGD("CryptAcquireContext go wrong: %s", GetLastError());
              return NULL;
       }
       HCRYPTPROV hHash = NULL;
       if (CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash) == FALSE)//初始化对数据流的hash,创建并返回一个与CSP的hash对象相关的句柄。这个句柄接下来将被CryptHashData调用。
       {
              LOGD("CryptCreateHash go wrong: %s", GetLastError());
              return NULL;
       }
       DWORD dwFileSize = GetFileSize(hFile, 0);    //获取文件的大小
       if (dwFileSize == 0xFFFFFFFF)                //如果获取文件大小失败
       {
              LOGD("GetFileSize go wrong: %s", GetLastError());
              return NULL;
       }
       byte* lpReadFileBuffer = new byte[dwFileSize];
       DWORD lpReadNumberOfBytes;
       if (ReadFile(hFile, lpReadFileBuffer, dwFileSize, &lpReadNumberOfBytes, NULL) == 0)//读取文件
       {
              LOGD("ReadFile go wrong: %s", GetLastError());
              return NULL;
       }
       if (CryptHashData(hHash, lpReadFileBuffer, lpReadNumberOfBytes, 0) == FALSE)//hash文件
       {
              LOGD("CryptHashData go wrong: %s", GetLastError());
              return NULL;
       }
       delete[] lpReadFileBuffer;
       CloseHandle(hFile);//关闭文件句柄
       BYTE *pbHash;
       DWORD dwHashLen = sizeof(DWORD);
       if (CryptGetHashParam(hHash, HP_HASHVAL, NULL, &dwHashLen, 0))//我也不知道为什么要先这样调用CryptGetHashParam,这块是参照的msdn      
       {
       }
       else
       {
              LOGD("get length wrong");
              return NULL;
       }
       if (pbHash = (byte*)malloc(dwHashLen))
       {
       }
       else
       {
              LOGD("allocation failed");
              return NULL;
       }
       if (CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &dwHashLen, 0))//获得md5值
       {
              //for (DWORD i = 0; i

判断文件是否改变逻辑

1、若未检测到md5值说明文件有问题

2、检测到文件md5值后

    1、若保存的md5值为空,则说明是第一次检测,保存好md5值供下次对比,之后进行配置下发

    2、原来就有md5值,则将现有md5与之前的做对比,相同则不做配置下发,不同则做配置下发,并且更新保存的md5值

bool VeryAgent::checkMd5() {

    //printMd5sum(mMd5sum);
    //类名为VeryAgent,记录一个成员变量为mMd5sum
    unsigned char *tmpMd5sum = getMd5();
	if (tmpMd5sum) {
		if (!mMd5sum) {
			LOGD("mMd5sum = null do agent config");
			mMd5sum = tmpMd5sum;
			return true;
		}
		if (memcmp(mMd5sum, tmpMd5sum, 16) == 0) {
			free(tmpMd5sum);
			tmpMd5sum = NULL;
			//LOGD("config not changed");
			return false;
		}
		else {
			free(mMd5sum);
			mMd5sum = tmpMd5sum;
			LOGD("config changed, do agent config");
			return true;
		}
	}
	else {
		LOGD("get new md5sum failed");
		return false;
	}
	return true;
}

最后是主函数循环

new的时候将文件名传入类成员变量mIniConfigPath以供使用

int main()
{
    const char* filename = "C:\\config.ini";
    VeryAgent *agent = new VeryAgent(filename);
    while (1)
    {
        if (agent->checkMd5()) {
            agent->doAgentConfig();
        }
        Sleep(1000 * 1);
    }
}

你可能感兴趣的:(c/c++应用编程,windows,c语言,开发语言)