TROIA'nın kendi komut setinin yetmediği yerler

TROIA çok geniş bir komut kütüphanesine sahip, ama bazen ihtiyacınız olan işlev (bir Windows API çağrısı, üçüncü parti bir .exe, işletim sistemine özgü bir araç) dilin dışında kalıyor. Bunun için üç farklı kaçış kapısı var: native DLL/SO çağırma, istemcide varsayılan uygulamayı açma, ve harici bir program çalıştırma.

LOADNATIVE: DLL/SO içindeki fonksiyonları çağırmak

LOADNATIVE {kutuphaneadi}, {imza} TO {hedefsembol} WITH {parametreler};

Bu, iasNativeCall.dll (Windows) ya da iasNativeCall.so (Linux) altyapısını kullanarak native bir kütüphanedeki fonksiyonu doğrudan çağırıyor. Örneğin msvcrt.dll'deki abs() fonksiyonunu çağırmak:

LOCAL:
    STRING IMZA;
    STRING SONUC;

IMZA = 'int abs(int)';
LOADNATIVE 'msvcrt.dll', IMZA TO SONUC WITH '-4';
/* SONUC = '4' */

İmza string'i, C fonksiyon prototipini birebir yansıtıyor — tip uyumsuzluğu burada derleme zamanında değil çalışma zamanında ortaya çıkıyor, bu yüzden imzayı hedef kütüphanenin belgesinden doğrulamak önemli.

RUNFILE: istemcinin varsayılan uygulamasıyla açmak

RUNFILE {istemciyolu};

Bir dosyayı, uzantısına göre işletim sisteminin ilişkilendirdiği varsayılan uygulamayla açar — hangi programın PDF, HTML ya da Excel dosyasını açacağını kod içinde hardcode etmenize gerek kalmaz. Sadece istemci tarafındaki yollarla çalışır (* önekiyle).

/* Bir HTML raporu oluşturup istemcide varsayılan tarayıcıda açar. */
LOCAL:
    STRING YOL;

YOL = '*C:\TMP\rapor.htm';
OPEN FILE YOL FORNEW;
PUT '<b>Rapor İçeriği</b>';
CLOSE FILE;
RUNFILE YOL;

RUNPROGRAM: harici bir programı çalıştırmak

RUNPROGRAM {calistirilabilir} [parametreler] [WITH WAIT [INTO {hedefsembol}]];

WITH WAIT verilirse TROIA, harici programın bitmesini bekler ve isterseniz çıktısını INTO ile bir değişkene aktarabilirsiniz — bu, bir sistem komutunun ya da başka bir Java uygulamasının çıktısını TROIA içinde işlemek istediğinizde kullanışlı.

Gerçek bir örnek: whois ile domain müsaitliğini kontrol etmek

Belgelerdeki alıştırma, harici bir whois.exe aracını döngü içinde çağırıp sonucu ayrıştırıyor:

/* Bir domain listesinin müsait olup olmadığını whois ile kontrol eder. */
LOCAL:
    TABLE DOMAINLER(AD CHAR(100));
    STRING KOMUT;
    STRING SONUC;

LOOP AT DOMAINLER
BEGIN
    KOMUT = 'whois.exe ' + DOMAINLER_AD;
    RUNPROGRAM KOMUT WITH WAIT INTO SONUC;

    IF STRPOS(SONUC, 'No match') > 0 THEN
        MESSAGE DOMAINLER_AD + ' müsait görünüyor.' TYPE INFORMATION;
    ENDIF;
ENDLOOP;

Hangi aracı ne zaman seçmeli

  • Sadece bir hesaplama/fonksiyon çağrısı ihtiyacınız varsa ve bunu sunan bir DLL/SO varsa: LOADNATIVE.
  • Kullanıcının, ürettiğiniz bir dosyayı kendi bilgisayarında görüntülemesini istiyorsanız: RUNFILE.
  • Bağımsız bir programı çalıştırıp (isteğe bağlı) çıktısını almanız gerekiyorsa: RUNPROGRAM.

Sık yapılan hatalar

  • İmza string'ini yanlış yazmak — LOADNATIVE'in imza parametresi hedef fonksiyonun C prototipiyle birebir eşleşmezse, sonuç tanımsız davranış ya da çökme olabilir; kullanmadan önce hedef DLL'in dokümantasyonunu doğrulayın.
  • RUNFILE'ı sunucu tarafı bir yolla çağırmaya çalışmak — bu komut sadece istemci makinesinde çalışır; sunucudaki bir dosyayı açmaya çalışmak işe yaramaz, önce dosyayı istemciye taşımanız (COPYFILE ya da benzeri) gerekir.
  • RUNPROGRAM'ı WITH WAIT olmadan çağırıp hemen çıktısını okumaya çalışmak — bekleme olmadan çağrılan bir program henüz bitmemişken çıktı değişkeni boş/eksik gelebilir; çıktıya ihtiyacınız varsa WITH WAIT şart.
  • Harici bir programın application server üzerinde çalıştığını unutmak — RUNPROGRAM, istemci değil sunucu üzerinde çalışır; çağırdığınız programın sunucu makinesinde kurulu ve erişilebilir olduğundan emin olun, aksi halde "dosya bulunamadı" hatası şaşırtıcı gelebilir.
  • Güvenlik: kullanıcı girdisini doğrudan RUNPROGRAM komutuna eklemek — bir kullanıcı girdisini hiç doğrulamadan komut satırına eklemek, command injection riskine yol açar; girdiyi her zaman beklenen formatla (örneğin sadece harf/rakam) doğrulayın.

Sıradaki adım

Sıradaki yazıda thread'ler ve semaforlarla TROIA'da paralel işlem yapmaya değineceğim.