Konuyu Oyla:
  • Derecelendirme: 4.5/5 - 2 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Komut Satırından (CMD) Toplu İş Yaptırmak
#11
(30-10-2020, Saat: 15:37)Bay_Y Adlı Kullanıcıdan Alıntı:
(17-09-2016, Saat: 22:56)Fesih ARSLAN Adlı Kullanıcıdan Alıntı: 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;
  • Komut satırında herhangi bir veya birden fazla iş yaptırıma (com, exe ve bat dosyalarını doğrudan çalıştırma),
  • Komutların işlem sonucunu kendi uygulamanızda görebilme (OnNewChar ve OnNewLine olayları ile OutputLnes ve Lines özellikleri),
  • Komutun bittiğini algılama (OnTerminateProcess ve  OnTerminated olayları),
  • Varsayılan dizini belirleyebilme (CurrentDir özelliği),
  • Geçici Ortam Değişkenleri ekleyebilme (Environment özelliği),
  • Karakter Decode ve Encode işlemleri yapabilme (OnCharEncoding ve OnCharDecoding olayları),
  • Çalışmayan ve Hata oluşturan komutları ve hata türünü yakalama (OnExecuteError olayı),
  • Çalıştırılacak Komutların İşletim Sisteminde öncelik sırasını belirleyebilme (Priority özelliği; aldığı değerler----> HIGH_PRIORITY_CLASS, IDLE_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS ve REALTIME_PRIORITY_CLASS),
  • Satır Satır Komut işletebilme (SendLine özelliği)
  • Çalışma anında iş durumu hakkında bilgi edinebilme (OnTerminateProcess olayı ve ProcessInformation özelliği),

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...

Ö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.

Rica ederim.
Uzun süredir bileşeni kullanmadım. Params veya benzeri bir özelliği varsa bu değerleri set ederek çözebilirsiniz. Yada aşağıdaki klasik yöntemlerden birini kullanabilirsiniz.
Konsoldan E/H parametresini, ilk komut dizisinde göndermeye çalışın (silent mode). Başarılı olursa, bunu bileşenin CommandLine'ına yazarak çalıştırdığınızda aynı sonucu alırsınız.
İlk komut dizisinde E/H gönderilemiyorsa, OnNewLine olayına düşen ANewLine değerini kontrol edin. Bu değer E/H satırındaki mesaj ile aynı ise yeni bir değer (E veya H) gönderin.
Cevapla
#12
(28-03-2018, Saat: 22:08)frmman Adlı Kullanıcıdan Alıntı: 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...s.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;

Benzer bir yöntemle;
Terminal ekranından gelen veriyi aşağıdaki gibi Türkçe karakter setine dönüştürebiliriz. 
procedure TForm1.DosCommand1NewLine(ASender: TObject; const ANewLine: string; AOutputType: TOutputType);
begin
 Memo1.Lines.Add(TEncoding.GetEncoding(857).GetString(TEncoding.Default.GetBytes(ANewLine)));
end;
Begin : = end / 2;
Cevapla
#13
Bir önceki mesajımda vermiş olduğum örnekte; TEncoding sınıfının iç içe kullanımından dolayı (birden fazla örneği çağrılıyor) memoryLeak oluşuyor. Bu nedenle ilk kullanımdaki TEncoding.GetEncoding(857) çağrımından elde edilen TEncoding sınıfının free edilmesi gerekiyor.  
MemoryLeak oluşturmaması için aşağıdaki gibi kullanılbilir.
  with TEncoding.GetEncoding(857) do
 begin
   ArsLog.Log := DateTimeToStr(Now) + ' : ' + GetString(TEncoding.Default.GetBytes(ANewLine));
   Free;
 end;
Console'dan çok fazla geri dönüş olması durumunda (örneğin /c dir Big Grin\*.* gibi), her işlem satırında nesnenin çağrılması (örneğinin oluşması) ve bunun free edilmesi işlemleri performans açısından iyi olmayacaktır.
Bu durumda en iyi performansı elde etmek için uygulama açılışında (OnCreate veya initialization) bir defaya mahsus TEncoding tipinde bir değişken tanımlayıp, buna TEncoding.GetEncoding(857) değeri set edilmelidir. Uygulama kapandığı anda da (destroy veya finalization), yok edilmelidir.
DosCommand bileşeninin OnDosCommandNewLine olayında, tanımladığınız encoding sınıfının GetString metodu kullanılmalıdır. 
Örnekleyecek olursak;
procedure TDosCMD.DosCommand1NewLine(ASender: TObject; const ANewLine: string; AOutputType: TOutputType);
begin
  ArsLog.Log := DateTimeToStr(Now) + ' : ' + DosCMD.ArsEncoding.GetString(TEncoding.Default.GetBytes(ANewLine));
end;

Not: DosCMD.ArsEncoding, TEncoding sınıf tipidir.
Begin : = end / 2;
Cevapla




Konuyu Okuyanlar: 1 Ziyaretçi