Ao contrário das sugestões de algumas das outras respostas, o uso do DllImport
atributo ainda é a abordagem correta.
Sinceramente, não entendo por que você não pode fazer como todos os outros no mundo e especificar um caminho relativo para sua DLL. Sim, o caminho em que seu aplicativo será instalado difere nos computadores de outras pessoas, mas isso é basicamente uma regra universal quando se trata de implantação. oDllImport
mecanismo é projetado com isso em mente.
De fato, nem isso é o DllImport
que lida com isso. São as regras nativas de carregamento da DLL do Win32 que governam as coisas, independentemente de você estar usando os úteis wrappers gerenciados (o empacotador P / Invoke apenas chama LoadLibrary
). Essas regras são enumeradas em grandes detalhes aqui , mas as importantes são extraídas aqui:
Antes de o sistema procurar uma DLL, ele verifica o seguinte:
- Se uma DLL com o mesmo nome de módulo já estiver carregada na memória, o sistema utilizará a DLL carregada, independentemente do diretório em que esteja. O sistema não procura a DLL.
- Se a DLL estiver na lista de DLLs conhecidas para a versão do Windows em que o aplicativo está sendo executado, o sistema utilizará sua cópia da DLL conhecida (e as DLLs dependentes da DLL conhecida, se houver). O sistema não procura a DLL.
Se SafeDllSearchMode
estiver ativado (o padrão), a ordem de pesquisa será a seguinte:
- O diretório a partir do qual o aplicativo foi carregado.
- O diretório do sistema. Use o
GetSystemDirectory
função para obter o caminho deste diretório.
- O diretório do sistema de 16 bits. Não há função que obtenha o caminho desse diretório, mas ele é pesquisado.
- O diretório do Windows. Use o
GetWindowsDirectory
função para obter o caminho deste diretório.
- O diretório atual.
- Os diretórios listados na
PATH
variável de ambiente. Observe que isso não inclui o caminho por aplicativo especificado pela chave do Registro App Paths. A chave Caminhos do aplicativo não é usada ao calcular o caminho de pesquisa da DLL.
Portanto, a menos que você esteja nomeando sua DLL da mesma forma que uma DLL do sistema (o que você obviamente nunca deveria fazer, em nenhuma circunstância), a ordem de pesquisa padrão começará a procurar no diretório em que seu aplicativo foi carregado. Se você colocar a DLL lá durante a instalação, ela será encontrada. Todos os problemas complicados desaparecem se você apenas usar caminhos relativos.
Apenas escreva:
[DllImport("MyAppDll.dll")] // relative path; just give the DLL's name
static extern bool MyGreatFunction(int myFirstParam, int mySecondParam);
Mas se isso não faz o trabalho por qualquer motivo, e você precisa forçar o aplicativo a olhar em um diretório diferente para o DLL, você pode modificar o caminho de busca padrão usando a SetDllDirectory
função .
Observe que, conforme a documentação:
Após a chamada SetDllDirectory
, o caminho de pesquisa DLL padrão é:
- O diretório a partir do qual o aplicativo foi carregado.
- O diretório especificado pelo
lpPathName
parâmetro
- O diretório do sistema. Use a
GetSystemDirectory
função para obter o caminho deste diretório.
- O diretório do sistema de 16 bits. Não há função que obtenha o caminho desse diretório, mas ele é pesquisado.
- O diretório do Windows. Use a
GetWindowsDirectory
função para obter o caminho deste diretório.
- Os diretórios listados na
PATH
variável de ambiente.
Portanto, desde que você chame essa função antes de chamar a função importada da DLL pela primeira vez, poderá modificar o caminho de pesquisa padrão usado para localizar DLLs. O benefício, é claro, é que você pode passar um valor dinâmico para essa função que é calculada em tempo de execução. Isso não é possível com o DllImport
atributo; portanto, você ainda usará um caminho relativo (apenas o nome da DLL) e contará com a nova ordem de pesquisa para encontrá-lo.
Você terá que P / Invocar esta função. A declaração é assim:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);