views:

1681

answers:

7

I want to call a function from a .NET DLL (coded in C#) from an Inno Setup script.

I have:

  1. marked the Register for COM interop option in the project properties,
  2. changed the ComVisible setting in the AssemblyInfo.cs file,
  3. added these lines to the ISS script:

[Files]

Source: c:\temp\1\MyDLL.dll; Flags: dontcopy

[Code]

function MyFunction(): string;

external 'MyFunction@files:MyDLL.dll stdcall setuponly';

but I still get the following error:

Runtime Error (at -1:0):

Cannot Import dll:C:\DOCUME~1\foo\LOCALS~1\Temp\is-LRL3E.tmp\MyDLL.dll.

What am I doing wrong?

+2  A: 

You're trying to import a C-style function from your .NET dll - this doesn't really have anything to do with COM interop. COM interop allows you to activate your .NET objects as COM objects, it doesn't expose them as C/C++ exported functions/types.

If your function doesn't need to return any data, why not make a simple .exe that calls your function and just run that from your setup?

Also: See the innosetup support newsgroups where you might get better support.

Simon Steele
+2  A: 

Oops, my bad, it's been too long since I've read pascal! So, if you need to get the value then there are a couple of possibilities:

  1. Write the functionality in C/C++ and export the function, that's definitely supported.
  2. Use a Managed C++ dll to shim to your .NET dll, and expose the call as a C interface point (this should work, but it's getting messy)
  3. Use an .exe to store the result of your code in a .INI file or the registry or in a temp file and read the result in the setup code section (this is now properly nasty)

When I last worked with InnoSetup it didn't support your scenario directly (calling .NET code from setup).

Simon Steele
+1  A: 

I read a little bit more about it - now I can see the difference between importing a C-style function and creating an OLE object.

Something like this would work for me:

[Code]
procedure MyFunction();
var
  oleObject: Variant;
begin
  oleObject := CreateOleObject('MyDLL.MyDLL');

  MsgBox(oleObject.MyFunction, mbInformation, mb_Ok);
end;

but it requires registering the DLL file.

I guess I will have to create a command-line application to call the functions from the DLL.

Marek Grzenkowicz
Just out of curiosity, did this work? Be able to call .Net Dll's from Innoset would be a boon...
Kris Erickson
Yes, something like this works, but I didn't use this method in my installer because it required registering the DLL.
Marek Grzenkowicz
A: 

A .NET dll can be best called from any other programming language by exposing it as a COM object. Take a look at this example: http://support.microsoft.com/kb/828736. This shows how to call a ".NET dll" from "unmanaged C++". You can replace the "unamanged C++" by any other programming language, that can be used as a COM client.

Shao
A: 

this might be of some use

http://www.ceveni.com/2008/03/check-dotnet-framework-using-innosetup.html

A: 

Intenta de esta manera (Try this way):

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 (good luck)

Miguel Vivanco
Interesting approach Miguel. Does this work? I've tried to get something like it working but I am not sure I have it setup correctly. Can you post the sample code that would call this routine? I think I am very close to getting it working.
Streamline
A: 

Try using delayload, it is used for a dll that may not exist at runtime. This solve the problem. For example:

[Files] Source: odbccp32.dll; Flags: dontcopy

[Code] procedure SQLConfigDataSource(hwndParent: Integer; Frequest: Integer; LpszDriver: String; lpszAttributes: String); external 'SQLConfigDataSource@files:odbccp32.dll stdcall delayload';

Greetings

Moissane