Reputation: 99
I currently have a working project where I am consuming a C# WinRT component in a win32 console app using Registration-free Winrt. Everything is working well, but the problem arises when I try to use Async methods from the C# component. Since Task
s are not WinRT types, I searched around to find a solution. So what's the correct way to go about calling Async methods from a C# WinRT component?
I'm using winmdidl.exe and midlrt.exe to create my WinRT comp header file for the console app. I've also included `"Winrt/Windows.Foundation.h".
I've tried "How to expose async methods in a Windows Runtime Component". This will build, but it errors at runtime with the daunting (imo) Class not registered
. It's also from 2014.
C# WinRT component:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
namespace MyComp
{
public sealed class MyLib
{
public static string OtherMethods() // only working method
{
return "string";
}
// Below methods results with `Class not registered` error
public static IAsyncOperation<string> TestAsync() // I think this is the problem
{
return TestAsyncHelper().AsAsyncOperation();
}
private static async Task<string> TestAsyncHelper()
{
// do stuff here
return "string";
}
// ******* Update ****
public static IDictionary<int, string> GetMapOfNames()
{
Dictionary<int, string> retval = new Dictionary<int, string>();
retval.Add(1, "one");
retval.Add(2, "two");
retval.Add(3, "three");
retval.Add(42, "forty-two");
retval.Add(100, "one hundred");
return retval;
}
}
}
I noticed that this is happening with every WinRT type that isn't primitive. I'm trying to implement an IList<int>
or IDictionary<int, string>
and neither of those work either. I found "Passing managed types to the Windows Runtime" which lead to "Returning managed types from your component", But every attempt I've tried has resulted in the Class not registered
error. In the linked articles, it mentions that when passing .Net types to the WinRT component, it would appear as the corresponding WinRT type on the other side, which sounds like it should just work. I've also tried to use IMap<int, string>
, but that errors with IMap<K, V> is inaccessible due to its protection level
. I've updated the sample code.
Upvotes: 0
Views: 154
Reputation: 1
I know it's a few years too late, maybe you already found the solution yourself, but I had the same problem for a couple of days and realized the solution.
Upon taking a looking at some samples in the CsWinRT project, especially this one, AuthoringDemo, which has a C++ console application (CppConsoleApp) consuming a C#/WinRT project (AuthoringDemo), I realized I missed the declaration of the tag <CsWinRTWindowsMetadata>10.0.19041.0</CsWinRTWindowsMetadata>
that's present in the file AuthoringDemo/AuthoringDemo.csproj
. This tag is describe in the CsWinRT documentation as "Specifies the source for Windows metadata" and its default value should be $(WindowsSDKVersion)
, but it seems like this value is never setup and the C#/WinRT projection doesn't get to export some runtime declarations.
After adding this tag with the correct SDK version (depends on your project setup), it recognized IAsyncAction
, IList<>
and IAsncOperation<>
and probably all other runtime non-primitive projections. This AuthoringDemo.csproj should have all you need to export to WinRT correctly.
It's also worth noting that CppConsoleApp has a manifest file CppConsoleApp.exe.manifest that must declare the C# classes you want WinRT to activate. Your C++ application should one similliar too.
Upvotes: 0