CsWinRT
CsWinRT copied to clipboard
Getting `REGDB_E_CLASSNOTREG` exception in all platforms except x86
Description
I'm trying the "hello world" scenario of consuming a C++/WinRT Runtime Component using a C# console application.
The compilation succeeds and the projection types get generated with no problems, but whenever I run the application, I get the following runtime exception:
System.Runtime.InteropServices.COMException: 'Class not registered (0x80040154 (REGDB_E_CLASSNOTREG))'
I searched online and some references were saying it might be something wrong/incompatible with platforms. That is why I tried a whole bunch of different project configurations, and the only change that worked for me is when I added <PlatformTarget>x86</PlatformTarget> to my C# project. Changing to <PlatformTarget>x64</PlatformTarget> and running the program as x64 didn't work; only x86 works.
I'm new to the whole WinRT and COM world so I have no clue what is going wrong, and I need to be able to run the application on different platforms. Help is really much appreciated!
Version Info Visual Studio: 17.9.1 Windows SDK: 10.0.22621.0 CppWinRT NuGet: 2.0.220531.1 CsWinRT NuGet: 2.0.7 .NET: 6.0, 7.0, and 8.0 (i.e., I tried on all versions)
Context Here is how I created the projects...
- Created a project using "Windows Runtime Component (C++/WinRT)" template
- Implemented the
runtimeclassas follows:
// Class.idl
namespace RuntimeComponent1
{
[default_interface]
runtimeclass Class
{
Class();
Int32 MyProperty;
}
}
// Class.h
#pragma once
#include "Class.g.h"
namespace winrt::RuntimeComponent1::implementation
{
struct Class : ClassT<Class>
{
Class() = default;
int32_t MyProperty();
void MyProperty(int32_t value);
private:
int32_t m_data = 0;
};
}
namespace winrt::RuntimeComponent1::factory_implementation
{
struct Class : ClassT<Class, implementation::Class>
{
};
}
// Class.cpp
#include "pch.h"
#include "Class.h"
#include "Class.g.cpp"
namespace winrt::RuntimeComponent1::implementation
{
int32_t Class::MyProperty()
{
return m_data;
}
void Class::MyProperty(int32_t data)
{
m_data = data;
}
}
- Created a C# Console Application
- Added
CsWinRTNuGet - Added reference to the C++/WinRT Windows Runtime Component project
- Updated the
csprojto add the following property group:
<PropertyGroup>
<CsWinRTIncludes>RuntimeComponent1</CsWinRTIncludes>
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
</PropertyGroup>
- Updated
Program.csas follows:
using System;
RuntimeComponent1.Class c1 = new ();
c1.MyProperty = 5;
Console.WriteLine(c1.MyProperty);
Just tried the C#/WinRT Projection Sample. It works for x64 and gives the same runtime exception when running in x86!
For your local repro, can you confirm a couple things:
- You have the
DesktopCompatibleproperty set for both x86 and x64. - That the runtime component is being built for x64
With respect to the sample, given building for each architecture requires multiple builds, we only include x64 in the NuGet that is consumed as seen here. That is why you see that x86 errors. Uncommenting out x86 when you do the x86 build should make it pass.
@manodasanW, confirming that...
DesktopCompatibleproperty is set for both x86 and x64 platforms.- The runtime component is being built for x64.
But still the same runtime exception. I just want to clarify that if I removed the <PlatformTarget>x86</PlatformTarget> from the C# application, the application crashes at runtime when running in x86. I don't understand why even though the sample didn't include this PlatformTraget property.
Regarding the sample, I did indeed uncomment the x86 part but it was still not working for me until I removed the project from the solution and re-add it again (strange!). 😅
For reference, here are the project files...
RuntimeComponent1.vcxproj:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="Globals">
<CppWinRTOptimized>true</CppWinRTOptimized>
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
<CppWinRTGenerateWindowsMetadata>true</CppWinRTGenerateWindowsMetadata>
<MinimalCoreWin>true</MinimalCoreWin>
<ProjectGuid>{6797a314-3617-4d66-bae5-523705c117d0}</ProjectGuid>
<ProjectName>RuntimeComponent1</ProjectName>
<RootNamespace>RuntimeComponent1</RootNamespace>
<DefaultLanguage>en-US</DefaultLanguage>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
<AppContainerApplication>true</AppContainerApplication>
<ApplicationType>Windows Store</ApplicationType>
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.22621.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.22621.0</WindowsTargetPlatformMinVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v143</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<GenerateManifest>false</GenerateManifest>
<DesktopCompatible>true</DesktopCompatible>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="PropertySheet.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
<WarningLevel>Level4</WarningLevel>
<AdditionalOptions>%(AdditionalOptions) /bigobj</AdditionalOptions>
<!--Temporarily disable cppwinrt heap enforcement to work around xaml compiler generated std::shared_ptr use -->
<AdditionalOptions Condition="'$(CppWinRTHeapEnforcement)'==''">/DWINRT_NO_MAKE_DETECTION %(AdditionalOptions)</AdditionalOptions>
<PreprocessorDefinitions>_WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
<ModuleDefinitionFile>RuntimeComponent1.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="Class.h">
<DependentUpon>Class.idl</DependentUpon>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="Class.cpp">
<DependentUpon>Class.idl</DependentUpon>
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
</ItemGroup>
<ItemGroup>
<Midl Include="Class.idl" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="RuntimeComponent1.def" />
</ItemGroup>
<ItemGroup>
<None Include="PropertySheet.props" />
<Text Include="readme.txt">
<DeploymentContent>false</DeploymentContent>
</Text>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
</Target>
</Project>
ConsoleApp1.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0-windows10.0.22621.0</TargetFramework>
<TargetPlatformMinVersion>10.0.22621.0</TargetPlatformMinVersion>
<!-- Set Platform to AnyCPU to allow consumption of the projection assembly from any architecture. -->
<Platform>AnyCPU</Platform>
<!-- Workaround for MSB3271 error on processor architecture mismatch -->
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
<!-- With the following line, the app works only on x86 platform -->
<!-- Changing this to x64 doesn't make the app work on x64 -->
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\RuntimeComponent1\RuntimeComponent1.vcxproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.7" />
</ItemGroup>
<!--CsWinRT properties-->
<PropertyGroup>
<CsWinRTIncludes>RuntimeComponent1</CsWinRTIncludes>
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
</PropertyGroup>
</Project>
It turned out that the problem is in <Platform>AnyCPU</Platform>. Changing this to <Platforms>x86;x64</Platforms> fixed the problem for me. I'm not sure what is exactly wrong with using AnyCPU, so it will be nice if you can understand more what is the root cause of the issue and try to solve it in future release of CsWinRT.