CsWinRT
CsWinRT copied to clipboard
ApplicationTrigger RequestAsync throws COMException
Describe the bug I am trying to implement background tasks for .NET MAUI apps. In the past Xamarin Forms used UWP, but now that Maui is based on WinUI3, I have to implement background tasks using the WinUI3 method with COMServer. Using code from this sample https://github.com/microsoft/DesktopBridgeToUWP-Samples/tree/master/Samples/BackgroundTaskWinMainComSample, I could get the background tasks triggered with a TimeTrigger or by manually triggering it through Visual Studio. However, when I use an ApplicationTrigger, and then call RequestAsync(). It throws COMException with error value E_FAIL | Unspecified failure | 0x80004005.
*Edit : seems that prior to calling RequestAsync, builder.Register() throws 0x80070032
To Reproduce Creating a trigger and initializing the view.:
public MainPage()
{
InitializeComponent();
_trigger = new ApplicationTrigger();
}
Function to register to the COMServer:
static void RegisterProcessForBackgroundTask<TaskType, TaskInterface>() where TaskType : TaskInterface, new()
{
// If the application is compiled with the full .NET frameworks, the
// built-in RegistrationServices class may be used to use COM server
// registration APIs.
/*
RegistrationServices registrationServices = new RegistrationServices();
registrationServices.RegisterTypeForComClients(typeof(TaskType),
RegistrationClassContext.LocalServer,
RegistrationConnectionType.MultipleUse);
*/
// This app is currently using the .NET Core framework. Use the
// manual C++ imported implementation of the CoRegisterClassObject
// API.
Guid taskGuid = typeof(TaskType).GUID;
ComApi.CoRegisterClassObject(ref taskGuid,
new ComApi.BackgroundTaskFactory<TaskType, TaskInterface>(),
ComApi.CLSCTX_LOCAL_SERVER,
ComApi.REGCLS_MULTIPLEUSE,
out _RegistrationToken);
}
Registering background task:
public IBackgroundTaskRegistration RegisterBackgroundTaskWithSystem(IBackgroundTrigger trigger, Guid entryPointClsid, string taskName)
{
foreach (var registrationIterator in BackgroundTaskRegistration.AllTasks)
{
if (registrationIterator.Value.Name == taskName)
{
return registrationIterator.Value;
}
}
BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
builder.SetTrigger(trigger);
builder.SetTaskEntryPointClsid(entryPointClsid);
builder.Name = taskName;
BackgroundTaskRegistration registration;
try
{
registration = builder.Register();
}
catch (Exception)
{
registration = null;
}
return registration;
}
Registering background tasks by calling the helper functions above on button click:
private async void Button_Clicked(object sender, EventArgs e)
{
BackgroundExecutionManager.RemoveAccess();
var requestStatus = await BackgroundExecutionManager.RequestAccessAsync();
if (requestStatus != BackgroundAccessStatus.AlwaysAllowed && requestStatus != BackgroundAccessStatus.AllowedSubjectToSystemPolicy)
{
// Depending on the value of requestStatus, provide an appropriate response
// such as notifying the user which functionality won't work as expected
Debug.WriteLine("Access Denied By RequestAccessAsync");
return;
}
RegisterBackgroundTaskWithSystem(_trigger, typeof(BackgroundTask).GUID, typeof(BackgroundTask).Name);
RegisterProcessForBackgroundTask<BackgroundTask, IBackgroundTask>();
if(_trigger != null)
{
await _trigger.RequestAsync();
}
}
appx:
<Extensions>
<!-- Register a COM32 server CLSID for handling background activation -->
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:ExeServer Executable="BackgroundTaskTest\BackgroundTaskTest.exe" DisplayName="Background Activator">
<!-- this CLSID is taken from BackgroundTaskTest::BackgroundTask -->
<com:Class Id="A8082001-73F7-4607-8521-60F03476E462" DisplayName="Notification Scheduler"/>
</com:ExeServer>
</com:ComServer>
</com:Extension>
</Extensions>
Expected behavior RequestAsync() executes successfully and the background tasks is run.
Version Info
Additional context Seeing some similar discussion about this in https://github.com/microsoft/CsWinRT/discussions/1296. I'm not 100% sure which project owns ApplicationTrigger but any suggestions or workarounds would be great. I basically want to trigger a background task through code, unfortunately TimeTrigger needs a minimum 15 minute delay to trigger which is too long. Thanks