Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

dscom, a toolkit for creating and registering type libraries (tlb) and additional interop helper methods for COM

License

NotificationsYou must be signed in to change notification settings

dspace-group/dscom

Repository files navigation

Nuget:Cli
Nuget:Lib
Nuget:LibBuildTask

ReleaseLicensedSPACE

Unit TestsExample TestsCode Style Check

The command line clientdscom is a replacement fortlbexp.exe andRegAsm.exe.
Among other things, you can create or register TLBs from .NET assemblies.

ThedSPACE.Runtime.InteropServices library contains various classes and methods for COM.
It can be used innet5+ or innet48 projects.
With the library you can register assemblies and classes for COM and programmatically generate TLBs at runtime.

ThedSPACE.Runtime.InteropServices.BuildTasks library provides build tasks which can be used to automatically generate TLBs at compile time.

Introduction

Fortunately, .NET still supports COM, but there is no support for generating TLBs.
From the Microsoft documentation:

Unlike in .NET Framework, there is no support in .NET Core or .NET 5+ for generating a COM Type Library (TLB) from a .NET assembly.

https://docs.microsoft.com/en-us/dotnet/core/native-interop/expose-components-to-com

One main goal is to makedscom behave liketlbexp.exe.

Also, some classes are missing in .NET 5+ that were available in the full framework.This is wheredSPACE.Runtime.InteropServices may be able to help.

Command Line Client

The command-line interface (CLI) tooldscom is a replacement fortlbexp.exe,OleView (View TypeLib) andRegAsm.exe.

It supports the following features:

  • Convert an assembly to a type library
    • Optionally embed the generated type library into the converted assembly
  • Convert a type library toYAML file
  • Register a type library
  • Unregister a type library
  • Embeds a type library into an existing assembly
  • Register an assembly (regasm.exe)
  • Unregister an assembly (regasm.exe)

Installation

The installation is quite simple. You can usedotnet tool to install thedscom binary if you want to create a 64Bit TLB.

dotnet tool install --global dscom

Here you can find all available versions:
https://www.nuget.org/packages/dscom/

Alternatively you can download dscom.exe from the relase page.
https://github.com/dspace-group/dscom/releases

Usage

Usedscom --help to get further information.

c:\> dscom --helpDescription:  dSPACE COM toolsUsage:  dscom [command] [options]Options:  --version       Show version information  -?, -h, --help  Showhelp and usage informationCommands:  tlbexport<Assembly>                           Export the assembly to the specifiedtype library  tlbdump<TypeLibrary>                          Dump atype library  tlbregister<TypeLibrary>                      Register atype library  tlbunregister<TypeLibrary>                    Unregister atype library  tlbembed<SourceTypeLibrary><TargetAssembly>  Embeds asourcetype library into a target file  regasm<TargetAssembly>                        Register an assembly

Library

Usage:

dotnet add package dSPACE.Runtime.InteropServices

dSPACE.Runtime.InteropServices supports the following methods and classes:

  • TypeLibConverter
    • ConvertAssemblyToTypeLib
  • TypeLibEmbedder
    • EmbedTypeLib
  • RegistrationServices
    • RegisterTypeForComClients
    • UnregisterTypeForComClients
    • RegisterAssembly
    • UnregisterAssembly

TypeLibConverter.ConvertAssemblyToTypeLib

If you miss theTypeLibConverter class and theConvertAssemblyToTypeLib method in.NET, then thedSPACE.Runtime.InteropServices might help you.This method should behave compatible to the.NET Framework method.

publicobject?ConvertAssemblyToTypeLib(Assemblyassembly,stringtlbFilePath,ITypeLibExporterNotifySink?notifySink)

https://www.nuget.org/packages/dSPACE.Runtime.InteropServices/

Example:

usingdSPACE.Runtime.InteropServices;// The assembly to convertvarassembly=typeof(Program).Assembly;// Convert to assemblyvartypeLibConverter=newTypeLibConverter();varcallback=newTypeLibConverterCallback();varresult=typeLibConverter.ConvertAssemblyToTypeLib(assembly,"MyTypeLib.tlb",callback);// Get the name of the type libraryvartypeLib2=resultasSystem.Runtime.InteropServices.ComTypes.ITypeLib2;if(typeLib2!=null){typeLib2.GetDocumentation(-1,outstringname,out_,out_,out_);Console.WriteLine($"TypeLib name:{name}");}// The callback to load additional type libraries, if necessarypublicclassTypeLibConverterCallback:ITypeLibExporterNotifySink{publicvoidReportEvent(ExporterEventKindeventKind,inteventCode,stringeventMsg){Console.WriteLine($"{eventCode}:{eventMsg}");}publicobject?ResolveRef(System.Reflection.Assemblyassembly){// Returns additional type librariesreturnnull;}}

TypeLibEmbedder.EmbedTypeLib

.NET +6 introduced ability to embed type library into assemblies with the ComHostTypeLibrary property. However, using this is not fully compatible with the dscom build tools as it requires a type library to be already generated prior to the build. This class provides the implementation for embedding a type library into an assembly via Win32 API p/invoke calls.

The class and method are static, so you only need to create a settings to provide parameter for the source type library and the target assembly for where the type library will be embedded.

It is important to note that type libraries arenot bit-agnostic and therefore, it will not make sense to embed them in an AnyCPU assemblies. For .NET 5.0 and greater, that is not an issue since the generated *.comhost.dll are tied to a specific bitness. For .NET 4.8, it is strongly recommended that the assembly be built with either x64 or x86 rather than AnyCPU.

publicstaticboolEmbedTypeLib(TypeLibEmbedderSettingssettings)

Example:

usingdSPACE.Runtime.InteropServices;varsettings=newTypeLibEmbedderSettings{SourceTlbPath="C:\\path\\to\\type\\library.tlb",TargetAssembly="C:\\path\\to\\assembly.dll"};TypeLibEmbedder.EmbedTypeLib(settings);

IMPORTANT: Embedding the type library will alter the assembly, which may cause issues with signing the assembly. Therefore, the scenario of signing the assembly with a certificate or a strong name is not tested. If it is required that the assembly be signed, it is recommended that a build script be used to ensure proper sequence of steps is executed.

IMPORTANT: In order to embed the type library into the built assembly, the process must unload the assembly. As dotnet restricts the usage of unloadable assemblies via AssemblyLoadContext to pure CLR assemblies, embedding TLBs into an assembly may only work, if none of the assemblies loaded via--asmpath may be a mixed mode C++/CLI assembly. In this case, please use to different calls todscom.exe /dscom32.exe or the separate dscom build tasks. For more information refer to issue#292.

RegistrationServices.RegisterTypeForComClients

ThedSPACE.Runtime.InteropServices.RegistrationServices provides a set of services for registering and unregistering managed assemblies for use from COM.

This method is equivalent to calling CoRegisterClassObject in COM.
You can register a .NET class so that other applications can connect to it (For example as INPROC_SERVER or as a LOCAL_SERVER).

A outproc demo application is available here:examples\outproc

Example:

usingdSPACE.Runtime.InteropServices;varregistration=newRegistrationServices();varcookie=registration.RegisterTypeForComClients(typeof(Server.Common.Greeter),RegistrationClassContext.LocalServer,RegistrationConnectionType.MultipleUse);Console.WriteLine($"Press enter to stop the server");Console.ReadLine();registration.UnregisterTypeForComClients(cookie);

RegistrationServices.RegisterAssembly

Registers the classes in a managed assembly to enable creation from COM.

usingdSPACE.Runtime.InteropServices;varregistration=newRegistrationServices();// Register MyAssemblyregistration.RegisterAssembly(typeof(MyAssembly),true);// Unregister MyAssemblyregistration.UnregisterAssembly(typeof(MyAssembly),true);

Build Tasks

ThedSPACE.Runtime.InteropServices.BuildTasks assembly and NuGet package provide the ability to create type libraries for a certain assembly at compile time.

Build task usage

To create a type library at compile time, simply add a reference to the nuget package, e.g. by using the command line.

dotnet add package dSPACE.Runtime.InteropServices.BuildTasks

The result should be a line as follows in your.csproj file:

    <PackageReferenceInclude="dSPACE.Runtime.InteropServices.BuildTasks"Version="0.17.0"NoWarn="NU1701">      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>      <PrivateAssets>all</PrivateAssets>    </PackageReference>

Note: The extra attributeNoWarn="NU1701" is only required, if neither.NET 4.8 nor.NET 6.0 are targeted, since dotnet pack will currently not create a .NETStandard 2.0 compliant NuGet Package.

Enforcing to stop the build, if an error occurs

The build tasks puts a warning to the build log, if the desired type library has not been created, even if the backend has reported a success.

This warning is issued with the warning codeDSCOM001, which can be collected in theWarningsAsErrors array:

<WarningsAsErrors>$(WarningsAsErrors);DSCOM001</WarningsAsErrors>

This way the build stops, if the type library is not exported.

Parameters

The build task can be parameterized with the followingproperties:

NameDescription
_DsComTlbExtExtension of the resulting type library.
Default Value:.tlb
DsComTypeLibraryUniqueIdOverwrite the library UUID
Default Value: Empty Guid
DsComOverideLibraryNameOverwrite the IDL name of the library.
Default Value: Empty string
DsComRegisterTypeLibrariesAfterBuildUse regasm call after the build to register type library after the build
Default value:false
DsComTlbExportAutoAddReferencesAdd referenced assemblies automatically to type libraries
Default value:true
DsComTlbExportIncludeReferencesWithoutHintPathIf aReference assembly does not provide aHintPath Metadata, the item spec shall be task.
Default value:false
DsComExportTypeLibraryTargetFilePath to the resulting file.
Default value:$(TargetDir)\$(TargetName)$(_DsComTlbExt) *
DsComExportTypeLibraryAssemblyFilePath to the source assembly file.
Default value:$(TargetPath) *
DsComTypeLibraryEmbedAfterBuildEmbeds the generated type library into the source assembly file.
Default value:false

The build task consumes the followingitems:

NameDescription
DsComTlbExportTlbReferencesReferenced type library files.
DsComTlbExportReferencePathsDirectories containing type libraries to use for export.
DsComTlbExportAssemblyPathsAssemblies to add for the export.
DsComTlbAliasNamesNames to use as aliases for types with aliases.

The CLI based task consumes these additionalproperties:

NameDescription
DsComToolVerboseEnablesverbose option.
DsComToolSilentEnablessilent option.

The CLI based task consumes these additionalitems:

NameDescription
DsComToolSilenceEnablessilence option for the given warnings

Example

<ProjectSdk="Microsoft.NET.Sdk">   <PropertyGroup>      <DsComTypeLibraryUniqueId>f74a0889-2959-4e7b-9a1b-f41c54f31d74</DsComTypeLibraryUniqueId>   </PropertyGroup>   <ItemGroup>    <DsComTlbExportTlbReferencesInclude="C:\Path\To\My.tlb" />    <DsComTlbExportAssemblyPathsInclude="C:\Path\To\Assemblies\Dependency.dll" />    <DsComTlbExportReferencePathsInclude="C:\Path\To\Additional\TypeLibraries\" />   </ItemGroup></Project>

Hints

When using the build tasks to create an 32 bit version for your type libraries / projects: The tasks require the .NET runtime in their specific CPU architecture to be installed.

So, for building 32 bit TLBs, dscom32 will be executed, whichrequires .NET runtime in x86 flavor to be available.

32Bit support

dscom installed bydotnet tool install can only handle AnyCPU or 64Bit assemblies and can only generate a 64bit TLB.Depending on whether you want to process 32bit or 64bit assemblies, you need to download different executables from therelease page.

  • dscom.exe to create a 64Bit TLB from a AnyCPU or a 64Bit assembly
  • dscom32.exe to create a 32Bit TLB from a AnyCPU or a 32Bit assembly

Warning!
If your assembly is an AnyCPU assembly, then an yourassemblyname.comhost.dll is created as a 64 bit dll.
Therefore after calling regserv32.exe a 64 bit dll is registred.
To prevent this it isrecommended that the assembly is compiled as a 32 bit assembly and not as an AnyCPU assembly.
see:dotnet/runtime#32493

Warning!In order to use 32 bit support with the build targets, the x86 version of .NET must be installed, as dscom requests the hostfxr.dll to be loaded.

Migration notes (mscorelib vs System.Private.CoreLib)

Both assemblies areComVisible=false but lot of .NET Framework types areComVisible=true.But this is not the case for .NET (.NET Core and .NET >= 5).
Unlike mscorelib (the good old .NET Framework), no tlb is shipped for .NET.

As example theSystem.Exception class:

In case of mscorelib theSystem.Exception class isComVisible=true:

[Serializable][ClassInterface(ClassInterfaceType.None)][ComDefaultInterface(typeof(_Exception))][ComVisible(true)]publicclassException:ISerializable, _Exception

In case ofSystem.Private.CoreLib (.NET Core and .NET >=5), theException class isComVisible=false

[Serializable][TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]publicclassException:ISerializable{

The_Exception class interface (default interface in this case) is not available in .NET (.NET Core and .NET >=5).

Why can I load a .NET Framework library into a .NET application?

The magic is inTypeForwardedFromAttribute.
If you try to load an .NET Framework assembly inside a .NET (.NET Core and .NET >=5) application, the runtime will forward the original type toa type defined in theSystem.Private.CoreLib assembly.

classextern forwarder System.Exception{    .assemblyextern System.Private.CoreLib}

Therefore you should make sure that you do not use any types from themscorelib typelib in your .NET Framework project if you plan to migrate to .NET 5+

Limitations

RegisterAssembly

  • InProc Registration only will take place, if a comhost assembly is present.
  • No CustomRegisterFunction Or CustomUnRegisterFunction Attribute support
  • No PrimaryInteropAssembly Support

RegAsm

featuredscom
assemblyFilesupported
codebasesupported
registerednot supported
asmpathsupported
nologonot supported
regfilenot supported
silentnot supported
tlbsupported
unregistersupported
verbosenot supported
helpsupported

Contributing

We would be happy if you would like to contribute to this project.

We use VSCode as IDE, but feel free to use your preferred IDE.
You need >= .NET 8.0 SDK and .NET Full Framework >= 4.8 SDK installed on your machine.
Before submitting a pull request, please note the following points:

  1. Code Formatting
    Ensure the code is properly formatted usingdotnet format --verify-no-changes.

  2. Unit Tests
    Run all tests withdotnet test and make sure all tests pass successfully.Usedotnet build before running the tests to ensure that the project is built correctly and thedscom.exe is available.

  3. Writing Tests
    We like to have unit tests 😊
    Write your own tests for any new features or bug fixes.

  4. Verifying the tlb generation
    To generate a TLB with dscom is the most important feature of this project.
    Compare the output ofdscom with that oftlbexp.
    Usescripts\test.assembly.bat to generate a TLB with bothdscom andtlbexp, and compare the outputs.
    This script will usesrc\dscom.test.assembly\dscom.test.assembly.csproj to generate a TLB with both tools.

    The script will attempt to open VSCode to facilitate the file comparison.

    Ensure tlbexp is installed on your machine.
    If you have Visual Studio installed, find tlbexp.exe in theC:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools folder, or use theDeveloper Command Prompt for VS to runtlbexp.

If you have any questions, feel free to ask in the issues section.

Thank you for your contribution ❤️


[8]ページ先頭

©2009-2025 Movatter.jp