#pragma once // CATIA (V5, CNEXT.exe) calisan instance kesfi — 10+ instance / birden fazla // Virtual Desktop senaryosu icin tasarlandi (bkz. docs/catia_calisma_alani.md). // // ONEMLI: "Sadece tek CATIA.Application bulmaya calisma" gereksinimi - // Running Object Table (ROT) coklu instance'ta genelde YALNIZ SON KAYITLI // (aktif/foreground) instance'i gosterir. Bu yuzden BIRINCIL yontem ROT // DEGIL, AccessibleObjectFromWindow(hwnd, OBJID_NATIVEOM, ...) ile HER // PENCEREYE OZEL COM nesnesini almaktir (Office'te dokumante calisan bir // teknik). // // GERCEK RUNTIME TEST (18 Eylul, gercek CATIA V5): AccessibleObjectFromWindow // 20/20 pencerede hr=0x80004005 (E_FAIL) ile basarisiz oldu (elevation // eslesmesi denendi, degismedi) — CATIA V5'in OBJID_NATIVEOM'u hic // desteklemedigi sonucuna varildi, bu yol COK OLASI bir CIKMAZ. // // BULUNAN IKINCI HATA (ayni oturum): eski ROT capraz-kontrolu // IMoniker::GetDisplayName() cikisinda literal "CATIA.Application" metni // ariyordu — ama RegisterActiveObject ile kaydolan bir EXE sunucusu ROT'a // CLASS MONIKER ile girer, ve bunun GetDisplayName() ciktisi // "clsid:{GUID}:" formatindadir, ProgID metnini ASLA icermez. Yani // "ROT kaydi=0" raporu ROT'un bos oldugunu KANITLAMAZ — yalniz yanlis // deseni aradigimizi gosterir. Duzeltme: rotAktifCatiaBagla() artik // CLSIDFromProgID+CreateClassMoniker+IRunningObjectTable::GetObject ile // (GetObject(,"CATIA.Application")'in VBScript/PowerShell'de yaptigi // AYNI islem) doguru sekilde AKTIF instance'a baglanmayi dener — bu SADECE // o an aktif/foreground olan TEK ornegi verir, coklu-instance kesif // sorununu COZMEZ (ROT'un dogasi geregi), ama "ROT gercekten bos mu" sorusuna // DOGRU cevap verir. #include #include #include namespace fiko { struct CatiaBelgeBilgi { std::string ad; // Documents.Item(i).Name std::string tamYol; // Documents.Item(i).FullName (kayitsiz belgede bos) bool aktifBelge = false; bool kayitliMi = false; // tamYol doluysa true }; struct CatiaOturumBilgi { uint32_t pid = 0; void* hwnd = nullptr; // GECICI eslesme icin; kalici kimlik olarak KULLANMA std::string pencereBasligi; std::string surecYolu; // CNEXT.exe tam yolu (surum ayrimi icin ipucu) bool comEslesmeBasarili = false; // AccessibleObjectFromWindow basarili mi std::vector belgeler; // Pencere geometrisi (Faz 2 geri-yukleme icin) — GetWindowPlacement kaynakli. long x = 0, y = 0, genislik = 0, yukseklik = 0; bool maksimize = false, minimize = false; // Sanal masaustu (bos ise tespit edilemedi; nedeni masaustuDurumu'nda). std::string masaustuGuid; std::string masaustuDurumu; // dogru rapor icin (basarisizsa neden metni) }; struct CatiaKesifSonucu { std::vector oturumlar; int adayPencereSayisi = 0; // surec adi CNEXT.exe olan aday ust pencere sayisi int comEslesenSayisi = 0; // bunlardan COM baglantisi kurulabilenler int rotKayitSayisi = -1; // ESKI capraz kontrol (display-name substring, GUVENILMEZ — bkz. dosya basi not) bool rotAktifCatiaBaglandi = false; // CLSIDFromProgID+CreateClassMoniker+GetObject basarili mi int rotAktifBelgeSayisi = -1; // basariliysa o AKTIF instance'in Documents.Count'u (-1=denenmedi/basarisiz) std::vector uyarilar; // eslesmeyen/eksik durumlar — DURUST rapor }; // Calisan tum CATIA (CNEXT.exe) orneklerini kesfeder. CoInitialize CAGIRANIN // sorumlulugundadir (fiko::ComOturum, sanal_masaustu.hpp) — bu fonksiyon // COM apartment'i ZATEN acik varsayar, kendi baslatmaz/kapatmaz. CatiaKesifSonucu catiaKesifYap(); // Insan-okunur ozet rapor (log/toast/panel ortak kaynagi). std::string catiaKesifRaporu(const CatiaKesifSonucu& s); // ---- Faz 2: yeni başlatılan bir CATIA sürecine belge açtırma ---- // // DÜRÜST NOT: CNEXT.exe'ye dosya yolu komut satırı argümanı olarak vermek // belgeyi YÜKLEMİYOR (deneyle doğrulandı — CATIA boş açılıyordu). Doğru yol: // süreci argümansız başlat, COM arayüzü hazır olana kadar bekle (poll), sonra // Application.Documents.Open(yol) çağır. // PID'i verilen (henüz keşif listesine hiç girmemiş olabilecek, YENİ başlatılmış) // CATIA sürecinin COM Application nesnesini bulmaya çalışır — o PID'e ait // sahipsiz üst pencereleri tarar, her biri için AccessibleObjectFromWindow // dener (catiaKesifYap ile AYNI teknik). Süreç COM'unu henüz hazırlamadıysa // (yeni başladı, hâlâ yükleniyor) nullptr döner — çağıran kısa aralıklarla // TEKRAR DENEMELİDİR (bu fonksiyon kendi içinde beklemez/loop atmaz). // Başarılı dönüşte void* bir IDispatch* taşır — çağıran işi bitince // reinterpret_cast(sonuc)->Release() ETMEKLE YÜKÜMLÜDÜR. // CoInitialize ÇAĞIRANIN sorumluluğundadır (bu fonksiyonu çağıran thread'in // COM apartment'i zaten açık olmalı — arka plan thread'inde çağrılıyorsa o // thread kendi fiko::ComOturum'unu açmalı, ana UI thread'ininkini PAYLAŞAMAZ). void* catiaUygulamasiPidIle(uint32_t pid); // PID'e ait, gorunur+sahipsiz bir ust pencerenin HWND'sini dondurur (yoksa // nullptr). catiaUygulamasiPidIle ile AYNI aday listesini kullanir ama COM // baglanmayi DENEMEZ — yalnizca pencere kimligi ister (ornegin Faz 2'de yeni // acilan CATIA penceresini dogru sanal masaustune TASIMAK icin gereken HWND). // Donen deger gercekte bir HWND'dir (fiko::CatiaOturumBilgi::hwnd ile ayni // sozlesme — void* olarak tasinir, cagiran HWND'ye geri donusturur). void* catiaPencereBulPidIle(uint32_t pid); // uygulamaIDispatch (catiaUygulamasiPidIle'dan) üzerinden // Application.Documents.Open(tamYolUtf8) çağırır. DÜRÜST hata raporu: başarı // yalnız COM Invoke SUCCEEDED olursa true — hataCikis'e gerçek HRESULT/CATIA // istisna mesajı yazılır, sessiz varsayım YOK. bool catiaBelgeAc(void* uygulamaIDispatch, const std::string& tamYolUtf8, std::string& hataCikis); } // namespace fiko