global CArchive/CFile object

i need a pair of CFile/CArchive objects that are accessible to all classes in the program in order to log possible errors occured during processing data. any suggestions?
is there a better way around this than declare CFile/CArchive objects as external?
flexsuiteAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
piano_boxerConnect With a Mentor Commented:
Maby this is what you want.

In my app I log internal status/error messages to a textfile. The nice thing about my approach is that you can add log-messages just like calling printf().

-

Create a new cpp/h file pair called log.cpp and log.h and insert the code.

*** USAGE:

Call OpenLogFile(_T("mylog.txt")) in your CWinApp::OnInitInstance().
Call CloseLogFile() in your CWinApp::ExitInstance().

Include the 'log.h' file in every .cpp file that you want to call
WriteLog from, or just include globally in stdafx.h

Here is some example of writing to the logfile:


1.  WriteLog(_T("Application started"));
2.  WriteLog(_T("Error writing %d bytes to socket"), nByteCount);
3.  WriteLog(_T("Cannot find the file: %s"), strFile);



------------- START OF LOG.H -------------------

#ifdef __LOG_H__
#define __LOG_H__

BOOL OpenLogFile(LPCTSTR lpszFilename);
void CloseLogFile()
void WriteLog(LPCTSTR lpszFmt, ...)

#define MAX_LOGFILE_SIZE 1024 * 1024; // 1MB

#endif



------------- START OF LOG.CPP -----------------

#include "stdafx.h"
#include "log.h"

HANDLE g_hLogFile = NULL;


BOOL OpenLogFile(LPCTSTR lpszFilename)
{
    ASSERT(lpszFilename != NULL);
    ASSERT(g_hLogFile == NULL);

    // Open existing or create new logfile and
    // move to end of file.
    g_hLogFile = CreateFile(
        lpszFilename,
        GENERIC_READ|GENERIC_WRITE,
        FILE_SHARE_READ,
        NULL,
        OPEN_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL );
    if(g_hLogFile == INVALID_HANDLE_VALUE)
    {
        g_hLogFile = NULL;
        return FALSE;
    }

    SetFilePointer(g_hLogFile, 0, 0, FILE_END);

    // Add a new-line to the text-file
    DWORD dw;
    WriteFile(g_hLogFile, _T("\r\n"), 2, &dw, NULL);

    return TRUE;
}

void CloseLogFile()
{
    if(g_hLogFile != NULL)
    {
        CloseHandle(g_hLogFile);
        g_hLogFile = NULL;
    }
}


////////////////////////////////////////////////////////
// The following function is used to adjust the size of
// the logfile so that it does not exceed a gived size
//
// The oldest entries are deleted first.
//
void AdjustLogFileSize()
{
    if(g_hLogFile == NULL)
    {
        ASSERT(FALSE);
        return;
    }

    //
    // Get current size of file and determine if we need to adjust the size.
    // If the logfile is greater that dwMax then the size if adjusted to:
    // Filesize - MAX_LOGFILE_SIZE/10
    //
    DWORD dwIoSize;
    DWORD dwSize = GetFileSize(g_hLogFile, NULL);
    if(dwSize > (MAX_LOGFILE_SIZE/10))
        dwSize -= (MAX_LOGFILE_SIZE/10);

    if(dwSize > MAX_LOGFILE_SIZE)
    {
        // Move to the position in the file where we want to cut, and scan forward to the
        // first newline. This way we do not cut any lines i half.
        DWORD dwSrcPos = dwSize - MAX_LOGFILE_SIZE;
        VERIFY(SetFilePointer(g_hLogFile, dwSrcPos, NULL, FILE_BEGIN) !=  0xFFFFFFFF);
        char c = 0;
        while(c != '\n' && dwSrcPos < dwSize)
        {
            if(!ReadFile(g_hLogFile, &c, 1, &dwIoSize, NULL))
                break;

            dwSrcPos++;
        }

        // Move data from ending to the beginning of file and set new EOF
        // We move 10KB at a time.
        DWORD dwReduce = dwSize - dwSrcPos;

        DWORD dwDstPos = 0;
        BYTE buf[10240];
        while(dwSrcPos < dwSize)
        {
            SetFilePointer(g_hLogFile, dwSrcPos, NULL, FILE_BEGIN);
            dwIoSize = 0;
            if(!ReadFile(g_hLogFile, buf, sizeof(buf), &dwIoSize, NULL) || !dwIoSize)
                break;

            SetFilePointer(g_hLogFile, dwDstPos, NULL, FILE_BEGIN);
            if(!WriteFile(g_hLogFile, buf, dwIoSize, &dwIoSize, NULL))
                break;

            dwSrcPos += dwIoSize;
            dwDstPos += dwIoSize;
        }

        // Set new EOF
        SetEndOfFile(g_hLogFile);
    }
}


////////////////////////////////////////////////////////
// This function will write to the logfile. Just call it
// as a normal printf() call.
//
// Every entry is timestamped.

void WriteLog(LPCTSTR lpszFmt, ...)
{
    if(g_hLogFile == NULL)
    {
        ASSERT(FALSE);
        return;
    }

    // Format the string based on lpszFmt and corresponding
    // parameters (if any).

    va_list argList;
    va_start(argList, lpszFmt);

    char sz[1024];

    CString s1;
    CTime tm;
    DWORD dwIoSize;

    tm = CTime::GetCurrentTime();

    _vstprintf(sz, lpszFmt, argList);

    va_end(argList);

    s1 = tm.Format(_T("%c"));
    s1 += _T(" ");
    s1 += sz;
    s1 += _T("\r\n");

    // Write to logfile and adjust size if neccessary.
    WriteFile(g_hLogFile, (LPCSTR)s1, s1.GetLength(), &dwIoSize, NULL);
    AdjustLogFileSize();
};
0
 
tma050898Commented:
You could place them both in the applicatoin object. That way you can easily access them from anywere in the application via the AfxGetApp function (after casting the returned CWinApp pointer). Lemme know if you need more detail.
0
 
flexsuiteAuthor Commented:
i am developing a win32 dll which does not have a CWinApp object. what shall i do?
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
tma050898Commented:
Ok. The file objects both live in a DLL. Why couldn't the DLL simply export two functions to retrieve pointers or references to the file objects?
0
 
flexsuiteAuthor Commented:
the file is processed inside the dll using buffered output method. the information to be placed in the file is gathered from various objects of different classes and stored in the archive. once the job is finished, the information stored in archive will be serialized into the file object. suggestions?
0
 
tma050898Commented:
I guess I'm just not seeing anything too problematic here. What am I missing?

You have a couple of file objects in the DLL. Both of these objects get written to by various objects in the appliction. The application's object accomplishs this by calling exported functions from the DLL. Conversely, the DLL could also wrap this functionality in a C++ class and export the entire class or a set of its member functions for the application's objects to call.

Tom

0
 
piano_boxerCommented:
I just spotted one mistake in my code:
  #ifdef __LOG_H__
should be replaced with
  #ifndef __LOG_H__

0
 
tma050898Commented:
flexsuite,

I'm glad that you finally got an answer to your question. However, one piece of advice. If you take a little more time to word your questions, next time you will get a much quicker resolution to your problem.

Your question stated...
"is there a better way around this than declare CFile/CArchive objects as external?"

This lead me to believe that your problem had nothing to do with how to log error messages. After reading your question, I thought that you already had that code written. In fact, from the question it looked like the only problem you had dealt with not knowing how make that logging capability available to the DLL's client code which is why I wasted both of our time with answers that in now way dealt with your problem.

Tom

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.