View Full Version : نحوه گرفتن خروجی یک فایل Batch در دلفی
yassabz
سه شنبه 08 اسفند 1391, 04:26 صبح
سلام
دوستان من میخوام یک فایل batch رو با دلفی اجرا کرده و گزارش خروجیش رو با دلفی داخل برنامه از طریق یل memo یا ... داشته باشم .. از طریق shellexecute تونستم فایل رو اجرا کنم و گزارشش رو داخل یک فایل متنی داشته باشم و فایل متن رو داخل memo نمایش بدم .. اما عملا خوب جواب نمیده و خروجیش رو نمیتونم خوب داشته باشم .مخصوصا این که گاهی عملیات کار ما گاهی بیشتر یا کمتر طول میکشه ... کسی در این رابطه تجربه ای چیزی داره ؟! یا راه بهتری برای نمایش مستقیم خروجی batch فایل ؟؟! مرسی
Felony
سه شنبه 08 اسفند 1391, 05:30 صبح
این رو قبلا تو یک برنامه برای pipe زدن نوشته بودم ( البته قسمت هایی رو یادمه از یه سایت روسی پیدا کرده بودم و کاملش کردم ) :
// Run command and return result of it
type
TArg<T> = reference to procedure(const Arg: T);
procedure CaptureConsoleOutput(const ACommand, AParameters: String;
CallBack: TArg<PAnsiChar>);
const
CReadBuffer = 2400;
var
saSecurity: TSecurityAttributes;
hRead: THandle;
hWrite: THandle;
suiStartup: TStartupInfo;
piProcess: TProcessInformation;
pBuffer: array [0 .. CReadBuffer] of AnsiChar;
dBuffer: array [0 .. CReadBuffer] of AnsiChar;
dRead: DWORD;
dRunning: DWORD;
dAvailable: DWORD;
begin
saSecurity.nLength := SizeOf(TSecurityAttributes);
saSecurity.bInheritHandle := True;
saSecurity.lpSecurityDescriptor := nil;
if CreatePipe(hRead, hWrite, @saSecurity, 0) then
try
FillChar(suiStartup, SizeOf(TStartupInfo), #0);
suiStartup.cb := SizeOf(TStartupInfo);
suiStartup.hStdInput := hRead;
suiStartup.hStdOutput := hWrite;
suiStartup.hStdError := hWrite;
suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
suiStartup.wShowWindow := SW_HIDE;
if CreateProcess(nil, PChar(ACommand + ' ' + AParameters), @saSecurity,
@saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup,
piProcess) then
try
repeat
dRunning := WaitForSingleObject(piProcess.hProcess, 100);
PeekNamedPipe(hRead, nil, 0, nil, @dAvailable, nil);
if (dAvailable > 0) then
repeat
dRead := 0;
ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
pBuffer[dRead] := #0;
OemToCharA(pBuffer, dBuffer);
CallBack(dBuffer);
until (dRead < CReadBuffer);
Application.ProcessMessages;
until (dRunning <> WAIT_TIMEOUT);
finally
CloseHandle(piProcess.hProcess);
CloseHandle(piProcess.hThread);
end;
finally
CloseHandle(hRead);
CloseHandle(hWrite);
end;
end;
نمونه استفاده :
CaptureConsoleOutput
('cmd.exe', 'dir',
procedure(const Line: PAnsiChar)
begin
Writeln(String(Line));
end);
خودتون میتونید تغییرات مورد نیاز رو انجام بدید .
yassabz
چهارشنبه 09 اسفند 1391, 05:32 صبح
سلام
ممنون از راهنمایی اما برای من خوب کار نکرد !!! احتمالا یه جای کار میلنگه ..
اینم نمونه برنامه ای ک توش به کار بردم : http://www.4shared.com/rar/XJ1X3Ut7/get_cmd.html
زحمتتون یه چک میکنین ؟ مرسی
yassabz
چهارشنبه 09 اسفند 1391, 10:26 صبح
کجای کارم مشکل داره : به این صورت استفاده کردم !!!
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons, Vcl.ComCtrls;
type
TForm1 = class(TForm)
gtbtn: TBitBtn;
Memo1: TMemo;
BitBtn1: TBitBtn;
ProgressBar1: TProgressBar;
procedure gtbtnClick(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
procedure ProgressBar1ContextPopup(Sender: TObject; MousePos: TPoint;
var Handled: Boolean);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
type
TArg<T> = reference to procedure(const Arg: T);
procedure CaptureConsoleOutput(const ACommand, AParameters: String;
CallBack: TArg<PAnsiChar>);
const
CReadBuffer = 2400;
var
saSecurity: TSecurityAttributes;
hRead: THandle;
hWrite: THandle;
suiStartup: TStartupInfo;
piProcess: TProcessInformation;
pBuffer: array [0 .. CReadBuffer] of AnsiChar;
dBuffer: array [0 .. CReadBuffer] of AnsiChar;
dRead: DWORD;
dRunning: DWORD;
dAvailable: DWORD;
begin
saSecurity.nLength := SizeOf(TSecurityAttributes);
saSecurity.bInheritHandle := True;
saSecurity.lpSecurityDescriptor := nil;
if CreatePipe(hRead, hWrite, @saSecurity, 0) then
try
FillChar(suiStartup, SizeOf(TStartupInfo), #0);
suiStartup.cb := SizeOf(TStartupInfo);
suiStartup.hStdInput := hRead;
suiStartup.hStdOutput := hWrite;
suiStartup.hStdError := hWrite;
suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
suiStartup.wShowWindow := SW_HIDE;
if CreateProcess(nil, PChar(ACommand + ' ' + AParameters), @saSecurity,
@saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup,
piProcess) then
try
repeat
dRunning := WaitForSingleObject(piProcess.hProcess, 100);
PeekNamedPipe(hRead, nil, 0, nil, @dAvailable, nil);
if (dAvailable > 0) then
repeat
dRead := 0;
ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
pBuffer[dRead] := #0;
OemToCharA(pBuffer, dBuffer);
CallBack(dBuffer);
until (dRead < CReadBuffer);
Application.ProcessMessages;
until (dRunning <> WAIT_TIMEOUT);
finally
CloseHandle(piProcess.hProcess);
CloseHandle(piProcess.hThread);
end;
finally
CloseHandle(hRead);
CloseHandle(hWrite);
end;
end;
procedure TForm1.gtbtnClick(Sender: TObject);
begin
CaptureConsoleOutput
('d:\cmd.exe ', ' dir c:\*.* ',procedure(const Line: PAnsiChar)
begin
// Writeln(String(Line));
Memo1.Lines.Add(String(Line)) ;
end);
end;
yassabz
شنبه 12 اسفند 1391, 06:24 صبح
دوستان از
OemToAnsi(Buffer,Buffer);
اشکال میگیره .. کسی میتونه راهنمایی کنه ؟؟؟ کارم گیرشه ..!!
Mask
شنبه 12 اسفند 1391, 11:07 صبح
دوست گرامی:
در ابتدا کدهات رو در بلوک کد سایت قرار بده . تا به صورت صحیح ببینیمشون.
وقتی خود شما برای سوالتون وقت صرف نمیکنید ، چطور انتظار دارید کاربران وقتی وارد این تاپیک میشوند و کدهای در هم شما رو بررسی کنند و به شما جواب بدهند.
و همچنین این سوال شما تا کنون چندین بار مطرح شده و به جواب رسیده. لطفا ، خواهشا ، حد اقل برای جلوگیری از بی نظمی بیشتر و یا سریعتر به جواب رسیدن سوالتون ، جستجو کنید.
لینکهای زیر در مورد سوال شما قبلا ایجاد شده:
http://barnamenevis.org/showthread.php?178069-%DA%AF%D8%B1%D9%81%D8%AA%D9%86-%D8%AE%D8%B1%D9%88%D8%AC%DB%8C-%DB%8C%DA%A9-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%DA%A9%D9%86%D8%B3%D9%88%D9%84-%D8%AF%D8%B1-Memo-%D8%AF%D8%B1-%D8%AF%D9%84%D9%81%DB%8C-2009&p=799628&viewfull=1#post799628
http://barnamenevis.org/showthread.php?52234-%D9%86%DA%A9%D8%A7%D8%AA-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%AF%D8%B1-%D8%AF%D9%84%D9%81%DB%8C&p=1699075&viewfull=1#post1699075
و ...
اگر هم باز این لینکها بهتون کمک نکرد ، میتونید از این کد استفاده کنید:
function GetDosOutput(CommandLine: string; Work: string = 'C:\'): string;
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
StdOutPipeRead, StdOutPipeWrite: THandle;
WasOK: Boolean;
Buffer: array[0..255] of AnsiChar;
BytesRead: Cardinal;
WorkDir: string;
Handle: Boolean;
begin
Result := '';
with SA do begin
nLength := SizeOf(SA);
bInheritHandle := True;
lpSecurityDescriptor := nil;
end;
CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
try
with SI do
begin
FillChar(SI, SizeOf(SI), 0);
cb := SizeOf(SI);
dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
wShowWindow := SW_HIDE;
hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin
hStdOutput := StdOutPipeWrite;
hStdError := StdOutPipeWrite;
end;
WorkDir := Work;
Handle := CreateProcess(nil, PChar('cmd.exe /C ' +'"'+CommandLine+'"'),
nil, nil, True, 0, nil,
PChar(WorkDir), SI, PI);
CloseHandle(StdOutPipeWrite);
if Handle then
try
repeat
WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
if BytesRead > 0 then
begin
Buffer[BytesRead] := #0;
Result := Result + Buffer;
end;
until not WasOK or (BytesRead = 0);
WaitForSingleObject(PI.hProcess, INFINITE);
finally
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
end;
finally
CloseHandle(StdOutPipeRead);
end;
end;
yassabz
یک شنبه 13 اسفند 1391, 05:56 صبح
ممنون .. عذر می خوام در رابطه با بلوک اطلاع نداشتم .. از لینک هایی که گذاشتین و استفاده کردم اما بازم تو این خط خطا میگیره :
OemToAnsi(Buffer,Buffer);
مشکل کجا میتونه باشه ؟
میشه یک مثال استفاده واسه کد بالا هم بزارید؟
مرسی
yassabz
یک شنبه 13 اسفند 1391, 11:27 صبح
از کدوم نسخه از دلفی استفاده میکنید.
از نسخه
Rad XE3
yassabz
یک شنبه 13 اسفند 1391, 15:19 عصر
چی شد ؟!! به چیزی بر خوردید ؟!!
Mask
یک شنبه 13 اسفند 1391, 16:44 عصر
من xe3 برای تست ندارم.
با xe تست کردم.مشکلی نداشت.
yassabz
یک شنبه 13 اسفند 1391, 21:16 عصر
من xe3 برای تست ندارم.
با xe تست کردم.مشکلی نداشت.
کدوم رو تست کردید ؟؟ واسه کدی که خودتون گذاشتید یک مورد نمونه دارید بزارید .. ممنون میشم
BORHAN TEC
دوشنبه 14 اسفند 1391, 15:04 عصر
سلام
بهترین و قابل اعتمادترین روشی که بعد از مدتها تحقیق در این رابطه توانستم پیدا کنم استفاده از کلاس TProcess در Lazarus بود و هیچ نمونه بهتری هم برای دلفی وجود ندارد. بهتره که در داخل Lazarus یک DLL برای این کار ایجاد کرده و از آن DLL در دلفی استفاده کنید. مطمئن باشید که نمونه بهتری را پیدا نخواهید کرد که در تمامی شرایط جوابگو باشد! :چشمک: این هم مستندات این کلاس:
http://wiki.freepascal.org/Executing_External_Programs
در هر صورت اگه یکی همت کنه و این کلاس رو به صورت کامل در دلفی پیاده سازی کنه خیلی ثواب میبره! :قلب:
موفق باشید...
yassabz
سه شنبه 15 اسفند 1391, 07:00 صبح
ممنون .. امکانش هست اگه خودتون اینو تا حالا تست کردید یک سورس کد در این رابطه برام بزارید ؟؟ .. باور کنید الان 2 هفته هست درگیر این جریانم و جواب نمی گیرم .. خیلی ممنون میشم
yassabz
چهارشنبه 16 اسفند 1391, 10:03 صبح
شما که اینو تست کردید اگه براتون امکانش هست سورس تونو برام بزارید .. من جواب نمی گیرم !!
Mask
چهارشنبه 16 اسفند 1391, 17:51 عصر
از این سمپل استفاده کنید.
yassabz
پنج شنبه 17 اسفند 1391, 14:06 عصر
از این سمپل استفاده کنید.
سلام
واقعا ممنون بابت نمونه ای که گذاشتید .. خیلی خوب بود ..اما از این طرق خروجی یک برنامه batch و یا اجرا کردن یکی ازپارامتر های یک برنامه کنسولی رو خیلی تست کردم نتونستم بگیرم !! فقط وارد پوشه یا گرفتن دایرکتری و .. و یا اجرا کردن برنامه ..اما بعد اجرا شدن برنامه نمیتونم پارامتر هاشو فراخونی کنم !! کجای کارم مشکل داره ؟؟؟
Mask
پنج شنبه 17 اسفند 1391, 14:22 عصر
مثال بزنید.
BORHAN TEC
جمعه 18 اسفند 1391, 11:20 صبح
سلام
یک راه حل هم برای دلفی پیدا کردم. استفاده از کامپوننت TJvCreateProcess از مجموعه JVCL. البته هنوز به صورت کامل تستش نکردم که ببینیم از لحاظ پایداری و قابلیت به کلاس TProcess موجود در Lazarus میرسه یا نه.
yassabz
جمعه 18 اسفند 1391, 13:47 عصر
سلام .ممنون از هم فکریتون
ببینید یک برنامه کنسولی هست که یک سری دستورات داره و من یک برنامه دارم که توی یک قسمتش نیاز هست که بعضی از دستورات این برنامه فراخونی بشه و بعضی هاشو خروجی داشته باشم .. البته دیدم که بعضی ها تو برنامه هاشون این کارو کردن .!
Mask
شنبه 19 اسفند 1391, 17:04 عصر
خوب. یه مثالی. نمونه ای. چیزی.آخه ما که علم غیب نداریم ،
من از همین سمپل برای همه دستورات cmd بدون مشکل استفاده میکنم.
BORHAN TEC
یک شنبه 20 اسفند 1391, 10:22 صبح
سلام
کامپوننت TJvCreateProcess رو به صورت کامل تست کردم و جالبه که در تمامی شرایط (مثل Nested Pipes و ...) جوابگو است. به عنوان یک نمونه هم می تونید از مثالی که به همراه JVCL عرضه شده استفاده کنید(ConsoleExample.dpr). در ضمن به رویداد OnShow در فرم مربوط به این مثال بیشتر دقت کنید.
موفق باشید...
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.