📄 tracetool.cpp.svn-base
字号:
// tracetool.h
//
// Author : Thierry Parent
// Version : 8.1.0
//
// HomePage : http://www.codeproject.com/csharp/TraceTool.asp
// Download : http://sourceforge.net/projects/tracetool/
// See License.txt for license information
#include "stdafx.h" // remove precompiled header
#include <windows.h>
#include <stdio.h>
#include <winsock.h>
#include <tchar.h>
#include <assert.h>
#ifndef _WIN32_WCE
#include <process.h>
#else
#include <Kfuncs.h>
#endif
#include "tracetool.h"
// static TTrace initialization
struct sockaddr_in TTrace::m_serverSockAddr ; // Socket adress
CRITICAL_SECTION TTrace::criticalSection ;
TraceOptions * TTrace::m_options = new TraceOptions();
WinTrace * TTrace::m_winTrace = new WinTrace() ;
WinWatch * TTrace::m_winWatch = new WinWatch() ;
WORD TTrace::m_DeviceId1 = 0;
WORD TTrace::m_DeviceId2 = 0;
WORD TTrace::m_DeviceId3 = 0;
bool TTrace::m_IsSocketInitialized = false ;
int TTrace::m_socketHandle = -1;
DWORD TTrace::m_ClockSequenceBase = TTrace::Init(); // Initialize the Tracetool system
//==========================================================================
// TTRACE
/// <summary>
// Initialize the Tracetool system
/// </summary>
DWORD TTrace::Init (void)
{
InitializeCriticalSection(&criticalSection);
// The spatially unique node identifier. Because we are not sure there is a network card ,
// we generate random number instead of unique network card id.
m_DeviceId1 = LOWORD(GetTickCount()*rand());
m_DeviceId2 = LOWORD(rand());
m_DeviceId3 = LOWORD(rand());
// sequence number
m_ClockSequenceBase = rand();
return m_ClockSequenceBase ;
}
//-------------------------------------------------------------------------
void TTrace::Stop (void)
{
CloseSocket() ;
if (m_options != NULL)
delete m_options ;
m_options = NULL ;
if (m_winTrace != NULL)
delete m_winTrace ;
if (m_winWatch != NULL)
delete m_winWatch ;
m_winTrace = NULL ;
}
//-------------------------------------------------------------------------
/// <summary>
// Close viewer connection.
// Replace TTrace destructor
/// </summary>
void TTrace::CloseSocket()
{
if (m_IsSocketInitialized == true)
{
// close connection
shutdown(m_socketHandle,2); // SD_BOTH
closesocket(m_socketHandle);
WSACleanup();
m_IsSocketInitialized = false ;
}
//DeleteCriticalSection(&criticalSection) ;
}
//-------------------------------------------------------------------------
/// <summary>
// Helper function : convert a widestring to a C string.
// The caller is responsive to destroy the new string
/// </summary>
char * TTrace::WideToMbs (const wchar_t * WideStr)
{
if (WideStr == NULL)
return NULL ;
int lenStr = wcslen(WideStr) + 1 ;
char * result = (char *) malloc (lenStr) ;
#if defined(_MSC_VER) && (_MSC_VER >= 1400) && (! UNDER_CE) // visual studio 2005 : deprecated function
size_t i ;
wcstombs_s(&i, result, lenStr, WideStr, lenStr );
#else
wcstombs(result , WideStr, lenStr );
#endif
return result ;
}
//-------------------------------------------------------------------------
/// <summary>
// Create an unique ID.
// For windows CE compatibility reason, we cannot ask microsoft API to return an unique ID
// Since this function uses random generator instead of computer id it cannot be
// garanted that generated GUID is unique in the world.
/// </summary>
char * TTrace::CreateTraceID() // static
{
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
WORD Sequence ;
char * bufferId ;
SYSTEMTIME systemTime;
FILETIME fileTime;
GetSystemTime(&systemTime);
BOOL bResult = SystemTimeToFileTime(&systemTime, &fileTime);
if (!bResult)
return NULL;
//0-3 The low field of the timestamp.
Data1 = fileTime.dwLowDateTime;
//4-5 The middle field of the timestamp.
Data2 = LOWORD(fileTime.dwHighDateTime);
//6-7 The high field of the timestamp multiplexed
// with the version number.
// Version number is 0x0002
Data3 = (HIWORD(fileTime.dwHighDateTime) & 0xFFF0) | 0x0002;
//8-9 Here we store sequence number
m_ClockSequenceBase++;
Sequence = LOWORD(m_ClockSequenceBase);
//10-15 The spatially unique node identifier.
// Because there is no network card we generate random number
// instead of unique network card id.
bufferId = (char*)malloc(32+1);
#if defined(_MSC_VER) && (_MSC_VER >= 1400) && (! UNDER_CE) // visual studio 2005 : deprecated function
sprintf_s (bufferId, 33,"%08x%04x%04x%04x%04x%04x%04x", Data1, Data2, Data3, Sequence,m_DeviceId1,m_DeviceId2,m_DeviceId3) ;
#else
sprintf (bufferId, "%08x%04x%04x%04x%04x%04x%04x", Data1, Data2, Data3, Sequence,m_DeviceId1,m_DeviceId2,m_DeviceId3) ;
#endif
return bufferId;
}
//-------------------------------------------------------------------------
HWND StartDebugWin ()
{
#ifndef _WIN32_WCE
// first check if already running
HWND hWndDBG;
hWndDBG = FindWindow(TEXT("TFormReceiver"), TEXT("FormReceiver"));
if (hWndDBG!=NULL)
return hWndDBG ;
// get the path in the registry
HKEY hKey;
char Buffer[MAX_PATH]; // char
DWORD dwBufferSize = MAX_PATH;
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\TraceTool",
0, KEY_READ, &hKey);
RegQueryValueEx( hKey, "FilePath", NULL, NULL, (LPBYTE) Buffer, &dwBufferSize);
RegCloseKey(hKey);
// run the tracetool process
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW ;
si.wShowWindow = SW_NORMAL ;
ZeroMemory( &pi, sizeof(pi) );
if (CreateProcess(Buffer, NULL, NULL, NULL, false, 0, NULL, NULL, &si, &pi) == false)
return NULL ;
// wait for the proces
WaitForInputIdle(pi.hProcess, 3 * 1000); // wait for 3 seconds to get idle
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
// check if the window is created now
hWndDBG = FindWindow(TEXT("TFormReceiver"), TEXT("FormReceiver"));
if (hWndDBG!=NULL)
return hWndDBG ;
#endif
// stil not found ? Run traceTool first to register it
return NULL ;
}
//-------------------------------------------------------------------------
/// <summary>
/// send the trace to the viewer
/// </summary>
/// <param name="Commands">The list of command to send</param>
/// <param name="winWatch">window watch</param>
void TTrace::SendToClient(CommandList * Commands, const WinWatch * winWatch)
{
Commands->AddFront(CST_WINWATCH_ID, winWatch->id.c_str());
SendToClient(Commands) ;
}
//-------------------------------------------------------------------------
/// <summary>
/// send the trace to the viewer
/// </summary>/// <param name="Commands">The list of command to send</param>
/// <param name="winTrace">window trace</param>
void TTrace::SendToClient(CommandList * Commands, const WinTrace * winTrace)
{
// CST_USE_TREE MUST be inserted at the first position
if (winTrace != NULL && winTrace->id != "")
Commands->AddFront (CST_USE_TREE ,winTrace->id.c_str());
SendToClient(Commands) ;
}
//-------------------------------------------------------------------------
/// <summary>
/// send the trace to the viewer
/// </summary>/// <param name="Commands">The list of command to send</param>
void TTrace::SendToClient(CommandList * Commands)
{
// TODO : place the Command list into a stack and let a thread send it !!!!!!!!!!!
// Save the last error. TraceTool must be neutral about the error
DWORD err = GetLastError() ;
// compute line size and create buffer to send
size_t j ; // int j;
char *line;
j=0;
CommandList::const_iterator c1_elem ;
CommandList::const_iterator c1_end ;
c1_end = Commands->end () ;
for (c1_elem = Commands->begin (); c1_elem < c1_end ; c1_elem++)
j += (* c1_elem).length() +1 ;
line=(char*)malloc(j+1);
// create a single buffer line for all commands
j=0;
for (c1_elem = Commands->begin (); c1_elem < c1_end ; c1_elem++)
{
string str = (* c1_elem) ;
size_t strLen = str.length()+1 ;
memcpy(line+j,str.c_str(),strLen);
j += strLen ;
}
Commands->clear() ;
line[j]=0;
if (m_options->sendMode == Socket)
{
// ensure only one thread send strings to the viewer using socket.
EnterCriticalSection (&criticalSection) ;
int err;
WSADATA wsaData;
if (m_IsSocketInitialized == false)
{
err = WSAStartup( MAKEWORD(1,1), &wsaData );
if ( err != 0 )
{
LeaveCriticalSection (&criticalSection) ;
return;
}
memset(&m_serverSockAddr,0,sizeof(m_serverSockAddr));
// Try to convert the string as an IP address (e.g., "192.168.55.100")
m_serverSockAddr.sin_addr.s_addr = inet_addr(m_options->socketHost); // host to network port
// If not in IP format, get the address via DSN...
if (m_serverSockAddr.sin_addr.s_addr == INADDR_NONE)
{
hostent* lphost;
// request the host address
lphost = gethostbyname(m_options->socketHost); // lphost is allocated by Windows Sockets
if (lphost != NULL) {
m_serverSockAddr.sin_addr.S_un.S_addr = ((LPIN_ADDR)lphost->h_addr_list[0])->s_addr;
//wsprintf (Host_adr, L"%s (%d.%d.%d.%d)", Host,
// serverSockAddr.sin_addr.S_un.S_un_b.s_b1,
// serverSockAddr.sin_addr.S_un.S_un_b.s_b2,
// serverSockAddr.sin_addr.S_un.S_un_b.s_b3,
// serverSockAddr.sin_addr.S_un.S_un_b.s_b4) ;
} else { // else name was invalid (or couldn't be resolved)
LeaveCriticalSection (&criticalSection) ;
return;
}
}
m_serverSockAddr.sin_port = htons(m_options->socketPort); // port to network port
m_serverSockAddr.sin_family = AF_INET; // AF_*** : INET=internet
// Socket creation
if ( (m_socketHandle = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
//MessageBox(NULL,_T("Couldn't create socket"),_T("Socket Error"),MB_OK);
LeaveCriticalSection (&criticalSection) ;
return;
}
// Open connection
if(connect(m_socketHandle,(struct sockaddr *)&m_serverSockAddr, sizeof(m_serverSockAddr))<0) {
//MessageBox(NULL,_T("Couldn't connect"),_T("Socket Error"),MB_OK);
LeaveCriticalSection (&criticalSection) ;
return;
}
m_IsSocketInitialized = true ;
}
// send the line lenght
char buffer [100] ;
#if defined(_MSC_VER) && (_MSC_VER >= 1400) && (! UNDER_CE) // visual studio 2005 : deprecated function
sprintf_s(buffer,100,"%d",j);
#else
sprintf(buffer,"%d",j);
#endif
send(m_socketHandle,buffer,strlen(buffer)+1,0);
// send the buffer
int i = send(m_socketHandle,line,j,0);
LeaveCriticalSection (&criticalSection) ;
//
//TCHAR message[256];
//_stprintf(message,TEXT("Done: %d bytes sent (%d normally)"),i,j);
//MessageBox(NULL,message,_T("Socket Error"),MB_OK);
} else {
HWND hWndDBG;
hWndDBG = StartDebugWin() ; // FindWindow(TEXT("TFormReceiver"), TEXT("FormReceiver"));
if (hWndDBG!=NULL) {
COPYDATASTRUCT CDS;
CDS.cbData = j+1;
CDS.dwData = WMD_TRACETOOL; // identification code 'traceTool'
CDS.lpData = line; // no need to add #0, because String are null terminated
SendMessage(hWndDBG, WM_COPYDATA, 0, (LPARAM)(&CDS)); //WParam(Application.Handle)
}
}
free(line);
SetLastError (err) ; // preserve last error
}
//-------------------------------------------------------------------------
/// <summary>
/// Clear all traces (main window)
/// </summary>
void TTrace::ClearAll ()
{
m_winTrace->ClearAll () ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -