borisbn

WatchDog.cpp

Mar 13th, 2013
709
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "WatchDog.h"
  2. #include <QMessageBox>
  3. #include <QCoreApplication>
  4. #include <QFile>
  5. #include <QMenu>
  6. #include <QCloseEvent>
  7. #include <QProcess>
  8. #include <QFileInfo>
  9. #include <QDateTime>
  10. #include <QRegExp>
  11. #include <string>
  12. #include "BorIni.h"
  13.  
  14. #include <tlhelp32.h>
  15.  
  16. const int INTERVAL_SEC = 15;
  17. const char * const COMMON_SECTION = "common";
  18.  
  19. WatchDog::WatchDog( QWidget * parent, Qt::WFlags flags )
  20.     : QDialog( parent, flags )
  21. {
  22.     ui.setupUi( this );
  23.    
  24.     m_restoreAction = new QAction( QIcon( ":/images/restore" ), "Восстановить", this );
  25.     connect( m_restoreAction, SIGNAL( triggered() ), this, SLOT( showNormal() ) );
  26.     QAction * quitAction = new QAction( QIcon( ":/images/close" ), "Выход", this );
  27.     connect( quitAction, SIGNAL( triggered() ), qApp, SLOT( quit() ) );
  28.  
  29.     QMenu * trayIconMenu = new QMenu( this );
  30.     trayIconMenu->addAction( m_restoreAction );
  31.     trayIconMenu->addSeparator();
  32.     trayIconMenu->addAction( quitAction );
  33.     trayIconMenu->setDefaultAction( m_restoreAction );
  34.  
  35.     m_trayIcon = new QSystemTrayIcon( this );
  36.     m_trayIcon->setContextMenu( trayIconMenu );
  37.     m_trayIcon->setToolTip( "Watch Dog. v. 2.0.0" );
  38.     connect( m_trayIcon
  39.         , SIGNAL( activated( QSystemTrayIcon::ActivationReason ) )
  40.         , SLOT( iconActivated( QSystemTrayIcon::ActivationReason ) )
  41.         );
  42.  
  43.     QIcon icon = QIcon( ":/images/dog" );
  44.     m_trayIcon->setIcon( icon );
  45.     setWindowIcon( icon );
  46.  
  47.     m_trayIcon->show();
  48.    
  49.     BorIni ini( "./WatchDog.ini", true );
  50.     m_timerInterval = ini.getInt( COMMON_SECTION, "interval (sec)", INTERVAL_SEC ) * 1000;
  51.     std::vector< std::string > sections = ini.sections();
  52.     for ( int i = 0, sectionsCount = sections.size(); i < sectionsCount; i++ )
  53.     {
  54.         const std::string & section = sections[ i ];
  55.         if ( section == COMMON_SECTION )
  56.         {
  57.             continue;
  58.         }
  59.         ExeParams exeParam;
  60.         exeParam.exeName = section.c_str();
  61.         exeParam.startCommand = ini.getString( section, "startCommand", section ).c_str();
  62.         std::vector< std::string > keys = ini.keys( section );
  63.         for ( int k = 0, keysCount = keys.size(); k < keysCount; k++ )
  64.         {
  65.             const std::string & key = keys[ k ];
  66.             if ( key == "startCommand" )
  67.             {
  68.                 continue;
  69.             }
  70.             std::string mask = ini.getString( section, key );
  71.             if ( ! mask.empty() )
  72.             {
  73.                 exeParam.captionMasks.push_back( mask.c_str() );
  74.             }
  75.         }
  76.         m_exeNames.push_back( exeParam );
  77.     }
  78.  
  79.     startTimer( m_timerInterval );
  80. }
  81.  
  82. WatchDog::~WatchDog()
  83. {
  84. }
  85.  
  86. void WatchDog::setVisible( bool visible )
  87. {
  88.     m_restoreAction->setEnabled( ! visible );
  89.     QDialog::setVisible( visible );
  90. }
  91.  
  92. void WatchDog::closeEvent( QCloseEvent * event )
  93. {
  94.     if ( m_trayIcon->isVisible() )
  95.     {
  96.         hide();
  97.         event->ignore();
  98.     }
  99. }
  100.  
  101. void WatchDog::iconActivated( QSystemTrayIcon::ActivationReason reason )
  102. {
  103.     switch ( reason )
  104.     {
  105.         case QSystemTrayIcon::DoubleClick:
  106.             if ( m_restoreAction->isEnabled() )
  107.             {
  108.                 m_restoreAction->trigger();
  109.             }
  110.         break;
  111.     }
  112. }
  113.  
  114. void WatchDog::timerEvent( QTimerEvent * event )
  115. {
  116.     m_windows.clear();
  117.     EnumWindows( nextWindow, (LPARAM) this );
  118.  
  119.     for ( int i = 0, exeNamesSize = m_exeNames.size(); i < exeNamesSize; i++ )
  120.     {
  121.         const ExeParams & exeParam = m_exeNames[ i ];
  122.         QString exe = exeParam.exeName.toLower();
  123.         QString logReason;
  124.  
  125.         DWORD processId = getProcessId( exe );
  126.         bool processFound = ( processId != 0 );
  127.  
  128.         if ( processFound && ! exeParam.captionMasks.isEmpty() )
  129.         {
  130.             for ( int j = 0, windowsSize = m_windows.size(); j < windowsSize; j++ )
  131.             {
  132.                 HWND hWnd = m_windows[ j ];
  133.                 DWORD wndProcessId = (DWORD)-1;
  134.                 GetWindowThreadProcessId( hWnd, & wndProcessId );
  135.                 if ( wndProcessId == processId )
  136.                 {
  137.                     if ( isCaptionMatches( hWnd, exeParam.captionMasks ) )
  138.                     {
  139.                         HANDLE hProcess = OpenProcess( PROCESS_TERMINATE, FALSE, processId );
  140.                         if ( hProcess != 0 )
  141.                         {
  142.                             TerminateProcess( hProcess, 0 );
  143.                             processFound = false;
  144.                             logReason = "обнаружено окно с заголовком \"" + getWindowCaption( hWnd ) + "\"";
  145.                             break;
  146.                         }
  147.                     }
  148.                 }
  149.             }
  150.         }
  151.         else
  152.         {
  153.             logReason = "приложение отсутствует в списке процессов";
  154.         }
  155.        
  156.         if ( processFound == false )
  157.         {
  158.             QProcess::startDetached( exeParam.startCommand, QStringList(), QFileInfo( exe ).absolutePath() );
  159.             QFile logFile( "WatchDog.log" );
  160.             if ( logFile.open( QIODevice::Append | QIODevice::Text ) )
  161.             {
  162.                 QString msg = QDateTime::currentDateTime().toString( "dd.MM.yyyy hh:mm:ss.zzz" ) +
  163.                               "    " + QFileInfo( exe ).fileName() + "    " + logReason + "    перезапуск\n";
  164.                 logFile.write( msg.toAscii() );
  165.             }
  166.             break;
  167.         }
  168.    }
  169. }
  170.  
  171. BOOL CALLBACK WatchDog::nextWindow( HWND hwnd, LPARAM lParam )
  172. {
  173.     WatchDog * self = (WatchDog*)lParam;
  174.     self->m_windows.push_back( hwnd );
  175.     return TRUE;
  176. }
  177.  
  178. DWORD WatchDog::getProcessId( const QString & exe )
  179. {
  180.     //  Take a snapshot of all processes in the system.
  181.     HANDLE hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
  182.     if ( INVALID_HANDLE_VALUE == hProcessSnap )
  183.     {
  184.         QMessageBox::critical( 0, "Ошибка", "CreateToolhelp32Snapshot вернула INVALID_HANDLE_VALUE" );
  185.         QCoreApplication::quit();
  186.         return 0;
  187.     }
  188.  
  189.     DWORD processId = 0;
  190.     //  Fill in the size of the structure before using it.
  191.     PROCESSENTRY32 pe32 = {0};
  192.     pe32.dwSize = sizeof( PROCESSENTRY32 );
  193.     if ( Process32First( hProcessSnap, &pe32 ) )
  194.     {
  195.         do
  196.         {
  197.             QString processName = QString::fromWCharArray( pe32.szExeFile ).toLower();
  198.             if ( exe.endsWith( processName ) )
  199.             {
  200.                 processId = pe32.th32ProcessID;
  201.                 break;
  202.             }
  203.         }
  204.         while ( Process32Next( hProcessSnap, &pe32 ) );
  205.     }
  206.     CloseHandle( hProcessSnap );
  207.     return processId;
  208. }
  209.  
  210. QString WatchDog::getWindowCaption( HWND hwnd )
  211. {
  212.     QString caption;
  213.     int captionLength = GetWindowTextLengthA( hwnd );
  214.     if ( captionLength != 0 )
  215.     {
  216.         char * c_caption = new char[ captionLength + 1 ];
  217.         GetWindowTextA( hwnd, c_caption, captionLength + 1 );
  218.         caption = c_caption;
  219.         delete []c_caption;
  220.     }
  221.     return caption;
  222. }
  223.  
  224. bool WatchDog::isCaptionMatches( HWND hwnd, const QStringList & masks )
  225. {
  226.     QString windowCaption = getWindowCaption( hwnd );
  227.     for ( int i = 0, masksCount = masks.size(); i < masksCount; i++ )
  228.     {
  229.         QRegExp rx( masks[ i ] );
  230.         rx.setPatternSyntax( QRegExp::Wildcard );
  231.         if ( rx.indexIn( windowCaption ) != -1 )
  232.         {
  233.             return true;
  234.         }
  235.     }
  236.     return false;
  237. }
Add Comment
Please, Sign In to add comment