Liberating Deployed Application Output from the Console Window
Guest blogger Peter Webb returns with another in an occasional series of postings about application deployment.
Contents
Integrating Output with a Window System
Applications developed with the MATLAB Compiler direct their output to the console window. While this may suffice for batch or background tasks, it is often not suitable for interactive or graphical environments. In an earlier post, I demonstrated how to use message handlers to redirect program output and error messages to a log file. For many batch or background applications, simply capturing output to a log file provides sufficient information for validation and debugging. However, if you need to more closely monitor the progress of your application while it is running, you might want to redirect output to a visible window.
I've written a short C program in monitor.c to demonstrate a few applications of this idea: on UNIX, the program sends output to an X terminal; on Windows, I created two programs. The simplest of the Windows programs displays the output in a Windows dialog box. The other, slightly more complex, sends the output as events to the Windows Event Log.
In all three cases (UNIX and Windows), the monitor main program calls a MATLAB function, sendmessages, contained in a shared library generated by MATLAB Compiler.
Creating a Shared Library
The sendmessages function displays an informational message, a warning and then issues an error:
function sendmessages(info, warn, err) disp(info); warning(warn); error(err);
Create a C shared library containing sendmessages with MATLAB Compiler:
mcc -W lib:libmsgfcn -T link:lib sendmessages.m
To follow the rest of this posting, download the source code for the main program that calls sendmessages from MATLAB Central. See the monitorREADME in the ZIP file for a description of each of the downloaded files and complete directions for building the example application.
Build the application using mbuild:
UNIX:
mbuild -g monitor.c monitorUNIX.c -L. -lmsgfcn
Windows -- two commands because there are two programs:
mbuild -g monitorWinDialog.c monitor.c WinLogger.rc libmsgfcn.lib
mbuild -g monitorWinEvents.c monitor.c libmsgfcn.lib
The first command builds the dialog box version (monitorWinDialog.exe) and the second command builds the event log version (monitorWinEvents.exe).
You can't run monitorWinEvents.exe on Microsoft Windows until you register the event source. (UNIX readers can skip this step.) To register the event source, follow the step-by-step instructions in the monitorREADME file in the source code distribution ZIP file.
Displaying Messages in a Visible Window
The main program in monitor.c relies on three external functions:
void StartMonitoring(void) void StopMonitoring(void) int MonitorHandler(const char *msg)
StartMonitoring initializes the monitoring system, MonitorHandler redirects the program's output to the monitoring window and StopMonitoring releases the resources required to capture the program's output. The implementation of these functions varies by platform.
On UNIX, for example, the StartMonitor function starts an xterm which runs tail -f to monitor the log file:
void StartMonitoring() { if (tmpLog == NULL) { char logFileName[80]; char cmd[128];
sprintf(logFileName, "/tmp/monitorLog.%d", getpid()); tmpLog = fopen(logFileName, "w"); sprintf(cmd, "xterm -e tail -f %s&", logFileName); system(cmd); } }
The UNIX message handler, MonitorHandler, is identical to the message handler from the previous post's example, except that it writes messages to a temporary log file instead of a persistent one.
On Windows, the simplest version of the monitoring system sends messages to a dialog box. StartMonitoring creates the dialog box and starts it running in a separate thread. MonitorHandler calls LogMessage to add lines of text to the ListBox contained in the dialog box. StopMonitoring waits for the dialog box's thread to terminate. LogMessage sends the lines of text to the ListBox using the Windows messaging system. Since each item in a list box only displays a single line of text, LogMessage sends multi-line text as a sequence of separate messages, one message per line.
int LogMessage(const char *s, int msgType) { char msg[1024]; char *pos = &msg[0]; char *cr = NULL; msg[0] = '\0'; strncat(msg, s, 1024);
while (pos != NULL && *pos != '\0') { cr = strchr(pos, '\n'); if (cr != NULL) *cr = '\0'; pos = CleanText(pos); if (strlen(pos) > 0) SendMessage(loggerDialog, WM_COMMAND, MAKEWPARAM(msgType, 0), (LPARAM)pos); pos = cr+1; } return strlen(s); }
Now run it. The program takes three input arguments: the informational message, the warning and the error message.
(UNIX): ./monitor information "look out!" oops
(Windows): monitorWinDialog.exe information "look out!" oops
On UNIX machines and when running the dialog box version (monitorWinDialog) on a Windows machine, you'll see a window pop up and display the messages. To view the output of the event log version on a Windows PC, you'll need to open the Event Logger and click on the Application category.
Next time: handling errors differently than information and warning messages. Until then, let me know how your application makes sure error messages get delivered to users. Do you need a permanent record, like the Windows event logger provides?
- Category:
- Deployment