当前位置:首页 > c++ > 正文内容

c++获取程序的最后使用时间

xuwenyan2年前 (2021-02-20)c++353

杀软的软件管家里面,卸载列表会显示出软件的最近使用时间,以帮助用户清晰的查看该软件的使用频次,那这个时间是怎么获取到的呢。其实系统在打开一个软件时基本都有记录打开时间,当然并不是每一个可执行程序都能得到这个时间。

我们可以从注册表和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));
     }
   }
 }
    文章作者:xuwenyan
    版权声明:本文为本站原创文章,转载请注明出处,非常感谢,如版权漏申明或您觉得任何有异议的地方欢迎与本站取得联系。

    扫描二维码推送至手机访问。

    版权声明:本文由艺文笔记发布,如需转载请注明出处。

    本文链接:https://www.xuwenyan.com/archives/159

    分享给朋友:

    “c++获取程序的最后使用时间” 的相关文章

    C++如何实现挂起进程、恢复进程

    C++如何实现挂起进程、恢复进程

    1:枚举进程的所有线程,使用SuspendThread函数挂起每一个线程,需要恢复时使用ResumeThread函数恢复。因为挂起和恢复的顺序是不可预知的,所以可能会导致一些多线程程序崩溃,单线程程序可能不受影响。void SuspendProcess(DWORD process...

    vs(vs2015)拖动或停靠窗口崩溃的解决方法

    vs(vs2015)拖动或停靠窗口崩溃的解决方法

    使用vs拖动窗口后想要停靠某一个区域时,ide会崩溃重启,而且会反复这样,拖动布局功能基本丧失,使用起来非常不爽。解决办法如下: vs2019(visual studio 2019) 如果vs版本是2019,那么直接升级vs即可解决问题。 vs2015(visual studio...

    ATL实现windows右键菜单扩展(ContextMenu)

    ATL实现windows右键菜单扩展(ContextMenu)

    右键菜单,即用户右击shell对象时弹出的上下文菜单(context menu)。本文记录了如何创建右键菜单的基本过程,跟着步骤一步一步来,即可创建出一个右键菜单工程。第一步,新建一个ATL工程Visual Studio—>新建项目—>ATL—>使用默认配置(一直按下一步即可)。注...

    C++ 获取进程所在目录(进程全路径)

    C++ 获取进程所在目录(进程全路径)

    打开windows任务管理器,会看到很多的进程在运行,随机挑选一个,如何通过c++代码获取某一个进程的所在全路径呢?这也是在windows软件开发中经常遇到的需求。通过进程名获取进程全路径由于可能很多进程叫同一个名字,所以获得的结果也有可能是多个#include <windows.h...

    c++函数模板参数类型限定

    c++函数模板参数类型限定

    函数模板函数模板可以实现对不同数据类型做统一操作,比如比较两个数据的大小:template<typename T> bool compare(T& a,T& b) {   return a...

    static_assert和assert有什么区别?

    static_assert和assert有什么区别?

    static_assert和assert都是断言,都可用于判断一个条件是否成立,并且在条件不成立时及时给出错误提示。那它们用什么不同和需要注意的地方呢? 1:static_assert在编译期执行,而assert在运行期执行。2:static_assert无论在debug模式还是relea...