C# DLL using DllExport: No entry point when called in VBA - c#

To avoid requiring a Dll be registered for all users of a spreadsheet, I'm trying to use late binding so that users do not need to add a reference to the Dll.
I've created the Dll in C# with Visual Studio, and even though I've included "using RGiesecke.DllExport;" and used DllExport on a function to return an object containing the functions I need to access in VBA, I still get the error "Run-time error '453': Can't Find DLL entry point CreateDotNetObject in C:\temp\MyFunctions.dll."
The DLL code is as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using System.Data;
using System.Text.RegularExpressions;
using Microsoft.TeamFoundation.Client;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Collections;
using System.Collections.ObjectModel;
using System.Threading;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework;
using Microsoft.TeamFoundation.Common;
using Microsoft.VisualBasic;
using System.Diagnostics;
using RGiesecke.DllExport;
namespace MyFunctions
{
public interface IMyFunctions
{
string GetWorkItemLinkList(string WIIDs);
}
[CLSCompliant(true), ComVisible(true), ClassInterface(ClassInterfaceType.AutoDual)]
public class MyFunctions : IMyFunctions
{
TfsConfigurationServer server;
WorkItemStore store;
private void TFSconnect()
{
//Code to connect
}
[CLSCompliant(true), ComVisible(true), Description("GetWorkItemLink func")]
public string GetWorkItemLink(int WIID)
{
TFSconnect();
//Code to build return string "message"
return message;
}
[CLSCompliant(true), ComVisible(true), Description("GetWorkItemLinkList func")]
public string GetWorkItemLinkList(string WIIDs)
{
TFSconnect();
//Code to build return string "returnStr"
return returnStr;
}
}
static class UnmanagedExports
{
[DllExport]
[return: MarshalAs(UnmanagedType.IDispatch)]
static Object CreateDotNetObject()
{
return new MyFunctions();
}
}
}
and the declaration in VBA is as follows:
Private Declare Function CreateDotNetObject Lib "c:\temp\MyFunctions.dll" () As Object
But when I try to instantiate an object, I get the error I mentioned above.
Sub test()
Dim o As Object
Set o = CreateDotNetObject()
End Sub
This is my first time attempting to use custom dll functions in Excel without adding a reference in the VBA. The functions do work if I add a reference (early binding), but the DLL is not going to be propogated to everyone who uses the spreadsheet, and I need it to not crash when they run normal functions.
EDIT: Additional info. I just noticed that in addition to the DLL, when I build the solution in Visual Studio I also get an " Object FileLibrary" and an "Exports Library File". When I register the DLL is there anything I should be doing with either the .exp or .lib?
Thanks,
Mike

I was building the solution with the Platform Target in the class library properties set to "Any PC", which apparently does not allow exports. When I switch it to "x86" it totally works.

Related

what reference I need to add in C# to get LaunchPadApi?

I try to connect to the API (Using C#) that client provided, but it is using LaunchPadApi() I am not sure what assembly I need to add to get this, these are 2 references that were added:
using IO.Swagger.Api;
using IO.Swagger.Client;
I was able to find using IO.Swagger.Client; but I am not able to find using IO.Swagger.Api;
This is a sample code I am not sure how I can get LaunchPadApi defined so "responsePost" method is not recognized as well,
using System;
using System.Diagnostics;
using IO.Swagger.Api;
using IO.Swagger.Client;
using IO.Swagger.Model;
public class responsePostExample
{
public void main()
{
var apiInstance = new LaunchPadApi();
....
try
{
apiInstance.responsePost(body, xAPIKey);
}
....
Install Launchpad in your nuget package manager for the project
Add using Launchpad; to the top of your file

Empty DLL, Class library C#

I have created a class library to be used in a other project (which is not a .Net project), i have built the solution the dll file was generated, but when i try to explor my dll using dllexp i foud that it's empty.
My class is declared public as you can see bellow:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PCLImportCLin.ServiceReference1;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;
namespace PCLImportCLin
{
public class ImportCL
{
public int geTroupeau()
{
// Rest of the code
}
}
}
What you are looking for, I guess, is this:
(Assuming you are using Visual Studio) In your project, right-click 'References', go to 'Browse' and then click the 'Browse...' button. Go to your dll path, select it. There you go. Now you can use it like this using Your.Dll.Namespace;

Class library loses references (dlls) when being used

Sorry for the title. I don't know how to describe this problem shortly.
My problem is that I have a class-library which has references to other (third party) DLLs.
I need to use this class-library in another project, so I obviously added the .dll of my class-library to my main-project.
When I start my main-project, there's alway an error which says, that a reference (dll) in my class-library cannot be found.
If I add the whole class-library as a project to my projectmap in visual studio and then reference the whole project, this error doesn't occur.
I really don't want to add the whole class-library as a project to every "host"-project I make.
Has anyone an idea why this error occurs when the .dll of the class-library is added, but not when the whole project of the class-library is added as reference?
There must be a solution to get this working even if I don't add the whole library-project as reference. Otherwise it wouldn't make any sense to make a class library, right?
By the way: My class-library contains third-party dlls and the local copy property of the third-party dll is set to true.
Thanks in advance!
Edit:
My goal is to really make the class-library portable, even though it contains third-party libraries. I want to give only the .dll to another pc and use it without adding the whole class-library project every time.
The error is because you're not copying the dll's on the second project, you added a reference to your dll so it get's copied, but not the dll's referenced by your dll, so there are missing libraries.
Or you redistribute the dependencys with your dll or you can embedd the dll's inside your dll as resources and then intercept the assembly load and provide it through a resource: http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx
EDIT: IN order to do it inside a dll you need to use an static class and call an static initializer BEFORE using any of the classes which are dependant on other libraries.
Here is an example setup:
-A library called LibraryB which supplies a simple class like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibraryB
{
public class ReferencedClass
{
public int GetIt()
{
return 5;
}
}
}
-A library called LibraryA which references LibraryB and supplies two classes, the initializer and the real class:
Initializer
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace LibraryA
{
public static class Initializer
{
public static void Init()
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
if (!args.Name.StartsWith("LibraryB"))
return null;
return Assembly.Load(LibraryA.Properties.Resources.LibraryB);
};
}
}
}
Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibraryA
{
public class RealClass
{
public int DoIt()
{
LibraryB.ReferencedClass cl = new LibraryB.ReferencedClass();
return cl.GetIt();
}
}
}
The LibraryA also has the LibraryB.dll compiled library embedded as a resource.
-A project called Test which only references LibraryA:
using LibraryA;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Initializer.Init();
RealClass c = new RealClass();
Console.WriteLine("From LibraryA: " + c.DoIt());
Console.ReadKey();
}
}
}
If you set-up everithing right and you execute it it will work, remember that if you are doing through visual studio, vs will copy the dll's so to do a real test after compiling all copy the exe and LibraryA and execute, it will work without LibraryB and LibraryB is being used from LibraryA.

Invoke function from DLL (c#) in Oracle Forms

I've got big problem with invoking method from DLL in Oracle Forms 6i. DLL has been written in
C#, and it is code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OnlineFPCommon;
using System.Windows.Forms;
namespace TestNamespace
{
public class TestClass
{
public static void testMethod()
{
MessageBox.Show("testMethod");
}
}
}
I try to invoke it using Oracle Forms code:
testlib_lhandle := Ora_Ffi.Load_library('C:\libdir\','test.dll');
getresult_fhandle := ora_ffi.register_function(testlib_lhandle,'testMethod');
but the second line, when I try to register function fails. Why? How Can I properly invoke that function?
register_function requires a dll entry point and you cannot generate that in managed code.
You can write a C++/CLi wrapper DLL to have native entry points for your managed code but if you are just starting from scratch then why not just write a plain native dll.

Create COM-Object from own C# Dll in Progress 4GL

I'm wondering how I can create a Com-Object from my own C# DLL.
I made the following Class in C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ProgressNet
{
[Guid("a9b1e34d-3ea3-4e91-a77a-5bcb25875485")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
[ProgId("ProgressNet.Server")]
public class NetServer
{
public NetServer() {}
[DispId(1)]
public string GetString()
{
return "Some String";
}
}
}
In Properties I checked Register for COM Interop.
Then I registered the DLL with regasm.
regasm G:\ProgressTestApp\ProgressNet.dll /tlb:G:\ProgressTestApp\ProgressNet.tlb /codebase
Then I tried in Progress 4GL this Code:
DEFINE VARIABLE NetServer AS COM-HANDLE.
CREATE "ProgressNet.NetServer" NetServer.
MESSAGE NetServer:GetString().
But then I get "The automation server for ProgressNet.NetServer is not registered properly"..
Any Suggestions? :)
IN case anyone is still reading this, the answer turns out to be pretty simple: The following line is wrong.
MESSAGE NetServer::GetString().
It should be
MESSAGE NetServer:GetString().
The error is in the create com-handle statement. It should be create "ProgressNet.Server" NetServer. and not "ProgressNet.NetServer" as specified by the ProgId call.
I registered the DLL with regasm as you mentioned and used the code below to test and it worked fine.
def var ch as com-handle no-undo.
create "ProgressNet.Server" ch.
MESSAGE ch:GetString()
VIEW-AS ALERT-BOX INFO BUTTONS OK.

Categories

Resources