Yorumları: 1.460
Konuları: 80
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 11.868 Üstad
Şu adreste bazı şeyler yazıyor. Benim iki üstteki mesajımda belirttiğim gibi durumun SendMessage API'si ile ilgili olduğu hususunda.
Alıntı:See the beginning of chapter 13 in the OLE 2 Programmer's Reference Volume 1 for the categories of OLE calls. An understanding of these categories is required for this article.
The majority of OLE calls are synchronous calls. A synchronous call to a different process yields to that process and waits for a reply from that process. In addition, OLE has input-synchronized calls that relate to the inplace-activation interfaces. Input-synchronized calls are implemented using an inter-process/inter-thread SendMessage.
Bu bir senkron çağrı olduğu için, mesajı gönderen bloke olmuş durumda ve muhtemelen bilgisini verdiği device'ı da lock'lamış durumdadır. OnArrival olayının bir başka thread içinden çağrılıp işin yine ana thread'e devredilmesi sayesinde, mesajı gönderen gönderdiği mesajın yanıtını hızla almış ve device ile ilgili işleri de tamamlamış olur.
Denemedim ama okuduklarımdan anladığım kadarı ile gelen mesajın içinde COM objelerini kullanıyor olmak hataya neden olmuyor. Hataya neden olan, gelen mesajın senkron olması ve hızlıca gönderene dönemiyor olması. Daha gelen mesaj sonuçlanmamış iken, mesajın konusu olan device ile ilgili bir iş yapılmaya çalışılması bu problemin nedeni gibi görünüyor.
Yine denemedim ama, muhtemelen; bir uygulama WM_DEVICECHANGE olay yöneticisi içinde uzun bir bekleme kodu koysa; bir başka uygulama üzerinden de WMI ile ya da başka bir şekilde o cihaza ulaşılmaya kalkılsa aynı hata yeniden alınır gibi geliyor bana.
Tabii çok büyük ihtimalle, mesajı gönderen taraf (yani işletim sistemi) aptal olmadığı için , muhtemelen mesajı SendMessage ile değil; SendMessageTimeOut ile göndermiştir.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
Yorumları: 149
Konuları: 48
Kayıt Tarihi: 24-10-2017
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 85 Başlangıç
Hocam yolun daha çok başındayım.25 yaşındayım.Öğreneceğim tonla bilgi var, bunun farkındayım. Genellikle sizler sayesinde çok fazla ilerleme kaydettim.Hepinize çok teşekkür ederim.
Yorumları: 1.460
Konuları: 80
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 11.868 Üstad
(20-02-2019, Saat: 12:05)seci20 Adlı Kullanıcıdan Alıntı: Hocam yolun daha çok başındayım.25 yaşındayım.Öğreneceğim tonla bilgi var, bunun farkındayım. Genellikle sizler sayesinde çok fazla ilerleme kaydettim.Hepinize çok teşekkür ederim.
Kendi adıma rica ederim. Öğrenmek isteyene kapımız açık. Siz yeterki, merakınızı, ilginizi, sabrınızı kaybetmeyin. Gerisi zamanla kendiliğinden gelecektir. Ama öğrenmek için fırsatları kaçırmamak gerekir. Misal, bu konu başlığı altında belirtilen SendMessage, SendMessageTimeOut, senkron mesaj gönderme, asenkron mesaj gönderme gibi konuları merak edip denemelisiniz. Bu merak sizde mevcut ise kimse ilerlemenize engel olamaz.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
Yorumları: 1.571
Konuları: 88
Kayıt Tarihi: 09-08-2016
Rep Puanı: 13.829 Üstad
(20-02-2019, Saat: 12:02)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: Şu adreste bazı şeyler yazıyor. Benim iki üstteki mesajımda belirttiğim gibi durumun SendMessage API'si ile ilgili olduğu hususunda.
Alıntı:See the beginning of chapter 13 in the OLE 2 Programmer's Reference Volume 1 for the categories of OLE calls. An understanding of these categories is required for this article.
The majority of OLE calls are synchronous calls. A synchronous call to a different process yields to that process and waits for a reply from that process. In addition, OLE has input-synchronized calls that relate to the inplace-activation interfaces. Input-synchronized calls are implemented using an inter-process/inter-thread SendMessage.
Bu bir senkron çağrı olduğu için, mesajı gönderen bloke olmuş durumda ve muhtemelen bilgisini verdiği device'ı da lock'lamış durumdadır. OnArrival olayının bir başka thread içinden çağrılıp işin yine ana thread'e devredilmesi sayesinde, mesajı gönderen gönderdiği mesajın yanıtını hızla almış ve device ile ilgili işleri de tamamlamış olur.
Denemedim ama okuduklarımdan anladığım kadarı ile gelen mesajın içinde COM objelerini kullanıyor olmak hataya neden olmuyor. Hataya neden olan, gelen mesajın senkron olması ve hızlıca gönderene dönemiyor olması. Daha gelen mesaj sonuçlanmamış iken, mesajın konusu olan device ile ilgili bir iş yapılmaya çalışılması bu problemin nedeni gibi görünüyor.
Yine denemedim ama, muhtemelen; bir uygulama WM_DEVICECHANGE olay yöneticisi içinde uzun bir bekleme kodu koysa; bir başka uygulama üzerinden de WMI ile ya da başka bir şekilde o cihaza ulaşılmaya kalkılsa aynı hata yeniden alınır gibi geliyor bana.
Tabii çok büyük ihtimalle, mesajı gönderen taraf (yani işletim sistemi) aptal olmadığı için , muhtemelen mesajı SendMessage ile değil; SendMessageTimeOut ile göndermiştir.
Örnek olarak şöyle bir şey yaptım:
Usb takıldığında tetiklenen OnArrival olayına şunları yazdım;
procedure TfrmDummy.USBDetector1Arrival(Sender: TObject; Drive: String);
begin
CoInitialize(nil);
try
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
finally
CoUninitialize;
end;
end
Aynı hatayı aldım.
Yukarıdaki durumda USB ile yeniden iletişim kurma vs. yok.
Ayrıca olay içine sadece 30 sn bekletme koysam bir sorun olmuyor. (işletim sistemi yazanlar Tuğrul Bey kadar düşünceli değiller galiba )
There's no place like 127.0.0.1
Yorumları: 1.460
Konuları: 80
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 11.868 Üstad
(20-02-2019, Saat: 14:04)SimaWB Adlı Kullanıcıdan Alıntı: (20-02-2019, Saat: 12:02)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: Şu adreste bazı şeyler yazıyor. Benim iki üstteki mesajımda belirttiğim gibi durumun SendMessage API'si ile ilgili olduğu hususunda.
Bu bir senkron çağrı olduğu için, mesajı gönderen bloke olmuş durumda ve muhtemelen bilgisini verdiği device'ı da lock'lamış durumdadır. OnArrival olayının bir başka thread içinden çağrılıp işin yine ana thread'e devredilmesi sayesinde, mesajı gönderen gönderdiği mesajın yanıtını hızla almış ve device ile ilgili işleri de tamamlamış olur.
Denemedim ama okuduklarımdan anladığım kadarı ile gelen mesajın içinde COM objelerini kullanıyor olmak hataya neden olmuyor. Hataya neden olan, gelen mesajın senkron olması ve hızlıca gönderene dönemiyor olması. Daha gelen mesaj sonuçlanmamış iken, mesajın konusu olan device ile ilgili bir iş yapılmaya çalışılması bu problemin nedeni gibi görünüyor.
Yine denemedim ama, muhtemelen; bir uygulama WM_DEVICECHANGE olay yöneticisi içinde uzun bir bekleme kodu koysa; bir başka uygulama üzerinden de WMI ile ya da başka bir şekilde o cihaza ulaşılmaya kalkılsa aynı hata yeniden alınır gibi geliyor bana.
Tabii çok büyük ihtimalle, mesajı gönderen taraf (yani işletim sistemi) aptal olmadığı için , muhtemelen mesajı SendMessage ile değil; SendMessageTimeOut ile göndermiştir.
Örnek olarak şöyle bir şey yaptım:
Usb takıldığında tetiklenen OnArrival olayına şunları yazdım;
procedure TfrmDummy.USBDetector1Arrival(Sender: TObject; Drive: String);
begin
CoInitialize(nil);
try
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
finally
CoUninitialize;
end;
end
Aynı hatayı aldım.
Yukarıdaki durumda USB ile yeniden iletişim kurma vs. yok.
Ayrıca olay içine sadece 30 sn bekletme koysam bir sorun olmuyor. (işletim sistemi yazanlar Tuğrul Bey kadar düşünceli değiller galiba )
Denediğiniz ve bizimle paylaştığınız için teşekkürler. Sadece CoInitialize/CoUnInitialize kullanımı da aynı hataya neden oluyor mu ? Bir de denemişken, CoInitialize'yi COINIT_MULTITHREADED parametresi ile dener misiniz ? Ayrıca, Sleep(30000) koyduktan sonra, bilgisi verilen cihaza bir başka uygulama üzerinden erişim sağlayabiliyor musunuz ?
İşletim sistemi yazanlar benden kat be kat bilgilidirler elbette. Benimki okuduklarımdan elde etmiş olduğum çıkarımlardı sadece.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
Yorumları: 1.571
Konuları: 88
Kayıt Tarihi: 09-08-2016
Rep Puanı: 13.829 Üstad
- Sadece CoInitialize/CoUnInitialize kullandığımda sorun yok.
- Sleep esnasında Usb Flash Diskte dosya oluşturup silebiliyorum.
- COINIT_MULTITHREADED ile değişen bir şey olmadı.
There's no place like 127.0.0.1
Yorumları: 1.460
Konuları: 80
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 11.868 Üstad
(20-02-2019, Saat: 16:18)SimaWB Adlı Kullanıcıdan Alıntı:
- Sadece CoInitialize/CoUnInitialize kullandığımda sorun yok.
- Sleep esnasında Usb Flash Diskte dosya oluşturup silebiliyorum.
- COINIT_MULTITHREADED ile değişen bir şey olmadı.
Teşekkür ederim, testler ve paylaşım için. Buradan benim anladığım; hatanın CoInitialize/CoUnInitialize çağrımından değil, WMI erişiminden kaynaklandığı söylenebilir. Sleep esnasında aslında Windows altından değil, bir başka uygulamadan yine WMI ile o cihazı sorgulayabiliyor musunuz diye sormaya çalışmıştım.
Tekrar sağolun.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
Yorumları: 1.660
Konuları: 20
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 18.981 Üstad
20-02-2019, Saat: 18:33
(Son Düzenleme: 20-02-2019, Saat: 19:16, Düzenleyen: mrmarman.)
Ben şimdi eve geldim ve merakımdan kolları sıvadım. Gelen mesajı yeniden mesaj sırasına atıp oradan dönünce bekleme zamanındaki değişkenliği bertaraf etmiş olduk.
Minareden at beni, in aşağıya tut beni bir çözüm oldu.
Denemek bedava...
type
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
private
const
WM_BenimMesaj = WM_USER + 401;
procedure OnBenimUSBMessage(var Msg: TMessage); message WM_BenimMesaj;
procedure FUSBDetectorOnArrival(Sender: TObject; Drive: String);
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses USBDetect, ActiveX, ComObj;
Var
FUSBDetector : TUSBDetector;
procedure TForm1.FormCreate(Sender: TObject);
begin
FUSBDetector := TUSBDetector.Create(nil);
FUSBDetector.OnArrival := FUSBDetectorOnArrival;
end;
procedure TForm1.FUSBDetectorOnArrival(Sender: TObject; Drive: String);
begin
// Minareden at beni, in aşağıya tut beni.
PostMessage(self.Handle, WM_BenimMesaj, 0, 0); // Topu Taca Atıyoruz...
end;
procedure TForm1.OnBenimUSBMessage(var Msg: TMessage);
Const
WbemComputer = 'localhost';
WbemUser = '';
WbemPassword = '';
Var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
begin
CoInitialize(nil);
try
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
finally
CoUninitialize;
end;
ShowMessage( 'USB Takıldı...');
end;
ya da sizin kodlara göre değerlendirmek istediğinizde...
procedure TForm1.OnBenimUSBMessage(var Msg: TMessage);
var
Y : string;
begin
Y := GetWMIstring('','Win32_DiskDrive','SerialNumber');
ShowMessage( 'USB Takıldı... S/N :' + Y );
end;
Saygılarımla
Muharrem ARMAN
|