Como posso chamar uma DLL .NET a partir de um script do Inno Setup?
-
09-06-2019 - |
Pergunta
Quero chamar uma função de uma DLL .NET (codificada em C#) de um script Inno Setup.
Eu tenho:
- marcou o Registre-se para interoperabilidade COM opção nas propriedades do projeto,
- mudou o ComVisível configuração no AssemblyInfo.cs arquivo,
- adicionei estas linhas ao script ISS:
[Arquivos]
Fonte:c: emp\1\MyDLL.dll;Bandeiras:não copie
[Código]
função MinhaFunção():corda;
externo 'MyFunction@files:MyDLL.dll stdcall setuponly';
mas ainda recebo o seguinte erro:
Erro de tempo de execução (em -1:0):
Não é possível importar dll:C:\DOCUME~1\foo\LOCALS~1 emp\is-LRL3E.tmp\MyDLL.dll.
O que estou fazendo de errado?
Solução
Opa, que pena, já faz muito tempo que não leio Pascal!Portanto, se você precisar obter o valor, existem algumas possibilidades:
- Escreva a funcionalidade em C/C++ e exporte a função, isso é definitivamente suportado.
- Use uma dll C++ gerenciada para corrigir sua dll .NET e exponha a chamada como um ponto de interface C (isso deve funcionar, mas está ficando confuso)
- Use um .exe para armazenar o resultado do seu código em um arquivo .INI ou no registro ou em um arquivo temporário e leia o resultado na seção de código de configuração (agora isso é desagradável)
Da última vez que trabalhei com o InnoSetup, ele não suportava diretamente o seu cenário (chamando o código .NET da configuração).
Outras dicas
Tentativa desta maneira (tente desta forma):
Var
obj: Variant
va: MyVariableType;
Begin
//Starting
ExtractTemporaryFile('MyDll.dll');
RegisterServer(False, ExpandConstant('{tmp}\MyDll.dll'), False);
obj := CreateOleObject('MyDll.MyClass');
//Using
va := obj.MyFunction();
//Finishing
UnregisterServer(False, ExpandConstant('{tmp}\MyDll.dll'), False);
DeleteFile('{tmp}\MyDll.dll');
End;
Suerte (boa sorte)
Li um pouco mais sobre isso - agora posso ver a diferença entre importar uma função estilo C e criar um objeto OLE.
Algo assim funcionaria para mim:
[Code]
procedure MyFunction();
var
oleObject: Variant;
begin
oleObject := CreateOleObject('MyDLL.MyDLL');
MsgBox(oleObject.MyFunction, mbInformation, mb_Ok);
end;
mas requer o registro do arquivo DLL.
Acho que terei que criar um aplicativo de linha de comando para chamar as funções da DLL.
Você está tentando importar uma função estilo C da sua dll .NET - isso realmente não tem nada a ver com interoperabilidade COM.A interoperabilidade COM permite que você ative seus objetos .NET como objetos COM, ela não os expõe como funções/tipos exportados em C/C++.
Se sua função não precisa retornar nenhum dado, por que não criar um .exe simples que chame sua função e executá-lo a partir de sua configuração?
Também:Veja o grupos de notícias de suporte innosetup onde você pode obter melhor suporte.
Use o Biblioteca de exportações não gerenciadas para exportar uma função de um assembly C#, de forma que ela possa ser chamada no Inno Setup.
- Implementar um método estático na biblioteca de classes C#
- Adicione o Exportações não gerenciadas Pacote NuGet para seu projeto
- Definir Alvo da plataforma do seu projeto para x86
- Adicione o
DllExport
atribua ao seu método - Se necessário, defina um empacotamento para os argumentos da função (particularmente o empacotamento de argumentos de string deve ser definido).
- Construir
using RGiesecke.DllExport;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
namespace MyNetDll
{
public class MyFunctions
{
[DllExport(CallingConvention = CallingConvention.StdCall)]
public static bool RegexMatch(
[MarshalAs(UnmanagedType.LPWStr)]string pattern,
[MarshalAs(UnmanagedType.LPWStr)]string input)
{
return Regex.Match(input, pattern).Success;
}
}
}
No lado do Inno Setup:
[Files]
Source: "MyNetDll.dll"; Flags: dontcopy
[Code]
function RegexMatch(Pattern: string; Input: string): Boolean;
external 'RegexMatch@files:MyNetDll.dll stdcall';
E agora você pode usar sua função assim:
if RegexMatch('[0-9]+', '123456789') then
begin
Log('Matched');
end
else
begin
Log('Not matched');
end;
Veja também:
Uma dll .NET pode ser melhor chamada de qualquer outra linguagem de programação, expondo-a como um objeto COM.Dê uma olhada neste exemplo: http://support.microsoft.com/kb/828736.Isso mostra como chamar uma "dll .NET" de "C++ não gerenciado".Você pode substituir o "C++ não gerenciado" por qualquer outra linguagem de programação, que possa ser usada como cliente COM.
Tente usar delayload, ele é usado para uma dll que pode não existir em tempo de execução.Isso resolve o problema.
Por exemplo:
[Files]
Source: odbccp32.dll; Flags: dontcopy
[Code]
procedure SQLConfigDataSource(hwndParent: Integer; Frequest: Integer; LpszDriver: String; lpszAttributes: String);
external 'SQLConfigDataSource@files:odbccp32.dll stdcall delayload';
Script Innosetup para detectar estrutura dotnet e versão antiga pode ser de alguma utilidade.