Skip to content

Commit

Permalink
docu: README.md (#125)
Browse files Browse the repository at this point in the history
* docu: README.md
  • Loading branch information
marklechtermann authored Jan 18, 2023
1 parent 1ea1da0 commit 478255c
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 129 deletions.
15 changes: 8 additions & 7 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"recommendations": [
"ryanluker.vscode-coverage-gutters",
"formulahendry.dotnet-test-explorer",
"ms-dotnettools.csharp",
"editorconfig.editorconfig"
]
}
"recommendations": [
"ryanluker.vscode-coverage-gutters",
"formulahendry.dotnet-test-explorer",
"ms-dotnettools.csharp",
"editorconfig.editorconfig",
"davidanson.vscode-markdownlint"
]
}
273 changes: 151 additions & 122 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

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

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.
<https://docs.microsoft.com/en-us/dotnet/core/native-interop/expose-components-to-com>

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

Expand All @@ -73,20 +80,6 @@ Here you can find all available versions:
Alternatively you can download dscom.exe from the relase page.
<https://github.com/dspace-group/dscom/releases>

### 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: <https://github.com/dotnet/runtime/issues/32493>
### Usage

Use `dscom --help` to get further information.
Expand All @@ -110,102 +103,23 @@ Commands:
tlbunregister <TypeLibrary> 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
<PackageReference Include="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 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</_DsComForceToolUsage>
```

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>$(WarningsAsErrors);DSCOM001</WarningsAsErrors>
```

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

Expand Down Expand Up @@ -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).

Expand All @@ -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
<PackageReference Include="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 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</_DsComForceToolUsage>
```

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>$(WarningsAsErrors);DSCOM001</WarningsAsErrors>
```

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: <https://github.com/dotnet/runtime/issues/32493>
## Migration notes (mscorelib vs System.Private.CoreLib)

Both assemblies are **ComVisible=false** but lot of .NET Framework types are **ComVisible=true**.
Expand Down Expand Up @@ -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

0 comments on commit 478255c

Please sign in to comment.