Mailslot example

Source code by Todd. G. Nist, Protech Systems Inc.

Source is attached for download.

This procedure can run either as a mailslot server or as a mailslot client. If it runs as a server, it will be able to read messages (it uses a PSTimer.ocx to scan for new messages each 500 msec). If it runs as a client it is able to send messages if there is also a server active.
I (Jurjen) had only one PC to play with, so I launched two instances of Progress on that PC, each running a copy of w-mailslot.w as shown on the pic.

User Manual for this example

First you have to start a mailslot server: run w-mailslot.w and make sure the toggle-box is checked. Click on the editor-widget: the ON ENTRY trigger of the editor will create the mailslot. From now on the PSTimer will check for new messages and will show them in the editor.
After you have created a server you can start one or more clients: run w-mailslot.w again and make sure the toggle-box is NOT checked. Change the mailslot name if the server is not running on the same PC. Click on the editor widget: the ON-ENTRY trigger will now open the mailslot for writing and the PSTimer.ocx will be closed.
Type a message, press the "Write" button and watch how the server receives it.

About the source

This program will not act as a server and a client at the same time, so let's look at it as if it were two separate programs.

the server functionality

These three parts do the core functionality: CreateMailslot, ReadMailslot and CloseHandle.

RUN CreateMailSlot{&A} (INPUT  cMailslotName:SCREEN-VALUE,
                        INPUT  0, /* Maximum message length */
                        INPUT  0, /* Read timeout */
                        INPUT  0, /* security attributes */
                        OUTPUT hMailSlot). /* handle to mailslot 
                                              or INVALID_HANDLE_VALUE */
--------------------------------------------------------------------------------
FUNCTION ReadMailSlot RETURNS CHARACTER
  ( /* parameter-definitions */ ) :
 
  DEFINE VARIABLE cTempStr    AS CHARACTER NO-UNDO.
  DEFINE VARIABLE iBytesRead  AS INTEGER  NO-UNDO.
  DEFINE VARIABLE iResultCode AS INTEGER  NO-UNDO.
 
  /* allocate some space */
  cTempStr = FILL(' ', 512).
 
  RUN ReadFile (INPUT  hMailslot,
                OUTPUT cTempStr,
                INPUT  512,
                OUTPUT iBytesRead,
                INPUT  0,
                OUTPUT iResultCode).
 
 
  RETURN TRIM(cTempStr) + 
         (IF TRIM(cTempStr) = '' THEN '' ELSE CHR(10)).
 
END FUNCTION.
--------------------------------------------------------------------------------
  RUN CloseHandle(hMailslot,
                  OUTPUT iResultCode).

Function ReadFile() reads one message even if there are more messages pending. The size (512) may not be enough. I think you should call function GetMailslotInfo() first: this returns the number of pending messages (so you can read all of them) and the size of the next message (so you can allocate the proper size).

the client functionality

The most important parts are now: CreateFile, WriteMailSlot and CloseHandle.

RUN CreateFile{&A}( INPUT cMailslotName:SCREEN-VALUE,
                    {&GENERIC_WRITE},
                    {&FILE_SHARE_READ},
                    0,
                    {&OPEN_EXISTING},
                    {&FILE_ATTRIBUTE_NORMAL},
                    0,   
                    OUTPUT hMailslot).
--------------------------------------------------------------------------------
FUNCTION WriteMailSlot RETURNS CHARACTER
  ( /* parameter-definitions */ ) :
 
  DEFINE VARIABLE iBytesWritten  AS  INTEGER     NO-UNDO.
  DEFINE VARIABLE iResultCode    AS  INTEGER     NO-UNDO.
 
  /* Write to the mailslot */
  cMsg =  "\\":U + cComputerName 
         + " - ":U 
         + cMsg:SCREEN-VALUE IN FRAME {&frame-name}.
 
  RUN WriteFile(INPUT  hMailslot,
                INPUT  cMsg,
                INPUT  LENGTH(cMsg) + 1,
                OUTPUT iBytesWritten,
                INPUT  0,
                OUTPUT iResultCode).
 
  IF iResultCode = 0 THEN
  DO:
    MESSAGE "Error on WriteFile. "  
            "Terminating client." 
            VIEW-AS ALERT-BOX.
    APPLY "window-close" TO {&window-name}.
  END.
  ELSE
    cMsg:SCREEN-VALUE = "".
 
 
  RETURN "".   /* Function return value. */
 
END FUNCTION.
--------------------------------------------------------------------------------
  RUN CloseHandle(hMailslot,
                  OUTPUT iResultCode).

Attachments

mailslot.zip : demo