c++获取程序的最后使用时间
杀软的软件管家里面,卸载列表会显示出软件的最近使用时间,以帮助用户清晰的查看该软件的使用频次,那这个时间是怎么获取到的呢。其实系统在打开一个软件时基本都有记录打开时间,当然并不是每一个可执行程序都能得到这个时间。
我们可以从注册表和Prefetch文件夹中获取最近打开时间,下面的例子我会优先选择从注册表获取,然后从Prefetch文件夹中补充。注册表位置:HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\UserAssist,Prefetch文件夹位置:C:\Windows\Prefetch。
从注册表中获取需要特殊注意,注册表UserAssist下有很多子健,只有两个子健是用于记录程序打开时间的,并且xp系统和非xp系统这个两个子健是不同的。这个两个子健就是两个GUID值,xp系统为:"75048700-EF1F-11D0-9888-006097DEACF9"和"5E6AB780-7743-11CF-A12B-00AA004AE837",非xp系统为:"F4E57C4B-2036-45F0-A9AB-443BCFE33D9F"和"CEBFF5CD-ACE2-4F4F-9178-9926F41749EA"。
下面将给出参考代码,代码仅供参考,因为使用了google base里面的一些方法,无法直接编译通过。
static const wchar_t* guides_XP[] = { L"75048700-EF1F-11D0-9888-006097DEACF9", L"5E6AB780-7743-11CF-A12B-00AA004AE837" }; static const wchar_t* guides_WIN7[] = { L"F4E57C4B-2036-45F0-A9AB-443BCFE33D9F", L"CEBFF5CD-ACE2-4F4F-9178-9926F41749EA" }; base::string16 rot13(const base::string16 &input) const { base::string16 r = input; int i = r.length(); while (i--) { if (r[i] >= L'A' && r[i] <= L'M' || r[i] >= L'a' && r[i] <= L'm') r[i] = (char)((int)(r[i] + 13)); else if (r[i] >= L'N' && r[i] <= L'Z' || r[i] >= L'n' && r[i] <= L'z') r[i] = (char)((int)(r[i] - 13)); } return r; } std::map user_assist_ void GetUserAssistList() { user_assist_.clear(); base::Time tNow = base::Time::Now(); bool is_xp_system = base::win::GetVersion() == base::win::Version::VERSION_XP; for (const base::string16& guid : is_xp_system ? guides_XP : guides_WIN7) { base::string16 path = base::StringPrintf(L"SOFTWARE\Microsoft\Windows\CurrentVersion\ Explorer\UserAssist\{%ls}\Count", guid.c_str()); base::win::RegistryValueIterator user_assistant_iter(HKEY_CURRENT_USER, path.c_str()); for (; user_assistant_iter.Valid(); ++user_assistant_iter) { base::string16 rot13_name = user_assistant_iter.Name(); base::string16 name = rot13(rot13_name); unsigned char* achData = (unsigned char*)user_assistant_iter.Value(); unsigned long long winDate = 0, noNano = 0; time_t last_run_time; // last start (long long) for (int i = 67; i >= 60; i--) winDate = (winDate <<= 8) + achData[i]; // convert nanosec. in unix seconds since epoch (1970) // and in normal date if (winDate) { noNano = winDate / 10000000; last_run_time = noNano - 11644473600; } user_assist_.insert(std::make_pair(name, (tNow - base::Time::FromTimeT(last_run_time)).InDays())); } } } int ComputeLastRun(base::FilePath path) { base::Time tRet; base::FileEnumerator file_iter(path, true, base::FileEnumerator::FILES, FILE_PATH_LITERAL(".exe")); for (base::FilePath name = file_iter.Next(); !name.empty(); name = file_iter.Next()) { base::Time time; base::FileEnumerator prefetcher_iter(base::FilePath(L"C:\Windows\Prefetch"), false, base::FileEnumerator::FILES, base::ToUpperASCII(name.BaseName().value()) + L""); for (base::FilePath prefetcher = prefetcher_iter.Next(); !prefetcher.empty(); prefetcher = prefetcher_iter.Next()) { base::File file(prefetcher, base::File::FLAG_OPEN | base::File::FLAG_READ); if (file.IsValid()) { base::File::Info info; file.GetInfo(&info); if (time < info.last_modified) time = info.last_modified; } } if (tRet < time) tRet = time; } if (tRet.is_null()) return -1; return (base::Time::Now() - tRet).InDays(); } void TestLastRun() { int last_run = 0; // 最近打开的天数 base::string16 install_location = "c:\xx\"; base::string16 exe_name = "xx.exe"; base::string16 exe_path = install_location + exe_name; const auto& user_assist = user_assist_.find(exe_path); if (user_assist != user_assist_.end()) last_run = user_assist->second; else { base::win::RegKey regPrefetch; if (regPrefetch.Open(HKEY_LOCAL_MACHINE, _T("SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters"), KEY_READ) == ERROR_SUCCESS) { DWORD dwEnablePrefetcher = 0; if (regPrefetch.ReadValueDW(_T("EnablePrefetcher"), &dwEnablePrefetcher) == ERROR_SUCCESS && (int((int)dwEnablePrefetcher) & 0x1) == 1) last_run = ComputeLastRun(base::FilePath(install_location)); } } }