Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何以编程方式检测代码是否在共享DLL或exe中运行?_C#_.net_Winapi_Dll_Registerhotkey - Fatal编程技术网

C# 如何以编程方式检测代码是否在共享DLL或exe中运行?

C# 如何以编程方式检测代码是否在共享DLL或exe中运行?,c#,.net,winapi,dll,registerhotkey,C#,.net,Winapi,Dll,Registerhotkey,A有一个C#类,它简化了全局热键的处理。 此类使用Win32 API函数RegisterHotKey()来注册热键 根据MSDN,当 当发生以下情况时,从应用程序和0xC000到0xFFFF范围内的ID值调用 从共享DLL调用GlobalAddAtom()可用于在运行时获取ID 在DLL中 为了向类的用户隐藏这种区别,类本身应该决定哪一个 注册热键时要使用ID范围。要做到这一点,全班必须 能够检测其代码是在应用程序中运行还是在 共享DLL 但如何做到这一点呢?C#/.NET最好的方法是什么?试试

A有一个C#类,它简化了全局热键的处理。 此类使用Win32 API函数
RegisterHotKey()
来注册热键

根据MSDN,当 当发生以下情况时,从应用程序和0xC000到0xFFFF范围内的ID值调用 从共享DLL调用
GlobalAddAtom()
可用于在运行时获取ID 在DLL中

为了向类的用户隐藏这种区别,类本身应该决定哪一个 注册热键时要使用ID范围。要做到这一点,全班必须 能够检测其代码是在应用程序中运行还是在 共享DLL

但如何做到这一点呢?C#/.NET最好的方法是什么?

试试这个:

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

“MethodInfo对象的属性值” 它代表了 此程序集。如果未指定入口点 已找到(例如,程序集是 DLL),一个空引用(在 返回“Visual Basic”


这是你的班级-你知道你把它放在哪里

如果您不共享它,那么只需在0xBFFF下面选择一个ID,就可以使用它了

如果您的类属于可由多个应用程序共享的DLL。。。或者可以由您无法控制的代码共享,因此无法为。。。然后使用获取ID(并记住在您之后打电话)


解释 可能值得花一分钟时间思考一下为什么有两个不同的ID范围,以及为什么API文档建议使用
GlobalAddAtom()
为共享DLL获取后一个范围内的ID。让我们从
RegisterHotKey()参数的文档开始:

id
[in]指定热键的标识符。如果hWnd参数为NULL,则热键与当前线程关联,而不是与特定窗口关联。如果已经存在具有相同hWnd和id参数的热键,请参阅备注了解所采取的操作

由此,我们可以推测热键是由两对潜在信息中的一对唯一标识的:线程或窗口句柄和任意16位数字。如果指定一个窗口句柄(
HWND
),则发送到该窗口;否则,它将被发送到线程

所以。。。如果只为给定窗口注册一个热键,则ID实际上并不重要1;其他人无法为该窗口注册热键,其他窗口的热键事件将发布到这些窗口。类似地,如果只为给定线程注册一个无窗口热键,则只会收到该热键的消息如果您控制应用程序的所有代码,您可以使用您想要分配的任何技术为热键选择任何ID;没有人会踩到它们,因为您拥有所有能够踩到它们的代码

但是,如果您正在编写一个可由其他代码调用的通用例程,该怎么办?您无法可靠地选择一个常量ID,因为调用者可能已经在使用该ID,如果他们也在使用相同的窗口或线程,您将重新定义他们的热键。或者,如果(如您的情况)您不知道在运行时之前将注册多少热键,该怎么办

您需要一种方法来确保您在运行时选择的ID不会被其他人使用。这就是
GlobalAddAtom()
发挥作用的地方:您向它传递一个字符串,它将为您提供一个保证与该字符串相对应的ID,而不是其他ID;这对于系统来说实际上是唯一的,除非其他人传递相同的字符串-您可能会得到一个唯一的字符串;只需使用您的公司名称,或您的社会保险号码,以及为您需要的每个新原子增加的前缀。或者,如果你真的很偏执,使用GUID

真相背后的真相 有了这些,让我试着澄清一点困惑:Windows实际上并不关心调用
RegisterHotKey()
的代码是否在DLL中。不可能。考虑下面的例程:

void RegisterSuperHappyFunHotKey(HWND hWnd, int id, 
                                 unsigned int fsModifiers, unsigned int vk)
{
   RegisterHotKey(hWnd, id, fsModifiers, vk);
}
此例程只将其参数转发给WinAPI函数,而WinAPI函数都不能识别调用模块。如果它存在于DLL中,它的行为将与编译到应用程序本身的行为相同。Windows没有可靠的方法来判断调用的起始位置,热键本身被绑定到一个窗口和线程(或一个单独的线程),这两个线程都可以由DLL中的代码控制。当然,现在您可以有自己的应用程序或库特定要求:如果您的DLL创建了一个窗口并为其设置了热键,那么当您销毁窗口时,您需要注意注销该热键。。。但这是你自己的问题,你可以随心所欲地处理

MSDN指定两个ID范围有一个很好的理由:鼓励DLL作者避免踩到应用程序作者使用的ID。如果您是应用程序的作者,那么世界就是您的牡蛎-您可以控制(在大多数情况下)在应用程序的进程中加载和执行哪些代码,因此可以决定使用哪些ID,但您认为合适:从0开始,每个新热键递增是完全可以接受的。但是,一旦进入了ID的上限,就必须像使用DLL一样使用
GlobalAddAtom()
,否则就有可能与从DLL加载的第三方代码以这种方式生成的ID发生冲突。这是一个。。。差不多

总结: “共享DLL”位在这里是一个模糊的概念;如果您可以知道应用程序注册的所有热键的ID,那么只需在0xBFFF下面选择一个数字并使用它。如果你不能,因为你的代码
Assembly assembly = Assembly.GetCallingAssembly();
Boolean isDll = assembly.EntryPoint == null;