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.
O Package Support Framework é um kit de software livre que ajuda você a aplicar correções ao aplicativo da área de trabalho existente (sem modificar o código) para que ele possa ser executado em um contêiner MSIX. O Package Support Framework ajuda seu aplicativo a seguir as práticas recomendadas do ambiente de runtime moderno.
Este artigo fornece uma análise aprofundada de cada componente do Package Support Framework, além de um guia passo a passo para usá-lo.
Entender o que está dentro de uma Estrutura de Suporte a Pacotes
O Package Support Framework contém um executável, uma DLL do gerenciador de runtime e um conjunto de correções de runtime.
Este é o processo:
- Crie um arquivo de configuração que especifique as correções que você deseja aplicar ao seu aplicativo.
- Modifique o pacote para apontar para o arquivo executável do inicializador PSF (Package Support Framework).
Quando os usuários iniciam seu aplicativo, o inicializador do Package Support Framework é o primeiro executável executado. Ele lê o arquivo de configuração e injeta as correções de runtime e a DLL do gerenciador de runtime no processo do aplicativo. O gerenciador de runtime aplica a correção quando é necessário para que o aplicativo seja executado dentro de um contêiner MSIX.
Etapa 1: identificar problemas de compatibilidade de aplicativos empacotados
Primeiro, crie um pacote para seu aplicativo. Em seguida, instale-o, execute-o e observe seu comportamento. Você pode receber mensagens de erro que podem ajudá-lo a identificar um problema de compatibilidade. Você também pode usar o Monitor de Processo para identificar problemas. Problemas comuns referem-se às suposições do aplicativo em relação ao diretório de trabalho e às permissões de caminho do programa.
Usando o Monitor de Processo para identificar um problema
O Monitor de Processo é um utilitário poderoso para observar as operações de arquivo e registro de um aplicativo e seus resultados. Isso pode ajudá-lo a entender os problemas de compatibilidade do aplicativo. Depois de abrir o Monitor do Processo, adicione um filtro (Filtro >) para incluir apenas eventos do executável do aplicativo.
Uma lista de eventos será exibida. Para muitos desses eventos, a palavra SUCCESS será exibida na coluna Resultado .
Opcionalmente, você pode filtrar eventos para mostrar apenas falhas.
Se você suspeitar de uma falha de acesso ao sistema de arquivos, pesquise eventos com falha que estejam no System32/SysWOW64 ou no caminho do arquivo do pacote. Os filtros também podem ajudar aqui. Inicie na parte inferior desta lista e role para cima. Falhas que aparecem na parte inferior desta lista ocorreram mais recentemente. Preste mais atenção aos erros que contêm cadeias de caracteres como "acesso negado" e "caminho/nome não encontrado" e ignore coisas que não parecem suspeitas. O PSFSample tem dois problemas. Você pode ver esses problemas na lista que aparece na imagem a seguir.
No primeiro problema que aparece nesta imagem, o aplicativo está falhando ao ler do arquivo "Config.txt" que está localizado no caminho "C:\Windows\SysWOW64". É improvável que o aplicativo esteja tentando referenciar esse caminho diretamente. Provavelmente, ele está tentando ler desse arquivo usando um caminho relativo e, por padrão, "System32/SysWOW64" é o diretório de trabalho do aplicativo. Isso sugere que o aplicativo espera que seu diretório de trabalho atual seja definido para algum lugar no pacote. Olhando dentro do appx, podemos ver que o arquivo existe no mesmo diretório que o executável.
O segundo problema aparece na imagem a seguir.
Neste caso, o aplicativo está falhando em gravar um arquivo .log no caminho do pacote. Isso sugere que uma correção de redirecionamento de arquivo pode ajudar.
Etapa 2: localizar uma correção de runtime
O PSF contém correções de runtime que você pode usar agora, como a correção de redirecionamento de arquivo.
Correção de Redirecionamento de Arquivo
Você pode usar a Correção de Redirecionamento de Arquivo para redirecionar tentativas de gravação ou leitura de dados em um diretório que não está acessível em um aplicativo que é executado em um contêiner MSIX.
Por exemplo, se seu aplicativo gravar em um arquivo de log que está no mesmo diretório que o executável do aplicativo, você poderá usar a Correção de Redirecionamento de Arquivo para criar esse arquivo de log em outro local, como o armazenamento de dados do aplicativo local.
Correções de runtime da comunidade
Examine as contribuições da comunidade para nossa página do GitHub . É possível que outros desenvolvedores tenham resolvido um problema semelhante ao seu e tenham compartilhado uma correção de runtime.
Etapa 3: Aplicar uma correção de runtime
Você pode aplicar uma correção de runtime existente com algumas ferramentas simples do SDK do Windows e seguindo estas etapas.
- Criar uma pasta de layout de pacote
- Obter os arquivos da Estrutura de Suporte de Pacote
- Adicioná-los ao seu pacote
- Modificar o manifesto do pacote
- Criar um arquivo de configuração
Vamos analisar cada tarefa.
Criar a pasta de layout do pacote
Se você já tiver um arquivo .msix (ou .appx), pode extrair seu conteúdo para uma pasta de layout que servirá como área de preparo do seu pacote. Você pode fazer isso em um prompt de comando usando a ferramenta MakeAppx, com base no caminho de instalação do SDK, é aqui que você encontrará a ferramenta makeappx.exe em seu computador Windows 10: x86: C:\Program Files (x86)\Windows Kits\10\bin\x86\makeappx.exe x64: C:\Program Files (x86)\Windows Kits\10\bin\x64\makeappx.exe
makeappx unpack /p PSFSamplePackage_1.0.60.0_AnyCPU_Debug.msix /d PackageContents
Isso resultará em algo parecido com o seguinte.
Se você não tiver um arquivo .msix (ou .appx) para começar, poderá criar a pasta do pacote e os arquivos do zero.
Obter os arquivos da Estrutura de Suporte de Pacote
Você pode obter o pacote Nuget PSF usando a ferramenta de linha de comando do Nuget autônoma ou por meio do Visual Studio.
Obter o pacote usando a ferramenta de linha de comando
Instale a ferramenta de linha de comando do Nuget a partir deste local: https://www.nuget.org/downloads. Em seguida, na linha de comando do Nuget, execute este comando:
nuget install Microsoft.PackageSupportFramework
Como alternativa, você pode renomear a extensão do pacote para .zip e descompactá-la. Todos os arquivos necessários estarão na pasta /bin.
Obter o pacote usando o Visual Studio
No Visual Studio, clique com o botão direito do mouse em sua solução ou nó de projeto e escolha um dos comandos Gerenciar Pacotes Nuget. Pesquise por Microsoft.PackageSupportFramework ou PSF para localizar o pacote no Nuget.org. Em seguida, instale-o.
Adicionar os arquivos do Package Support Framework ao seu pacote
Adicione as DLLs PSF de 32 e 64 bits necessárias e os arquivos executáveis ao diretório do pacote. Use a tabela a seguir como guia. Você também desejará incluir as correções de runtime necessárias. Em nosso exemplo, precisamos da correção do runtime de redirecionamento de arquivo.
| O executável do aplicativo é x64 | O executável do aplicativo é x86 |
|---|---|
| PSFLauncher64.exe | PSFLauncher32.exe |
| PSFRuntime64.dll | PSFRuntime32.dll |
| PSFRunDll64.exe | PSFRunDll32.exe |
O conteúdo do pacote agora deve ser semelhante a este.
Modificar o manifesto do pacote
Abra o manifesto do pacote em um editor de texto e defina o atributo Executable do elemento Application como o nome do arquivo executável do Inicializador PSF. Se você souber a arquitetura do aplicativo de destino, selecione a versão apropriada, PSFLauncher32.exe ou PSFLauncher64.exe. Caso contrário, PSFLauncher32.exe funcionará em todos os casos. Aqui está um exemplo.
<Package ...>
...
<Applications>
<Application Id="PSFSample"
Executable="PSFLauncher32.exe"
EntryPoint="Windows.FullTrustApplication">
...
</Application>
</Applications>
</Package>
Criar um arquivo de configuração
Crie um nome config.jsonde arquivo e salve esse arquivo na pasta raiz do pacote. Modifique a ID de aplicativo declarada do arquivo config.json para apontar para o executável que você acabou de substituir. Usando o conhecimento obtido usando o Monitor de Processo, você também pode definir o diretório de trabalho, bem como usar a correção de redirecionamento de arquivos para redirecionar leituras/gravações para arquivos .log no diretório "PSFSampleApp" relativo ao pacote.
{
"applications": [
{
"id": "PSFSample",
"executable": "PSFSampleApp/PSFSample.exe",
"workingDirectory": "PSFSampleApp/"
}
],
"processes": [
{
"executable": "PSFSample",
"fixups": [
{
"dll": "FileRedirectionFixup.dll",
"config": {
"redirectedPaths": {
"packageRelative": [
{
"base": "PSFSampleApp/",
"patterns": [
".*\\.log"
]
}
]
}
}
}
]
}
]
}
Veja a seguir um guia para o esquema config.json.
| Matriz | chave | Valor |
|---|---|---|
| aplicativos | id | Use o valor do atributo Id do elemento Application no manifesto do pacote. |
| aplicativos | executável | O caminho relativo ao pacote para o executável que você deseja iniciar. Na maioria dos casos, você pode obter esse valor do arquivo de manifesto do pacote antes de modificá-lo. É o valor do Executable atributo do Application elemento. |
| aplicativos | diretório de trabalho | (Opcional) Um caminho relativo ao pacote a ser usado como o diretório de trabalho do aplicativo iniciado. Se você não definir esse valor, o sistema operacional usará o System32 diretório como o diretório de trabalho do aplicativo. |
| processos | executável | Na maioria dos casos, esse será o nome do executable configurado acima com o caminho e a extensão de arquivo removidos. |
| correções | Dll | Caminho relativo ao pacote para a correção, .msix/.appx a ser carregada. |
| correções | configuração | (Opcional) Controla como a dll de correção se comporta. O formato exato deste valor varia de acordo com cada correção, pois cada uma pode interpretar este "blob" da forma que desejar. |
As teclas applications, processes e fixups são matrizes. Isso significa que você pode usar o arquivo config.json para especificar mais de um aplicativo, processo e DLL de correção.
Empacotar e testar o aplicativo
Em seguida, crie um pacote.
makeappx pack /d PackageContents /p PSFSamplePackageFixup.msix
Então, assine isso.
signtool sign /a /v /fd sha256 /f ExportedSigningCertificate.pfx PSFSamplePackageFixup.msix
Para obter mais informações, confira como criar um certificado de assinatura de pacote e como assinar um pacote usando signtool
Usando o PowerShell, instale o pacote.
Observação
Lembre-se de desinstalar o pacote primeiro.
powershell Add-AppPackage .\PSFSamplePackageFixup.msix
Execute o aplicativo e observe o comportamento com a correção de runtime aplicada. Repita as etapas de diagnóstico e empacotamento conforme necessário.
Verificar se o Package Support Framework está em execução
Você pode verificar se a correção do runtime está em execução. Uma maneira de fazer isso é abrir o Gerenciador de Tarefas e clicar em Mais detalhes. Localize o aplicativo ao qual a estrutura de suporte do pacote foi aplicada e expanda os detalhes do aplicativo para obter mais detalhes. Você deve ser capaz de exibir que a Estrutura de Suporte a Pacotes está em execução.
Usar a Correção de Rastreamento
Uma técnica alternativa para diagnosticar problemas de compatibilidade de aplicativos empacotados é usar o Trace Fixup. Essa DLL é incluída no PSF e fornece uma exibição de diagnóstico detalhada do comportamento do aplicativo, semelhante ao Monitor de Processo. Ele foi especialmente projetado para revelar problemas de compatibilidade do aplicativo. Para usar a Correção de Rastreamento, adicione a DLL ao pacote, adicione o seguinte fragmento ao seu config.json e, em seguida, empacote e instale seu aplicativo.
{
"dll": "TraceFixup.dll",
"config": {
"traceLevels": {
"filesystem": "allFailures"
}
}
}
Por padrão, a Correção de Rastreamento filtra falhas que podem ser consideradas "esperadas". Por exemplo, os aplicativos podem tentar excluir incondicionalmente um arquivo sem verificar se ele já existe, ignorando o resultado. Isso tem a infeliz consequência de que algumas falhas inesperadas podem ser filtradas, portanto, no exemplo acima, optamos por receber todas as falhas das funções do sistema de arquivos. Fazemos isso porque sabemos de antes que a tentativa de leitura do arquivo Config.txt falha com a mensagem "arquivo não encontrado". Essa é uma falha que é frequentemente observada e geralmente não considerada inesperada. Na prática, é provável que seja melhor começar a filtrar apenas falhas inesperadas e, em seguida, considerar todas as falhas se houver um problema que ainda não possa ser identificado.
Por padrão, a saída da Correção de Rastreamento é enviada ao depurador conectado. Para este exemplo, não vamos anexar um depurador e, em vez disso, usaremos o programa DebugView do SysInternals para exibir sua saída. Depois de executar o aplicativo, podemos ver as mesmas falhas de antes, o que nos apontaria para as mesmas correções de runtime.
Depurar, estender ou criar uma correção de runtime
Você pode usar o Visual Studio para depurar uma correção de runtime, estender uma correção de runtime ou criar uma do zero. Você precisará fazer essas coisas para ter êxito.
- Adicionar um projeto de empacotamento
- Adicionar projeto para a correção de runtime
- Adicionar um projeto que inicie o executável do Inicializador PSF
- Configurar o projeto de empacotamento
Quando terminar, sua solução será semelhante a esta.
Vamos examinar cada projeto neste exemplo.
| Projeto | Propósito |
|---|---|
| Pacote de Aplicativos para Desktop | Esse projeto é baseado no projeto de Empacotamento de Aplicativos do Windows e gera o pacote MSIX. |
| Runtimefix | Este é um projeto da Biblioteca C++ Dynamic-Linked que contém uma ou mais funções de substituição que servem como correção em tempo de execução. |
| PSFLauncher | Este é o Projeto Vazio do C++. Este projeto é um local para coletar os arquivos redistribuíveis de runtime da Estrutura de Suporte de Pacote. Ele gera um arquivo executável. Esse executável é a primeira coisa que é executada quando você inicia a solução. |
| WinFormsDesktopApplication | Este projeto contém o código-fonte de um aplicativo da área de trabalho. |
Para examinar um exemplo completo que contém todos esses tipos de projetos, consulte PSFSample.
Vamos percorrer as etapas para criar e configurar cada um desses projetos em sua solução.
Criar uma solução de pacote
Se você ainda não tiver uma solução para o seu aplicativo de desktop, crie uma nova solução em branco no Visual Studio.
Talvez você também queira adicionar todos os projetos de aplicativo que tiver.
Adicionar um projeto de empacotamento
Se você ainda não tiver um Projeto de Empacotamento de Aplicativos do Windows, crie um e adicione-o à sua solução.
Para obter mais informações sobre o projeto de Empacotamento de Aplicativos do Windows, consulte Empacotar seu aplicativo usando o Visual Studio.
No Gerenciador de Soluções, clique com o botão direito do mouse no projeto de empacotamento, selecione Editar e adicione-o à parte inferior do arquivo de projeto:
<Target Name="PSFRemoveSourceProject" AfterTargets="ExpandProjectReferences" BeforeTargets="_ConvertItems">
<ItemGroup>
<FilteredNonWapProjProjectOutput Include="@(_FilteredNonWapProjProjectOutput)">
<SourceProject Condition="'%(_FilteredNonWapProjProjectOutput.SourceProject)'=='<your runtime fix project name goes here>'" />
</FilteredNonWapProjProjectOutput>
<_FilteredNonWapProjProjectOutput Remove="@(_FilteredNonWapProjProjectOutput)" />
<_FilteredNonWapProjProjectOutput Include="@(FilteredNonWapProjProjectOutput)" />
</ItemGroup>
</Target>
Adicionar projeto para a correção de runtime
Adicionar um projeto de Biblioteca de vínculo dinâmico (DLL) C++ à solução.
Clique com o botão direito do mouse nesse projeto e escolha Propriedades.
Nas páginas de propriedades, localize o campo Padrão da Linguagem C++ e, na lista suspensa ao lado desse campo, selecione a opção ISO C++17 Standard (/std:c++17).
Clique com o botão direito do mouse nesse projeto e, no menu de contexto, escolha a opção Gerenciar Pacotes Nuget . Verifique se a opção de origem do pacote está definida como Todos ou nuget.org.
Clique no ícone de configurações ao lado desse campo.
Pesquise o pacote Nuget PSF* e instale-o para este projeto.
Se você quiser depurar ou estender uma correção de runtime existente, adicione os arquivos de correção de runtime obtidos usando as diretrizes descritas na seção Localizar uma correção de runtime deste guia.
Se você pretende criar uma nova correção, não adicione nada a este projeto ainda. Ajudaremos você a adicionar os arquivos certos a este projeto mais adiante neste guia. Por enquanto, continuaremos configurando sua solução.
Adicionar um projeto que inicie o executável do Inicializador PSF
Adicione um projeto C++ Empty Project à solução.
Adicione o pacote Nuget PSF a este projeto usando as mesmas diretrizes descritas na seção anterior.
Abra as páginas de propriedades do projeto e, na página de Configurações Gerais, defina a propriedade Nome de Destino como PSFLauncher32 ou PSFLauncher64 dependendo da arquitetura do aplicativo.
Adicione uma referência de projeto ao projeto de correção de runtime em sua solução.
Clique com o botão direito do mouse na referência e, na janela Propriedades , aplique esses valores.
| Propriedade | Valor |
|---|---|
| Copiar local | Verdade |
| Copiar Assemblies Satélite Locais | Verdade |
| Saída do Assembly de Referência | Verdade |
| Vincular Dependências de Biblioteca | Falso |
| Vincular Entradas de Dependência da Biblioteca | Falso |
Configurar o projeto de empacotamento
No projeto de empacotamento, clique com o botão direito do mouse na pasta Aplicativos e escolha Adicionar Referência.
Escolha o projeto do Inicializador PSF e seu projeto de aplicativo da área de trabalho e, em seguida, escolha o botão OK .
Observação
Se você não tiver o código-fonte em seu aplicativo, basta escolher o projeto do Inicializador PSF. Mostraremos como fazer referência ao executável ao criar um arquivo de configuração.
No nó Aplicativos , clique com o botão direito do mouse no aplicativo PSF Launcher e, em seguida, escolha Definir como Ponto de Entrada.
Adicione um arquivo nomeado config.json ao seu projeto de empacotamento e, em seguida, copie e cole o seguinte texto json no arquivo. Defina a propriedade Ação do Pacote como Conteúdo.
{
"applications": [
{
"id": "",
"executable": "",
"workingDirectory": ""
}
],
"processes": [
{
"executable": "",
"fixups": [
{
"dll": "",
"config": {
}
}
]
}
]
}
Forneça um valor para cada chave. Use essa tabela como um guia.
| Matriz | chave | Valor |
|---|---|---|
| aplicativos | id | Use o valor do atributo Id do elemento Application no manifesto do pacote. |
| aplicativos | executável | O caminho relativo ao pacote para o executável que você deseja iniciar. Na maioria dos casos, você pode obter esse valor do arquivo de manifesto do pacote antes de modificá-lo. É o valor do Executable atributo do Application elemento. |
| aplicativos | diretório de trabalho | (Opcional) Um caminho relativo ao pacote a ser usado como o diretório de trabalho do aplicativo iniciado. Se você não definir esse valor, o sistema operacional usará o System32 diretório como o diretório de trabalho do aplicativo. |
| processos | executável | Na maioria dos casos, esse será o nome do executable configurado acima com o caminho e a extensão de arquivo removidos. |
| correções | Dll | Caminho relativo ao pacote para a DLL de correção a ser carregada. |
| correções | configuração | (Opcional) Controla como a DLL de correção se comporta. O formato exato deste valor varia de acordo com cada correção, pois cada uma pode interpretar este "blob" da forma que desejar. |
Quando você terminar, o arquivo config.json ficará semelhante a este.
{
"applications": [
{
"id": "DesktopApplication",
"executable": "DesktopApplication/WinFormsDesktopApplication.exe",
"workingDirectory": "WinFormsDesktopApplication"
}
],
"processes": [
{
"executable": ".*App.*",
"fixups": [ { "dll": "RuntimeFix.dll" } ]
}
]
}
Observação
As teclas applications, processes e fixups são matrizes. Isso significa que você pode usar o arquivo config.json para especificar mais de um aplicativo, processo e DLL de correção.
Depurar uma correção de runtime
No Visual Studio, pressione F5 para iniciar o depurador. A primeira coisa que é iniciada é o aplicativo Inicializador PSF, que, por sua vez, inicia o aplicativo da área de trabalho de destino. Para depurar o aplicativo da área de trabalho de destino, você precisará anexar manualmente ao processo do aplicativo da área de trabalho escolhendo Depurar->Anexar ao Processo e selecionando o processo do aplicativo. Para permitir a depuração de um aplicativo .NET com uma DLL de correção de runtime nativa, selecione tipos de código gerenciado e nativo (depuração em modo misto).
Depois de configurar isso, você pode definir pontos de interrupção ao lado de linhas de código no código do aplicativo da área de trabalho e no projeto de correção de runtime. Se você não tiver o código-fonte em seu aplicativo, poderá definir pontos de interrupção apenas ao lado de linhas de código em seu projeto de correção de runtime.
Como a depuração com F5 executa o aplicativo implantando arquivos soltos do caminho da pasta de layout do pacote, em vez de instalar a partir de um pacote .msix/.appx, a pasta de layout geralmente não tem as mesmas restrições de segurança que uma pasta de pacote instalada. Como resultado, pode não ser possível reproduzir erros de negação de acesso ao caminho do pacote antes de aplicar uma correção de runtime.
Para resolver esse problema, use a implantação de pacotes .msix / .appx em vez da implantação de arquivos soltos com F5. Para criar um arquivo de pacote .msix/.appx, use o utilitário MakeAppx do SDK do Windows, conforme descrito acima. Ou, no Visual Studio, clique com o botão direito do mouse no nó do projeto do aplicativo e selecione Store –> Criar Pacotes de Aplicativos.
Outro problema com o Visual Studio é que ele não tem suporte interno para anexação a processos filho iniciados pelo depurador. Isso dificulta a depuração da lógica no caminho de inicialização do aplicativo de destino, que deve ser anexado manualmente pelo Visual Studio após a inicialização.
Para resolver esse problema, use um depurador que dê suporte à anexação de processos filho. Observe que geralmente não é possível anexar um depurador JIT (just-in-time) ao aplicativo de destino. Isso ocorre porque a maioria das técnicas JIT envolve iniciar o depurador no lugar do aplicativo de destino, por meio da chave do Registro ImageFileExecutionOptions. Isso neutraliza o mecanismo de desvio usado por PSFLauncher.exe para injetar FixupRuntime.dll no aplicativo de destino. O WinDbg, incluído nas Ferramentas de Depuração para Windows e obtido no SDK do Windows, dá suporte à anexação de processos filho. Ele também dá suporte diretamente ao início e à depuração direta de um aplicativo UWP.
Para depurar a inicialização do aplicativo de destino como um processo filho, inicie WinDbg.
windbg.exe -plmPackage PSFSampleWithFixup_1.0.59.0_x86__7s220nvg1hg3m -plmApp PSFSample
No prompt WinDbg, habilite a depuração de processos filho e defina os pontos de interrupção apropriados.
.childdbg 1
g
(executar até que o aplicativo de destino seja iniciado e interrompido no depurador)
sxe ld fixup.dll
g
(execute até que a DLL de correção seja carregada)
bp ...
Observação
PLMDebug também pode ser usado para anexar um depurador a um aplicativo após a inicialização e também está incluído nas Ferramentas de Depuração para Windows. No entanto, é mais complexo usar do que o suporte direto agora fornecido pelo WinDbg.
Apoio
Tem dúvidas? Pergunte-nos sobre o espaço de conversa do Package Support Framework no site da comunidade técnica MSIX.