كيفية اكتشاف ما إذا كان الكود يعمل برمجيًا في DLL مشترك أو exe؟

StackOverflow https://stackoverflow.com/questions/1633490

سؤال

يحتوي A على فئة C# مما يبسط التعامل مع مفاتيح التشغيل السريع العامة.تستخدم هذه الفئة الدالة Win32-API RegisterHotKey() لتسجيل المفاتيح الساخنة.

وفقًا لـ MSDN ، تحتاج هذه الوظيفة إلى قيمة معرف في النطاق 0x0000 إلى 0xBFFF عند الاتصال من تطبيق وقيمة معرّف في نطاق 0xC000 إلى 0xFFFF عند الاتصال من DLL المشترك. GlobalAddAtom() يمكن استخدامها للحصول على الهوية في حالة التشغيل في DLL.

لإخفاء هذا التمييز عن مستخدم الفئة ، يجب أن تقرر الفئة نفسها أي يتم استخدام نطاق المعرف عند تسجيل مفتاح التشغيل السريع.حسنا ، وللقيام بذلك ، يجب على الفصل تكون قادرة على اكتشاف ما إذا كان الرمز الخاص به يعمل داخل تطبيق أو داخل DLL مشترك.

لكن كيف افعل ذلك؟ما هي أفضل طريقة C#/.NET للقيام بذلك؟

هل كانت مفيدة؟

المحلول

وجرب هذا:

bool isDll = this.GetType().Assembly.EntryPoint == null;

وMSDN:

Assembly.EntryPoint الملكية

<اقتباس فقرة>   

و"كائن خاصية القيمة A MethodInfo   الذي يمثل نقطة دخول   هذه الجمعية. إذا لم يكن هناك نقطة الإدخال   وجدت (على سبيل المثال، هو التجميع على   DLL)، في اشارة فارغة (لا شيء في   البصري الأساسية) يتم إرجاعها. "

نصائح أخرى

إنه لك فصل - أنت تعرف حيث كنت وضعه.

إذا كنت لا تشاركه، فما عليك سوى اختيار معرف أقل من 0xBFFF والانتهاء منه.

إذا كان فصلك ينتمي إلى ملف DLL يمكن مشاركته بواسطة تطبيقات متعددة...أو يمكن ببساطة مشاركتها عن طريق رمز لا يمكنك التحكم فيه وبالتالي لا يمكنك فرز المعرفات الخاصة بـ...ثم استخدام GlobalAddAtom() للحصول على بطاقة هوية (وتذكر الاتصال GlobalDeleteAtom() بعدك قم بإلغاء تسجيل مفتاح التشغيل السريع).


توضيح

ربما يستحق الأمر دقيقة للتفكير في سبب وجود نطاقين مختلفين للمعرفات، ولماذا توصي مستندات API باستخدام GlobalAddAtom() للحصول على معرف في النطاق الأخير لمكتبات الارتباط الحيوي (DLL) المشتركة.لنبدأ بالوثائق الخاصة بالمعلمة to RegisterHotKey():

بطاقة تعريف
[في] يحدد معرف المفتاح السريع.إذا كانت المعلمة hWnd فارغة، فإن المفتاح السريع يرتبط بمؤشر الترابط الحالي بدلاً من نافذة معينة.إذا كان مفتاح التشغيل السريع موجودًا بالفعل بنفس معلمات hWnd وid، فراجع ملاحظات حول الإجراء المتخذ.

من هذا، يمكننا أن نستنتج أن مفاتيح التشغيل السريع يتم تحديدها بشكل فريد من خلال أحد الزوجين المحتملين من المعلومات:مؤشر ترابط أو مقبض نافذة ورقم عشوائي مكون من 16 بت.إذا قمت بتحديد مقبض النافذة (HWND)، ثم الرسالة يتم إرساله إلى تلك النافذة؛وإلا فسيتم إرساله إلى الموضوع.

لذا...إذا قمت بالتسجيل فقط واحد مفتاح التشغيل السريع لنافذة معينة، لا يهم المعرف حقًا1;لا يمكن لأي شخص آخر تسجيل مفتاح التشغيل السريع لتلك النافذة، وسيتم نشر أحداث مفتاح التشغيل السريع للنوافذ الأخرى على تلك النوافذ.وبالمثل، إذا قمت بتسجيل مفتاح تشغيل سريع واحد فقط بدون نوافذ لموضوع معين، فستتلقى فقط رسائل لمفتاح التشغيل السريع هذا. إذا كنت تتحكم في كل التعليمات البرمجية لتطبيقك، فيمكنك اختيار أي معرفات تريدها لمفاتيح التشغيل السريع الخاصة بك, باستخدام أي تقنية تريد تخصيصها لهم؛لن يدوس عليهم أحد آخر، لأنه أنت تملك كل التعليمات البرمجية ممكن حدوثه قادر للدوس عليهم!

ولكن ماذا لو كنت تكتب روتينًا للأغراض العامة يمكن استدعاؤه بواسطة كود آخر؟لا يمكنك اختيار معرف ثابت بشكل موثوق بعد ذلك، نظرًا لأنه من المحتمل أن يكون المتصل يستخدم هذا المعرف بالفعل، وإذا كان يستخدم أيضًا نفس النافذة أو الموضوع، فسينتهي بك الأمر إلى إعادة تعريف مفتاح التشغيل السريع الخاص به.أو ماذا لو (كما في حالتك) كنت لا تعرف عدد مفاتيح التشغيل السريع التي سيتم تسجيلها حتى وقت التشغيل؟

أنت بحاجة إلى طريقة للتأكد من أن المعرف الذي تختاره في وقت التشغيل سيكون معرفًا لا يستخدمه أي شخص آخر. هذا هو المكان GlobalAddAtom() يأتي دور:تمررها سلسلة، فيعطيك معرفًا مضمونًا أنه يتوافق مع تلك السلسلة وليس غيرها؛يعد هذا أمرًا فريدًا بالنسبة للنظام، ما لم يمرر شخص آخر نفس السلسلة - ومن المحتمل أن تتمكن من التوصل إلى سلسلة فريدة؛ما عليك سوى استخدام اسم شركتك، أو رقم الضمان الاجتماعي الخاص بك، والبادئة التي تقوم بزيادتها لكل ذرة جديدة تحتاجها.أو، إذا كنت مصابًا بجنون العظمة حقًا، فاستخدم المعرف الفريد العمومي (GUID).

الحقيقة وراء الحقائق

وبعد أن انتهيت من هذا، اسمحوا لي أن أحاول إزالة بعض الالتباس:لا يهتم Windows فعليًا بما إذا كان الرمز الذي يستدعي أم لا RegisterHotKey() موجود في ملف DLL.هو - هي لا أستطيع.النظر في الروتين التالي:

void RegisterSuperHappyFunHotKey(HWND hWnd, int id, 
                                 unsigned int fsModifiers, unsigned int vk)
{
   RegisterHotKey(hWnd, id, fsModifiers, vk);
}

هذا الروتين يفعل لا شئ ولكن قم بإعادة توجيه معلماتها إلى وظيفة WinAPI، ولا يحدد أي منها وحدة الاستدعاء.إذا كان موجودًا في ملف DLL، فسيتصرف بنفس الطريقة كما لو تم تجميعه في التطبيق نفسه.لا توجد طريقة موثوقة لنظام التشغيل Windows لمعرفة مكان بدء المكالمة، ويرتبط مفتاح التشغيل السريع نفسه بنافذة وخيط (أو خيط وحده) يمكن التحكم في أي منهما عن طريق التعليمات البرمجية داخل أو خارج DLL.الآن بالطبع، يمكن أن يكون لديك متطلبات خاصة بالتطبيق أو المكتبة:إذا قام ملف DLL الخاص بك بإنشاء نافذة وإعداد مفتاح تشغيل سريع لها، فستحتاج إلى الاهتمام بإلغاء تسجيل مفتاح التشغيل السريع هذا عند تدمير النافذة...ولكن هذا هو اهتمامك الخاص، للتعامل معه كما تراه مناسبًا.

تحدد MSDN نطاقين من المعرفات لسبب وجيه واحد:لتشجيعك، مؤلف DLL، على تجنب الدوس على المعرفات التي يستخدمها مؤلف التطبيق.إذا كنت مؤلف التطبيق، ثم العالم الذي تعيشون فيه المحار - أنت تتحكم (في معظم الأحيان) في أي كود يتم تحميله وتنفيذه في عملية التطبيق الخاص بك، وبالتالي يمكنك اتخاذ القرارات بشأن المعرفات التي تستخدمها ومع ذلك تراه مناسبا:البدء من 0 والزيادة لكل مفتاح تشغيل سريع جديد أمر مقبول تمامًا.ولكن بمجرد المغامرة في النطاق الأعلى من المعرفات، سيتعين عليك استخدامها GlobalAddAtom() تمامًا كما لو كنت ملف DLL - أو أنك تتعرض لخطر الاصطدام بمعرف تم إنشاؤه بهذه الطريقة بواسطة تعليمات برمجية خارجية تم تحميلها من ملف DLL.انه... عقد اجتماعي من أنواع.

ملخص:

إن بت "DLL المشترك" هو أمر مريب هنا؛إذا كان بإمكانك معرفة معرفات جميع مفاتيح التشغيل السريع المسجلة بواسطة تطبيقك، فما عليك سوى اختيار رقم أقل من 0xBFFF واستخدامه.إذا لم تتمكن من ذلك، لأن الرمز الخاص بك سيتم استخدامه من قبل عدة متصلين (كما هو الحال بالنسبة لك...)، فاحصل على معرف باستخدام GlobalAddAtom() واستخدام ذلك.

توصية

لهذه الأسباب أنصحك بذلك يفعل يستخدم GlobalAddAtom() بالنسبة للفئة التي تقوم بتصميمها، ببساطة لأنه يبدو كما لو كنت لا تعرف في هذا الوقت ما إذا كنت ستقوم ببنائها في تطبيق من تصميمك الخاص (حيث يمكنك التحكم في المعرفات المستخدمة) أو ملف DLL ليتم تحميلها بواسطة تطبيق آخر (حيث يمكنك لا).لا تقلق، فأنت لا تنتهك العقد التظاهر أن تكون DLL، طالما أنك تتبع القواعد المنصوص عليها لمتصلي DLL.


1حسنًا، هناك بعض معرفات مفاتيح التشغيل السريع المحددة من قبل النظام والتي يجب عليك الانتباه إليها...

واستكمال الإجابة فيليب:

وتحتاج إلى الحصول على مرجع للجمعية التي يتم استدعاء الدالة، وبالتالي فإن قانون يجب أن يكون مثل هذا:

Assembly assembly = Assembly.GetCallingAssembly();
Boolean isDll = assembly.EntryPoint == null;

وآمل أن يساعد هذا.

وريكاردو اسيردا كاستيلو برانكو

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top