RegisterEventSource(0, "App1.exe") => what if there are multiple "App1.exe"s under ...\Eventlog registry key? - c++

I am trying to use the Windows Event Logging service and in struggle with RegisterEventSource owing to the insufficient/ambiguous description.
Let's assume "App1.exe" is the event source name that will be used from an application program App1.exe.
And I will use my own custom event log subkey named "MyCustLog" under which "App1.exe" subkey will be created.
So, my custom event log subkey for App1.exe will look like "... \MyCustLog\App1.exe" under which EventMessageFile/CategoryMessageFile/CategoryCount will be set as "App1.exe"/"App1.exe"/3, respectively.
Now, there happens and/or will happen to be another "App1.exe" event source name registered under a 3rd party custom event log key as shown below:
HKEY_LOCAL_MACHINE
SYSTEM
CurrentControlSet
Services
Eventlog
Application
Security
System
3rdPartyLog
App1.exe
After I create my own custom event log key it looks like:
HKEY_LOCAL_MACHINE
SYSTEM
CurrentControlSet
Services
Eventlog
Application
Security
System
3rdPartyLog
App1.exe
MyCustLog
App1.exe
Now, I call RegisterEventSource follows:
HANDLE hEvtSrc = RegisterEventSource(0, "App1.exe");
=> returns an event log handle to hEvtSrc, but how can I be sure that the handle is returned for MyCustLog's App1.exe, not 3rdPartyLog's App1.exe?
What I have tried:
I tried the following:
HANDLE hEvtSrc2 = RegisterEventSource(0, "MyCustLog\\App1.exe");
=> this also successfully returns an event log handle but not sure if it is for MyCustLog's App1.exe, nonetheless. Moreover, an event fired by the following ReportEvent with this handle shows failure description in its property window from Windows Event Log Viewer.
CONST LPCTSTR pBadCommand = _T("The command that was not valid");
DWORD dwEventDataSize = ((DWORD)_tcslen(pBadCommand) + 1) * sizeof(TCHAR);
BOOL bRet = ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, UI_CATEGORY, MSG_INVALID_COMMAND, NULL, 0, dwEventDataSize, NULL, (LPVOID)pBadCommand);
The failure message says: The description for event id MSG_INVALID_COMMAND cannot be found from the source MyCustLog\App1.exe
I also tried the third way:
HANDLE hEvtSrc3 = RegisterEventSource(0, "MyCustLog/App1.exe");
=> this again successfully returns an event log handle, but still an event fired by ReportEvent with this handle shows the almost the same failure description in its property window from event viewer. The only difference in failure message is MyCustLog/App1.exe instead of MyCustLog\App1.exe.
Therefore, "MyCustLog\App1.exe" or "MyCustLog/App1.exe" cannot be used instead of "App1.exe" to get the right handle of my own for RegisterEventSource. So we are back to the square one again.
So, once again, how can I be sure the returned handle for RegisterEventSource(0, "App1.exe") is for MyCustLog\App1.exe, not for 3rdPartyLog\App1.exe?
Below is shown the .mc file in use for App1.exe.
[Message file]
; // App1.mc
; // This is the header section.
SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
Warning=0x2:STATUS_SEVERITY_WARNING
Error=0x3:STATUS_SEVERITY_ERROR
)
FacilityNames=(System=0x0:FACILITY_SYSTEM
Runtime=0x2:FACILITY_RUNTIME
Stubs=0x3:FACILITY_STUBS
Io=0x4:FACILITY_IO_ERROR_CODE
)
LanguageNames=(English=0x409:MSG00409)
; // The following are the categories of events.
MessageIdTypedef=WORD
MessageId=0x1
SymbolicName=NETWORK_CATEGORY
Language=English
Network Events
.
MessageId=0x2
SymbolicName=DATABASE_CATEGORY
Language=English
Database Events
.
MessageId=0x3
SymbolicName=UI_CATEGORY
Language=English
UI Events
.
; // The following are the message definitions.
MessageIdTypedef=DWORD
MessageId=0x100
Severity=Error
Facility=Runtime
SymbolicName=MSG_INVALID_COMMAND
Language=English
The command is not valid.
.
MessageId=0x101
Severity=Error
Facility=System
SymbolicName=MSG_BAD_FILE_CONTENTS
Language=English
File %1 contains content that is not valid.
.
MessageId=0x102
Severity=Warning
Facility=System
SymbolicName=MSG_RETRIES
Language=English
There have been %1 retries with %2 success! Disconnect from
the server and try again later.
.
MessageId=0x103
Severity=Informational
Facility=System
SymbolicName=MSG_COMPUTE_CONVERSION
Language=English
%1 %%4096 = %2 %%4097.
.
; // The following are the parameter strings */
MessageId=0x1000
Severity=Success
Facility=System
SymbolicName=QUARTS_UNITS
Language=English
quarts%0
.
MessageId=0x1001
Severity=Success
Facility=System
SymbolicName=GALLONS_UNITS
Language=English
gallons%0
.

If there are multiple App1.exe event sources, there is no way to tell RegisterEventSource() which source to use. RegisterEventSource() only accepts a source name, not a log name.
In fact, the Event Sources documentation says:
You cannot use a source name that has already been used as a log name. In addition, source names cannot be hierarchical; that is, they cannot contain the backslash character ("").
Which is why registering MyCustLog\App1.exe doesn't work, as it is an illegal source name. And why registering MyCustLog/App1.exe doesn't differentiate App1.exe between multiple logs, as / is not a hierarchy delimiter so RegisterEventSource() treats MyCustLog/App1.exe as the entire source name, not as App1.exe underneath MyCustLog.
So, since the source name for both logs is just App1.exe, you must use RegisterEventSource("App1.exe"), and so it will use the the first App1.exe it finds. And if it doesn't find any, it will fallback to using the Application log, which doesn't support category/message files.
So, make sure your event source is named uniquely. For instance, by NOT using your app's filename, but rather more descriptive names, eg:
HKEY_LOCAL_MACHINE
SYSTEM
CurrentControlSet
Services
Eventlog
My Custom Log
My Custom App Name
You can point My Custom App Name to the actual App1.exe file in its EventMessageFile/CategoryMessageFile values as needed.
And then you can use RegisterEventSource("My Custom App Name").
You should have a look at your local Registry to see how other apps register their event sources. It is actually rare for filenames to be used as key names. For example, here is what is registered in the eventlog key on my local system. As you can see, none of the log keys or app keys use filenames for their names:

Related

LTTNG: using with a popular library

I have a trivially simple question that I could not find the answer yet.
Say, I have a shared library X that is used by 100 simultaneously running applications A0, A1, ... A99. I had instrumented my library and with LTTNG using "X-Provider" as the provider name. How can my user distinguish between X-Provider events that happen in A10 and A15?
With the lttng command-line utility, add the vpid context field to be recorded to your event records, for example:
$ lttng add-context -u -t vpid
This targets all the user space channels of the current recording session; you can of course select a specific recording session and/or channel (see lttng-add-context(1)).
You need to use this command before you start the tracers (lttng start).
All your event records will have a context field named vpid which is the virtual IDs of the processes which emitted them.
Now, you need to find a way to associate such VPIDs to instance IDs (A10, A15, etc.). You can do so with your own application-specific strategy, or you can simply record an initial event when starting the application which indicates the instance ID/name, for example:
tracepoint(x_provider, app_state, app_id);
Then, when reading the resulting trace(s), you can correlate the x_provider:app_state event record info with the records of your library-emitted events. For example, using the Babeltrace 2 Python bindings:
import bt2
vpid_app_ids = {}
for msg in bt2.TraceCollectionMessageIterator('/path/to/trace'):
if type(msg) is not bt2._EventMessageConst:
continue
vpid = int(msg.event.common_context_field['vpid'])
if msg.event.name == 'x_provider:app_state':
app_id = int(msg.event.payload_field['app_id'])
vpid_app_ids[vpid] = app_id
else:
app_id = vpid_app_ids[vpid]
# Continue to process `msg.event` knowing the instance ID is
# `app_id`...
I didn't test the example above, but you get the gist.

Temporary disable console output for boost::log

I added sink to file via boost::log::add_file_log and console output via boost::log::add_console_log. I am calling a logger via BOOST_LOG_SEV and everything workds perfectely. But there is a place, where a want output only to the file.
How I can disable cosole output in certain place?
You could achieve this with attributes and filters. For example, you could set up a filter in your console sink to suppress any log records that have (or don't have, depending on your preference) a particular attribute value attached.
boost::log::add_console_log
(
...
boost::log::keywords::filter = !boost::log::expressions::has_attr("NoConsole")
...
);
Then you could set this attribute in the code region that shouldn't output logs in the console. For example, you could use a scoped attribute:
BOOST_LOG_SCOPED_THREAD_ATTR("NoConsole", true);
BOOST_LOG(logger) << "No console output";
You can use whatever method of setting the attribute - as a thread-local attribute, or a logger-specific, it doesn't matter.
The important difference from temporarily removing the sink is that the solution with attributes will not affect other threads that may be logging while you're suspending console output.
You can easely do it with remove_sink() function.
console_sink = boost::log::add_console_log(std::cout);
boost::log::core::get()->remove_sink(console_sink);
After that you can call an add_console_log() again and enable console output.

How to give link for users to Download the Csv Template in Apex

I have an requirement to give link to users in Apex Application to download the csv template.
I have created a link and created an process code as below for the users to download the csv file, But its showing some json error,
begin
-- Set the MIME type
owa_util.mime_header( 'application/octet', FALSE );
-- Set the name of the file
htp.p('Content-Disposition: attachment; filename="test.csv"');
-- Close the HTTP Header
owa_util.http_header_close;
-- Loop through all rows in EMP
for x in (select WORKSPACE,GROUPNAME,MEMBERS from CSV_NON_DYNAMIC_TEMPLATE where FILENAME='test.csv')
loop
-- Print out a portion of a row,
-- separated by commas and ended by a CR
htp.prn(x.WORKSPACE ||','|| x.GROUPNAME ||','||x.MEMBERS|| chr(13));
end loop;
-- Send an error code so that the
-- rest of the HTML does not render
htmldb_application.g_unrecoverable_error := true;
end;
Even i code the process code to on load process, then its working the excel is creating but other than that no buttons or process code not working on the same page.
thanks
First, saying you're getting "some json error" is not helpful. It helps to put the exact error message you're getting in your question.
Second, you probably have this process running at the Process step. Apex is submitting the page via Ajax, your process runs, returns an error to the page and you're getting your message.
Change your process to run at the Before Header point and change it so it has a server side condition of "Request = Value" and make the value "DOWNLOAD".
Change your button's action to Redirect to Page In This Application, and set the link to your page number with a request of "DOWNLOAD" (that's under the advanced section).

WinAPI ReportEvent - component not installed

I've implemented a simple function to log on event viewer from my application. However, I'm getting the following message every time I log something, regardless the error level:
The description for Event ID 0 from source MyAppEvents cannot be found. Either the component that raises this event is not installed on your local computer or the installation is corrupted. You can install or repair the component on the local computer.
If the event originated on another computer, the display information had to be saved with the event.
I'm not an expert on Event log, actually, this is the first time I'm using it in C++, and the documentation is confusing and misleading...
Here is the method I've implemented, to encapsulate event log calls:
HANDLE source = NULL;
void app_log(std::string m, WORD level) {
std::wstring msg_temp (m.begin(), m.end());
LPCWSTR msg = msg_temp.c_str();
std::wstring name(L"MyAppEvents");
if (source == NULL)
source = RegisterEventSource(NULL, name.c_str());
if (source) {
if (!ReportEvent(source, level, 0, 0, NULL, 1, 0, &msg, NULL))
std::cerr << "Error when logging";
}
else
std::cerr << "Error when logging";
}
I have an installer for my app, built with WIX (this installer creates the key needed to log on event viewer - subkey of Application) and it runs smoothly. However, I didn't understand that message, and also don't know how to attach my installed app to the event log - I'm actually not even sure if this is the problem, or if it is maybe one of the parameters I'm passing as NULL or 0.
This message appears also when I debug (without installing, but with the "application subkey" manually created).
Could you help me?
I can't use C++ managed code...
There is nothing wrong with your logging code. The warning message simply means that you have not properly registered the MyAppEvents event source in the Registry. This is documented on MSDN:
RegisterEventSource function:
pSourceName [in]
The name of the event source whose handle is to be retrieved. The source name must be a subkey of a log under the Eventlog registry key. Note that the Security log is for system use only.
Event Sources:
The structure of the event sources is as follows:
HKEY_LOCAL_MACHINE
SYSTEM
CurrentControlSet
Services
EventLog
Application
AppName
Security
System
DriverName
CustomLog
AppName
...
Each event source contains information (such as a message file) specific to the software that will be logging the events
...
An application can use the Application log without adding a new event source to the registry. If the application calls RegisterEventSource and passes a source name that cannot be found in the registry, the event-logging service uses the Application log by default. However, because there are no message files, the Event Viewer cannot map any event identifiers or event categories to a description string, and will display an error. For this reason, you should add a unique event source to the registry for your application and specify a message file.
It is not enough to just create the MyAppEvents subkey, you also have to point it to the message files for your app. If you store your event log categories and event messages as resources of your app executable, the subkey can register the executable itself as the message files.

Qt/C++ getting OS proxy settings

I need to retrieve the proxy settings on Windows. They have been set by an admin, so they reside in the registry at locations:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings
ProxySettingsPerUser = 0x00000000 (0)
This entry is giving the information whether the proxy settings need to be read from HKCU(ProxySettingsPerUser=1) or HKLM(ProxySettingsPerUser=0).
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings
ProxyEnable = 0x00000001 (1)
ProxyServer = Host:Port
When I try to read them directly, the default value/string is returned (i.e. not the actual contents of the variable):
Code:
#define HKLM_INTERNET_SETTINGS_KEY "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
//[...]
QSettings regHKLM( HKLM_INTERNET_SETTINGS_KEY, QSettings::NativeFormat );
QString read = regHKLM.value( "ProxyServer", "default" ).toString();
logDebug(QString("ProxyServer %1").arg(read));
Other entries in the same location, such as CodeBaseSearchPath = "CODEBASE" or WarnOnIntranet = 0x00000001 (1), can be read without a problem.
THe second approach tried was to read the proxy settings by using the MSDN functions ::WinHttpGetIEProxyConfigForCurrentUser and ::WinHttpGetProxyForUrl. The code is working fine when trying to read HKCU settings (given both manually host-port or as pac file). But when the settings need to be retrieved from HKLM, the following error is returned:
ERROR_WINHTTP_AUTODETECTION_FAILED
12180
Returned by WinHttpDetectAutoProxyConfigUrl if WinHTTP was unable to discover the URL of the Proxy Auto-Configuration (PAC) file.
Is there another approach to retrieving the HKLM proxy settings?
If the approaches described above should have worked, is there a special condition/privilage that needs to be fulfilled before the settings can be read? (in the first approached, the application already has elevated the privilage level to maximum possible, and the manifest file is set to level "asInvoker")
Best regards,
Kornrade