PDA

View Full Version : کار با Batch File در دلفی



asdfghjkl
شنبه 05 آبان 1386, 15:25 عصر
دوستان من یک برنامه نوشتم که یک Batch فایل را اجرا می کند اما این Batch File خیلی طول می کشد تا اجرا شود سوال :
1. چگونه بفهمم که Batch File کاملاً اجرا و به اتمام رسیده است
2. چگونه این Batch فایل را بصورت مخفی اجرا کنم (محیط Command Lineنمایش داده نشود)
3. چگونه از خروجی های این Batch فایل در برنامه استفاده کنم

Hamid_PaK
شنبه 05 آبان 1386, 19:50 عصر
1. باید از CreateProcess استفاده کنید تا انتهای اجرای آن منتظر بماند.
2. در هنگام اجرا از پارامتر SW_HIDE استفاده کنید.
3. برای دریافت خروجی CmdLine نیز باید از GetStdHandle استفاده کنید.

یه نگاهی به سورس این پروژه بیاندازید ، نتیجه حاصل خواهد انشاالله ...

Execute Redirected Console
http://praiser.persiangig.com/tmp/bt_download.png (http://praiser.persiangig.com/download/proggy/source/ExecuteRedirectedConsole.Hamid_PaK._PRAISER_.rar)

یا حق ...

dkhatibi
یک شنبه 06 آبان 1386, 06:34 صبح
@ Echo off را نیز در ابتدای فایل بگذارید.

asdfghjkl
یک شنبه 06 آبان 1386, 09:54 صبح
سلام
اگر بخواهیم خروجی کنسول را در فایل نریزیم (در مثال شما خروجی کنسول در یک فایل بنام Output.tmp ریخته می شود ) چکار باید کرد

Hamid_PaK
یک شنبه 06 آبان 1386, 11:47 صبح
اون هم ممکن است ولی خیلی پیچیده می شود و تنها نتیجه آنگاهی که برنامه اصلی نیز Console باشد امکان پذیر است :



function ExecuteIORedirect( const AppPath, CmdLine, DfltDirectory: KOLString;
Show: DWORD; ProcID: PDWORD; InPipe, OutPipeWr, OutPipeRd: PHandle ): Boolean;
{* Executes an application with its console input and output redirection.
Terminating of the application is not waiting, but if ProcID pointer
is defined, it receives process Id launched, so it is possible to
call WaitForSingleObject for it. InPipe is a pointer to THandle variable
which receives a handle to input pipe of the console redirected. The same
is for OutPipeWr and OutPipeRd, but for output of the console redirected.
Before reading from OutPipeRd^, first close OutPipeWr^. If you run
simple console application, for which you want to read results after its
termination, you can use ExecuteConsoleAppIORedirect instead.
|<br>&nbsp;&nbsp;&nbsp;
Notes: if your application is not console and it does not create console
using AllocConsole, this function will fail to redirect input-output. }
function ExecuteConsoleAppIORedirect( const AppPath, CmdLine, DfltDirectory: String;
Show: DWORD; const InStr: String; var OutStr: String; WaitTimeout: DWORD )
: Boolean;
{* Executes an application, redirecting its console input and output.
After redirecting input and output and launching the application,
content of InStr is written to input stream of the application, then
the application is waiting for its termination (WaitTimeout milliseconds
or INFINITE, as passed) and console output of the application is read to
OutStr. TRUE is returned only in case, when all these tasks are
completed successfully.
|<br>&nbsp;&nbsp;&nbsp;
Notes: if your application is not console and it does not create console
using AllocConsole, this function will fail to redirect input-output. }
____________

//[function ExecuteIORedirect]
function ExecuteIORedirect( const AppPath, CmdLine, DfltDirectory: KOLString;
Show: DWORD; ProcID: PDWORD; InPipe, OutPipeWr, OutPipeRd: PHandle ): Boolean;
var Flags: DWORD;
Startup: TStartupInfo;
ProcInf: TProcessInformation;
DfltDir: PKOLChar;
SecurityAttributes: TSecurityAttributes;
SaveStdOut, SaveStdIn: THandle;
ChildStdOutRd, ChildStdOutWr: THandle;
ChildStdInRd, ChildStdInWr: THandle;
ChildStdOutRdDup: THandle;
ChildStdInWrDup: THandle;

procedure Do_CloseHandle( var Handle: THandle );
begin
if Handle <> 0 then
begin
CloseHandle( Handle );
Handle := 0;
end;
end;

procedure Close_Handles;
begin
Do_CloseHandle( ChildStdOutRd );
Do_CloseHandle( ChildStdOutWr );
Do_CloseHandle( ChildStdInRd );
Do_CloseHandle( ChildStdInWr );
end;

function RedirectInputOutput: Boolean;
begin
Result := FALSE;
if (OutPipeRd <> nil) or (OutPipeWr <> nil) then
begin
// redirect output
SaveStdOut := GetStdHandle(STD_OUTPUT_HANDLE);
if not CreatePipe( ChildStdOutRd, ChildStdOutWr, @ SecurityAttributes, 0 ) then
Exit;
if not SetStdHandle( STD_OUTPUT_HANDLE, ChildStdOutWr ) then
Exit;
if not DuplicateHandle( GetCurrentProcess, ChildStdOutRd,
GetCurrentProcess, @ ChildStdOutRdDup, 0, FALSE,
2 {DUPLICATE_SAME_ACCESS} ) then
Exit;
Do_CloseHandle( ChildStdOutRd );
if OutPipeRd <> nil then
OutPipeRd^ := ChildStdOutRdDup;
if OutPipeWr <> nil then
OutPipeWr^ := ChildStdOutWr;
end;
if InPipe <> nil then
begin
// redirect input
SaveStdIn := GetStdHandle(STD_INPUT_HANDLE);
if not CreatePipe( ChildStdInRd, ChildStdInWr, @ SecurityAttributes, 0 ) then
Exit;
if not SetStdHandle( STD_INPUT_HANDLE, ChildStdInRd ) then
Exit;
if not DuplicateHandle( GetCurrentProcess, ChildStdInWr,
GetCurrentProcess, @ ChildStdInWrDup, 0, FALSE,
2 {DUPLICATE_SAME_ACCESS} ) then
Exit;
Do_CloseHandle( ChildStdInWr );
if InPipe <> nil then
InPipe^ := ChildStdInWrDup;
Do_CloseHandle( ChildStdInRd );
end;
Result := TRUE;
end;

procedure Restore_Saved_StdInOut;
begin
SetStdHandle( STD_OUTPUT_HANDLE, SaveStdOut );
SetStdHandle( STD_INPUT_HANDLE, SaveStdIn );
end;

begin
Result := FALSE;
Flags := 0;
if Show = SW_HIDE then
Flags := Flags or {$IFDEF F_P}$08000000{$ELSE}CREATE_NO_WINDOW{$ENDIF};
FillChar( Startup, SizeOf( Startup ), 0 );
Startup.cb := Sizeof( Startup );
if ProcID <> nil then
ProcID^ := 0;
DfltDir := nil;
SecurityAttributes.nLength := Sizeof( SecurityAttributes );
SecurityAttributes.lpSecurityDescriptor := nil;
SecurityAttributes.bInheritHandle := TRUE;
SaveStdOut := 0;
SaveStdIn := 0;
ChildStdOutRd := 0;
ChildStdOutWr := 0;
ChildStdInRd := 0;
ChildStdInWr := 0;
if not RedirectInputOutput then
begin
Close_Handles;
Exit;
end;;
if DfltDirectory <> '' then
DfltDir := PKOLChar( DfltDirectory );
if CreateProcess( nil, PKOLChar( '"' + AppPath + '" ' + CmdLine ),
nil, nil, TRUE, Flags, nil, DfltDir, Startup,
ProcInf ) then
begin
if ProcID <> nil then
ProcID^ := ProcInf.hProcess
else
CloseHandle( ProcInf.hProcess );
CloseHandle( ProcInf.hThread );
Restore_Saved_StdInOut;
Result := TRUE;
end
else
begin
Restore_Saved_StdInOut;
Close_Handles;
Exit;
end;
end;

//[function ExecuteConsoleAppIORedirect]
function ExecuteConsoleAppIORedirect( const AppPath, CmdLine, DfltDirectory: String;
Show: DWORD; const InStr: String; var OutStr: String; WaitTimeout: DWORD ): Boolean;
var PipeIn, PipeOutRd, PipeOutWr: THandle;
ProcID: DWORD;
BytesCount: DWORD;
Buffer: array[ 0..4096 ] of Char;
BufStr: String;
PPipeIn: PHandle;
begin
Result := FALSE;
PPipeIn := @ PipeIn;
if InStr = '' then
PPipeIn := nil;
PipeOutRd := 0;
PipeOutWr := 0;
if not ExecuteIORedirect( AppPath, CmdLine, DfltDirectory, Show, @ ProcID,
PPipeIn, @ PipeOutWr, @ PipeOutRd ) then Exit;
if PPipeIn <> nil then
begin
if InStr <> '' then
WriteFile( PipeIn, InStr[ 1 ], Length( InStr ), BytesCount, nil );
CloseHandle( PipeIn );
end;
OutStr := '';
if WaitForSingleObject( ProcID, WaitTimeOut ) = WAIT_OBJECT_0 then
begin
CloseHandle( ProcID );
CloseHandle( PipeOutWr );
while ReadFile( PipeOutRd, Buffer, Sizeof( Buffer ), BytesCount, nil ) do
begin
SetLength( BufStr, BytesCount );
Move( Buffer[ 0 ], BufStr[ 1 ], BytesCount );
OutStr := OutStr + BufStr;
end;
end
else
CloseHandle( PipeOutWr );
CloseHandle( PipeOutRd );
Result := TRUE;
end;
به نقل از یونیت KOL نوشته کلادوو ولادمیر ...

یا حق ...

dkhatibi
دوشنبه 07 آبان 1386, 06:55 صبح
سلام
اگر بخواهیم خروجی کنسول را در فایل نریزیم (در مثال شما خروجی کنسول در یک فایل بنام Output.tmp ریخته می شود ) چکار باید کرد
در داس با نوشتن دستور و علامت < می شه خروجی را به فایل منتقل کرد
مثال:

Dir c:\>temp.txt
dir c:\>>temp.txt

Hamid_PaK
دوشنبه 07 آبان 1386, 07:59 صبح
اگر بخواهیم خروجی کنسول را در فایل نریزیم چکار باید کرد
آقای خطیبی این دوست ما گفتن که نمی خواهند خروجی در فایلی ذخیره شود !

یا حق ...

Inprise
دوشنبه 07 آبان 1386, 19:05 عصر
اگر هم مایل بودی این مجموعه نیازها رو خودت ننویسی ، همه اش یکجا در کامپوننت tjvclprocess که در بسته JVCL هست وجود داره . رایگان .

dkhatibi
دوشنبه 07 آبان 1386, 20:32 عصر
آقای خطیبی این دوست ما گفتن که نمی خواهند خروجی در فایلی ذخیره شود !

یا حق ...
معذرت
اشکال در بینایی