0

I am trying to call a C# dll to modify a json config file for my app during installation.

I have found several posts about this on StackOverflow but they relate to much older versions. Unfortunately none of them worked for me. For the DLL I used the sample C# project that comes with Inno and just added my method. I have not modified the project or solution in any other way apart from adding my method. For the Inno project I created an app from scratch.
Version numbers:
Inno Setup 6.0.3
C#: Framework 4.5

C# snippet:

[DllExport("Test", CallingConvention = CallingConvention.StdCall)]
public static int Test([MarshalAs(UnmanagedType.BStr)] out string strout)
{
      strout = "Hello World!";
      return 0; // indicates success
}

Inno project:

[Files]
Source: "MyDll.dll"; DestDir: "{tmp}"; Flags: dontcopy
Source: "example.json"; DestDir: "{app}"; AfterInstall: CallTest

[Code]
function Test(out strout: WideString): Integer; 
  external 'Test@MyDll.dll stdcall setuponly delayload';

procedure CallTest;
var
  retval: Integer;
  str: WideString;
begin
  MsgBox('Hello from CallTest', mbInformation, MB_OK);
  retval := Test(str);
  MsgBox('Return str is: ' + str, mbInformation, MB_OK);
end;

The Inno compiles correctly. During installation I do get the popup message "Hello from CallTest" but then get the error message "Line 32: Could not call proc". Line 32 is where we call our Test function and we set the return value to the Integer defined earlier. Although we are calling a method (not a procedure) and I looked at the return types from the DLL I cannot figure out why I am getting this error. Any help would be appreciated.

VasilisP
  • 136
  • 2
  • 11
  • You didn't specify a path to the DLL - It should be `external 'Test@{tmp}\MyDll.dll ...';` – Martin Prikryl Nov 11 '19 at 12:47
  • @TLama Why not? See for example [Calling .NET DLL in Inno Setup](https://stackoverflow.com/q/8487925/850848). – Martin Prikryl Nov 11 '19 at 12:48
  • 1
    @VasilisP Though the correct way is not deploying the DLL explicitly at all, and use `files:` prefix instead. See [Calling .NET DLL in Inno Setup](https://stackoverflow.com/q/8487925/850848). – Martin Prikryl Nov 11 '19 at 12:49
  • @TLama But OP has the function decorated using UnmanagedExports (`DllExport` attribute) – Though `UnmanagedType.BStr` is probably wrong. It should be `UnmanagedType.LPWStr`. – Martin Prikryl Nov 11 '19 at 13:05
  • @Martin, do'h, you're right. Sorry, taking back my comments [will delete them soon]. – TLama Nov 11 '19 at 13:36
  • @MartinPrikryl Adding a specific path does not help. So for example using 'Test@{tmp}\MyDll.dll stdcall setuponly delayload'; still gives me the same error, Cannot load proc. If I then use files ie 'Test@files:MyDll.dll stdcall setuponly'; (my understanding is that I do not need the delayload keyword) I get a compilation error message "cannot import dll". – VasilisP Nov 11 '19 at 14:35
  • Did you do everything according to [Calling .NET DLL in Inno Setup?](https://stackoverflow.com/q/8487925/850848) For instance, did you set *Platform target* of your C# project to *x86*? – Also consider starting with a simpler function – Like one that does not use `out` parameter – Try the exact code from my answer from the linked question for a start. – Martin Prikryl Nov 11 '19 at 14:51
  • @MartinPrikryl I used their provided C# example solution. I also double checked that the Platform target was set to x86. I already tried a simple C# method with no return value and changed the Inno definition to a procedure. Still getting the "Could not call proc" error message. I also tried LPWStr instead of Bstr enum for the marshalling but still getting the "Could not call proc" error message. – VasilisP Nov 11 '19 at 14:54
  • @MartinPrikryl I followed the post you linked me to. It is however 7yrs old. I do not know if something changed, however the C# code matches. What I cannot get to match is how we import the dll. I have to use the "delayload" and no specific path when I am declaring the Test function calling the dll. See more here: http://jrsoftware.org/ishelp/topic_scriptdll.htm – VasilisP Nov 11 '19 at 15:00
  • If I exactly follow (my) answer to [Calling .NET DLL in Inno Setup?](https://stackoverflow.com/q/8487925/850848) with VS 2017, .NET 4.7.2, Windows Desktop Class Library (.NET Framework) project, Unmanaged Exports 1.2.7, Inno Setup 6.0.3, it works. You must be doing something differently. My answer is only 2 years old and up to date. We need [mcve]. – Martin Prikryl Nov 11 '19 at 15:01
  • @MartinPrikryl I re-did the C# dll and removed ALL the code from inno's example. Then both the strout and the return value worked absolutely fine. I am not 100% what was causing the issue but giving it a clean start worked. I also managed to load the DLL using the "files" location and no use of delayload. Your previous answer worked fine. I need to back fill it to my actual project today so hopefully there will be no issues there. Is it possible to use a Net Standard library instead of a Framework one? – VasilisP Nov 12 '19 at 11:16
  • I didn't test .NET standard. – Martin Prikryl Nov 12 '19 at 11:20
  • @MartinPrikryl shall I write the answer or would you like to point towards your post and claim the points? – VasilisP Nov 12 '19 at 14:01
  • 1
    @MartinPrikryl Done :) – VasilisP Nov 12 '19 at 15:38

0 Answers0