PDA

Ver la Versión Completa : Error utilizando GetModuleUsage en WinExecAndWait32 en Borland Delphi 7


feidakila
22-08-2007, 18:51:43
Hola, estoy usando Borland Delphi 7 y necesitaba un procedimiento para ejecutar un programa en consola (cmd) de manera síncrona (es decir hasta que no termina de ejecutarse el programa en la consola no se devuelve el control al programa Delphi que lo llamó) y he estado investigando en la red y el foro y me he topado con una funcion llamada WinExecAndWait32. He descargado 3 versiones diferentes de esta y sólo he conseguido hacer funcionar una de las 3 después de alguna leve modificación.

Pongo las 3 funciones, los problemas que he tenido y las modificaciones que les he hecho, además propongo una duda al final del post que me surge en una de las implementaciones y que no se resolver (por curiosidad)

1era implementacion: esta no me funciona, ya que se llama a WaitForSingleObject antes de que finalice el programa llamado por WinExec
function TForm1.WinExecAndWait(Path:PChar;Visibility:Word):Word;
var
InstanceID:THandle;
begin
InstanceID:=WinExec(Path, Visibility);
WinExecAndWait:=WaitForSingleObject(InstanceID,INFINITE);
end;



2da implementacion: en esta me surgieron los siguientes errores, al principio cuando operamos con la variable Path, se intenta acceder mediante la funcion move a Path[0] con lo que da un error de compilación de valor inaccesible (supongo que se almacena el valor de la longitud de la cadena en esa celda); esto lo he solucionado cambiando el tipo de la variable Path a PChar para no tener que hacer ninguna transformación a Path (de todas maneras no se porque lo hace el autor). Como 2º error que no he conseguido solventar es la llamada a la funcion GetModuleUsage, la cual al compilar me dice que no existe dicho identificador y en la ayuda de Dephi no viene nada al respecto, como solución la he comentado pero evidentemente la función retoma el control antes de que el programa de consola termine (la condición es true)
Function TForm1.WinExecAndWait33(Path : PChar; Visibility : word) : word;
var
InstanceID : THandle;
// PathLen : integer;
begin
{ inplace conversion of a String to a PChar }
// PathLen := Length(Path);
// Move(Path[1],Path[0],PathLen); {esta linea falla al acceder a path[0]}
// Path[PathLen] := #0;
{ Try to run the application }
InstanceID := WinExec(Path,Visibility); {hemos sustituido @Path por Path}
if InstanceID < 32 then { a value less than 32 indicates an Exec error }
WinExecAndWait33 := InstanceID
else
begin
Repeat
Application.ProcessMessages;
until Application.Terminated;{or (GetModuleUsage(InstanceID)=0);} {error! getmoduleusage -> identificador no declarado}
WinExecAndWait33 := 32;
end;
end;



3era implementacion: por último y la que me ha funcionado, salvo una ligera modificación. Y ha sido cambiar el tipo de la variable lpExitCode (antes entero) a tipo cardinal (según parece antes estaba definido como entero y ahora como cardinal)
function TForm1.WinExecAndWait32(Path: PChar; Visibility: Word): integer;
var
Msg: TMsg;
lpExitCode : cardinal; {antes era integer}
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
with StartupInfo do
begin
cb := SizeOf(TStartupInfo);
dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
wShowWindow := visibility;
end;
if CreateProcess(nil,path,nil, nil, False,
NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then begin
repeat
while PeekMessage(Msg, 0, 0, 0, pm_Remove) do
begin
if Msg.Message = wm_Quit then Halt(Msg.WParam);
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
GetExitCodeProcess(ProcessInfo.hProcess,lpExitCode); {producia error porque lpExitCode es de tipo entero y ha de ser cardinal}
until lpExitCode<>Still_Active;
with ProcessInfo do
begin
CloseHandle(hThread);
CloseHandle(hProcess);
end;
result := 0; {sucess}
end
else
result:=GetLastError;
end;



Duda en la 2da implementación ¿porqué no me deja declarar la función GetModuleUsage?, ¿no viene implementada en la librería ShellApi de Borland? (he tratado a incluir la librería WinApi pero me da error, supongo que tampoco existe), ¿existe una función similar, se llama de otra manera?

Perdonad el rollo, pero es que llevaba un tiempo estancado con esto y lo mismo este post sirve por si alguien se topa con el mismo problema, muchas gracias y enhorabuena por el foro es de grandísima ayuda :)