Skip to main content
Software used:
 
Microsoft Visual Studio Professional 2019
Version 16.11.42
 
Micro Focus Visual COBOL 8.0 
 
Operating System: Windows Server 2022 Datacenter
 
Problem Description:
 
I have a Micro Focus Visual COBOL code that is built into exe and made to run as Windows services. There is a requirement to capture more information through code and record it in Windows event log as part of Windows services event logging.
 
Looking to find solution for below two items:
 
1. Micro Focus Visual COBOL API functions that can access (read/write) to Windows event log.
 
2. Ways to capture Windows logged in user information in Micro Focus Visual COBOL code and write it to event log.


------------------------------
Kavitha Natarajan
Rocket Software Forum Member
------------------------------
Software used:
 
Microsoft Visual Studio Professional 2019
Version 16.11.42
 
Micro Focus Visual COBOL 8.0 
 
Operating System: Windows Server 2022 Datacenter
 
Problem Description:
 
I have a Micro Focus Visual COBOL code that is built into exe and made to run as Windows services. There is a requirement to capture more information through code and record it in Windows event log as part of Windows services event logging.
 
Looking to find solution for below two items:
 
1. Micro Focus Visual COBOL API functions that can access (read/write) to Windows event log.
 
2. Ways to capture Windows logged in user information in Micro Focus Visual COBOL code and write it to event log.


------------------------------
Kavitha Natarajan
Rocket Software Forum Member
------------------------------

Hi Kavitha,

See the code attached.

& this one too

       115-log-nt-event.
 
      ***  First register the Event Source
 
           call staticWINAPI RegisterEventSource
              using by value     0 size 4
                    by reference EVENT-NAME & x"00"
              returning ws-event-handle
           end-call
 
           if ws-event-handle not = 0
      ***     Successfully registered. Report the event
              move "COBOL has sent a a message" & x"00"
                 to ws-event-message
              set message-pointer to address of ws-event-message
              call staticWINAPI ReportEvent
                 using by value ws-event-handle
                       by value EVENTLOG-INFORMATION-TYPE size 2
                       by value 0 size 2
                       by value 0 size 4
                       by value 0 size 4
                       by value 1 size 2
                       by value 0 size 4
                       by reference message-pointer
                       by value 0 size 4
                 returning ws-retcode
               end-call
 
           *>    call staticWINAPI GetLastError returning ws-error
           *>    end-call
               call staticWINAPI DeregisterEventSource
                  using by value ws-event-handle
               end-call
           end-if.



------------------------------
Yvon Abgrall
Support engeneer
Rocket Internal - All Brands
... FR
------------------------------

Hi Kavitha,

See the code attached.

& this one too

       115-log-nt-event.
 
      ***  First register the Event Source
 
           call staticWINAPI RegisterEventSource
              using by value     0 size 4
                    by reference EVENT-NAME & x"00"
              returning ws-event-handle
           end-call
 
           if ws-event-handle not = 0
      ***     Successfully registered. Report the event
              move "COBOL has sent a a message" & x"00"
                 to ws-event-message
              set message-pointer to address of ws-event-message
              call staticWINAPI ReportEvent
                 using by value ws-event-handle
                       by value EVENTLOG-INFORMATION-TYPE size 2
                       by value 0 size 2
                       by value 0 size 4
                       by value 0 size 4
                       by value 1 size 2
                       by value 0 size 4
                       by reference message-pointer
                       by value 0 size 4
                 returning ws-retcode
               end-call
 
           *>    call staticWINAPI GetLastError returning ws-error
           *>    end-call
               call staticWINAPI DeregisterEventSource
                  using by value ws-event-handle
               end-call
           end-if.



------------------------------
Yvon Abgrall
Support engeneer
Rocket Internal - All Brands
... FR
------------------------------

Hi Yvon,

Thanks a lot for your response and code. I did try your code snippet and was able to see the written event, through event viewer.

I now have the need to send the local system logged in user information to the event. Is there any means we can capture the Windows logged in user through code?

Thanks & Regards,

Kavitha.



------------------------------
Kavitha Natarajan
Rocket Software Forum Member
------------------------------

Hi Yvon,

Thanks a lot for your response and code. I did try your code snippet and was able to see the written event, through event viewer.

I now have the need to send the local system logged in user information to the event. Is there any means we can capture the Windows logged in user through code?

Thanks & Regards,

Kavitha.



------------------------------
Kavitha Natarajan
Rocket Software Forum Member
------------------------------

Demo attached

LookupAccountNameA function (winbase.h) - Win32 apps | Microsoft Learn   to get the SID



------------------------------
Yvon Abgrall
Support engeneer
Rocket Internal - All Brands
... FR
------------------------------

Demo attached

LookupAccountNameA function (winbase.h) - Win32 apps | Microsoft Learn   to get the SID



------------------------------
Yvon Abgrall
Support engeneer
Rocket Internal - All Brands
... FR
------------------------------
      $set case sourceformat"variable"
       program-id. MSReportEvent as "MSReportEvent".
       environment division.
           special-names. call-convention 74 is WINAPI.
 
       data division.
       working-storage section.  
       78 78-ServiceName           value
          'COBOL MSReportEvent'.
       
       01 int      is typedef pic s9(9)  comp-5.
       01 ulong    is typedef pic 9(9)   comp-5.
       01 BOOL     is typedef int.
       01 DWORD    is typedef ulong.
       01 uns-long pic  9(9)  comp-5 is typedef.
 
       01 string-ptr                     pic x comp-x.
       01 msg-rec                        pic x(51).
       01 HANDLE                         pic x(4) comp-5 is typedef.
       01 hEventSource                   usage HANDLE.
       01 pString                        usage pointer.
 
       78 EVENTLOG-INFORMATION-TYPE      value 4.
       
      *--> zones below used by API getusername & getcomputername
       01 Buffer                        pic x(1024).
       01 BufferLen                     DWORD.
       01 aBool                          BOOL.
       78 isTrue                        value 1.
       
       01 SID pic x(256).
       01 SIDlen DWORD value 256.
       01 ReferencedDomainName pic x(64).
       01 ReferencedDomainNameLen DWORD value 64.
       01  1-SID-AND-ATTRIBUTES               is typedef.
        02 1sid              usage pointer.
        02 1attributes       usage uns-long.       
       01 enum_SID_NAME_USE    1-SID-AND-ATTRIBUTES.
      *linkage section.
 
       01 msg-1                pic x(50).
       01 msg-2                pic x(50).
       01 msg-3                pic x(50).
       01 msg-4                pic x(50).
 
       procedure division.
      *    call "cob32api".
      *
      *-->     Get the Computer Name
               move 1024 to BufferLen move spaces to buffer
               call WINAPI "GetComputerNameA" using
                    by reference Buffer,
                    by reference BufferLen
                    returning aBool
               end-call
               if aBool is not equal to isTrue
                   move "??????????" to  Buffer(1:10)
               end-if
               display "**-> PC name: " buffer(1:bufferlen)
               
      *-->     Get the user Name
               move 1024 to BufferLen move spaces to buffer
               call WINAPI "GetUserNameA" using
                    by reference Buffer,
                    by reference BufferLen
                    returning aBool
               end-call
               if aBool is not equal to isTrue
                   move "??????????" to  Buffer(1:10)
               end-if
               display "**-> PC name: " buffer(1:bufferlen)
               
               
               
      *https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-lookupaccountnamea
      *LookupAccountNameA
           inspect buffer replacing all spaces by low-values
           perform varying BufferLen from 1 by 1
             until Buffer(BufferLen:1) = low-value
           end-perform
           
           call WINAPI "LookupAccountNameA"
               using by value       0 size 4 *> local system
 
                     by reference  buffer
                     by reference  SID 
                     by reference  SIDlen
                     by reference  ReferencedDomainName
                     by reference  ReferencedDomainNameLen
                     by reference  enum_SID_NAME_USE
               returning aBool
           if aBool = 0
               display "LookupAccountSidA failed"
           else
               display "LookupAccountSidA did succeed"
           end-if
 
           move "*--> COBOL msg-1"     to msg-1
           move "*--> COBOL msg-2"     to msg-2
           move "*--> COBOL msg-3"     to msg-3
           move "*--> COBOL msg-4"     to msg-4
           move spaces                 to msg-rec
 
           move 1 to string-ptr
           string msg-1 x'00' delimited by size into msg-rec
               with pointer string-ptr
           perform do-report-event.
 
           move 1 to string-ptr
           string msg-2 x'00' delimited by size into msg-rec
               with pointer string-ptr
           perform do-report-event.
 
           move 1 to string-ptr
           string msg-3 x'00' delimited by size into msg-rec
               with pointer string-ptr
           perform do-report-event.
 
           move 1 to string-ptr
           string msg-4 x'00' delimited by size into msg-rec
               with pointer string-ptr
           perform do-report-event.
 
           exit program.
           goback .
           stop run.
 
       do-report-event.
      *    Register as an event source
           call WINAPI 'RegisterEventSourceA'
               using by value 0 size 4
                     by reference 78-ServiceName & x'00'
               returning hEventSource
           if hEventSource not = 0
      *        Successfully registered. Report the event
               set pString to address of msg-rec
               call WINAPI 'ReportEventA'
                   using by value hEventSource
                         by value EVENTLOG-INFORMATION-TYPE size 2
                         by value 333 size 2
                         by value 0   size 4
                         *>by value 0   size 4
                         by reference SID 
                         by value 1   size 2
                         by value 0   size 4
                         by reference pString
                         by value 0 size 4
               call WINAPI 'DeregisterEventSource'
                   using by value hEventSource
           end-if
 
       end program MSReportEvent.



------------------------------
Yvon Abgrall
Support engeneer
Rocket Internal - All Brands
... FR
------------------------------
      $set case sourceformat"variable"
       program-id. MSReportEvent as "MSReportEvent".
       environment division.
           special-names. call-convention 74 is WINAPI.
 
       data division.
       working-storage section.  
       78 78-ServiceName           value
          'COBOL MSReportEvent'.
       
       01 int      is typedef pic s9(9)  comp-5.
       01 ulong    is typedef pic 9(9)   comp-5.
       01 BOOL     is typedef int.
       01 DWORD    is typedef ulong.
       01 uns-long pic  9(9)  comp-5 is typedef.
 
       01 string-ptr                     pic x comp-x.
       01 msg-rec                        pic x(51).
       01 HANDLE                         pic x(4) comp-5 is typedef.
       01 hEventSource                   usage HANDLE.
       01 pString                        usage pointer.
 
       78 EVENTLOG-INFORMATION-TYPE      value 4.
       
      *--> zones below used by API getusername & getcomputername
       01 Buffer                        pic x(1024).
       01 BufferLen                     DWORD.
       01 aBool                          BOOL.
       78 isTrue                        value 1.
       
       01 SID pic x(256).
       01 SIDlen DWORD value 256.
       01 ReferencedDomainName pic x(64).
       01 ReferencedDomainNameLen DWORD value 64.
       01  1-SID-AND-ATTRIBUTES               is typedef.
        02 1sid              usage pointer.
        02 1attributes       usage uns-long.       
       01 enum_SID_NAME_USE    1-SID-AND-ATTRIBUTES.
      *linkage section.
 
       01 msg-1                pic x(50).
       01 msg-2                pic x(50).
       01 msg-3                pic x(50).
       01 msg-4                pic x(50).
 
       procedure division.
      *    call "cob32api".
      *
      *-->     Get the Computer Name
               move 1024 to BufferLen move spaces to buffer
               call WINAPI "GetComputerNameA" using
                    by reference Buffer,
                    by reference BufferLen
                    returning aBool
               end-call
               if aBool is not equal to isTrue
                   move "??????????" to  Buffer(1:10)
               end-if
               display "**-> PC name: " buffer(1:bufferlen)
               
      *-->     Get the user Name
               move 1024 to BufferLen move spaces to buffer
               call WINAPI "GetUserNameA" using
                    by reference Buffer,
                    by reference BufferLen
                    returning aBool
               end-call
               if aBool is not equal to isTrue
                   move "??????????" to  Buffer(1:10)
               end-if
               display "**-> PC name: " buffer(1:bufferlen)
               
               
               
      *https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-lookupaccountnamea
      *LookupAccountNameA
           inspect buffer replacing all spaces by low-values
           perform varying BufferLen from 1 by 1
             until Buffer(BufferLen:1) = low-value
           end-perform
           
           call WINAPI "LookupAccountNameA"
               using by value       0 size 4 *> local system
 
                     by reference  buffer
                     by reference  SID 
                     by reference  SIDlen
                     by reference  ReferencedDomainName
                     by reference  ReferencedDomainNameLen
                     by reference  enum_SID_NAME_USE
               returning aBool
           if aBool = 0
               display "LookupAccountSidA failed"
           else
               display "LookupAccountSidA did succeed"
           end-if
 
           move "*--> COBOL msg-1"     to msg-1
           move "*--> COBOL msg-2"     to msg-2
           move "*--> COBOL msg-3"     to msg-3
           move "*--> COBOL msg-4"     to msg-4
           move spaces                 to msg-rec
 
           move 1 to string-ptr
           string msg-1 x'00' delimited by size into msg-rec
               with pointer string-ptr
           perform do-report-event.
 
           move 1 to string-ptr
           string msg-2 x'00' delimited by size into msg-rec
               with pointer string-ptr
           perform do-report-event.
 
           move 1 to string-ptr
           string msg-3 x'00' delimited by size into msg-rec
               with pointer string-ptr
           perform do-report-event.
 
           move 1 to string-ptr
           string msg-4 x'00' delimited by size into msg-rec
               with pointer string-ptr
           perform do-report-event.
 
           exit program.
           goback .
           stop run.
 
       do-report-event.
      *    Register as an event source
           call WINAPI 'RegisterEventSourceA'
               using by value 0 size 4
                     by reference 78-ServiceName & x'00'
               returning hEventSource
           if hEventSource not = 0
      *        Successfully registered. Report the event
               set pString to address of msg-rec
               call WINAPI 'ReportEventA'
                   using by value hEventSource
                         by value EVENTLOG-INFORMATION-TYPE size 2
                         by value 333 size 2
                         by value 0   size 4
                         *>by value 0   size 4
                         by reference SID 
                         by value 1   size 2
                         by value 0   size 4
                         by reference pString
                         by value 0 size 4
               call WINAPI 'DeregisterEventSource'
                   using by value hEventSource
           end-if
 
       end program MSReportEvent.



------------------------------
Yvon Abgrall
Support engeneer
Rocket Internal - All Brands
... FR
------------------------------



------------------------------
Yvon Abgrall
Support engeneer
Rocket Internal - All Brands
... FR
------------------------------



------------------------------
Yvon Abgrall
Support engeneer
Rocket Internal - All Brands
... FR
------------------------------

Hi Yvon!

Thank you so much, I tried the user name part of the code and was able to pull the logged in user information to the event viewer. I have more details to populate in the event viewer as the project develops. All information you have provided has been super helpful.

Appreciate all your support!

Thanks,

Kavitha.



------------------------------
Kavitha Natarajan
Rocket Software Forum Member
------------------------------