Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo descreve vários mecanismos que os aplicativos de provedor para Ações de Aplicativo no Windows podem implementar para limitar o conjunto de aplicativos que podem consultar ou invocar uma ação. Essa é uma etapa de implementação opcional projetada para dar suporte a cenários como ações que consomem recursos que têm custos por uso, como serviços LLM baseados em assinatura.
Definir allowedAppInvokers no arquivo JSON de definição de ação
O arquivo JSON de definição de ação, que é usado para registrar uma ação com o sistema, inclui um campo allowedAppInvokers para cada definição de ação. O valor desse campo é uma lista de IDs do Modelo de Usuário do Aplicativo (AUMID) que podem descobrir a ação por meio de uma chamada para GetActionsForInputs ou GetAllActions. Os caracteres curinga têm suporte. "*" corresponderá a todos os AppUserModelIDs. Se allowedAppInvokers for omitido ou for uma lista vazia, nenhum aplicativo poderá descobrir a ação. Para obter mais informações sobre AppUserModelIDs, consulte IDs do modelo de usuário do aplicativo. Para obter detalhes do arquivo JSON de definição de ação, consulte O esquema JSON de definição de ação para Ações de Aplicativo no Windows.
Observe que o campo allowedAppInvokers limita apenas quais aplicativos podem consultar para uma ação. Devido às maneiras pelas quais os provedores de ações são registrados com o sistema, ainda é possível que os aplicativos invoquem uma ação, mesmo que sejam impedidos de consultar por allowedAppInvokers. O restante deste artigo discute diferentes maneiras de restringir os chamadores para uma ação em runtime.
Detectar o chamador ao usar a ativação de lançamento do URI
A seção a seguir descreve diferentes maneiras de detectar o chamador de uma ação durante a execução para aplicativos do provedor de ações que usam ativação por lançamento de URI.
Obter o nome da família do pacote do chamador (somente ativação avançada)
Os aplicativos de provedor que usam ativação moderna e avançada podem verificar o valor da propriedade CallerPackageFamilyName da classe ProtocolForResultsActivatedEventArgs passada para seu aplicativo provedor na inicialização. Se o valor terminar com a cadeia de caracteres "_cw5n1h2txyewy", a ação será invocada pelo Windows. Para obter mais informações sobre ativação avançada, consulte Ativação avançada com a API de ciclo de vida do aplicativo.
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();
}
Use o parâmetro de cadeia de caracteres de consulta URI do $.Token
Os provedores de ação que usam a ativação de URI declaram o URI que inicia sua ação no arquivo de manifesto JSON de definição de ação. Há um parâmetro $.Token de cadeia de caracteres de consulta especial que instrui o Action Runtime a passar um token de identificador exclusivo na cadeia de caracteres de consulta do URI de inicialização quando seu aplicativo é invocado. O exemplo a seguir mostra a sintaxe para declarar um URI com o $.Token parâmetro.
"invocation": {
"type": "Uri",
"uri": "urilaunchaction-protocol://messageaction?token=${$.Token}",
"inputData": {
"message": "${message.Text}"
}
}
Quando a ação for iniciada, recupere o parâmetro Token de cadeia de caracteres de consulta do URI de ativação. Passe esse token em uma chamada de GetActionInvocationContextFromToken. O Action Runtime validará o token em relação ao token fornecido ao iniciar o provedor de ações. Se os valores corresponderem, um objeto ActionInvocationContext válido será retornado, validando que a ação foi invocada pelo Action Runtime.
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;
}
}
Observe que este exemplo usa métodos auxiliares fornecidos pelo pacote NuGet Microsoft.AI.Actions. Para obter informações sobre como referenciar esse pacote de um provedor de ações, consulte Implementar o lançamento de URI para Ações para Aplicativos no Windows.
Detectar o chamador em runtime da ativação COM
A seção a seguir explica o processo de obtenção do AUMID do aplicativo que invocou uma ação em tempo de execução. Os exemplos nesta seção verificarão o AUMID do Action Runtime. Os aplicativos podem optar por filtrar pelo AUMID de outros aplicativos ou usar o PFN (Nome da Família do Pacote) para filtrar todos os aplicativos contidos em um pacote específico.
Adicionar uma referência ao pacote Nuget CsWin32
O código de exemplo mostrado nesta seção usa APIs Win32 para obter o nome da família de pacotes do chamador. Para chamar mais facilmente as APIs Win32 de um aplicativo C#, este exemplo usará o pacote NuGet CsWin32, que gera wrappers C# para APIs Win32 no momento do build. Para obter mais informações, consulte o repositório github CsWin32.
- No Gerenciador de Soluções, clique com o botão direito do mouse em seu projeto e selecione Gerenciar Pacotes NuGet....
- Na guia Procurar, pesquise por "Microsoft.Windows.CsWin32".
- Selecione este pacote e clique em Instalar, seguindo todos os prompts.
Ao instalar este pacote, ele mostrará um README explicando como especificar as APIs Win32 para as quais os wrappers C# serão gerados. Para fazer isso, você precisará criar um arquivo de texto que liste os métodos que você usará.
- No Gerenciador de Soluções, clique com o botão direito do mouse em seu projeto e selecione Adicionar> Novo Item....
- Selecione o modelo TextFile .
- Nomeie o arquivo como "NativeMethods.txt" e clique em Adicionar
- Clique duas vezes NativeMethods.txt para abrir o arquivo e adicionar as linhas a seguir.
CoRegisterClassObject
CoRevokeClassObject
CoImpersonateClient
OpenThreadToken
GetCurrentThread
CoRevertToSelf
GetPackageFamilyNameFromToken
GetLastError
Atualizar sua classe ActionProvider para verificar o PFN do invocador de ação
O método auxiliar a seguir usa as APIs Win32 especificadas em NativeMethods.txt para recuperar o AUMID para o processo de chamada e retorna true se corresponder ao AUMID que é passado. Para obter uma explicação detalhada sobre como esse código funciona, consulte Como representar um cliente.
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;
}
}
Devido à maneira como o CoImpersonateClient é implementado, é importante que você chame o método auxiliar de dentro da invocação de sua ação e não de dentro do procedimento de inicialização do aplicativo.
O exemplo a seguir ilustra uma verificação do AUMID do Action Runtime em uma ação implementada usando a estrutura de geração de código 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)
};
}