Using undocumented native code APIs to install items into the GAC - api

I'm working on a project whose setup uses the APIs documented in Microsoft Knowledge Base article KB317540 to install and uninstall assemblies into the GAC. The KB article states:
SUMMARY
The native code application
programming interfaces (APIs) that
allow you to interact with the Global
Assembly Cache (GAC) are not
documented in the .NET Framework
Software Development Kit (SDK)
documentation.
MORE INFORMATION
CAUTION: Do not use
these APIs in your application to
perform assembly binds or to test for
the presence of assemblies or other
run time, development, or design-time
operations. Only administrative tools
and setup programs must use these
APIs. If you use the GAC, this
directly exposes your application to
assembly binding fragility or may
cause your application to work
improperly on future versions of the
.NET Framework.
The GAC stores assemblies that are
shared across all applications on a
computer. The actual storage location
and structure of the GAC is not
documented and is subject to change in
future versions of the .NET Framework
and the Microsoft Windows operating
system.
The only supported method to access
assemblies in the GAC is through the
APIs that are documented in this
article.
Most applications do not have to use
these APIs because the assembly
binding is performed automatically by
the common language runtime. Only
custom setup programs or management
tools must use these APIs. Microsoft
Windows Installer has native support
for installing assemblies to the GAC.
For more information about assemblies
and the GAC, see the .NET Framework
SDK.
Use the GAC API in the following
scenarios: When you install an
assembly to the GAC. When you remove
an assembly from the GAC. When you
export an assembly from the GAC. When
you enumerate assemblies that are
available in the GAC. NOTE:
CoInitialize(Ex) must be called before
you use any of the functions and
interfaces that are described in this
specification.
What are the pros and cons of this technique? Are these APIs safe to use? Anyone out there using them? If so, why?

Why not just create a Windows Installer package? See Demystifying the .NET Global Assembly Cache. Quoting:
Developers of Windows Installer
packages can install assemblies to the
GAC using Microsoft Windows Installer
2.0. This is the preferred way for installing such shared assemblies and
should be the only way shared
assemblies are installed on non
development machines.

It says, "Only administrative tools and setup programs must use these APIs."
There are tools (e.g. command-line tools) to work with the GAC. Why not invoke these executables, instead of using these APIs directly?

Related

.NET Core 2.1 How to provide nuget packages to a heavily modularized deployment with shared runtime

Setup:
single offline (blocked from inet) server
multiple applications
apps load .net core assemblies (plugins with their own assembly or nuget deps) at runtime through reflection
Problem: What is the most efficient way to deploy the application set?
Currently I publish application per application, so that all required nuget packages and assemblies are available. However, this means the complete .net core and asp.net assembly set is copied over multiple times.
To have a shared deployment with an installed .net core runtime or sdk, there does not seem to be an easy way to make the required nuget packages available on an offline machine?
Any suggestions on the best-practices setup for these kind of deployments?
Cheers.
Sounds like you could use the global packages folder.
If your projects use PackageReference they consume their dependencies directly out of that folder instead of copying them locally, so if you're worried about disk space that would be a way to avoid duplication if that's what you're really worried about.

How to create dll inclusive msi installer package

I've created a program and would like to release it, but am currently struggling with dll dependency issues. How can I create a msi installer package that will properly install .dlls? Every solution I've found online so far has created msi packages that only include the exe.
Short Answer: Generally, the most common runtimes are: Java, Visual Studio C/C++ Runtime, .NET Framework. Try installing these on a clean virtual and try launching your application. Debugging application launch check-list.
Modern Deployment: Many Microsoft runtimes that we used to deploy are now part of Windows. An exception is the Visual Studio C/C++ runtimes. I am not sure why they are not just included in Windows at this point. In general you should not pick single dll files to deploy, you need to locate a merge module, a setup.exe or an MSI to deploy the runtime. Commercial tools have features to help you download such bundles.
Setup: The basic, general steps to create a setup are described here: How to create a windows installer for multi language program with outside dependencies?
Specific Runtimes: One can generally determine runtime requirements by looking at the application files (experience - trained eye), looking at the application GUI (visual clues), checking dependencies using dependency scanner tools, talking to the developers of the application, checking file properties of files you find to depend upon (Company name is a good clue), etc... Then you verify and test this on a clean, virtual machine. You keep installing runtimes manually until your application works. In the section "The Complexity of Deployment" here you can find a listing of common runtimes and technologies.

C++/CLI Support in .Net Core

Our project structure is like,
native.dll :- This contains pure native code written in c\c++.
This native.dll exposes some functions using *def file.
Wrapper Library(wrapper.dll compiled with .Net framework v4.0) :-
In order to use functionality of native.dll, a Wrapper lib(wrapper.dll)
is written in C++\CLI using :clr\oldsyntax. This wrapper has all
code of Interoperability and Marshalling.
Application(Console App v4.0) directly uses wrapper.dll to use functionality provided
by native.dll.
Now this project needs to run in .Net Core. This means we will have an
.Net Core application that will reference wrapper.dll that in turn will refer
native.dll.
I know this will not directly work. But the issue is whether .Net Core(CoreCLR) supports
C++\CLI (clr\oldsyntax) runtime environment ?
If no, what can be the possible solutions to this application work ?
whether .Net Core(CoreCLR) supports C++\CLI (clr\oldsyntax) runtime environment ?
As far as I know there is no plan to support C++/CLI with .NET Core.
If no, what can be the possible solutions to this application work ?
You can (should) provide a C API. Mono e. g. supports P/Invoke and .NET Core also supports P/Invoke (see also this Stack overflow question and this DllMap related ticket).
Update (2022-09-02): This answer is from 2016. See the other answers (e.g., this) for what is possible with recent .Net Core versions.
Officially announced eventually...
(next wish... support linux # .Net 5 ^^)
https://devblogs.microsoft.com/cppblog/the-future-of-cpp-cli-and-dotnet-core-3/
C++/CLI will have full IDE support for targeting .NET Core 3.1 and higher. This support will include projects, IntelliSense, and mixed-mode debugging (IJW) on Windows. We don’t currently have plans for C++/CLI for targeting macOS or Linux. Additionally, compiling with “/clr:pure” and “/clr:safe” won’t be supported for .NET Core.
The first public previews for C++/CLI are right around the corner. Visual Studio 2019 16.4 Preview 1 includes an updated compiler with “/clr:netcore”
Updat: From replied of origin url:
"We are still working on the IDE and MSBuild integration, so I can’t share a sample project quite yet. Once it’s available, likely with 16.4 Preview 2 or 3"
(16.4 Preview1 cannot create C++/CLI with .NetCore project.)
191015
16.4 Preview2 Released.
I'v tried asp.net core 3.1 with c++/CLI dll, it works.
(need set plateform to x64 both asp.net core and c++/CLI dll)
.net Core team will only commit (now?) to supporting C++/CLI for Windows only.
The intention was to deliver it for .net Core 3.0. While I haven't found explicit mention of it yet in the release notes, C++/CLI support was a prerequisite for delivering WPF (windows-only), which is now supported in .net Core 3.0.
Support mixed-mode assemblies on Windows - #18013
This issue (#18013) will track progress toward supporting loading and running
mixed-mode assemblies on CoreCLR. The main goal is to provide support
for WPF and other existing C++/CLI code on .NET Core. Some of the work
will be dependent on updates to the MSVC compiler.
The github issue (#659) mentioned above by #Tomas-Kubes, Will CoreCLR support C++/CLI crossplat? - #659, is about cross-platform C++/CLI.
BTW, I am getting compiler warnings on "clr\oldsyntax" with VS2017/.net-4.7. So this compiler flag is already deprecated.
UPDATE: This isn't coming till .Net Core 3.1
Another potential solution (though obviously quite a difficult task) if you want to stick with C++ (i.e. expose an OO interface to .NET) might be to have a look at CppSharp from the mono project. It is able to expose native C++ code through an automatically generated C# wrapper. It supports Windows, Linux as well as OSX. However, I don't know if the generated code can be compiled to a .NET standard target (didn't try to). I can only suppose it would because the generated code does not use any fancy API (it is basically interop and marshalling code); and, by the way, it is also possible to customize the generation process (although, once again, probably not an easy task).
For those who are looking at this for general .Net Core stuff without specific clr parameters (as this is a high result on google) Microsoft have written a guide on how to port C++/CLI to .Net Core:
https://learn.microsoft.com/en-us/dotnet/core/porting/cpp-cli
Port a C++/CLI project
To port a C++/CLI project to .NET Core, make the following changes to the .vcxproj file. These migration steps differ from the steps needed for other project types because C++/CLI projects don't use SDK-style project files.
Replace <CLRSupport>true</CLRSupport> properties with <CLRSupport>NetCore</CLRSupport>. This property is often in configuration-specific property groups, so you may need to replace it in multiple places.
Replace <TargetFrameworkVersion> properties with <TargetFramework>netcoreapp3.1</TargetFramework>.
Remove any .NET Framework references (like <Reference Include="System" />). .NET Core SDK assemblies are automatically referenced when using <CLRSupport>NetCore</CLRSupport>.
Update API usage in .cpp files, as necessary, to remove APIs unavailable to .NET Core. Because C++/CLI projects tend to be fairly thin interop layers, there are often not many changes needed. You can use the .NET Portability Analyzer to identify unsupported .NET APIs used by C++/CLI binaries just as with purely managed binaries.
Build without MSBuild
It's also possible to build C++/CLI projects without using MSBuild. Follow these steps to build a C++/CLI project for .NET Core directly with cl.exe and link.exe:
When compiling, pass -clr:netcore to cl.exe.
Reference necessary .NET Core reference assemblies.
When linking, provide the .NET Core app host directory as a LibPath (so that ijwhost.lib can be found).
Copy ijwhost.dll (from the .NET Core app host directory) to the project's output directory.
Make sure a runtimeconfig.json file exists for the first component of the application that will run managed code. If the application has a managed entry point, a runtime.config file will be created and copied automatically. If the application has a native entry point, though, you need to create a runtimeconfig.json file for the first C++/CLI library to use the .NET Core runtime.
There are some more nuances but these are the actual steps to port

Unable to resolve assemblies that use Portable Class Libraries

I'm having a problem with assembly resolution on an end-user machine and I believe it's related to using Portable Class Libraries....
I have a .NET 4.0 application that was originally written in Visual Studio 2010. Recently we upgraded to Visual Studio 2012 and we've created a few projects that are Portable Class Libraries. I don't believe we need these features now, but we're also building a Windows 8 Store application that might benefit from these libraries.
When I compile my project, what exactly does the portable library feature do? I expect that it allows me to run it on different frameworks without modification or recompiling.
When I look at the library in reflector dotPeek it shows the Platform attribute as:
.NETPortable,Version=v4.0,Profile=Profile5
And the references seem 2.0-ish:
mscorlib, Version=2.0.5.0
System, Version=2.0.5.0
System.Runtime.Serialization, Version=2.0.5.0
When I run the application on this end-user's machine, I see an error in the log file:
Could not load file or assembly, 'System.Core, Version=2.0.5.0...'
Googling System.Core 2.0.5.0 seems to refer to SilverLight -- which appears to be one of the targeted frameworks.
This machine does not have Visual Studio installed, but has .NET 4.0 (4.0.3 update)
Is there something I should be doing differently to compile, something I should investigate in my dependencies or something I should be looking to install on the end-user machine? What does the 2.0.5.0 refer to?
For .NET 4, you need an update (KB2468871) for Portable Class Libraries to work. From the KB Article:
Feature 5
Changes to the support portable libraries. These changes include API
updates and binder modifications. This update enables the CLR to bind
successfully to portable libraries so that a single DLL can run on the
.NET Framework 4, on Silverlight, on Xbox, or on the Windows Phone.
This update adds public Silverlight APIs to the .NET Framework 4 in
the same location. The API signatures will remain consistent across
the platform. All modifications are 100 percent compatible and will
not break any existing code.
Also see the "Deploying A .NET Framework App" section of the MSDN Portable Class Library Documentation.
EDIT: Actually, if the machine has .NET 4.0.3 installed as you mention, that should be sufficient. Can you double-check to make sure that it is actually installed?

Wix: COM registration with heat or ComPlusExtension?

We build our setups with Wix. We have a mix of native and .NET components, and use COM for interop.
Until now, I have used heat.exe to generate wix fragments for installing .NET assemblies and registering them as COM servers. The wix fragment created by heat takes care of writing the COM related registry entries.
However, somebody just told me that you can also use the ComPlusExtension to do COM registration. The documentation I can find regarding this "ComPlus" stuff is quite cryptic.
Is this ComPlusExtension a valid alternative to the heat.exe approach for registering .NET assemblies as COM components? Are there any differences or gotchas I should be aware of?
I guess you could register as COM+ it isn't really the same thing and means the components would then be running out of process with respect to your calling process (they runs as dllhost.exe IIRC). If you want to see how to use the COM+ extensions checkout the WiX Tutorial. Personally I would stick to regular COM or if you can Registration Free COM.
COM+ ( aka Component Services ) is cryptic. That's why Microsoft invented .NET Remoting, WebServices and WCF. :-)
I havn't used the WiX Complus extension but I would imagine it's not a proper substitute for actually registering the COM server. COM Plus just makes it available for invocation on other machines as a package / application. (See DCOMCNFG.EXE ). I know I did this stuff about 5 years ago and I would lay the DLL down, register it using MSI tables and then call out to a custom action that would set the rest up.