2011-01-24 12 views
11

मैं दृश्य स्टूडियो के साथ काम कर रहा हूँ 2005कर्नेल 32.dll और user32.dll पर केवल निर्भरता के साथ एक सी ++ प्रोग्राम संकलित करें?

मैं एक साधारण प्रोग्राम है कि स्थापित क्या C++ रनटाइम लायब्रेरी संस्करण के किसी भी विंडोज 32bit संस्करण स्वतंत्र के साथ काम करेंगे संकलित करने के लिए चाहते हैं।

यह प्रोग्राम किसी भी अन्य फ़ंक्शन कॉल के बिना GetModuleHandle और GetProcAddress फ़ंक्शन पर कॉल करेगा, और फिर बाहर निकलें, जब निकास कोड फ़ंक्शन पता होता है।

किसी भी C++ रनटाइम लाइब्रेरी के बिना kernel32.dll और user32.dll पर केवल निर्भरता के साथ एक C++ प्रोग्राम को संकलित करने के लिए कैसे करें?

+1

+1 यह एक अच्छा SO प्रश्न का प्रतीक है। –

+0

यदि मैं पूछूं तो इस कार्यक्रम का उद्देश्य क्या है? –

+0

मैं 64 बिट प्रक्रिया से 32 बिट प्रक्रिया में कोड इंजेक्शन लागू कर रहा हूं, और मुझे कुछ कार्यों के पते को खोजने के लिए सहायक 32 बिट प्रोग्राम की आवश्यकता है। – DxCK

उत्तर

5

अपने प्रोजेक्ट विकल्पों के तहत /NODEFAULTLIB सेट करें। विजुअल सी ++ के नए संस्करणों में, आपको स्टैक ओवररन चेक को भी बंद करना होगा, क्योंकि वे संकलक लाइब्रेरी फ़ंक्शंस में स्वचालित रूप से कॉल डालने का कारण बनते हैं।

संपादित करें: यदि आप वास्तव में "किसी भी 32-बिट विंडोज संस्करण पर चलते हैं" का अर्थ है, तो आपको पीई हेडर में उपप्रणाली संस्करण फ़ील्ड को बदलने के लिए editbin का उपयोग करना होगा। अन्यथा आप (आईआईआरसी) विंडोज 2000 तक सीमित हैं और बाद में जब वीसी ++ 2005 लिंकर के साथ निर्माण करते हैं, और वीसी ++ के नए संस्करण भी बदतर होते हैं (डिफ़ॉल्ट रूप से एक्सपी की आवश्यकता होती है)। विंडोज 2000 5.0 है, आप Win9x के अतिरिक्त NT के सभी संस्करणों को अनुमति देने के लिए 3.5 या वहां निर्दिष्ट करना चाहते हैं।

+1

जबकि आप '/ nodefaultlib' निर्दिष्ट करना चाहते हैं, लेकिन स्वयं ही यह आपको 'अनसुलझा बाहरी' त्रुटियां देगा। वास्तविक कुंजी पुस्तकालय पर निर्भरताओं को खत्म करने के लिए अपने स्वयं के प्रवेश बिंदु का उपयोग कर रही है। –

+0

@ जेरी: मुझे लगता है कि लिंकर जो भी डिफ़ॉल्ट रूप से दिखता है उसके अनुसार आप अपना एंट्री पॉइंट नाम दे सकते हैं ('wCRTWinMain' या इसी तरह), लेकिन मैं मानता हूं कि '/ entry' का उपयोग क्लीनर है। –

+0

मैंने कभी कोशिश नहीं की है, इसलिए मुझे लगता है कि यह काम कर सकता है, लेकिन निश्चित रूप से यह नहीं कह सकता है (परीक्षण के बिना, यह कहना मुश्किल है कि लिंकर किस जादू का उपयोग/आक्रमण/निर्भर हो सकता है)। भले ही आप यह निर्दिष्ट करने के लिए '/ entry: 'का उपयोग करें कि यह क्या है, फिर भी, आपको एंट्री पॉइंट को वैसे भी परिभाषित करना होगा। –

5

आपको main या WinMain का उपयोग करने के बजाय अपना स्वयं का प्रवेश बिंदु परिभाषित करने की आवश्यकता होगी। आपका प्रवेश बिंदु एक शून्य कार्य नहीं है जिसमें कोई तर्क नहीं है। आपको /entry:funcName के साथ लिंकर को अपना नाम निर्दिष्ट करना होगा (जहां funcName आपके द्वारा दिए गए फ़ंक्शन को जो भी नाम दिया गया है, उसे प्रविष्टि बिंदु के रूप में उपयोग करना है)।

जब आप ऐसा करते हैं तो आपको लिंकर को सबसिस्टम निर्दिष्ट करना होगा, जैसा कि /subsystem:console में है। यह आमतौर पर उस कार्य के नाम के आधार पर उपप्रणाली को घटाता है (यानी, main -> कंसोल, WinMain -> विंडोज़), लेकिन जब आप अपने स्वयं के प्रवेश बिंदु का उपयोग करते हैं, तो आपको इसे स्पष्ट रूप से निर्दिष्ट करना होगा। यद्यपि आप शायद अक्सर नहीं चाहते हैं, आप उप-सिस्टम को स्पष्ट रूप से निर्दिष्ट कर सकते हैं जब भी आप अपना स्वयं का एंट्री पॉइंट निर्दिष्ट नहीं करते हैं, इसलिए (उदाहरण के लिए) आप main का उपयोग विंडोज सबसिस्टम प्रोग्राम के प्रवेश बिंदु के रूप में कर सकते हैं, या WinMain एक कंसोल कार्यक्रम के प्रवेश बिंदु के रूप में।

+1

इसके अलावा, प्रवेश बिंदु को 'APIENTRY' (== '__stdcall') घोषित किया जाना चाहिए, और आपको इसे वापस करने के बजाय' ExitProcess()' का उपयोग करने की आवश्यकता है। –

+0

@ ब्रायन: एमएसडीएन रिटर्न वैल्यू के बारे में क्या नहीं कहता है --http: //msdn.microsoft.com/en-us/library/f9t8842e (v = VS.80) .aspx –

+1

@ ब्रायन: इससे लौटने से ठीक काम करता है । मैं आमतौर पर इसे 'APIENTRY' या '__stdcall' के साथ घोषित नहीं करता - मैं बस'/Gz' के साथ संकलित करता हूं। ओटीओएच, जो आप सलाह दे रहे हैं वह शायद * बेहतर * है, भले ही यह वास्तव में आवश्यक न हो। –

0

छोटे सी libs की जांच करें। स्थिर रूप से लिंक भी।

+0

तकनीकी रूप से यह एक उत्तर है क्योंकि वह एक सुझाव दे रहा है कि डीएक्सकेसी को अपनी परियोजना शुरू करने/समाप्त करने की आवश्यकता हो सकती है। हालांकि यह मांसपेशियों के साथ कर सकता है। –

1

मुझे यकीन नहीं है कि हर कोई मानक पुस्तकालय का उपयोग करने के खिलाफ क्यों सलाह दे रहा है। यह विधि मानती है कि आप चाहते हैं कि आपका कोड विंडोज 2000 या बाद में चलाना पड़े और Win 9x के लिए समर्थन खोने में कोई फर्क नहीं पड़ता। आप अभी भी सी/सी ++ मानक लाइब्रेरी का उपयोग कर सकते हैं - आप अपने प्रोजेक्ट के सी/सी ++ कोड जेनरेशन पेजों में /MT विकल्प का उपयोग कर सकते हैं, जो मानक लाइब्रेरी में स्थिर रूप से लिंक होगा।

हालांकि, दो नोट्स, मेरे पहले से पहले: गतिशील रूप से जुड़ी मानक लाइब्रेरी रखने का विचार यह है कि इसमें कोई भी बग विंडोज अपडेट (सिद्धांत रूप में) द्वारा पैच किया जाएगा। यदि आप लाइब्रेरी को स्थिर रूप से लिंक करते हैं, तो आपको मानक लाइब्रेरी बग को ठीक करने के लिए अपने एप्लिकेशन को फिर से वितरित करने की आवश्यकता है। तो यह सलाह नहीं दी जाती है।

दूसरे, MSDN लेख से compiler options पर:

सावधानी स्थिर मिश्रण और रन-टाइम पुस्तकालयों के गतिशील संस्करणों न करें। प्रक्रिया में रन-टाइम लाइब्रेरीज़ की एक से अधिक प्रति समस्याएं पैदा कर सकती हैं, क्योंकि एक प्रतिलिपि में स्थिर डेटा अन्य प्रतिलिपि के साथ साझा नहीं किया जाता है। लिंकर को एक स्थिर और गतिशील संस्करणों को एक .exe फ़ाइल, के साथ जोड़ने से रोकता है लेकिन आप अभी भी रन-टाइम लाइब्रेरीज़ की दो (या और) प्रतियों के साथ समाप्त हो सकते हैं। उदाहरण के लिए, रन-टाइम लाइब्रेरी के स्थिर (गैर-डीएलएल) संस्करणों से जुड़े एक गतिशील-लिंकलाइब्रेरी का उपयोग एक .exe फ़ाइल के साथ किया गया था जो डायनामिक (डीएलएल) संस्करण के साथ जुड़ा हुआ था। रन-टाइम पुस्तकालय। (आप भी से बचने के एक प्रक्रिया में डिबग और गैर डिबग पुस्तकालयों के संस्करणों मिश्रण चाहिए।)

संक्षेप में, ऐसा करने से भ्रम की स्थिति पैदा करता है, तो आप अन्य एक गतिशील के खिलाफ जुड़ा हुआ घटकों में निर्माण करने के लिए कोशिश कर सकते हैं -लिंक मानक पुस्तकालय।

बेशक, दूसरा नकारात्मक यह है कि यह आपके निष्पादन योग्य को भी बड़ा कर देगा।

संपादित करें: परिणाम, depend.exe के तहत, ऐसा लगता है: (बेशक, मैं 64-बिट विंडोज का उपयोग कर रहा हूं, जो केवल एक्सपी के लिए उपलब्ध है और बाद में ... यदि आप जानना चाहते हैं कि यह क्या दिखता है 32-बिट विंडोज़ की तरह, कल्पना करें कि 64 एस वहां नहीं थे!)।

depends.exe program showing only one dynamic dependency, kernel32.dll

+0

"मुझे यकीन नहीं है कि हर कोई मानक पुस्तकालय का उपयोग करने के खिलाफ क्यों सलाह दे रहा है।" हाँ, यह वही था जो मैं सोच रहा था। +1। – wj32

+0

मुझे खुशी है कि यह सिर्फ मुझे नहीं था। मैंने यह सुनिश्चित करने के लिए 'depend.exe' प्रोफाइलर का उपयोग करके इसे भी प्रयोग किया है कि मानक libs को गतिशील रूप से नहीं कहा जा रहा है। शायद ज़रुरत पड़े। –

+0

शायद क्योंकि मानक पुस्तकालय विंडोज के किसी विशेष संस्करण में पेश किए गए कार्यों पर निर्भर करता है, जो प्रश्न की आवश्यकताओं के विपरीत है। और सवाल यह भी कहा कि "बिना किसी सी ++ रनटाइम लाइब्रेरी के"। –

0

आप वास्तव में User32.dll या तो ज़रूरत नहीं है, केवल लोगों को आप वास्तव में नहीं निकाल सकते Kernel32.dll और Ntdll.dll कर रहे हैं - उन PsCreateProcess करके अपने प्रक्रिया अंतरिक्ष में इंजेक्ट किया जाता है (यानी गिरी आधा कर्नेल कैसे एक नई प्रक्रिया बनाता है)।

+0

नहीं, कर्नेल 32 को "PsCreateProcess" द्वारा मैप नहीं किया गया है, जिस तरह से मौजूद नहीं है। कर्नेल 32 को उपयोगकर्ता-मोड में, ntdll में LdrpInitializeProcess द्वारा लोड किया जाता है। एकमात्र डीएलएल जिसे आप हटा नहीं सकते हैं वह है। – wj32

+0

शायद यह PspCreateProcess होना चाहिए, यही कारण है कि यह "अस्तित्व में नहीं है"। ओह अच्छा। –

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