PDA

View Full Version : سوال: گرفتن متن CMD در برنامه



Mask
جمعه 09 فروردین 1392, 03:11 صبح
با سلام.
برنا مه ای دارم که در شبکه به صورت استندبای میمونه و گزارشاتی رو در cmd که در اون در حال اجراست به من میده.
اما مشکا اینه که من این گزارشات رو میخام تحلیل کنم و باید در برنامه من باشه.
از سمپلهای خودم و حتی JvCreateProcess هم استفاده کردم. اما فایده نداشت ، و نمیتونم دقیق گزارشات رو ببینم.
بنابر این تصمیم کرفتم که در مورد GetText از cmd تحقیق کنم.
نظر دوستان چیه؟ چه راههای به نظرتون میرسه که دقیق و بدون خطا باشه.
آیا cmd اصلا GetText میده.
ممنون.

BORHAN TEC
جمعه 09 فروردین 1392, 10:59 صبح
سلام

از سمپلهای خودم و حتی JvCreateProcess هم استفاده کردم. اما فایده نداشت ، و نمیتونم دقیق گزارشات رو ببینم.
من این کامپوننت رو در شرایط مختلفی تست کرده ام و در همه حالات جواب خوبی گرفته ام. به نظرم شما درست عمل نکرده اید. من با این مسئله به طور مستمر در مدت یکسال درگیر بوده ام و در تمام این مدت جامعترین و بهترین راه حلی که در مورد دلفی پیدا کرده ام همین JvCreateProcess بوده است که در تمامی حالات جوابگو است. اگر از من میشنوی به دنبال راه حل دیگری نرو و سعی کن از همین مورد یاد شده درست استفاده کنی! مطمئن هستم که سراغ هر چی بری آخر برمیگردی به همین کامپوننت(به عبارتی وقتت رو تباه نکن)! :چشمک:

MSK
دوشنبه 12 فروردین 1392, 21:34 عصر
خوب اگه میگی که برنامه‌ه خودش داره به کنسول رایت می‌کنه، اگه برنامه‌ی خودت هم کنسول باشه یه راه سادش اینه که از پایپ استفاده کنی. یعنی مثلا اگه برنامه ای که داره گزارش تولید می‌کنه اسمش reporter ه و برنامه تو اسمش consumer ه با اجرای دستور زیر، خروجی اون برنامه به برنامه‌ی تو میاد و می‌تونی از دستورات ساده‌ی read برای گفتن خروجیش استفاده کنی:


C:\> reporter | consumer


اما اگه برنامت گرافیکی ه و میخوای که کنسول برنامه‌ی reporter هم نشون داده نشه و از توی برنامه ی خودت اون برنامه رو هم اجرا کنی، اونوقت راهش دستور api ه createpipe ه که بهش می‌تونی فایل هندلر های خودت رو بدی. اینجا رو ببین: MSDN (http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499%28v=vs.85%29.aspx)

بهروز عباسی
چهارشنبه 25 اردیبهشت 1392, 18:50 عصر
با این که مدت زیادی از ایجاد این تاپیک گذشته ،امروز همچین مطلبی رو روی سایتم قرار دادم گفتم اینجا هم بذارم شاید کسی خواست .
کپی از Capture کردن ConsoleOutput در Delphi (http://codingmaster.ir/?p=200) :

شاید برای شما هم پیش آمده باشد ،که بخواهید خروجی دستورات اجرا شده در CMD ویندوز را به برنامه هایی خودتان وارد کنید ؛مثلاً :خروجی دستور IpConfig
اگر چنین باشد شما با توابع زیر قادر به انجام چنین کاری خواهید بود.

تابع اول :
procedure CaptureConsoleOutput(const ACommand, AParameters: String;
AMemo: TMemo);
const
CReadBuffer = 2400;
var
saSecurity: TSecurityAttributes;
hRead: THandle;
hWrite: THandle;
suiStartup: TStartupInfo;
piProcess: TProcessInformation;
pBuffer: array [0 .. CReadBuffer] of AnsiChar;
dRead: DWord;
dRunning: DWord;
begin
saSecurity.nLength := SizeOf(TSecurityAttributes);
saSecurity.bInheritHandle := True;
saSecurity.lpSecurityDescriptor := nil;

if CreatePipe(hRead, hWrite, @saSecurity, 0) then
begin
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
begin
repeat
dRunning := WaitForSingleObject(piProcess.hProcess, 100);
Application.ProcessMessages();
repeat
dRead := 0;
ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
pBuffer[dRead] := #0;

OemToAnsi(pBuffer, pBuffer);
AMemo.Lines.Add(String(pBuffer));
until (dRead < CReadBuffer);
until (dRunning <> WAIT_TIMEOUT);
CloseHandle(piProcess.hProcess);
CloseHandle(piProcess.hThread);
end;

CloseHandle(hRead);
CloseHandle(hWrite);

end;
end;
روش استفاده :
CaptureConsoleOutput('Ipconfig','',mmo_1)

* mmo_1 یک Memo میباشد .


تابع دوم :
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;

روش استفاده :
mmo_1.Lines.Text := GetDosOutput('Ipconfig')

موفق باشید.

Felony
چهارشنبه 25 اردیبهشت 1392, 19:15 عصر
تابع اولی که قرار دادید مناسبتر عمل کرده ، فقط یه مشکلی داره که وقتی دستورات اشتباه بهش میدید به مشکل میخوره و برنامه فریز میشه ، برای حل این مشکل هم باید حلقه repeat مربوط به کد until (dRunning <> WAIT_TIMEOUT) رو از کد حذف کنید .