dspace-group / dscom Goto Github PK
View Code? Open in Web Editor NEWdscom, a toolkit for creating and registering type libraries (tlb) and additional interop helper methods for COM
License: Apache License 2.0
dscom, a toolkit for creating and registering type libraries (tlb) and additional interop helper methods for COM
License: Apache License 2.0
If you have a .NET COM library that references an COM Interop assembly, and try to export the TLB of your library, the exporter tries to export the interop assembly into the TLB.
For example, I have a .NET COM library that makes reference to an Interop with Excel and the TLB export fails because it tries to export the Excel interop and some GUID in the interop are the same, then it fails when trying to assign the GUID to a member or class.
Description
Adding the package dSPACE.Runtime.InteropServices.BuildTasks package (added in #102) to projects targetting .NET Standard 2.0 causes NuGet restore to issue a NU1701 warning.
This is due to the fact, that no group for .NET Standard 2.0 is created in the resulting NuGet package.
Accepted workaround is currently, that the package must be added with ItemMetadata NoWarn="1702"
.
Severity
Major
(.NET Standard 2.0 is losing ground, Workaround exists)
How to reproduce
Add the build task to a project targeting .NET Standard 2.0. Run the restore.
Acceptance criteria
The NU1701 warning must not appear.
I think this section need some more explanation as I have my doubts about this:
dscom/src/dscom/RegistrationServices.cs
Lines 431 to 452 in 9a6ad4f
My concerns are as follows:
This method can only be called by the owner of a category, usually as part of the installation or de-installation of the operating system or application.
Reference
0
(e.g. LOCALE_NEUTRAL
). When I look at all other component categories within the HKCR\Component Categories\
, I do not see any other categories with a neutral locale. In fact, on my computer, all have the same locale of 409 (e.g. en-us
locale). I'm not sure how that looks on other computers. I would expect that as part of the .NET installation, it will use the appropriate locales and thus it isn't our responsibility to add it.From my testing, ICatRegister::RegisterCategory
will not register the category unless running in an elevated context, which fits the expectation because those are described in HKLM exclusively, never in HKCU, and the ICatRegister
will write to the HKLM only. Indeed, when running non-elevated, it won't even throw an error but silently gives S_OK
even though no registry keys were written. I cannot find any documentation suggesting whether a component category can be registered non-elevated and even though HCKR will reflect HKCU (which normally does not have the Component Categories
key and must be manually added), I don't think anyone has used components on a per-user level, only at per-machine level. That makes sense because the component categories are normally used to support tasks such as displaying an dialog to select from a list of controls that can be inserted into a container.
Can you provide a counterexample as to why this code is necessary? The code to register a component as implementing a certain category certainly is appropriate but I'm not so sure we ought to be registering category that aren't ours.
Addendum:
After posting above, I found this article which does list component categories as one of elements that's merged in the HKCR which mirror my manual test even though I did not have any per-user categories registered. The only problem is that for older software that's incorrectly using HKLM rather than HKCR; those will not work correctly if the data is in HKCU even though it will also appear in HKCR. If you are aware of such examples where HKLM is essential we ought to consider this. In the example of registering a neutral locale key, that could be written to HKCU instead of HKCR which would then remove the need to elevate the privileges for registering the assembly.
Using .NET Sourcelink, nuget packages can be published that will reference not only the project on github, but also the commit that was used for the creation of the package.
For details, please refer to the package and the repository.
It is really easy to introduce: Just add the package Microsoft.SourceLink.Github
to the development dependencies of the project to be published.
According to the project website, the following new properties should be added to the project:
<!-- Optional: Publish the repository URL in the built .nupkg (in the NuSpec <Repository> element) -->
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<!-- Optional: Embed source files that are not tracked by the source control manager in the PDB -->
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<!-- Optional: Build symbol package (.snupkg) to distribute the PDB containing Source Link -->
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
The first one should already be setup for dscom.
The second parameter will include generated code to the pdb. This is optional.
The third and fourth parameter can be used to create a symbol nuget package (snupkg), which will remove the necessity to use a symbol server.
This affects the new attributes in .NET 8
https://learn.microsoft.com/en-us/dotnet/standard/native-interop/pinvoke-source-generation
https://www.youtube.com/watch?v=DZd1SGd7dSU
We will have to check how dscom currently handle these new attributes and what's planned for the future:
[GeneratedComClass]
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshalling.generatedcomclassattribute?view=net-8.0
[GeneratedComInterface]
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshalling.generatedcominterfaceattribute?view=net-8.0
[LibraryImport]
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.libraryimportattribute?view=net-8.0
This may be an error on my part, but I thought I'd bring it up here in case there's a bug to fix, or even a clarification that can be made on the main page. Consistently when I run my CPP code, that imports a tlb and attempts to point to a class, I'm getting this error:
onecore\com\combase\dcomrem\resolver.cxx(2299)\combase.dll!77A61A49: (caller: 77ADABBC) ReturnHr(1) tid(3a1c) 80040154 Class not registered
The error occurs when I call "PSP_CSLibraryDLLClassPtr p(__uuidof(PSP_CSLibrary));" - I'm guessing that it's PSP_CSLibrary which is the unregistered class.
Note that this error does not appear if I use an old tlb made with tlbexp.exe
I already made sure the tlb was created with --win32 (from AnyCpu), which matched my C++ architecture, and then I registered it with "dscom tlbregister".
Is there anything more I have to do? Register the dll somehow? Do something extra to register the class? The class itself has a unique GUID in my C# file as well. Not sure what to do, or where this error is coming from.
The title already tells it.
$ mkdir C:\test
$ mkdir "C:\test\My Project"
$ mkdir "C:\test\My Project\test"
$ cd "C:\test\My Project\test"
$ dotnet new console
$ dotnet add package dspace.runtime.interopservices.buildtasks
$ dotnet build
Expected: The build works
Result: Calling dscom.exe to export type library
Unrecognized command or argument 'Project\test\bin\Debug\net6.0\test.dll'.
If an interface is referenced as a parameter that cannot be resolved by a TLB, a warning comes up, see this simple example:
public interface WarningTestInterface
{
System.Collections.IList GetList();
}
dscom : warning TX0013116F : Warning: Type library exporter could not find the type library for IList. IUnknown was substituted for the interface.
If you now want to resolve this warning by an explicit MarshalAs as follows, the warning still appears.
public interface WarningTestInterface
{
[return: MarshalAs(UnmanagedType.IUnknown)]
System.Collections.IList GetList();
}
One should be able to avoid the warning by an explicit MarshalAs, since the origin type becomes irrelevant with it.
Hi!
As of today (6/7/2024), https://www.virustotal.com is flagging dscom32.exe (v1.10.0) as malicious by 3 out of 73 engines:
https://www.virustotal.com/gui/file/d3dbf44f87859d7410a8216e0b42536a9dd78b4265debbef16d6ac107aee6391
Earlier this week it was 10 out of 73 engines one of which was BitDefender. Our IT director filed a false positive report to BitDefender which seems to have helped but not fully resolved the false positives.
Strangely, dscom.exe (v1.10.0) is not flagged at all:
https://www.virustotal.com/gui/file/01e88ce60d43a9ab718fae315f3f72706c2d914faa8b5af9cfcff5b4703a4948
We are shipping both utilities with our product and our dealers got concerned about the false positives on dscom32.exe. Any help clearing them out is appreciated!
Thanks...
Berk
The global.json requires .NET 6.0.100 because 6.0.200 contained a bug but currently 6.0.300 is available where the bug was fixed. The configurations should be updated
If I set PlatformTarget
to x86
the CLI version ist used for creating the tlb-file. So far so good. However the wrong version is used. The build task returns an error, which points out that the x64-version ist used.
Fehler MSB3073 Der Befehl "D:\Entwicklung.nuget\packages\dspace.runtime.interopservices.buildtasks\0.21.0\build..\tools\x64\dscom.exe tlbexport D:\Entwicklung<PathTo>\My.dll --out D:\Entwicklung<PathTo>\My.tlb" wurde mit dem Code 1 beendet.
According to the message the error originates in dSPACE.Runtime.InteropServices.BuildTasks.Tools.targets
, line 62. However I think it originates in the lines 23 resp. 24. In Line 23 _DsComToolsFileDir
is set without condition. Line 24 provides condition for x86. To me it seems the condition ist wrong. If I comment out line 23 $(_DsComToolsFileDir)
becomes empty (instead of pointing to $(MsBuildThisFileDirectory)..\tools\x86\
). Therefore I think something with the condition in line 24 is wrong.
Using the method fails when the provided Type element has no CustomAttribute GuidAttribute.
RegisterTypeForComClients(Type type, ComTypes.RegistrationClassContext classContext, ComTypes.RegistrationConnectionType flags)
An empty sequence exception is thrown by this line.
var guid = new Guid(type.GetCustomAttributes<GuidAttribute>().First().Value);
Using the RegistrationServices from System.Runtime.InteropServices the method works, the passed type object is the same and does also not contain a CustomAttribute GuidAttribute.
I did observer that the Type object has an assembly property. Looking into it the provided assembly has a GuidAttribute. Adjusting the code as such:
var guid = new Guid(type.Assembly.GetCustomAttributes<GuidAttribute>().First().Value);
The code works, and cross referencing with the source code the GUID is also correct.
The code should also check the Assembly for the GUID.
A more fitting Exception would be helpful if the GUID cannot be retrieved at all.
I faced strange error.
dscom fails to export tlb if assembly references System.Security.Cryptography.
Interop+BCrypt+BCRYPT_DSA_KEY_BLOB_V2+<Count>e__FixedBuffer, System.Security.Cryptography, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
I think it's related to .NET 8.
Originally posted by @gureedo in #196 (comment)
With the following code example:
public void MyMethodName(int param1, [DefaultParameterValue(1)] int param2);
public void MyMethodName2(IDemoInterface param1, [DefaultParameterValue(null)] IDemoInterface? param2);
public void MyMethodName3(IDemoInterface param1, IDemoInterface? param2 = null);
The first and third options to set a default value work as expected.
But the second option will ignore the default value.
This happens only if the provided default value is not optional and null
Because there is no clear naming schema, it's sometimes hard to see which test cases are missing.
Here we should define an easier to read naming schema and rename the tests accordingly.
There are currently test cases missing in the unit tests. For example:
It's likely that we will identify additional missing test cases during the renaming operation.
Hello,
First of all, many thanks for this extremely useful tool. We use it on many projects and it saves us a lot of time.
I'd like to suggest a small improvement, unless the functionality already exists but I've missed it: our assemblies contain imported interop types and, from time to time, these imported types appear several times in the hierarchy when the tlb is exported. This generates a TYPE_E_DUPLICATEID error when the SetGuid method is called, preventing the command from executing correctly.
It seems to me that it would be fairly easy to get around this problem by adding an option (e.g. --includeimportedtypes) and a test on type.IsImport in the LibraryWriter.CollectAllTypes method so that imported types can be ignored.
What do you think?
Hi!
Is it possible to return mixed assembly support?
Latest version is unable to perform tlbexport for mixed assembly or assembly with mixed assembly dependency.
I have digged a bit and found that AssemblyLoadContext is constructed with unload feature which is not supported for mixed assemblies.
The code style check fails after the used windows image was updated:
Worked with:
https://github.com/dspace-group/dscom/actions/runs/4281683514/jobs/7455010898
Current runner version: '2.301.1'
Operating System
Microsoft Windows Server 2022
10.0.20348
Datacenter
Runner Image
Image: windows-2022
Version: 20230219.1
Included Software: https://github.com/actions/runner-images/blob/win22/20230219.1/images/win/Windows2022-Readme.md
Image Release: https://github.com/actions/runner-images/releases/tag/win22%2F20230219.1
Failing with:
https://github.com/dspace-group/dscom/actions/runs/4363953151/jobs/7630677977
Current runner version: '2.302.1'
Operating System
Microsoft Windows Server 2022
10.0.20348
Datacenter
Runner Image
Image: windows-2022
Version: 20230226.1
Included Software: https://github.com/actions/runner-images/blob/win22/20230226.1/images/win/Windows2022-Readme.md
Image Release: https://github.com/actions/runner-images/releases/tag/win22%2F20230226.1
Some configurations are distributed in the respective projects. Directory.Build.props and Directory.Build.target should be used to keep the configuration consistent.
In #205 we have a problems that exceptions can't be properly logged as warnings because the LoggingTypeLibExporterSink
has not been created yet.
Ideas to solve this:
INameResolvers
to an initialization method which is called after the Logging sink was created.Trying to install the dscom nuget package in a .NET Framewok 4.8-project results in the following error message:
Das Paket "dscom 0.22.1" weist den Pakettyp "DotnetTool" auf, der vom Projekt ".NETFramework\COMFassade" nicht unterstützt wird.
According to readme.me it is meant to work for .NET Framework too. How?
Using the build tasks adds a lot of (unnecessary) files to the output directory:
All this files have nothing to do with the COM-Server I am building and they are not needed to run it. Is there a way preventing these files to be copied to the output directory?
I assume they are put in the output directory because they are referenced by the dSPACE.Runtime.InteropServices.BuildTasks
-package.
I use the property NETCoreSdkRuntimeIdentifier
in some of my projects to specify if a 32 or 64 bit comhost.dll
will be generated. However dSPACE.Runtime.InteropServices.BuildTasks.Tools.targets
does not recognize this property and uses the 64-bit version of dscom for a 32-bit comhost.dll
.
I suggest adding a line like this
<_DsComToolsFileDir Condition="'$(NETCoreSdkRuntimeIdentifier)' == 'win-x86'">$(MsBuildThisFileDirectory)..\tools\x86\</_DsComToolsFileDir>
to dSPACE.Runtime.InteropServices.BuildTasks.Tools.targets
. This makes MSBuild to use the right version of dscom if NETCoreSdkRuntimeIdentifier
is set to win-x86
.
I think you also have to add a line to dSPACE.Runtime.InteropServices.BuildTasks.targets
to automatically use the cli version in this case. I assume it will be something like
<_DsComExporterTargetsFile Condition="'$(NETCoreSdkRuntimeIdentifier)' == 'win-x86'">$(MsBuildThisFileDirectory)dSPACE.Runtime.InteropServices.BuildTasks.Tools.targets</_DsComExporterTargetsFile>
I have simple example:
public interface IMyClass {
[ComVisible(false)]
public System.Security.Cryptography.X509Certificates.X509RevocationMode RevocationMode { get; set; }
}
public class MyClass: IMyClass {
public System.Security.Cryptography.X509Certificates.X509RevocationMode RevocationMode { get; set; }
}
If I run tlbexport with --createmissingdependenttlbs false
there will be warnings in output.
dscom : warning TX00000000 : The referenced library System.Security.Cryptography does not have a type library and auto generation of dependent type libs is disabled
Hi there,
I'm attempting to export TLBs from a 32-bit .NET class library which contains several interfaces and classes.
Some of the methods defined in these interfaces require IntPtr arguments, and when I import the TLB into unmanaged C++, the resulting .TLH requires int64 * arguments in place of the IntPtr ones, when I would've expected them to require long *.
I've verified the contents of the TLB using OleView, so it would seem that dscom32 is not differentiating IntPtr into long* and int64*.
I'm wondering is this expected behaviour or a bug?
I'm getting this error after a .Net 6 port. TlbExport (.Net 4.7.2) could generate the files, dscom reports this error on IEnumerable
dscom : warning TX00000000 : ComVisible interface System.Collections.IEnumerable could not be added to source type ....
The c# dll compiles without errors.
Description
In some cases, the TlbExport
task fails with DSCOM0001
, i.e. the requested library does not exist, even though the Conversion method did not return null
. This was observed when adding #102.
The reason is yet unkown.
As a workaround, by default the usage of the CLI during the build is enforced.
Severity
Major
Workaround exists
How to reproduce
Run the acceptance criteria when _DsComForceToolUsage
is set to false
.
Acceptance criteria
The build does not issue warning DSCOM0001
I worked out the logic for using the TypeLibConverter
by using the sink's ResolveRef
to mirror the argument line commands for the command-line tools. However, I did want to use the build task instead of running code. The documentation implies that the equivalent should be:
<DsComTlbExportTlbReferences>C:\Program Files\Common Files\DESIGNER\MSADDNDR.OLB</DsComTlbExportTlbReferences>
As a property in my .csproj
. However, it does not appear that it get passed as an input to the command line tool during the build. I tried with DsComTlbExportAssemblyPaths
but got the same result; no changes to the command line generated by the build task.
In both cases, the error is as following:
The command "C:\Users\User\.nuget\packages\dspace.runtime.interopservices.buildtasks\0.18.0\build\..\tools\x64\dscom.exe tlbexport C:\GitHub\Rubberduck\Rubberduck.Main\bin\Debug\net48\Rubberduck.dll --out C:\GitHub\Rubberduck\Rubberduck.Main\bin\Debug\net48\\Rubberduck.tlb" exited with code 1.
with additional warnings:
TX00000000 Type library exporter encountered an error while processing 'Microsoft.VisualStudio.Interop'. Error: Could not load file or assembly 'Microsoft.VisualStudio.Imaging.Interop.14.0.DesignTime, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
TX00000000 Type library exporter encountered an error while processing 'Rubberduck'. Error: Could not load file or assembly 'System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. The system cannot find the file specified.
I should note that in the TypeLibConverter
+ sink's ResolveRef
approach, I basically check if it's trying to resolve the Microsoft.VisualStudio.Interop
in which case I pass back C:\Program Files\Common Files\DESIGNER\MSADDNDR.OLB
which has the needed type information without all the junk. This works correctly but not sure how to replicate this as a build task.
Originally posted by @bclothier in #120 (comment)
Recently started seeing this error when trying to export a type library from a 32-bit .NET assembly using dscom32 (it was working before):
Failed to export type library. Could not load file or assembly 'System.Drawing.Common, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.
However, dscom 64-bit has no issues exporting from 64-bit assembly.
Any pointers appreciated, cheers.
Export a TLB for the following code:
[ComVisible(false)]
public interface ComInvisibleInterface
{}
public interface TestInterface
{
void DoSomething(ComInvisibleInterface param);
}
Using the --createmissingdependenttlbs:false --overridetlbid:12345678-1234-1234-1234-123456789012 parameters, the following warnings will appear:
dscom : warning TX00000000 : The referenced library dSPACE.Runtime.InteropServices.DemoAssembly1 does not have a type library and auto generation of dependent type libs is
disabled
dscom : warning TX00000000 : The referenced library dSPACE.Runtime.InteropServices.DemoAssembly1 does not have a type library and auto generation of dependent type libs is
disabled
dscom : warning TX00000000 : The referenced library dSPACE.Runtime.InteropServices.DemoAssembly1 does not have a type library and auto generation of dependent type libs is
disabled
dscom : warning TX00000000 : The referenced library dSPACE.Runtime.InteropServices.DemoAssembly1 does not have a type library and auto generation of dependent type libs is
disabled
dscom : warning TX00000000 : The referenced library dSPACE.Runtime.InteropServices.DemoAssembly1 does not have a type library and auto generation of dependent type libs is
disabled
dscom : warning TX00000000 : The referenced library dSPACE.Runtime.InteropServices.DemoAssembly1 does not have a type library and auto generation of dependent type libs is
disabled
dscom : warning TX00000000 : The referenced library dSPACE.Runtime.InteropServices.DemoAssembly1 does not have a type library and auto generation of dependent type libs is
disabled
dscom : warning TX0013116F : Warning: Type library exporter could not find the type library for ComInvisibleInterface. IUnknown was substituted for the interface.
dscom : warning TX00000000 : The referenced library dSPACE.Runtime.InteropServices.DemoAssembly1 does not have a type library and auto generation of dependent type libs is
disabled
dscom : warning TX00000000 : The referenced library dSPACE.Runtime.InteropServices.DemoAssembly1 does not have a type library and auto generation of dependent type libs is
disabled
dscom : warning TX00000000 : The referenced library dSPACE.Runtime.InteropServices.DemoAssembly1 does not have a type library and auto generation of dependent type libs is
disabled
dscom : warning TX00000000 : The referenced library dSPACE.Runtime.InteropServices.DemoAssembly1 does not have a type library and auto generation of dependent type libs is
disabled
The warnings are caused by the fact that in the generated TLB with the specified GUID the type "ComInvisibleInterface" cannot be found because it was not created. Therefore dscom looks now whether there is a TLB with the GUID, which dscom would have assigned, here the overwritten GUID is ignored and if necessary tries to generate the TLB again with the automatically generated GUID. The overwritten GUID must be used consistently as identity for the TLB in all places.
Hello! Thank you for publishing such a useful project. It was a pleasure to find and easy to get started. As a minor nit, one of the "tripping points" I experienced was that unlike regasm
, dscom tlbregister
does not expand the path provided to be a full path.
Actual behavior:
PS C:\path\to\project> dscom tlbregister foo.tlb
Type library was registered successfully
PS C:\path\to\project> (Get-ItemProperty 'hklm:Software\Classes\TypeLib\{F50810FE-4FA5-3CFF-9523-530867891B55}\1.0\0\win64')."(default)"
foo.tlb
Expected behavior:
PS C:\path\to\project> dscom tlbregister foo.tlb
Type library was registered successfully
PS C:\path\to\project> (Get-ItemProperty 'hklm:Software\Classes\TypeLib\{F50810FE-4FA5-3CFF-9523-530867891B55}\1.0\0\win64')."(default)"
C:\path\to\project\foo.tlb
If you prefer a PR, let me know.
I'm trying to use the NuGet package to integrate TLB exports into my build process. For pure 32-bit libraries, it appears that there is a conditional statement here that is blocking a target for the export from being generated, despite lines earlier in the file which appear to be setting up the use of the 32-bit dscom.exe
We are trying to migrate to Net6 and want to consume this NugetPackage instead of the original System.Runtime.InteropServices.
Since we need to generate code and register this code at runtime, we need to add the .dll to our deliverables.
Since we are StrongName-Signing our product, we can only deliver packages, that are strongName-Signed as well.
==> We want a strongName-Signed version of the dSPACE.Runtime.InteropServices Package.
Hi. i have create a small test project and try your project but it thow an error, can you help me please?
PS C:\Users\user1\Documents\GitHub\TestComExport\TestComExport\bin\x86\Debug\net6.0> dscom tlbexport .\TestComExport.dll
Failed to export type library. Could not load file or assembly 'TestComExport, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnableComHosting>true</EnableComHosting>
<Platforms>x86</Platforms>
</PropertyGroup>
</Project>
using System.Runtime.InteropServices;
namespace TestComExport
{
[ComVisible(true), Guid("FA63E193-BF1E-41A2-95B6-D0AEDC825CFB")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IFlyNumbers
{
[DispId(1)]
int GetDay();
[DispId(2)]
int GetMonth();
[DispId(3)]
int GetYear();
[DispId(4)]
int DayOfYear();
}
[ComVisible(true), Guid("F9AFBEBF-401F-4074-BEA8-9C49FF3EA1EB")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("FlyTest")]
public class FlyNumbers : IFlyNumbers
{
public FlyNumbers() { }
public int GetDay()
{
return DateTime.Today.Day;
}
public int GetMonth()
{
return DateTime.Today.Month;
}
public int GetYear()
{
return DateTime.Today.Year;
}
public int DayOfYear()
{
return DateTime.Now.DayOfYear;
}
}
}
In case of IEnumerable
(this interface is ComVisible=true in System.Private.CoreLib) dscom should generate:
type: VT_PTR -> VT_USERDEFINED refType: name: IEnumerable
As example:
void MyMethod(IEnumerable elements);
The .NET Runtime offers the ability to map datatypes using the ComAliasNameAttribute.
This is currently unsupported by dscom.
Contributions welcome
We are currently missing a "How to contribute" section with information about code style and commit message conventions.
This should be documented in a section of the ReadMe.md
I cloned the repository and built it.
It took me a while to find the correct solution and project to look for, but that's ok.
However, to my surprise, on the output folder of the dscom.client
project instead of a single .exe
file, I had a truckload of files, as shown in the image.
When I copied the dscom.exe
to another folder to test a modification I made, the program blew up on me with the following error:
Failed to run as a self-contained app.
- The application was run as a self-contained app because 'C:\path\dscom.runtimeconfig.json' was not found.
- If this should be a framework-dependent app, add the 'C:\path\dscom.runtimeconfig.json' file
and specify the appropriate framework.
How can I build the project to generate a self-contained .exe
as exposed in the Releases?
It appears that if a solution contains WPF & WinForms, there are errors within the library that prevents it from exporting correctly where the same DLL will export fine with the System.Runtime.InteropServices
.
To reproduce, use the Rubberduck.dll
which can be obtained from here and run the command line tool:
dscom tlbexport .\Rubberduck.Deployment\bin\Rubberduck.dll --out .\Rubberduck.Deployment\bin\Test.tlb
I get the following output:
dscom : warning TX00000000 : Type library exporter encountered an error while processing 'Rubberduck'. Error: Could not load file or assembly 'System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. The system cannot find the file specified.
dscom : warning TX00000000 : Type library exporter encountered an error while processing 'Microsoft.VisualStudio.Interop'. Error: Could not load file or assembly 'Microsoft.VisualStudio.Imaging.Interop.14.0.DesignTime, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
Failed to export type library. Failed to set GUID for DOMDocument. Duplicate ID in inheritance hierarchy. (0x800288C6 (TYPE_E_DUPLICATEID))
We need to check how .NET 8 compatibility can be achieved and how .NET 8 will affect our tool.
https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8
When dscom is called, dependent TLBs are generated if necessary.
It would be good if there is a switch to stop this behavior.
For example:
--generateDependentTlbs false
Node.js 12 actions are deprecated. For more information see: https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/. Please update the following actions to use Node.js 16: actions/checkout@v2, actions/setup-dotnet@v1
Heya,
I loove your dscom tool as it is the only feasable possibility for my project to get MSAL working on an old C++ app by calling current .NET Code from C++.
.NET 7 is out since yesterday and the released dscom32.exe throws an error when working on a .NET 7 Library.
Do you have any plans to support .NET 7 as quick as possible?
Thanks
Soko
This is an idea for enhancement:
If I got it right, dscom
picks AssemblyName
as name of the library in the TLB. Maybe in some cases it might come in handy to override this behaviour and define a name manually.
Therefore I suggest adding a new item which the build task consumes also. Something like DsComTlbLibraryName
When using dscom to export a library referencing WPF or another unavailable library, exceptions are thrown from ComAliasNameResolver
. We don't really want to "fix" those reference problems, just to have tlbexport
ignore them. LibraryWriter
already has the logic to turn missing references into warnings, but ComAliasNameWriter
is missing them.
Related to #120, PR incoming
In case of an single threaded apartment, the StandardOleMarshalObject should be used.
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.standardolemarshalobject?view=net-7.0
In case of an MTA, we should use the regular free-threaded marshaler.
https://devblogs.microsoft.com/oldnewthing/20220622-00/?p=106774
dscom tlbexport may throw a FileLoadException when trying to load a dependent assembly if that assembly was previously loaded from a different path. This has occured for the WindowsBase.dll assembly, which is part of the .NET Windows Runtime.
The issue may be fixed by using Assembly.LoadFile() rather than Assembly.LoadFrom() when loading dependent assemblies from paths specified by --asmpath.
When using dscom to export a library referencing WPF or another unavailable library, exceptions are thrown. We don't really want to "fix" those reference problems, just to have tlbexport ignore them.
Related to #120, #204 and fixed in #205 for v1.4.0.
✅ Build succeeds, TLB is successfully produced with log output
1>Calling dscom.exe to export type library
1>dscom : warning TX00000000: Type library exporter encountered an error while processing 'AssemblyName'. Error: Could not load file or assembly 'PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified.
1>Done building project "AssemblyName.csproj".
❌No TLB is produced, build fails with log output
1>Calling dscom.exe to export type library
1>dscom : warning TX00000000: Type library exporter encountered an error while processing 'AssemblyName'. Error: Could not load file or assembly 'PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified.
1>Failed to export type library. Could not load file or assembly 'PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified.
1>C:\Users\user\.nuget\packages\dspace.runtime.interopservices.buildtasks\1.6.0\build\dSPACE.Runtime.InteropServices.BuildTasks.Tools.targets(64,5): error MSB3073: The command "C:\Users\user\.nuget\packages\dspace.runtime.interopservices.buildtasks\1.6.0\build\..\tools\x64\dscom.exe tlbexport C:\dev\source\repos\OopWpf\AssemblyName\bin\Debug\net462\AssemblyName.dll --out "C:\dev\source\repos\OopWpf\AssemblyName\bin\Debug\net462\\AssemblyName.tlb"" exited with code 1.
1>Done building project "AssemblyName.csproj" -- FAILED.
Issue occurs on net462 and net7.0. Other frameworks not tested.
Diff between 1.5 to 1.6: https://github.com/dspace-group/dscom/compare/v1.5.0..v1.6.0
After adding the nuget package to my project the build returns an error:
Fehler MSB4113 Die angegebene Bedingung @(DsComTlbAliasNames->Count() > 0) wird zu @(DsComTlbAliasNames->Count() > 0) statt zu einem booleschen Wert ausgewertet.
According to the message the error originates in dSPACE.Runtime.InteropServices.BuildTasks.Tools.targets
, line 47. It seems there is a typo in the condition phrase of _DsComAliasNames
(comparing it to the surrounding ones). I assume it should be Condition="@(DsComTlbAliasNames->Count()) > 0"
instead of Condition="@(DsComTlbAliasNames->Count() > 0)"
(wrong position of the closing paranthesis).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.