![]() |
|
Komut Satırından (CMD) Toplu İş Yaptırmak - Baskı Önizleme +- Delphi Can (https://www.delphican.com) +-- Forum: Delphi (https://www.delphican.com/forumdisplay.php?fid=3) +--- Forum: Eğitim (https://www.delphican.com/forumdisplay.php?fid=19) +---- Forum: Makale (https://www.delphican.com/forumdisplay.php?fid=20) +---- Konu Başlığı: Komut Satırından (CMD) Toplu İş Yaptırmak (/showthread.php?tid=203) Sayfalar:
1
2
|
Komut Satırından (CMD) Toplu İş Yaptırmak - Fesih ARSLAN - 17-09-2016 Merhaba, Windows hedef platformu için bir çoğumuz uygulama yazarken DOS ekranında komut çalıştırma ihtiyacı duymuşuzdur. Bu kapsamda üretilen ve Ücretsiz olarak dağıtılan son derece etkili ve kullanışlı bir Component'ten bahsederek, kullanımı konusunda bilgiler vermek istiyorum. Kullanacağımız component TurboPack DOSCommand. Genel Özellikleri;
Component'i indirmek için: TurboPack - DOSCommand Örnek Bir Uygulama; Yukarıdaki linkten TurboPack - DOSCommand Component'ini indirip kuralım. Tool Palette Penceresi, DOSCommand sekmesinden form üzerine bir adet DosCommand nesnesi yerleştirelim. Form üzerine komutları çalıştırmak ve komut geri dönüş değerlerini almak için birer adet Edit, Button ve Memo nesnesi yerleştirelim ve tasarımını aşağıdaki gibi yapalım. Bir veya birden fazla komut içeren bir toplu işlem dosyası (Batch dosyası) oluşturalım. Benim kullanacağım örnek dosya içeriği aşağıdaki gibi olacak. Butonu çift tıklayıp, OnClick olayına aşağıdaki kodları yazalım. procedure TForm1.Button1Click(Sender: TObject);
begin
DosCommand1.Priority := HIGH_PRIORITY_CLASS; {Çalışacak komutun iş önceliğini Yüksek olarak belirledik}
DosCommand1.CommandLine := edtKomut.Text; {Çalıştırılacak Komut veya Komutlar listesi}
DosCommand1.Execute; {Komutları çalıştır}
end;
DosCommand nesnesini seçelim ve Object Inspector Penceresi Events sekmesinde OnNewLine olayını çift tıklayalım ve aşağıdaki kodları yazalım. procedure TForm1.DosCommand1NewLine(ASender: TObject; const ANewLine: string; AOutputType: TOutputType); begin case AOutputType of TOutputType.otEntireLine: Memo1.Lines.Add(ANewLine); end; end; Son olarak uygulamayı çalıştırıp, sonucuna bakalım. İyi çalışmalar... Cvp: Komut Satırından (CMD) Toplu İş Yaptırmak - Fesih ARSLAN - 18-09-2016 Bu arada toplu iş dosyasının ilk satırında komutları gizlemek için kullandığım echo off komutunun başında @ işareti olması gerekiyordu (@echo off). Konumuzla pek alakası yok ama hatamı sonradan gördüğüm için düzeltme yapayım dedim. Komut Satırından (CMD) Toplu İş Yaptırmak - frmman - 28-03-2018 Merhaba Fesih bey Delphi ile konsol uygulamasından veri alma ile ilgili arama yaparken çözümün DelphiCanda olduğunu görünce çok sevindim ![]() C# da yazdığım bir konsol uygulaması ile Delphi vcl uygulamasını anlattığınız bileşeni kullanarak haberleştirmeyi denedim. Uygulamayı windowsun cmd penceresinden çalıştırılınca, türkçe karakterleri sorunsuz olarak ekranda görebiliyorum. cmd penceresinden c:\consol.exe --- "Şeker gibi" ekrana bir çıktı üretiyor. Aynı işlemi delphi tarafında DosCommand1.CommandLine :='c:\consol.exe'; şeklinde denediğimde çıktıyı memo nesnesine aktarıyor fakat türkçe karakterlerde bozulma meydana geliyor. Makalenizde belirttiğiniz "OnCharEncoding ve OnCharDecoding olayları" nı kullanmayı beceremedim. Aradan baya zaman geçmiş fakat yardımcı olursanız sevinirm. Edit: İlk mesajda geçen link pasif olmuş. Güncel link : https://github.com/TurboPack/DOSCommand Cvp: Komut Satırından (CMD) Toplu İş Yaptırmak - barutali - 28-03-2018 (28-03-2018, Saat: 00:53)frmman Adlı Kullanıcıdan Alıntı: Merhaba Fesih bey Merhaba; Nereden bulduğumu hatırlamıyorum ama aşağıdaki şekilde çözmüştüm. function GetDosOutput(CommandLine: string; Work: string = 'C:\'): AnsiString;
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
StdOutPipeRead, StdOutPipeWrite: THandle;
WasOK: Boolean;
Buffer: array[0..255] of AnsiChar;
BytesRead: Cardinal;
WorkDir: string;
Handle: Boolean;
function StrOemToAnsi(const aStr : AnsiString) : AnsiString;
var
Len : Integer;
begin
if aStr = '' then Exit;
Len := Length(aStr);
SetLength(Result, Len);
OemToCharBuffA(PAnsiChar(aStr), PAnsiChar(Result), Len);
end;
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 := StrOemToAnsi(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;
Kullanımı Memo1.Lines.Text := GetDosOutput('TREE D:\');
Komut Satırından (CMD) Toplu İş Yaptırmak - frmman - 28-03-2018 Teşekkürler @barutali Memo2.Lines.Text := GetDosOutput('TREE C:\1');
Önerdiğiniz yöntemi de denedim, C:\1 klasörü içerisine türkçe karakter içeren klasörler isimlerinde bozulma meydana geldi. Komut Satırından (CMD) Toplu İş Yaptırmak - frmman - 28-03-2018 Aşağıdaki kod türkçe karakter problemi çıkartmadan çalışıyor. DosCommand komponenti çıktı parametrelerini işlem devam ederken gösterebiliyor. Güzel bir özellik. Çok fazla sayıda dosya içeren bir klasörün listelenmesi işleminde, işlem devam ederken ekrana yansımanı göze çok güzel görünüyor. Diğer çözümlerde işlem bittikden sonra sonuç görünüyor. Kaynak procedure RunDosInMemo(DosApp: string; AMemo:TMemo);
const
READ_BUFFER_SIZE = 2400;
var
Security: TSecurityAttributes;
readableEndOfPipe, writeableEndOfPipe: THandle;
start: TStartUpInfo;
ProcessInfo: TProcessInformation;
Buffer: PAnsiChar;
BytesRead: DWORD;
AppRunning: DWORD;
begin
Security.nLength := SizeOf(TSecurityAttributes);
Security.bInheritHandle := True;
Security.lpSecurityDescriptor := nil;
if CreatePipe({var}readableEndOfPipe, {var}writeableEndOfPipe, @Security, 0) then
begin
Buffer := AllocMem(READ_BUFFER_SIZE+1);
FillChar(Start, Sizeof(Start), #0);
start.cb := SizeOf(start);
// Set up members of the STARTUPINFO structure.
// This structure specifies the STDIN and STDOUT handles for redirection.
// - Redirect the output and error to the writeable end of our pipe.
// - We must still supply a valid StdInput handle (because we used STARTF_USESTDHANDLES to swear that all three handles will be valid)
start.dwFlags := start.dwFlags or STARTF_USESTDHANDLES;
start.hStdInput := GetStdHandle(STD_INPUT_HANDLE); //we're not redirecting stdInput; but we still have to give it a valid handle
start.hStdOutput := writeableEndOfPipe; //we give the writeable end of the pipe to the child process; we read from the readable end
start.hStdError := writeableEndOfPipe;
//We can also choose to say that the wShowWindow member contains a value.
//In our case we want to force the console window to be hidden.
start.dwFlags := start.dwFlags + STARTF_USESHOWWINDOW;
start.wShowWindow := SW_HIDE;
// Don't forget to set up members of the PROCESS_INFORMATION structure.
ProcessInfo := Default(TProcessInformation);
//WARNING: The unicode version of CreateProcess (CreateProcessW) can modify the command-line "DosApp" string.
//Therefore "DosApp" cannot be a pointer to read-only memory, or an ACCESS_VIOLATION will occur.
//We can ensure it's not read-only with the RTL function: UniqueString
UniqueString({var}DosApp);
if CreateProcess(nil, PChar(DosApp), nil, nil, True, NORMAL_PRIORITY_CLASS, nil, nil, start, {var}ProcessInfo) then
begin
//Wait for the application to terminate, as it writes it's output to the pipe.
//WARNING: If the console app outputs more than 2400 bytes (ReadBuffer),
//it will block on writing to the pipe and *never* close.
repeat
Apprunning := WaitForSingleObject(ProcessInfo.hProcess, 100);
Application.ProcessMessages;
until (Apprunning <> WAIT_TIMEOUT);
//Read the contents of the pipe out of the readable end
//WARNING: if the console app never writes anything to the StdOutput, then ReadFile will block and never return
repeat
BytesRead := 0;
ReadFile(readableEndOfPipe, Buffer[0], READ_BUFFER_SIZE, {var}BytesRead, nil);
Buffer[BytesRead]:= #0;
OemToAnsi(Buffer,Buffer);
AMemo.Text := AMemo.text + String(Buffer);
until (BytesRead < READ_BUFFER_SIZE);
end;
FreeMem(Buffer);
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
CloseHandle(readableEndOfPipe);
CloseHandle(writeableEndOfPipe);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin {button 1 code}
RunDosInMemo('chkdsk.exe c:\',Memo1);
end;
Komut Satırından (CMD) Toplu İş Yaptırmak - frmman - 28-03-2018 DosCommand komponentinin türkçe karakter problemini , onCharDecoding olayında "code page" kullanarak aşağıdaki şekilde çözdüm. Kod içerisindeki linkde code page ile ilgili açıklayıcı tablo bulunmaktadır. Not: onCharDecoding olayı oluşturulunca onNewLine olayı otomatik olarak devre dışı kalıyor. Konsoldan cevap olarak çok fazla veri geldiğinde yukarıda paylaştığım procedure RunDosInMemo(DosApp: string; AMemo:TMemo);ile başlayan yöntem kilitlenip kalıyordu. DosCommand komponenti sorunsuz çalışıyor. function TForm1.DosCommand1CharDecoding(ASender: TObject; ABuf: TStream): string; var s:string; Bytes: TBytes; begin SetLength(Bytes, abuf.Size); abuf.Read(bytes[0],ABuf.Size -1); // https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx // 857 ibm857 OEM Turkish; Turkish (DOS) // 1026 IBM1026 IBM EBCDIC Turkish (Latin 5) // 1254 windows-1254 ANSI Turkish; Turkish (Windows) s:= TEncoding.GetEncoding(857).GetString(bytes); Memo1.Lines.Add(s); end; Cvp: Komut Satırından (CMD) Toplu İş Yaptırmak - Fesih ARSLAN - 31-10-2018 Merhaba, Linux hedef platformunda Terminal (CMD) üzerinde bir komutu çalıştırmak için de bir çözüm paylaşılmış. Learn How To Execute External Commands On Linux From An Auto Tables For RAD Server API Endpoint Komut Satırından (CMD) Toplu İş Yaptırmak - Bay_Y - 16-11-2018 Teşekkürler, çok güzel birkonu olmuş. Cvp: Komut Satırından (CMD) Toplu İş Yaptırmak - Bay_Y - 30-10-2020 (17-09-2016, Saat: 22:56)Fesih ARSLAN Adlı Kullanıcıdan Alıntı: Merhaba, Öncelikle bilgilendirme için çok teşekkürler Fesih Bey. Birşey sormak istiyorum içeriğinde çalıştırdığımız komutların azılarında E/H sorusu var , sanırım yönetici yetkisinden içindeki komutları bu yetki sorununa takılmadan nasıl çalıştırabilir. Mesela ben sql server durdurmak istiyorum. Bir süre sonra çalıştırmak istiyorum ama durdurmaya çalıştığımda E/H kısmında kaldığı için çalışmıyor. |