Note
Access to this page requires authorization. You can try signing in or .
Access to this page requires authorization. You can try .
Create and register a Win32 COM background task
Tip
The BackgroundTaskBuilder.SetTaskEntryPointClsid method is available starting in Windows 10, version 2004.
Note
This scenario is only applicable to packaged Win32 apps. UWP applications will encounter errors trying to implement this scenario.
Important APIs
Create a COM background task class and register it to run in your full trust packaged Win32 app in response to triggers. You can use background tasks to provide functionality when your app is suspended or not running. This topic demonstrates how to create and register a background task that can run in your foreground app process or another process.
Create the Background Task class
You can run code in the background by writing classes that implement the IBackgroundTask interface. This code runs when a specific event is triggered by using, for example, SystemTrigger or TimeTrigger.
The following steps show you how to write a new class that implements the IBackgroundTask interface and add it to your main process.
- See these instructions to reference WinRT APIs in your packaged Win32 application solution. This is required to use the IBackgroundTask and related APIs.
- In that new class, implement the IBackgroundTask interface. The IBackgroundTask.Run method is a required entry point that will be called when the specified event is triggered; this method is required in every background task.
Note
The background task class itself—and all other classes in the background task project—need to be public.
The following sample code shows a basic a background task class that counts primes and writes it to a file until it is requested to be canceled.
The C++/WinRT example implements the background task class as a COM coclass.
Add the support code to instantiate the COM class
In order for the background task to be activated into a full trust Win32 application, the background task class must have support code such that COM understands how to start the app process if it is not running, and then understanding which instance of the process is currently the server for handling new activations for that background task.
- COM needs to understand how to launch the app process if it is not running already. The app process that hosts the background task code needs to be declared in the package manifest. The following sample code shows how the SampleTask is hosted inside SampleBackgroundApp.exe. When the background task is launched when no process is running, SampleBackgroundApp.exe will be launched with process arguments "-StartSampleTaskServer".
<Extensions>
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:ExeServer Executable="SampleBackgroundApp\SampleBackgroundApp.exe" DisplayName="SampleBackgroundApp" Arguments="-StartSampleTaskServer">
<com:Class Id="14C5882B-35D3-41BE-86B2-5106269B97E6" DisplayName="Sample Task" />
</com:ExeServer>
</com:ComServer>
</com:Extension>
</Extensions>
- Once your process is started with the right arguments, it should tell COM that it is the current COM server for new instances of SampleTask. The following sample code shows how the application process should register itself with COM. Note these samples indicate how the process would declare itself as the COM server for SampleTask for at least one instance to complete before exiting. This is optional, and handling a background task may start your main process functions.
class SampleTaskServer
{
SampleTaskServer()
{
comRegistrationToken = 0;
waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
}
~SampleTaskServer()
{
Stop();
}
public void Start()
{
RegistrationServices registrationServices = new RegistrationServices();
comRegistrationToken = registrationServices.RegisterTypeForComClients(typeof(SampleTask), RegistrationClassContext.LocalServer, RegistrationConnectionType.MultipleUse);
// Either have the background task signal this handle when it completes, or never signal this handle to keep this
// process as the COM server until the process is closed.
waitHandle.WaitOne();
}
public void Stop()
{
if (comRegistrationToken != 0)
{
RegistrationServices registrationServices = new RegistrationServices();
registrationServices.UnregisterTypeForComClients(registrationCookie);
}
waitHandle.Set();
}
private int comRegistrationToken;
private EventWaitHandle waitHandle;
}
var sampleTaskServer = new SampleTaskServer();
sampleTaskServer.Start();
class SampleTaskServer
{
public:
SampleTaskServer()
{
waitHandle = EventWaitHandle(false, EventResetMode::AutoResetEvent);
comRegistrationToken = 0;
}
~SampleTaskServer()
{
Stop();
}
void Start()
{
try
{
com_ptr<IClassFactory> taskFactory = make<TaskFactory>();
winrt::check_hresult(CoRegisterClassObject(__uuidof(SampleTask),
taskFactory.get(),
CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE,
&comRegistrationToken));
// Either have the background task signal this handle when it completes, or never signal this handle to
// keep this process as the COM server until the process is closed.
waitHandle.WaitOne();
}
catch (...)
{
// Indicate an error has been encountered.
}
}
void Stop()
{
if (comRegistrationToken != 0)
{
CoRevokeClassObject(comRegistrationToken);
}
waitHandle.Set();
}
private:
DWORD comRegistrationToken;
EventWaitHandle waitHandle;
};
SampleTaskServer sampleTaskServer;
sampleTaskServer.Start();
Register the background task to run
- Find out whether the background task is already registered by iterating through the BackgroundTaskRegistration.AllTasks property. This step is important; if your app doesn't check for existing background task registrations, it could easily register the task multiple times, causing issues with performance and maxing out the task's available CPU time before work can complete. An application is free to use the same entry point to handle all background tasks and use other properties like the Name or TaskId assigned to a BackgroundTaskRegistration to decide what work should be done.
The following example iterates on the AllTasks property and sets a flag variable to true if the task is already registered.
var taskRegistered = false;
var sampleTaskName = "SampleTask";
foreach (var task in BackgroundTaskRegistration.AllTasks)
{
if (task.Value.Name == sampleTaskName)
{
taskRegistered = true;
break;
}
}
// The code in the next step goes here.
bool taskRegistered = false;
std::wstring sampleTaskName = L"SampleTask";
auto allTasks = BackgroundTaskRegistration::AllTasks();
for (auto const& task : allTasks)
{
if (task.Value().Name() == sampleTaskName)
{
taskRegistered = true;
break;
}
}
// The code in the next step goes here.
- If the background task is not already registered, use BackgroundTaskBuilder to create an instance of your background task. The task entry point should be the name of your background task class prefixed by the namespace.
The background task trigger controls when the background task will run. For a list of possible triggers, see the Windows.ApplicationModel.Background Namespace.
Note
Only a subset of triggers are supported for packaged Win32 background tasks.
For example, this code creates a new background task and sets it to run it on a 15-minute recurring :
if (!taskRegistered)
{
var builder = new BackgroundTaskBuilder();
builder.Name = sampleTaskName;
builder.SetTaskEntryPointClsid(typeof(SampleTask).GUID);
builder.SetTrigger(new TimeTrigger(15, false));
}
// The code in the next step goes here.
if (!taskRegistered)
{
BackgroundTaskBuilder builder;
builder.Name(sampleTaskName);
builder.SetTaskEntryPointClsid(__uuidof(SampleTask));
builder.SetTrigger(TimeTrigger(15, false));
}
// The code in the next step goes here.
- You can add a condition to control when your task will run after the trigger event occurs (optional). For example, if you don't want the task to run until internet is available, use the condition InternetAvailable. For a list of possible conditions, see SystemConditionType.
The following sample code assigns a condition requiring the user to be present:
builder.AddCondition(new SystemCondition(SystemConditionType.InternetAvailable));
// The code in the next step goes here.
builder.AddCondition(SystemCondition{ SystemConditionType::InternetAvailable });
// The code in the next step goes here.
- Register the background task by calling the Register method on the BackgroundTaskBuilder object. Store the BackgroundTaskRegistration result so it can be used in the next step. Note that the register function may return errors in the form of exceptions. Be sure to call Register in a try-catch.
The following code registers the background task and stores the result:
try
{
var task = builder.Register();
}
catch (...)
{
// Indicate an error was encountered.
}
try
{
auto task = builder.Register();
}
catch (...)
{
// Indicate an error was encountered.
}
Bringing it all together
The following code samples show the complete code required to run and register your COM Win32 background task:
Remarks
Unlike UWP apps that can run background tasks in modern standby, Win32 apps cannot run code from the lower power phases of modern standby. See Modern Standby to learn more.
[!NOTE] Download the Win32 COM background task sample to see similar code examples in the context of a complete Desktop Bridge app that uses background tasks.
See the following related topics for API reference, background task conceptual guidance, and more detailed instructions for writing apps that use background tasks.
Related topics
- Respond to system events with background tasks
- Register a background task
- Set conditions for running a background task
- Use a maintenance trigger
- Handle a cancelled background task
- Monitor background task progress and completion
- Run a background task on a timer
- Create and register an in-process background task.
- Convert an out-of-process background task to an in-process background task
Background task guidance
- Guidelines for background tasks
- Debug a background task
- How to trigger suspend, resume, and background events in UWP apps (when debugging)
Background Task API Reference
Feedback
Was this page helpful?
