Pergunta

Quero chamar uma função de uma DLL .NET (codificada em C#) de um script Inno Setup.

Eu tenho:

  1. marcou o Registre-se para interoperabilidade COM opção nas propriedades do projeto,
  2. mudou o ComVisível configuração no AssemblyInfo.cs arquivo,
  3. 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?

Foi útil?

Solução

Opa, que pena, já faz muito tempo que não leio Pascal!Portanto, se você precisar obter o valor, existem algumas possibilidades:

  1. Escreva a funcionalidade em C/C++ e exporte a função, isso é definitivamente suportado.
  2. 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)
  3. 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';
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top