Thread: ReportEvent() displays garbage in Event Log?

  1. #1
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545

    ReportEvent() displays garbage in Event Log?

    I'm not sure why, but when I try to write to the Event Log, it just writes this:
    The description for Event ID ( 20515 ) in Source ( MyService ) cannot be found. The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer. You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details. The following information is part of the event: ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ (܈ퟰŮ�Ů.
    The code I'm using is:
    Code:
    BOOL LogMessage (const DWORD msg_id, const TCHAR **InsertionStrings,
    				 const int nInsertionStrings,const WORD wType,DWORD DataSize,LPVOID Data){
    		if (!ReportEvent(
    			EventSource,
    			wType,
    			0,
    			msg_id,
    			NULL,
    			nInsertionStrings,
    			DataSize,
    			InsertionStrings,
    			Data)){
    		return (FALSE);
    	}
    
    	return (TRUE);
    }
    
    bool
    LogEventQueueIncreasing( const std::wstring&  queueName,
    				  double  percentFull )
    
    {
    	std::wstringstream ss;
    	ss << L"Outgoing Queue " << queueName.c_str() << L" has exceeded " << percentFull << L"% full!";
    	const TCHAR* pMsg = ss.str().c_str();
    
    	return (LogMessage( WAIT_Q_FILLING, &pMsg, 1, EVENTLOG_WARNING_TYPE ) == TRUE);
    }

  2. #2
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    As the message says, you're probably missing a message dll and/or registry entries. You first have to create a message file as indicated below

    Code:
     MessageId=20515
    SymbolicName=WAIT_Q_FILLING
    Language=English
    %1
    We'll call the above help.mc.

    Next, you will have to run the message compiler on help.mc as follows:
    Code:
    mc help.mc
    This will create a help.h and a help.rc file

    Now, we'll run the resource compiler as follows on the help.rc file
    Code:
    rc -r -fo help.res help.rc
    Now, we'll have to create a help.dll as follows:
    Code:
    link -dll -noentry -out:help.dll help.res
    Then copy this help.dll to %SystemRoot%\System folder

    Next we have to "install" the message using the following code. We are assuming the name of your app is MYPROGRAM

    Code:
    #pragma comment( lib, "advapi32.lib" )
    #include <windows.h>
    #include <stdio.h>
    BOOL Install(void)
    {
        HKEY hk;
        DWORD dwDisposition, dwAllowed;
        char szName[256] = {0};
    
        strcpy(szName,"SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\");
        strcat(szName,"MYPROGRAM");
        if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,szName, 0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,
            NULL,&hk,&dwDisposition))
        {
            printf("Unable to create registry key");
            return FALSE;
        }
        strcpy (szName,"%SystemRoot%\\System\\HELP.DLL");
        if(RegSetValueEx(hk,"EventMessageFile",0,REG_EXPAND_SZ,(LPBYTE)szName,strlen(szName)+1))
        {
            printf("Unable to create/set registry value (message DLL name)");
            return FALSE;
        }
        dwAllowed=EVENTLOG_ERROR_TYPE  |EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
        if (RegSetValueEx(hk,"TypesSupported",0,REG_DWORD,
            (LPBYTE)&dwAllowed,sizeof(DWORD)))
        { 
            printf("Unable to create/set registry value (message types)");
            return FALSE;
        }
        RegCloseKey(hk);
        return TRUE;
    }
    
    int main(void)
    {
        Install();
        return 0;
    }
    Finally, include the help.h in your source code.

  3. #3
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    WOW! That's an incredibly convoluted way to do something that should be simple, but if MS wrote it I guess anything is possible...

    I still don't see why you should have to do all that since you pass all the info that's needed directly to ReportEvent(), but I'll give that a try.

    Thanks.

  4. #4
    Registered User
    Join Date
    Apr 2007
    Posts
    137
    You should read the doc before posting a question answered for about 15 years on Usenet.
    http://msdn2.microsoft.com/en-us/library/aa363680.aspx

  5. #5
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    You don't *have* to register an event source and provide a message file.....but it makes things look nicer.
    Code:
    #include <windows.h>
    #include <iostream>
    using namespace std;
    
    int main()
    {
        const wchar_t *str = L"Log Message Test.";
    
        HANDLE hLog = RegisterEventSourceW(0, L"TestApp");
        if (!hLog)
        {
            cerr << "RegisterEventSourceW() failed with " << GetLastError() << endl;
            return 1;
        }//if
    
        BOOL res = ReportEventW(hLog, EVENTLOG_WARNING_TYPE, 0, 111, 0, 1, 0, &str, 0);
        if (!res)
        {
            cerr << "ReportEventW() failed with " << GetLastError() << endl;
            CloseEventLog(hLog);
            return 1;
        }//if
    
        CloseEventLog(hLog);
    
        return 0;
    }//main
    Quote Originally Posted by EventVwr.msc
    The description for Event ID ( 111 ) in Source ( TestApp ) cannot be found. The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer. You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details. The following information is part of the event: Log Message Test..
    So there's something wrong with your code if you're getting garbage like that. I would first get rid of all those TCHAR's and just use WCHAR/wchar_t with explicit wide-API calls.

    gg

  6. #6
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    If you do a hex dump of any EVT file, you'll find that there are absolutely no strings other than filenames, userid's etc stored in any of these files. This is to accomodate international Windows application development. All localized strings used in event messages are stored in the external message file which is actually a resource DLL or even an executable. A message file should contain one MESSAGETABLE resource for each language that it supports. So, if you want to enter anything other than the follwing in an EVT file:

    Code:
    The description for Event ID ( 20515 ) in Source ( MyService ) cannot be found. The local 
    computer may not have the necessary registry information or message DLL files to display
     messages from a remote computer. You may be able to use the /AUXSOURCE= flag to retrieve 
    this description; see Help and Support for details. The following information is part of the event: 
    ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ 
    ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ (܈ퟰŮ�Ů.
    You will be required to create a message file

  7. #7
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    I tried those 5 steps, but they didn't help.
    The strange thing is, when I assign a literal string instead of the wstringstream buffer like this:
    Code:
    bool
    LogEventQueueIncreasing( const std::wstring&  queueName,
    				  double  percentFull )
    {
    	std::wstringstream ss;
    	ss << L"Security Domain Request Outgoing Queue " << queueName.c_str() << L" has exceeded " << percentFull << L"% full!";
    	const TCHAR* pMsg[2];
    	pMsg[0] = L"ss.str().c_str()";
    
    	return (LogMessage( WAIT_Q_FILLING, (const TCHAR**)pMsg, 1, EVENTLOG_WARNING_TYPE ) == TRUE);
    }
    then it finally outputs the string I set (although the rest of that warning stuff is still there):
    The description for Event ID ( 20515 ) in Source ( MyService ) cannot be found. The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer. You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details. The following information is part of the event: ss.str().c_str().
    There must be something wrong with the wstringstream buffer that's getting corrupted?

  8. #8
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Ahh - that's a nice little bug you have there.
    Code:
        wstringstream ss;
        ss << L"Hello World.";
        const wchar_t *p = ss.str().c_str();
        wcout << p << endl;
    That doesn't work as you expect. It has to do with the lifetime of the object returned by the call in red.

    gg

  9. #9
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Codeplug View Post
    Ahh - that's a nice little bug you have there.
    Code:
        wstringstream ss;
        ss << L"Hello World.";
        const wchar_t *p = ss.str().c_str();
        wcout << p << endl;
    That doesn't work as you expect. It has to do with the lifetime of the object returned by the call in red.

    gg
    Yeah thanks , I just thought of that, so I fixed it like this:
    Code:
    std::wstring str = ss.str();
    Now I just need to get the ugly warning part of the message to go away.

  10. #10
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Woohoo! I also got rid of that ugly warning message.
    Somebody already wrote a command script which calls mc.exe and copies the result to a bunch of different directories. I just recompiled the error.dll and it worked!

  11. #11
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    I do not understand why do you mixing TCHAR and wchar_t types

    If you are planning to compile both UNICODE/ANSI versions - use TCHAR everythere
    If you are planning use only UNICODE version - get rid of TCHAR and casts - they only get you into truble when UNICODE settings do not match your expectations withouot even wanrnigs about mismatched types...

    Be consistent in your type usage
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  12. #12
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by vart View Post
    I do not understand why do you mixing TCHAR and wchar_t types

    If you are planning to compile both UNICODE/ANSI versions - use TCHAR everythere
    If you are planning use only UNICODE version - get rid of TCHAR and casts - they only get you into truble when UNICODE settings do not match your expectations withouot even wanrnigs about mismatched types...

    Be consistent in your type usage
    I guess I could use std::basic_stringstream<TCHAR> in my new function rather than change all the existing code to wchar_t... I doubt they're ever going to compile an ANSI version now anyways (actually they can't since some places they use _T("...") and other places they use L"..."). I'm amazed it works at all whenever I look at this code.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. event log name
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 05-26-2008, 02:14 AM
  2. Windows service event log message file
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 05-22-2008, 03:24 AM
  3. delegate & event
    By Micko in forum C# Programming
    Replies: 5
    Last Post: 03-08-2004, 04:05 AM
  4. I Need To Know Some Things That I Can Put Into A Batch File
    By TheRealNapster in forum A Brief History of Cprogramming.com
    Replies: 1
    Last Post: 10-20-2003, 08:12 PM