Skip to content

Commit 4e77476

Browse files
Merge pull request #5738 from MicrosoftDocs/main
Auto Publish – main to live - 2025-08-26 18:21 UTC
2 parents 9044989 + 98f4609 commit 4e77476

File tree

5 files changed

+136
-40
lines changed

5 files changed

+136
-40
lines changed

hub/apps/develop/data-binding/data-binding-in-depth.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@ In the two examples below, the `Button.Content` property is the binding target,
162162
<Button Content="{Binding ...}" ... />
163163
```
164164

165+
If you're using C++/WinRT, then you'll need to add the [**BindableAttribute**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.bindableattribute) attribute to any runtime class that you want to use the [{Binding}](/windows/uwp/xaml-platform/binding-markup-extension) markup extension with.
166+
167+
> [!IMPORTANT]
168+
> If you're using C++/WinRT, then the [**BindableAttribute**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.bindableattribute) attribute is available with Windows App SDK. Without that attribute, you'll need to implement the [ICustomPropertyProvider](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.icustompropertyprovider) and [ICustomProperty](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.icustomproperty) interfaces in order to be able to use the [{Binding}](/windows/uwp/xaml-platform/binding-markup-extension) markup extension.
169+
165170
### Binding object declared using {x:Bind}
166171

167172
There's one step we need to do before we author our [{x:Bind}](/windows/uwp/xaml-platform/x-bind-markup-extension) markup. We need to expose our binding source class from the class that represents our page of markup. We do that by adding a property (of type `HostViewModel` in this case) to our `MainWindow` window class.
@@ -234,6 +239,22 @@ Code to support `{x:Bind}` is generated at compile-time in the partial classes f
234239
235240
### Binding object declared using {Binding}
236241

242+
If you're using C++/WinRT then, to use the [{Binding}](/windows/uwp/xaml-platform/binding-markup-extension) markup extension, you'll need to add the [**BindableAttribute**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.bindableattribute) attribute to any runtime class that you want to bind to. To use [{x:Bind}](/windows/uwp/xaml-platform/x-bind-markup-extension), you don't need that attribute.
243+
244+
```cppwinrt
245+
// HostViewModel.idl
246+
// Add this attribute:
247+
[Microsoft.UI.Xaml.Data.Bindable]
248+
runtimeclass HostViewModel : Microsoft.UI.Xaml.Data.INotifyPropertyChanged
249+
{
250+
HostViewModel();
251+
String NextButtonText;
252+
}
253+
```
254+
255+
> [!IMPORTANT]
256+
> If you're using C++/WinRT, then the [**BindableAttribute**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.bindableattribute) attribute is available with Windows App SDK. Without that attribute, you'll need to implement the [ICustomPropertyProvider](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.icustompropertyprovider) and [ICustomProperty](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.icustomproperty) interfaces in order to be able to use the [{Binding}](/windows/uwp/xaml-platform/binding-markup-extension) markup extension.
257+
237258
[{Binding}](/windows/uwp/xaml-platform/binding-markup-extension) assumes, by default, that you're binding to the [**DataContext**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.frameworkelement.datacontext) of your markup window. So we'll set the `DataContext` of our window to be an instance of our binding source class (of type `HostViewModel` in this case). The example below shows the markup that declares the binding object. We use the same `Button.Content` binding target we used in the "Binding target" section earlier, and we bind to the `HostViewModel.NextButtonText` property.
238259

239260
``` xaml

hub/apps/develop/launch/web-to-app-linking.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,21 @@ Create a JSON file (without the .json file extension) named **windows-app-web-li
6363

6464
Windows will make an https connection to your website and will look for the corresponding JSON file on your web server.
6565

66+
### Subdomain support
67+
68+
If your app manifest includes both a main domain (for example, `example.com`) and wildcard subdomains (for example, `*.example.com`), you need to add the `allowSubdomains` field to your JSON file to enable subdomain linking. Without this field, links to subdomains will open in the browser instead of your app.
69+
70+
``` JSON
71+
[{
72+
"packageFamilyName" : "Your app's package family name, e.g MyApp_9jmtgj1pbbz6e",
73+
"paths" : [ "*" ],
74+
"excludePaths" : [ "/news/*", "/blog/*" ],
75+
"allowSubdomains" : true
76+
}]
77+
```
78+
79+
When `allowSubdomains` is set to `true`, links to subdomains like `subdomain.example.com/path` will correctly open in your app instead of the browser.
80+
6681
### Wildcards
6782

6883
The JSON file example above demonstrates the use of wildcards. Wildcards allow you to support a wide variety of links with fewer lines of code. Web-to-app linking supports two types of wildcards in the JSON file:
@@ -90,6 +105,9 @@ If you have two apps that you would like to link to your website, list both of t
90105
}]
91106
```
92107

108+
> [!NOTE]
109+
> If your apps need to support subdomains, add `"allowSubdomains": true` to each app entry in the JSON file.
110+
93111
To provide the best experience for your users, use exclude paths to make sure that online-only content is excluded from the supported paths in your JSON file.
94112

95113
Exclude paths are checked first and if there is a match the corresponding page will be opened with the browser instead of the designated app. In the example above, ‘/news/\*’ includes any pages under that path while ‘/news\*’ (no forward slash trails 'news') includes any paths under ‘news\*’ such as ‘newslocal/’, ‘newsinternational/’, and so on.

hub/apps/develop/security/smart-cards.md

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,64 @@ Once [RequestVirtualSmartCardCreationAsync](/uwp/api/windows.devices.smartcards.
8484

8585
To authenticate with smart cards or virtual smart cards, your app must provide the behavior to complete challenges between the admin key data stored on the card, and the admin key data maintained by the authentication server or management tool.
8686

87+
### Obtaining the admin key
88+
89+
Before you can perform authentication, you need to obtain the admin key. The source of the admin key depends on your scenario:
90+
91+
- **For virtual smart cards you created**: Use the same admin key that was generated during card creation (as shown in the "Create a virtual smart card" section above). You should store this key securely for later authentication use.
92+
- **For existing physical or virtual smart cards**: The admin key is typically provided by your organization's IT department, card management system, or the service that issued the card.
93+
- **For development/testing**: You can generate a test admin key using [CryptographicBuffer.GenerateRandom](/uwp/api/windows.security.cryptography.cryptographicbuffer.generaterandom) as shown in the virtual card creation example below.
94+
95+
```cs
96+
// Example: Store the admin key from virtual card creation for later use
97+
IBuffer adminkey = CryptographicBuffer.GenerateRandom(24);
98+
99+
// Store this key securely in your app (e.g., in app settings, secure storage, etc.)
100+
// You'll need this same key for authentication operations
101+
102+
SmartCardProvisioning provisioning = await
103+
SmartCardProvisioning.RequestVirtualSmartCardCreationAsync(
104+
"Card friendly name",
105+
adminkey,
106+
pinPolicy);
107+
108+
// Save the adminkey for future authentication
109+
SaveAdminKeySecurely(adminkey);
110+
```
111+
112+
### Example admin key management methods
113+
114+
Here are example methods you might implement to securely store and retrieve admin keys:
115+
116+
```cs
117+
// Example implementation for storing admin key securely
118+
private void SaveAdminKeySecurely(IBuffer adminKey)
119+
{
120+
// Convert to string for storage (consider encryption for production)
121+
string adminKeyString = CryptographicBuffer.EncodeToBase64String(adminKey);
122+
123+
// Store in app settings (consider using Windows Credential Manager for production)
124+
ApplicationData.Current.LocalSettings.Values["SmartCardAdminKey"] = adminKeyString;
125+
}
126+
127+
// Example implementation for retrieving stored admin key
128+
private IBuffer GetStoredAdminKey()
129+
{
130+
// Retrieve from app settings
131+
string adminKeyString = ApplicationData.Current.LocalSettings.Values["SmartCardAdminKey"] as string;
132+
133+
if (string.IsNullOrEmpty(adminKeyString))
134+
{
135+
throw new InvalidOperationException("Admin key not found. Ensure the smart card was created by this app or the admin key was provided by your IT department.");
136+
}
137+
138+
// Convert back to IBuffer
139+
return CryptographicBuffer.DecodeFromBase64String(adminKeyString);
140+
}
141+
```
142+
143+
### Authentication algorithm
144+
87145
The following code shows how to support smart card authentication for services or modification of physical or virtual card details. If the data generated using the admin key on the card ("challenge") is the same as the admin key data provided by the server or management tool ("adminkey"), authentication is successful.
88146

89147
```cs
@@ -123,9 +181,14 @@ SmartCardProvisioning provisioning =
123181
SmartCardChallengeContext context =
124182
await provisioning.GetChallengeContextAsync();
125183

184+
// Use the admin key that was either:
185+
// 1. Generated during virtual card creation, or
186+
// 2. Provided by your IT department/card management system
187+
IBuffer adminKey = GetStoredAdminKey(); // Your method to retrieve the stored admin key
188+
126189
IBuffer response = ChallengeResponseAlgorithm.CalculateResponse(
127190
context.Challenge,
128-
rootPage.AdminKey);
191+
adminKey);
129192

130193
verifyResult = await context.VerifyResponseAsync(response);
131194
```
@@ -163,10 +226,13 @@ bool result = await provisioning.RequestPinResetAsync(
163226

164227
try
165228
{
229+
// Use the same admin key from card creation or your secure storage
230+
IBuffer adminKey = GetStoredAdminKey(); // Your method to retrieve the stored admin key
231+
166232
IBuffer response =
167233
ChallengeResponseAlgorithm.CalculateResponse(
168234
request.Challenge,
169-
rootPage.AdminKey);
235+
adminKey);
170236
request.SetResponse(response);
171237
}
172238
finally

hub/apps/windows-app-sdk/applifecycle/applifecycle-instancing.md

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -336,56 +336,47 @@ Unlike the UWP version of `RedirectActivationTo`, the Windows App SDK's implemen
336336

337337
### Redirection without blocking
338338

339-
Most apps will want to redirect as early as possible, before doing unnecessary initialization work. For some app types, initialization logic runs on an STA thread, which must not be blocked. AppInstance.RedirectActivationToAsync method is asynchronous, and the calling app must wait for the method to complete, otherwise the redirection will fail. However, waiting on an async call will block the STA. In these situations, call RedirectActivationToAsync in another thread, and set an event when the call completes. Then wait on that event using non-blocking APIs such as CoWaitForMultipleObjects. Here’s a C# sample for a WPF app.
339+
Most apps will want to redirect as early as possible, before doing unnecessary initialization work. For some app types, initialization logic runs on an STA thread, which must not be blocked. **AppInstance.RedirectActivationToAsync** method is asynchronous, and the calling app must wait for the method to complete, otherwise the redirection will fail. However, waiting on an async call will block the STA. In these situations, call **RedirectActivationToAsync** in another thread, and set an event when the call completes. Then wait on that event using non-blocking APIs.
340+
341+
The following is a C# sample for a WPF app:
340342

341343
```csharp
342-
private static bool DecideRedirection()
344+
private static bool DecideRedirection(string key)
343345
{
344346
bool isRedirect = false;
345347

346348
// Find out what kind of activation this is.
347349
AppActivationArguments args = AppInstance.GetCurrent().GetActivatedEventArgs();
348350
ExtendedActivationKind kind = args.Kind;
349-
if (kind == ExtendedActivationKind.File)
351+
352+
if (kind == ExtendedActivationKind.Launch)
350353
{
351354
try
352355
{
353-
// This is a file activation: here we'll get the file information,
354-
// and register the file name as our instance key.
355-
if (args.Data is IFileActivatedEventArgs fileArgs)
356+
AppInstance keyInstance = AppInstance.FindOrRegisterForKey(key);
357+
358+
// If we successfully registered the key, we must be the
359+
// only instance running that was activated for this key.
360+
if (keyInstance.IsCurrent)
361+
{
362+
// Hook up the Activated event, to allow for this instance of the app
363+
// getting reactivated as a result of multi-instance redirection.
364+
keyInstance.Activated += OnKeyInstanceActivated;
365+
}
366+
else
356367
{
357-
IStorageItem file = fileArgs.Files[0];
358-
AppInstance keyInstance = AppInstance.FindOrRegisterForKey(file.Name);
368+
isRedirect = true;
359369

360-
// If we successfully registered the file name, we must be the
361-
// only instance running that was activated for this file.
362-
if (keyInstance.IsCurrent)
370+
// Ensure we don't block the STA, by doing the redirect operation
371+
// in another thread, and using an event to signal when it has completed.
372+
var redirectSemaphore = new Semaphore(0, 1);
373+
Task.Run(() =>
363374
{
364-
// Hook up the Activated event, to allow for this instance of the app
365-
// getting reactivated as a result of multi-instance redirection.
366-
keyInstance.Activated += OnActivated;
367-
}
368-
else
369-
{
370-
isRedirect = true;
371-
372-
// Ensure we don't block the STA, by doing the redirect operation
373-
// in another thread, and using an event to signal when it has completed.
374-
redirectEventHandle = CreateEvent(IntPtr.Zero, true, false, null);
375-
if (redirectEventHandle != IntPtr.Zero)
376-
{
377-
Task.Run(() =>
378-
{
379-
keyInstance.RedirectActivationToAsync(args).AsTask().Wait();
380-
SetEvent(redirectEventHandle);
381-
});
382-
uint CWMO_DEFAULT = 0;
383-
uint INFINITE = 0xFFFFFFFF;
384-
_ = CoWaitForMultipleObjects(
385-
CWMO_DEFAULT, INFINITE, 1,
386-
new IntPtr[] { redirectEventHandle }, out uint handleIndex);
387-
}
388-
}
375+
keyInstance.RedirectActivationToAsync(args).AsTask().Wait();
376+
redirectSemaphore.Release();
377+
});
378+
redirectSemaphore.WaitOne();
379+
389380
}
390381
}
391382
catch (Exception ex)

hub/powertoys/hosts-file-editor.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ From the Settings menu, the following options can be configured:
4545
| :--- | :--- |
4646
| Open as administrator | Open as administrator to be able edit the hosts file. If disabled, the editor is run in read-only mode. Hosts File Editor is started as administrator by default. |
4747
| Show a warning at startup | Warns that editing hosts can change DNS names resolution. Enabled by default. |
48-
| Placement of additional content | Default value is **Top**. If **Bottom** is selected, the file header is moved below hosts settings to the bottom. |
49-
| Consider loopback addresses as duplicates | Loopback addresses (like 127.0.0.1 and ::1) are considered as duplicates. |
48+
| Placement of additional content | Determines where new host entries are added in the hosts file. Default value is **Top** (new entries are added near the top of the file after the default Windows header comments). If **Bottom** is selected, new entries are added at the end of the file. This affects the organization of your hosts file and can impact which entries take precedence if there are conflicts. |
49+
| Consider loopback addresses as duplicates | When enabled, multiple loopback addresses (127.0.0.1, ::1) pointing to the same hostname are treated as duplicates. This prevents adding redundant entries and helps avoid conflicts. When disabled, you can add multiple loopback entries for the same hostname, which may be useful for testing different network configurations but could lead to unexpected behavior. |
5050
| Encoding | Default value is **UTF-8**. If **UTF-8 with BOM** is selected, a Byte Order Mark (BOM) is included at the start of the file. |
5151

5252
## Troubleshooting

0 commit comments

Comments
 (0)