2009-10-28 19 views
7

[इस TLDR हो रही है ... खेद ...]निर्धारण जब नेट के बारे में में लोड किया जा रहा है (अप्रबंधित) सी ++

मैं DLLs के सैकड़ों के साथ एक विशाल (अधिकतर) सी ++/MFC आवेदन पर काम ; यह COM के माध्यम से एक गतिशील रूप से लोड "एड इन" तंत्र का समर्थन करता है, इस प्रकार COM इंटरऑप का उपयोग करके .NET में एड-इन्स विकसित किया जा सकता है। इस "ऐड-इन" तंत्र का उपयोग करते हुए .NET w/o में कुछ सीमित नई कार्यक्षमता विकसित की गई है (हालांकि अभी भी गतिशील रूप से लोड हो चुकी है); हालांकि, अंतिम उपयोगकर्ता इस सुविधा का उपयोग न करने का निर्णय ले सकता है। इस प्रकार, .NET स्टार्टअप पर लोड नहीं किया जा सकता है।

लेकिन, जब नेट भरी हुई, मैं कुछ नेट विशेष initialzation क्या करने की जरूरत है (विशेष रूप से देशी/अप्रबंधित यूआई मैच के लिए CurrentUICulture की स्थापना)।

एक समाधान केवल पंट करना और ऐसा करना है .NET प्रारंभिकता जब कोड नए .NET functionaliy या COM एड-इन्स को लोड करने के लिए हो जाता है। इस आवेदक की प्रकृति को देखते हुए, यह शायद 95 +% समाधान है (अधिकतर उपयोगकर्ता नई कार्यक्षमता का उपयोग करेंगे)।

लेकिन यह मूर्खतापूर्ण नहीं है। कोई भी /clr ध्वज (याद रखें, यह एक बड़ा एप्लीकेशन है) के साथ मॉड्यूल बनाने के द्वारा किसी भी समय नई .NET कार्यक्षमता को "आसानी से" जोड़ सकता है।

एक और मजबूत (और स्पष्ट) समाधान केवल सीई ++/सीएलआई के माध्यम से स्टार्टअप पर लोड होने के लिए .NET का कारण बनता है। लेकिन कुछ मरने वाले सी ++ डेवलपर जिनके लिए प्रत्येक बाइट और घड़ी चक्र पदार्थ ऐसा नहीं करना चाहते हैं; कुछ हद तक समझ में आता है क्योंकि CurrentUICulture सेट करने की आवश्यकता नहीं है जब तक कि .NET लोड नहीं हो जाता है।

एक और संभावना मैंने सोचा कि LoadLibrary को हुक करना और mscorlib देखें। अब मुझे पता है कि .NET किसी कारण से लोड होने वाला है, इसे सामान्य तरीके से लोड करें और दूसरे कोड से पहले प्रारंभ करने से पहले प्रारंभ करें। लेकिन LoadLibrary (या उस मामले के लिए कुछ भी) हुकिंग वास्तव में ऐसा कुछ नहीं है जिसे मैं करना चाहता हूं।

तो, क्या .NET लोड होने के बारे में बताने के लिए कोई आसान (ier)/बेहतर तरीका है?

संपादित करें: LockClrVersion की रीड का जवाब बहुत रफ़ू करीब है। एकमात्र हिचकी यह है कि यदि आप मिश्रित-मोड DLL/असेंबली में लिंक करते हैं तो यह काम नहीं करेगा।

// ClrAboutToLoad.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 

#include <MSCorEE.h> 

// http://community.bartdesmet.net/blogs/bart/archive/2005/07/22/2882.aspx 
FLockClrVersionCallback begin_init, end_init; 
STDAPI hostCallback() 
{ 
    printf("hostCallback()\n"); 

    // we're in control; notify the shim to grant us the exclusive initialization right 
    begin_init(); 

    ICLRRuntimeHost *pHost = NULL; 
    HRESULT hr = CorBindToRuntimeEx(NULL, L"wks", STARTUP_SERVER_GC, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (PVOID*) &pHost); 
    hr = pHost->Start(); 

    // mission completed; tell the shim we're ready 
    end_init(); 

    return S_OK; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    LockClrVersion(&hostCallback, &begin_init, &end_init); 

    //fnTheDLL(); 
    HMODULE hModule = LoadLibrary(L"TheDLL"); 
    FARPROC fp = GetProcAddress(hModule, "fnTheDLL"); 
    typedef void (*fnTheDLL_t)(); 
    fnTheDLL_t fnTheDLL = reinterpret_cast<fnTheDLL_t>(fp); 
    fnTheDLL(); 
    FreeLibrary(hModule); 

    return 0; 
} 

उत्तर

6

मुझे विश्वास है कि आप किसी भी प्रबंधित एपीआई का उपयोग करने से पहले अपनी प्रक्रिया को अप्रबंधित LockClrVersion फ़ंक्शन कॉल करके ऐसा कर सकते हैं। यह फ़ंक्शन आपको दो FLockClrVersion callback विधियों को निर्दिष्ट करने की अनुमति देता है।

पहली विधि (pBeginHostSetup), जिसे होस्टिंग प्रक्रिया के लिए पहली बार सीएलआर शुरू किया जा रहा है। दूसरी विधि (pEndHostSetup) को कॉल किया जाता है जब सीएलआर का प्रारंभ पूरा हो जाता है।

यह आपको अप्रबंधित कोड निर्दिष्ट करने की अनुमति दे सकता है जो पहले ही चल रहा है और सीएलआर प्रारंभिकरण के बाद ही। आपके मामले में, आपको शायद अपने प्रबंधित API सेटअप दिनचर्या को कॉल करने के लिए pEndHostSetup में हुक करने की आवश्यकता है (आपको सीएलआर सफलतापूर्वक होस्ट होने तक प्रतीक्षा करने की आवश्यकता होगी)।

+0

यह आशाजनक लग रहा है! –

+0

यह ठीक वही करना चाहिए जो आप बाद में कर रहे हैं - मैंने इसे कभी भी लागू नहीं किया है, लेकिन मैं इसे ट्रैक करने की कोशिश कर रहे पूरे सीएलआर होस्टिंग एपीआई के माध्यम से चला गया। –

+0

यह लगभग सही है; एकमात्र हिचकिचाहट यह है कि आपको यह सुनिश्चित करने की ज़रूरत है कि कॉल करने से पहले सीएलआर लोड होने के कारण कुछ भी नहीं हो * LockClrVersion *। "समस्या" यह है कि मिश्रित मोड असेंबली में लिंकिंग सीएलआर लोड करती है, आपको गतिशील रूप से असेंबली लोड करना होगा। –

-1

आपको शायद एप्लिकेशन स्टार्टअप पर .NET ढांचे को प्रारंभ करना चाहिए। मैंने ऐप पर एक समान पृष्ठभूमि के साथ काम किया और यह कभी-कभी डेडलॉक होता क्योंकि 2 डीएल अप्रत्यक्ष रूप से .NET dlls तक पहुंचकर सैमटाइम पर .net ढांचे को शुरू करने की कोशिश कर रहे थे। इसे ठीक करने के लिए हमने निष्पादन योग्य के प्रवेश बिंदु की पहली कुछ पंक्तियों में CorBindToRuntimeEx पर कॉल किया।

मुझे नहीं लगता कि ओएस आपको लोड करने वाला है, तो ओएस आपको बताएगा कि एक तरीका है।

+0

मुझसे कोई तर्क नहीं; लेकिन बाइट काउंटरों को .NET प्रारंभ करने का कोई मतलब नहीं दिखता है, यदि इसका उपयोग नहीं किया जा रहा है। याद रखें, यह एक (बहुत) बड़ी परियोजना है; राजनीतिक लोगों के साथ काम करने के लिए केवल इंजीनियरिंग मुद्दे ही नहीं हैं। –

1

आप run your own CLR host to load assemblies कर सकते हैं। फिर आप लोड करने के लिए रनटाइम (1.1? 2.0? 4.0?) के किस संस्करण के बारे में अधिक विशिष्ट निर्णय ले सकते हैं, और when a plugin crash, your code won't go down with it पर अपने कोड से प्रबंधित कोड अलग कर सकते हैं।

+0

मैंने इसके बारे में सोचा था ... लेकिन बाइट काउंटर बिल्कुल शुरू करने के लिए .NET को गले लगा रहे हैं। COM इंटरऑप के लिए धन्यवाद, वे (ज्यादातर) आनंद से अनजान रह सकते हैं कि .NET भी मौजूद है (मैंने जो .NET में लिखा है "नई कार्यक्षमता" उन पर मजबूर थी)। –

1

ऐसी दो चीजें हैं जो आपकी मदद कर सकती हैं: प्रदर्शन काउंटर और डब्लूएमआई। .NET CLR दोनों के साथ एकीकृत करता है, और आप AppDomain स्टार्टअप के लिए देखने के लिए या तो (WMI शायद सबसे अच्छा होगा) के साथ बातचीत करने में सक्षम होना चाहिए।हालांकि, इन उपकरणों में से कोई भी विशेष रूप से आदर्श नहीं है, और ओवरहेड के मामले में, जो शेंग जियांग ने स्वयं को सीएलआर की मेजबानी की, वह संभवतः अधिक कुशल (और इस प्रकार आपके "बाइट काउंटर" के लिए अधिक प्रसन्न होगा।)

थोड़ा अलग नोट पर ... यदि आपके पास विकास टीम पर कोई प्रभाव और नियंत्रण है, तो मैं "बाइट काउंटर" में थोड़ा सा शासन करूंगा। .NET के बारे में सबसे बड़ी गलत धारणाओं में से एक यह है कि यह सी ++ से कम कुशल है। उस पुराने फसल को दफनाया जाना चाहिए, क्योंकि .NET आश्चर्यजनक रूप से कुशल हो सकता है, और जब इसे सही ढंग से उपयोग किया जाता है, तो कभी-कभी सी ++ से अधिक कुशल होता है। किसी भी मंच की आधारभूत दक्षता से परे, आपको सवाल पूछना होगा: बेहतरीन अनाज को अनुकूलित करने के घंटों के अज्ञात मात्रा खर्च करके मुझे वास्तव में कितनी दक्षता मिल जाएगी, जब सांख्यिकीय रूप से, इसकी बड़ी स्केल चीजें जो आम तौर पर प्रदर्शन को मारती हैं: क्रॉस-प्रोसेस कॉल (यानी सी ++ बनाम COM से कॉलिंग COM ऑब्जेक्ट्स को कॉल करना, .NET से .NET ऑब्जेक्ट्स को कॉल करना), दूरस्थ प्रक्रियाओं (यानी वेब सेवाएं, आरपीसी इत्यादि) का आह्वान करना, डेटाबेस में कॉल करना आदि।

आप अपने .NET को हल करने का प्रयास कर सकते हैं बाइट-काउंटर गलत धारणाओं को खुश करने के लिए AppDomain स्टार्टअप समस्या, या आप एक .NET सिस्टम को ठीक से कार्यान्वित कर सकते हैं, और मार्शलिंग और इंटर-ऑप हिट से बचने के लिए बाइट-स्तरीय प्रदर्शन ट्यूनिंग की किसी भी मात्रा की तुलना में बड़े पैमाने पर अधिक निकासी जा रही है।

+0

मुझसे कोई तर्क नहीं; लेकिन पुरानी गलत धारणाएं मर जाती हैं। –

+0

हे, बहुत सच है। दुखद, लेकिन निश्चित रूप से सच है। – jrista

0

असेंबली लोड होने पर हुक करने की कोशिश करने के बजाय, क्या आप ऐपडोमेन लोड होने पर हुक कर सकते हैं? ऐसा करने के लिए System.AppDomainManager में देखें।

आपके उप-वर्गीकृत सिस्टम को लोड करने के बाद। GAC में AppDomainManager, आपको अपने C++ प्रोग्राम को चलाने से पहले कुछ पर्यावरण चर (APPDOMAIN_MANAGER_TYPE, APPDOMAIN_MANAGER_ASM) सेट करना होगा।

+0

मैं जानना चाहता हूं कि .NET (सीएलआर) लोड होने वाला है, न कि असेंबली या ऐपडोमेन। दूसरे शब्दों में, मैं जानना चाहता हूं कि मेरी अप्रबंधित (ठीक, मिश्रित) प्रक्रिया पहली बार प्रबंधित कोड चलाने के लिए तैयार है। –

संबंधित मुद्दे