Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym artykule opisano kilka mechanizmów, które dostawcy aplikacji dla akcji aplikacji w systemie Windows mogą implementować w celu ograniczenia zestawu aplikacji, które mogą wykonywać zapytania dotyczące akcji lub wywoływać ją. Jest to opcjonalny krok implementacji przeznaczony do obsługi scenariuszy, takich jak akcje korzystające z zasobów, które mają koszty użycia, takie jak usługi LLM oparte na subskrypcji.
Ustaw wartość allowedAppInvokers w pliku JSON definicji akcji
Plik JSON definicji akcji, który służy do rejestrowania akcji w systemie, zawiera pole allowedAppInvokers dla każdej definicji akcji. Wartość tego pola to lista identyfikatorów modelu użytkownika aplikacji (AUMID), które mogą odnaleźć akcję za pomocą wywołania metody GetActionsForInputs lub GetAllActions. Obsługiwane są symbole wieloznaczne. Wartość "*" będzie zgodna ze wszystkimi identyfikatorami AppUserModelID. Jeśli aplikacja allowedAppInvokers zostanie pominięta lub jest pustą listą, żadne aplikacje nie będą mogły odnaleźć akcji. Aby uzyskać więcej informacji na temat identyfikatorów AppUserModelID, zobacz Identyfikatory modelu użytkownika aplikacji. Aby uzyskać szczegółowe informacje na temat pliku JSON definicji akcji, zobacz Schemat JSON definicji akcji dla akcji aplikacji w systemie Windows.
Należy pamiętać, że pole allowedAppInvokers ogranicza tylko aplikacje, które mogą wykonywać zapytania dotyczące akcji. Ze względu na sposób, w jaki dostawcy działań są zarejestrowani w systemie, aplikacje nadal mogą wywoływać działania, nawet jeśli są ograniczone do wykonywania zapytań przez allowedAppInvokers. W pozostałej części tego artykułu omówiono różne sposoby ograniczania wywołań dla akcji w czasie wykonywania.
Wykrywanie wywołującego podczas korzystania z aktywacji identyfikatora URI
W poniższej sekcji opisano różne metody wykrywania wywołującego akcję w czasie wykonywania dla aplikacji dostawców akcji wykorzystujących uruchamianie przy użyciu identyfikatora URI.
Pobierz nazwę rodziny pakietów dzwoniącego (tylko aktywacja bogata)
Aplikacje dostawcy, które korzystają z nowoczesnej, rozbudowanej aktywacji, mogą sprawdzać wartość właściwości CallerPackageFamilyName klasy ProtocolForResultsActivatedEventArgs przekazywanej do aplikacji dostawcy podczas uruchamiania. Jeśli wartość kończy się ciągiem "_cw5n1h2txyewy", akcja została wywołana przez system Windows. Aby uzyskać więcej informacji na temat rozbudowanej aktywacji, zobacz Rozbudowana aktywacja przy użyciu interfejsu API cyklu życia aplikacji.
const string windowsPFN = "_cw5n1h2txyewy";
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
var eventargs = AppInstance.GetCurrent().GetActivatedEventArgs();
if ((eventargs != null) && (eventargs.Kind == ExtendedActivationKind.ProtocolForResults))
{
ProtocolForResultsActivatedEventArgs? protocolForResultsArgs = eventargs.Data as ProtocolForResultsActivatedEventArgs;
if (protocolForResultsArgs.CallerPackageFamilyName.EndsWith(windowsPFN))
{
// Perform the action if invoked by Windows
}
}
_window = new MainWindow();
_window.Activate();
}
Użyj parametru ciągu zapytania $.Token URI
Dostawcy akcji korzystający z aktywacji identyfikatora URI deklarują ten identyfikator, który uruchamia akcję, w pliku manifestu definicji akcji w formacie JSON. Istnieje specjalny parametr $.Token ciągu zapytania, który instruuje Action Runtime do przekazania unikalnego tokenu identyfikatora w ciągu zapytania URI uruchamiania przy uruchomieniu aplikacji. Poniższy przykład przedstawia składnię deklarowania identyfikatora URI za pomocą parametru $.Token .
"invocation": {
"type": "Uri",
"uri": "urilaunchaction-protocol://messageaction?token=${$.Token}",
"inputData": {
"message": "${message.Text}"
}
}
Po uruchomieniu akcji pobierz parametr ciągu zapytania Token z identyfikatora URI aktywacji. Przekaż ten token podczas wywołania metody GetActionInvocationContextFromToken. Środowisko uruchomieniowe akcji zweryfikuje token względem tokenu podanego podczas uruchamiania dostawcy akcji. Jeśli wartości są zgodne, zwracany jest prawidłowy obiekt ActionInvocationContext , sprawdzając, czy akcja została wywołana przez środowisko uruchomieniowe akcji.
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
var eventargs = AppInstance.GetCurrent().GetActivatedEventArgs();
if ((eventargs != null) && (eventargs.Kind == ExtendedActivationKind.ProtocolForResults))
{
ProtocolForResultsActivatedEventArgs? protocolForResultsArgs = eventargs.Data as ProtocolForResultsActivatedEventArgs;
using (ActionRuntime runtime = ActionRuntimeFactory.CreateActionRuntime())
{
var launchUri = protocolForResultsArgs.Uri;
var query = HttpUtility.ParseQueryString(launchUri.Query);
var token = query["Token"];
if(token != null)
{
var context = runtime.GetActionInvocationContextFromToken(token);
if(context == null)
{
// Caller is not Action Runtime
return;
}
}
Należy pamiętać, że w tym przykładzie użyto metod pomocnika udostępnianych przez pakiet NuGet Microsoft.AI.Actions. Aby uzyskać informacje na temat odwoływania się do tego pakietu przez dostawcę akcji, zobacz Implementowanie uruchamiania identyfikatora URI dla akcji aplikacji w systemie Windows.
Wykrywanie obiektu wywołującego w czasie wykonywania z poziomu aktywacji modelu COM
W poniższej sekcji przedstawiono proces pobierania identyfikatora AUMID aplikacji, która wywołała akcję w czasie wykonywania. Przykłady w tej sekcji będą sprawdzane pod kątem identyfikatora AUMID środowiska uruchomieniowego akcji. Aplikacje mogą filtrować według identyfikatora AUMID innych aplikacji lub użyć nazwy rodziny pakietów (PFN) do filtrowania wszystkich aplikacji zawartych w określonym pakiecie.
Dodawanie odwołania do pakietu NuGet CsWin32
Przykładowy kod pokazany w tej sekcji używa interfejsów API Win32 do pobrania nazwy rodziny pakietów obiektu wywołującego. Aby łatwiej wywoływać interfejsy API Win32 z aplikacji języka C#, w tym przykładzie zostanie użyty pakiet NuGet CsWin32, który generuje otoki języka C# dla interfejsów API Win32 w czasie kompilacji. Aby uzyskać więcej informacji, zobacz repozytorium GitHub CsWin32.
- W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy projekt i wybierz polecenie Zarządzaj pakietami NuGet....
- Na karcie Przeglądaj wyszukaj ciąg "Microsoft.Windows.CsWin32".
- Wybierz ten pakiet i kliknij przycisk Zainstaluj, postępując zgodnie ze wszystkimi monitami.
Po zainstalowaniu tego pakietu wyświetli się plik readme szczegółowo opisujący, jak określić interfejsy API Win32, dla których zostaną wygenerowane opakowania języka C#. W tym celu należy utworzyć plik tekstowy, który zawiera listę metod, których będziesz używać.
- W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy projekt i wybierz polecenie Dodaj nowy> element....
- Wybierz szablon TextFile .
- Nadaj plikowi nazwę "NativeMethods.txt" i kliknij przycisk Dodaj
- Kliknij dwukrotnie NativeMethods.txt, aby otworzyć plik i dodać następujące wiersze.
CoRegisterClassObject
CoRevokeClassObject
CoImpersonateClient
OpenThreadToken
GetCurrentThread
CoRevertToSelf
GetPackageFamilyNameFromToken
GetLastError
Zaktualizuj klasę ActionProvider, aby sprawdzić PFN wywoływacza akcji
Poniższa metoda pomocnika używa interfejsów API Win32 określonych w NativeMethods.txt w celu pobrania identyfikatora AUMID dla procesu wywołującego i zwraca wartość true, jeśli pasuje do przekazanego identyfikatora AUMID. Aby uzyskać szczegółowe wyjaśnienie sposobu działania tego kodu, zobacz Personifikacja klienta.
static bool WasInvokedByAUMID(string aumid)
{
Windows.Win32.Foundation.HRESULT hr = PInvoke.CoImpersonateClient();
var RPC_E_CALL_COMPLETE = unchecked((int)0x80010117);
if (hr.Value == RPC_E_CALL_COMPLETE)
{
return false;
}
Microsoft.Win32.SafeHandles.SafeFileHandle hThreadTok;
bool bRes = PInvoke.OpenThreadToken(
new Microsoft.Win32.SafeHandles.SafeFileHandle(PInvoke.GetCurrentThread(), true),
Windows.Win32.Security.TOKEN_ACCESS_MASK.TOKEN_QUERY,
true,
out hThreadTok
);
if (bRes == false)
{
var e = Marshal.GetLastWin32Error();
Console.WriteLine("Unable to read thread token. " + e);
hThreadTok.Close();
return false;
}
PInvoke.CoRevertToSelf();
var invokerAumid = new Span<char>();
uint aumidLength = 0;
PInvoke.GetApplicationUserModelIdFromToken(hThreadTok, ref aumidLength, invokerAumid);
invokerAumid = new char[aumidLength].AsSpan();
PInvoke.GetApplicationUserModelIdFromToken(hThreadTok, ref aumidLength, invokerAumid);
hThreadTok.Close();
if (invokerAumid.Trim('\0').EndsWith(aumid))
{
return true;
}
else
{
return false;
}
}
Ze względu na sposób, w jaki CoImpersonateClient jest zaimplementowany, ważne jest, aby wywołać metodę pomocniczą podczas wykonywania akcji, a nie podczas procedury uruchamiania aplikacji.
Poniższy przykład ilustruje sprawdzenie identyfikatora AUMID środowiska uruchomieniowego akcji w akcji zaimplementowanej przy użyciu platformy generowania kodu Microsoft.AI.Actions.
const string actionRuntimeAUMID = "_cw5n1h2txyewy!ActionRuntime";
[WindowsActionInputCombination(
Inputs = ["Contact", "Message"],
Description = "Send '${Message.Text}' to '${Contact.Text}'"
)]
public async Task<SendMessageResult> SendMessage(
[Entity(Name = "Contact")] string contact,
[Entity(Name = "Message")] string? message,
InvocationContext context)
{
if (!WasInvokedByAUMID(actionRuntimeAUMID))
{
context.Result = ActionInvocationResult.Unavailable;
return new SendMessageResult
{
Text = context.EntityFactory.CreateTextEntity("")
};
}
// Your action logic here
string result = await ProcessMessageAsync(contact, message);
return new SendMessageResult
{
Text = context.EntityFactory.CreateTextEntity(result)
};
}