You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: hub/apps/develop/widgets/implement-widget-provider-cs.md
+61-1Lines changed: 61 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,6 +32,8 @@ In Visual Studio, create a new project. In the **Create a new project** dialog,
32
32
33
33
When the project loads, in **Solution Explorer** right-click the project name and select **Properties**. On the **General** page, scroll down to **Target OS** and select "Windows". Under **Target OS Version**, select version 10.0.19041.0 or later.
34
34
35
+
Note that this walkthrough uses a console app that displays the console window when the widget is activated to enable easy debugging. When you are ready to publish your widget provider app, you can convert the console application to a Windows application by following the steps in [Convert your console app to a Windows app](#convert-your-console-app-to-a-windows-app).
36
+
35
37
## Add references to the Windows App SDK and Windows Implementation Library NuGet packages
36
38
37
39
This sample uses the latest stable Windows App SDK NuGet package. In **Solution Explorer**, right-click **Dependencies** and select **Manage NuGet packages...**. In the NuGet package manager, select the **Browse** tab and search for "Microsoft.WindowsAppSDK". Select the latest stable version in the **Version** drop-down and then click **Install**.
@@ -238,6 +240,23 @@ The widget host calls [DeleteWidget](/windows/windows-app-sdk/api/winrt/microsof
For this example, in addition to removing the widget with the specified from the list of enabled widgets, we also check to see if the list is now empty, and if so, we set an event that will be used later to allow the app to exit when there are no enabled widgets. Inside your class definition, add the declaration of the [ManualResetEvent](dotnet/api/system.threading.manualresetevent) and a public accessor function.
@@ -528,9 +550,24 @@ CoRegisterClassObject(CLSID_Factory, new WidgetProviderFactory<WidgetProvider>()
528
550
Console.WriteLine("Registered successfully. Press ENTER to exit.");
529
551
Console.ReadLine();
530
552
531
-
CoRevokeClassObject(cookie);
553
+
if (GetConsoleWindow() !=IntPtr.Zero)
554
+
{
555
+
Console.WriteLine("Registered successfully. Press ENTER to exit.");
556
+
Console.ReadLine();
557
+
}
558
+
else
559
+
{
560
+
// Wait until the manager has disposed of the last widget provider.
561
+
using (varemptyWidgetListEvent=WidgetProvider.GetEmptyWidgetListEvent())
562
+
{
563
+
emptyWidgetListEvent.WaitOne();
564
+
}
565
+
566
+
CoRevokeClassObject(cookie);
567
+
}
532
568
```
533
569
570
+
Note that this code example imports the [GetConsoleWindow](/windows/console/getconsolewindow) function to determine if the app is running as a console application, the default behavior for this walkthrough. If function returns a valid pointer, we write debug information to the console. Otherwise, the app is running as a Windows app. In that case, we wait for the event that we set in [DeleteWidget](#deletewidget) method when the list of enabled widgets is empty, and the we exit the app. For information on converting the example console app to a Windows app, see [Convert your console app to a Windows app](#convert-your-console-app-to-a-windows-app).
534
571
535
572
## Package your widget provider app
536
573
@@ -704,6 +741,29 @@ For information about the design requirements for screenshot images and the nami
704
741
705
742
Make sure you have selected the architecture that matches your development machine from the **Solution Platforms** drop-down, for example "x64". In **Solution Explorer**, right-click your solution and select **Build Solution**. Once this is done, right-click your **ExampleWidgetProviderPackage** and select **Deploy**. In the current release, the only supported widget host is the Widgets Board. To see the widgets you will need to open the Widgets Board and select **Add widgets** in the top right. Scroll to the bottom of the available widgets and you should see the mock **Weather Widget** and **Microsoft Counting Widget** that were created in this tutorial. Click on the widgets to pin them to your widgets board and test their functionality.
706
743
744
+
## Debugging your widget provider
745
+
746
+
After you have pinned your widgets, the Widget Platform will start your widget provider application in order to receive and send relevant information about the widget. To debug the running widget you can either attach a debugger to the running widget provider application or you can set up Visual Studio to automatically start debugging the widget provider process once it's started.
747
+
748
+
In order to attach to the running process:
749
+
750
+
1. In Visual Studio click **Debug -> Attach to process**.
751
+
1. Filter the processes and find your desired widget provider application.
752
+
1. Attach the debugger.
753
+
754
+
In order to automatically attach the debugger to the process when it's initially started:
755
+
756
+
1. In Visual Studio click **Debug -> Other Debug Targets -> Debug Installed App Package**.
757
+
1. Filter the packages and find your desired widget provider package.
758
+
1. Select it and check the box that says Do not launch, but debug my code when it starts.
759
+
1. Click **Attach**.
760
+
761
+
## Convert your console app to a Windows app
762
+
763
+
To convert the console app created in this walkthrough to a Windows app, right-click the **ExampleWidgetProvider** project in **Solution Explorer** and select **Properties**. Under Application->General change the **Output type** from "Console Application" to "Windows Application".
764
+
765
+
:::image type="content" source="images/convert-to-windows-app-cs.png" alt-text="A screenshot showing the C# widget provider project properties with the output type set to Windows Application":::
766
+
707
767
## Publishing your widget
708
768
709
769
After you have developed and tested your widget you must publish your app on the Microsoft Store in order for users to install your widgets on their devices. For step by step guidance for publishing an app, see [Publish your app in the Microsoft Store](/windows/apps/publish/publish-your-app/overview?pivots=store-installer-msix).
Copy file name to clipboardExpand all lines: hub/apps/develop/widgets/implement-widget-provider-win32.md
+85-8Lines changed: 85 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -49,6 +49,49 @@ In the precompiled header file, pch.h, add the following include directives.
49
49
> [!NOTE]
50
50
> You must include the wil/cppwinrt.h header first, before any WinRT headers.
51
51
52
+
In order to handle shutting down the widget provider app correctly, we need to a custom implementation of **winrt::get_module_lock**. We pre-declare the **SignalLocalServerShutdown** method which will be defined in our main.cpp file and will set an event that signals the app to exit. Add the following code to your pch.h file, just below the `#pragma once` directive, before the other includes.
53
+
54
+
```cpp
55
+
//pch.h
56
+
#include<stdint.h>
57
+
#include<combaseapi.h>
58
+
59
+
// In .exe local servers the class object must not contribute to the module ref count, and use
60
+
// winrt::no_module_lock, the other objects must and this is the hook into the C++ WinRT ref counting system
61
+
// that enables this.
62
+
voidSignalLocalServerShutdown();
63
+
64
+
namespacewinrt
65
+
{
66
+
inline auto get_module_lock() noexcept
67
+
{
68
+
struct service_lock
69
+
{
70
+
uint32_t operator++() noexcept
71
+
{
72
+
return ::CoAddRefServerProcess();
73
+
}
74
+
75
+
uint32_t operator--() noexcept
76
+
{
77
+
const auto ref = ::CoReleaseServerProcess();
78
+
79
+
if (ref == 0)
80
+
{
81
+
SignalLocalServerShutdown();
82
+
}
83
+
return ref;
84
+
}
85
+
};
86
+
87
+
return service_lock{};
88
+
}
89
+
}
90
+
91
+
92
+
#defineWINRT_CUSTOM_MODULE_LOCK
93
+
```
94
+
52
95
## Add a WidgetProvider class to handle widget operations
53
96
54
97
In Visual Studio, right-click the `ExampleWidgetProvider` project in **Solution Explorer** and select **Add->Class**. In the **Add class** dialog, name the class "WidgetProvider" and click **Add**.
@@ -471,6 +514,17 @@ Add the header that defines the **WidgetProvider** class to the includes at the
471
514
#include<mutex>
472
515
```
473
516
517
+
Declare the event that will trigger our app to exit and the **SignalLocalServerShutdown** function that will set the event. Paste the following code in main.cpp.
Next, you will need to create a [CLSID](/windows/win32/com/com-class-objects-and-clsids) that will be used to identify your widget provider for COM activation. Generate a GUID in Visual Studio by going to **Tools->Create GUID**. Select the option "static const GUID =" and click **Copy** and then paste that into `main.cpp`. Update the GUID definition with the following C++/WinRT syntax, setting the GUID variable name widget_provider_clsid. Leave the commented version of the GUID because you will need this format later, when packaging your app.
Add the following class factory definition to `main.cpp`. This is boilerplate code that is not specific to widget provider implementations.
540
+
Add the following class factory definition to `main.cpp`. This is mostly boilerplate code that is not specific to widget provider implementations. Note that **CoWaitForMultipleObjects** waits for our shutdown event to be triggered before the app exits.
@@ -719,6 +772,30 @@ For information about the design requirements for screenshot images and the nami
719
772
720
773
Make sure you have selected the architecture that matches your development machine from the **Solution Platforms** drop-down, for example "x64". In **Solution Explorer**, right-click your solution and select **Build Solution**. Once this is done, right-click your **ExampleWidgetProviderPackage** and select **Deploy**. In the current release, the only supported widget host is the Widgets Board. To see the widgets you will need to open the Widgets Board and select **Add widgets** in the top right. Scroll to the bottom of the available widgets and you should see the mock **Weather Widget** and **Microsoft Counting Widget** that were created in this tutorial. Click on the widgets to pin them to your widgets board and test their functionality.
721
774
775
+
## Debugging your widget provider
776
+
777
+
After you have pinned your widgets, the Widget Platform will start your widget provider application in order to receive and send relevant information about the widget. To debug the running widget you can either attach a debugger to the running widget provider application or you can set up Visual Studio to automatically start debugging the widget provider process once it's started.
778
+
779
+
In order to attach to the running process:
780
+
781
+
1. In Visual Studio click **Debug -> Attach to process**.
782
+
1. Filter the processes and find your desired widget provider application.
783
+
1. Attach the debugger.
784
+
785
+
In order to automatically attach the debugger to the process when it's initially started:
786
+
787
+
1. In Visual Studio click **Debug -> Other Debug Targets -> Debug Installed App Package**.
788
+
1. Filter the packages and find your desired widget provider package.
789
+
1. Select it and check the box that says Do not launch, but debug my code when it starts.
790
+
1. Click **Attach**.
791
+
792
+
## Convert your console app to a Windows app
793
+
794
+
To convert the console app created in this walkthrough to a Windows app:
795
+
1. Right-click on the ExampleWidgetProvider project in **Solution Explorer** and select **Properties**. Navigate to **Linker -> System** and change **SubSystem** from "Console" to "Windows". This can also be done by adding <SubSystem>Windows</SubSystem> to the <Link>..</Link> section of the .vcxproj.
796
+
1. In main.cpp, change `int main()` to `int WINAPI wWinMain(_In_ HINSTANCE /*hInstance*/, _In_opt_ HINSTANCE /*hPrevInstance*/, _In_ PWSTR pCmdLine, _In_ int /*nCmdShow*/)`.
797
+
798
+
:::image type="content" source="images/convert-to-windows-app-cpp.png" alt-text="A screenshot showing the C++ widget provider project properties with the output type set to Windows Application":::
722
799
723
800
## Publishing your widget
724
801
@@ -728,4 +805,4 @@ After you have developed and tested your widget you must publish your app on the
728
805
729
806
After your app has been published on the Microsoft Store, you can request for your app to be included in the widgets Store Collection that helps users discover apps that feature Windows Widgets. To submit your request, see [Submit your Widget information for addition to the Store Collection](https://forms.office.com/pages/responsepage.aspx?id=v4j5cvGGr0GRqy180BHbRzIsoQuXjKhIoGxHt2iT41RUNjJJM09JSlFBOFJTTDJQT1dOODBEWlNYQy4u&wdLOR=c3CBC769A-D2E1-4558-8FAF-09B14B60351D).
730
807
731
-
:::image type="content" source="images/widgets-store-collection.png" alt-text="Screenshot of the Microsoft Store showing the widgets collection that allows users to discover apps that feature Windows Widgets.":::
808
+
:::image type="content" source="images/widgets-store-collection.png" alt-text="Screenshot of the Microsoft Store showing the widgets collection that allows users to discover apps that feature Windows Widgets.":::
0 commit comments