Referencing Shell32.dll? - c#

I don't have .NET 4.5 to unzip zip files, so I'm using Shell32 like this. But when I reference the dll like this:
csc.exe /r:"C:\Windows\System32\shell32.dll" ...
I get this error:
fatal error CS0009: Metadata file 'c:\Windows\System32\shell32.dll' could not be opened -- 'An attempt was made to load
a program with an incorrect format. '
Update: Without Visual Studio, just csc.exe.

Shell32 is a COM server that you can use in your C# program. You however have to generate an interop assembly first to convert the type library inside shell32.dll (same idea as .NET metadata) to declarations that the CLR can understand. Either by running Tlbimp.exe or, much simpler, by adding a reference to the DLL in the IDE.
As long as you do this from the command line and don't use msbuild to get a .csproj project file compiled then you have to do the same thing that msbuild does, run tlbimp. For shell32.dll this only has to be done once and you can check-in the interop library in source control so you don't have to do it again. Use /r on the interop library.
Using the IDE or MSBuild.exe are of course the wise choices. Also helps you fall in the pit of success, you really want to use the Embed Interop Types feature so you don't need the interop assembly at runtime and don't have to deploy it. Looking at the build commands generated by MSBuild is useful.

Possibly because you are trying to reference it like a .NET assembly.
I would try to include the assembly using the /lib: argument instead as per...
/lib:dir1[,dir2] Compiler option.

Related

How to publish a COM-Visible library created with C#

I have to create a COM library from a C# project, but I'm pretty stuck with referencing the external libraries.
I have set "Make assembly COM-Visible" in the project's properties and when I build it creates the dll and it puts all required dll's in the bin/Release directory.
Libraries used
All libraries are .NET imported with NuGet or System libraries.
Creating the .tlb file
When I run a command to create a .tlb file, it is created, but it also shows a warning:
tlbexp.exe "MyLib.dll"
TlbExp : warning TX00131175 : When cross-compiling, all type library references should be included on the command line to ensure the correct bit-specific type libraries are loaded.
Assembly exported to 'C:\Workspace\MyProject\bin\MyLib.tlb'
It looks like this library is ready to be shipped, but I'm wondering if I can just ignore the warning.
And, what is the best way to ship this COM-Visible library?
Can I just ship the entire bin/Release directory, or should I use another method?
Well the .tlb is needed just to reference your library from a development tool ( for example Visual C++ ), referencing correctly does not mean that program, after compiling correctly, will work. This because you need to proper install the dll on the target machine, typically you need to xcopy the dll with all dependencies, and then use regasm.exe ( specifying the /CODEBASE flag I suggest, so you can point surely the dll you want on your file system ). Of course even proper Framework has to be installed too.

A reference to .dll could not be added. Please make sure that the file is accessible, and that it is a valid assembly or COM component

Ok now i will try to explain my problem as much as possible. I want to use popular compression algorithm 7zip at my c# project
There is already NuGet package for 7zip
Now when i install 7zip page https://www.nuget.org/packages/SevenZipSharp/0.64.0 it installs fine however it gives error when i try to run
An unhandled exception of type 'SevenZip.SevenZipLibraryException' occurred in SevenZipSharp.dll
Additional information: Can not load 7-zip library or internal COM error! Message: failed to load library
So i decide to add dll file manually and i get this error below
---------------------------
Microsoft Visual Studio
---------------------------
A reference to 'D:\51_doktora tez projesi\program_crawler\doktora_tez_projesi_crawler_program\ExternalDLLs\7z_9_38_2015_01_03.dll' could not be added. Please make sure that the file is accessible, and that it is a valid assembly or COM component.
---------------------------
OK
---------------------------
Ok but i found a solution and it works that way
First install nuget package
And before start calling functions set path
SevenZip.SevenZipExtractor.SetLibraryPath("SevenZipSharp.dll");
SevenZip.SevenZipCompressor.SetLibraryPath("SevenZipSharp.dll");
Ok second question which is also interesting
I wanted to use latest version of 7zip DLL file. So downloaded it from official website : https://sourceforge.net/projects/sevenzip/files/7-Zip/9.38/
Downloaded MSI installed and got 64bit dll file. However when i try to reference this file, it fails with error message above: Please make sure that the file is accessible, and that it is a valid assembly or COM component.
However the trick works again
I install NuGet 7zip package. Then before calling functions i set these 2 lines of code and it uses latest version of DLL file
SevenZip.SevenZipExtractor.SetLibraryPath("ExternalDLLs/7z_9_38_2015_01_03.dll");
SevenZip.SevenZipCompressor.SetLibraryPath("ExternalDLLs/7z_9_38_2015_01_03.dll");
So i am looking for answers why all these happens? Why i can not directly add as a reference the DLL file however the trick works?
windows 8.1 64bit, Visual Studio 2013 update 3 WPF application
Part of your problem most likely stems from the fact that SevenZipSharp is merely a wrapper for the 7z.dll, which to the best of my knowledge is a c++ dll. The project page, for SevenZipSharp, also mentions that any compatible dll can be used and needs to be specified:
SevenZipSharp requires a 7-zip native library to function. You can specify the path to a 7-zip dll (7z.dll, 7za.dll, etc.) in LibraryManager.cs at compile time, your app.config or via SetLibraryPath() method at runtime. + "7z.dll" is the default path. For 64-bit systems, you must use the 64-bit versions of those libraries.
7-zip ships with 7z.dll, which is used for all archive operations (usually it is "Program Files\7-Zip\7z.dll"). 7za.dll is a light version of 7z.dll, it supports only 7zip archives. You may even build your own library with formats you want from 7-zip sources. SevenZipSharp will work with them all.

how to merge dll's into one dll

Using c# in visual studio 2012, I've created a class library FileTube.dll
It uses 3 other dll's.
I want to make a single dll to contain those thus I can publish my library via nuget.
I have tried 3 approaches all failing:
approach 1: In vistual studio, I set the "Embed Interop Assembly" to true, I get this error:
Error 2 Cannot embed interop types from assembly 'DiffieHellman.dll' because it is missing the 'GuidAttribute' attribute DiffieHellman.dll
approach 2: I used ILMergeGUI. It generated the code to use for ILMerge which fails with the error:
Object reference not set to an instance of an object.
Here is the command:
"C:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe"
/ndebug
/copyattrs
/targetplatform:4.0,"C:\Windows\Microsoft.NET\Framework64\v4.0.30319"
/out:"C:\temp\z.dll"
"C:\\FileTube\TestApp\bin\Debug\FileTube.dll"
"C:\\FileTube\TestApp\bin\Debug\DiffieHellman.dll"
"C:\\FileTube\TestApp\bin\Debug\Org.Mentalis.Security.dll"
"C:\\FileTube\TestApp\bin\Debug\Tamir.SharpSSH.dll"
approach 3:
I followed this tutorial
to use reflection to include the dll assemblies. The difference is that the tutorial has a main executable and is including dll in the executable while I'm trying to include dlls in my dll. so I added the reflection code to the class constructor of my main dll. It compiles but it would fail if I rename that external dll meaning that it's not really loading it.
Any ideas?
You have several options:
use ILMerge (free)
For howto see here and here
OR
use some tool like SmartAssembly (commercial)
it can embed and merge among other things (no need to change your source code)
OR
code that yourself in less than 10 lines (free but minimal source code change)
mark all needed dependencies as "embedded resource" - this way they are included in the EXE file... you need to setup an AssemblyResolve handler which at runtime reads from Resources and returns the needed DLLs to the .NET runtime...
(Answer copied from: How to merge multiple assemblies into one?)

How to register type library file (.tlb) with InstallShield LE in Visual Studio 2012 C#

I've been creating various plugins for an application that requires me to produce a .tlb file. In the past, it has simply been a case of configuring my project's build properties to 'Register for COM interop' thereby producing a .tlb file along with my output dll. Previously, when using the Visual Studio 2010 installer projects template, this would always correctly register .tlb during installation on the target machine.
I've recently attempted to make the switch to Visual Studio 2012 and use the InstallShield LE project to produce my installer, but it doesn't seem to register the type library during the install, nor does the express addition seem to allow me to manually register via the cmd-line regasm route - or at least it's not that obvious to me.
In the InstallShield project options I had to manually add the .tlb application file (from the build's \release folder) to the list of files to be included in the installer as it doesn't seem to get included along with the files produced by the project output or content options. In the .tlb file's 'COM & .Net Settings' properties, I have it configured to Registration Type: 'Extract COM Information' and have enabled 'COM Interop'.
What am I missing?
Try this thread for a good technical description: Are *.tlb files ever used at runtime?
In most cases I believe the *.tlb file is not needed because it is already compiled into most binaries regardless of whether it is an exe file or a dll, but .NET Interop is a lot more complex and as the other thread explains the *.tlb file can be needed to deal with advanced communication issues between threads and processes - something that I incidentially had forgotten.
When implementing a setup I have never had the need to register a *.tlb file by itself, it has been enough to register the corresponding binary (exe/dll), but this all depends on the use cases for the product.
Be aware that the way Installshield is registering for COM Interop is not always the best option as far as I recall. I am not sure exactly what they are doing, but I would check and compare with a normal regasm.exe registration:
http://msdn.microsoft.com/en-us/library/tzat5yw6(v=vs.110).aspx . And read the linked thread (Are *.tlb files ever used at runtime?) carefully on the issues of proxies, stubs and marshalling in case you need these features supported.
Here are some further links with concise information on COM/DCOM:
Contents of a Type Library:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms221355(v=vs.85).aspx
COM, DCOM, and Type Libraries: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366757(v=vs.85).aspx
Files Generated for a COM Interface: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366830(v=vs.85).aspx

How do you manage generated code in Visual Studio - in particular, creating DLLs from .idls

I'm trying to add a generated COM interop assembly project to my solution, and the only solution I could come up with feels really nasty.
I created a .net dll project, removed all .cs files from it and then created the following post-build event:
call "$(DevEnvDir)..\tools\vsvars32.bat"
midl.exe $(ProjectDir)relative-path-to-my-idl\MyComName.idl /tlb MyComName.tlb
tlbimp.exe /keyfile:path-to-my-key\k.snk MyComName.tlb
Essentially, I first create an empty DLL, then overwrite it with a real interop DLL. And there's no dependency management here - it's created every time.
Is there a better way to do this?
The MIDL compilation can be handled by making the COM interop project a managed C++ project (instead of a C# project) then adding the idl and h to the project as regular source files.
You can overcome the dependency problem by using MSBuild tasks directly instead of a PostBuild batch file, which line up nicely with the MSBuild dependency system.
However, why are you generating the file manually from an idl? When I need COM interop, I just import it and put the generated assembly (*.Interop.dll) into version control. This way, you always have the version you need and it's already ready to use, and Visual Studio can find the interop DLL before the first build, i.e. Intellisense is there right from the beginning.
Now some people won't like to check in a binary file, which I typically agree with, but well, if it works... :)
Of course, my method won't work if building the COM server is part of building the solution. In this case, just try to put the generation into the MSBuild script to get rid of the dependency thing, unless Visual Studio accepts a reference to a solution-internal non-.NET-COM project.

Categories