TNB Library
TnbConsoleHooker.h
[詳解]
1#pragma once
11#include <Wincon.h>
12#ifdef __TNBPROCESSHANDLE_H__
13 #ifndef _TnbPROCESS_PipeInOut_ENABLE
14 #error Please define _TnbPROCESS_PipeInOut_ENABLE first rather than you include TnbProcessHandle.h.
15 #endif
16 #ifndef _TnbPROCESS_EnumProcesses_ENABLE
17 #error Please define _TnbPROCESS_EnumProcesses_ENABLE first rather than you include TnbProcessHandle.h.
18 #endif
19#endif
20
21#ifndef _TnbDOXYGEN //Document作成用シンボル
22 #define _TnbPROCESS_PipeInOut_ENABLE
23 #define _TnbPROCESS_EnumProcesses_ENABLE
24#endif
25#include "TnbProcessHandle.h"
26#include "TnbStrVector.h"
27#include "TnbStrOperator.h"
28
29
30
31//TNB Library
32namespace TNB
33{
34
35
36
48{
49public:
50
52 CConsoleHooker(void) : m_processId(0), m_isHooked(false), m_hStdOutput(NULL), m_hStdInput(NULL)
53 {
54 m_rep.SetKind(_T("ConsoleHooker"));
55 }
56
59 {
60 Unhook();
61 }
62
68 bool IsHooked(void) const
69 {
70 return m_isHooked || m_proc.IsAlive();
71 }
72
79 bool IsAlived(void) const
80 {
81 return (m_processId != 0 && ::GetProcessVersion(m_processId) != 0);
82 }
83
89 DWORD GetProcessId(void) const
90 {
91 return m_processId;
92 }
93
100 bool Hook(DWORD processId)
101 {
102 m_processName.Format(_T("%d"), processId);
103 return m_Hook(processId);
104 }
105
113 bool Hook(LPCTSTR lpszProcessName)
114 {
115 m_processName = lpszProcessName;
116 DWORD id = 0;
118 CTickCount tc;
119 do
120 {
121 if ( CProcessHandle::EnumProcesses(ids, lpszProcessName) )
122 {
123 if ( ids.GetSize() > 0 )
124 {
125 id = ids[0];
126 break;
127 }
128 }
129 }
130 while ( ! tc.IsPassed(2000) );
131 return m_Hook(id);
132 }
133
142 bool Execute(LPCTSTR lpszProcessName, bool isShow = false)
143 {
144 Unhook();
145 m_pipeOut.Open();
146 m_pipeIn.Open();
147 if ( m_proc.Create(lpszProcessName, &m_pipeIn, &m_pipeOut, NULL, isShow) )
148 {
149 m_processId = m_proc.GetProcessId();
150 CStr s = lpszProcessName;
151 s = m_processName.FindCut(' ');
152 if ( s.IsEmpty() )
153 {
154 s = lpszProcessName;
155 }
156 int r = ToInt(s.ReverseFindOneOf(_T("\\/")));
157 m_processName = (r < 0) ? s : s.Mid(r + 1);
158 return true;
159 }
160 return false;
161 }
162
167 void Terminate(void)
168 {
169 Unhook();
170 m_proc.Terminate();
171 }
172
177 void Unhook(void)
178 {
179 m_pipeIn.Close();
180 m_pipeOut.Close();
181 if ( m_isHooked )
182 {
183 ::FreeConsole();
184 m_hStdOutput = NULL;
185 m_hStdInput = NULL;
186 m_isHooked = false;
187 }
188 }
189
197 bool WaitForExit(DWORD to)
198 {
199 CTickCount tc;
200 do
201 {
202 if ( ::GetProcessVersion(m_processId) == 0 )
203 {
204 return true;
205 }
206 ::Sleep(1);
207 }
208 while ( ! tc.IsPassed(to) );
209 return false;
210 }
211
219 bool SendString(LPCTSTR lpsz)
220 {
221 if ( m_isHooked )
222 {
223 CStr s = lpsz;
224 size_t len = s.GetLength();
225 loop ( i, len )
226 {
227 if ( ! m_SendChar(s[i]) )
228 {
229 return false;
230 }
231 }
232 return true;
233 }
234 CAscii a = lpsz;
235 a.Replace('\r', '\n');
236 LPCSTR P = a;
237 size_t l = a.GetLength();
238 return (m_pipeIn.Send(l, P) == l);
239 }
240
246 {
247 CStrVector vs;
248 if ( m_isHooked )
249 {
250 m_WaitIdle();
251 CONSOLE_SCREEN_BUFFER_INFO sb;
252 if ( ::GetConsoleScreenBufferInfo(m_hStdOutput, &sb) )
253 {
254 size_t len = sb.dwCursorPosition.Y * sb.dwSize.X + sb.dwCursorPosition.X;
255 //
256 COORD coord = { 0, 0 };
257 size_t sz = len;
258 CWorkMemT<TCHAR> buf(sb.dwSize.X + 1);
259 DWORD dw;
260 while ( sz > 0 )
261 {
262 buf.Fill(0);
263 size_t z = min(sb.dwSize.X, ToInt(sz));
264 ::ReadConsoleOutputCharacter(m_hStdOutput, buf, ToDword(z), coord, &dw);
265 coord.Y++;
266 sz -= z;
267 CStr s = buf.Ref();
268 s.TrimRight(' ');
269 vs.Add(s);
270 TRACE2("%s [%s]\n", m_processName, s);
271 m_rep.ToViewer(CStr::Fmt(_T("%s [%s]\n"), m_processName, s));
272 }
273 coord.Y = 0;
274 ::FillConsoleOutputCharacter(m_hStdOutput, ' ', ToDword(len), coord, &dw);
275 ::SetConsoleCursorPosition(m_hStdOutput, coord);
276 }
277 }
278 else
279 {
280 size_t l = m_pipeOut.GetReceivingDataSize();
281 if ( l > 0 && l != INVALID_SIZE )
282 {
283 CWorkMemT<char> work(l + 1);
284 work.Fill(0); //終端
285 m_pipeOut.Receive(l, work);
287 loop ( i, va )
288 {
289 vs.Add(CStr(va[i]));
290 TRACE2("%s [%s]\n", m_processName, CStr(va[i]));
291 m_rep.ToViewer(CStr::Fmt(_T("%s [%s]\n"), m_processName, CStr(va[i])));
292 }
293 }
294 }
295 return vs;
296 }
297
306 bool WaitString(LPCTSTR lpsz, DWORD to)
307 {
308 m_lastStrings.RemoveAll();
309 CStr a = lpsz;
310 CTickCount tc;
311 do
312 {
313 if ( ::GetProcessVersion(m_processId) == 0 )
314 {
315 return false;
316 }
317 CStrVector vs = GetString();
318 m_lastStrings.Append(vs);
319 loop ( i, vs )
320 {
321 if ( vs[i].Find(a) != INVALID_INDEX )
322 {
323 return true;
324 }
325 }
326 ::Sleep(1);
327 }
328 while ( ! tc.IsPassed(to) );
329 return false;
330 }
331
341 int WaitStringEx(const CStrVector& words, DWORD to)
342 {
343 m_lastStrings.RemoveAll();
344 CTickCount tc;
345 do
346 {
347 if ( ::GetProcessVersion(m_processId) == 0 )
348 {
349 return -2;
350 }
351 CStrVector vs = GetString();
352 m_lastStrings.Append(vs);
353 loop ( j, words )
354 {
355 loop ( i, vs )
356 {
357 if ( vs[i].Find(words[j]) != INVALID_INDEX )
358 {
359 return ToInt(j);
360 }
361 }
362 }
363 ::Sleep(1);
364 }
365 while ( ! tc.IsPassed(to) );
366 return -1;
367 }
368
380 int WaitStringEx(LPCTSTR lpszWord1, LPCTSTR lpszWord2, DWORD to)
381 {
382 CStrVector vs;
383 vs.Add(lpszWord1);
384 vs.Add(lpszWord2);
385 return WaitStringEx(vs, to);
386 }
387
393 const CStrVector& GetLastString(void) const
394 {
395 return m_lastStrings;
396 }
397
403 void SetLastString(const CStrVector& vs)
404 {
405 m_lastStrings = vs;
406 }
407
408private:
410 bool m_Hook(DWORD processId)
411 {
412 Unhook();
413 if ( ::AttachConsole(processId) )
414 {
415 m_hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
416 m_hStdOutput = reinterpret_cast<HANDLE>(7);
417 m_hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
418 if ( m_hStdOutput != NULL && m_hStdInput != NULL )
419 {
420 m_processId = processId;
421 m_isHooked = true;
422 return true;
423 }
424 }
425 _GetLastError("AttachConsole");
426 return false;
427 }
429 bool m_WaitIdle(DWORD to = 500)
430 {
431 ASSERT( m_isHooked );
432 CONSOLE_SCREEN_BUFFER_INFO sb1;
433 CONSOLE_SCREEN_BUFFER_INFO sb;
434 if ( ! ::GetConsoleScreenBufferInfo(m_hStdOutput, &sb1) )
435 {
436 _GetLastError("GetConsoleScreenBufferInfo");
437 return false;
438 }
439 while ( true )
440 {
441 CTickCount tc;
442 bool isIdle = true;
443 do
444 {
445 ::Sleep(100);
446 if ( ! ::GetConsoleScreenBufferInfo(m_hStdOutput, &sb) )
447 {
448 return false;
449 }
450 if ( sb1.dwCursorPosition.X != sb.dwCursorPosition.X || sb1.dwCursorPosition.Y != sb.dwCursorPosition.Y )
451 {
452 isIdle = false;
453 break;
454 }
455 }
456 while ( ! tc.IsPassed(to) );
457 if ( isIdle )
458 {
459 return true;
460 }
461 sb1 = sb;
462 }
463 return false;
464 }
466 bool m_SendChar(TCHAR c)
467 {
468 ASSERT( m_isHooked );
469 INPUT_RECORD ir[2] = { 0 };
470 ir[0].EventType = KEY_EVENT;
471 #ifndef _UNICODE
472 ir[0].Event.KeyEvent.uChar.AsciiChar = c;
473 #else
474 ir[0].Event.KeyEvent.uChar.UnicodeChar = c;
475 #endif
476 ir[1] = ir[0];
477 ir[0].Event.KeyEvent.bKeyDown = true;
478 DWORD dw;
479 if ( ::WriteConsoleInput(m_hStdInput, ir, 2, &dw) )
480 {
481 return dw == 2;
482 }
483 return false;
484 }
485 CStr m_processName;
486 DWORD m_processId;
487 bool m_isHooked;
488 HANDLE m_hStdOutput;
489 HANDLE m_hStdInput;
490 CPipe m_pipeIn;
491 CPipe m_pipeOut;
492 CProcessHandle m_proc;
493 CStrVector m_lastStrings;
494 CReportViewerEx m_rep;
495};
496
497
498
499}; // TNBLIB
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
プロセスハンドル管理ヘッダ
文字列操作関係のヘッダ
文字列情報配列管理関係のヘッダ
コンソールフッカークラス
void Unhook(void)
[設定] アンフック.
bool SendString(LPCTSTR lpsz)
[送信] 文字列送信.
void Terminate(void)
[設定] ターミネート.
bool Hook(LPCTSTR lpszProcessName)
[設定] フック.
bool Hook(DWORD processId)
[設定] フック.
bool Execute(LPCTSTR lpszProcessName, bool isShow=false)
[設定] 実行.
DWORD GetProcessId(void) const
[取得] プロセスID取得.
const CStrVector & GetLastString(void) const
[取得] 取得文字列取得.
CConsoleHooker(void)
コンストラクタ
bool WaitForExit(DWORD to)
[処理] 終了待ち.
bool IsHooked(void) const
[確認] フック済み?
~CConsoleHooker(void)
デストラクタ
CStrVector GetString(void)
[取得] コンソール文字列取得.
int WaitStringEx(LPCTSTR lpszWord1, LPCTSTR lpszWord2, DWORD to)
[取得] 指定文字列待ち.
void SetLastString(const CStrVector &vs)
[設定] 取得文字列設定.
bool IsAlived(void) const
[確認] プロセス生存確認.
bool WaitString(LPCTSTR lpsz, DWORD to)
[取得] 指定文字列待ち.
int WaitStringEx(const CStrVector &words, DWORD to)
[取得] 指定文字列待ち.
[ETC] コピー不可能スーパークラス.
Definition: TnbDef.h:599
パイプアクセスクラス
Definition: TnbPipe.h:38
virtual bool Open(void)
[処理] オープン.
Definition: TnbPipe.h:105
virtual void Close(void)
[処理] クローズ.
Definition: TnbPipe.h:142
virtual size_t Receive(size_t size, LPVOID _P)
[処理] 受信.
Definition: TnbPipe.h:198
virtual size_t GetReceivingDataSize(void) const
[確認] 受信データ確認.
Definition: TnbPipe.h:226
virtual size_t Send(size_t size, LPCVOID P)
[処理] 送信.
Definition: TnbPipe.h:178
プロセスハンドル管理クラス
bool Terminate(UINT uExitCode=0)
[通知] 強制終了.
static bool EnumProcesses(CWorkMemT< DWORD > &_ids)
[取得] プロセスID一覧取得
DWORD GetProcessId(void) const
[取得] プロセスID取得
bool Create(LPCTSTR lpszExecName, LPCTSTR lpszCommand, STARTUPINFO &si)
[実行] プロセス実行
bool IsAlive(void) const
[確認] 起動確認.
TNBレポートビュワー
void SetKind(DWORD kind)
[設定] 種類設定.
void ToViewer(size_t sizeData, LPCVOID lpcvData, DWORD dire=0)
[出力] ダンプ出力.
static CVectorT< CStrT< TYP > > SeparateLine(const TYP *lpsz)
[取得] 改行毎分離
INT_PTR ReverseFindOneOf(const TYP *lpsz) const
[確認] 検索(後ろから)
Definition: TnbStr.h:621
bool IsEmpty(void) const
[確認] 空チェック
Definition: TnbStr.h:528
size_t GetLength(void) const
[取得] 文字列長
Definition: TnbStr.h:518
static CStrT Fmt(const TCHAR *lpszFormat,...)
[作成] 書式付き文字列作成
Definition: TnbStr.h:1206
CStrT & TrimRight(TYP t=' ')
[処理] 末尾から文字をトリム.
Definition: TnbStr.h:990
CStrT FindCut(TYP c, CStrT *_pstrRest=NULL) const
[作成] 切り分け
Definition: TnbStr.h:1122
int Replace(TYP tOld, TYP tNew)
[処理] 文字置換.
Definition: TnbStr.h:1038
void Format(const TYP *lpszFormat,...)
[代入] 書式付き文字列代入.
Definition: TnbStr.h:359
CStrT Mid(INDEX iOffset, size_t iSize=INVALID_SIZE) const
[作成] 範囲取得.
Definition: TnbStr.h:766
経過時間管理クラス
Definition: TnbTickCount.h:57
bool IsPassed(DWORD dwTime) const
[確認] 経過確認.
Definition: TnbTickCount.h:114
virtual bool RemoveAll(void)
[削除] 空化
Definition: TnbVector.h:565
virtual INDEX Add(const TYP &t)
[追加] 要素一つ追加.
Definition: TnbVector.h:383
virtual size_t Append(const IConstCollectionT< TYP > &c)
[追加] 追加.
Definition: TnbVector.h:545
size_t GetSize(void) const
[取得] サイズ取得
Definition: TnbDef.h:665
void Fill(const TYP &other)
[設定] 全情報代入.
Definition: TnbDef.h:724
const TYP * Ref(void) const
[取得] ポインタ取得
Definition: TnbDef.h:712
DWORD ToDword(LPCSTR lpsz, int iBase=10)
[変換] INT変換(ASCII/SJIS用).
Definition: TnbStrLib.h:395
TNB::CStrT< TCHAR > CStr
文字列クラス
Definition: TnbStr.h:1785
int ToInt(LPCSTR lpsz, int iBase=10)
[変換] INT変換(ASCII/SJIS用).
Definition: TnbStrLib.h:367
TNB Library
Definition: TnbDoxyTitle.txt:2