PC SOFT

FOROS PROFESIONALES
WINDEVWEBDEV y WINDEV Mobile

Inicio → WINDEV 2024 → Reading an external program output from WinDev Application
Reading an external program output from WinDev Application
Iniciado por guest, 12,oct. 2010 09:23 - 11 respuestas
Publicado el 12,octubre 2010 - 09:23
Hi All:
In WInDev, I need to run an external program in Command Line (for example, using ExeRun()), and read the output from this program from the WinDev application.
I know it's possible to redirect to a file using the ">" operator, but for some reason it's not working, because when I call the program like "program.exe > tempfile.txt", the program.exe takes the ">" symbol as a command line option, so the shell is interpreting the ">" symbol as a command line and not as a redirection command...
Anyway, I would also like to avoid using files between the external program and WInDev application, so my question is if there is a way to read the output from the external program directly from WinDev. The Output is the Standard Output defined in Windows, so we would need to capture this STDO from WinDev.
Any help would be appreciated.
Regards;
Michael
Publicado el 12,octubre 2010 - 12:54
Hi,
use global shared memory zone an comunicate thru memory directly.
Regards.
Publicado el 12,octubre 2010 - 19:56
Hi Novica:
It sounds interesting! But, how can I know the memory address for the Standard Output that the Command line is using? I have no control over this...
Thanks;
Michael
Publicado el 12,octubre 2010 - 19:57
Hi Michael,
Shouldn't it be ">>"?
Georgio
Publicado el 13,octubre 2010 - 01:09
Hi Giorgio:
The ">>" operator is used for redirection to a file/device, but it appends the content (rather than overwrite the file).
I'm trying to avoid the use of files. I'm looking the way to capture the command line output (Standard Output) from the WinDev App. May be using Pipes?
Michael
Publicado el 13,octubre 2010 - 01:11
Hi Michael
From Windev help:

Overview
WinDev, WebDev and WinDev Mobile propose to handle the shared memory zones.
The shared memory zones are a communication mechanism between several applications on a given computer. They are used to easily exchange data between a service and the setting application for instance.
The functions for managing the shared memory zones use the standard APIs of the different operating systems (Windows or Linux) and they facilitate the interoperability between the WinDev/WebDev/WinDev Mobile applications and the applications developed in other languages.



How do I proceed?
Creating a shared memory zone
The shared memory zones are created and opened by fMemOpen.
The first application that accesses the zone will provoke its creation while the other applications will perform a simple opening.
The application that creates the zone defines its size by supplying a minimum size. The operating system will create a zone whose size is a multiple of the size of the memory pages (4 KB sous in Windows 32 bits for example). The actual size of the memory zone is returned by fSize.

// Open the shared memory zone
IdZone is int
IdZone = fMemOpen("MySharedZone",50,shareGlobal)
IF IdZone>0 THEN
ZoneSize is int
ZoneSize = fSize(IdZone)
Info(StringBuild("The memory zone %1 was opened. Its size is equal to %2 bytes.",...
IdZone,ZoneSize))
END
...
// Close the shared memory zone
fClose(IdZone)
Copy this code

Finding out whether a shared memory zone already exists
In some cases, it may be useful to find out whether a shared memory zone already exists.
For example, an application used to configure a service can check whether the service is properly started: all you have to do is check whether a specific shared memory zone was created by the service. If the zone does not exist, an error message can be displayed by the application.
fMemExist is used to find out whether a shared memory zone has already been created by another application.

// Check the existence of the shared memory zone
IF fMemExist("MySharedZone",shareGlobal)=False THEN
Error("Check whether the XXX server was started.")
RETURN
END
Copy this code

Handling the content of a shared memory zone by programming
To handle the content of a shared memory zone, you can:
use the functions for reading and writing in the external files. This solution is recommended for the simple cases (transmission of a string for example).
use the automatic serialization of WLanguage (Serialize and Deserialize), then use the functions for reading and writing in the external files to transmit the elements. This solution is recommended when transmitting classes whose members correspond to the elements to transmit.
The following functions for managing the external files can be used with the shared memory zones:

fWrite Writes:
a character string into an external file.
a section of memory

fWriteLine Writes a line into a text file (in ANSI or UNICODE format)
fRead Reads:
a block of bytes (characters) in an external file (ANSI or Unicode),
the content of an external file (ANSI or Unicode) and assigns it to a memory zone

fReadLine Reads a line in an external file (in ANSI or UNICODE format)
fSeek Returns and modifies the current position in an external file



Dialog between several applications
Two applications can share data by using a shared memory zone.
Two synchronization mechanisms are available:
the automatic notification (by using the callback functions)
the manual synchronization via a semaphore.


Automatic notification of modifications
The automatic notification of modifications can be implemented as soon as a shared memory zone is opened.
To do so, each application that accesses the memory zone must give the name of WLanguage procedure in last parameter of fMemOpen. This procedure will be automatically called whenever the content of the shared memory zone is modified.
To wait for the notification to have been processed by the other applications (before performing a new modification of the memory zone for instance), you must use fMemWait.

// Open the memory zone in the application 1
IdZone is int
IdZone = fMemOpen("SharedZone",200,shareGlobal,"ModifMemory")
...
-- Procedure used for callback (application 1)
PROCEDURE ModifMemory(ModifZoneName is string,IdModifZone is int)
Info(StringBuild("The %1 zone was modified.",ModifZoneName))
Copy this code
// Open the memory zone in the application 2
IdZone is int
IdZone = fMemOpen("SharedZone",200,shareGlobal,"ModifMemory")
// Write into the zone
fWrite(ZoneID,"Hello, I am the application 2.")
// Wait for the validation of "Info" of the "ModifMemory" procedure in the application 1
fMemWait(IdZone)
// Second write operation in the zone
fWrite(IdZone,"New information.")
...
Copy this code

Manual synchronization
The manual synchronization can be performed according to the following principle:
The applications open the shared memory zone and the dialog semaphore.
The first application "takes" the semaphore (SemaphoreStart).
The first application writes its data into the memory zone.
The first application frees the semaphore (SemaphoreEnd).
The second application "takes" the semaphore.
The second application reads the data written by the first application.
The second application frees the semaphore.
Note: If the two applications want to exchange data, two semaphores must be used to insure the regulation.
Tip: The manual synchronization will be preferably used when:
one of the two applications is not written in WLanguage.
the mechanism for notification of modifications is not available.



Naming the shared memory zones
The shared memory zones are identified by their name.
Note: The names of the shared memory zones are case sensitive in Windows and in Linux.

Managing the share mode
The share mode differs according to the versions of the operating systems:
Linux, Windows 2000 and earlier: there is a single space for creating the share memory zone. The parameter of fMemOpen is ignored.
Windows XP: the parameter of fMemOpen is effective if the service for quick change of user is enabled, otherwise it is ignored.
Windows Vista and later: the parameter of fMemOpen is managed. The services and the users are located in a different space. To share a memory zone between a service and an application in the session of a user, the shareGlobal constant must be used.
In Terminal Server: the parameter of fMemOpen is managed. Each session opened on the Terminal Server has a different memory space. The applications started in the same TSE session can share a memory zone created with the shareUser constant. The applications located in different sessions can share a shared memory zone created with the shareGlobal constant.

Correspondence between the name supplied to fMemOpen and the opening in C
The two following code examples present the opening of a memory zone (named "myzone") in WLanguage and in C).

// Code in WLanguage
IdZone is int
IdZone = fMemOpen("myzone",1024,shareGlobal)
Copy this code
// Equivalent code in C
char * szZoneName = "myzone";
int nSize;
int nMem;
key_t nKey;
int nAccess = 0666; // Open in read/write
nSize = 1024;
nKey = ftok(szZoneName+sizeof(char),(int) szZoneName[0]);
nMem = shmget(nKey, nSize , nAccess);
Copy this code


Related Examples :
Tutorial example : WD SharingMemory
[ + ] This example shows how to use the memory sharing functions introduced in WinDev 15.
Several applications may share some data when they are started at the same time. In this case, you may need to share a memory zone. This memory zone will allow all the started applications to share some information.
Publicado el 13,octubre 2010 - 09:07
Hi Novica:
Thanks for taking the time.
From the WinDev Application, there is no problem.
But the other application is already done, and I don't have a way to create a Memory Zone from this side. I call this application from my WinDev App, and the results are sending to the STD Output (you can see the results in the Command Line window). This is the information I need to capture and show in the WinDev App.
However, I don't know how to create a Memory Zone and redirect the messages that is being sent to the STD Output to that Memory Zone.
Regards;
Michael.
Publicado el 13,octubre 2010 - 14:39
Michael,
create a batch file (bat or cmd) with the commands and options you need. Or build it from within your wd-program. And start that bat/cmd using exerun(). You still need the > operator and a tmp-file to get the results.
Publicado el 27,octubre 2010 - 16:06
Hi Michael
I just stumbled on something that looks like a valid answer to your question on the french forum...
Here is a translation:
Use the wddos class from drCharly93 available here:
http://sourceforge.net/projects/wdforge/files/Classes/WD7Dos/cl_7.5WDDos-1.0.0.zip/download
It allows to get the info resulting froma DOS command without opening a dos console.
example:
1 - include the wddos.cdc class in your project
2 - In global delcare a WDDos object
MyCommand is WDDos

3 - Declare a local procedure to capture the output of the command
(here, by example, I display the output in an edit field called DisplayDos)
Procedure WDDOS_ReceiveOutputs(pCommandOutPut is string)
DisplayDOS = DisplayDOS + pCommandOutPut

4 - Run the DOS command
DisplayDos = ""
MyCommand:CommandLine_Let("ipconfig /all")
MyCommand:ExecuteCommand()


----
I haven't tested, but I think it's worth a try
Let us know
Best regards
Publicado el 22,diciembre 2014 - 10:11
I have just used this - it's a bit strangely coded, and I will make a few small changes, but it works great even with WD19.

Thanks for pointing to it.

Kind Regards

Ben
Publicado el 21,octubre 2024 - 10:56
Fabrice Harari wrote:
Hi Michael
I just stumbled on something that looks like a valid answer to your question on the french forum...
Here is a translation:
Use the wddos class from drCharly93 available here:
http://sourceforge.net/projects/wdforge/files/Classes/WD7Dos/cl_7.5WDDos-1.0.0.zip/download
It allows to get the info resulting froma DOS command without opening a dos console.
example:
1 - include the wddos.cdc class in your project
2 - In global delcare a WDDos object
MyCommand is WDDos

3 - Declare a local procedure to capture the output of the command
(here, by example, I display the output in an edit field called DisplayDos)
Procedure WDDOS_ReceiveOutputs(pCommandOutPut is string)
DisplayDOS = DisplayDOS + pCommandOutPut

4 - Run the DOS command
DisplayDos = ""
MyCommand:CommandLine_Let("ipconfig /all")
MyCommand:ExecuteCommand()


----
I haven't tested, but I think it's worth a try
Let us know
Best regards


This wddos program works. But in 64 bit environment it didnt work.
Publicado el 07,junio 2025 - 13:03
a écrit :
Fabrice Harari wrote:
Hi Michael
I just stumbled on something that looks like a valid answer to your question on the french forum...
Here is a translation:
Use the wddos class from drCharly93 available here:
http://sourceforge.net/projects/wdforge/files/Classes/WD7Dos/cl_7.5WDDos-1.0.0.zip/download
It allows to get the info resulting froma DOS command without opening a dos console.
example:
1 - include the wddos.cdc class in your project
2 - In global delcare a WDDos object
MyCommand is WDDos

3 - Declare a local procedure to capture the output of the command
(here, by example, I display the output in an edit field called DisplayDos)
Procedure WDDOS_ReceiveOutputs(pCommandOutPut is string)
DisplayDOS = DisplayDOS + pCommandOutPut

4 - Run the DOS command
DisplayDos = ""
MyCommand:CommandLine_Let("ipconfig /all")
MyCommand:ExecuteCommand()


----
I haven't tested, but I think it's worth a try
Let us know
Best regards

This wddos program works. But in 64 bit environment it didnt work.



ce code fonctionne bien avec windev 25
merci