I can't find any good resources online about what this is. It's required in one of the steps for deploying a .NET assembly for use by COM, but there is no detail what it is or what it means.
As an example, here is something from the book I'm reading on Interop:
Next you need to create a resource script MyExampleAssembly.res with the following statement:
(This gets run at the VS command prompt in the directory where you just exported your .NET component using the Type Library Exporter Utility)
IDR_TYPELIB1 typelib "MyExampleAssembly.tlb"
What is IDR_TYPELIB1?
Also, it's not working for me. I have tried running this and it doesn't compile. I get a message "'IDR_TYPELIB1' is not recognized as an internal or external command".
It is a macro that's normally auto-generated when you use the unmanaged resource editor. Just use a constant, 1 is fine. You are also using the wrong tool to compile the resource script by the sound of it, you must run rc.exe. It translates your .rc file to a .res file that the C# compiler can use.
Embedding the type library is optional btw, it is not something that COM Automation requires. It is not a very good idea to do this in a managed project since the .tlb is generated after building the project. Instead of before, as happens in a native COM project. You create it with regasm.exe, /tlb option or the tlbexp.exe utility. Your client can do this too.
Related
How do you compile .cs files using C++
I have searched all through Mono's documentation and can't find a way to just compile C# code from the embedded mono runtime in C++. I know how to open a C# .exe assembly file using the embedded mono functions from C++, but I can't seem to find a way to just compile a .cs file to the .exe from C++.
I have also managed to compile the .cs files by calling the mcs.bat file from the CreateProcessA() function that Windows provides, however this does not give me a way to log errors or even check if it succeeded in compilation etc. (It also feels like a hack and not the official solution). The main reason I need to do this is so that I can recompile C# scripts on the fly by detecting when the source code has changed and another subset of conditions.
Does anyone know of a way to properly compile C# files using the embedded Mono runtime? And where to find the documentation for this? Currently I've been using the documentation here: http://docs.go-mono.com/?link=xhtml%3adeploy%2fmono-api-assembly.html which provides enough information for the most part.
Linking Mono in a DLL
Also, if you're familiar with embedding mono, do you know how to use it in a dll? I've managed to successfully link and compile it within a console application, but when I try to compile it as a part of a dynamic library, I get unresolved external symbol errors (specifically functions with the prefix __imp*).
Lastly, I'm using mono to embed C# as a scripting language for my game engine, however I don't know if there is a better (smaller) solution that I can use. If you know of any better solution feel free to leave a recommendation.
The mono runtime is a "Runtime", only for running the code,
but if you have installed the csc command then you can use this:
#include <cstdlib>
int main(){
system("csc yourfile.cs")
return 0;
}
The user's main application is ms-access (with ms-sql server). Ton of code in vba.
One of the main features i have to manifest is controlling my client's voip telephony. My plan is to make a COM DLL that the ms-access can use.
As of now, i've managed to write a C# project (vs2019 .net framework) that handles the voip pbx well, using json, and do all missions necessary, such as invoking calls, sending sms, get calls list, recodings list, get recordings wav files and convert them to mp3. I use Newtopsoft.Json and NAudio.Lame.
BUT it only works as a standalone .net project or exe.
As a COM DLL (class library) - ms-access can handle and use it UNTIL it gets to the part where the code uses ANY external dll's functionality - and it crashes (with newtonsoft) or just not working (with naudio), although the dll's are in the working folder.
I know i have to found a way to make these external dll's to work under the office (32bit) enviroment.
I was trying and guessing many code samples for a couple of days. I tried to follow the Assembly.Load/From/File examples to dynamically load and include the dll's, but i failed to assimilate it in my code or even to understand it enough.
I hope i'll get a solution here.
Thanks :)
Hum, I am able to create a COM object for use with Access. External library code (in my case Newton soft) for serializing data works just fine when that class code is used as a COM object from Access.
You don't mention if the other libraries are managed code, or external win32 .dll? I have however used un-managed .dll’s with a .net COM object, and then have consumed that from MS-access.
The only issue would be in project explorer is to ensure that you have a copy local setting = true for the external referenced .net .dll libraries. (And that is the default, so I am sure you do.
The next issue of course is of course is there any use of configuration files? (app.config) etc.? The reason for this of course that since your application is being launched with msaccess.exe, then the config and settings will be assumed to be in the office install folder, and not the local application. As a result, it not all so practical to move/copy those app.config files to the office folder where msaccess.exe resides. And the config file name will not only have to be in the same folder, but also named.
Msaccess.exe.config.
In place of
YourDotNet.exe.config
Now of course, if you build your project as a .net exec? Well then of course any config settings (application ones, not user) will be placed in this config file, and of course that file will have to be placed in the same folder as the .exe file.
So, one might add a “test” function (any function is a method of that class) to the class that you test/call from VBA to ensure that such settings are being seen and read (if you are using any settings).
Eg:
System.Reflection.Assembly.GetExecutingAssembly().Location + ".config"
So, return that to access and display this result.
The other issue is of course to FORCE your project to x86. I would not use “any” CPU. While this “may” work, since you are using access x32, then I would force compile your .net class to x86 as opposed to “any” CPU. This would also spit out some errors in case some of the external assemble(ies) are compared to a particular bit size and thus x86 settings will result in your class not consuming some of the external .net .dll’s.
Now you “note” that your project works as an .exe, and then “sort of” works as a class and “.dll” registered as a COM.
However, you don’t mention how you are “flipping” this from an .exe to a class, or do you simply have a .net “test” project that you run as an .exe, and it of course has a reference to that class .dll. And you NOT using “COM” for this testing.
If your test.exe program can use that external assembly?
Then I would create a test2 project, but this time around do NOT reference the assembly (as .net), but try using .net CreateObject(). (I think c# has this choice – vb.net certainly does).
So you could try + use a CreateObject() in this .net test sample, and thus test from .net as COM.
So this test .net program (one that has NOT referenced the assembly) would a intermediate test before you jump all the way into ms-access + VBA test code.
However, I would first test/check if an app.config file is being used here, since as noted when you flip to a COM object, and then create a instance of that object in Access/VBA?
Then the config file will NOT be used. You can in .net code force/change the app.config file in that running assembly, and I can’t seem to find my code example that does this. But I am not going to dig too hard until such time we confirm that you are using app.exe.config file here.
Edit
Out of cuirous, I googled naudio. It is managed code. So, that library should work just fine. If that project is compiled as "ANY CPU", you COULD try re-compile as x86, and also re-compile your test program as x86. Then when you create a COM object, then again compile that as x86.
As noted, I do quite a bit of COM stuff for ms-access, and I have without issue used Newtonsoft (for jason serializing/de-serializing) as a COM object that is consumed by ms-access.
And given that naudio is managed code then I don't see why it would be an issue. Any other 3rd party .dll's you using here? As a quick test, I would set all projects to x86. You seem to "mention" that "some" of the COM object works, but just not all.
I wrote a Win32-DLL (with clr support in VS 2010/13, c++) as extension for another/old VB6 app and use the opensource-dll PDFSharp.
It works fine, but if the "PDFSharp.dll" removed from Directory the Application crashes if the program try to load my dll.
I want to include the Sharp DLL into mine, so that only one DLL is needed.
I tried to add it to resources, and load/catch the error during run time by
AppDomain^ root = AppDomain::CurrentDomain;
root->CurrentDomain->AssemblyResolve += gcnew ResolveEventHandler(MyResolveEventHandler);
in the first Function that the app calls, but my Problem is, the app/dll crashes before i can handle something.
ILMerge can't help, because it is a Win32/net(clr) DLL not a 100% NET-DLL.
C++/CLI mixed-mode DLLs have two sets of references: the native imports in the PE header, and the .NET assembly references. Problems finding the native imports will cause the symptom you observed, that loading the assembly fails early during load and cannot be intercepted and recovered.
It's not clear to me why the native dependency rules are applicable here. For a true native dependency that needs to be located using an alternate search order under your control, delay-loading could be applied. But that can't be used with a referenced .NET assembly.
In any case, the simplest fix is to not need a separate assembly at all. Your goal is single file deployment, and the ideal single file deployment scenario is when all the code is contained in a single DLL and you don't need to unpack a second file at runtime.
For pure .NET assemblies, there is an ILMerge tool that combines multiple DLLs into a single file. But your case has a C++/CLI mixed mode DLL, not pure MSIL.
Using multiple languages in a native program generally works a little bit differently. Instead of producing a complete executable from each toolset, native code standardizes an object file format (Windows .obj, Linux .o) which all the various toolsets know how to produce, and then the link step can link together object files from a variety of languages. The object files are often bundled into static libraries. (A static library is just an archive of object files, with a symbol index) Because the C++/CLI toolset is patterned on native C++, it uses this model as well.
The .NET version of this language-independent "object file" which can be further linked is a .netmodule file. Internally, it is a .NET assembly without a manifest. Functionally, it acts like a static library. And the C++/CLI link.exe can link together C# (and VB, and F#, etc) .netmodule static libraries together with the C++/CLI object files and static libraries, and native object files and libraries, when it creates the mixed-mode assembly.
This isn't the most straightforward process, because while it is supported by the underlying toolchains, the Visual Studio project options dialog boxes don't have a UI for either creating or consuming .netmodule static libraries.
For the C# side to produce a .netmodule, you should open your .csproj file and change the <OutputType> setting to module. Then reopen the project in Visual Studio and build as usual.
On the C++/CLI side, the project options dialog allows you to customize the compile and link command-lines. Change the linker command to include /link and the name of the .netmodule file.
If you've done it right, the C++/CLI linker will create a single mixed-mode DLL with all the types and code from both the C# and C++/CLI source files. And all the internal usage between C# and C++/CLI will be already resolved, so you won't have to worry about missing dependencies at run time. Well, at least not these dependencies; any you didn't choose to link in will still be handled normally.
I have a c++/CLI library that is in turn calling a c# library. That is fine, it is linking implicitly and all is good with the world. But for various reasons the libraries are not getting quite the prefect treatment by our automated build process, and the libraries are not finding each other unless we move the libraries to locations that we would rather not have them in, and would rather not fold into our build process.
It is suggested to me that we/I could write a post-build event that uses XCOPY. but lets say we don't want to do that.
Another suggestion is to explicitly load the dll. Windows says that to link explicitly "Applications must make a function call to explicitly load the DLL at run time." The problem is that Microsoft's example is not enough for my small mind to understand how to proceed with this idea. Worse, the only example I could find is out of date. Perhaps I am not using the right search terms but I am having difficulty finding more about it with google.
How do we explicitly Link a c++/Cli Library to a C# .dll?
----edit
OK, How do we explicitly Link a C++/CLI code, which exports a library using __declspec(), to a C# .dll.
There is no such thing as a "C++/CLI library", only assemblies are supported. There is no explicit or implicit linking, binding always happens at runtime. Assemblies are found at runtime by the CLR, the rules it uses to locate them are described in detail in the MSDN library.
Copying all dependencies into the same directory as the EXE is the sane way to go about it while you are developing the code. Well supported by build system, the C# and C++ rules are however different. C++ projects build to the solution's Debug directory, C# projects build to the EXE project's bin\Debug directory. So yes, altering a C++ project's Output Directory setting or copying files with a post build event is usually required to get everything together.
I have a ActiveX COM control and its source code. I wanted to change one of the method's input parameter, so I changed the IDL etc and generated the COM DLL and TLB.
But when I imported the COM DLL in a .NET project the method had retained its old signature. So I tried to generate the ActiveX DLL using AXIMP (though it is all the same, I wanted to give a try).
Still the method's signature did not change to what I changed to.
But when I generated the interop DLL using TLBIMP from the TLB file generated, the method signature changed correctly.
Where can I be wrong?
Thanks.
There are a lot of manual steps involved so it easy to miss one. It rather depends on how you imported the type library, there's more than one way to do it. If you picked the reference from the Add Reference + COM tab then the likely mistake is that you forgot to re-register the new COM server. Or you accidentally picked the old one instead of the new one, which can happen when you change the guids, like you should, and forgot to cleanup the old one. Cleaning up is pretty important and easily missed since it needs to be done before you rebuild the COM server. You can end up with a lot of garbage in the registry.
And yes, using Tlbimp.exe directly is the most reliable way to avoid accidents. Since you run it directly on the type library and don't use the registry at all.
A recipe for having the least possible amount of trouble could look like this:
Unregister the old COM server first by running regsvr.exe -u
Delete the old DLL and TLB files
Change the IDL to add your new method
Assign a new IID for the interface you changed
Assign a new CLSID for the coclass that uses the interface
Increment the library version
Change the name of the output DLL, favor including the major+minor version in the name
Build the new COM server
Register the server with regsvr32.exe
Run Tlbimp.exe to generate the interop library
Remove the reference to the old interop library in your .NET project
Use Add Reference + Browse to add the new interop library
Skipping any of these steps can invoke build trouble, registry pollution, DLL Hell and having an all-around lousy wrecked day without getting anything done.