installshield for class library COM interop project - c#

I have created a Class Library project with some COM visible types. The project is installed via InstallShield.
To ensure proper registration of my assembly, I have defined the following in the build events:
"%Windir%\Microsoft.NET\Framework64\v4.0.30319\regasm" /codebase /tlb
"$(MSBuildProjectDirectory)\$(OutputPath)$(AssemblyName).dll"
I am trying to use this tlb file in vba. When I build the solution it is creating the tlb file and I am able to add that tlb file as reference and use it in VBA.
I created an installer for this project and added .dll and .tlb files in the project files in InstallShield
I installed the library in another system, and the .dll and .tlb files were present in the installation folder (C:/program files/Project/Name.dll)
But when I refer to that tlb file, and then try to create an object from it, VBA throws a 429 can't create object error.
In the classlibrary project properties - Platform target, I have tried Any CPU as well as x64

Below you'll find an excerpt from my blog that may help. I'm not 100% certain that you're facing the same issue that I was, but you may be.
Go to the Project Assistant, and then to the Application Files screen.
You’ll need to take a couple of Actions here to properly create the
installer. Obviously, you’ll need to add the Primary Output. What’s
not so obvious is that you’ll also need to manually link the *.tlb
file by selecting installation folder, then the Add File button, and
pointing to the file in your \bin\Release directory.
The second not so obvious (and most frustrating) thing is you’ll need
to set the properties on the assembly correctly. So, right click on
the Primary Output, and select Properties. In the dialog, go to the
COM & .Net Settings tab. Once you’re there, use the settings below.
Extract COM Information
Scan at Build == Dependencies and Properties
Check the COM Interop box.
You’ll need to do the same for the *.tlb file, only don’t check
the COM Interop box this time.
Another possibility is that you have a class that should have the ComVisible attribute that isn't, or you're missing the com visible interface that VBA needs to connect to the server.
As was mentioned in the comments, you may also be missing a dependency that your *.dll needs to function. I ran into that issue once. Installshield only picks up the files that are directly inside of the bin\release\ directory. If one of your dependencies are creating a sub-directory, say bin\release\someDirectory\someFile.dll, then you will need a custom post-build on your project to copy the dependency into the release folder prior to the installer build.

Related

Packaging files into one executable (C#)

I developed a small project using C# and got everything working perfectly.
The only problem is that this app will be regularly sent via emails, therefore I'm trying to assemble all the files as one executable. The user will only have to open and see one executable, which will load the needed files and start the application.
The app does not use any external libraries. The only .dll file is for the IWshRuntimeLibrary.
The files that need to be assembled:
Note that I know that some files can be removed (svhost etc.). However this won't help because I'll still have more than one file. Also I've tried some free assemblers online but none of them worked.
In Solution Explorer, select the reference of Interop.IWshRunctime... and in the property window, change the value of Embed Interop Types to True.
This will not generate a separate dll for Interop Types.
PS: This is not a generic solution, but works with Interop Type only.
I've used https://github.com/Fody/Costura in the past. Nuget install Install-Package Costura.Fody (https://www.nuget.org/packages/Costura.Fody/)
Description about what it does from the source:
Take all assemblies (and pdbs) that have been marked as "Copy Local" and embed them as resources in the target assembly.
Actually you are looking for a method to merge some assemblies and resources into one executable file.
Custora.Fody, ILMerge, Obfuscators with assembly merging feature are some examples that can be used for this purpose.
You can find some answers here:
Embedding DLLs in a compiled executable
How to merge multiple assemblies into one?
List of obfuscators for .NET
If this is not about security reason, I would create the directory structure as follow:
- root
└ Startup.bat
└ lib
└ DiagnosticsSwitch.exe
└ DiagnosticsSwitch.exe.config
└ DiagnosticsSwitch.exe.manifest
└ Interop.IWshRuntimeLibrary.dll
And inside the Startup.bat
"lib/DiagnosticsSwitch.exe"

How do I resolve "Please make sure that the file is accessible and that it is a valid assembly or COM component"?

I am building a project with OpenCV in C#. It requires a dll file called cvextern.dll. but, when adding this file as a reference, this message appears :-
a reference "cvextern.dll" can't be added, Please make sure that the file is accessible and that it is a valid assembly or COM component.
I get tired from searching, I spent the past 2 days in searching for a solution for that problem
the file is a native DLL which means you can't add it to a .NET project via Add Reference... you can use it via DllImport (see http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.aspx)
In my case I had to register the .dll.
To do so, open cmd.exe (the console) with admin rights and type:
regsvr32 "foo.dll"
Make sure the required dlls are exported (or copied manually) to the bin folder when building your application.
'It' requires a dll file called cvextern.dll . 'It' can be either your own cs file or some other third party dll which you are using in your project.
To call native dlls to your own cs file, copy the dll into your project's root\lib directory and add it as an existing item. (Add -Existing item) and use Dllimport with correct location.
For third party , copy the native library to the folder where the third party library resides and add it as an existing item.
After building make sure that the required dlls are appearing in Build folder. In some cases it may not appear or get replaced in Build folder. Delete the Build folder manually and build again.
I had the same program, I hope this could help.
I your using Windows 7, open Command Prompt-> run as Administrator. register your <...>.dll.
Why run as Administrator, you can register your <...>.dll using the run at the Windows Start, but still your dll only run as user even your account is administrator.
Now you can add your <...>.dll at the Project->Add Reference->Browse
Thanks
Look here for the answer by TheMattster. I implemented it and it worked like a charm. In a nutshell, his solution suggests to add the COM dll as a resource to the project (so now it compiles into the project's dll), and upon the first run write it to a file (i.e. the dll file I wanted there in the first place).
The following is taken from his answer.
Step 1) Add the DLL as a resource (below as "Resources.DllFile"). To do this open project properties, select the resources tab, select "add existing file" and add the DLL as a resource.
Step 2) Add the name of the DLL as a string resource (below as "Resources.DllName").
Step 3) Add this code to your main form-load:
if (!File.Exists(Properties.Resources.DllName))
{
var outStream = new StreamWriter(Properties.Resources.DllName, false);
var binStream = new BinaryWriter(outStream.BaseStream);
binStream.Write(Properties.Resources.DllFile);
binStream.Close();
}
My problem was that not only I had to use the COM dll in my project, I also had to deploy it with my app using ClickOnce, and without being able to add reference to it in my project the above solution is practically the only one that worked.
In my case I also have unmanaged dll's (C++) in workspace and if you specify:
<files>
<file src="bin\*.dll" target="lib" />
</files>
nuget would try to load every dll as an assembly, even the C++ libraries! To avoid this
behaviour explicitly define your C# assemblies with references tag:
<references>
<reference file="Managed1.dll" />
<reference file="Managed2.dll" />
</references>
Remark: parent of references is metadata -> according to documentation
https://learn.microsoft.com/en-us/nuget/reference/nuspec#general-form-and-schema
Documentation: https://learn.microsoft.com/en-us/nuget/reference/nuspec

C# plugin system design

So I am creating a plugin system for my app.
I have the following components:
1) Main Application
2) PluginInterface.dll
3) Plugin(s).dll
The problem now is that, when I create my plugins and compile them, there are more then just the Plugin.dll file. It has other required files in the Release directory such as the PluginInterface.dll that it uses, an xml configuration file, etc.
So how can I make it so that it is just a single dll file that user can drop into a plugin directory?
OR
do you think it's better to have the plugins be a folder? then, i have to scan all the folders for the right DLL...
The Managed Extensibility Framework is designed for plugin architectures. Before you go too far down your current path, check it out. It might serve you better.
When you compile your plug-in project, right-click on the references to the DLLs you are seeing and select properties. In the proepties set the "Copy Local" property to "false". Make sure that these DLLs are part of your main application, otherwise the code will fail when it can't find code that depends on it.
If you want to do that when compiling your solution you should create a post build event (Project Properties -> Build Events) to copy only the required files to the plugin directory.
You could also change the OutputPath of you project and use the option "Copy Local" to "false", but you'll not have the same level of control as by creating a build event.

Adding a dll file to a C# project

It's a beginners question, but...
Image of dll reference and dll included in project file http://a3.vox.com/6a00c2251e5b66549d00e398ca81eb0003-pi
If you look at the image above, there is the "Bass.Net" dll added as reference and also directly as file in the project.
Can someone tell me what's the point of doing that?
No reason, really. It could be that Visual Studio is set to display files not in the project (hard to tell from the picture) and the dll's happen to be in the main directory. The text is pretty clear that the extra files are
bass.dll
bassenc.dll
lame.exe
The .net one happens to be with the others in the same directory and you need to add it as a reference.
Within Windows, a DLL is a dynamic link library, which packages a set of programmatic functionality together. In this example, bass.dll exposes the features and functionality relevant to audio processing through this file (and any files it depends on). In order to use this functionality, you need the reference in the solution, so that Visual Studio can link it at compile time. The DLL will then typically be copied to your output directory when the application is built.
That's all that is necessary to get the code to work properly, the rest is really just preference or convention. Some people prefer to have all the files that exist in the project directory in the solution, so that the Solution Explorer reflects the file system. Typically you will want to have libraries your application depends on somewhere in your solution directory hierarchy so that the entire application is packaged together (making source code control use easier, for instance). You won't want to put this library in the BIN directory or any directory that Visual Studio generates, though, to avoid accidental deletions. In any event, having the reference is the important part, the file being in the project or solution is not necessary.
Typically, you'll want to keep external libraries out of your source directories, though, so I wouldn't actually recommend this structure. I tend to use a structure like this, but, again, this is all preference:
Source: Source code and project files
Libraries: DLLs
Support: Miscellaneous code or projects, but not actually part of the application (perhaps deployment scripts)
Having those in your project and output directory allows the final executing code to reference them without any issues running on different machines.
It sounds as it they put the reference dlls in the project directory, reference them from there, and also include them in the project. That way, when the project directory is copied, the reference dll will be copied with it. Additionally, if the reference dll is missing, the project will complain in Visual Studio.
If an assembly (Bass.Net.dll in your case) contains classes you want to use, you must add a reference to that assembly to your project.
No point the best thing to do is get all your dependenicies and store them in a seperate folder and only reference them do not copy them to your solution ;)
It's really hard to guess why someone else did something, but if I really had to guess, I'ld say that the guy thought to embed the necessary dlls as resources to be sure it was availale to the application. I have seen this technique used to embed fonts or sounds and am not sure if it works at all with dlls; but it's just a guess.
Of course the best way to be sure the files were available would have been to create a deployment project, with Visual Studio or some other installation tool loke Wise or InnoSetup, just to name a few.
This actually might be a good idea in a lot of circumstances. In my opinion their are 3 types of dependencies
Assemblies from the .Net standard library. Never include those locally.
Assemblies that you expect other developers to install as part of an MSI or exe setup package. This usually means their strongly signed and have a copy in the GAC.
Assemblies that you don't expect other developers to install via an MSI or exe installer. Maybe because you have a third party or in house library not in the GAC.
In the third case, the simplest thing to do is store a copy of the DLL in the source repo.

System.Addin & ClickOnce

I have a annoying build process from using System.Addins API with ClickOnce. Using System.Addins requires a specific directory structure, and the main project does not reference the adapters, view, and contract directly, which doesn't work well with the ClickOnce architechture.
The annoying part with the build process is that I have to copy, via post build event, the .dlls from the add-in components into the directory of the main app project, then reference those files manually from the main project, so that ClickOnce will include them. Firstly, this takes 2 iterations of build to get it to build correctly, secondly, it interferes with source control (I have to exclude the copied add-in dll files from source control or any changes made to them would require checkout).
So, my question is, is there a way around this hack? Something more elegant?
I can't fully answer your question, but it appears you are creating ClickOnce deployments through Visual Studio. I would ditch that method and use MageUI instead. It's a stand-alone executable that can be found in the framework SDK that will generate your application and deployment manifest files. It comes with a gui version (mageui.exe) and a command line version (mage.exe).
Mage may not get rid of your post-build event but it should do away with having to reference the files to get ClickOnce to see them.
Thanks for your input, I am currently doing it the way you mentioned; creating the folder in my project, and include the dlls that I need. It works, but it's an ugly solution, and it interferes with Source Control.
I'm aware of the limitations of ClickOnce, I was hoping there may be a way around it. For example, I read somewhere that I can use deployment projects to create the appropriate dependencies needed in a specific structure. The problem with that is once it is deployed to the public, there is no easy way (within ClickOnce) to update those dependencies.
The solution I use is to have a single output folder for all projects. Every project puts it's own files in the correct subfolder. The application bootstrapper project puts his dlls also in the output (root) folder. When you then create a click-ones for the bootstrapper, it will take all the content from the output folder.
The hardest part is to actually get all the dll's in the right place (and have every dll only once)
I solved this problem by adding the pipeline assemblies as content into the main solution structure.
To do this, change the output folder from (/bin/debug /bin/Release) to something else. I used ../lib otherwise you would get a visual studio cannot reference this file error.
Create the pipeline folders in your main solution
\AddInSideAdapters
\AddInViews
\Contracts
\HostSideAdapters
Right click on each of the folders and click "add existing item" change to view all files and then browse to your ../lib (or wherever you have the output set) and then pull down the add button (click the down arrow) and click "Add as a Link".
Right click on each file and set it to Content.
This will create a refresh file pointed to your assemblies and they will be included into the clickonce manifest.
ClickOnce do not let you install the software where you want. It will install the binary and dlls in the documents and settings. You can in your project properties go in the Publish tab and select Application Files to select additional file to Include. If the System.Addings require dll in a specific folder relatively to your assembly, you might just create the folder in you project and includes from here the dlls. This might works. If not, I do not have "hack" or other solution, clickonce is great but limited with some functionalities.

Categories

Resources