Download demo project - 148 Kb
Download source files - 8 Kb
SoftechSoftware
homepage
SoftechSoftware Email
If you write commercial or real-time applications you are familiar
with trace strings. These traces are those cryptic strings sent to
screen or disk that help the programmer during the debug phase of his work.
If you write more than one application that needs traces you will
look for a standard, simple to integrate and easy to use trace system.
CTracerST
presents a consistent way to implement and use
a trace system inside your applications.
Features of this class are:
This class has been tested on:
-
Visual C++ 6.0 sp3
- Windows NT Workstation 4.0 sp6a
- Windows 2000
Terms of use
You can use CTracerST
anywhere you want, without limitations.
You can include this software in DLLs, libriaries, CD-ROM collections
etc. You are only asked to give credits to SoftechSoftware
for this portion of code.
If you use this class a screenshot of your application or a download
link (if shareware/freeware) is welcome.
If you find bugs or make improvements please let SoftechSoftware
know it!
Abstract
Basically CTracerST
accepts a string and a trace level.
If the level is enabled the string is stored internally else it is
discarded. Also, if save-to-disk is enabled, the string is
immediately saved.
Why trace levels?
Your application can produce a lot of trace strings. If you assign a
particular type of information (info/errors/fatal errors ...) to each
string then you will have the ability to programmatically select
which type of traces produce. For example if you trace all
information at level 0 then all information can be toggled on and off
by disabling level 0 traces.
Trace strings are stored internally in the form of a STRUCT_TRACERST
structure:
typedef struct _STRUCT_TRACERST
{
DWORDdwLevel;
TCHARszText[256];
SYSTEMTIMEcsTime;
} STRUCT_TRACERST;
You will need to play with this structure only if your application
needs to display the trace strings.
CTracerST
saves strings on disk in a plain text file. If
your application is built for UNICODE then these text files will be
UNICODE, that is, the characters 0xFFFE are written at the top of
file. This marker seems to be a standard mode to recognize an UNICODE
text file (Notepad does this).
The filename of the produced files is in the form ddmmyyyy_Tracexxx.txt
where xxx is a number starting from 000 to 255. CTracerST
has the ability to produce files more or less of a predefined size;
eachtime a new file is created it will be numbered sequentially from
0 to 255. The numeration starts by default from 0.
Example: 07062000_Trace000.txt
Trace strings are written in the form hh:mm:ss:ms [level]
< trace string>
Example: 09:26:03:0214 [0] Database started (Size = 32672 bytes)
CSharedQueueST
CTracerST
stores trace strings using a queue implemented
through a class called CSharedQueueST
.
When an element is added to the queue this class has the ability to:
Using one of this ways an application that needs to display trace
strings can detect when a new string is available.
The correct steps required to get a trace string from CTracerST
are:
The following example shows how to display trace strings using a listbox:
STRUCT_TRACERST csTracer;
TCHAR szText[512];
int nIndex;
COLOR="BLUE">if (m_Tracer.GetItem((char*)&csTracer) == TRACERST_OK)
{
COLOR="GREEN">
COLOR="GREEN">
COLOR="BLUE">if (nIndex != LB_ERR && nIndex != LB_ERRSPACE)
m_lbxTrace.SetCurSel(nIndex);
}
How to integrate CTracerST in your application
Include in your application's project the following files:
<LI
CLASS="mvd-PRE">TracerST.h
<LI
CLASS="mvd-PRE">TracerST.cpp
<LI
CLASS="mvd-PRE">SharedQueueST.h
<LI
CLASS="mvd-PRE">SharedQueueST.cpp
<LI
CLASS="mvd-PRE">Macros.h
declare a CTracerST
object:
CTracerST m_Tracer;
initialize your object:
m_Tracer.Create(250, 64, FALSE, this->m_hWnd, WM_APP + 1);
That's all! To use your tracer:
m_Tracer.Trace(0, _T("Trace string"));
CTracerST methods
Constructor
CTracerST();
Standard constructor. It does nothing.
Create
DWORD Create(DWORD dwMaxItems,
DWORD dwMaxFilesize,
BOOL bUseAlternateDateFormat,
HWND hWndParent = NULL,
UINT nMsgParent = NULL,
HANDLE hEventParent = NULL,
HANDLE hThreadHandle = NULL);
Initializes a CTracerST
object.
Parameters:
-
dwMaxItems
[IN] Maximum number of trace strings the object can hold.
-
dwMaxFilesize
[IN] Maximum size (in KBytes) of the saved files.
-
bUseAlternateDateFormat
[IN] Indicates if an alternate date-format convention must be used.
If TRUE files will be saved in the form mmddyyyy_Tracexxx.txt
If FALSE files will be saved in the form ddmmyyyy_Tracexxx.txt
-
hWndParent
[IN] Handle of the window that will receive a message every time a
string is traced.
-
nMsgParent
[IN] Message to send every time a string is traced.
-
hEventParent
[IN] Handle of the event to set every time a string is traced.
-
hThreadParent
[IN] Handle of the thread to resume every time a string is traced.
Return value:
Example:
DWORD dwRetValue;
dwRetValue = m_Tracer.Create(250, 64, FALSE, this->m_hWnd, WM_APP + 1);
ASSERT(dwRetValue == TRACERST_OK);
Trace
DWORD Trace(BYTE byLevelNumber, LPCTSTR lpszText);
Traces a string.
Parameters:
Remarks:
If the trace level is disabled the string will be ignored and
discarded. Also no message/event/thread will be sent/set/resumed. If
the trace level is outside the limits the string will be processed.
You can use SetTraceLevels
to enable/disable trace levels.
If the save flag is set then the string will be written to disk in
the specified directory. You can use SetFlags
to
set/reset flags and SetTraceDirectory
to set the
directory in which to save trace files.
CTracerST
comes with a default of 10 trace levels. If
you need more levels just change the TRACERST_MAX_LEVELS
define located in the TracerST.h
file.
#defineTRACERST_MAX_LEVELS 10
Return value:
Example:
DWORD dwRetValue;
COLOR="GREEN">
GetItem
DWORD GetItem(char* szpBuffer,
BOOL bRemove = TRUE,
LPDWORD lpdwNumBytesCopied = NULL);
Gets the first available trace data from the CTracerST's queue.
Parameters:
-
szpBuffer
[IN] Points to a STRUCT_TRACERST
structure that will
receive the trace data.
It must be cast as char*
.
-
bRemove
[IN] Indicates if the trace data must be removed from the queue.
If TRUE the trace data will be removed from the queue.
If FALSE the trace data will remain in the queue. A second call to GetItem
will return the same trace data.
This value should be always TRUE.
-
lpdwNumBytesCopied
[OUT] Returns the number of bytes copied in szpBuffer
.
This value is always SIZE_STRUCT_TRACERST
.
Return value:
Example:
STRUCT_TRACERST csTracer;
TCHAR szText[512];
int nIndex;
COLOR="BLUE">if (m_Tracer.GetItem((char*)&csTracer) == TRACERST_OK)
{
COLOR="GREEN">
COLOR="GREEN">
COLOR="BLUE">if (nIndex != LB_ERR && nIndex != LB_ERRSPACE)
m_lbxTrace.SetCurSel(nIndex);
}
SetTraceDirectory
void SetTraceDirectory(LPCTSTR lpszTraceDir);
Sets the directory where trace files are to be saved.
Parameters:
Remarks:
By default trace files are saved in the directory from which the
application loaded.
Example:
m_Tracer.SetTraceDirectory(_T("c:\\traces\\"));
GetTraceLevels
void GetTraceLevels(LPBYTE lpbyTraceLevels);
Retrieves the state (enabled/disabled) of all trace levels.
Parameters:
Remarks:
The specified byte array must be large enough to receive the state of
all available trace levels.
A state set to 1 means enabled, while set to 0 means disabled.
byArray[0] --- Trace level 0 state
.
.
.
byArray[TRACERST_MAX_LEVELS - 1] --- Trace level TRACERST_MAX_LEVELS - 1 state
Example:
the following example tests the state of the trace level number 0.
BYTE byTraceLevels[TRACERST_MAX_LEVELS];
m_Tracer.GetTraceLevels(byTraceLevels);
if (byTraceLevels[0] == 1)
COLOR="BLUE">else
SetTraceLevels
void SetTraceLevels(LPBYTE lpbyTraceLevels);
Sets the state (enabled/disabled) of all trace levels.
Parameters:
Remarks:
The specified byte array must hold the state of all available trace levels.
A state set to 1 means enabled, while set to 0 means disabled.
Example:
the following example sets to enabled all trace levels.
BYTE byTraceLevels[TRACERST_MAX_LEVELS];
::FillMemory(&byTraceLevels, sizeof(byTraceLevels), 1);
m_Tracer.SetTraceLevels(byTraceLevels);
GetFlags
void GetFlags(LPBYTE lpbyFlags);
Get CTracerST
flags.
Parameters:
Example:
BYTE byFlags;
m_Tracer.GetFlags(&byFlags);
SetFlags
void SetFlags(LPBYTE lpbyFlags);
Set CTracerST
flags.
Parameters:
Remarks:
Each bit of the byte specifies a single flag.
Currently only one flag is supported:
-
TRACERST_FLAG_SAVE
Save traces to disk.
Example:
the following example sets the save-to-disk flag.
BYTE byFlags;
m_Tracer.GetFlags(&byFlags);
byFlags |= TRACERST_FLAG_SAVE;
m_Tracer.SetFlags(&byFlags);
GetVersionI
short GetVersionI();
Returns the CTracerST
version as a short number.
Divide by 10 to get actual version.
GetVersionC
LPCTSTR GetVersionC();
Returns the CTracerST
version as a string.
Example:
TCHAR szText[128];
::wsprintf(szText, _T("Version is: %s"), CTracerST::GetVersionC());
::MessageBox(NULL, szText, NULL, MB_OK);
Remarks
CTracerST
is Critical-Section protected. This makes it
callable from different threads at the same time without problems
(thread-safe). It's currently used in two industrial application
without problems of any type.
The only area where an application must take care is to not fill the
trace queue. This queue has a limited number of trace strings that
can buffered, as specified in the Create
function (dwMaxItems
parameters). Trace data are not removed from the queue by CTracerST
.
Even if an application doesn't need to display traces it should
remove trace datas from the queue. It can be done with the following example:
COLOR="BLUE">return 0;
}
Want to include CTracerST in a DLL ?
CTracerST
is ready to be used from inside a DLL. You
need to export from your DLL CTracerST
and also CSharedQueueST
.
Include in your DLL's project the following files:
<LI
CLASS="mvd-PRE">TracerST.h
<LI
CLASS="mvd-PRE">TracerST.cpp
<LI
CLASS="mvd-PRE">SharedQueueST.h
<LI
CLASS="mvd-PRE">SharedQueueST.cpp
<LI
CLASS="mvd-PRE">Macros.h
Add to your DLL's project settings the following defines:
<LI
CLASS="mvd-PRE">_CMLHTDLL_NOLIB_
<LI
CLASS="mvd-PRE">_CMLHTDLL_BUILDDLL_
From TracerST.h
comment the following line:
#define _TRACERST_NODLL_
then update the various #pragma comment(lib, "???")
according to your DLL produced .lib files.
From SharedQueueST.h
comment the following line:
#define _SHAREDQUEUEST_NODLL_
then update the various #pragma comment(lib, "???")
according to your DLL produced .lib files.
History
-
CTracerST v1.0
First release