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