diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 22039203..81c85e57 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,8 +1,9 @@ { - "recommendations": [ - "ryanluker.vscode-coverage-gutters", - "formulahendry.dotnet-test-explorer", - "ms-dotnettools.csharp", - "editorconfig.editorconfig" - ] - } \ No newline at end of file + "recommendations": [ + "ryanluker.vscode-coverage-gutters", + "formulahendry.dotnet-test-explorer", + "ms-dotnettools.csharp", + "editorconfig.editorconfig", + "davidanson.vscode-markdownlint" + ] +} diff --git a/README.md b/README.md index d51c6834..bac0e241 100644 --- a/README.md +++ b/README.md @@ -12,41 +12,48 @@ [![Example Tests](https://github.com/dspace-group/dscom/actions/workflows/example-test.yaml/badge.svg)](https://github.com/dspace-group/dscom/actions/workflows/example-test.yaml) [![Code Style Check](https://github.com/dspace-group/dscom/actions/workflows/code-style.yaml/badge.svg)](https://github.com/dspace-group/dscom/actions/workflows/code-style.yaml) -> This is an unstable prerelease. Anything may change at any time! - -dscom generates a type library that describes the types defined in a common language runtime assembly and is a replacement for `tlbexp.exe` and `TypeLibConverter.ConvertAssemblyToTypeLib`. -The tool consists of a library and a command line tool. The library can be used in `net5+` or in `net48` projects. - -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. +The command line client `dscom` is a replacement for `tlbexp.exe` and creates and registers TLBs from .NET assemblies. +The `dSPACE.Runtime.InteropServices` library contains various classes and methods for COM. +It can be used in `net5+` or in `net48` projects. With the library you can register assemblies and classes for COM and programmatically generate TLBs at runtime. +The `dSPACE.Runtime.InteropServices.BuildTasks` library provides build tasks which can be used to automatically generate TLBs at compile time. - - -One main goal is to make `dscom` behave like `tlbexp.exe`. - -_Happy IUnknowing and IDispatching ;-)_ +> This is an unstable prerelease. Anything may change at any time! - [dSPACE COM tools](#dspace-com-tools) + - [Introducing](#introducing) - [Command Line Client](#command-line-client) - [Installation](#installation) - - [32Bit support](#32bit-support) - [Usage](#usage) + - [Library](#library) + - [TypeLibConverter.ConvertAssemblyToTypeLib](#typelibconverterconvertassemblytotypelib) + - [RegistrationServices.RegisterTypeForComClients](#registrationservicesregistertypeforcomclients) + - [RegistrationServices.RegisterAssembly](#registrationservicesregisterassembly) - [Build Tasks](#build-tasks) - - [Preface](#preface) - [Build task usage](#build-task-usage) - [Using the native build task](#using-the-native-build-task) - [Using the CLI based task](#using-the-cli-based-task) - [Enforcing the usage of the CLI](#enforcing-the-usage-of-the-cli) - [Enforcing to stop the build, if an error occurs](#enforcing-to-stop-the-build-if-an-error-occurs) - [Parameters](#parameters) - - [Library](#library) - - [TypeLibConverter.ConvertAssemblyToTypeLib](#typelibconverterconvertassemblytotypelib) - - [RegistrationServices.RegisterTypeForComClients and RegistrationServices.UnregisterTypeForComClients](#registrationservicesregistertypeforcomclients-and-registrationservicesunregistertypeforcomclients) + - [32Bit support](#32bit-support) - [Migration notes (mscorelib vs System.Private.CoreLib)](#migration-notes-mscorelib-vs-systemprivatecorelib) - [Why can I load a .NET Framework library into a .NET application?](#why-can-i-load-a-net-framework-library-into-a-net-application) - [Limitations](#limitations) + - [RegisterAssembly](#registerassembly) + +## Introducing + +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. + + + +One main goal is to make `dscom` behave like `tlbexp.exe`. + +Also, some classes are missing in .NET 5+ that were available in the full framework. +This is where `dSPACE.Runtime.InteropServices` may be able to help. ## Command Line Client @@ -73,20 +80,6 @@ Here you can find all available versions: Alternatively you can download dscom.exe from the relase page. -### 32Bit support - -`dscom` installed by `dotnet 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 the [release page](https://github.com/dspace-group/dscom/releases). - -* **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 is **recommended that the assembly is compiled as a 32 bit assembly** and not as an AnyCPU assembly. -> see: - ### Usage Use `dscom --help` to get further information. @@ -110,102 +103,23 @@ Commands: tlbunregister Unregister a type library ``` -## Build Tasks - -### Preface - -The `dSPACE.Runtime.InteropServices.BuildTasks` assembly and NuGet package provide the ability to create type libraries for a certain assembly at runtime. - -For details on the implementation refer to the [documentation](/src/dscom.build/docs/ReadMe.md) section of the repository. - -### 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. - -```shell -dotnet add package dSPACE.Runtime.InteropServices.BuildTasks -``` - -The result should be a line as follows in your `.csproj` file: - -```xml - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - -``` - -**Note**: The extra attribute `NoWarn="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. - -#### Using the native build task - -The native build task is automatically selected, if a .NET 4.8 or .NET 6.0 assembly for Windows is being build using an x64 platform. - -#### Using the CLI based task - -The CLI task is automatically selected, if a .NET Standard 2.0 assembly is build. It is also chosen, if the target platform is set to x86. - -#### Enforcing the usage of the CLI - -It might be necessary to select the CLI based task. To do so, add the following property to your `.csproj` file: - -```XML -<_DsComForceToolUsage>true -``` - -This will enforce the usage of the DsCom as a command-line tool. Please note, that verbose logging will no longer be working. - -#### 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 code `DSCOM001`, which can be collected in the `WarningsAsErrors` array: - -```XML -$(WarningsAsErrors);DSCOM001 -``` - -This way the build stops, if the type library is not exported. - -### Parameters - -The build task can be parameterized with the following properties: - -| **Name** | **Description** | **Default** | -| ---------------------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------- | -| _DsComTlbExt | Extension of the resulting type library. | .tlb | -| _DsComForceToolUsage | Use DsCom Exe files to create the TLB | false | -| DsComTypeLibraryUniqueId | Overwrite the library UUID | Empty Guid | -| DsComRegisterTypeLibrariesAfterBuild | Use regasm call after the build to register type library after the build | false | -| DsComTlbExportAutoAddReferences | Add referenced assemblies automatically to type libraries | true | -| DsComTlbExportIncludeReferencesWithoutHintPath | If a `Reference` assembly does not provide a `HintPath` Metadata, the item spec shall be task. | false | -| _DsComExportTypeLibraryTargetFile | Path to the resulting file. | `$(TargetDir)\$(TargetName)$(_DsComTlbExt)` * | -| _DsComExportTypeLibraryAssemblyFile | Path to the source assembly file. | `$(TargetPath)` * | - -*) This value cannot be overridden. - -The build task consumes the following items: - -| **Name** | **Description** | -| ---------------------------- | -------------------------------------------------------- | -| DsComTlbExportTlbReferences | Referenced type library files. | -| DsComTlbExportReferencePaths | Directories containing type libraries to use for export. | -| DsComTlbExportAssemblyPaths | Assemblies to add for the export. | - ## Library Usage: + ```bash dotnet add package dSPACE.Runtime.InteropServices ``` dSPACE.Runtime.InteropServices supports the following methods and classes: -* TypeLibConverter - * ConvertAssemblyToTypeLib -* RegistrationServices - * RegisterTypeForComClients - * UnregisterTypeForComClients +- TypeLibConverter + - ConvertAssemblyToTypeLib +- RegistrationServices + - RegisterTypeForComClients + - UnregisterTypeForComClients + - RegisterAssembly + - UnregisterAssembly ### TypeLibConverter.ConvertAssemblyToTypeLib @@ -258,9 +172,10 @@ public class TypeLibConverterCallback : ITypeLibExporterNotifySink } ``` -### RegistrationServices.RegisterTypeForComClients and RegistrationServices.UnregisterTypeForComClients +### RegistrationServices.RegisterTypeForComClients + +The `dSPACE.Runtime.InteropServices.RegistrationServices` provides a set of services for registering and unregistering managed assemblies for use from COM. -The `dSPACE.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). @@ -282,6 +197,114 @@ Console.ReadLine(); registration.UnregisterTypeForComClients(cookie); ``` +### RegistrationServices.RegisterAssembly + +Registers the classes in a managed assembly to enable creation from COM. + +```csharp +using dSPACE.Runtime.InteropServices; + +var registration = new RegistrationServices(); + +// Register MyAssembly +registration.RegisterAssembly(typeof(MyAssembly), true); + +// Unregister MyAssembly +registration.UnregisterAssembly(typeof(MyAssembly), true); +``` + +## Build Tasks + +The `dSPACE.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. + +```shell +dotnet add package dSPACE.Runtime.InteropServices.BuildTasks +``` + +The result should be a line as follows in your `.csproj` file: + +```xml + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + +``` + +**Note**: The extra attribute `NoWarn="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. + +#### Using the native build task + +The native build task is automatically selected, if a .NET 4.8 or .NET 6.0 assembly for Windows is being build using an x64 platform. + +#### Using the CLI based task + +The CLI task is automatically selected, if a .NET Standard 2.0 assembly is build. It is also chosen, if the target platform is set to x86. + +#### Enforcing the usage of the CLI + +It might be necessary to select the CLI based task. To do so, add the following property to your `.csproj` file: + +```XML +<_DsComForceToolUsage>true +``` + +This will enforce the usage of the DsCom as a command-line tool. Please note, that verbose logging will no longer be working. + +#### 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 code `DSCOM001`, which can be collected in the `WarningsAsErrors` array: + +```XML +$(WarningsAsErrors);DSCOM001 +``` + +This way the build stops, if the type library is not exported. + +### Parameters + +The build task can be parameterized with the following properties: + +| **Name** | **Description** | **Default** | +| ---------------------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------- | +| _DsComTlbExt | Extension of the resulting type library. | .tlb | +| _DsComForceToolUsage | Use DsCom Exe files to create the TLB | false | +| DsComTypeLibraryUniqueId | Overwrite the library UUID | Empty Guid | +| DsComRegisterTypeLibrariesAfterBuild | Use regasm call after the build to register type library after the build | false | +| DsComTlbExportAutoAddReferences | Add referenced assemblies automatically to type libraries | true | +| DsComTlbExportIncludeReferencesWithoutHintPath | If a `Reference` assembly does not provide a `HintPath` Metadata, the item spec shall be task. | false | +| _DsComExportTypeLibraryTargetFile | Path to the resulting file. | `$(TargetDir)\$(TargetName)$(_DsComTlbExt)` * | +| _DsComExportTypeLibraryAssemblyFile | Path to the source assembly file. | `$(TargetPath)` * | + +*) This value cannot be overridden. + +The build task consumes the following items: + +| **Name** | **Description** | +| ---------------------------- | -------------------------------------------------------- | +| DsComTlbExportTlbReferences | Referenced type library files. | +| DsComTlbExportReferencePaths | Directories containing type libraries to use for export. | +| DsComTlbExportAssemblyPaths | Assemblies to add for the export. | + +## 32Bit support + +`dscom` installed by `dotnet 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 the [release page](https://github.com/dspace-group/dscom/releases). + +- **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 is **recommended that the assembly is compiled as a 32 bit assembly** and not as an AnyCPU assembly. +> see: + ## Migration notes (mscorelib vs System.Private.CoreLib) Both assemblies are **ComVisible=false** but lot of .NET Framework types are **ComVisible=true**. @@ -351,3 +374,9 @@ classextern forwarder System.Exception - Color is converted to `OLE_COLOR`(stdole) - No support for `UnmanagedType.CustomMarshaler` - No support for .NET Framework assemblies with `AssemblyMetadataAttribute` value ".NETFrameworkAssembly" + +### RegisterAssembly + +- InProc Registration only will take place, if a comhost assembly is present. +- No CustomRegisterFunction Or CustomUnRegisterFunction Attribute support +- No PrimaryInteropAssembly Support