Win32 API samples

This collection of code snippets used to be hosted on
It is an old collection: it all began in 1996 or 1997, when Progress 8 was new and many of us were still using Windows 3.1 !!
Unlike wine or paintings, program code doesn't get better when it ages. You can find fragments that can be improved because Microsoft continuously expands their API, or are outdated because Progress has added features to the ABL so we don't need to use the WIN32 API anymore.

the obsolete WinExec procedure

WinExec is often found in old examples for Visual Basic. It's old... don't use it!
In Windows 3.x you would have used the WinExec procedure to run a program. The procedure is still around in Windows but it is obsolete, you should use CreateProcess or ShellExecute instead. In fact, WinExec itself is nothing but a wrapper to CreateProcess.
Note that WinExec from "krnl386.exe" (the 16 bit version) can not execute a 32-bit program, while WinExec from "kernel32.dll" (the 32 bit version) can't execute a 16-bit program.
So if you are running a Progress version less than 8.2 on Windows 95+, you may end up using two different versions of WinExec (the regular 16-bits version and a thunked 32-bits version).



Get a list of processes (Windows 95/98/2000)

based on an example by Michael Rüsweg-Gilbert

This procedure can be used to show a list of all running processes, for example to see if Netscape.exe is running. The process indentifier (pid) can be used for getting additional information about the process, or for terminating the process. See TerminateProcess.

This method only works on Windows 95, Windows 98 and Windows 2000. For Windows NT4.0 you have to use procedure EnumProcesses instead.
To check if you are running Windows NT4.0 see page: which Windows version is running.

NT Services Status

by Todd G. Nist

Program source is available for download: w-findservice.w
This is a program for an NT environment which will determine all of the computers on a given network and which services they are running. You can then inquire of a given server what the status is of a services and it will return weather it is running, in error, etc...

It has only been tested under NT 4.0 with service pack 3. You will have to be logged into and authenticated on the network in order to inquire of the status of services running on other machines in the network.

Disallowing multiple instances of your application

_Based on an example from Microsofts whitepaper 'Optimizing Applications for Windows NT Server Terminal Server Edition, version 4.0'_
Suppose you want to prevent your Progress application to be launched more than once on each computer. The startup procedure would contain something like this:

IF IsAppAlreadyRunning(NO, "MyProgressApplication") THEN DO:
   MESSAGE "'MyProgressApplication' is already running on this machine,"
           "only one instance is allowed."
           VIEW-AS ALERT-BOX.
RUN LetAnotherInstanceRun("MyProgressApplication").


sourcecode by Michael Rüsweg-Gilbert

Function GetProcessTimes works on Windows NT only.
GetProcessTimes obtains timing information about a specified process: the creation time, exit time, kernel time and user time. All these are returned as FILETIME structures (a 64 bit count of 100-nanosecond units).
Creation time and exit time are expressed as time elapsed since midnight January 1, 1601 (UTC). Function FileTimeToSystemTime converts this to system time - which may also be UTC.
Function FileTimeToLocalFileTime can be called prior to FileTimeToSystemTime if you want the output to be displayed in local time.

terminate a process gently

Topic TerminateProcess introduced the equivalent to the Unix "kill -9" command.
The following 4GL procedure KillProcess(pid) also terminates a process, but tries to avoid the use of TerminateProcess.
Procedure CloseProcessWindows is based on API-function EnumWindows. This API-function can not be called from within P4GL because it needs a callback, so I wrote procedure CloseProcessWindows in Pascal and added it to proextra.dll (see page ProExtra.dll). Of course I might as well have included all the rest in Pascal too, but then I would not allow myself to post it on this Progress site :-)

terminating a process

To terminate a process for which you know the process handle, you can use function TerminateProcess.
If you don't know the process handle but the process identifier, you can get the handle by calling OpenProcess first.

RUN OpenProcess ({&PROCESS_TERMINATE}, 0, ProcessId, OUTPUT ProcessHandle).
IF ProcessHandle NE 0 THEN DO:
   RUN TerminateProcess (ProcessHandle, 0, OUTPUT ReturnValue).
   RUN CloseHandle(ProcessHandle, OUTPUT ReturnValue).

change title and icon in Windows Task Manager

by Jurjen Dijkstra and Edwin van Elk

When you look at the "Applications" tab in Windows Task Manager, you see that every Progress session has the same title and icon. When you run multiple Progress sessions you may wish to change the icon and/or title of each individual entry in this list.
The Progress session creates one hidden window, which is the owner of all other Progress window. This ultimate owner is the window whos icon and title are displayed in the Task Manager. There is no Progress widget for this window, so you need API functions in order to manipulate it.

&Scoped-Define WM_GETICON 127

sleep (milliseconds)

The P4GL PAUSE function can only be used for whole seconds, not fractions of seconds.
A loop using the ETIME function can be used to wait for fractions of a second, but will keep the processor busy in the current thread.
The following call will wait for 0.5 seconds and minimize system load :

/* by Michael Rüsweg-Gilbert */
RUN sleep ( 500 ).

How does Sleep minimize system load?

Windows works multi-tasking, sort of. A thread is allowed to work for a certain time quantum. When that quantum is over, the running thread is suspended and one of the other threads can start its own time quantum. Which thread? Well, that is decided based on priorities and is not easy to understand, but one thing is clear: a thread is skipped when it has requested a Sleep.

Modules in the current process

It is possible to list all modules (exe, dll, ocx, drv) that are in use by a particular process. This example lists all modules loaded by the current process, which is of course the running Progress process.
The resulting list can be useful during development, to check if a certain DLL or OCX really got released, but can also be useful for support engineers to check if a customer site has the appropriate module versions.
Unfortunately the procedure for Windows NT4 is very different compared to 95/98/2000.

      FIELD hModule        AS INTEGER  FORMAT "->>>>>>>>>>>9"

which version of Windows is running

** note: this topic is outdated, needs to be adjusted for ME and XP **
The API is not exactly the same for the different Windows versions so it is sometimes usefull to know which Windows version is running. However the differences may disappear when Windows 95/98 and Windows NT mature (or when add-ons are installed) so checking for the Windows version may become less interesting: you should prefer to check for features instead versions.
This procedure here shows what Windows version you are running providing it's a 32-bit version. These are:
* Windows 3.1 with win32s
* Windows 95

get a list of processes

This procedure can be used to show a list of all running processes, for example to see if Netscape.exe is running. The process indentifier (pid) can be used for getting additional information about the process, or for terminating the process.
This method uses the psapi.dll which only works on NT (and Windows 2000 etc). On Windows 95 or Windows 98 you can not use psapi.dll, instead you can use the much nicer CreateToolhelp32 functions.
To check if you are running Windows NT4.0 see page: which version of Windows is running.

the current Progress executable

by Sturla Johnsen

This procedure is convenient for tech support: it shows some information about the currently running Progress process like path and name of the Progress executable ("D:\DLC\BIN\PROWIN32.EXE"), the Progress version ("8.2C") and the serial number (believe me).

ASSIGN hModule   = ?
       cFileName = FILL(" ",256).
RUN GetModuleFileNameA(hModule, OUTPUT cFileName, 256, OUTPUT RetVal).
MESSAGE "Progress exe :" SUBSTRING(cFileName, 1, RetVal) SKIP



Syndicate content