Como detectar programaticamente se o código está sendo executado em DLL ou exe compartilhado?

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

Pergunta

A tem uma classe C # que simplifica a manipulação de teclas de atalho globais. Essa classe usa a função Win32 API-RegisterHotKey() para registrar as teclas de atalho.

De acordo com MSDN esta função precisa de um valor de ID na faixa de 0x0000 através 0xBFFF quando chamando a partir de uma aplicação e um valor de ID na faixa de 0xC000 a 0xFFFF quando chamando a partir de uma DLL compartilhada. GlobalAddAtom() pode ser usado para obter o ID em caso de execução em uma DLL.

Para ocultar esta distinção do usuário da classe a classe em si deve decidir qual faixa de ID é para ser usado ao registrar uma tecla de atalho. Bem, e para isso, a classe deve ser capaz de detectar se o código está sendo executado dentro de um aplicativo ou dentro um compartilhada DLL.

Mas como fazer isso? Qual é a melhor maneira C # /. NET para fazer isso?

Foi útil?

Solução

Tente isto:

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

MSDN:

Assembly.EntryPoint Propriedade

"objeto Propriedade Valor A MethodInfo que representa o ponto de entrada de esta montagem. Se nenhum ponto de entrada é encontrado (por exemplo, o conjunto é um DLL), uma referência nula (Nada nas Visual Basic) é retornado. "

Outras dicas

de o classe - você sabe , onde você está colocando isso.

Se você não está compartilhando-o, em seguida, basta escolher um ID abaixo 0xBFFF e ser feito com ele.

Se a sua classe pertence em uma DLL que pode ser compartilhado por vários aplicativos ... Ou pode simplesmente ser compartilhado por código que você não controla e, portanto, são incapazes de resolver IDs para ... uso, em seguida, GlobalAddAtom() para obter uma ID (e lembre-se de chamada GlobalDeleteAtom() depois de unregister a tecla de atalho ).


Explicação

É provavelmente vale a pena tomar um minuto para pensar sobre por que existem duas faixas de identificação diferentes, e porque a documentação da API recomendo usar GlobalAddAtom() para obter uma ID no último intervalo para DLLs compartilhadas. Vamos começar com a documentação para o parâmetro para RegisterHotKey():

id
[No] Especifica o identificador da chave quente. Se o parâmetro hWnd é NULL, em seguida, a tecla de atalho é associado ao segmento atual, em vez de com uma janela particular. Se uma tecla de atalho já existe com os mesmos parâmetros hWND e id, consulte Comentários para a ação tomada.

A partir disso, podemos supor que as teclas de atalho são identificados exclusivamente por um dos dois pares potenciais de informação: um fio ou janela alça, e um número de 16 bits arbitrária. Se você especificar um identificador de janela (HWND), então a mensagem é enviado para aquela janela; Caso contrário, é enviado para o segmento.

Então ... Se você só registar um atalho para uma determinada janela, o ID não importa realmente 1 ; ninguém mais pode registrar um atalho para essa janela, e eventos das teclas de atalho para outras janelas irá publicar a essas janelas. Da mesma forma, se você só registrar um atalho sem janelas para um determinado segmento, só obterá mensagens desse atalho. Se você controla todo o código para o seu aplicativo, você pode escolher o que IDs que você deseja para suas hotkeys , utilizando qualquer técnica que pretende atribuir-lhes; ninguém passo será outra coisa sobre eles, porque você possui todo o código que seria pode pisar neles!

Mas o que se você estiver escrevendo uma rotina de uso geral que pode ser chamado por outro código? Você não pode escolher de forma confiável uma identificação constante, então, uma vez que o chamador poderia estar usando esse ID já, e se eles também estão usando a mesma janela ou tópico, você ia acabar redefinindo o seu atalho. Ou que se (como no seu caso) você não sabe quantas teclas de atalho será registrado até a execução?

Você precisa de uma maneira de garantir que o ID que você escolher em tempo de execução será aquele que ninguém mais está usando Isto é onde GlobalAddAtom() entra em jogo:. Você passa uma string, e dá -lhe um ID garantida para corresponder a essa corda e nenhuma outra; este é efetivamente exclusivo para o sistema, a menos que alguém passa a mesma cadeia - e provavelmente você pode vir até com uma cadeia exclusiva; basta usar o nome da empresa, ou o seu número de segurança social, e um prefixo que você incrementa para cada novo átomo que você precisa. Ou, se você é realmente paranóico, usar um GUID.

A verdade por trás verdades

Com isso fora do caminho, deixe-me tentar esclarecer um pouco de confusão: Windows na verdade não importa se ou não o código que chama RegisterHotKey() está em uma DLL. É não pode . Considere a seguinte rotina:

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

Esta rotina faz nada , mas envia os seus parâmetros para a função WinAPI, nenhum dos quais identificar o módulo de chamada. Se ele viveu em uma DLL, ele se comportaria o same como se fosse compilado no próprio aplicativo. Não há nenhuma maneira confiável para o Windows dizer onde a chamada teve origem, eo próprio atalho está vinculado a uma janela e thread (ou um fio sozinho) seja de que poderia ser controlada pelo código dentro ou fora de uma DLL. Agora, é claro, você poderia ter app- ou requisitos específicos de biblioteca de sua própria: se sua DLL cria uma janela e configura um atalho para isso, então você vai querer cuidar de cancelar o registro de que atalho quando você destruir a janela. .. Mas isso é seu próprio interesse, para lidar com como você vê o ajuste.

MSDN especifica os dois intervalos de IDs para uma boa razão: para incentivá-lo, o autor DLL, para evitar pisar em IDs usados ??pelo autor do aplicativo. Se você é o autor do aplicativo, em seguida, o mundo é sua ostra - você controla (em sua maior parte) que o código é carregado e executado no processo do seu aplicativo, e pode, portanto, tomar as decisões a respeito de que IDs que você usa , contudo, você vê o ajuste : a partir de 0 e incrementando a cada novo atalho é perfeitamente aceitável. Mas uma vez que você se aventurar na faixa superior de IDs, você terá que usar GlobalAddAtom() como se você fosse um DLL - ou você corre o risco de colidir com um ID gerado desta forma pelo código de terceiros carregado a partir de uma DLL. É uma ... contrato social das sortes.

Sumário:

O bit "DLL compartilhada" é um arenque vermelho aqui; se você pode conhecer os IDs de todos os atalhos registrados pelo seu aplicativo, em seguida, basta escolher um número abaixo 0xBFFF e usá-lo. Se você não pode, porque o seu código será utilizado por vários chamadores (como o seu é ...), então, obter uma ID utilizando GlobalAddAtom() e uso isso.

Recomendação

Por estas razões, eu recomendo que você não uso GlobalAddAtom() para a classe que você está projetando, simplesmente porque ele soa como se você não sabe, neste momento ou não poderás construí-lo em um aplicativo de seu próprio projeto (onde você controla os IDs sendo usado) ou um DLL a ser carregado por algum outro aplicativo (onde não ). Não se preocupe - você não está violando o contrato pelo fingir ser uma DLL, desde que você siga as regras estabelecidas para chamadas DLL.


1 ok, por isso há um par de IDs das teclas de atalho definidas pelo sistema que você tem que tomar cuidado para ...

Completando a resposta Philip:

Você precisa obter uma referência do assembly que está chamando a função, de modo que o código deve ser assim:

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

Espero que isso ajude.

Ricardo Lacerda Castelo Branco

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top