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

<p>I have:</p>

<ol>
<li>marked the <em>Register for COM interop</em> option in the project properties,</li>
<li>changed the <em>ComVisible</em> setting in the <em>AssemblyInfo.cs</em> file,</li>
<li>added these lines to the ISS script:</li>
</ol>

<blockquote>
  <p>[Files]</p>
  
  <p>Source: c:\temp\1\MyDLL.dll; Flags: dontcopy</p>
  
  <p>[Code]</p>
  
  <p>function MyFunction(): string;</p>
  
  <p>external 'MyFunction@files:MyDLL.dll stdcall setuponly';</p>
</blockquote>

<p>but I still get the following error:</p>

<blockquote>
  <p>Runtime Error (at -1:0):</p>
  
  <p>Cannot Import dll:C:\DOCUME~1\foo\LOCALS~1\Temp\is-LRL3E.tmp\MyDLL.dll.</p>
</blockquote>

<p>What am I doing wrong?</p>

[{'answer_id': 45517, 'author': 'Simon Steele', 'author_id': 4591, 'author_profile': 'https://Stackoverflow.com/users/4591', 'pm_score': 2, 'selected': False, 'text': '<p>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.</p>\n\n<p>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?</p>\n\n<p>Also: See the <a href="http://www.jrsoftware.org/newsgroups.php" rel="nofollow noreferrer">innosetup support newsgroups</a> where you might get better support.</p>\n'}, {'answer_id': 45537, 'author': 'Simon Steele', 'author_id': 4591, 'author_profile': 'https://Stackoverflow.com/users/4591', 'pm_score': 3, 'selected': True, 'text': "<p>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:</p>\n\n<ol>\n<li>Write the functionality in C/C++ and export the function, that's definitely supported.</li>\n<li>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)</li>\n<li>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)</li>\n</ol>\n\n<p>When I last worked with InnoSetup it didn't support your scenario directly (calling .NET code from setup).</p>\n"}, {'answer_id': 45590, 'author': 'Marek Grzenkowicz', 'author_id': 95, 'author_profile': 'https://Stackoverflow.com/users/95', 'pm_score': 2, 'selected': False, 'text': "<p>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.</p>\n\n<p>Something like this would work for me:</p>\n\n<pre><code>[Code]\nprocedure MyFunction();\nvar\n  oleObject: Variant;\nbegin\n  oleObject := CreateOleObject('MyDLL.MyDLL');\n\n  MsgBox(oleObject.MyFunction, mbInformation, mb_Ok);\nend;\n</code></pre>\n\n<p>but it requires registering the DLL file.</p>\n\n<p>I guess I will have to create a command-line application to call the functions from the DLL.</p>\n"}, {'answer_id': 64479, 'author': 'Juba', 'author_id': 8661, 'author_profile': 'https://Stackoverflow.com/users/8661', 'pm_score': 0, 'selected': False, 'text': '<p>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: <a href="http://support.microsoft.com/kb/828736" rel="nofollow noreferrer">http://support.microsoft.com/kb/828736</a>. 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.</p>\n'}, {'answer_id': 1705317, 'author': 'Miguel Vivanco', 'author_id': 207459, 'author_profile': 'https://Stackoverflow.com/users/207459', 'pm_score': 3, 'selected': False, 'text': "<p>Intenta de esta manera (Try this way):</p>\n\n<pre><code>Var\n obj: Variant\n va: MyVariableType;\nBegin\n //Starting\n ExtractTemporaryFile('MyDll.dll');\n RegisterServer(False, ExpandConstant('{tmp}\\MyDll.dll'), False);\n obj := CreateOleObject('MyDll.MyClass');\n //Using\n va := obj.MyFunction();\n //Finishing\n UnregisterServer(False, ExpandConstant('{tmp}\\MyDll.dll'), False);\n DeleteFile('{tmp}\\MyDll.dll');\nEnd;\n</code></pre>\n\n<p>Suerte (good luck)</p>\n"}, {'answer_id': 3417533, 'author': 'Moissane', 'author_id': 412236, 'author_profile': 'https://Stackoverflow.com/users/412236', 'pm_score': 0, 'selected': False, 'text': "<p>Try using delayload, it is used for a dll that may not exist at runtime. This solve the problem.</p>\n\n<p>For example:</p>\n\n<pre><code>[Files]\nSource: odbccp32.dll; Flags: dontcopy\n\n[Code]\nprocedure SQLConfigDataSource(hwndParent: Integer; Frequest: Integer; LpszDriver: String; lpszAttributes: String);\nexternal 'SQLConfigDataSource@files:odbccp32.dll stdcall delayload';\n</code></pre>\n"}, {'answer_id': 43316676, 'author': 'Martin Prikryl', 'author_id': 850848, 'author_profile': 'https://Stackoverflow.com/users/850848', 'pm_score': 2, 'selected': False, 'text': '<p>Use the <a href="https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports" rel="nofollow noreferrer">Unmanaged Exports library</a> to export a function from a C# assembly, in a way that it can be called in Inno Setup.</p>\n\n<ul>\n<li>Implement a static method in C# class library</li>\n<li>Add the <a href="https://www.nuget.org/packages/UnmanagedExports/" rel="nofollow noreferrer">Unmanaged Exports</a> NuGet package to your project</li>\n<li>Set <em>Platform target</em> of your project to <em>x86</em></li>\n<li><a href="https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports#TOC-C-:" rel="nofollow noreferrer">Add the <code>DllExport</code> attribute to your method</a></li>\n<li>If needed, define a marshaling for the function arguments (particularly marshaling of string arguments has to be defined).</li>\n<li>Build</li>\n</ul>\n\n\n\n<pre><code>using RGiesecke.DllExport;\nusing System.Runtime.InteropServices;\nusing System.Text.RegularExpressions;\n\nnamespace MyNetDll\n{\n    public class MyFunctions\n    {\n        [DllExport(CallingConvention = CallingConvention.StdCall)]\n        public static bool RegexMatch(\n            [MarshalAs(UnmanagedType.LPWStr)]string pattern,\n            [MarshalAs(UnmanagedType.LPWStr)]string input)\n        {\n            return Regex.Match(input, pattern).Success;\n        }\n    }\n}\n</code></pre>\n\n<p>On Inno Setup side:</p>\n\n<pre class="lang-pascal prettyprint-override"><code>[Files]\nSource: "MyNetDll.dll"; Flags: dontcopy\n\n[Code]\nfunction RegexMatch(Pattern: string; Input: string): Boolean;\n    external \'RegexMatch@files:MyNetDll.dll stdcall\';\n</code></pre>\n\n<p>And now you can use your function like this:</p>\n\n<pre class="lang-pascal prettyprint-override"><code>if RegexMatch(\'[0-9]+\', \'123456789\') then\nbegin\n  Log(\'Matched\');\nend\n  else\nbegin\n  Log(\'Not matched\');\nend;\n</code></pre>\n\n<hr>\n\n<p>See also:</p>\n\n<ul>\n<li><a href="https://stackoverflow.com/q/20776847/850848">Returning a string from a C# DLL with Unmanaged Exports to Inno Setup script</a></li>\n<li><a href="https://stackoverflow.com/q/45955312/850848">Inno Setup - External .NET DLL with dependencies</a></li>\n</ul>\n'}]
['https://Stackoverflow.com/questions/45510', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/95/']