Challenge 7

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Challenge 7

Mesaj gönderen thelvaci »

Hemen hemen hepimizin bazen yazdığımız bir uygulamanın birden fazla çalışmamasına ihtiyacımız olmuştur. Uygulamamızın ikinci bir kopyasının çalıştırılmasını istemediğimiz durumlar olmuştur. Ve bu isteğimizi Mutex'ler vasıtası ile rahat bir şekilde karşılayabiliyoruz.

Peki ya uygulamızdan sadece 2 kopya çalışmasını istese idik; nasıl bir kontrol yapmamız gerekir idi ? Yani abc.exe'nin sadece 2 kere çalıştırılmasını arzu ediyoruz.

Kurallar: Uygulamamız herhangi bir şekilde diske, registry'e çalışma sayısı ile ilgili bir bilgi yazamaz ve oradan okuyamaz.
Kullanıcı avatarı
SimaWB
Üye
Mesajlar: 1316
Kayıt: 07 May 2009 10:42
Konum: İstanbul
İletişim:

Re: Challenge 7

Mesaj gönderen SimaWB »

EnumWindows ile pencereleri listelesek. Bu listede ana formumun class'ına uyanların sayısını alsak. Bu sayı 2 ise programın açılmasına izin vermesek?
There's no place like 127.0.0.1
ikra
Üye
Mesajlar: 901
Kayıt: 28 Nis 2005 01:26
Konum: Simdilik Topragin Üstü

Re: Challenge 7

Mesaj gönderen ikra »

kendimize ait iki adet atom belirler, atom'un var olup olmadigini check ederiz.
Atom1 var ve Atom2 yok ise, 1 adet program calisiyor demektir, ikincisine de access verilir.
Atom2 var ve Atom1 yok ise, yine b1 adet program calisiyor demektir, ikincisine de access verilir.
Atom1 ve Atom2 yok ise, program ilk defa calisacaktir, hem birincisine, hem de ikincisine access verilir.
Atom1 ve Atom2 var ise, iki program da calisiyor demektir, access verilmez.
kıdemsiz üye
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: Challenge 7

Mesaj gönderen thelvaci »

SimaWB yazdı:EnumWindows ile pencereleri listelesek. Bu listede ana formumun class'ına uyanların sayısını alsak. Bu sayı 2 ise programın açılmasına izin vermesek?
:bravo: Peki başka nasıl yapılabilir, çok daha kısa ve efektif bir yolu daha var Veli bey ;)
ikra
Üye
Mesajlar: 901
Kayıt: 28 Nis 2005 01:26
Konum: Simdilik Topragin Üstü

Re: Challenge 7

Mesaj gönderen ikra »

thelvaci yazdı:Kurallar: Uygulamamız herhangi bir şekilde diske, registry'e çalışma sayısı ile ilgili bir bilgi yazamaz ve oradan okuyamaz.
bunu görmemistim.
baska alternatif gelmiyor aklima.
kıdemsiz üye
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: Challenge 7

Mesaj gönderen thelvaci »

ikra yazdı:kendimize ait iki adet atom belirler, atom'un var olup olmadigini check ederiz.
Atom1 var ve Atom2 yok ise, 1 adet program calisiyor demektir, ikincisine de access verilir.
Atom2 var ve Atom1 yok ise, yine b1 adet program calisiyor demektir, ikincisine de access verilir.
Atom1 ve Atom2 yok ise, program ilk defa calisacaktir, hem birincisine, hem de ikincisine access verilir.
Atom1 ve Atom2 var ise, iki program da calisiyor demektir, access verilmez.
:bravo: Gayet güzel ama Veli bey'e söylediğim gibi daha efektif bir yolu var ;) Ayrıca Atom'larda bazen sıkıntı olabiliyor, uygulama normal bir şekilde kapatılamaz ise bazen atom sistemden silinmemiş oluyor. Dolayısı ile gerçekten de çalışan bir exe'niz olmasa da uygulamanızı çalıştıramayabiliyorsunuz.
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: Challenge 7

Mesaj gönderen thelvaci »

ikra yazdı:
thelvaci yazdı:Kurallar: Uygulamamız herhangi bir şekilde diske, registry'e çalışma sayısı ile ilgili bir bilgi yazamaz ve oradan okuyamaz.
bunu görmemistim.
baska alternatif gelmiyor aklima.
Gelir gelir biraz daha düşün ;)
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: Challenge 7

Mesaj gönderen thelvaci »

Kernel nesneleri üzerinde düşünün arkadaşlar ;)
Kullanıcı avatarı
SimaWB
Üye
Mesajlar: 1316
Kayıt: 07 May 2009 10:42
Konum: İstanbul
İletişim:

Re: Challenge 7

Mesaj gönderen SimaWB »

File Mapping ile yapılıyormuş :)
CreateFileMapping, OpenFileMapping, MapViewOfFile....
Çözümü buldum ama örnek yazacak vakit yok :(
There's no place like 127.0.0.1
xxxjedixxx
Üye
Mesajlar: 216
Kayıt: 10 Ara 2013 03:50

Re: Challenge 7

Mesaj gönderen xxxjedixxx »

Merhaba,

RAM'de bir dosya oluşturup bu dosya ile çalışma sayısı artırılıp azaltılabilir. Aşağıdaki API'ler ile bu kontrol yapılabilir.

CreateFileMapping - dosyayı oluşturmak,
OpenFileMapping - var olan dosyayı okuma ve yazma için açmak
MapViewOfFile - dosyanın içeriğini okuma
UnmapViewOfFile - Dosyayı değiştirme ve kapatma

Dosya yoksa program henüz hiç çalışmamıştır. Dosyaya 1 değeri yazılır ve kapatılır. Eğer dosya varsa sayı okunur ve bir artırılıp kaydedilir. Programdan çıkarken de bu sayı bir azaltırılıp kaydedilir. Çıkarken eğer sayı 1 ise dosya silinir.
Kullanıcı avatarı
G.Arkas
Üye
Mesajlar: 829
Kayıt: 01 Eki 2007 07:16
Konum: İstanbul
İletişim:

Re: Challenge 7

Mesaj gönderen G.Arkas »

CreateMutex
FileMapping
Resim
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: Challenge 7

Mesaj gönderen thelvaci »

:bravo: Arkadaşlar, güzel noktalara temas etmişsiniz. Herbirinizin ellerine sağlık. Evet named FileMapping objeleri ile bu iş yapılabilir elbette ama biraz meşakkatli olur. Birden fazla mutex kullanarak da yapılabilir sizlerin de belirttiği gibi. Ama gözünüzün önünde olan inanılmaz kolay ve efektif bir başka çözümü daha var.

Kısaca bir ipucu vereyim, örnek yapma işini de siz halledin. Semaphore ;)

Bu arada gördüm ki, challange açar iken daha dikkatli olmalıymışım. Zehir gibi arkadaşlar, şu anda bu challange'ı deldiler :) Aslında hiç bir şekilde yazma ve okuma yapmadan nasıl yapılır diye sormalıymışım, öyle sormadığım için hemen CreateFileMapping IPC mekanizmasına atıfta bulunmuşsunuz :) Neyse bir sonraki challange'da sizlerin nerelerden sızıntı yapabileceğini hesaplayıp kuralları ona göre koymaya çalışacağım ;)
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: Challenge 7

Mesaj gönderen thelvaci »

Ayrıca belirtmek isterim ki; Atom'ları ve FileMapping nesnelerini kullanır iken dikkatli olmalısınız. Bu tarz bir iş için yeterli işlevselliği sunmayabilirler. GlobalAddAtom ile eklenen bir atomun sistemden silinebilmesi için ilgili atom tablosunda referansının sıfıra erişmesi gerekir; dolayısı ile uygulamalar ilgili atom ile işleri kalmadığında GlobalDeleteAtom çağrımını yapmak zorundadırlar. Aynı şekilde; CreateFileMapping ile oluşturulan bir hafıza bölgesi; sizlerin de belirttiği gibi uygulamadan çıkılır iken güncellenmelidir. Ancak; bunlar kernel nesneleri olmadıkları için kontrol kullanıcı bazlıdır ve uygulamanız TerminateProcess yada ona benzer API'ler ile sonlandırılır ise istenmeyen sonuçları gözlemlersiniz. Atom kullanımında uygulamanız terminate edildiğinde GlobalDeleteAtom çağrımını yapamamış olursunuz ve atom tablosunda ilgili atomun referansı azaltılmamış şekilde kalır. Aynı şekilde FileMapping'de de ilgili hafıza bölgesini güncelleyememiş olursunuz.

Bu bilgileri de ek bir izahat olarak sunmak gerektiğini düşündüm.
Kullanıcı avatarı
SimaWB
Üye
Mesajlar: 1316
Kayıt: 07 May 2009 10:42
Konum: İstanbul
İletişim:

Re: Challenge 7

Mesaj gönderen SimaWB »

Projemizin DPR dosyasını aşağıdaki şekilde yapıyoruz:

Kod: Tümünü seç

uses
  Forms, Windows, SysUtils, Dialogs,
  Unit1 in 'Unit1.pas' {FormTest};

{$R *.res}

var
  Semaphore: THandle;

begin
  Semaphore := CreateSemaphore(nil, 2, 2, 'Semaphore-umBeniiiiiim:)');
  if Semaphore <> 0 then
    try
      if WaitForSingleObject(Semaphore, 0) = WAIT_OBJECT_0 then
      begin
        try
          Application.Initialize;
          Application.MainFormOnTaskbar := True;
          Application.CreateForm(TFormTest, FormTest);
          Application.Run;
        finally
          ReleaseSemaphore(Semaphore, 1, nil);
        end;
      end
      else begin
        ShowMessage('En fazla 2 örnek çalışabilir');
        Exit;
      end;
    finally
      CloseHandle(Semaphore);
    end;
end.
2 örnekten fazla çalıştırmak istersek hata mesajı gösterip kapanır.
There's no place like 127.0.0.1
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: Challenge 7

Mesaj gönderen thelvaci »

SimaWB yazdı:Projemizin DPR dosyasını aşağıdaki şekilde yapıyoruz:

Kod: Tümünü seç

uses
  Forms, Windows, SysUtils, Dialogs,
  Unit1 in 'Unit1.pas' {FormTest};

{$R *.res}

var
  Semaphore: THandle;

begin
  Semaphore := CreateSemaphore(nil, 2, 2, 'Semaphore-umBeniiiiiim:)');
  if Semaphore <> 0 then
    try
      if WaitForSingleObject(Semaphore, 0) = WAIT_OBJECT_0 then
      begin
        try
          Application.Initialize;
          Application.MainFormOnTaskbar := True;
          Application.CreateForm(TFormTest, FormTest);
          Application.Run;
        finally
          ReleaseSemaphore(Semaphore, 1, nil);
        end;
      end
      else begin
        ShowMessage('En fazla 2 örnek çalışabilir');
        Exit;
      end;
    finally
      CloseHandle(Semaphore);
    end;
end.
2 örnekten fazla çalıştırmak istersek hata mesajı gösterip kapanır.
Tebrik ederim hakikaten, bu kadar hızlı ve geniş cevaplar verileceğini beklemiyordum. :bravo:

Gördüğünüz gibi ne kadar da kolaymış değil mi ;)
Cevapla