{"id":320,"date":"2012-01-02T09:35:47","date_gmt":"2012-01-02T14:35:47","guid":{"rendered":"https:\/\/blogs.mathworks.com\/loren\/?p=320"},"modified":"2016-08-23T09:39:44","modified_gmt":"2016-08-23T14:39:44","slug":"liberating-deployed-application-output-from-the-console-window","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/loren\/2012\/01\/02\/liberating-deployed-application-output-from-the-console-window\/","title":{"rendered":"Liberating Deployed Application Output from the Console Window"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <introduction>\r\n      <p>Guest blogger <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/4660\">Peter Webb<\/a> returns with another in an <a href=\"https:\/\/blogs.mathworks.com\/loren\/category\/deployment\/\">occasional series<\/a> of postings about application deployment.\r\n      <\/p>\r\n   <\/introduction>\r\n   <h3>Contents<\/h3>\r\n   <div>\r\n      <ul>\r\n         <li><a href=\"#1\">Integrating Output with a Window System<\/a><\/li>\r\n         <li><a href=\"#2\">Creating a Shared Library<\/a><\/li>\r\n         <li><a href=\"#3\">Displaying Messages in a Visible Window<\/a><\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <h3>Integrating Output with a Window System<a name=\"1\"><\/a><\/h3>\r\n   <p>Applications developed with the MATLAB Compiler direct their output to the console window. While this may suffice for batch\r\n      or background tasks, it is often not suitable for interactive or graphical environments. In an <a href=\"https:\/\/blogs.mathworks.com\/loren\/2011\/11\/04\/managing-deployed-application-output-with-message-handlers\">earlier post<\/a>, I demonstrated how to use <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/compiler\/f2-998954.html#f2-1008529\"><i>message handlers<\/i><\/a> to redirect program output and error messages to a log file. For many batch or background applications, simply capturing\r\n      output to a log file provides sufficient information for validation and debugging. However, if you need to more closely monitor\r\n      the progress of your application while it is running, you might want to redirect output to a visible window.\r\n   <\/p>\r\n   <p>I've written a short C program in <tt>monitor.c<\/tt> to demonstrate a few applications of this idea: on UNIX, the program sends output to an <a href=\"http:\/\/en.wikipedia.org\/wiki\/X_terminal\">X terminal<\/a>; on Windows, I created two programs. The simplest of the Windows programs displays the output in a Windows dialog box. The\r\n      other, slightly more complex, sends the output as events to the <a href=\"\">Windows Event Log<\/a>.\r\n   <\/p>\r\n   <p>In all three cases (UNIX and Windows), the <tt>monitor<\/tt> main program calls a <a href=\"https:\/\/www.mathworks.com\/products\/matlab\">MATLAB<\/a> <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/function.html\">function<\/a>, <tt>sendmessages<\/tt>, contained in a shared library generated by <a href=\"https:\/\/www.mathworks.com\/access\/helpdesk\/help\/releases\/R2011b\/toolbox\/compiler\">MATLAB Compiler<\/a>.\r\n   <\/p>\r\n   <h3>Creating a Shared Library<a name=\"2\"><\/a><\/h3>\r\n   <p>The <tt>sendmessages<\/tt> function displays an <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/disp.html\">informational message<\/a>, a <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/warning.html\">warning<\/a> and then issues an <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/error.html\">error<\/a>:\r\n   <\/p><pre>function sendmessages(info, warn, err)\r\n    disp(info); warning(warn); error(err);<\/pre><p>Create a <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/compiler\/f2-972343.html\">C shared library<\/a> containing <tt>sendmessages<\/tt> with <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/compiler\/f0-979233.html\">MATLAB Compiler<\/a>:\r\n   <\/p><pre>mcc -W lib:libmsgfcn -T link:lib sendmessages.m<\/pre><p>To follow the rest of this posting, <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/32598-liberating-deployed-application-output-from-the-console-window\">download the source code<\/a> for the main program that calls <tt>sendmessages<\/tt> from MATLAB Central. See the <tt>monitorREADME<\/tt> in the ZIP file for a description of each of the downloaded files and complete directions for building the example application.\r\n   <\/p>\r\n   <p>Build the application using <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/compiler\/mbuild.html#zmw57dd0e18448\">mbuild<\/a>:\r\n   <\/p>\r\n   <p>UNIX:<\/p><pre>mbuild -g monitor.c monitorUNIX.c -L. -lmsgfcn<\/pre><p>Windows -- two commands because there are two programs:<\/p><pre>mbuild -g monitorWinDialog.c monitor.c WinLogger.rc libmsgfcn.lib<\/pre><pre>mbuild -g monitorWinEvents.c monitor.c libmsgfcn.lib<\/pre><p>The first command builds the dialog box version (<tt>monitorWinDialog.exe<\/tt>) and the second command builds the event log version (<tt>monitorWinEvents.exe<\/tt>).\r\n   <\/p>\r\n   <p>You can't run <tt>monitorWinEvents.exe<\/tt> on Microsoft Windows until you register the event source. (UNIX readers can skip this step.) To register the event source,\r\n      follow the step-by-step instructions in the <tt>monitorREADME<\/tt> file in the source code distribution ZIP file.\r\n   <\/p>\r\n   <h3>Displaying Messages in a Visible Window<a name=\"3\"><\/a><\/h3>\r\n   <p>The main program in <tt>monitor.c<\/tt> relies on three external functions:\r\n   <\/p><pre>void StartMonitoring(void) void StopMonitoring(void) int\r\nMonitorHandler(const char *msg)<\/pre><p><tt>StartMonitoring<\/tt> initializes the monitoring system, <tt>MonitorHandler<\/tt> redirects the program's output to the monitoring window and <tt>StopMonitoring<\/tt> releases the resources required to capture the program's output. The implementation of these functions varies by platform.\r\n   <\/p>\r\n   <p>On UNIX, for example, the <tt>StartMonitor<\/tt> function starts an <tt>xterm<\/tt> which runs <tt>tail -f<\/tt> to monitor the log file:\r\n   <\/p><pre>void StartMonitoring() {\r\n    if (tmpLog == NULL) {\r\n        char logFileName[80]; char cmd[128];<\/pre><pre>        sprintf(logFileName, \"\/tmp\/monitorLog.%d\", getpid()); tmpLog =\r\n        fopen(logFileName, \"w\"); sprintf(cmd, \"xterm -e tail -f %s&amp;\",\r\n        logFileName); system(cmd);\r\n    }\r\n}<\/pre><p>The UNIX message handler, <tt>MonitorHandler<\/tt>, is identical to the message handler from <a href=\"https:\/\/blogs.mathworks.com\/loren\/2011\/11\/04\/managing-deployed-application-output-with-message-handlers\/\">the previous post's<\/a> example, except that it writes messages to a temporary log file instead of a persistent one.\r\n   <\/p>\r\n   <p>On Windows, the simplest version of the monitoring system sends messages to a dialog box. <tt>StartMonitoring<\/tt> creates the dialog box and starts it running in a separate thread. <tt>MonitorHandler<\/tt> calls <tt>LogMessage<\/tt> to add lines of text to the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb775146%28VS.85%29.aspx\"><tt>ListBox<\/tt><\/a> contained in the dialog box. <tt>StopMonitoring<\/tt> waits for the dialog box's thread to terminate. <tt>LogMessage<\/tt> sends the lines of text to the <tt>ListBox<\/tt> using the Windows messaging system. Since each item in a list box only displays a single line of text, <tt>LogMessage<\/tt> sends multi-line text as a sequence of separate messages, one message per line.\r\n   <\/p><pre>int LogMessage(const char *s, int msgType) {\r\n    char msg[1024]; char *pos = &amp;msg[0]; char *cr = NULL; msg[0] = '\\0';\r\n    strncat(msg, s, 1024);<\/pre><pre>    while (pos != NULL &amp;&amp; *pos != '\\0') {\r\n       cr = strchr(pos, '\\n');\r\n        if (cr != NULL)\r\n            *cr = '\\0';\r\n        pos = CleanText(pos); if (strlen(pos) &gt; 0)\r\n            SendMessage(loggerDialog, WM_COMMAND, MAKEWPARAM(msgType,\r\n            0),\r\n                        (LPARAM)pos);\r\n        pos = cr+1;\r\n    } return strlen(s);\r\n}<\/pre><p>Now run it. The program takes three input arguments: the informational message, the warning and the error message.<\/p>\r\n   <p>(UNIX):    <tt>.\/monitor information \"look out!\" oops<\/tt><\/p>\r\n   <p>(Windows): <tt>monitorWinDialog.exe information \"look out!\" oops<\/tt><\/p>\r\n   <p>On UNIX machines and when running the dialog box version (<tt>monitorWinDialog<\/tt>) 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\r\n      a Windows PC, you'll need to <a title=\"http:\/\/support.microsoft.com\/kb\/308427 (link no longer works)\">open the Event Logger<\/a> and click on the <i>Application<\/i> category.\r\n   <\/p>\r\n   <p>Next time: handling errors differently than information and warning messages. Until then, <a href=\"https:\/\/blogs.mathworks.com\/loren\/?p=320#view_comments\">let me know<\/a> how your application makes sure error messages get delivered to users. Do you need a permanent record, like the Windows event\r\n      logger provides?\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_9aa2fd68293244438880c24c79ee83fe() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='9aa2fd68293244438880c24c79ee83fe ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 9aa2fd68293244438880c24c79ee83fe';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        author = 'Peter Webb';\r\n        copyright = 'Copyright 2011 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add author and copyright lines at the bottom if specified.\r\n        if ((author.length > 0) || (copyright.length > 0)) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (author.length > 0) {\r\n                d.writeln('% _' + author + '_');\r\n            }\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n      \r\n      d.title = title + ' (MATLAB code)';\r\n      d.close();\r\n      }   \r\n      \r\n-->\r\n<\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_9aa2fd68293244438880c24c79ee83fe()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n            the MATLAB code \r\n            <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; 7.13<br><\/p>\r\n<\/div>\r\n<!--\r\n9aa2fd68293244438880c24c79ee83fe ##### SOURCE BEGIN #####\r\n%% Liberating Deployed Application Output from the Console Window\r\n% Guest blogger\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/4660 Peter\r\n% Webb> returns with another in an\r\n% <https:\/\/blogs.mathworks.com\/loren\/category\/deployment\/ occasional series>\r\n% of postings about application deployment.\r\n%% Integrating Output with a Window System\r\n% Applications developed with the MATLAB Compiler direct their output to\r\n% the console window. While this may suffice for batch or background tasks,\r\n% it is often not suitable for interactive or graphical environments. In an\r\n% <https:\/\/blogs.mathworks.com\/loren\/2011\/11\/04\/managing-deployed-application-output-with-message-handlers\r\n% earlier post>, I demonstrated how to use\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/compiler\/f2-998954.html#f2-1008529\r\n% _message handlers_> to redirect program output and error messages to a\r\n% log file. For many batch or background applications, simply capturing\r\n% output to a log file provides sufficient information for validation and\r\n% debugging. However, if you need to more closely monitor the progress of\r\n% your application while it is running, you might want to redirect output\r\n% to a visible window.\r\n%\r\n% I've written a short C program in |monitor.c| to demonstrate a few\r\n% applications of this idea: on UNIX, the program sends output to an\r\n% <http:\/\/en.wikipedia.org\/wiki\/X_terminal X terminal>; on Windows, I\r\n% created two programs. The simplest of the Windows programs displays the\r\n% output in a Windows dialog box. The other, slightly more complex, sends\r\n% the output as events to the\r\n% <\r\n% Windows Event Log>.\r\n%\r\n% In all three cases (UNIX and Windows), the |monitor| main program calls a\r\n% <https:\/\/www.mathworks.com\/products\/matlab MATLAB>\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/function.html function>,\r\n% |sendmessages|, contained in a shared library generated by\r\n% <https:\/\/www.mathworks.com\/access\/helpdesk\/help\/releases\/R2011b\/toolbox\/compiler MATLAB\r\n% Compiler>.\r\n%\r\n%% Creating a Shared Library\r\n% The |sendmessages| function displays an\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/disp.html informational\r\n% message>, a <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/warning.html\r\n% warning> and then issues an\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/error.html error>:\r\n%\r\n%  function sendmessages(info, warn, err)\r\n%      disp(info); warning(warn); error(err);\r\n%\r\n% Create a <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/compiler\/f2-972343.html C\r\n% shared library> containing |sendmessages| with\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/compiler\/f0-979233.html\r\n% MATLAB Compiler>:\r\n%\r\n%  mcc -W lib:libmsgfcn -T link:lib sendmessages.m\r\n%\r\n% To follow the rest of this posting,\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/32598-liberating-deployed-application-output-from-the-console-window\r\n% download the source code> for the main program that calls |sendmessages|\r\n% from MATLAB Central. See the |monitorREADME| in the ZIP file for a\r\n% description of each of the downloaded files and complete directions for\r\n% building the example application.\r\n%\r\n% Build the application using\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/compiler\/mbuild.html#zmw57dd0e18448\r\n% mbuild>:\r\n%\r\n% UNIX:\r\n%\r\n%  mbuild -g monitor.c monitorUNIX.c -L. -lmsgfcn\r\n% \r\n% Windows REPLACE_WITH_DASH_DASH two commands because there are two programs:\r\n%\r\n%  mbuild -g monitorWinDialog.c monitor.c WinLogger.rc libmsgfcn.lib\r\n%\r\n%  mbuild -g monitorWinEvents.c monitor.c libmsgfcn.lib\r\n%\r\n% The first command builds the dialog box version (|monitorWinDialog.exe|)\r\n% and the second command builds the event log version\r\n% (|monitorWinEvents.exe|).\r\n%\r\n% You can't run |monitorWinEvents.exe| on Microsoft Windows until you\r\n% register the event source. (UNIX readers can skip this step.) To register\r\n% the event source, follow the step-by-step instructions in the\r\n% |monitorREADME| file in the source code distribution ZIP file.\r\n%% Displaying Messages in a Visible Window\r\n% The main program in |monitor.c| relies on three external functions:\r\n%\r\n%  void StartMonitoring(void) void StopMonitoring(void) int\r\n%  MonitorHandler(const char *msg)\r\n%\r\n% |StartMonitoring| initializes the monitoring system, |MonitorHandler|\r\n% redirects the program's output to the monitoring window and\r\n% |StopMonitoring| releases the resources required to capture the program's\r\n% output. The implementation of these functions varies by platform.\r\n%\r\n% On UNIX, for example, the |StartMonitor| function starts an |xterm| which\r\n% runs |tail -f| to monitor the log file:\r\n%\r\n%  void StartMonitoring() {\r\n%      if (tmpLog == NULL) {\r\n%          char logFileName[80]; char cmd[128];\r\n%          \r\n%          sprintf(logFileName, \"\/tmp\/monitorLog.%d\", getpid()); tmpLog =\r\n%          fopen(logFileName, \"w\"); sprintf(cmd, \"xterm -e tail -f %s&\",\r\n%          logFileName); system(cmd);\r\n%      }\r\n%  }\r\n%\r\n% The UNIX message handler, |MonitorHandler|, is identical to the message\r\n% handler from\r\n% <https:\/\/blogs.mathworks.com\/loren\/2011\/11\/04\/managing-deployed-application-output-with-message-handlers\/\r\n% the previous post's> example, except that it writes messages to a\r\n% temporary log file instead of a persistent one.\r\n%\r\n% On Windows, the simplest version of the monitoring system sends messages\r\n% to a dialog box. |StartMonitoring| creates the dialog box and starts it\r\n% running in a separate thread. |MonitorHandler| calls |LogMessage| to add\r\n% lines of text to the\r\n% <http:\/\/msdn.microsoft.com\/en-us\/library\/bb775146%28VS.85%29.aspx\r\n% |ListBox|> contained in the dialog box. |StopMonitoring| waits for the\r\n% dialog box's thread to terminate. |LogMessage| sends the lines of text to\r\n% the |ListBox| using the Windows messaging system. Since each item in a\r\n% list box only displays a single line of text, |LogMessage| sends\r\n% multi-line text as a sequence of separate messages, one message per line.\r\n%\r\n%  int LogMessage(const char *s, int msgType) {\r\n%      char msg[1024]; char *pos = &msg[0]; char *cr = NULL; msg[0] = '\\0';\r\n%      strncat(msg, s, 1024);\r\n%      \r\n%      while (pos != NULL && *pos != '\\0') {\r\n%         cr = strchr(pos, '\\n');\r\n%          if (cr != NULL)\r\n%              *cr = '\\0';\r\n%          pos = CleanText(pos); if (strlen(pos) > 0)\r\n%              SendMessage(loggerDialog, WM_COMMAND, MAKEWPARAM(msgType,\r\n%              0),\r\n%                          (LPARAM)pos);\r\n%          pos = cr+1;\r\n%      } return strlen(s);\r\n%  }\r\n%\r\n% Now run it. The program takes three input arguments: the informational\r\n% message, the warning and the error message.\r\n%\r\n% (UNIX):    |.\/monitor information \"look out!\" oops|\r\n%\r\n% (Windows): |monitorWinDialog.exe information \"look out!\" oops|\r\n% \r\n% On UNIX machines and when running the dialog box version\r\n% (|monitorWinDialog|) on a Windows machine, you'll see a window pop up and\r\n% display the messages. To view the output of the event log version on a\r\n% Windows PC, you'll need to <http:\/\/support.microsoft.com\/kb\/308427 open\r\n% the Event Logger> and click on the _Application_ category.\r\n%\r\n% Next time: handling errors differently than information and warning\r\n% messages. Until then, <https:\/\/blogs.mathworks.com\/loren\/?p=301#respond\r\n% let me know> how your application makes sure error messages get delivered\r\n% to users. Do you need a permanent record, like the Windows event logger\r\n% provides?\r\n##### SOURCE END ##### 9aa2fd68293244438880c24c79ee83fe\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   \r\n      Guest blogger Peter Webb returns with another in an occasional series of postings about application deployment.\r\n      \r\n   \r\n   Contents\r\n   \r\n      \r\n   ... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/loren\/2012\/01\/02\/liberating-deployed-application-output-from-the-console-window\/\">read more >><\/a><\/p>","protected":false},"author":39,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[24],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/320"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/users\/39"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/comments?post=320"}],"version-history":[{"count":10,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/320\/revisions"}],"predecessor-version":[{"id":2015,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/320\/revisions\/2015"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/media?parent=320"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/categories?post=320"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/tags?post=320"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}