diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 7398a1b2b9..ca122671a2 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -40,7 +40,8 @@ azurewebsites bcp BEFACEF BFirst -bght +bght +bigcatalog BITMAPINFOHEADER bitspace bkup @@ -89,7 +90,7 @@ createmanifestmetadata cswinrt ctc currentuser -DACL +dacl datetimeoffset debian dedupe @@ -399,7 +400,8 @@ roy runspace runtimeclass ryfu -rzkzqaqjwj +rzkzqaqjwj +sacl SARL SASURL schematab diff --git a/Localization/Policies/de-DE/DesktopAppInstaller.adml b/Localization/Policies/de-DE/DesktopAppInstaller.adml index 5d364881aa..41869407b0 100644 --- a/Localization/Policies/de-DE/DesktopAppInstaller.adml +++ b/Localization/Policies/de-DE/DesktopAppInstaller.adml @@ -100,15 +100,28 @@ Wenn Sie diese Einstellung deaktivieren oder nicht konfigurieren, können Benutz Wenn Sie diese Richtlinie deaktivieren, können Benutzer die Windows-Paketverwaltungs-CLI und PowerShell-Cmdlets nicht ausführen. - Wenn Sie diese Richtlinie aktivieren oder nicht konfigurieren, können Benutzer die Windows Package Manager CLI-Befehle und PowerShell-Cmdlets ausführen. (Vorausgesetzt, die Richtlinie "App-Installationsprogramm aktivieren" ist nicht deaktiviert). + Wenn Sie diese Richtlinie aktivieren oder nicht konfigurieren, können Benutzer die CLI-Befehle des Windows-Paket-Managers und PowerShell-Cmdlets ausführen. (Vorausgesetzt, die Richtlinie „App Installer aktivieren“ ist nicht deaktiviert.) - Diese Richtlinie hat keinen Einfluss auf die Richtlinie "App-Installationsprogramm aktivieren". + Diese Richtlinie setzt die Richtlinie „App-Installer aktivieren“ nicht außer Kraft. Aktivieren der Windows-Paket-Manager-Konfiguration Diese Richtlinie steuert, ob das Windows-Paket-Manager Konfigurationsfeature von Benutzern verwendet werden kann. Wenn Sie diese Einstellung aktivieren oder nicht konfigurieren, können Benutzer das Konfigurationsfeature Windows-Paket-Manager verwenden. Wenn Sie diese Einstellung deaktivieren, können Benutzer das Konfigurationsfeature Windows-Paket-Manager nicht verwenden. + Befehlszeilenoptionen für Windows-Paket-Manager Proxy aktivieren + + Diese Richtlinie steuert, ob die Windows-Paket-Manager Verwendung des Proxys von Benutzern über die Befehlszeile konfiguriert werden kann. + +Wenn Sie diese Einstellung aktivieren, können Benutzer die Verwendung des Proxys durch die Windows-Paket-Manager über die Befehlszeile konfigurieren. + +Wenn Sie diese Einstellung deaktivieren oder nicht konfigurieren, können Benutzer die Verwendung des Proxys durch die Windows-Paket-Manager über die Befehlszeile nicht konfigurieren. + Standardproxy für den Windows-Paket-Manager festlegen + Diese Richtlinie steuert den Standardproxy, der vom Windows-Paket-Manager verwendet wird. + +Wenn Sie diese Einstellung deaktivieren oder nicht konfigurieren, wird standardmäßig kein Proxy verwendet. + +Wenn Sie diese Einstellung aktivieren, wird der angegebene Proxy standardmäßig verwendet. @@ -120,6 +133,11 @@ Wenn Sie diese Einstellung deaktivieren, können Benutzer das Konfigurationsfeat Erlaubte Quellen: + + + + + diff --git a/Localization/Policies/es-ES/DesktopAppInstaller.adml b/Localization/Policies/es-ES/DesktopAppInstaller.adml index 10e34ed19d..2b5a602d91 100644 --- a/Localization/Policies/es-ES/DesktopAppInstaller.adml +++ b/Localization/Policies/es-ES/DesktopAppInstaller.adml @@ -98,17 +98,30 @@ Si deshabilita o no establece esta configuración, los usuarios no podrán insta Habilitar Administrador de paquetes de Windows interfaces de línea de comandos Esta directiva determina si un usuario puede realizar una acción mediante el Administrador de paquetes de Windows a través de una interfaz de línea de comandos (CLI de WinGet o WinGet PowerShell). -Si deshabilita esta directiva, los usuarios no podrán ejecutar la CLI de Administrador de paquetes de Windows ni los cmdlets de PowerShell. + Si deshabilita esta directiva, los usuarios no podrán ejecutar la CLI de Administrador de paquetes de Windows y los cmdlets de PowerShell. -Si habilita o no configura esta directiva, los usuarios podrán ejecutar los comandos de la CLI de Administrador de paquetes de Windows y los cmdlets de PowerShell. (La directiva "Habilitar Instalador de aplicación" proporcionada no está deshabilitada). + Si habilita o no configura esta directiva, los usuarios podrán ejecutar los comandos de la CLI de Administrador de paquetes de Windows y los cmdlets de PowerShell. (Proporcionado “Habilitar Instalador de aplicación” directiva no está deshabilitada). -Esta directiva no invalida la directiva "Habilitar Instalador de aplicación". + Esta directiva no invalida la directiva “Habilitar Instalador de aplicación”. Habilitar configuración de Administrador de paquetes de Windows Esta directiva controla si los usuarios pueden usar la característica de configuración Administrador de paquetes de Windows. Si habilita o no establece esta configuración, los usuarios podrán usar la característica de configuración Administrador de paquetes de Windows. Si deshabilita esta configuración, los usuarios no podrán usar la característica de configuración Administrador de paquetes de Windows. + Habilitar Administrador de paquetes de Windows opciones de la línea de comandos del proxy + + Esta directiva controla si los usuarios pueden configurar el uso Administrador de paquetes de Windows del proxy a través de la línea de comandos. + +Si habilita esta configuración, los usuarios podrán configurar el uso del proxy del Administrador de paquetes de Windows a través de la línea de comandos. + +Si deshabilita o no establece esta configuración, los usuarios no podrán configurar el uso del proxy del Administrador de paquetes de Windows a través de la línea de comandos. + Establecer Administrador de paquetes de Windows proxy predeterminado + Esta directiva controla el proxy predeterminado que usa el Administrador de paquetes de Windows. + +Si deshabilita o no establece esta configuración, no se usará ningún proxy de forma predeterminada. + +Si habilita esta configuración, el proxy especificado se usará de forma predeterminada. @@ -120,6 +133,11 @@ Si deshabilita esta configuración, los usuarios no podrán usar la característ Orígenes permitidos: + + + + + diff --git a/Localization/Policies/fr-FR/DesktopAppInstaller.adml b/Localization/Policies/fr-FR/DesktopAppInstaller.adml index 5d57ffaee3..97b503e991 100644 --- a/Localization/Policies/fr-FR/DesktopAppInstaller.adml +++ b/Localization/Policies/fr-FR/DesktopAppInstaller.adml @@ -98,17 +98,30 @@ Si vous désactivez ou ne configurez pas ce paramètre, les utilisateurs ne peuv Activer les interfaces de ligne de commande Gestionnaire de package Windows Cette stratégie détermine si un utilisateur peut effectuer une action à l’aide du Gestionnaire de package Windows via une interface de ligne de commande (WinGet CLI ou WinGet PowerShell). -Si vous désactivez cette stratégie, les utilisateurs ne peuvent pas exécuter l’interface CLI Gestionnaire de package Windows et les applets de commande PowerShell. + Si vous désactivez cette stratégie, les utilisateurs ne pourront pas exécuter l’interface CLI Gestionnaire de package Windows et les cmdlets PowerShell. -Si vous activez ou ne configurez pas cette stratégie, les utilisateurs peuvent exécuter les commandes Gestionnaire de package Windows CLI et PowerShell. (La stratégie « Activer Programme d'installation d'application » fournie n’est pas désactivée). + Si vous activez ou ne configurez pas cette stratégie, les utilisateurs peuvent exécuter les commandes Gestionnaire de package Windows CLI et les cmdlets PowerShell. (La stratégie « Activer Programme d'installation d'application » fournie n’est pas désactivée). -Cette stratégie ne remplace pas la stratégie « Activer Programme d'installation d'application ». + Cette stratégie ne remplace pas la stratégie « Activer Programme d'installation d'application ». Activer la configuration Gestionnaire de package Windows Cette stratégie contrôle si la fonctionnalité de configuration Gestionnaire de package Windows peut être utilisée par les utilisateurs. Si vous activez ou ne configurez pas ce paramètre, les utilisateurs peuvent utiliser la fonctionnalité de configuration Gestionnaire de package Windows. Si vous désactivez ce paramètre, les utilisateurs ne peuvent pas utiliser la fonctionnalité de configuration Gestionnaire de package Windows. + Activer les options de ligne de commande du proxy Gestionnaire de package Windows + + Cette stratégie contrôle si l’utilisation Gestionnaire de package Windows proxy peut être configurée par les utilisateurs via la ligne de commande. + +Si vous activez ce paramètre, les utilisateurs peuvent configurer l’utilisation du proxy par le Gestionnaire de package Windows via la ligne de commande. + +Si vous désactivez ou ne configurez pas ce paramètre, les utilisateurs ne peuvent pas configurer l’utilisation du proxy par le Gestionnaire de package Windows via la ligne de commande. + Définir Gestionnaire de package Windows proxy par défaut + Cette stratégie contrôle le proxy par défaut utilisé par le Gestionnaire de package Windows. + +Si vous désactivez ou ne configurez pas ce paramètre, aucun proxy n’est utilisé par défaut. + +Si vous activez ce paramètre, le proxy spécifié est utilisé par défaut. @@ -120,6 +133,11 @@ Si vous désactivez ce paramètre, les utilisateurs ne peuvent pas utiliser la f Sources autorisées : + + + + + diff --git a/Localization/Policies/it-IT/DesktopAppInstaller.adml b/Localization/Policies/it-IT/DesktopAppInstaller.adml index 651a595444..95fb331f23 100644 --- a/Localization/Policies/it-IT/DesktopAppInstaller.adml +++ b/Localization/Policies/it-IT/DesktopAppInstaller.adml @@ -96,19 +96,32 @@ Se si abilita questa impostazione, gli utenti potranno installare pacchetti da s Se si disabilita o non si configura questa impostazione, gli utenti non potranno installare pacchetti da siti Web che utilizzano questo protocollo. Abilita Gestione interfacce della riga di comando dei pacchetti Windows - Questo criterio determina se un utente può eseguire un'azione usando la Gestione pacchetti Windows tramite un'interfaccia della riga di comando (interfaccia della riga di comando di WinGet o WinGet PowerShell). + Questo criterio determina se un utente può eseguire un'azione usando Gestione pacchetti Windows tramite un'interfaccia della riga di comando (interfaccia della riga di comando di WinGet o WinGet PowerShell). -Se disabiliti questo criterio, gli utenti non potranno eseguire l'interfaccia della riga di comando Gestione pacchetti Windows e i cmdlet di PowerShell. + Se si disabilita questo criterio, gli utenti non saranno in grado di eseguire l'interfaccia della riga di comando Gestione pacchetti Windows e i cmdlet di PowerShell. -Se abiliti o non configuri questo criterio, gli utenti potranno eseguire i comandi dell'interfaccia della riga di comando Gestione pacchetti Windows e i cmdlet di PowerShell. (Il criterio "Abilita Programma di installazione app" specificato non è disabilitato). + Se si abilita o non si configura questo criterio, gli utenti non saranno in grado di eseguire l'interfaccia della riga di comando Gestione pacchetti Windows e i cmdlet di PowerShell. (se il criterio "Abilita programma di installazione app" non è disabilitato). -Questo criterio non esegue l'override del criterio "Abilita Programma di installazione app". + Questo criterio non sostituisce il criterio "Abilita programma di installazione app". Abilita la configurazione di Gestione pacchetti Questo criterio controlla se la funzionalità di configurazione Gestione pacchetti Windows può essere usata dagli utenti. Se si abilita o non si configura questa impostazione, gli utenti potranno usare la funzionalità di configurazione Gestione pacchetti Windows. Se si disabilita questa impostazione, gli utenti non potranno usare la funzionalità di configurazione Gestione pacchetti Windows. + Abilita le opzioni della riga di comando del proxy Gestione pacchetti Windows + + Questo criterio controlla se l'utilizzo Gestione pacchetti Windows del proxy può essere configurato dagli utenti tramite la riga di comando. + +Se si abilita questa impostazione, gli utenti potranno configurare l'uso del proxy da parte del Gestione pacchetti Windows tramite la riga di comando. + +Se si disabilita o non si configura questa impostazione, gli utenti non potranno configurare l'utilizzo del proxy da parte del Gestione pacchetti Windows tramite la riga di comando. + Imposta proxy predefinito Gestione pacchetti Windows + Questo criterio controlla il proxy predefinito utilizzato dal Gestione pacchetti Windows. + +Se si disabilita o non si configura questa impostazione, per impostazione predefinita non verrà utilizzato alcun proxy. + +Se si abilita questa impostazione, per impostazione predefinita verrà utilizzato il proxy specificato. @@ -120,6 +133,11 @@ Se si disabilita questa impostazione, gli utenti non potranno usare la funzional Origini consentite: + + + + + diff --git a/Localization/Policies/ja-JP/DesktopAppInstaller.adml b/Localization/Policies/ja-JP/DesktopAppInstaller.adml index 1c78c6d37a..2c31873a8d 100644 --- a/Localization/Policies/ja-JP/DesktopAppInstaller.adml +++ b/Localization/Policies/ja-JP/DesktopAppInstaller.adml @@ -96,19 +96,32 @@ この設定を無効にするか、未構成にした場合、ユーザーはこのプロトコルを使用する Web サイトからパッケージをインストールできなくなります。 Windows パッケージ マネージャーのコマンド ライン インターフェイスを有効にする - このポリシーは、ユーザーがコマンド ライン インターフェイス (WinGet CLI または WinGet PowerShell) を通じて Windows パッケージ マネージャーを使用してアクションを実行できるかどうかを決定します。 + このポリシーは、ユーザーがコマンド ライン インターフェイス (WinGet CLI または WinGet PowerShell) を使用してWindows パッケージ マネージャーを使用してアクションを実行できるかどうかを決定します。 -このポリシーを無効にすると、ユーザーは Windows パッケージ マネージャー CLI と PowerShell コマンドレットを実行できなくなります。 + このポリシーを無効にすると、ユーザーは Windows パッケージ マネージャー CLI と PowerShell コマンドレットを実行できなくなります。 -このポリシーを有効にした場合、または構成しなかった場合、ユーザーは Windows パッケージ マネージャー CLI コマンドと PowerShell コマンドレットを実行できます ([アプリ インストーラーを有効にする] ポリシーが無効になっている場合に限る)。 + このポリシーを有効にした場合、または構成しなかった場合、ユーザーは Windows パッケージ マネージャー CLI コマンドと PowerShell コマンドレットを実行できます。(ただし、"アプリ インストーラーを有効にする" ポリシーが無効になっていない場合に限ります)。 -このポリシーは、[アプリ インストーラーを有効にする] ポリシーをオーバーライドしません。 + このポリシーは、"アプリ インストーラーを有効にする" ポリシーをオーバーライドしません。 Windows パッケージ マネージャーの構成を有効にする このポリシーでは、Windows パッケージ マネージャー構成機能をユーザーが使用できるかどうかを制御します。 この設定を有効にした場合、または構成しなかった場合、ユーザーはWindows パッケージ マネージャー構成機能を使用できます。 この設定を無効にすると、ユーザーはWindows パッケージ マネージャー構成機能を使用できなくなります。 + Windows パッケージ マネージャー Proxy コマンド ライン オプションを有効にする + + このポリシーでは、ユーザーがコマンド ラインでプロキシのWindows パッケージ マネージャーの使用を構成できるかどうかを制御します。 + +この設定を有効にした場合、ユーザーはコマンド ラインを使用してWindows パッケージ マネージャーのプロキシの使用を構成できます。 + +この設定を無効にした場合、または構成しなかった場合、ユーザーはコマンド ラインでWindows パッケージ マネージャーのプロキシの使用を構成できなくなります。 + Windows パッケージ マネージャーの既定のプロキシを設定する + このポリシーは、Windows パッケージ マネージャーで使用される既定のプロキシを制御します。 + +この設定を無効にした場合、または構成しなかった場合、既定ではプロキシは使用されません。 + +この設定を有効にした場合、指定したプロキシが既定で使用されます。 @@ -120,6 +133,11 @@ 許可されたソース: + + + + + diff --git a/Localization/Policies/ko-KR/DesktopAppInstaller.adml b/Localization/Policies/ko-KR/DesktopAppInstaller.adml index 86d724317b..9bbc425ce6 100644 --- a/Localization/Policies/ko-KR/DesktopAppInstaller.adml +++ b/Localization/Policies/ko-KR/DesktopAppInstaller.adml @@ -96,19 +96,32 @@ 이 설정을 사용하지 않거나 구성하지 않으면 사용자가 이 프로토콜을 사용하는 웹 사이트의 패키지를 설치할 수 없습니다. Windows 패키지 관리자 명령줄 인터페이스 활성화 - 이 정책은 사용자가 명령줄 인터페이스(WinGet CLI 또는 WinGet PowerShell)를 통해 Windows 패키지 관리자를 사용하여 작업을 수행할 수 있는지 결정합니다. + 이 정책은 사용자가 명령줄 인터페이스(WinGet CLI 또는 WinGet PowerShell)를 통해 Windows 패키지 관리자를 사용하여 작업을 수행할 수 있는지 여부를 결정합니다. - 이 정책을 비활성화하면 사용자는 Windows 패키지 관리자 CLI 및 PowerShell cmdlet을 실행할 수 없습니다. + 이 정책을 사용하지 않도록 설정하면 사용자는 Windows 패키지 관리자 CLI 및 PowerShell cmdlet을 실행할 수 없습니다. - 이 정책을 활성화하거나 구성하지 않으면 사용자는 Windows 패키지 관리자 CLI 명령 및 PowerShell cmdlet을 실행할 수 있습니다. ('앱 설치 프로그램 활성화' 정책이 비활성화되지 않은 경우). + 이 정책을 사용하도록 설정하거나 구성하지 않을 경우 사용자는 Windows 패키지 관리자 CLI 명령 및 PowerShell cmdlet을 실행할 수 없습니다. (제공된 “앱 설치 관리자 사용” 정책을 사용하지 않도록 설정할 수 없습니다.) - 이 정책은 '앱 설치 프로그램 활성화' 정책보다 우선 적용되지 않습니다. + 이 정책은 “앱 설치 관리자 사용” 정책을 재정의하지 않습니다. Windows 패키지 관리자 구성 사용 이 정책은 사용자가 Windows 패키지 관리자 구성 기능을 사용할 수 있는지 여부를 제어합니다. 이 설정을 사용하거나 구성하지 않으면 사용자가 Windows 패키지 관리자 구성 기능을 사용할 수 있습니다. 이 설정을 사용하지 않으면 사용자가 Windows 패키지 관리자 구성 기능을 사용할 수 없습니다. + 프록시 Windows 패키지 관리자 명령줄 옵션 사용 + + 이 정책은 명령줄을 통해 사용자가 프록시의 Windows 패키지 관리자 사용을 구성할 수 있는지 여부를 제어합니다. + +이 설정을 사용하면 사용자가 명령줄을 통해 Windows 패키지 관리자 프록시 사용을 구성할 수 있습니다. + +이 설정을 사용하지 않거나 구성하지 않으면 사용자가 명령줄을 통해 Windows 패키지 관리자 프록시 사용을 구성할 수 없습니다. + Windows 패키지 관리자 기본 프록시 설정 + 이 정책은 Windows 패키지 관리자 사용하는 기본 프록시를 제어합니다. + +이 설정을 사용하지 않거나 구성하지 않으면 기본적으로 프록시가 사용되지 않습니다. + +이 설정을 사용하면 지정된 프록시가 기본적으로 사용됩니다. @@ -120,6 +133,11 @@ 허용된 원본: + + + + + diff --git a/Localization/Policies/pt-BR/DesktopAppInstaller.adml b/Localization/Policies/pt-BR/DesktopAppInstaller.adml index d6937c092e..d8ad3bb50b 100644 --- a/Localization/Policies/pt-BR/DesktopAppInstaller.adml +++ b/Localization/Policies/pt-BR/DesktopAppInstaller.adml @@ -96,19 +96,32 @@ Se você habilitar essa configuração, os usuários poderão instalar pacotes d Se você desabilitar ou não definir essa configuração, os usuários não poderão instalar pacotes de sites que usam esse protocolo. Habilitar interfaces de linha de comando do Gerenciador de Pacotes do Windows - Esta política determina se um usuário pode executar uma ação usando o Gerenciador de Pacotes do Windows por uma interface de linha de comando (WINGet CLI ou WinGet PowerShell). + Essa política determina se um usuário pode executar uma ação usando o Gerenciador de Pacotes do Windows por meio de uma interface de linha de comando (CLI do WinGet ou WinGet PowerShell). -Se você desabilitar essa política, os usuários não poderão executar o Gerenciador de Pacotes do Windows CLI e os cmdlets do PowerShell. + Se você desabilitar essa política, os usuários não poderão executar a CLI do Gerenciador de Pacotes do Windows e os cmdlets do PowerShell. -Se você habilitar ou não configurar essa política, os usuários poderão executar os comandos Gerenciador de Pacotes do Windows CLI e os cmdlets do PowerShell. (A política "Habilitar Instalador de Aplicativo" fornecida não está desabilitada). + Se você habilitar ou não configurar essa política, os usuários poderão executar os comandos CLI do Gerenciador de Pacotes do Windows e os cmdlets do PowerShell. (A política “Habilitar Instalador de Aplicativo” fornecida não está desabilitada). -Esta política não substitui a política "Habilitar Instalador de Aplicativo". + Essa política não substitui a política "Habilitar Instalador de Aplicativo". Habilitar as Configurações do Gerenciador de Pacotes do Windows Esta política controla se o Gerenciador de Pacotes do Windows de configuração pode ser usado pelos usuários. Se você habilitar ou não definir essa configuração, os usuários poderão usar o recurso Gerenciador de Pacotes do Windows configuração. Se você desabilitar essa configuração, os usuários não poderão usar o recurso Gerenciador de Pacotes do Windows configuração. + Habilitar Gerenciador de Pacotes do Windows de linha de comando proxy + + Esta política controla se o uso Gerenciador de Pacotes do Windows proxy pode ser configurado pelos usuários por meio da linha de comando. + +Se você habilitar essa configuração, os usuários poderão configurar o Gerenciador de Pacotes do Windows do proxy por meio da linha de comando. + +Se você desabilitar ou não definir essa configuração, os usuários não poderão configurar o uso Gerenciador de Pacotes do Windows do proxy por meio da linha de comando. + Definir Proxy Padrão do Gerenciador de Pacotes do Windows + Esta política controla o proxy padrão usado pelo Gerenciador de Pacotes do Windows. + +Se você desabilitar ou não definir essa configuração, nenhum proxy será usado por padrão. + +Se você habilitar essa configuração, o proxy especificado será usado por padrão. @@ -120,6 +133,11 @@ Se você desabilitar essa configuração, os usuários não poderão usar o recu Fontes Permitidas: + + + + + diff --git a/Localization/Policies/ru-RU/DesktopAppInstaller.adml b/Localization/Policies/ru-RU/DesktopAppInstaller.adml index 70fa7ceb00..b7e8caca52 100644 --- a/Localization/Policies/ru-RU/DesktopAppInstaller.adml +++ b/Localization/Policies/ru-RU/DesktopAppInstaller.adml @@ -96,19 +96,32 @@ Если отключить или не настраивать этот параметр, пользователи не смогут устанавливать пакеты с веб-сайтов, которые используют этот протокол. Включить интерфейсы командной строки Диспетчера пакетов Windows - Эта политика определяет, может ли пользователь выполнять действие с помощью Диспетчера пакетов Windows посредством интерфейса командной строки (WinGet CLI или WinGet PowerShell). + Эта политика определяет, может ли пользователь выполнять действие с помощью диспетчера пакетов Windows через интерфейс командной строки (WinGet CLI или WinGet PowerShell). - Если эта политика отключена, пользователи не смогут выполнять команды CLI Диспетчера пакетов Windows и командлеты PowerShell. + Если вы отключите эту политику, пользователи не смогут выполнять CLI диспетчера пакетов Windows и командлеты PowerShell. - Если эта политика включена или не настроена, пользователи смогут выполнять команды CLI Диспетчера пакетов Windows и командлеты PowerShell. (Указанная политика "Включить установщик приложений" не отключена.) + Если вы включите или не настроите эту политику, пользователи смогут выполнять команды CLI диспетчера пакетов Windows и командлеты PowerShell. (При условии, что политика "Включить установщик приложений" не отключена). - Эта политика не переопределяет политику "Включить установщик приложений". + Эта политика не отменяет политику "Включить установщик приложений". Включить конфигурацию Диспетчера пакетов Windows Эта политика определяет, Диспетчер пакетов Windows ли пользователи могут использовать эту Диспетчер пакетов Windows конфигурацию. Если этот параметр включен или не настроен, пользователи смогут использовать Диспетчер пакетов Windows конфигурации. Если этот параметр отключен, пользователи не смогут использовать Диспетчер пакетов Windows конфигурации. + Включить Диспетчер пакетов Windows командной строки прокси-сервера + + Эта политика определяет, может ли Диспетчер пакетов Windows использование прокси-сервера настраивать пользователи с помощью командной строки. + +Если этот параметр включен, пользователи смогут Диспетчер пакетов Windows использовать прокси-сервер в командной строке. + +Если вы отключаете или не настраиваете этот параметр политики, пользователи не смогут Диспетчер пакетов Windows использовать прокси-сервер в командной строке. + Задать прокси по умолчанию для Диспетчера пакетов Windows + Эта политика управляет прокси-сервером по умолчанию, используемым Диспетчер пакетов Windows. + +Если этот параметр отключен или не настроен, по умолчанию прокси-сервер не будет использоваться. + +Если этот параметр включен, указанный прокси-сервер будет использоваться по умолчанию. @@ -120,6 +133,11 @@ Разрешенные источники: + + + + + diff --git a/Localization/Policies/zh-CN/DesktopAppInstaller.adml b/Localization/Policies/zh-CN/DesktopAppInstaller.adml index a19d7e4a5d..a09e6e4df2 100644 --- a/Localization/Policies/zh-CN/DesktopAppInstaller.adml +++ b/Localization/Policies/zh-CN/DesktopAppInstaller.adml @@ -96,19 +96,32 @@ 如果禁用或未配置此设置,则用户将无法安装来自使用此协议的网站的包。 启用 Windows 程序包管理器命令行接口 - 此策略确定用户是否可以通过命令行界面 (WinGet CLI 或 WinGet PowerShell) 使用 Windows 程序包管理器执行操作。 + 此策略确定用户是否可以通过命令行界面(WinGet CLI 或 WinGet PowerShell)使用 Windows 程序包管理器执行操作。 - 如果禁用此策略,用户将无法执行 Windows 程序包管理器 CLI 和 PowerShell cmdlet。 + 如果禁用此策略,用户将无法执行 Windows 程序包管理器 CLI 和 PowerShell cmdlet。 - 如果启用或未配置此策略,用户将能够执行 Windows 程序包管理器 CLI 命令和 PowerShell cmdlet。(未禁用提供的“启用应用安装程序”策略)。 + 如果启用或未配置此策略,用户将能够执行 Windows 程序包管理器 CLI 命令和 PowerShell cmdlet。(前提是 “启用应用安装程序” 策略未禁用)。 - 此策略不会替代“启用应用安装程序”策略。 + 此策略不会替代 “启用应用安装程序” 策略。 启用 Windows 程序包管理器配置 此策略控制用户是否可以使用Windows 程序包管理器配置功能。 如果启用或未配置此设置,则用户将能够使用Windows 程序包管理器配置功能。 如果禁用此设置,则用户将无法使用Windows 程序包管理器配置功能。 + 启用Windows 程序包管理器代理命令行选项 + + 此策略控制用户是否可以通过命令行配置代理的Windows 程序包管理器使用情况。 + +如果启用此设置,则用户将能够通过命令行配置Windows 程序包管理器使用代理。 + +如果禁用或未配置此设置,则用户将无法通过命令行配置Windows 程序包管理器使用代理。 + 设置 Windows 程序包管理器默认代理 + 此策略控制Windows 程序包管理器使用的默认代理。 + +如果禁用或未配置此设置,则默认情况下不会使用任何代理。 + +如果启用此设置,则默认情况下将使用指定的代理。 @@ -120,6 +133,11 @@ 允许的源: + + + + + diff --git a/Localization/Policies/zh-TW/DesktopAppInstaller.adml b/Localization/Policies/zh-TW/DesktopAppInstaller.adml index d02f21dd54..a9d5823cc6 100644 --- a/Localization/Policies/zh-TW/DesktopAppInstaller.adml +++ b/Localization/Policies/zh-TW/DesktopAppInstaller.adml @@ -96,19 +96,32 @@ 如果您停用或未設定這個設定,使用者將無法從使用此通訊協定的網站安裝套件。 啟用 Windows 封裝管理員命令列介面 - 此原則決定使用者是否可以透過命令列介面 (WinGet CLI 或 WinGet PowerSh) 使用 Windows 封裝管理員執行動作。 + 此原則會判斷使用者是否可透過命令列介面 (WinGet CLI 或 WinGet PowerShell) 使用 Windows 封裝管理員執行動作。 - 如果您停用此原則,使用者將無法執行 Windows 封裝管理員 CLI 和 PowerShell Cmdlet。 + 如果停用此原則,使用者將無法執行 Windows 封裝管理員 CLI 和 PowerShell Cmdlet。 - 如果您啟用或未設定此原則,使用者將可以執行 Windows 封裝管理員 CLI 命令和 PowerShell Cmdlet。(提供的 [啟用應用程式安裝程式] 原則將不會停用)。 + 如果啟用或未設定此原則,使用者將可以執行 Windows 封裝管理員 CLI 命令和 PowerShell Cmdlet。(未停用提供的 [啟用應用程式安裝程式] 原則)。 - 此原則不會覆寫 [啟用應用程式安裝程式] 原則。 + 此原則不會覆寫 [啟用應用程式安裝程式] 原則。 啟用 Windows 封裝管理員設定 此原則控制使用者是否可以使用Windows 封裝管理員設定功能。 如果您啟用或未設定這個設定,使用者將可以使用Windows 封裝管理員設定功能。 如果您停用這個設定,使用者將無法使用Windows 封裝管理員設定功能。 + 啟用Windows 封裝管理員 Proxy 命令行選項 + + 此原則控制使用者是否可以透過命令行設定 proxy 的Windows 封裝管理員使用方式。 + +如果您啟用這個設定,使用者將可以透過命令行設定Windows 封裝管理員使用 Proxy。 + +如果您停用或未設定這個設定,用戶將無法透過命令行設定Windows 封裝管理員使用 Proxy。 + 設定 Windows 封裝管理員預設 Proxy + 此原則控制Windows 封裝管理員使用的預設 Proxy。 + +如果停用或未設定此設定,則預設不會使用任何 Proxy。 + +如果您啟用這個設定,預設會使用指定的 Proxy。 @@ -120,6 +133,11 @@ 允許的來源: + + + + + diff --git a/Localization/Resources/de-DE/winget.resw b/Localization/Resources/de-DE/winget.resw index 83c24393a6..26e7624941 100644 --- a/Localization/Resources/de-DE/winget.resw +++ b/Localization/Resources/de-DE/winget.resw @@ -1173,6 +1173,9 @@ Stimmen Sie den Bedingungen zu? Freigabedatum: + + Unterstützte Offlineverteilung: + Herausgeber-URL: @@ -2272,14 +2275,14 @@ Geben Sie eine Option für --source an, um den Vorgang fortzusetzen. Der Vorgang wird durch Gruppenrichtlinie blockiert - - Interner Fehler der REST-Quelle + + Interner Fehler der REST-API Ungültige REST-Quell-URL - - Von der REST-Quelle wird ein nicht unterstützter MIME-Typ zurückgegeben + + Nicht unterstützter MIME-Typ, der von der REST-API zurückgegeben wird Ungültige Version des REST-Quellvertrags @@ -2299,8 +2302,8 @@ Geben Sie eine Option für --source an, um den Vorgang fortzusetzen. Die Suchanforderung wird von mindestens einer Quelle nicht unterstützt. - - Der REST-Quellendpunkt wurde nicht gefunden. + + Der REST-API-Endpunkt wurde nicht gefunden. Fehler beim Öffnen der Quelle. @@ -2814,4 +2817,232 @@ Geben Sie eine Option für --source an, um den Vorgang fortzusetzen. Fehler bei der Reparatur mit Exitcode: {0} {Locked="{0}"} Error message displayed when an attempt to repair an application package fails. {0} is a placeholder replaced by an error code. + + Die SQLite-Verbindung wurde beendet, um Beschädigungen zu verhindern. + + + Alle Versionen deinstallieren + + + Die Version, auf die reagiert werden soll + + + Mehrere Versionen dieses Pakets sind installiert. Verfeinern Sie die Suche, übergeben Sie das Argument "--version", um eines auszuwählen, oder übergeben Sie das Flag "--all-versions", um alle zu deinstallieren. + {Locked="--version,--all-versions"} + + + Befehlszeilenoptionen für Windows-Paket-Manager Proxy aktivieren + Describes a Group Policy that can enable the use of the --proxy option to set a proxy + + + Legen Sie einen Proxy fest, der für diese Ausführung verwendet werden soll. + + + Verwendung des Proxys für diese Ausführung deaktivieren + + + {0} kann nicht zurückgesetzt werden. Diese Einstellung wird durch eine Richtlinie gesteuert. Wenden Sie sich an den Systemadministrator, um weitere Informationen zu erfahren. + {Locked="{0}"} The value will be replaced with the feature name + + + Administratoreinstellung „{0}“ zurücksetzen. + {Locked="{0}"} Message displayed after the user resets an admin setting to its default value. Reset is used as verb in past tense. {0} is a placeholder replaced by the setting name. + + + {0} kann nicht festgelegt werden. Diese Einstellung wird durch eine Richtlinie gesteuert. Wenden Sie sich an den Systemadministrator, um weitere Informationen zu erfahren. + {Locked="{0}"} The value will be replaced with the feature name + + + Legen Sie die Administratoreinstellung „{0}“ auf „{1}“ fest. + {Locked="{0}"} Message displayed after the user sets the value of an admin setting. Set is used as a verb in past tense. {0} is a placeholder replaced by the setting name. {1} is a placeholder replaced + + + Name der zu ändernden Einstellung + + + Wert, der für die Einstellung festgelegt werden soll. + + + Setzt eine Administratoreinstellung auf den Standardwert zurück. + + + Setzt eine Administratoreinstellung auf den Standardwert zurück. + + + Legt den Wert einer Administratoreinstellung fest. + + + Legt den Wert einer Administratoreinstellung fest. + + + Schließt eine Quelle aus der Ermittlung aus, sofern keine Angabe erfolgt. + + + Anstößig + + + Vertrauensebene der Quelle (keine oder vertrauenswürdig) + + + Vertrauensebene + + + Fehler beim Abrufen des Microsoft Store-Paketkatalogs. + + + In Microsoft Store-Paketkatalog wurde kein anwendbares Microsoft Store-Paket gefunden. + + + Fehler beim Abrufen von Microsoft Store Paketdownloadinformationen. + + + Es wurden keine anwendbaren Microsoft Store-Paketdownloadinformationen gefunden. + + + Fehler beim Abrufen der Microsoft Store-Paketlizenz. + + + Das Microsoft Store-Paket wurde nicht gefunden. + + + Der Pakethash für Microsoft Store wurde erfolgreich überprüft. + + + Microsoft Store Pakethashkonflikt + + + Microsoft Store heruntergeladenes Paket: {0} + {Locked="{0}"} Full path of the downloaded package. + + + Fehler beim Herunterladen des Microsoft Store-Pakets: {0} + {Locked="{0}"} Package name. + + + Microsoft Store-Paketdownload abgeschlossen + + + Hauptpakete werden von Microsoft Store heruntergeladen... + + + Abhängigkeitspakete werden von Microsoft Store heruntergeladen... + + + Microsoft Store-Paketdownloadinformationen werden abgerufen + + + Fehler beim Abrufen von Microsoft Store Paketdownloadinformationen + + + Microsoft Store Paketlizenz wird abgerufen + + + Microsoft Store-Paketlizenz gespeichert: {0} + {Locked="{0}"} License file full path. + + + Fehler beim Abrufen der Microsoft Store-Paketlizenz + + + Microsoft Store Paketdownload unterstützt das Argument --rename nicht. Microsoft Store-Paket verwendet Namen, die von Microsoft Store-Katalog bereitgestellt werden. + {Locked="--rename"} + + + Microsoft Store-Paketdownload erfordert eine Microsoft Entra-ID-Authentifizierung. Bei Bedarf wird möglicherweise eine Authentifizierungsaufforderung angezeigt. Authentifizierte Informationen werden für Microsoft-Dienste zur Zugriffsautorisierung freigegeben. Zur Microsoft Store-Paketlizenzierung benötigt das Microsoft Entra-ID-Konto Administratorzugriff auf den Microsoft-Entra-ID-Mandanten. + + + Überspringt das Abrufen der Offlinelizenz des Microsoft Store-Pakets + + + Zielplattform auswählen + + + Konfigurationsdatei wird hinzugefügt: {0} + {Locked="{0}"} + + + Erfolgreich exportiert + + + Konfigurationseinstellungen werden abgerufen... + + + Es müssen mindestens --packageId und/oder --module mit --resource angegeben werden + {Locked="--packageId,--module, --resource"} + + + Exportiert Konfigurationsressourcen in eine Konfigurationsdatei. Bei Verwendung mit "--packageId" wird eine WinGetPackage-Ressource der angegebenen Paket-ID exportiert. Bei Verwendung mit "--module" und "--resource" werden die Einstellungen der Ressource abgerufen und in die Konfigurationsdatei exportiert. Wenn die Ausgabekonfigurationsdatei bereits vorhanden ist, werden die exportierten Konfigurationsressourcen angefügt. + {Locked="WinGetPackage,--packageId,--module, --resource"} + + + Exportiert Konfigurationsressourcen in eine Konfigurationsdatei. + + + Das Modul der zu exportierenden Ressource. + + + Der zu exportierende Paketbezeichner. + + + Die zu exportierende Konfigurationsressource. + + + Fehler beim Abrufen der Eigenschaften der Konfigurationseinheit. + + + Fehler beim Exportieren der Konfiguration. + + + "{0}" konfigurieren + {Locked="{0}"} + + + {0}Installieren + {Locked="{0}"} + + + Einige der in der Konfigurationsdatei vorhandenen Daten wurden für diese Ausgabe abgeschnitten. überprüfen Sie den Dateiinhalt auf den vollständigen Inhalt. + + + <dieser Wert wurde abgeschnitten; überprüfen Sie den Dateiinhalt auf den vollständigen Text> + Keep some form of separator like the "<>" around the text so that it stands out from the preceding text. + + + Zeigt die Details der obersten Ebene für Konfigurationen an, die auf das System angewendet wurden. Diese Daten können dann mit `configure` Befehlen verwendet werden, um weitere Details zu erhalten. + {Locked="`configure`"} + + + Zeigt den Konfigurationsverlauf an. + + + Im Verlauf sind keine Konfigurationen vorhanden. + + + Elemente aus dem Verlauf auswählen + + + Es wurde keine einzelne Konfiguration gefunden, die mit den angegebenen Daten übereinstimmt. Geben Sie entweder den vollständigen Namen oder einen Teil des Bezeichners an, der eindeutig mit der gewünschten Konfiguration übereinstimmt. + + + Element aus Verlauf entfernen + + + Zuerst angewendet + Column header for date values indicating when a configuration was first applied to the system. + + + Bezeichner + + + Name + + + Ursprung + + + Pfad + + + Die angegebene Konfiguration wurde nicht gefunden. + \ No newline at end of file diff --git a/Localization/Resources/es-ES/winget.resw b/Localization/Resources/es-ES/winget.resw index 6f8ef3268b..a3e4a7a7e2 100644 --- a/Localization/Resources/es-ES/winget.resw +++ b/Localization/Resources/es-ES/winget.resw @@ -262,7 +262,7 @@ Se pueden configurar mediante el archivo de configuración "winget settings".Filtrar resultados por id - Suprime las salidas de advertencia. + Suprime las salidas de advertencia El propietario de esta aplicación le concede una licencia. @@ -1173,6 +1173,9 @@ La configuración está deshabilitada debido a la Directiva de grupo. Fecha de lanzamiento: + + Distribución sin conexión admitida: + Dirección URL del editor: @@ -2272,14 +2275,14 @@ Especifique uno de ellos con la opción --source para continuar. La operación está bloqueada por la directiva de grupo - - Error interno de origen REST + + Error interno de la API de REST Dirección URL de origen REST no válida - - Tipo MIME no admitido devuelto por el origen REST + + Tipo MIME no admitido devuelto por la API de REST Versión del contrato de origen REST no válida @@ -2299,8 +2302,8 @@ Especifique uno de ellos con la opción --source para continuar. Uno o varios orígenes no admiten la solicitud de búsqueda. - - No se encuentra el punto de conexión de origen REST. + + No se encuentra el punto de conexión de API de REST. Error al abrir el origen. @@ -2814,4 +2817,232 @@ Especifique uno de ellos con la opción --source para continuar. Error de reparación con el código de salida: {0} {Locked="{0}"} Error message displayed when an attempt to repair an application package fails. {0} is a placeholder replaced by an error code. + + La conexión de SQLite finalizó para evitar daños. + + + Desinstalar todas las versiones + + + La versión sobre la que actuar + + + Hay varias versiones de este paquete instaladas. Restrinja la búsqueda, pase el argumento "--version" para seleccionar una o pase la marca "--all-versions" para desinstalarlas todas. + {Locked="--version,--all-versions"} + + + Habilitar Administrador de paquetes de Windows opciones de la línea de comandos del proxy + Describes a Group Policy that can enable the use of the --proxy option to set a proxy + + + Establecer un proxy para usar para esta ejecución + + + Deshabilitar el uso del proxy para esta ejecución + + + No se puede restablecer {0}. Esta configuración está controlada por la directiva. Para obtener más información, póngase en contacto con el administrador del sistema. + {Locked="{0}"} The value will be replaced with the feature name + + + Restablezca la configuración de administrador "{0}". + {Locked="{0}"} Message displayed after the user resets an admin setting to its default value. Reset is used as verb in past tense. {0} is a placeholder replaced by the setting name. + + + No se puede establecer {0}. Esta configuración está controlada por la directiva. Para obtener más información, póngase en contacto con el administrador del sistema. + {Locked="{0}"} The value will be replaced with the feature name + + + Establezca la configuración de administrador "{0}" en "{1}". + {Locked="{0}"} Message displayed after the user sets the value of an admin setting. Set is used as a verb in past tense. {0} is a placeholder replaced by the setting name. {1} is a placeholder replaced + + + Nombre de la configuración que se va a modificar + + + Valor que se va a establecer para la configuración. + + + Restablece una configuración de administración a su valor predeterminado. + + + Restablece una configuración de administración a su valor predeterminado. + + + Establece el valor de una configuración de administrador. + + + Establece el valor de una configuración de administrador. + + + Excluye un origen de la detección a menos que se especifique + + + Explícito + + + Nivel de confianza del origen (ninguno o de confianza) + + + Nivel de confianza + + + Error al obtener el catálogo de paquetes de Microsoft Store. + + + No se encontró ningún paquete de Microsoft Store aplicable en el catálogo de paquetes de Microsoft Store. + + + Error al obtener la información de descarga del paquete Microsoft Store. + + + No se encontró información de descarga del paquete de Microsoft Store aplicable. + + + Error al recuperar la licencia del paquete de Microsoft Store. + + + No se encontró el paquete de Microsoft Store. + + + Hash de paquete de Microsoft Store comprobado correctamente + + + Error de coincidencia del hash del paquete Microsoft Store + + + Paquete de Microsoft Store descargado: {0} + {Locked="{0}"} Full path of the downloaded package. + + + Error al descargar el paquete de Microsoft Store: {0} + {Locked="{0}"} Package name. + + + Descarga del paquete de Microsoft Store completada + + + Descargando paquetes principales de Microsoft Store... + + + Descargando paquetes de dependencias de Microsoft Store... + + + Recuperando información de descarga del paquete de Microsoft Store + + + Error al recuperar la información de descarga del paquete Microsoft Store + + + Recuperar la licencia del paquete de Microsoft Store + + + Se guardó la licencia del paquete de Microsoft Store: {0} + {Locked="{0}"} License file full path. + + + Error al recuperar la licencia del paquete de Microsoft Store + + + La descarga del paquete de Microsoft Store no admite el argumento --rename. El paquete de Microsoft Store usará nombres proporcionados por el catálogo de Microsoft Store. + {Locked="--rename"} + + + La descarga del paquete de Microsoft Store requiere autenticación de Microsoft Entra ID. La solicitud de autenticación puede aparecer cuando sea necesario. La información autenticada se compartirá con servicios Microsoft para la autorización de acceso. Para la licencia de paquetes de Microsoft Store, la cuenta de Microsoft Entra ID debe tener acceso de administrador al inquilino de Microsoft Entra ID. + + + Omite la recuperación de la licencia sin conexión del paquete de Microsoft Store + + + Seleccionar la plataforma de destino + + + Agregando archivo de configuración: {0} + {Locked="{0}"} + + + Se ha exportado correctamente + + + Obteniendo opciones de configuración... + + + Se debe proporcionar al menos --packageId o --module con --resource + {Locked="--packageId,--module, --resource"} + + + Exporta recursos de configuración a un archivo de configuración. Cuando se usa con --packageId, exporta un recurso WinGetPackage del identificador de paquete dado. Cuando se usa con --module y --resource, obtiene la configuración del recurso y lo exporta al archivo de configuración. Si el archivo de configuración de salida ya existe, anexa los recursos de configuración exportados. + {Locked="WinGetPackage,--packageId,--module, --resource"} + + + Exporta recursos de configuración a un archivo de configuración. + + + Módulo del recurso que se va a exportar. + + + Identificador del paquete que se va a exportar. + + + Recurso de configuración que se va a exportar. + + + La unidad de configuración no pudo obtener sus propiedades. + + + Error al exportar la configuración. + + + Configurar {0} + {Locked="{0}"} + + + Instalar {0} + {Locked="{0}"} + + + Algunos de los datos presentes en el archivo de configuración se truncaron para esta salida; inspeccionar el contenido del archivo para obtener el contenido completo. + + + <este valor se ha truncado; inspeccionar el contenido del archivo para ver el texto completo> + Keep some form of separator like the "<>" around the text so that it stands out from the preceding text. + + + Muestra los detalles de alto nivel de las configuraciones que se han aplicado al sistema. Estos datos se pueden usar con `configure` comandos para obtener más detalles. + {Locked="`configure`"} + + + Muestra el historial de configuración + + + No hay ninguna configuración en el historial. + + + Seleccionar elementos del historial + + + No se encontró ninguna configuración única que coincida con los datos proporcionados. Proporcione el nombre completo o parte del identificador que coincida sin ambigüedad con la configuración deseada. + + + Quitar el elemento del historial + + + Primera aplicación + Column header for date values indicating when a configuration was first applied to the system. + + + Identificador + + + Nombre + + + Origen + + + Ruta de acceso + + + No se encontró la configuración especificada. + \ No newline at end of file diff --git a/Localization/Resources/fr-FR/winget.resw b/Localization/Resources/fr-FR/winget.resw index 0c599fee2c..62be3caab7 100644 --- a/Localization/Resources/fr-FR/winget.resw +++ b/Localization/Resources/fr-FR/winget.resw @@ -262,7 +262,7 @@ Elles peuvent être configurées par le biais du fichier de paramètres « wing Filtrer les résultats par identifiant - Supprime les sorties d’avertissement. + Supprime les sorties d'avertissement La licence d’utilisation de cette application vous est octroyée par son propriétaire. @@ -1173,6 +1173,9 @@ Acceptez-vous les conditions ? Date de version : + + Distribution hors ligne prise en charge : + ID de l’Editeur @@ -2272,14 +2275,14 @@ Spécifiez l’un d’entre eux à l’aide de l’option --source pour continue L’opération est bloquée par la stratégie de groupe - - Erreur interne de la source rest + + Erreur interne de l'API Rest URL de source rest non valide - - Type MIME (Multipurpose Internet Mail Extensions) non pris en charge retourné par la source rest + + Type MIME non supporté renvoyé par l'API restante Version de contrat source rest non valide @@ -2299,8 +2302,8 @@ Spécifiez l’un d’entre eux à l’aide de l’option --source pour continue La demande de recherche n’est pas prise en charge par une ou plusieurs sources - - Le point de terminaison de la source rest est introuvable. + + Le point de terminaison de l'API de repos est introuvable. Échec de l’ouverture de la source. @@ -2814,4 +2817,232 @@ Spécifiez l’un d’entre eux à l’aide de l’option --source pour continue Échec de la réparation avec le code de sortie : {0} {Locked="{0}"} Error message displayed when an attempt to repair an application package fails. {0} is a placeholder replaced by an error code. + + La connexion SQLite a été interrompue pour éviter toute altération. + + + Désinstaller toutes les versions + + + La version à suivre + + + Plusieurs versions de ce paquet sont installées. Soit vous affinez la recherche, soit vous passez l'argument `--version` pour en sélectionner une, soit vous passez l'option `--all-versions` pour les désinstaller toutes. + {Locked="--version,--all-versions"} + + + Activer les options de ligne de commande du gestionnaire de paquets Windows + Describes a Group Policy that can enable the use of the --proxy option to set a proxy + + + Définir un proxy à utiliser pour cette exécution + + + Désactiver l’utilisation du proxy pour cette exécution + + + Impossible de réinitialiser {0}. Ce paramètre est contrôlé par la stratégie. Pour plus d’informations, contactez votre administrateur système. + {Locked="{0}"} The value will be replaced with the feature name + + + Réinitialiser les paramètres administratifs '{0}'. + {Locked="{0}"} Message displayed after the user resets an admin setting to its default value. Reset is used as verb in past tense. {0} is a placeholder replaced by the setting name. + + + Impossible de définir {0}. Ce paramètre est contrôlé par la stratégie. Pour plus d’informations, contactez votre administrateur système. + {Locked="{0}"} The value will be replaced with the feature name + + + Régler le paramètre d'administration '{0}' sur '{1}'. + {Locked="{0}"} Message displayed after the user sets the value of an admin setting. Set is used as a verb in past tense. {0} is a placeholder replaced by the setting name. {1} is a placeholder replaced + + + Nom du paramètre à modifier + + + Valeur à définir pour le paramètre. + + + Rétablit la valeur par défaut d’un paramètre d’administrateur. + + + Rétablit la valeur par défaut d’un paramètre d’administrateur. + + + Définit la valeur d'un paramètre administratif. + + + Définit la valeur d'un paramètre administratif. + + + Exclut une source de la recherche, sauf indication contraire + + + Contenu explicite + + + Niveau de confiance de la source (aucun ou approuvé) + + + Niveau de confiance + + + Échec de l'obtention du catalogue de paquets Microsoft Store. + + + Aucun paquet Microsoft Store applicable n'a été trouvé dans le catalogue de paquets Microsoft Store. + + + Échec de l'obtention des informations de téléchargement du paquet Microsoft Store. + + + Aucune information sur le téléchargement du paquet Microsoft Store n'a été trouvée. + + + Échec de la récupération de la licence du paquet Microsoft Store. + + + Le paquet Microsoft Store n'a pas pu être trouvé. + + + Vérification réussie du hachage du paquet Microsoft Store + + + Mauvaise correspondance du hachage du paquet Microsoft Store + + + Paquet Microsoft Store téléchargé : {0} + {Locked="{0}"} Full path of the downloaded package. + + + Le téléchargement du paquet Microsoft Store a échoué : {0} + {Locked="{0}"} Package name. + + + Le téléchargement du paquet Microsoft Store est terminé + + + Téléchargement des principaux paquets à partir du Microsoft Store... + + + Téléchargement de paquets de dépendances à partir du Microsoft Store... + + + Récupération des informations de téléchargement des paquets Microsoft Store + + + Échec de la récupération des informations de téléchargement du paquet Microsoft Store + + + Récupération de la licence du paquet Microsoft Store + + + Licence du paquet Microsoft Store sauvegardée : {0} + {Locked="{0}"} License file full path. + + + Échec de la récupération de la licence du paquet Microsoft Store + + + Le téléchargement du paquet Microsoft Store ne prend pas en charge l'argument --rename. Le paquet Microsoft Store utilisera les noms fournis par le catalogue Microsoft Store. + {Locked="--rename"} + + + Le téléchargement des paquets Microsoft Store nécessite l'authentification Microsoft Entra Id. Une demande d'authentification peut apparaître si nécessaire. Les informations authentifiées seront partagées avec les services Microsoft pour l'autorisation d'accès. Pour l'octroi de licences de paquets Microsoft Store, le compte Microsoft Entra Id doit disposer d'un accès administrateur au locataire Microsoft Entra Id. + + + Ne pas récupérer la licence hors ligne du paquet Microsoft Store + + + Sélectionner la plate-forme cible + + + Ajout d'un fichier de configuration : {0} + {Locked="{0}"} + + + Exportation réussie + + + Obtenir les paramètres de configuration... + + + Au moins --packageId et/ou --module avec --resource doivent être fournis. + {Locked="--packageId,--module, --resource"} + + + Exporte les ressources de configuration vers un fichier de configuration. Lorsqu’il est utilisé avec --packageId, exporte une ressource WinGetPackage de l’ID de package donné. Lorsqu’il est utilisé avec --module et --resource, obtient les paramètres de la ressource et l’exporte vers le fichier de configuration. Si le fichier de configuration de sortie existe déjà, ajoute les ressources de configuration exportées. + {Locked="WinGetPackage,--packageId,--module, --resource"} + + + Exporte les ressources de configuration vers un fichier de configuration. + + + Le module de la ressource à exporter. + + + L'identifiant du paquet à exporter. + + + La ressource de configuration à exporter. + + + L'unité de configuration n'a pas réussi à obtenir ses propriétés. + + + Échec de l'exportation de la configuration. + + + Configuration de {0} + {Locked="{0}"} + + + Installer {0} + {Locked="{0}"} + + + Certaines données présentes dans le fichier de configuration ont été tronquées pour cette sortie ; inspecter le contenu du fichier pour en obtenir le contenu complet. + + + <cette valeur a été tronquée ; consultez le contenu du fichier pour obtenir le texte complet> + Keep some form of separator like the "<>" around the text so that it stands out from the preceding text. + + + Affiche les détails de niveau supérieur pour les configurations qui ont été appliquées au système. Ces données peuvent ensuite être utilisées avec des commandes `configure` pour obtenir plus de détails. + {Locked="`configure`"} + + + Affiche l’historique de configuration + + + On ne trouve aucune configuration dans l'historique. + + + Sélectionner des éléments de l’historique + + + Aucune configuration unique correspondant aux données fournies n’a été trouvée. Fournissez le nom complet ou une partie de l’identificateur qui correspond sans ambiguïté à la configuration souhaitée. + + + Supprimer l’élément de l’historique + + + Première application + Column header for date values indicating when a configuration was first applied to the system. + + + Identificateur + + + Nom + + + Origine + + + Chemin d'accès + + + La configuration spécifiée est introuvable. + \ No newline at end of file diff --git a/Localization/Resources/it-IT/winget.resw b/Localization/Resources/it-IT/winget.resw index 0d944e8483..1bfb9c2ba0 100644 --- a/Localization/Resources/it-IT/winget.resw +++ b/Localization/Resources/it-IT/winget.resw @@ -262,7 +262,7 @@ Possono essere configurati tramite il file di impostazioni ' winget settings '.< Filtra i risultati per ID - Elimina gli output di avviso. + Elimina gli output di avviso Questa applicazione viene concessa in licenza dal proprietario. @@ -1173,6 +1173,9 @@ Accetti le condizioni? Data di rilascio: + + Distribuzione offline supportata: + URL editore: @@ -2272,14 +2275,14 @@ Specificarne uno utilizzando l'opzione --source per continuare. L'operazione è bloccata da Criteri di gruppo - - Errore interno dell'origine rest + + Errore interno dell'API Rest L'URL dell'origine rest non è valido - - Tipo MIME non supportato restituito dall'origine rest + + Tipo MIME non supportato restituito dall'API REST Versione del contratto di origine rest non valida @@ -2299,8 +2302,8 @@ Specificarne uno utilizzando l'opzione --source per continuare. La richiesta di ricerca non è supportata da una o più origini - - L'endpoint di origine rest non è stato trovato. + + L'endpoint dell'API REST non è stato trovato. Impossibile aprire l'origine. @@ -2814,4 +2817,232 @@ Specificarne uno utilizzando l'opzione --source per continuare. Ripristino non riuscito con codice di uscita: {0} {Locked="{0}"} Error message displayed when an attempt to repair an application package fails. {0} is a placeholder replaced by an error code. + + La connessione SQLite è stata terminata per evitare il danneggiamento. + + + Disinstalla tutte le versioni + + + Versione su cui intervenire + + + Sono installate più versioni di questo pacchetto. Affinare la ricerca, passare l'argomento '--version' per selezionarne uno oppure passare il flag '--all-versions' per disinstallarli tutti. + {Locked="--version,--all-versions"} + + + Abilita le opzioni della riga di comando del proxy Gestione pacchetti Windows + Describes a Group Policy that can enable the use of the --proxy option to set a proxy + + + Imposta un proxy da usare per questa esecuzione + + + Disabilita l'uso del proxy per questa esecuzione + + + Impossibile reimpostare {0}. Questa impostazione è controllata dai criteri. Per ulteriori informazioni, contattare l'amministratore di sistema. + {Locked="{0}"} The value will be replaced with the feature name + + + Reimposta l'impostazione di amministrazione '{0}’. + {Locked="{0}"} Message displayed after the user resets an admin setting to its default value. Reset is used as verb in past tense. {0} is a placeholder replaced by the setting name. + + + Impossibile impostare {0}. Questa impostazione è controllata dai criteri. Per ulteriori informazioni, contattare l'amministratore di sistema. + {Locked="{0}"} The value will be replaced with the feature name + + + Esegui l'impostazione di amministrazione '{0}' su '{1}'. + {Locked="{0}"} Message displayed after the user sets the value of an admin setting. Set is used as a verb in past tense. {0} is a placeholder replaced by the setting name. {1} is a placeholder replaced + + + Nome dell'impostazione da modificare + + + Valore da impostare per l'impostazione. + + + Ripristina il valore predefinito di un'impostazione di amministrazione. + + + Ripristina il valore predefinito di un'impostazione di amministrazione. + + + Imposta il valore di un'impostazione di amministrazione. + + + Imposta il valore di un'impostazione di amministrazione. + + + Esclude un'origine dall'individuazione, a meno che non venga specificata + + + Contenuti espliciti + + + Livello di attendibilità dell'origine (nessuno o attendibile) + + + Livello di trust + + + Non è possibile ottenere il catalogo pacchetti Microsoft Store. + + + Non sono stati trovati pacchetti Microsoft Store applicabili dal catalogo pacchetti Microsoft Store. + + + Non è possibile ottenere informazioni sul download del pacchetto Microsoft Store. + + + Non sono disponibili informazioni sul download del pacchetto Microsoft Store applicabili. + + + Non è stato possibile recuperare la licenza del pacchetto Microsoft Store. + + + Non è possibile trovare il pacchetto Microsoft Store. + + + La verifica dell'hash del pacchetto Microsoft Store è stata completata + + + Mancata corrispondenza dell'hash del pacchetto Microsoft Store + + + Pacchetto Microsoft Store scaricato: {0} + {Locked="{0}"} Full path of the downloaded package. + + + Download del pacchetto Microsoft Store non riuscito: {0} + {Locked="{0}"} Package name. + + + Download del pacchetto Microsoft Store completato + + + Download dei pacchetti principali da Microsoft Store... + + + Download dei pacchetti di dipendenze da Microsoft Store... + + + Recupero delle informazioni di download del pacchetto Microsoft Store + + + Non è possibile recuperare le informazioni sul download del pacchetto Microsoft Store + + + Recupero della licenza del pacchetto Microsoft Store + + + Licenza del pacchetto Microsoft Store salvata: {0} + {Locked="{0}"} License file full path. + + + Non è possibile recuperare la licenza del pacchetto Microsoft Store + + + Il download del pacchetto Microsoft Store non supporta l'argomento --rename. Il pacchetto Microsoft Store userà i nomi forniti dal catalogo Microsoft Store. + {Locked="--rename"} + + + Il download del pacchetto Microsoft Store richiede l'autenticazione di Microsoft Entra ID. La richiesta di autenticazione può essere visualizzata quando necessario. Le informazioni autenticate verranno condivise con servizi Microsoft per l'autorizzazione di accesso. Per la gestione delle licenze dei pacchetti Microsoft Store, l'account Microsoft Entra ID deve avere accesso come amministratore al tenant di Microsoft Entra ID. + + + Ignora il recupero della licenza offline del pacchetto Microsoft Store + + + Seleziona la piattaforma di destinazione + + + Aggiunta del file di configurazione: {0} + {Locked="{0}"} + + + Esportazione completata + + + Recupero delle impostazioni di configurazione in corso... + + + È necessario specificare almeno --packageId e/o --module con --resource + {Locked="--packageId,--module, --resource"} + + + Esporta le risorse di configurazione in un file di configurazione. Se usato con --packageId, esporta una risorsa WinGetPackage dell'ID pacchetto specificato. Se usato con --module e --resource, ottiene le impostazioni della risorsa ed esporta la risorsa nel file di configurazione. Se il file di configurazione di output esiste già, aggiunge le risorse di configurazione esportate. + {Locked="WinGetPackage,--packageId,--module, --resource"} + + + Esporta le risorse di configurazione in un file di configurazione. + + + Modulo della risorsa da esportare. + + + Identificatore del pacchetto da esportare. + + + Risorsa di configurazione da esportare. + + + Non è possibile ottenere le proprietà dell'unità di configurazione. + + + Esportazione della configurazione non riuscita. + + + Configura {0} + {Locked="{0}"} + + + Installa {0} + {Locked="{0}"} + + + Alcuni dati presenti nel file di configurazione sono stati troncati per questo output; controllare il contenuto completo del file. + + + <questo valore è stato troncato; controlla il contenuto del file per il testo completo> + Keep some form of separator like the "<>" around the text so that it stands out from the preceding text. + + + Mostra i dettagli di alto livello per le configurazioni applicate al sistema. Questi dati possono quindi essere usati con `configure` comandi per ottenere maggiori dettagli. + {Locked="`configure`"} + + + Mostra la cronologia di configurazione + + + Non sono presenti configurazioni nella cronologia. + + + Seleziona elementi dalla cronologia + + + Impossibile trovare una singola configurazione corrispondente ai dati forniti. Specificare il nome completo o parte dell'identificatore che corrisponda senza ambiguità alla configurazione desiderata. + + + Rimuovi l'elemento dalla cronologia + + + Prima applicazione + Column header for date values indicating when a configuration was first applied to the system. + + + Identificatore + + + Nome + + + Origine + + + Percorso + + + Non è possibile trovare la configurazione specificata. + \ No newline at end of file diff --git a/Localization/Resources/ja-JP/winget.resw b/Localization/Resources/ja-JP/winget.resw index 9867de0569..5112d7dcc7 100644 --- a/Localization/Resources/ja-JP/winget.resw +++ b/Localization/Resources/ja-JP/winget.resw @@ -262,7 +262,7 @@ ID で結果をフィルター処理 - 警告出力を非表示にします。 + 警告出力を非表示にする このアプリケーションは所有者からライセンス供与されます。 @@ -1173,6 +1173,9 @@ リリース日: + + オフライン配信をサポート: + 発行元 URL: @@ -2272,14 +2275,14 @@ 操作はグループ ポリシーによってブロックされています - - REST ソースの内部エラー + + Rest API 内部エラー REST ソース URL が無効です - - サポートされていない MIME の種類が REST ソースから返されました + + REST API によって返されたサポートされていない MIME の種類 REST ソース コントラクト バージョンが無効です @@ -2299,8 +2302,8 @@ 検索要求は 1 つ以上のソースでサポートされていません - - REST ソース エンドポイントが見つかりません。 + + Rest API エンドポイントが見つかりません。 ソースを開けませんでした。 @@ -2814,4 +2817,232 @@ 修復が終了コードで失敗しました: {0} {Locked="{0}"} Error message displayed when an attempt to repair an application package fails. {0} is a placeholder replaced by an error code. + + SQLite 接続は破損を防ぐために終了しました。 + + + すべてのバージョンをアンインストール + + + 処理するバージョン + + + このパッケージの複数のバージョンがインストールされています。検索を絞り込むか、'--version' 引数を渡して 1 つ選択するか、'--all-versions' フラグを渡してすべてをアンインストールしてください。 + {Locked="--version,--all-versions"} + + + プロキシ コマンド ライン オプションWindows パッケージ マネージャー有効にする + Describes a Group Policy that can enable the use of the --proxy option to set a proxy + + + この実行に使用するプロキシを設定します + + + この実行に対するプロキシの使用を無効にする + + + {0} をリセットできません。この設定はポリシーによって制御されます。詳細については、システム管理者に問い合わせてください。 + {Locked="{0}"} The value will be replaced with the feature name + + + 管理者設定 '{0}' をリセットします。 + {Locked="{0}"} Message displayed after the user resets an admin setting to its default value. Reset is used as verb in past tense. {0} is a placeholder replaced by the setting name. + + + {0} を設定できません。この設定はポリシーによって制御されます。詳細については、システム管理者に問い合わせてください。 + {Locked="{0}"} The value will be replaced with the feature name + + + 管理者設定の '{0}' を '{1}' に設定します。 + {Locked="{0}"} Message displayed after the user sets the value of an admin setting. Set is used as a verb in past tense. {0} is a placeholder replaced by the setting name. {1} is a placeholder replaced + + + 変更する設定の名前 + + + 設定に設定する値。 + + + 管理者設定を既定値にリセットします。 + + + 管理者設定を既定値にリセットします。 + + + 管理者設定の値を設定します。 + + + 管理者設定の値を設定します。 + + + 指定しない限り、ソースを検出から除外します + + + 成人指定 + + + ソースの信頼レベル (なしまたは信頼済み) + + + 信頼レベル + + + Microsoft Store パッケージ カタログを取得できませんでした。 + + + Microsoft Store パッケージ カタログから該当する Microsoft Store パッケージが見つかりません。 + + + Microsoft Store パッケージのダウンロード情報を取得できませんでした。 + + + 該当する Microsoft Store パッケージのダウンロード情報が見つかりません。 + + + Microsoft Store パッケージ ライセンスを取得できませんでした。 + + + Microsoft Store パッケージが見つかりませんでした。 + + + Microsoft Store パッケージ ハッシュの検証に成功しました + + + Microsoft Store パッケージ ハッシュの不一致 + + + Microsoft Store パッケージがダウンロードされました: {0} + {Locked="{0}"} Full path of the downloaded package. + + + Microsoft Store パッケージのダウンロードに失敗しました: {0} + {Locked="{0}"} Package name. + + + Microsoft Store パッケージのダウンロードが完了しました + + + Microsoft Store からメイン パッケージをダウンロードしています... + + + Microsoft Store から依存パッケージをダウンロードしています... + + + Microsoft Store パッケージのダウンロード情報を取得しています + + + Microsoft Store パッケージのダウンロード情報を取得できませんでした + + + Microsoft Store パッケージ ライセンスを取得しています + + + Microsoft Store のパッケージ ライセンスを保存しました: {0} + {Locked="{0}"} License file full path. + + + Microsoft Store パッケージ ライセンスを取得できませんでした + + + Microsoft Store パッケージのダウンロードでは、--rename 引数はサポートされていません。Microsoft Store パッケージでは、Microsoft Store カタログによって提供される名前が使用されます。 + {Locked="--rename"} + + + Microsoft Store パッケージのダウンロードには、Microsoft Entra ID 認証が必要です。必要に応じて認証プロンプトが表示されることがあります。認証された情報は、アクセス承認のために Microsoft サービスと共有されます。Microsoft Store パッケージのライセンスを管理するには、Microsoft Entra ID アカウントに Microsoft Entra ID テナントへの管理者アクセス権が必要です。 + + + Microsoft Store パッケージのオフライン ライセンスの取得をスキップします + + + ターゲット プラットフォームの選択 + + + 構成ファイルの追加: {0} + {Locked="{0}"} + + + エクスポートに成功しました + + + 構成設定を取得しています... + + + 少なくとも --packageId および/または --module を --resource とともに指定する必要があります + {Locked="--packageId,--module, --resource"} + + + 構成リソースを構成ファイルにエクスポートします。--packageId と共に使用すると、指定されたパッケージ ID の WinGetPackage リソースがエクスポートされます。--module および --resource と共に使用する場合、リソースの設定を取得し、構成ファイルにエクスポートします。出力構成ファイルが既に存在する場合は、エクスポートされた構成リソースを追加します。 + {Locked="WinGetPackage,--packageId,--module, --resource"} + + + 構成リソースを構成ファイルにエクスポートします。 + + + エクスポートするリソースのモジュール。 + + + エクスポートするパッケージ識別子。 + + + エクスポートする構成リソース。 + + + 構成ユニットはプロパティの取得に失敗しました。 + + + 構成をエクスポートできませんでした。 + + + {0} の構成 + {Locked="{0}"} + + + {0} のインストール + {Locked="{0}"} + + + 構成ファイルに存在するデータの一部が、この出力に対して切り捨てられました。ファイルの内容を検査して、完全なコンテンツを確認してください。 + + + <この値は切り捨てられています。完全なテキストについてはファイルの内容を調べてください> + Keep some form of separator like the "<>" around the text so that it stands out from the preceding text. + + + システムに適用された構成の詳細レベルを表示します。このデータは、`configure` コマンドと共に使用して、詳細を取得できます。 + {Locked="`configure`"} + + + 構成履歴の表示 + + + 履歴に構成はありません。 + + + 履歴からアイテムを選択する + + + 指定されたデータに一致する単一の構成が見つかりませんでした。必要な構成と厳密に一致する完全な名前または識別子の一部を指定してください。 + + + 履歴からアイテムを削除する + + + 最初に適用された日 + Column header for date values indicating when a configuration was first applied to the system. + + + ID + + + 名前 + + + 元の場所 + + + パス + + + 指定された構成が見つかりませんでした。 + \ No newline at end of file diff --git a/Localization/Resources/ko-KR/winget.resw b/Localization/Resources/ko-KR/winget.resw index f551778486..af5bf1ddcb 100644 --- a/Localization/Resources/ko-KR/winget.resw +++ b/Localization/Resources/ko-KR/winget.resw @@ -1173,6 +1173,9 @@ 릴리스 날짜: + + 지원되는 오프라인 배포: + 게시자 URL: @@ -2272,14 +2275,14 @@ 작업이 그룹 정책 의해 차단되었습니다. - - Rest 원본 내부 오류 + + Rest API 내부 오류 잘못된 REST 원본 URL - - rest 원본에서 반환된 지원되지 않는 MIME 형식 + + REST API에서 반환된 지원되지 않는 MIME 형식 잘못된 REST 원본 계약 버전 @@ -2299,8 +2302,8 @@ 하나 이상의 원본에서 검색 요청을 지원하지 않습니다. - - 나머지 원본 엔드포인트를 찾을 수 없습니다. + + 나머지 API 엔드포인트를 찾을 수 없습니다. 원본을 열지 못했습니다. @@ -2814,4 +2817,232 @@ 복구하지 못했습니다. 종료 코드: {0} {Locked="{0}"} Error message displayed when an attempt to repair an application package fails. {0} is a placeholder replaced by an error code. + + 손상을 방지하기 위해 SQLite 연결을 종료했습니다. + + + 모든 버전 제거 + + + 작업할 버전 + + + 이 패키지의 여러 버전이 설치되어 있습니다. 검색을 구체화하거나,'--version' 인수를 전달하여 하나를 선택하거나, '--all-versions' 플래그를 전달하여 모두 제거하세요. + {Locked="--version,--all-versions"} + + + 프록시 명령줄 옵션 Windows 패키지 관리자 사용 + Describes a Group Policy that can enable the use of the --proxy option to set a proxy + + + 이 실행에 사용할 프록시 설정 + + + 이 실행에 프록시 사용 안 함 + + + {0} 다시 설정할 수 없습니다. 이 설정은 정책에 의해 제어됩니다. 자세한 내용은 시스템 관리자에게 문의하십시오. + {Locked="{0}"} The value will be replaced with the feature name + + + 관리자 설정 ‘{0}’을(를) 초기화합니다. + {Locked="{0}"} Message displayed after the user resets an admin setting to its default value. Reset is used as verb in past tense. {0} is a placeholder replaced by the setting name. + + + {0} 설정할 수 없습니다. 이 설정은 정책에 의해 제어됩니다. 자세한 내용은 시스템 관리자에게 문의하십시오. + {Locked="{0}"} The value will be replaced with the feature name + + + 관리자 설정 '{0}'을(를) '{1}'(으)로 설정합니다. + {Locked="{0}"} Message displayed after the user sets the value of an admin setting. Set is used as a verb in past tense. {0} is a placeholder replaced by the setting name. {1} is a placeholder replaced + + + 수정할 설정의 이름 + + + 설정에 대해 설정할 값입니다. + + + 관리자 설정을 기본값으로 다시 설정합니다. + + + 관리자 설정을 기본값으로 다시 설정합니다. + + + 관리자 설정의 값을 설정합니다. + + + 관리자 설정의 값을 설정합니다. + + + 지정하지 않는 한 검색에서 원본 제외 + + + 유해 콘텐츠 + + + 원본의 신뢰 수준(없음 또는 신뢰할 수 없음) + + + 신뢰 수준 + + + Microsoft Store 패키지 카탈로그를 가져오지 못했습니다. + + + Microsoft Store 패키지 카탈로그에서 적용 가능한 Microsoft Store 패키지를 찾을 수 없습니다. + + + Microsoft Store 패키지 다운로드 정보를 가져오지 못했습니다. + + + 적용 가능한 Microsoft Store 패키지 다운로드 정보를 찾을 수 없습니다. + + + Microsoft Store 패키지 라이선스를 검색하지 못했습니다. + + + Microsoft Store 패키지를 찾을 수 없습니다. + + + Microsoft Store 패키지 해시가 성공적으로 확인되었습니다. + + + Microsoft Store 패키지 해시 불일치 + + + Microsoft Store 패키지 다운로드됨: {0} + {Locked="{0}"} Full path of the downloaded package. + + + Microsoft Store 패키지 다운로드 실패: {0} + {Locked="{0}"} Package name. + + + Microsoft Store 패키지 다운로드 완료 + + + Microsoft Store 기본 패키지를 다운로드하는 중... + + + Microsoft Store에서 종속성 패키지를 다운로드하는 중... + + + Microsoft Store 패키지 다운로드 정보 검색 + + + Microsoft Store 패키지 다운로드 정보를 검색하지 못했습니다. + + + Microsoft Store 패키지 라이선스 검색 + + + Microsoft Store 패키지 라이선스 저장됨: {0} + {Locked="{0}"} License file full path. + + + Microsoft Store 패키지 라이선스를 검색하지 못했습니다. + + + Microsoft Store 패키지 다운로드는 --rename 인수를 지원하지 않습니다. Microsoft Store 패키지는 Microsoft Store 카탈로그에서 제공하는 이름을 사용합니다. + {Locked="--rename"} + + + Microsoft Store 패키지를 다운로드하려면 Microsoft Entra ID 인증이 필요합니다. 필요한 경우 인증 프롬프트가 표시될 수 있습니다. 인증된 정보는 액세스 권한 부여를 위해 Microsoft 서비스 공유됩니다. Microsoft Store 패키지 라이선스의 경우 Microsoft Entra ID 계정에 Microsoft Entra ID 테넌트에 대한 관리자 액세스 권한이 있어야 합니다. + + + Microsoft Store 패키지 오프라인 라이선스 검색 건너뛰기 + + + 대상 플랫폼 선택 + + + 구성 파일 추가: {0} + {Locked="{0}"} + + + 내보냈습니다. + + + 구성 설정을 가져오는 중... + + + 최소한 --resource와 함께 --packageId 및/또는 --module을 제공해야 합니다. + {Locked="--packageId,--module, --resource"} + + + 구성 리소스를 구성 파일로 내보냅니다. --packageId와 함께 사용하면 지정된 패키지 ID의 WinGetPackage 리소스를 내보냅니다. --module 및 --resource와 함께 사용하면 리소스의 설정을 가져오고 구성 파일로 내보냅니다. 출력 구성 파일이 이미 있으면 내보낸 구성 리소스를 추가합니다. + {Locked="WinGetPackage,--packageId,--module, --resource"} + + + 구성 리소스를 구성 파일로 내보냅니다. + + + 내보낼 리소스의 모듈입니다. + + + 내보낼 패키지 식별자입니다. + + + 내보낼 구성 리소스입니다. + + + 구성 단위가 해당 속성을 가져오지 못했습니다. + + + 구성을 내보내지 못했습니다. + + + {0} 구성 + {Locked="{0}"} + + + {0} 설치 + {Locked="{0}"} + + + 구성 파일에 있는 일부 데이터가 이 출력에 대해 잘렸습니다. 파일 콘텐츠를 검사하여 전체 콘텐츠를 검사합니다. + + + <이 값이 잘렸습니다. 전체 텍스트를 보려면 파일 내용을 검사합니다> + Keep some form of separator like the "<>" around the text so that it stands out from the preceding text. + + + 시스템에 적용된 구성에 대한 높은 수준의 세부 정보를 표시합니다. 그런 다음 이 데이터를 `configure` 명령과 함께 사용하여 자세한 정보를 확인할 수 있습니다. + {Locked="`configure`"} + + + 구성 기록 표시 + + + 기록에 구성이 없습니다. + + + 기록에서 항목 선택 + + + 제공된 데이터와 일치하는 단일 구성을 찾을 수 없습니다. 원하는 구성과 명확하게 일치하는 식별자의 전체 이름 또는 일부를 제공하십시오. + + + 기록에서 항목 제거 + + + 처음 적용됨 + Column header for date values indicating when a configuration was first applied to the system. + + + 식별자 + + + 이름 + + + 원본 + + + 경로 + + + 지정한 구성을 찾을 수 없습니다. + \ No newline at end of file diff --git a/Localization/Resources/pt-BR/winget.resw b/Localization/Resources/pt-BR/winget.resw index 2c8ba5aaf2..ca09ac6258 100644 --- a/Localization/Resources/pt-BR/winget.resw +++ b/Localization/Resources/pt-BR/winget.resw @@ -262,7 +262,7 @@ Eles podem ser configurados por meio do arquivo de configurações ' winget sett Filtrar resultados por id - Suprime as saídas de aviso. + Suprime saídas de aviso Este aplicativo é licenciado para você pelo proprietário. @@ -1173,6 +1173,9 @@ Você concorda com os termos? Data do Lançamento: + + Distribuição Offline Com Suporte: + URL do Fornecedor: @@ -2272,14 +2275,14 @@ Especifique um deles usando a opção --source para continuar. A operação está bloqueada pela Política de Grupo - - Erro interno da origem REST + + Erro interno da API Rest URL de origem REST inválida - - Não há suporte para o tipo MIME retornado pela origem REST + + Tipo MIME sem suporte retornado pela API rest Versão inválida do contrato da origem REST @@ -2299,8 +2302,8 @@ Especifique um deles usando a opção --source para continuar. Uma ou mais fontes não dão suporte à solicitação de pesquisa - - O ponto de extremidade da origem REST não foi encontrado. + + O ponto de extremidade da API rest não foi encontrado. Falha ao abrir a origem. @@ -2814,4 +2817,232 @@ Especifique um deles usando a opção --source para continuar. O reparo falhou com o código de saída: {0} {Locked="{0}"} Error message displayed when an attempt to repair an application package fails. {0} is a placeholder replaced by an error code. + + A conexão SQLite foi encerrada para evitar danos. + + + Desinstale todas as versões + + + A versão para agir + + + Várias versões deste pacote estão instaladas. Refine a pesquisa, passe o argumento '--version' para selecionar um ou passe o sinalizador '--all-versions' para desinstalar todos eles. + {Locked="--version,--all-versions"} + + + Habilitar Gerenciador de Pacotes do Windows de linha de comando do proxy atual + Describes a Group Policy that can enable the use of the --proxy option to set a proxy + + + Definir um proxy a ser usado para esta execução + + + Desabilitar o uso de proxy para esta execução + + + Não é possível redefinir {0}. Esta configuração é controlada pela política. Para obter mais informações, contate o administrador do sistema. + {Locked="{0}"} The value will be replaced with the feature name + + + Redefinir configuração de administrador '{0}'. + {Locked="{0}"} Message displayed after the user resets an admin setting to its default value. Reset is used as verb in past tense. {0} is a placeholder replaced by the setting name. + + + Não é possível definir {0}. Esta configuração é controlada pela política. Para obter mais informações, contate o administrador do sistema. + {Locked="{0}"} The value will be replaced with the feature name + + + Defina a configuração de administrador '{0}' para '{1}'. + {Locked="{0}"} Message displayed after the user sets the value of an admin setting. Set is used as a verb in past tense. {0} is a placeholder replaced by the setting name. {1} is a placeholder replaced + + + Nome da configuração a ser modificada + + + Valor a ser definido para a configuração. + + + Redefine uma configuração de administrador para seu valor padrão. + + + Redefine uma configuração de administrador para seu valor padrão. + + + Define o valor de uma configuração de administrador. + + + Define o valor de uma configuração de administrador. + + + Exclui uma fonte da descoberta, a menos que especificado + + + Explícito + + + Nível de confiança da origem (nenhum ou confiável) + + + Nível de Confiança + + + Falha ao obter o catálogo do pacotes da Microsoft Store. + + + Nenhum pacote aplicável da Microsoft Store encontrado no catálogo dos pacotes da Microsoft Store. + + + Recuperando informações de download do pacote Microsoft Store. + + + Nenhuma informação de download do pacote da Microsoft Store aplicável foi encontrada. + + + Falha ao recuperar a licença do pacote da Microsoft Store. + + + O pacote da Microsoft Store não foi encontrado. + + + Hash do pacote da Microsoft Store verificado com êxito + + + Incompatibilidade de hash do pacote da Microsoft Store + + + Pacote da Microsoft Store baixado: {0} + {Locked="{0}"} Full path of the downloaded package. + + + Falha no download do pacote da Microsoft Store: {0} + {Locked="{0}"} Package name. + + + Download do pacote da Microsoft Store concluído + + + Baixando pacotes principais da Microsoft Store... + + + Baixando pacotes de dependências da Microsoft Store... + + + Recuperando informações de download de pacotes da Microsoft Store + + + Falha ao recuperar informações de download do pacote da Microsoft Store + + + Recuperando licença do pacote da Microsoft Store + + + Licença do pacote da Microsoft Store salva: {0} + {Locked="{0}"} License file full path. + + + Falha ao recuperar a licença do pacote da Microsoft Store + + + O download do pacote da Microsoft Store não dá suporte ao argumento --rename. O pacote da Microsoft Store usará nomes fornecidos pelo catálogo da Microsoft Store. + {Locked="--rename"} + + + O download do pacote da Microsoft Store requer autenticação do Microsoft Entra ID. O prompt de autenticação poderá ser exibido quando necessário. As informações autenticadas serão compartilhadas com os serviços da Microsoft para autorização de acesso. Para o licenciamento de pacotes da Microsoft Store, a conta do Microsoft Entra ID precisa ter acesso de administrador ao locatário do Microsoft Entra ID. + + + Ignora a recuperação da licença offline do pacote da Microsoft Store + + + Selecione a plataforma de destino + + + Adicionando arquivo de configuração: {0} + {Locked="{0}"} + + + Exportado com êxito + + + Obtendo definições de configuração... + + + Pelo menos --packageId e/ou --module com --resource devem ser fornecidos + {Locked="--packageId,--module, --resource"} + + + Exporta recursos de configuração para um arquivo de configuração. Quando usado com --packageId, exporta um recurso WinGetPackage da ID do pacote fornecida. Quando usado com --module e --resource, obtém as configurações do recurso e exporta-o para o arquivo de configuração. Se o arquivo de configuração de saída já existir, anexa os recursos de configuração exportados. + {Locked="WinGetPackage,--packageId,--module, --resource"} + + + Exporta recursos de configuração para um arquivo de configuração. + + + O módulo do recurso a ser exportado. + + + O identificador do pacote a ser exportado. + + + O recurso de configuração a ser exportado. + + + Falha na unidade de configuração ao obter suas propriedades. + + + Falha na exportação da configuração. + + + Configurar {0} + {Locked="{0}"} + + + Instalar {0} + {Locked="{0}"} + + + Alguns dos dados presentes no arquivo de configuração foram truncados para esta saída; inspecione o conteúdo do arquivo para obter o conteúdo completo. + + + <este valor foi truncado; inspecione o conteúdo do arquivo para obter o texto completo> + Keep some form of separator like the "<>" around the text so that it stands out from the preceding text. + + + Mostra os detalhes de alto nível das configurações que foram aplicadas ao sistema. Em seguida, os dados podem ser usados com `configure` para obter mais detalhes. + {Locked="`configure`"} + + + Mostra o histórico de configurações + + + Não há configurações no histórico. + + + Selecionar itens do histórico + + + Não foi encontrada nenhuma configuração única que corresponda aos dados fornecidos. Forneça o nome completo ou parte do identificador que corresponda ineiguamente à configuração desejada. + + + Remover o item do histórico + + + Primeira Aplicação + Column header for date values indicating when a configuration was first applied to the system. + + + Identificador + + + Nome + + + Origem + + + Caminho + + + Não foi possível encontrar a configuração especificada. + \ No newline at end of file diff --git a/Localization/Resources/ru-RU/winget.resw b/Localization/Resources/ru-RU/winget.resw index c125f7db6c..1263178025 100644 --- a/Localization/Resources/ru-RU/winget.resw +++ b/Localization/Resources/ru-RU/winget.resw @@ -262,7 +262,7 @@ Фильтровать результаты по идентификатору - Подавляет вывод предупреждений. + Подавляет вывод предупреждений Лицензия на это приложение предоставлена вам владельцем. @@ -1173,6 +1173,9 @@ Дата выпуска: + + Поддерживается автономное распространение: + URL-адрес издателя: @@ -2272,14 +2275,14 @@ Операция заблокирована групповой политикой - - Внутренняя ошибка источника REST + + Внутренняя ошибка REST API Недопустимый URL-адрес источника REST - - Источник REST вернул неподдерживаемый тип MIME + + REST API вернул неподдерживаемый тип MIME Недопустимая версия контракта источника REST @@ -2299,8 +2302,8 @@ Запрос поиска не поддерживается одним или несколькими источниками - - Конечная точка источника REST не найдена. + + Конечная точка REST API не найдена. Не удалось открыть источник. @@ -2814,4 +2817,232 @@ Сбой восстановления с кодом выхода: {0} {Locked="{0}"} Error message displayed when an attempt to repair an application package fails. {0} is a placeholder replaced by an error code. + + Подключение SQLite было разорвано для предотвращения повреждения. + + + Удалить все версии + + + Версия для действий + + + Установлено несколько версий этого пакета. Уточните условия поиска, передайте аргумент "--version", чтобы выбрать его, или передайте флаг "--all-versions", чтобы удалить все из них. + {Locked="--version,--all-versions"} + + + Включить Диспетчер пакетов Windows командной строки прокси-сервера + Describes a Group Policy that can enable the use of the --proxy option to set a proxy + + + Задать прокси-сервер для этого выполнения + + + Отключить использование прокси-сервера для этого выполнения + + + Не удается сбросить {0}. Этот параметр управляется политикой. Для получения дополнительных сведений обратитесь к системному администратору. + {Locked="{0}"} The value will be replaced with the feature name + + + Сброс параметра администратора "{0}". + {Locked="{0}"} Message displayed after the user resets an admin setting to its default value. Reset is used as verb in past tense. {0} is a placeholder replaced by the setting name. + + + Невозможно задать {0}. Этот параметр управляется политикой. Для получения дополнительных сведений обратитесь к системному администратору. + {Locked="{0}"} The value will be replaced with the feature name + + + Задайте для параметра администратора "{0}" значение "{1}". + {Locked="{0}"} Message displayed after the user sets the value of an admin setting. Set is used as a verb in past tense. {0} is a placeholder replaced by the setting name. {1} is a placeholder replaced + + + Имя изменяемого параметра + + + Значение, настраиваемое для параметра. + + + Сбрасывает значение по умолчанию для параметра администратора. + + + Сбрасывает значение по умолчанию для параметра администратора. + + + Задает значение параметра администратора. + + + Задает значение параметра администратора. + + + Исключает источник из обнаружения, если не указано + + + Возрастные ограничения + + + Уровень доверия источника (нет или недоверенный) + + + Уровень доверия + + + Не удалось получить каталог пакетов Microsoft Store. + + + Применимый пакет Microsoft Store не найден в каталоге пакетов Microsoft Store. + + + Не удалось получить сведения о скачивании пакета Microsoft Store. + + + Применимые сведения о скачивании пакета Microsoft Store не найдены. + + + Не удалось получить лицензию пакета Microsoft Store. + + + Не удалось найти пакет Microsoft Store. + + + Хэш пакета Microsoft Store успешно проверен + + + Несоответствие хэша пакета Microsoft Store + + + Пакет Microsoft Store скачан: {0} + {Locked="{0}"} Full path of the downloaded package. + + + Не удалось скачать пакет Microsoft Store: {0} + {Locked="{0}"} Package name. + + + Скачивание пакета Microsoft Store завершено + + + Скачивание основных пакетов из Microsoft Store... + + + Скачивание пакетов зависимостей из Microsoft Store... + + + Получение сведений о скачивании пакета Microsoft Store + + + Не удалось получить сведения о скачивании пакета Microsoft Store + + + Получение лицензии пакета Microsoft Store + + + Лицензия пакета Microsoft Store сохранена: {0} + {Locked="{0}"} License file full path. + + + Не удалось получить лицензию пакета Microsoft Store + + + Скачивание пакета Microsoft Store не поддерживает аргумент --rename. Пакет Microsoft Store будет использовать имена, предоставленные каталогом Microsoft Store. + {Locked="--rename"} + + + Для скачивания пакета Microsoft Store требуется проверка подлинности Microsoft Entra ID. При необходимости может появиться запрос проверки подлинности. Сведения проверки подлинности будут предоставлены службам Майкрософт для авторизации доступа. Для лицензирования пакета Microsoft Store учетная запись Microsoft Entra ID должна обладать правами администратора на доступ к клиенту Microsoft Entra ID. + + + Пропускает получение автономной лицензии пакета Microsoft Store + + + Выбор целевой платформы + + + Добавление файла конфигурации: {0} + {Locked="{0}"} + + + Экспорт успешно выполнен + + + Получение параметров конфигурации... + + + Необходимо указать хотя бы --packageId и (или) --module с параметром --resource + {Locked="--packageId,--module, --resource"} + + + Экспорт ресурсов конфигурации в файл конфигурации. При использовании с --packageId выполняется экспорт ресурса WinGetPackage указанного идентификатора пакета. При использовании с --module и --resource получает параметры ресурса и экспортирует его в файл конфигурации. Если выходной файл конфигурации уже существует, добавляет экспортированные ресурсы конфигурации. + {Locked="WinGetPackage,--packageId,--module, --resource"} + + + Экспорт ресурсов конфигурации в файл конфигурации. + + + Модуль ресурса для экспорта. + + + Идентификатор пакета для экспорта. + + + Ресурс конфигурации для экспорта. + + + Единице конфигурации не удалось получить свойства. + + + Не удалось экспортировать конфигурацию. + + + {0}: настройка + {Locked="{0}"} + + + Установить {0} + {Locked="{0}"} + + + Некоторые данные в файле конфигурации были усечены для этого вывода; проверьте содержимое файла на наличие полного содержимого. + + + <это значение было усечено; проверьте содержимое файла на наличие полного текста> + Keep some form of separator like the "<>" around the text so that it stands out from the preceding text. + + + Отображение сведений о конфигурациях высокого уровня, которые были применены к системе. Эти данные можно использовать с командами `configure` для получения дополнительных сведений. + {Locked="`configure`"} + + + Отображает журнал конфигурации + + + В журнале нет конфигураций. + + + Выбор элементов из журнала + + + Не удалось найти одну конфигурацию, соответствующую предоставленным данным. Укажите полное имя или часть идентификатора, однозначно соответствующую требуемой конфигурации. + + + Удалить элемент из журнала + + + Первое применение + Column header for date values indicating when a configuration was first applied to the system. + + + Идентификатор + + + Имя + + + Источник + + + Путь + + + Не удалось найти указанную конфигурацию. + \ No newline at end of file diff --git a/Localization/Resources/zh-CN/winget.resw b/Localization/Resources/zh-CN/winget.resw index 25450554db..52512d8c75 100644 --- a/Localization/Resources/zh-CN/winget.resw +++ b/Localization/Resources/zh-CN/winget.resw @@ -262,7 +262,7 @@ 按 id 筛选结果 - 禁止显示警告输出。 + 禁止显示警告输出 此应用程序由其所有者授权给你。 @@ -1173,6 +1173,9 @@ 发布日期: + + 支持脱机分发: + 发布服务器 URL: @@ -2272,14 +2275,14 @@ 操作被组策略阻止 - - REST 源内部错误 + + Rest API 内部错误 REST 源 URL 无效 - - REST 源返回的 MIME 类型不受支持 + + REST API 返回的 MIME 类型不受支持 REST 源合同版本无效 @@ -2299,8 +2302,8 @@ 一个或多个源不支持搜索请求 - - 找不到 REST 源终结点。 + + 找不到 Rest API 终结点。 未能打开源。 @@ -2814,4 +2817,232 @@ 修复失败,退出代码为: {0} {Locked="{0}"} Error message displayed when an attempt to repair an application package fails. {0} is a placeholder replaced by an error code. + + 为了防止损坏,SQLite 连接已终止。 + + + 卸载所有版本 + + + 要执行的版本 + + + 已安装此包的多个版本。请优化搜索,传递 “--version” 参数以选择一个,或传递 “--all-versions” 标志以卸载所有这些参数。 + {Locked="--version,--all-versions"} + + + 启用Windows 程序包管理器代理命令行选项 + Describes a Group Policy that can enable the use of the --proxy option to set a proxy + + + 设置要用于此执行的代理 + + + 禁止对此执行使用代理 + + + 无法重置 {0}。此设置由策略控制。有关详细信息,请与系统管理员联系。 + {Locked="{0}"} The value will be replaced with the feature name + + + 重置管理员设置“{0}”。 + {Locked="{0}"} Message displayed after the user resets an admin setting to its default value. Reset is used as verb in past tense. {0} is a placeholder replaced by the setting name. + + + 无法设置 {0}。此设置由策略控制。有关详细信息,请与系统管理员联系。 + {Locked="{0}"} The value will be replaced with the feature name + + + 将管理员设置 '{0}' 设置为 '{1}'。 + {Locked="{0}"} Message displayed after the user sets the value of an admin setting. Set is used as a verb in past tense. {0} is a placeholder replaced by the setting name. {1} is a placeholder replaced + + + 要修改的设置的名称 + + + 要为设置设置的值。 + + + 将管理员设置重置为其默认值。 + + + 将管理员设置重置为其默认值。 + + + 设置管理员设置的值。 + + + 设置管理员设置的值。 + + + 除非指定,否则从发现中排除源 + + + 显式 + + + 源的信任级别 (无或受信任的) + + + 信任级别 + + + 未能获取 Microsoft Store 程序包目录。 + + + 未从 Microsoft Store 程序包目录中找到适用的 Microsoft Store 程序包。 + + + 无法获取 Microsoft Store 程序包下载信息。 + + + 找不到适用的 Microsoft Store 程序包下载信息。 + + + 无法检索 Microsoft Store 程序包许可证。 + + + 找不到 Microsoft Store 程序包。 + + + 已成功验证 Microsoft Store 程序包哈希 + + + Microsoft Store 程序包哈希不匹配 + + + 已下载 Microsoft Store 程序包: {0} + {Locked="{0}"} Full path of the downloaded package. + + + Microsoft Store 程序包下载失败: {0} + {Locked="{0}"} Package name. + + + 已完成 Microsoft Store 程序包下载 + + + 正在从 Microsoft Store 下载主程序包... + + + 正在从 Microsoft Store 下载依赖项程序包... + + + 正在检索 Microsoft Store 程序包下载信息 + + + 未能检索 Microsoft Store 程序包下载信息 + + + 正在检索 Microsoft Store 程序包许可证 + + + 已保存 Microsoft Store 程序包许可证: {0} + {Locked="{0}"} License file full path. + + + 未能检索 Microsoft Store 程序包许可证 + + + Microsoft Store 程序包下载不支持 --rename 参数。Microsoft Store 程序包将使用 Microsoft Store 目录提供的名称。 + {Locked="--rename"} + + + Microsoft Store 程序包下载需要 Microsoft Entra ID 身份验证。必要时可能会显示身份验证提示。将与 Microsoft 服务共享经过身份验证的信息以进行访问授权。对于 Microsoft Store 程序包授权,Microsoft Entra ID 帐户需要具有对 Microsoft Entra ID 租户的管理员访问权限。 + + + 跳过检索 Microsoft Store 程序包脱机许可证 + + + 选择目标平台 + + + 正在添加配置文件: {0} + {Locked="{0}"} + + + 已成功导出 + + + 正在获取配置设置... + + + 必须至少提供 --packageId 和/或 --module 以及 --resource + {Locked="--packageId,--module, --resource"} + + + 将配置资源导出到配置文件。与 --packageId 一起使用时,导出给定包 ID 的 WinGetPackage 资源。与 --module 和 --resource 一起使用时,获取资源的设置并将其导出到配置文件。如果输出配置文件已存在,则追加导出的配置资源。 + {Locked="WinGetPackage,--packageId,--module, --resource"} + + + 将配置资源导出到配置文件。 + + + 要导出的资源的模块。 + + + 要导出的程序包标识符。 + + + 要导出的配置资源。 + + + 配置单元无法获取其属性。 + + + 导出配置失败。 + + + 配置{0} + {Locked="{0}"} + + + 安装 {0} + {Locked="{0}"} + + + 对于此输出,配置文件中存在的某些数据被截断;检查文件内容的完整内容。 + + + <此值已被截断;检查文件内容以获取完整文本> + Keep some form of separator like the "<>" around the text so that it stands out from the preceding text. + + + 显示已应用于系统的配置的高级别详细信息。然后,此数据可与 `configure` 命令一起使用以获取更多详细信息。 + {Locked="`configure`"} + + + 显示配置历史记录 + + + 历史记录中没有配置。 + + + 从历史记录中选择项目 + + + 找不到与提供的数据匹配的单个配置。提供与所需配置明确匹配的全名或标识符的一部分。 + + + 从历史记录中移除项 + + + 首次应用 + Column header for date values indicating when a configuration was first applied to the system. + + + 标识符 + + + 名称 + + + 来源 + + + 路径 + + + 找不到指定的配置。 + \ No newline at end of file diff --git a/Localization/Resources/zh-TW/winget.resw b/Localization/Resources/zh-TW/winget.resw index 081feed14f..b92478e721 100644 --- a/Localization/Resources/zh-TW/winget.resw +++ b/Localization/Resources/zh-TW/winget.resw @@ -262,7 +262,7 @@ 依識別碼篩選結果 - 抑制警告輸出。 + 抑制警告輸出 此應用程式已由其擁有者授權給您。 @@ -1173,6 +1173,9 @@ 發行日期: + + 支援離線散發: + 發行者 URL: @@ -2272,14 +2275,14 @@ [群組原則] 封鎖作業 - - 剩餘來源內部錯誤 + + Rest API 內部錯誤 剩餘來源 URL 無效 - - 剩餘來源傳回不支援的 MIME 類型 + + 剩餘 API 傳回不支援的 MIME 類型 休息來源合約版本無效 @@ -2299,8 +2302,8 @@ 一或多個來源不支持搜尋要求 - - 找不到剩餘來源端點。 + + 找不到其餘的 API 端點。 無法開啟來源。 @@ -2814,4 +2817,232 @@ 修復失敗,結束代碼為: {0} {Locked="{0}"} Error message displayed when an attempt to repair an application package fails. {0} is a placeholder replaced by an error code. + + 已終止 SQLite 連線以避免損毀。 + + + 解除安裝所有版本 + + + 要執行的版本 + + + 已安裝此套件的多個版本。請精簡搜尋、傳遞 '--version' 自變數以選取,或傳遞 '--all-versions' 旗標以卸載所有專案。 + {Locked="--version,--all-versions"} + + + 啟用Windows 封裝管理員 Proxy 命令行選項 + Describes a Group Policy that can enable the use of the --proxy option to set a proxy + + + 設定要用於此執行的 Proxy + + + 停用此執行的 Proxy 使用 + + + 無法重設 {0}。這個設定是由原則控制。如需詳細資訊,請連絡您的系統管理員。 + {Locked="{0}"} The value will be replaced with the feature name + + + 重設系統管理員設定 '{0}'。 + {Locked="{0}"} Message displayed after the user resets an admin setting to its default value. Reset is used as verb in past tense. {0} is a placeholder replaced by the setting name. + + + 無法設定 {0}。這個設定是由原則控制。如需詳細資訊,請連絡您的系統管理員。 + {Locked="{0}"} The value will be replaced with the feature name + + + 將系統管理員設定 '{0}' 設為 '{1}'。 + {Locked="{0}"} Message displayed after the user sets the value of an admin setting. Set is used as a verb in past tense. {0} is a placeholder replaced by the setting name. {1} is a placeholder replaced + + + 要修改之設定的名稱 + + + 要為設定設定的值。 + + + 將系統管理員設定重設為其預設值。 + + + 將系統管理員設定重設為其預設值。 + + + 設定系統管理設定的值。 + + + 設定系統管理設定的值。 + + + 除非指定,否則將來源排除在探索之外 + + + 偏激 + + + 來源的信任層級 (無或信任) + + + 信任層級 + + + 無法取得 Microsoft Store 封裝類別目錄。 + + + 在套件目錄 Microsoft Store 找不到適用的 Microsoft Store 封裝。 + + + 無法取得 Microsoft Store 套件下載資訊。 + + + 找不到適用 Microsoft Store 套件下載資訊。 + + + 無法擷取 Microsoft Store 套件授權。 + + + 找不到 Microsoft Store 封裝。 + + + 已成功驗證 Microsoft Store 套件雜湊 + + + Microsoft Store 套件雜湊不符 + + + 已下載 Microsoft Store套件: {0} + {Locked="{0}"} Full path of the downloaded package. + + + Microsoft Store 套件下載失敗: {0} + {Locked="{0}"} Package name. + + + Microsoft Store 套件下載完成 + + + 正在從 Microsoft Store 下載主要套件... + + + 正在從 Microsoft Store 下載相依性套件... + + + 正在擷取 Microsoft Store 套件下載資訊 + + + 無法擷取 Microsoft Store 套件下載資訊 + + + 正在擷取 Microsoft Store 套件授權 + + + 已儲存 Microsoft Store套件授權: {0} + {Locked="{0}"} License file full path. + + + 無法擷取 Microsoft Store 套件授權 + + + Microsoft Store 套件下載不支援 --rename 引數。Microsoft Store 封裝將使用 Microsoft Store 目錄提供的名稱。 + {Locked="--rename"} + + + Microsoft Store 套件下載需要 Microsoft Entra ID 驗證。必要時可能會顯示驗證提示。將與 Microsoft 服務共用已驗證的資訊,以進行存取授權。若要 Microsoft Store 套件授權,Microsoft Entra ID 帳戶必須具有 Microsoft Entra ID 租用戶的系統管理員存取權。 + + + 略過擷取 Microsoft Store 套件離線授權 + + + 選取目標平台 + + + 正在新增設定檔: {0} + {Locked="{0}"} + + + 已成功匯出 + + + 正在取得組態設定... + + + 至少必須提供 --packageId 和/或 --module with --resource + {Locked="--packageId,--module, --resource"} + + + 將設定資源匯出至組態檔。搭配 --packageId 使用時,導出指定套件標識符的 WinGetPackage 資源。與 --module 和 --resource 搭配使用時,取得資源的設定,並將它匯出至組態檔。如果輸出組態檔已存在,會附加導出的設定資源。 + {Locked="WinGetPackage,--packageId,--module, --resource"} + + + 將設定資源匯出至設定檔。 + + + 要匯出之資源的模組。 + + + 要匯出的套件識別碼。 + + + 要匯出的設定資源。 + + + 設定單位無法取得其屬性。 + + + 無法匯出設定。 + + + 設定 {0} + {Locked="{0}"} + + + 安裝 {0} + {Locked="{0}"} + + + 組態檔中存在的部分數據已針對此輸出截斷;檢查檔案內容以取得完整內容。 + + + <此值已被截斷; 檢查檔案內容以取得完整的文字> + Keep some form of separator like the "<>" around the text so that it stands out from the preceding text. + + + 顯示已套用至系統之設定的高層級詳細數據。此數據可與 `configure` 命令搭配使用,以取得更多詳細數據。 + {Locked="`configure`"} + + + 顯示設定歷程記錄 + + + 歷程記錄中沒有設定。 + + + 從歷程記錄選取項目 + + + 找不到符合所提供數據的單一設定。提供明確符合所需設定的完整名稱或標識碼的一部分。 + + + 從歷程記錄中移除項目 + + + 首次套用 + Column header for date values indicating when a configuration was first applied to the system. + + + 識別碼 + + + 名稱 + + + 來源 + + + 路徑 + + + 找不到指定的設定。 + \ No newline at end of file diff --git a/doc/Settings.md b/doc/Settings.md index ae654a2aaf..5c24f4feff 100644 --- a/doc/Settings.md +++ b/doc/Settings.md @@ -97,6 +97,16 @@ The 'skipDependencies' behavior affects whether dependencies are installed for a "installBehavior": { "skipDependencies": true }, +``` + +### Archive Extraction Method +The 'archiveExtractionMethod' behavior affects how installer archives are extracted. Currently there are two supported values: `Tar` or `ShellApi`. +`Tar` indicates that the archive should be extracted using the tar executable ('tar.exe') while `shellApi` indicates using the Windows Shell API. Defaults to `shellApi` if value is not set or is invalid. + +```json + "installBehavior": { + "archiveExtractionMethod": "tar" | "shellApi" + }, ``` ### Preferences and Requirements @@ -313,17 +323,6 @@ Currently, this means that properly attributed configuration units (and only tho }, ``` -### storeDownload - -This feature enables packages to be downloaded from the Microsoft Store. -You can enable the feature as shown below. - -```json - "experimentalFeatures": { - "storeDownload": true - }, -``` - ### configureExport This feature enables exporting a configuration file. diff --git a/schemas/JSON/settings/settings.schema.0.2.json b/schemas/JSON/settings/settings.schema.0.2.json index 4271121140..ca65700d61 100644 --- a/schemas/JSON/settings/settings.schema.0.2.json +++ b/schemas/JSON/settings/settings.schema.0.2.json @@ -276,11 +276,6 @@ "type": "boolean", "default": false }, - "storeDownload": { - "description": "Enable support for downloading packages from the Microsoft Store", - "type": "boolean", - "default": false - }, "configureExport": { "description": "Enable support for the configure export command", "type": "boolean", diff --git a/src/AppInstallerCLICore/Commands/RepairCommand.cpp b/src/AppInstallerCLICore/Commands/RepairCommand.cpp index 210dabb584..39543f527d 100644 --- a/src/AppInstallerCLICore/Commands/RepairCommand.cpp +++ b/src/AppInstallerCLICore/Commands/RepairCommand.cpp @@ -104,11 +104,7 @@ namespace AppInstaller::CLI Workflow::GetManifestFromArg << Workflow::ReportManifestIdentity << Workflow::SearchSourceUsingManifest << - Workflow::EnsureOneMatchFromSearchResult(OperationType::Repair) << - Workflow::GetInstalledPackageVersion << - Workflow::SelectInstaller << - Workflow::EnsureApplicableInstaller << - Workflow::RepairSinglePackage; + Workflow::EnsureOneMatchFromSearchResult(OperationType::Repair); } else { @@ -116,10 +112,12 @@ namespace AppInstaller::CLI Workflow::SearchSourceForSingle << Workflow::HandleSearchResultFailures << Workflow::EnsureOneMatchFromSearchResult(OperationType::Repair) << - Workflow::ReportPackageIdentity << - Workflow::GetInstalledPackageVersion << - Workflow::SelectApplicablePackageVersion << - Workflow::RepairSinglePackage; + Workflow::ReportPackageIdentity; } + + context << + Workflow::GetInstalledPackageVersion << + Workflow::SelectApplicableInstallerIfNecessary << + Workflow::RepairSinglePackage; } } diff --git a/src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp b/src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp index 069598e45b..fe5c3a5890 100644 --- a/src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp @@ -2,9 +2,10 @@ // Licensed under the MIT License. #include "pch.h" #include "ArchiveFlow.h" -#include "PortableFlow.h" +#include "PortableFlow.h" +#include "ShellExecuteInstallerHandler.h" #include -#include +#include #include using namespace AppInstaller::Manifest; @@ -42,30 +43,38 @@ namespace AppInstaller::CLI::Workflow } } } - } - - void ExtractFilesFromArchive(Execution::Context& context) - { + } + + void ExtractFilesFromArchive(Execution::Context& context) + { const auto& installerPath = context.Get(); std::filesystem::path destinationFolder = installerPath.parent_path() / s_Extracted; - std::filesystem::create_directory(destinationFolder); - + std::filesystem::create_directory(destinationFolder); + AICLI_LOG(CLI, Info, << "Extracting archive to: " << destinationFolder); - context.Reporter.Info() << Resource::String::ExtractingArchive << std::endl; - HRESULT result = AppInstaller::Archive::TryExtractArchive(installerPath, destinationFolder); - - if (SUCCEEDED(result)) - { - AICLI_LOG(CLI, Info, << "Successfully extracted archive"); - context.Reporter.Info() << Resource::String::ExtractArchiveSucceeded << std::endl; - } - else - { - AICLI_LOG(CLI, Info, << "Failed to extract archive with code " << result); - context.Reporter.Error() << Resource::String::ExtractArchiveFailed << std::endl; - AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_EXTRACT_ARCHIVE_FAILED); - } - } + context.Reporter.Info() << Resource::String::ExtractingArchive << std::endl; + + if (Settings::User().Get() == Archive::ExtractionMethod::Tar) + { + context << ShellExecuteExtractArchive(installerPath, destinationFolder); + } + else + { + HRESULT result = AppInstaller::Archive::TryExtractArchive(installerPath, destinationFolder); + + if (SUCCEEDED(result)) + { + AICLI_LOG(CLI, Info, << "Successfully extracted archive"); + context.Reporter.Info() << Resource::String::ExtractArchiveSucceeded << std::endl; + } + else + { + AICLI_LOG(CLI, Info, << "Failed to extract archive with code " << result); + context.Reporter.Error() << Resource::String::ExtractArchiveFailed << std::endl; + AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_EXTRACT_ARCHIVE_FAILED); + } + } + } void VerifyAndSetNestedInstaller(Execution::Context& context) { @@ -137,4 +146,4 @@ namespace AppInstaller::CLI::Workflow } } } -} \ No newline at end of file +} diff --git a/src/AppInstallerCLICore/Workflows/ArchiveFlow.h b/src/AppInstallerCLICore/Workflows/ArchiveFlow.h index 6fa3a09169..0bc8209d8f 100644 --- a/src/AppInstallerCLICore/Workflows/ArchiveFlow.h +++ b/src/AppInstallerCLICore/Workflows/ArchiveFlow.h @@ -10,12 +10,12 @@ namespace AppInstaller::CLI::Workflow // Inputs: InstallerPath // Outputs: None void ScanArchiveFromLocalManifest(Execution::Context& context); - + // Extracts the files from an archive // Required Args: None // Inputs: InstallerPath - // Outputs: None - void ExtractFilesFromArchive(Execution::Context& context); + // Outputs: None + void ExtractFilesFromArchive(Execution::Context& context); // Verifies that the NestedInstaller exists and sets the InstallerPath // Required Args: None @@ -28,4 +28,4 @@ namespace AppInstaller::CLI::Workflow // Inputs: Installer, InstallerPath // Outputs: None void EnsureValidNestedInstallerMetadataForArchiveInstall(Execution::Context& context); -} \ No newline at end of file +} diff --git a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp index 6b8cee0c1a..0ffcaa6794 100644 --- a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp @@ -244,7 +244,6 @@ namespace AppInstaller::CLI::Workflow if (installerDownloadOnly) { context << - EnsureFeatureEnabled(Settings::ExperimentalFeature::Feature::StoreDownload) << MSStoreDownload << ExportManifest; } diff --git a/src/AppInstallerCLICore/Workflows/RepairFlow.cpp b/src/AppInstallerCLICore/Workflows/RepairFlow.cpp index 44e05419d5..4bfc1d4a23 100644 --- a/src/AppInstallerCLICore/Workflows/RepairFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/RepairFlow.cpp @@ -19,16 +19,14 @@ using namespace AppInstaller::Manifest; using namespace AppInstaller::Msix; using namespace AppInstaller::Repository; +using namespace AppInstaller::CLI::Execution; namespace AppInstaller::CLI::Workflow { // Internal implementation details namespace { - // Sets the uninstall string in the context. - // RequiredArgs: - // Inputs:InstalledPackageVersion - // Outputs:SilentUninstallString, UninstallString + void SetUninstallStringInContext(Execution::Context& context) { const auto& installedPackageVersion = context.Get(); @@ -56,10 +54,6 @@ namespace AppInstaller::CLI::Workflow context.Add(uninstallCommandItr->second); } - // Sets the modify path in the context. - // RequiredArgs:None - // Inputs:InstalledPackageVersion - // Outputs:ModifyPath void SetModifyPathInContext(Execution::Context& context) { const auto& installedPackageVersion = context.Get(); @@ -76,10 +70,6 @@ namespace AppInstaller::CLI::Workflow context.Add(modifyPathItr->second); } - // Sets the product codes in the context. - // RequiredArgs:None - // Inputs:InstalledPackageVersion - // Outputs:ProductCodes void SetProductCodesInContext(Execution::Context& context) { const auto& installedPackageVersion = context.Get(); @@ -94,10 +84,6 @@ namespace AppInstaller::CLI::Workflow context.Add(productCodes); } - // Sets the package family names in the context. - // RequiredArgs:None - // Inputs:InstalledPackageVersion - // Outputs:PackageFamilyNames void SetPackageFamilyNamesInContext(Execution::Context& context) { const auto& installedPackageVersion = context.Get(); @@ -112,10 +98,13 @@ namespace AppInstaller::CLI::Workflow context.Add(packageFamilyNames); } - // The function performs a preliminary check on the installed package by reading its ARP registry flags for NoModify and NoRepair to confirm if the repair operation is applicable. - // RequiredArgs:None - // Inputs:InstalledPackageVersion, NoModify ?, NoRepair ? - // Outputs:None + InstallerTypeEnum GetInstalledType(Execution::Context& context) + { + const auto& installedPackage = context.Get(); + std::string installedType = installedPackage->GetMetadata()[PackageVersionMetadata::InstalledType]; + return ConvertToInstallerTypeEnum(installedType); + } + void ApplicabilityCheckForInstalledPackage(Execution::Context& context) { // Installed Package repair applicability check @@ -145,12 +134,14 @@ namespace AppInstaller::CLI::Workflow } } - // This function performs a preliminary check on the available matching package by reading its manifest entries for repair behavior to determine the type of repair operation and repair switch are applicable - // RequiredArgs:None - // Inputs:InstallerType, RepairBehavior - // Outputs:None void ApplicabilityCheckForAvailablePackage(Execution::Context& context) { + // Skip the Available Package applicability check for MSI and MSIX repair as they aren't needed. + if (!context.Contains(Execution::Data::Installer)) + { + return; + } + // Selected Installer repair applicability check auto installerType = context.Get()->EffectiveInstallerType(); auto repairBehavior = context.Get()->RepairBehavior; @@ -170,10 +161,34 @@ namespace AppInstaller::CLI::Workflow } } - // Generate the repair string based on the repair behavior and installer type. - // RequiredArgs:None - // Inputs:BaseInstallerType, RepairBehavior, ModifyPath?, UninstallString?, InstallerArgs - // Outputs:RepairString + void HandleModifyRepairBehavior(Execution::Context& context, std::string& repairCommand) + { + SetModifyPathInContext(context); + repairCommand += context.Get(); + } + + void HandleInstallerRepairBehavior(Execution::Context& context, InstallerTypeEnum installerType) + { + context << + ShowInstallationDisclaimer << + ShowPromptsForSinglePackage(/* ensureAcceptance */ true) << + DownloadInstaller; + + if (installerType == InstallerTypeEnum::Zip) + { + context << + ScanArchiveFromLocalManifest << + ExtractFilesFromArchive << + VerifyAndSetNestedInstaller; + } + } + + void HandleUninstallerRepairBehavior(Execution::Context& context, std::string& repairCommand) + { + SetUninstallStringInContext(context); + repairCommand += context.Get(); + } + void GenerateRepairString(Execution::Context& context) { const auto& installer = context.Get(); @@ -185,35 +200,14 @@ namespace AppInstaller::CLI::Workflow switch (repairBehavior) { case RepairBehaviorEnum::Modify: - { - SetModifyPathInContext(context); - repairCommand.append(context.Get()); - } - break; + HandleModifyRepairBehavior(context, repairCommand); + break; case RepairBehaviorEnum::Installer: - { - // [NOTE:] We will ShellExecuteInstall for this scenario which uses installer path directly.so no need for repair command generation. - // We prepare installer download and archive extraction here. - context << - ShowInstallationDisclaimer << - ShowPromptsForSinglePackage(/* ensureAcceptance */ true) << - DownloadInstaller; - - if (installerType == InstallerTypeEnum::Zip) - { - context << - ScanArchiveFromLocalManifest << - ExtractFilesFromArchive << - VerifyAndSetNestedInstaller; - } - } - break; + HandleInstallerRepairBehavior(context, installerType); + break; case RepairBehaviorEnum::Uninstaller: - { - SetUninstallStringInContext(context); - repairCommand.append(context.Get()); - } - break; + HandleUninstallerRepairBehavior(context, repairCommand); + break; case RepairBehaviorEnum::Unknown: default: context.Reporter.Error() << Resource::String::NoRepairInfoFound << std::endl; @@ -223,41 +217,81 @@ namespace AppInstaller::CLI::Workflow context << GetInstallerArgs; - // Following is not applicable for RepairBehaviorEnum::Installer, as we can call ShellExecuteInstall directly with repair argument. - if (repairBehavior != RepairBehaviorEnum::Installer) + // If the repair behavior is set to 'Installer', we can proceed with the repair command as is. + // For repair behaviors other than 'Installer', subsequent steps will be necessary to prepare the repair command. + if (repairBehavior == RepairBehaviorEnum::Installer) + { + return; + } + + if (repairCommand.empty()) + { + context.Reporter.Error() << Resource::String::NoRepairInfoFound << std::endl; + AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_NO_REPAIR_INFO_FOUND); + } + + repairCommand += " "; + repairCommand += context.Get(); + context.Add(repairCommand); + } + + bool IsInstallerMappingRequired(Execution::Context& context) + { + InstallerTypeEnum installerTypeEnum = GetInstalledType(context); + + switch (installerTypeEnum) { - if (repairCommand.empty()) + case InstallerTypeEnum::Msi: + return false; + case InstallerTypeEnum::Msix: + // For MSIX packages that are from the Microsoft Store, selecting an installer is required. + if (context.Contains(Execution::Data::Package)) { - context.Reporter.Error() << Resource::String::NoRepairInfoFound << std::endl; - AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_NO_REPAIR_INFO_FOUND); + auto availablePackages = context.Get()->GetAvailable(); + + if (availablePackages.size() == 1 && availablePackages[0]->GetSource() == WellKnownSource::MicrosoftStore) + { + return true; + } } - repairCommand.append(" "); - repairCommand.append(context.Get()); - context.Add(repairCommand); + // For MSIX packages that are not from the Microsoft Store, selecting an installer is not required. + return false; + default: + return true; } } - } - void RunRepairForRepairBehaviorBasedInstaller(Execution::Context& context) - { - const auto& installer = context.Get(); - auto repairBehavior = installer->RepairBehavior; - - if (repairBehavior == RepairBehaviorEnum::Modify || repairBehavior == RepairBehaviorEnum::Uninstaller) + void HandleModifyOrUninstallerRepair(Execution::Context& context, RepairBehaviorEnum repairBehavior) { context << ShellExecuteRepairImpl << ReportRepairResult(RepairBehaviorToString(repairBehavior), APPINSTALLER_CLI_ERROR_EXEC_REPAIR_FAILED); } - else if (repairBehavior == RepairBehaviorEnum::Installer) + + void HandleInstallerRepair(Execution::Context& context, RepairBehaviorEnum repairBehavior) { context << ShellExecuteInstallImpl << ReportInstallerResult(RepairBehaviorToString(repairBehavior), APPINSTALLER_CLI_ERROR_EXEC_REPAIR_FAILED); } - else + } + + void RunRepairForRepairBehaviorBasedInstaller(Execution::Context& context) + { + const auto& installer = context.Get(); + auto repairBehavior = installer->RepairBehavior; + + switch (repairBehavior) { + case RepairBehaviorEnum::Modify: + case RepairBehaviorEnum::Uninstaller: + HandleModifyOrUninstallerRepair(context, repairBehavior); + break; + case RepairBehaviorEnum::Installer: + HandleInstallerRepair(context, repairBehavior); + break; + default: context.Reporter.Error() << Resource::String::NoRepairInfoFound << std::endl; AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_NO_REPAIR_INFO_FOUND); } @@ -279,11 +313,7 @@ namespace AppInstaller::CLI::Workflow void ExecuteRepair(Execution::Context& context) { - // [TODO:] At present, the repair flow necessitates a mapped available installer. - // However, future refactoring should allow for msix/msi repair without the need for one. - - const auto& installer = context.Get(); - InstallerTypeEnum installerTypeEnum = installer->EffectiveInstallerType(); + InstallerTypeEnum installerTypeEnum = context.Contains(Execution::Data::Installer) ? context.Get()->EffectiveInstallerType() : GetInstalledType(context); Synchronization::CrossProcessInstallLock lock; @@ -303,8 +333,8 @@ namespace AppInstaller::CLI::Workflow switch (installerTypeEnum) { - case InstallerTypeEnum::Burn: case InstallerTypeEnum::Exe: + case InstallerTypeEnum::Burn: case InstallerTypeEnum::Inno: case InstallerTypeEnum::Nullsoft: { @@ -340,11 +370,11 @@ namespace AppInstaller::CLI::Workflow void GetRepairInfo(Execution::Context& context) { - const auto& installer = context.Get(); - InstallerTypeEnum installerTypeEnum = installer->EffectiveInstallerType(); + InstallerTypeEnum installerTypeEnum = context.Contains(Execution::Data::Installer) ? context.Get()->BaseInstallerType : GetInstalledType(context); switch (installerTypeEnum) { + // Exe based installers, for installed package all gets mapped to exe extension. case InstallerTypeEnum::Burn: case InstallerTypeEnum::Exe: case InstallerTypeEnum::Inno: @@ -354,6 +384,7 @@ namespace AppInstaller::CLI::Workflow GenerateRepairString; } break; + // MSI based installers, for installed package all gets mapped to msi extension. case InstallerTypeEnum::Msi: case InstallerTypeEnum::Wix: { @@ -361,6 +392,7 @@ namespace AppInstaller::CLI::Workflow SetProductCodesInContext; } break; + // MSIX based installers, msix. case InstallerTypeEnum::Msix: { context << @@ -432,6 +464,12 @@ namespace AppInstaller::CLI::Workflow void SelectApplicablePackageVersion(Execution::Context& context) { + // If the repair flow is initiated with manifest, then we don't need to select the applicable package version. + if (context.Args.Contains(Args::Type::Manifest)) + { + return; + } + const auto& installedPackage = context.Get(); Utility::Version installedVersion = Utility::Version(installedPackage->GetProperty(PackageVersionProperty::Version)); @@ -459,9 +497,20 @@ namespace AppInstaller::CLI::Workflow context << GetManifestWithVersionFromPackage( requestedVersion, - context.Args.GetArg(Execution::Args::Type::Channel), false) << - SelectInstaller << - EnsureApplicableInstaller; + context.Args.GetArg(Execution::Args::Type::Channel), false); + } + + void SelectApplicableInstallerIfNecessary(Execution::Context& context) + { + // For MSI installers, the platform provides built-in support for repair via msiexec, hence no need to select an installer. + // Similarly, for MSIX packages that are not from the Microsoft Store, selecting an installer is not required. + if (IsInstallerMappingRequired(context)) + { + context << + SelectApplicablePackageVersion << + SelectInstaller << + EnsureApplicableInstaller; + } } void ReportRepairResult::operator()(Execution::Context& context) const @@ -470,7 +519,9 @@ namespace AppInstaller::CLI::Workflow if (repairResult != 0) { - const auto& repairPackage = context.Get(); + auto& repairPackage = context.Contains(Execution::Data::PackageVersion) ? + context.Get() : + context.Get(); Logging::Telemetry().LogRepairFailure( repairPackage->GetProperty(PackageVersionProperty::Id), @@ -505,4 +556,4 @@ namespace AppInstaller::CLI::Workflow context.Reporter.Info() << Resource::String::RepairFlowRepairSuccess << std::endl; } } -} \ No newline at end of file +} diff --git a/src/AppInstallerCLICore/Workflows/RepairFlow.h b/src/AppInstallerCLICore/Workflows/RepairFlow.h index 6af77249df..5c15d9f666 100644 --- a/src/AppInstallerCLICore/Workflows/RepairFlow.h +++ b/src/AppInstallerCLICore/Workflows/RepairFlow.h @@ -35,7 +35,7 @@ namespace AppInstaller::CLI::Workflow // Outputs:RepairString?, ProductCodes?, PackageFamilyNames? void GetRepairInfo(Execution::Context& context); - // Perform the repair operation for the MSIX package. + // Perform the repair operation for the MSIX NonStore package. // RequiredArgs:None // Inputs:PackageFamilyNames , InstallScope? // Outputs:None @@ -47,6 +47,13 @@ namespace AppInstaller::CLI::Workflow // Outputs:Manifest, PackageVersion, Installer void SelectApplicablePackageVersion(Execution::Context& context); + /// + /// Select the applicable installer for the installed package if necessary. + // RequiredArgs:None + // Inputs: Package,InstalledPackageVersion, AvailablePackageVersions + // Outputs:Manifest, PackageVersion, Installer + void SelectApplicableInstallerIfNecessary(Execution::Context& context); + // Perform the repair operation for the single package. // RequiredArgs:None // Inputs: SearchResult, InstalledPackage, ApplicableInstaller diff --git a/src/AppInstallerCLICore/Workflows/ShellExecuteInstallerHandler.cpp b/src/AppInstallerCLICore/Workflows/ShellExecuteInstallerHandler.cpp index a25ca30cd0..781984a47c 100644 --- a/src/AppInstallerCLICore/Workflows/ShellExecuteInstallerHandler.cpp +++ b/src/AppInstallerCLICore/Workflows/ShellExecuteInstallerHandler.cpp @@ -538,4 +538,55 @@ namespace AppInstaller::CLI::Workflow context.Add(enableFeatureResult.value()); } } -} \ No newline at end of file + +#ifndef AICLI_DISABLE_TEST_HOOKS + std::optional s_ExtractArchiveWithTarResult_Override{}; + + void TestHook_SetExtractArchiveWithTarResult_Override(std::optional&& result) + { + s_ExtractArchiveWithTarResult_Override = std::move(result); + } +#endif + + void ShellExecuteExtractArchive::operator()(Execution::Context& context) const + { + auto tarExecPath = AppInstaller::Filesystem::GetExpandedPath("%windir%\\system32\\tar.exe"); + + std::string args = "-xf \"" + m_archivePath.u8string() + "\" -C \"" + m_destPath.u8string() + "\""; + + std::optional extractArchiveResult; +#ifndef AICLI_DISABLE_TEST_HOOKS + if (s_ExtractArchiveWithTarResult_Override) + { + extractArchiveResult = *s_ExtractArchiveWithTarResult_Override; + } + else +#endif + { + extractArchiveResult = context.Reporter.ExecuteWithProgress( + std::bind(InvokeShellExecuteEx, + tarExecPath, + args, + false, + SW_HIDE, + std::placeholders::_1)); + } + + if (!extractArchiveResult) + { + AICLI_TERMINATE_CONTEXT(E_ABORT); + } + + if (extractArchiveResult.value() == ERROR_SUCCESS) + { + AICLI_LOG(CLI, Info, << "Successfully extracted archive"); + context.Reporter.Info() << Resource::String::ExtractArchiveSucceeded << std::endl; + } + else + { + AICLI_LOG(CLI, Info, << "Failed to extract archive with exit code " << extractArchiveResult.value()); + context.Reporter.Error() << Resource::String::ExtractArchiveFailed << std::endl; + AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_EXTRACT_ARCHIVE_FAILED); + } + } +} diff --git a/src/AppInstallerCLICore/Workflows/ShellExecuteInstallerHandler.h b/src/AppInstallerCLICore/Workflows/ShellExecuteInstallerHandler.h index 87fac6db18..8dc3cfb70e 100644 --- a/src/AppInstallerCLICore/Workflows/ShellExecuteInstallerHandler.h +++ b/src/AppInstallerCLICore/Workflows/ShellExecuteInstallerHandler.h @@ -60,4 +60,19 @@ namespace AppInstaller::CLI::Workflow private: std::string_view m_featureName; }; -} \ No newline at end of file + + // Extracts the installer archive using the tar executable. + // Required Args: None + // Inputs: InstallerPath + // Outputs: None + struct ShellExecuteExtractArchive : public WorkflowTask + { + ShellExecuteExtractArchive(const std::filesystem::path& archivePath, const std::filesystem::path& destPath) : WorkflowTask("ShellExecuteExtractArchive"), m_archivePath(archivePath), m_destPath(destPath) {} + + void operator()(Execution::Context& context) const override; + + private: + std::filesystem::path m_archivePath; + std::filesystem::path m_destPath; + }; +} diff --git a/src/AppInstallerCLIE2ETests/Constants.cs b/src/AppInstallerCLIE2ETests/Constants.cs index 5aa1c34efe..378ce3b3af 100644 --- a/src/AppInstallerCLIE2ETests/Constants.cs +++ b/src/AppInstallerCLIE2ETests/Constants.cs @@ -25,6 +25,7 @@ public class Constants public const string LocalServerCertPathParameter = "LocalServerCertPath"; public const string ExeInstallerPathParameter = "ExeTestInstallerPath"; public const string MsiInstallerPathParameter = "MsiTestInstallerPath"; + public const string MsiInstallerV2PathParameter = "MsiTestInstallerV2Path"; public const string MsixInstallerPathParameter = "MsixTestInstallerPath"; public const string PackageCertificatePathParameter = "PackageCertificatePath"; public const string PowerShellModulePathParameter = "PowerShellModulePath"; @@ -59,6 +60,7 @@ public class Constants public const string ZipInstaller = "AppInstallerTestZipInstaller"; public const string ExeInstallerFileName = "AppInstallerTestExeInstaller.exe"; public const string MsiInstallerFileName = "AppInstallerTestMsiInstaller.msi"; + public const string MsiInstallerV2FileName = "AppInstallerTestMsiInstallerV2.msi"; public const string MsixInstallerFileName = "AppInstallerTestMsixInstaller.msix"; public const string ZipInstallerFileName = "AppInstallerTestZipInstaller.zip"; public const string IndexPackage = "source.msix"; @@ -92,6 +94,7 @@ public class Constants public const string TestExeInstalledFileName = "TestExeInstalled.txt"; public const string TestExeUninstallerFileName = "UninstallTestExe.bat"; public const string TestExeUninstalledFileName = "TestExeUninstalled.txt"; + public const string TestExeRepairCompletedFileName = "TestExeRepairCompleted.txt"; // PowerShell Cmdlets public const string FindCmdlet = "Find-WinGetPackage"; @@ -119,6 +122,7 @@ public class Constants public const string PathSubKey_Machine = @"SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; // User settings + public const string ArchiveExtractionMethod = "archiveExtractionMethod"; public const string PortablePackageUserRoot = "portablePackageUserRoot"; public const string PortablePackageMachineRoot = "portablePackageMachineRoot"; public const string InstallBehaviorScope = "scope"; @@ -264,6 +268,10 @@ public class ErrorCode public const int ERROR_INVALID_RESUME_STATE = unchecked((int)0x8A150070); public const int ERROR_CANNOT_OPEN_CHECKPOINT_INDEX = unchecked((int)0x8A150071); + public const int ERROR_NO_REPAIR_INFO_FOUND = unchecked((int)0x8A150079); + public const int ERROR_REPAIR_NOT_SUPPORTED = unchecked((int)0x8A15007C); + public const int ERROR_ADMIN_CONTEXT_REPAIR_PROHIBITED = unchecked((int)0x8A15007D); + public const int ERROR_INSTALL_PACKAGE_IN_USE = unchecked((int)0x8A150101); public const int ERROR_INSTALL_INSTALL_IN_PROGRESS = unchecked((int)0x8A150102); public const int ERROR_INSTALL_FILE_IN_USE = unchecked((int)0x8A150103); diff --git a/src/AppInstallerCLIE2ETests/Helpers/TestCommon.cs b/src/AppInstallerCLIE2ETests/Helpers/TestCommon.cs index ddad1a1d2a..9d60109edc 100644 --- a/src/AppInstallerCLIE2ETests/Helpers/TestCommon.cs +++ b/src/AppInstallerCLIE2ETests/Helpers/TestCommon.cs @@ -16,6 +16,7 @@ namespace AppInstallerCLIE2ETests.Helpers using System.Security.Principal; using System.Text; using System.Threading; + using System.Web; using AppInstallerCLIE2ETests; using AppInstallerCLIE2ETests.PowerShell; using Microsoft.Management.Deployment; @@ -470,6 +471,32 @@ public static bool VerifyTestExeInstalled(string installDir, string expectedCont return verifyInstallSuccess; } + /// + /// Verifies if the repair of the test executable was successful. + /// + /// The directory where the test executable is installed. + /// The expected content in the test executable file. This is optional. + /// Returns true if the repair was successful, false otherwise. + public static bool VerifyTestExeRepairSuccessful(string installDir, string expectedContent = null) + { + bool verifyRepairSuccess = true; + + if (!File.Exists(Path.Combine(installDir, Constants.TestExeRepairCompletedFileName))) + { + TestContext.Out.WriteLine($"{Constants.TestExeRepairCompletedFileName} not found at {installDir}"); + verifyRepairSuccess = false; + } + + if (verifyRepairSuccess && !string.IsNullOrEmpty(expectedContent)) + { + string content = File.ReadAllText(Path.Combine(installDir, Constants.TestExeRepairCompletedFileName)); + TestContext.Out.WriteLine($"TestExeRepairCompleted.txt content: {content}"); + verifyRepairSuccess = content.Contains(expectedContent); + } + + return verifyRepairSuccess; + } + /// /// Verify installer and manifest downloaded correctly and cleanup. /// @@ -543,6 +570,35 @@ public static bool VerifyInstallerDownload( return downloadResult; } + /// + /// Best effort test exe cleanup. + /// + /// Install directory. + public static void BestEffortTestExeCleanup(string installDir) + { + var uninstallerPath = Path.Combine(installDir, Constants.TestExeUninstallerFileName); + if (File.Exists(uninstallerPath)) + { + RunCommand(Path.Combine(installDir, Constants.TestExeUninstallerFileName)); + } + } + + /// + /// Best effort test exe cleanup and install directory cleanup. + /// + /// Install directory. + public static void CleanupTestExeAndDirectory(string installDir) + { + // Always try clean up and ignore clean up failure + BestEffortTestExeCleanup(installDir); + + // Delete the install directory to reclaim disk space + if (Directory.Exists(installDir)) + { + Directory.Delete(installDir, true); + } + } + /// /// Verify exe installer correctly and then uninstall it. /// @@ -554,15 +610,25 @@ public static bool VerifyTestExeInstalledAndCleanup(string installDir, string ex bool verifyInstallSuccess = VerifyTestExeInstalled(installDir, expectedContent); // Always try clean up and ignore clean up failure - var uninstallerPath = Path.Combine(installDir, Constants.TestExeUninstallerFileName); - if (File.Exists(uninstallerPath)) - { - RunCommand(Path.Combine(installDir, Constants.TestExeUninstallerFileName)); - } + BestEffortTestExeCleanup(installDir); return verifyInstallSuccess; } + /// + /// Verify exe repair completed and cleanup. + /// + /// Install directory. + /// Optional expected context. + /// True if success. + public static bool VerifyTestExeRepairCompletedAndCleanup(string installDir, string expectedContent = null) + { + bool verifyRepairSuccess = VerifyTestExeRepairSuccessful(installDir, expectedContent); + CleanupTestExeAndDirectory(installDir); + + return verifyRepairSuccess; + } + /// /// Verify msi installed correctly. /// @@ -912,6 +978,61 @@ public static string GetExpectedModulePath(TestModuleLocation location) } } + /// + /// Copy the installer file to the ARP InstallSource directory. + /// + /// Test installer to be copied. + /// Installer Product. + /// is WoW6432Node to use. + /// Returns the installer source directory if the file operation is successful, otherwise returns an empty string. + public static string CopyInstallerFileToARPInstallSourceDirectory(string installerFilePath, string productCode, bool useWoW6432Node = false) + { + if (string.IsNullOrEmpty(installerFilePath)) + { + new ArgumentNullException(nameof(installerFilePath)); + } + + if (!File.Exists(installerFilePath)) + { + new FileNotFoundException(installerFilePath); + } + + string outputDirectory = string.Empty; + + // Define the registry paths for both x64 and x86 + string registryPath = useWoW6432Node + ? $@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{productCode}" + : $@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{productCode}"; + + // Open the registry key where the uninstall information is stored + using (RegistryKey key = Registry.LocalMachine.OpenSubKey(registryPath)) + { + if (key != null) + { + // Read the InstallSource value + string arpInstallSourceDirectory = key.GetValue("InstallSource") as string; + + if (!string.IsNullOrEmpty(arpInstallSourceDirectory)) + { + // Copy the MSI installer to the InstallSource directory + string installerFileName = Path.GetFileName(installerFilePath); + string installerDestinationPath = Path.Combine(arpInstallSourceDirectory, installerFileName); + + if (!Directory.Exists(arpInstallSourceDirectory)) + { + Directory.CreateDirectory(arpInstallSourceDirectory); + } + + File.Copy(installerFilePath, installerDestinationPath, true); + + outputDirectory = arpInstallSourceDirectory; + } + } + } + + return outputDirectory; + } + /// /// Run winget command via direct process. /// diff --git a/src/AppInstallerCLIE2ETests/Helpers/TestIndex.cs b/src/AppInstallerCLIE2ETests/Helpers/TestIndex.cs index 91931403f8..2728661e86 100644 --- a/src/AppInstallerCLIE2ETests/Helpers/TestIndex.cs +++ b/src/AppInstallerCLIE2ETests/Helpers/TestIndex.cs @@ -1,4 +1,4 @@ -// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. Licensed under the MIT License. // @@ -22,6 +22,7 @@ static TestIndex() // Expected path for the installers. TestIndex.ExeInstaller = Path.Combine(TestSetup.Parameters.StaticFileRootPath, Constants.ExeInstaller, Constants.ExeInstallerFileName); TestIndex.MsiInstaller = Path.Combine(TestSetup.Parameters.StaticFileRootPath, Constants.MsiInstaller, Constants.MsiInstallerFileName); + TestIndex.MsiInstallerV2 = Path.Combine(TestSetup.Parameters.StaticFileRootPath, Constants.MsiInstaller, Constants.MsiInstallerV2FileName); TestIndex.MsixInstaller = Path.Combine(TestSetup.Parameters.StaticFileRootPath, Constants.MsixInstaller, Constants.MsixInstallerFileName); TestIndex.ZipInstaller = Path.Combine(TestSetup.Parameters.StaticFileRootPath, Constants.ZipInstaller, Constants.ZipInstallerFileName); } @@ -36,6 +37,11 @@ static TestIndex() /// public static string MsiInstaller { get; private set; } + /// + /// Gets the signed msi installerV2 path used by the manifests in the E2E test. + /// + public static string MsiInstallerV2 { get; private set; } + /// /// Gets the signed msix installer path used by the manifests in the E2E test. /// @@ -73,6 +79,16 @@ public static void GenerateE2ESource() throw new FileNotFoundException(testParams.MsiInstallerPath); } + if (string.IsNullOrEmpty(testParams.MsiInstallerV2Path)) + { + throw new ArgumentNullException($"{Constants.MsiInstallerV2PathParameter} is required"); + } + + if (!File.Exists(testParams.MsiInstallerV2Path)) + { + throw new FileNotFoundException(testParams.MsiInstallerV2Path); + } + if (string.IsNullOrEmpty(testParams.MsixInstallerPath)) { throw new ArgumentNullException($"{Constants.MsixInstallerPathParameter} is required"); @@ -118,6 +134,13 @@ public static void GenerateE2ESource() HashToken = "", }, new LocalInstaller + { + Type = InstallerType.Msi, + Name = Path.Combine(Constants.MsiInstaller, Constants.MsiInstallerV2FileName), + Input = testParams.MsiInstallerPath, + HashToken = "", + }, + new LocalInstaller { Type = InstallerType.Msix, Name = Path.Combine(Constants.MsixInstaller, Constants.MsixInstallerFileName), diff --git a/src/AppInstallerCLIE2ETests/Helpers/TestSetup.cs b/src/AppInstallerCLIE2ETests/Helpers/TestSetup.cs index 2e81098f8e..b681fc710f 100644 --- a/src/AppInstallerCLIE2ETests/Helpers/TestSetup.cs +++ b/src/AppInstallerCLIE2ETests/Helpers/TestSetup.cs @@ -43,6 +43,7 @@ private TestSetup() this.ExeInstallerPath = this.InitializeFileParam(Constants.ExeInstallerPathParameter); this.MsiInstallerPath = this.InitializeFileParam(Constants.MsiInstallerPathParameter); this.MsixInstallerPath = this.InitializeFileParam(Constants.MsixInstallerPathParameter); + this.MsiInstallerV2Path = this.InitializeFileParam(Constants.MsiInstallerV2PathParameter); this.ForcedExperimentalFeatures = this.InitializeStringArrayParam(Constants.ForcedExperimentalFeaturesParameter); } @@ -103,6 +104,11 @@ public static TestSetup Parameters /// public string MsiInstallerPath { get; } + /// + /// Gets the msi installer V2 path. + /// + public string MsiInstallerV2Path { get; } + /// /// Gets the msix installer path. /// diff --git a/src/AppInstallerCLIE2ETests/InstallCommand.cs b/src/AppInstallerCLIE2ETests/InstallCommand.cs index be81f220d0..54efdef1c8 100644 --- a/src/AppInstallerCLIE2ETests/InstallCommand.cs +++ b/src/AppInstallerCLIE2ETests/InstallCommand.cs @@ -552,6 +552,21 @@ public void InstallZipWithMsix() Assert.True(TestCommon.VerifyTestMsixInstalledAndCleanup()); } + /// + /// Test install zip exe by extracting with tar. + /// + [Test] + public void InstallZip_ExtractWithTar() + { + WinGetSettingsHelper.ConfigureInstallBehavior(Constants.ArchiveExtractionMethod, "tar"); + var installDir = TestCommon.GetRandomTestDir(); + var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestZipInstallerWithExe --silent -l {installDir}"); + WinGetSettingsHelper.ConfigureInstallBehavior(Constants.ArchiveExtractionMethod, string.Empty); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Successfully installed")); + Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(installDir, "/execustom")); + } + /// /// Test install an installed package and convert to upgrade. /// @@ -764,4 +779,4 @@ public void InstallExeThatInstallsMSIX() TestCommon.RemoveARPEntry(fakeProductCode); } } -} \ No newline at end of file +} diff --git a/src/AppInstallerCLIE2ETests/RepairCommand.cs b/src/AppInstallerCLIE2ETests/RepairCommand.cs new file mode 100644 index 0000000000..53c361ad72 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/RepairCommand.cs @@ -0,0 +1,280 @@ +// ----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT License. +// +// ----------------------------------------------------------------------------- + +namespace AppInstallerCLIE2ETests +{ + using System.IO; + using AppInstallerCLIE2ETests.Helpers; + using NUnit.Framework; + + /// + /// Test Repair command. + /// + public class RepairCommand : BaseCommand + { + /// + /// One time setup. + /// + [OneTimeSetUp] + public void OneTimeSetup() + { + // Try clean up AppInstallerTest.TestMsiInstaller for failure cases where cleanup is not successful + TestCommon.RunAICLICommand("uninstall", "AppInstallerTest.TestMsiInstaller"); + } + + /// + /// Test MSI installer repair. + /// + [Test] + public void RepairMSIInstaller() + { + if (string.IsNullOrEmpty(TestIndex.MsiInstallerV2)) + { + Assert.Ignore("MSI installer not available"); + } + + var installDir = TestCommon.GetRandomTestDir(); + var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestMsiRepair --silent -l {installDir}"); + + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Successfully installed")); + + // Note: The 'msiexec repair' command requires the original installer file to be present at the location registered in the ARP (Add/Remove Programs). + // In our test scenario, the MSI installer file is initially placed in a temporary location and then deleted, which can cause the repair operation to fail. + // To work around this, we copy the installer file to the ARP source directory before running the repair command. + // A more permanent solution would be to modify the MSI installer to cache the installer file in a known location and register that location as the installer source. + // This would allow the 'msiexec repair' command to function as expected. + string installerSourceDir = TestCommon.CopyInstallerFileToARPInstallSourceDirectory(TestCommon.GetTestDataFile("AppInstallerTestMsiInstallerV2.msi"), Constants.MsiInstallerProductCode, true); + + result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestMsiRepair"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Repair operation completed successfully")); + Assert.True(TestCommon.VerifyTestMsiInstalledAndCleanup(installDir)); + + if (installerSourceDir != null && Directory.Exists(installerSourceDir)) + { + Directory.Delete(installerSourceDir, true); + } + } + + /// + /// Test MSIX non-store package repair. + /// + [Test] + public void RepairNonStoreMSIXPackage() + { + // install a test msix package from TestSource and then repair it. + var installDir = TestCommon.GetRandomTestDir(); + var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestMsixInstaller --silent -l {installDir}"); + + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Successfully installed")); + + result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestMsixInstaller"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Repair operation completed successfully")); + Assert.True(TestCommon.VerifyTestMsixInstalledAndCleanup()); + } + + /// + /// Test MSIX non-store package repair with machine scope. + /// + [Test] + public void RepairNonStoreMsixPackageWithMachineScope() + { + // Selecting Microsoft.Paint_8wekyb3d8bbwe because it's a system package suitable for this scenario. + // First, we need to ensure this package is installed, otherwise, we skip the test. + var result = TestCommon.RunAICLICommand("list", "Microsoft.Paint_8wekyb3d8bbwe"); + + if (result.ExitCode != Constants.ErrorCode.S_OK) + { + Assert.Ignore("Test skipped as Microsoft.Paint_8wekyb3d8bbwe is not installed."); + } + + Assert.True(result.StdOut.Contains("Microsoft.Paint_8wekyb3d8bbwe")); + + result = TestCommon.RunAICLICommand("repair", "Microsoft.Paint_8wekyb3d8bbwe --scope machine"); + Assert.AreEqual(Constants.ErrorCode.ERROR_INSTALL_SYSTEM_NOT_SUPPORTED, result.ExitCode); + Assert.True(result.StdOut.Contains("The current system configuration does not support the repair of this package.")); + } + + /// + /// Test repair of a Burn installer that has a "modify" repair behavior specified in the manifest. + /// + [Test] + public void RepairBurnInstallerWithModifyBehavior() + { + // install a test burn package from TestSource and then repair it. + var installDir = TestCommon.GetRandomTestDir(); + var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestModifyRepair -v 2.0.0.0 --silent -l {installDir}"); + + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Successfully installed")); + + result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestModifyRepair"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Repair operation completed successfully")); + Assert.True(TestCommon.VerifyTestExeRepairCompletedAndCleanup(installDir, "Modify Repair operation")); + } + + /// + /// Tests the repair operation of a Burn installer that was installed in user scope but is being repaired in an admin context. + /// + [Test] + public void RepairBurnInstallerInAdminContextWithUserScopeInstall() + { + // install a test burn package from TestSource and then repair it. + var installDir = TestCommon.GetRandomTestDir(); + var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestUserScopeInstallRepairInAdminContext -v 2.0.0.0 --silent -l {installDir}"); + + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Successfully installed")); + + result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestUserScopeInstallRepairInAdminContext"); + Assert.AreEqual(Constants.ErrorCode.ERROR_ADMIN_CONTEXT_REPAIR_PROHIBITED, result.ExitCode); + Assert.True(result.StdOut.Contains("The package installed for user scope cannot be repaired when running with administrator privileges.")); + TestCommon.CleanupTestExeAndDirectory(installDir); + } + + /// + /// Tests the repair operation of a Burn installer that lacks a repair behavior. + /// + [Test] + public void RepairBurnInstallerMissingRepairBehavior() + { + // install a test burn package from TestSource and then repair it. + var installDir = TestCommon.GetRandomTestDir(); + var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestMissingRepairBehavior -v 2.0.0.0 --silent -l {installDir}"); + + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Successfully installed")); + + result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestMissingRepairBehavior"); + Assert.AreEqual(Constants.ErrorCode.ERROR_NO_REPAIR_INFO_FOUND, result.ExitCode); + Assert.True(result.StdOut.Contains("The repair command for this package cannot be found. Please reach out to the package publisher for support.")); + TestCommon.CleanupTestExeAndDirectory(installDir); + } + + /// + /// Test repair of a Exe installer that has a "uninstaller" repair behavior specified in the manifest and NoModify ARP flag set. + /// + [Test] + public void RepairBurnInstallerWithWithModifyBehaviorAndNoModifyFlag() + { + // install a test Exe package from TestSource and then repair it. + var installDir = TestCommon.GetRandomTestDir(); + var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestModifyRepairWithNoModify -v 2.0.0.0 --silent -l {installDir}"); + + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Successfully installed")); + + result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestModifyRepairWithNoModify"); + Assert.AreEqual(Constants.ErrorCode.ERROR_REPAIR_NOT_SUPPORTED, result.ExitCode); + Assert.True(result.StdOut.Contains("The installer technology in use does not support repair.")); + TestCommon.CleanupTestExeAndDirectory(installDir); + } + + /// + /// Tests the scenario where the repair operation is not supported for Portable Installer type. + /// + [Test] + public void RepairOperationNotSupportedForPortableInstaller() + { + string installDir = TestCommon.GetPortablePackagesDirectory(); + string packageId, commandAlias, fileName, packageDirName, productCode; + packageId = "AppInstallerTest.TestPortableExe"; + packageDirName = productCode = packageId + "_" + Constants.TestSourceIdentifier; + commandAlias = fileName = "AppInstallerTestExeInstaller.exe"; + + var result = TestCommon.RunAICLICommand("install", $"{packageId}"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Successfully installed")); + + result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestPortableExe"); + Assert.AreEqual(Constants.ErrorCode.ERROR_REPAIR_NOT_SUPPORTED, result.ExitCode); + Assert.True(result.StdOut.Contains("The installer technology in use does not support repair.")); + + // If no location specified, default behavior is to create a package directory with the name "{packageId}_{sourceId}" + TestCommon.VerifyPortablePackage(Path.Combine(installDir, packageDirName), commandAlias, fileName, productCode, true); + } + + /// + /// Test repair of a Exe installer that has a "uninstaller" repair behavior specified in the manifest. + /// + [Test] + public void RepairExeInstallerWithUninstallerBehavior() + { + // install a test Exe package from TestSource and then repair it. + var installDir = TestCommon.GetRandomTestDir(); + var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.UninstallerRepair -v 2.0.0.0 --silent -l {installDir}"); + + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Successfully installed")); + + result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.UninstallerRepair"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Repair operation completed successfully")); + Assert.True(TestCommon.VerifyTestExeRepairCompletedAndCleanup(installDir, "Uninstaller Repair operation")); + } + + /// + /// Test repair of a Exe installer that has a "uninstaller" repair behavior specified in the manifest and NoRepair ARP flag set. + /// + [Test] + public void RepairExeInstallerWithUninstallerBehaviorAndNoRepairFlag() + { + // install a test Exe package from TestSource and then repair it. + var installDir = TestCommon.GetRandomTestDir(); + var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.UninstallerRepairWithNoRepair -v 2.0.0.0 --silent -l {installDir}"); + + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Successfully installed")); + + result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.UninstallerRepairWithNoRepair"); + Assert.AreEqual(Constants.ErrorCode.ERROR_REPAIR_NOT_SUPPORTED, result.ExitCode); + Assert.True(result.StdOut.Contains("The installer technology in use does not support repair.")); + TestCommon.CleanupTestExeAndDirectory(installDir); + } + + /// + /// Test repair of a Nullsoft installer that has a "uninstaller" repair behavior specified in the manifest. + /// + [Test] + public void RepairNullsoftInstallerWithUninstallerBehavior() + { + // install a test Nullsoft package from TestSource and then repair it. + var installDir = TestCommon.GetRandomTestDir(); + var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.UninstallerRepair -v 2.0.0.0 --silent -l {installDir}"); + + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Successfully installed")); + + result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.UninstallerRepair"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Repair operation completed successfully")); + Assert.True(TestCommon.VerifyTestExeRepairCompletedAndCleanup(installDir, "Uninstaller Repair operation")); + } + + /// + /// Test repair of a Inno installer that has a "installer" repair behavior specified in the manifest. + /// + [Test] + public void RepairInnoInstallerWithInstallerBehavior() + { + // install a test Inno package from TestSource and then repair it. + var installDir = TestCommon.GetRandomTestDir(); + var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestInstallerRepair -v 2.0.0.0 --silent -l {installDir}"); + + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Successfully installed")); + + result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestInstallerRepair"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("Repair operation completed successfully")); + Assert.True(TestCommon.VerifyTestExeRepairCompletedAndCleanup(installDir, "Installer Repair operation")); + } + } +} diff --git a/src/AppInstallerCLIE2ETests/TestData/AppInstallerTestMsiInstallerV2.msi b/src/AppInstallerCLIE2ETests/TestData/AppInstallerTestMsiInstallerV2.msi new file mode 100644 index 0000000000..0024a35649 Binary files /dev/null and b/src/AppInstallerCLIE2ETests/TestData/AppInstallerTestMsiInstallerV2.msi differ diff --git a/src/AppInstallerCLIE2ETests/TestData/Manifests/TestBurnInstaller.MissingRepairBehavior.yaml b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestBurnInstaller.MissingRepairBehavior.yaml new file mode 100644 index 0000000000..d490a7b4d1 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestBurnInstaller.MissingRepairBehavior.yaml @@ -0,0 +1,18 @@ +PackageIdentifier: AppInstallerTest.TestMissingRepairBehavior +PackageVersion: 2.0.0.0 +PackageLocale: en-US +PackageName: TestMissingRepairBehavior +Publisher: AppInstallerTest +Installers: + - Architecture: x86 + InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestExeInstaller/AppInstallerTestExeInstaller.exe + InstallerType: burn + InstallerSha256: + ProductCode: '{A499DD5E-8DC5-4AD2-911A-BCD0263295E9}' + ElevationRequirement: elevationRequired + InstallerSwitches: + InstallLocation: /InstallDir + Custom: /Version 2.0.0.0 /DisplayName TestMissingRepairBehavior /UseHKLM + Repair: /repair +ManifestType: singleton +ManifestVersion: 1.7.0 diff --git a/src/AppInstallerCLIE2ETests/TestData/Manifests/TestBurnInstaller.ModifyRepair.yaml b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestBurnInstaller.ModifyRepair.yaml new file mode 100644 index 0000000000..70b44ec797 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestBurnInstaller.ModifyRepair.yaml @@ -0,0 +1,19 @@ +PackageIdentifier: AppInstallerTest.TestModifyRepair +PackageVersion: 2.0.0.0 +PackageLocale: en-US +PackageName: TestModifyRepair +Publisher: AppInstallerTest +RepairBehavior: modify +Installers: + - Architecture: x86 + InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestExeInstaller/AppInstallerTestExeInstaller.exe + InstallerType: burn + InstallerSha256: + ProductCode: '{A499DD5E-8DC5-4AD2-911A-BCD0263295E9}' + ElevationRequirement: elevationRequired + InstallerSwitches: + InstallLocation: /InstallDir + Custom: /Version 2.0.0.0 /DisplayName TestModifyRepair /UseHKLM + Repair: /repair +ManifestType: singleton +ManifestVersion: 1.7.0 diff --git a/src/AppInstallerCLIE2ETests/TestData/Manifests/TestBurnInstaller.ModifyRepairWithNoModify.yaml b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestBurnInstaller.ModifyRepairWithNoModify.yaml new file mode 100644 index 0000000000..65a93af82f --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestBurnInstaller.ModifyRepairWithNoModify.yaml @@ -0,0 +1,19 @@ +PackageIdentifier: AppInstallerTest.TestModifyRepairWithNoModify +PackageVersion: 2.0.0.0 +PackageLocale: en-US +PackageName: TestModifyRepairWithNoModify +Publisher: AppInstallerTest +RepairBehavior: modify +Installers: + - Architecture: x86 + InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestExeInstaller/AppInstallerTestExeInstaller.exe + InstallerType: burn + InstallerSha256: + ProductCode: '{A499DD5E-8DC5-4AD2-911A-BCD0263295E9}' + ElevationRequirement: elevationRequired + InstallerSwitches: + InstallLocation: /InstallDir + Custom: /Version 2.0.0.0 /DisplayName TestModifyRepairWithNoModify /UseHKLM /NoModify + Repair: /repair +ManifestType: singleton +ManifestVersion: 1.7.0 diff --git a/src/AppInstallerCLIE2ETests/TestData/Manifests/TestBurnInstaller.UserScopeInstallRepairInAdminContext.yaml b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestBurnInstaller.UserScopeInstallRepairInAdminContext.yaml new file mode 100644 index 0000000000..9255693e78 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestBurnInstaller.UserScopeInstallRepairInAdminContext.yaml @@ -0,0 +1,19 @@ +PackageIdentifier: AppInstallerTest.TestUserScopeInstallRepairInAdminContext +PackageVersion: 2.0.0.0 +PackageLocale: en-US +PackageName: TestUserScopeInstallRepairInAdminContext +Publisher: AppInstallerTest +RepairBehavior: modify +Installers: + - Architecture: x86 + InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestExeInstaller/AppInstallerTestExeInstaller.exe + InstallerType: burn + InstallerSha256: + ProductCode: '{A499DD5E-8DC5-4AD2-911A-BCD0263295E9}' + ElevationRequirement: elevationRequired + InstallerSwitches: + InstallLocation: /InstallDir + Custom: /Version 2.0.0.0 /DisplayName TestUserScopeInstallRepairInAdminContext + Repair: /repair +ManifestType: singleton +ManifestVersion: 1.7.0 diff --git a/src/AppInstallerCLIE2ETests/TestData/Manifests/TestExeInstaller.UninstallerRepair.yaml b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestExeInstaller.UninstallerRepair.yaml new file mode 100644 index 0000000000..6bd501d5c1 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestExeInstaller.UninstallerRepair.yaml @@ -0,0 +1,19 @@ +PackageIdentifier: AppInstallerTest.UninstallerRepair +PackageVersion: 2.0.0.0 +PackageLocale: en-US +PackageName: UninstallerRepair +Publisher: AppInstallerTest +RepairBehavior: uninstaller +Installers: + - Architecture: x86 + InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestExeInstaller/AppInstallerTestExeInstaller.exe + InstallerType: exe + InstallerSha256: + ProductCode: '{A499DD5E-8DC5-4AD2-911A-BCD0263295E9}' + ElevationRequirement: elevationRequired + InstallerSwitches: + InstallLocation: /InstallDir + Custom: /Version 2.0.0.0 /DisplayName UninstallerRepair /UseHKLM + Repair: /repair +ManifestType: singleton +ManifestVersion: 1.7.0 diff --git a/src/AppInstallerCLIE2ETests/TestData/Manifests/TestExeInstaller.UninstallerRepairWithNoRepair.yaml b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestExeInstaller.UninstallerRepairWithNoRepair.yaml new file mode 100644 index 0000000000..e816c82e04 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestExeInstaller.UninstallerRepairWithNoRepair.yaml @@ -0,0 +1,19 @@ +PackageIdentifier: AppInstallerTest.UninstallerRepairWithNoRepair +PackageVersion: 2.0.0.0 +PackageLocale: en-US +PackageName: UninstallerRepairWithNoRepair +Publisher: AppInstallerTest +RepairBehavior: uninstaller +Installers: + - Architecture: x86 + InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestExeInstaller/AppInstallerTestExeInstaller.exe + InstallerType: exe + InstallerSha256: + ProductCode: '{A499DD5E-8DC5-4AD2-911A-BCD0263295E9}' + ElevationRequirement: elevationRequired + InstallerSwitches: + InstallLocation: /InstallDir + Custom: /Version 2.0.0.0 /DisplayName UninstallerRepairWithNoRepair /UseHKLM /NoRepair + Repair: /repair +ManifestType: singleton +ManifestVersion: 1.7.0 diff --git a/src/AppInstallerCLIE2ETests/TestData/Manifests/TestInnoInstaller.InstallerRepair.yaml b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestInnoInstaller.InstallerRepair.yaml new file mode 100644 index 0000000000..a43a34722b --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestInnoInstaller.InstallerRepair.yaml @@ -0,0 +1,19 @@ +PackageIdentifier: AppInstallerTest.TestInstallerRepair +PackageVersion: 2.0.0.0 +PackageLocale: en-US +PackageName: TestInstallerRepair +Publisher: AppInstallerTest +RepairBehavior: installer +Installers: + - Architecture: x86 + InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestExeInstaller/AppInstallerTestExeInstaller.exe + InstallerType: inno + InstallerSha256: + ProductCode: '{A499DD5E-8DC5-4AD2-911A-BCD0263295E9}' + ElevationRequirement: elevationRequired + InstallerSwitches: + InstallLocation: /InstallDir + Custom: /Version 2.0.0.0 /DisplayName TestInstallerRepair /UseHKLM + Repair: /repair /UseHKLM +ManifestType: singleton +ManifestVersion: 1.7.0 diff --git a/src/AppInstallerCLIE2ETests/TestData/Manifests/TestMsiInstaller.Repair.yaml b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestMsiInstaller.Repair.yaml new file mode 100644 index 0000000000..1ae08edcea --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestMsiInstaller.Repair.yaml @@ -0,0 +1,14 @@ +# Uses the MSI installer; +PackageIdentifier: AppInstallerTest.TestMsiRepair +PackageVersion: 2.0.0.0 +PackageLocale: en-US +PackageName: TestMsiInstallerV2 +Publisher: AppInstallerTest +Installers: + - Architecture: x86 + InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestMsiInstaller/AppInstallerTestMsiInstallerV2.msi + InstallerType: msi + InstallerSha256: + ProductCode: '{A5D36CF1-1993-4F63-BFB4-3ACD910D36A1}' +ManifestType: singleton +ManifestVersion: 1.7.0 diff --git a/src/AppInstallerCLIE2ETests/TestData/Manifests/TestNullsoftInstaller.UninstallerRepair.yaml b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestNullsoftInstaller.UninstallerRepair.yaml new file mode 100644 index 0000000000..c1444e6626 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestNullsoftInstaller.UninstallerRepair.yaml @@ -0,0 +1,19 @@ +PackageIdentifier: AppInstallerTest.NullsoftUninstallerRepair +PackageVersion: 2.0.0.0 +PackageLocale: en-US +PackageName: NullsoftUninstallerRepair +Publisher: AppInstallerTest +RepairBehavior: uninstaller +Installers: + - Architecture: x86 + InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestExeInstaller/AppInstallerTestExeInstaller.exe + InstallerType: exe + InstallerSha256: + ProductCode: '{A499DD5E-8DC5-4AD2-911A-BCD0263295E9}' + ElevationRequirement: elevationRequired + InstallerSwitches: + InstallLocation: /InstallDir + Custom: /Version 2.0.0.0 /DisplayName NullsoftUninstallerRepair /UseHKLM + Repair: /repair +ManifestType: singleton +ManifestVersion: 1.7.0 diff --git a/src/AppInstallerCLIE2ETests/TestData/localsource.json b/src/AppInstallerCLIE2ETests/TestData/localsource.json index adb672f0fc..45bae359be 100644 --- a/src/AppInstallerCLIE2ETests/TestData/localsource.json +++ b/src/AppInstallerCLIE2ETests/TestData/localsource.json @@ -17,6 +17,12 @@ "Input": "%BUILD_SOURCESDIRECTORY%/src/AppInstallerCLIE2ETests/TestData/AppInstallerTestMsiInstaller.msi", "HashToken": "" }, + { + "Type": "msi", + "Name": "AppInstallerTestMsiInstaller/AppInstallerTestMsiInstallerV2.msi", + "Input": "%BUILD_SOURCESDIRECTORY%/src/AppInstallerCLIE2ETests/TestData/AppInstallerTestMsiInstallerV2.msi", + "HashToken": "" + }, { "Type": "msix", "Name": "AppInstallerTestMsixInstaller/AppInstallerTestMsixInstaller.msix", diff --git a/src/AppInstallerCLIPackage/Package.appxmanifest b/src/AppInstallerCLIPackage/Package.appxmanifest index 6d93cc4abe..18d9ca333e 100644 --- a/src/AppInstallerCLIPackage/Package.appxmanifest +++ b/src/AppInstallerCLIPackage/Package.appxmanifest @@ -1,4 +1,4 @@ - + - + @@ -74,8 +74,6 @@ - - @@ -83,6 +81,14 @@ + + + + + + + + @@ -116,4 +122,4 @@ - \ No newline at end of file + diff --git a/src/AppInstallerCLITests/Archive.cpp b/src/AppInstallerCLITests/Archive.cpp index 31070c7c39..4d415761f1 100644 --- a/src/AppInstallerCLITests/Archive.cpp +++ b/src/AppInstallerCLITests/Archive.cpp @@ -31,4 +31,4 @@ TEST_CASE("Scan_ZipArchive", "[archive]") const auto& testZipPath = testZip.GetPath(); bool result = ScanZipFile(testZipPath); REQUIRE(result); -} \ No newline at end of file +} diff --git a/src/AppInstallerCLITests/InstallFlow.cpp b/src/AppInstallerCLITests/InstallFlow.cpp index a52dd702a1..5cf6229805 100644 --- a/src/AppInstallerCLITests/InstallFlow.cpp +++ b/src/AppInstallerCLITests/InstallFlow.cpp @@ -507,6 +507,59 @@ TEST_CASE("ExtractInstallerFromArchive_InvalidZip", "[InstallFlow][workflow]") auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Zip_Exe.yaml")); context.Add(manifest); context.Add(manifest.Installers.at(0)); + + // Provide an invalid zip file which should be handled appropriately. + context.Add(TestDataFile("AppInstallerTestExeInstaller.exe")); + context << ExtractFilesFromArchive; + REQUIRE_TERMINATED_WITH(context, APPINSTALLER_CLI_ERROR_EXTRACT_ARCHIVE_FAILED); + REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::ExtractArchiveFailed).get()) != std::string::npos); +} + +TEST_CASE("ExtractInstallerFromArchiveWithTar", "[InstallFlow][workflow]") +{ + TestCommon::TestUserSettings testSettings; + testSettings.Set(AppInstaller::Archive::ExtractionMethod::Tar); + + TestCommon::TempFile installResultPath("TestExeInstalled.txt"); + + std::ostringstream installOutput; + TestContext context{ installOutput, std::cin }; + auto previousThreadGlobals = context.SetForCurrentThread(); + + OverrideForShellExecute(context); + OverrideForVerifyAndSetNestedInstaller(context); + context.Args.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_Zip_Exe.yaml").GetPath().u8string()); + + TestHook::SetScanArchiveResult_Override scanArchiveResultOverride(true); + TestHook::SetExtractArchiveWithTarResult_Override setExtractArchiveWithTarResultOverride(ERROR_SUCCESS); + + InstallCommand install({}); + install.Execute(context); + INFO(installOutput.str()); + REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::ExtractArchiveSucceeded).get()) != std::string::npos); + + // Verify Installer is called and parameters are passed in. + REQUIRE(std::filesystem::exists(installResultPath.GetPath())); + std::ifstream installResultFile(installResultPath.GetPath()); + REQUIRE(installResultFile.is_open()); + std::string installResultStr; + std::getline(installResultFile, installResultStr); + REQUIRE(installResultStr.find("/custom") != std::string::npos); + REQUIRE(installResultStr.find("/silentwithprogress") != std::string::npos); +} + +TEST_CASE("ExtractInstallerFromArchiveWithTar_InvalidZip", "[InstallFlow][workflow]") +{ + TestCommon::TestUserSettings testSettings; + testSettings.Set(AppInstaller::Archive::ExtractionMethod::Tar); + + std::ostringstream installOutput; + TestContext context{ installOutput, std::cin }; + auto previousThreadGlobals = context.SetForCurrentThread(); + auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallFlowTest_Zip_Exe.yaml")); + context.Add(manifest); + context.Add(manifest.Installers.at(0)); + // Provide an invalid zip file which should be handled appropriately. context.Add(TestDataFile("AppInstallerTestExeInstaller.exe")); context << ExtractFilesFromArchive; diff --git a/src/AppInstallerCLITests/MSStoreDownloadFlow.cpp b/src/AppInstallerCLITests/MSStoreDownloadFlow.cpp index 195a1ae1b6..53fa34a8a9 100644 --- a/src/AppInstallerCLITests/MSStoreDownloadFlow.cpp +++ b/src/AppInstallerCLITests/MSStoreDownloadFlow.cpp @@ -22,7 +22,7 @@ utility::string_t TestDisplayCatalogResponse = _XPLATSTR( "DisplaySkuAvailabilities": [ { "Sku": { - "SkuId": "0010", + "SkuId": "0015", "Properties": { "Packages": [ { @@ -242,8 +242,6 @@ std::vector GetSfsAppContentsOverrideFunction(std::string_view TEST_CASE("MSStoreDownloadFlow_Success", "[MSStoreDownloadFlow][workflow]") { - auto enableFeature = TestUserSettings::EnableExperimentalFeature(AppInstaller::Settings::ExperimentalFeature::Feature::StoreDownload); - TestCommon::TempDirectory tempDirectory("TestDownloadDirectory", false); std::ostringstream downloadOutput; @@ -287,8 +285,6 @@ TEST_CASE("MSStoreDownloadFlow_Success", "[MSStoreDownloadFlow][workflow]") TEST_CASE("MSStoreDownloadFlow_Success_SkipDependencies", "[MSStoreDownloadFlow][workflow]") { - auto enableFeature = TestUserSettings::EnableExperimentalFeature(AppInstaller::Settings::ExperimentalFeature::Feature::StoreDownload); - TestCommon::TempDirectory tempDirectory("TestDownloadDirectory", false); std::ostringstream downloadOutput; @@ -328,8 +324,6 @@ TEST_CASE("MSStoreDownloadFlow_Success_SkipDependencies", "[MSStoreDownloadFlow] TEST_CASE("MSStoreDownloadFlow_Success_SkipLicense", "[MSStoreDownloadFlow][workflow]") { - auto enableFeature = TestUserSettings::EnableExperimentalFeature(AppInstaller::Settings::ExperimentalFeature::Feature::StoreDownload); - TestCommon::TempDirectory tempDirectory("TestDownloadDirectory", false); std::ostringstream downloadOutput; @@ -364,8 +358,6 @@ TEST_CASE("MSStoreDownloadFlow_Success_SkipLicense", "[MSStoreDownloadFlow][work TEST_CASE("MSStoreDownloadFlow_Success_SpecificLocale", "[MSStoreDownloadFlow][workflow]") { - auto enableFeature = TestUserSettings::EnableExperimentalFeature(AppInstaller::Settings::ExperimentalFeature::Feature::StoreDownload); - TestCommon::TempDirectory tempDirectory("TestDownloadDirectory", false); std::ostringstream downloadOutput; @@ -404,8 +396,6 @@ TEST_CASE("MSStoreDownloadFlow_Success_SpecificLocale", "[MSStoreDownloadFlow][w TEST_CASE("MSStoreDownloadFlow_Success_SpecificArchitecture", "[MSStoreDownloadFlow][workflow]") { - auto enableFeature = TestUserSettings::EnableExperimentalFeature(AppInstaller::Settings::ExperimentalFeature::Feature::StoreDownload); - TestCommon::TempDirectory tempDirectory("TestDownloadDirectory", false); std::ostringstream downloadOutput; @@ -445,8 +435,6 @@ TEST_CASE("MSStoreDownloadFlow_Success_SpecificArchitecture", "[MSStoreDownloadF TEST_CASE("MSStoreDownloadFlow_Success_SpecificPlatform", "[MSStoreDownloadFlow][workflow]") { - auto enableFeature = TestUserSettings::EnableExperimentalFeature(AppInstaller::Settings::ExperimentalFeature::Feature::StoreDownload); - TestCommon::TempDirectory tempDirectory("TestDownloadDirectory", false); std::ostringstream downloadOutput; @@ -486,8 +474,6 @@ TEST_CASE("MSStoreDownloadFlow_Success_SpecificPlatform", "[MSStoreDownloadFlow] TEST_CASE("MSStoreDownloadFlow_Fail_TargetSkuNotFound", "[MSStoreDownloadFlow][workflow]") { - auto enableFeature = TestUserSettings::EnableExperimentalFeature(AppInstaller::Settings::ExperimentalFeature::Feature::StoreDownload); - TestCommon::TempDirectory tempDirectory("TestDownloadDirectory", false); std::ostringstream downloadOutput; @@ -507,8 +493,6 @@ TEST_CASE("MSStoreDownloadFlow_Fail_TargetSkuNotFound", "[MSStoreDownloadFlow][w TEST_CASE("MSStoreDownloadFlow_Fail_LocaleNotApplicable", "[MSStoreDownloadFlow][workflow]") { - auto enableFeature = TestUserSettings::EnableExperimentalFeature(AppInstaller::Settings::ExperimentalFeature::Feature::StoreDownload); - TestCommon::TempDirectory tempDirectory("TestDownloadDirectory", false); std::ostringstream downloadOutput; @@ -528,8 +512,6 @@ TEST_CASE("MSStoreDownloadFlow_Fail_LocaleNotApplicable", "[MSStoreDownloadFlow] TEST_CASE("MSStoreDownloadFlow_Fail_ArchitectureNotApplicable", "[MSStoreDownloadFlow][workflow]") { - auto enableFeature = TestUserSettings::EnableExperimentalFeature(AppInstaller::Settings::ExperimentalFeature::Feature::StoreDownload); - TestCommon::TempDirectory tempDirectory("TestDownloadDirectory", false); std::ostringstream downloadOutput; @@ -550,8 +532,6 @@ TEST_CASE("MSStoreDownloadFlow_Fail_ArchitectureNotApplicable", "[MSStoreDownloa TEST_CASE("MSStoreDownloadFlow_Fail_PlatformNotApplicable", "[MSStoreDownloadFlow][workflow]") { - auto enableFeature = TestUserSettings::EnableExperimentalFeature(AppInstaller::Settings::ExperimentalFeature::Feature::StoreDownload); - TestCommon::TempDirectory tempDirectory("TestDownloadDirectory", false); std::ostringstream downloadOutput; @@ -572,8 +552,6 @@ TEST_CASE("MSStoreDownloadFlow_Fail_PlatformNotApplicable", "[MSStoreDownloadFlo TEST_CASE("MSStoreDownloadFlow_Fail_Licensing", "[MSStoreDownloadFlow][workflow]") { - auto enableFeature = TestUserSettings::EnableExperimentalFeature(AppInstaller::Settings::ExperimentalFeature::Feature::StoreDownload); - TestCommon::TempDirectory tempDirectory("TestDownloadDirectory", false); std::ostringstream downloadOutput; diff --git a/src/AppInstallerCLITests/TestCommon.cpp b/src/AppInstallerCLITests/TestCommon.cpp index 1c0e3eff0d..1a924d9b85 100644 --- a/src/AppInstallerCLITests/TestCommon.cpp +++ b/src/AppInstallerCLITests/TestCommon.cpp @@ -262,14 +262,13 @@ namespace TestCommon std::unique_ptr result = std::make_unique(keepFileSettings); // Due to the template usage, this needs to be updated for any features that want to use it. - switch (feature) - { - case Settings::ExperimentalFeature::Feature::StoreDownload: - result->Set(true); - break; - default: - THROW_HR(E_NOTIMPL); - } + // Currently no feature is used. Uncomment below when a feature needs to be used. + // switch (feature) + // { + // default: + // THROW_HR(E_NOTIMPL); + // } + UNREFERENCED_PARAMETER(feature); return result; } diff --git a/src/AppInstallerCLITests/TestHooks.h b/src/AppInstallerCLITests/TestHooks.h index f27b1738bc..3917c8d1c2 100644 --- a/src/AppInstallerCLITests/TestHooks.h +++ b/src/AppInstallerCLITests/TestHooks.h @@ -71,6 +71,7 @@ namespace AppInstaller { void TestHook_SetEnableWindowsFeatureResult_Override(std::optional&& result); void TestHook_SetDoesWindowsFeatureExistResult_Override(std::optional&& result); + void TestHook_SetExtractArchiveWithTarResult_Override(std::optional&& result); } namespace Reboot @@ -183,6 +184,19 @@ namespace TestHook } }; + struct SetExtractArchiveWithTarResult_Override + { + SetExtractArchiveWithTarResult_Override(DWORD result) + { + AppInstaller::CLI::Workflow::TestHook_SetExtractArchiveWithTarResult_Override(result); + } + + ~SetExtractArchiveWithTarResult_Override() + { + AppInstaller::CLI::Workflow::TestHook_SetExtractArchiveWithTarResult_Override({}); + } + }; + struct SetInitiateRebootResult_Override { SetInitiateRebootResult_Override(bool status) : m_status(status) diff --git a/src/AppInstallerCLITests/UserSettings.cpp b/src/AppInstallerCLITests/UserSettings.cpp index b8f072e632..ed54c36bbc 100644 --- a/src/AppInstallerCLITests/UserSettings.cpp +++ b/src/AppInstallerCLITests/UserSettings.cpp @@ -524,6 +524,28 @@ TEST_CASE("SettingsDownloadDefaultDirectory", "[settings]") REQUIRE(userSettingTest.Get() == "C:/Foo/Bar"); REQUIRE(userSettingTest.GetWarnings().size() == 0); } +} + +TEST_CASE("SettingsArchiveExtractionMethod", "[settings]") +{ + auto again = DeleteUserSettingsFiles(); + + SECTION("Shell api") + { + std::string_view json = R"({ "installBehavior": { "archiveExtractionMethod": "shellApi" } })"; + SetSetting(Stream::PrimaryUserSettings, json); + UserSettingsTest userSettingTest; + + REQUIRE(userSettingTest.Get() == AppInstaller::Archive::ExtractionMethod::ShellApi); + } + SECTION("Shell api") + { + std::string_view json = R"({ "installBehavior": { "archiveExtractionMethod": "tar" } })"; + SetSetting(Stream::PrimaryUserSettings, json); + UserSettingsTest userSettingTest; + + REQUIRE(userSettingTest.Get() == AppInstaller::Archive::ExtractionMethod::Tar); + } } TEST_CASE("SettingsInstallScope", "[settings]") diff --git a/src/AppInstallerCLITests/YamlManifest.cpp b/src/AppInstallerCLITests/YamlManifest.cpp index 3938d20724..b7c1517b72 100644 --- a/src/AppInstallerCLITests/YamlManifest.cpp +++ b/src/AppInstallerCLITests/YamlManifest.cpp @@ -1289,6 +1289,18 @@ TEST_CASE("WriteV1_7SingletonManifestAndVerifyContents", "[ManifestCreation]") VerifyV1ManifestContent(generatedMultiFileManifest, false, ManifestVer{ s_ManifestVersionV1_7 }, true); } +TEST_CASE("WriteManifestWithMultipleLocale", "[ManifestCreation]") +{ + Manifest multiLocaleManifest = YamlParser::CreateFromPath(TestDataFile("Manifest-Good-MultiLocale.yaml")); + TempDirectory exportedDirectory{ "exported" }; + std::filesystem::path generatedManifestPath = exportedDirectory.GetPath() / "testManifestWithMultipleLocale.yaml"; + YamlWriter::OutputYamlFile(multiLocaleManifest, multiLocaleManifest.Installers[0], generatedManifestPath); + + REQUIRE(std::filesystem::exists(generatedManifestPath)); + Manifest generatedManifest = YamlParser::CreateFromPath(generatedManifestPath); + REQUIRE(generatedManifest.Localizations.size() == 2); +} + YamlManifestInfo CreateYamlManifestInfo(std::string testDataFile) { YamlManifestInfo result; diff --git a/src/AppInstallerCommonCore/Archive.cpp b/src/AppInstallerCommonCore/Archive.cpp index 9d5f9c5896..95766519e9 100644 --- a/src/AppInstallerCommonCore/Archive.cpp +++ b/src/AppInstallerCommonCore/Archive.cpp @@ -49,7 +49,6 @@ namespace AppInstaller::Archive return S_OK; } - #ifndef AICLI_DISABLE_TEST_HOOKS static bool* s_ScanArchiveResult_TestHook_Override = nullptr; @@ -77,4 +76,4 @@ namespace AppInstaller::Archive return scanResult == 0; } -} \ No newline at end of file +} diff --git a/src/AppInstallerCommonCore/ExperimentalFeature.cpp b/src/AppInstallerCommonCore/ExperimentalFeature.cpp index e1c2a55276..7222dcbbc2 100644 --- a/src/AppInstallerCommonCore/ExperimentalFeature.cpp +++ b/src/AppInstallerCommonCore/ExperimentalFeature.cpp @@ -46,8 +46,6 @@ namespace AppInstaller::Settings return userSettings.Get(); case ExperimentalFeature::Feature::ConfigureSelfElevation: return userSettings.Get(); - case ExperimentalFeature::Feature::StoreDownload: - return userSettings.Get(); case ExperimentalFeature::Feature::IndexV2: return userSettings.Get(); case ExperimentalFeature::Feature::ConfigureExport: @@ -87,8 +85,6 @@ namespace AppInstaller::Settings return ExperimentalFeature{ "Configuration Schema 0.3", "configuration03", "https://aka.ms/winget-settings", Feature::Configuration03 }; case Feature::ConfigureSelfElevation: return ExperimentalFeature{ "Configure Self Elevation", "configureSelfElevate", "https://aka.ms/winget-settings", Feature::ConfigureSelfElevation }; - case Feature::StoreDownload: - return ExperimentalFeature{ "Store Download", "storeDownload", "https://aka.ms/winget-settings", Feature::StoreDownload }; case Feature::IndexV2: return ExperimentalFeature{ "Index V2", "indexV2", "https://aka.ms/winget-settings", Feature::IndexV2 }; case Feature::ConfigureExport: diff --git a/src/AppInstallerCommonCore/MSStoreDownload.cpp b/src/AppInstallerCommonCore/MSStoreDownload.cpp index d5171128d7..4db8b72d60 100644 --- a/src/AppInstallerCommonCore/MSStoreDownload.cpp +++ b/src/AppInstallerCommonCore/MSStoreDownload.cpp @@ -49,7 +49,7 @@ namespace AppInstaller::MSStore namespace DisplayCatalogDetails { // Default preferred sku to use - constexpr std::string_view TargetSkuIdValue = "0010"sv; + constexpr std::string_view TargetSkuIdValue = "0015"sv; // Json response fields constexpr std::string_view Product = "Product"sv; @@ -67,9 +67,10 @@ namespace AppInstaller::MSStore constexpr std::string_view WuCategoryId = "WuCategoryId"sv; // Display catalog rest endpoint - constexpr std::string_view DisplayCatalogRestApi = R"(https://displaycatalog.mp.microsoft.com/v7.0/products/{0}?fieldsTemplate={1}&market={2}&languages={3})"; + constexpr std::string_view DisplayCatalogRestApi = R"(https://displaycatalog.mp.microsoft.com/v7.0/products/{0}?fieldsTemplate={1}&market={2}&languages={3}&catalogIds={4})"; constexpr std::string_view Details = "Details"sv; constexpr std::string_view Neutral = "Neutral"sv; + constexpr std::string_view TargetCatalogId = "4"sv; enum class DisplayCatalogPackageFormatEnum { @@ -411,7 +412,7 @@ namespace AppInstaller::MSStore locales.emplace_back(Neutral); auto restEndpoint = AppInstaller::Utility::Format(std::string{ DisplayCatalogRestApi }, - productId, Details, AppInstaller::Runtime::GetOSRegion(), Utility::Join(Utility::LocIndView(","), locales)); + productId, Details, AppInstaller::Runtime::GetOSRegion(), Utility::Join(Utility::LocIndView(","), locales), TargetCatalogId); return JSON::GetUtilityString(restEndpoint); } @@ -422,7 +423,7 @@ namespace AppInstaller::MSStore // "DisplaySkuAvailabilities": [ // { // "Sku": { - // "SkuId": "0010", + // "SkuId": "0015", // ... Sku Contents ... // } // } @@ -570,7 +571,7 @@ namespace AppInstaller::MSStore return displayCatalogPackages; } - DisplayCatalogPackage CallDisplayCatalogAndGetPreferredPackage(std::string_view productId, std::string_view locale, Utility::Architecture architecture) + DisplayCatalogPackage CallDisplayCatalogAndGetPreferredPackage(std::string_view productId, std::string_view locale, Utility::Architecture architecture, const Http::HttpClientHelper::HttpRequestHeaders& authHeaders) { AICLI_LOG(Core, Info, << "CallDisplayCatalogAndGetPreferredPackage with ProductId: " << productId << " Locale: " << locale << " Architecture: " << Utility::ToString(architecture)); @@ -585,7 +586,7 @@ namespace AppInstaller::MSStore } #endif - std::optional displayCatalogResponseObject = httpClientHelper.HandleGet(displayCatalogApi); + std::optional displayCatalogResponseObject = httpClientHelper.HandleGet(displayCatalogApi, {}, authHeaders); if (!displayCatalogResponseObject) { @@ -1007,6 +1008,19 @@ namespace AppInstaller::MSStore AppInstaller::Authentication::AuthenticationArguments authArgs) : m_productId(std::move(productId)), m_architecture(architecture), m_platform(platform), m_locale(std::move(locale)) { +#ifndef AICLI_DISABLE_TEST_HOOKS + if (!TestHooks::s_DisplayCatalog_HttpPipelineStage_Override) +#endif + { + Authentication::MicrosoftEntraIdAuthenticationInfo displayCatalogMicrosoftEntraIdAuthInfo; + displayCatalogMicrosoftEntraIdAuthInfo.Resource = "https://bigcatalog.commerce.microsoft.com"; + Authentication::AuthenticationInfo displayCatalogAuthInfo; + displayCatalogAuthInfo.Type = Authentication::AuthenticationType::MicrosoftEntraId; + displayCatalogAuthInfo.MicrosoftEntraIdInfo = std::move(displayCatalogMicrosoftEntraIdAuthInfo); + + m_displayCatalogAuthenticator = std::make_unique(std::move(displayCatalogAuthInfo), authArgs); + } + #ifndef AICLI_DISABLE_TEST_HOOKS if (!TestHooks::s_Licensing_HttpPipelineStage_Override) #endif @@ -1017,7 +1031,6 @@ namespace AppInstaller::MSStore licensingAuthInfo.Type = Authentication::AuthenticationType::MicrosoftEntraId; licensingAuthInfo.MicrosoftEntraIdInfo = std::move(licensingMicrosoftEntraIdAuthInfo); - // Not moving authArgs because we'll have auth for display catalog and sfs client in the near future. m_licensingAuthenticator = std::make_unique(std::move(licensingAuthInfo), authArgs); } } @@ -1025,7 +1038,7 @@ namespace AppInstaller::MSStore MSStoreDownloadInfo MSStoreDownloadContext::GetDownloadInfo() { #ifndef WINGET_DISABLE_FOR_FUZZING - auto displayCatalogPackage = DisplayCatalogDetails::CallDisplayCatalogAndGetPreferredPackage(m_productId, m_locale, m_architecture); + auto displayCatalogPackage = DisplayCatalogDetails::CallDisplayCatalogAndGetPreferredPackage(m_productId, m_locale, m_architecture, GetAuthHeaders(m_displayCatalogAuthenticator)); auto downloadInfo = SfsClientDetails::CallSfsClientAndGetMSStoreDownloadInfo(displayCatalogPackage.WuCategoryId, m_architecture, m_platform); downloadInfo.ContentId = displayCatalogPackage.ContentId; return downloadInfo; diff --git a/src/AppInstallerCommonCore/Manifest/YamlWriter.cpp b/src/AppInstallerCommonCore/Manifest/YamlWriter.cpp index 33d35249a4..61910e13e9 100644 --- a/src/AppInstallerCommonCore/Manifest/YamlWriter.cpp +++ b/src/AppInstallerCommonCore/Manifest/YamlWriter.cpp @@ -610,14 +610,14 @@ namespace AppInstaller::Manifest::YamlWriter { out << YAML::Key << Localization; out << YAML::BeginSeq; - out << YAML::BeginMap; for (const auto& localization : localizations) - { - ProcessLocaleFields(out, localization); + { + out << YAML::BeginMap; + ProcessLocaleFields(out, localization); + out << YAML::EndMap; } - out << YAML::EndMap; out << YAML::EndSeq; } } @@ -669,4 +669,4 @@ namespace AppInstaller::Manifest::YamlWriter emitter.Emit(outFileStream); outFileStream.close(); } -} \ No newline at end of file +} diff --git a/src/AppInstallerCommonCore/Public/winget/Archive.h b/src/AppInstallerCommonCore/Public/winget/Archive.h index 8855d42fc4..3ca16a3b3e 100644 --- a/src/AppInstallerCommonCore/Public/winget/Archive.h +++ b/src/AppInstallerCommonCore/Public/winget/Archive.h @@ -5,7 +5,14 @@ namespace AppInstaller::Archive { + enum class ExtractionMethod + { + // Default archive extraction method is ShellApi. + ShellApi, + Tar, + }; + HRESULT TryExtractArchive(const std::filesystem::path& archivePath, const std::filesystem::path& destPath); bool ScanZipFile(const std::filesystem::path& zipPath); -} \ No newline at end of file +} diff --git a/src/AppInstallerCommonCore/Public/winget/ExperimentalFeature.h b/src/AppInstallerCommonCore/Public/winget/ExperimentalFeature.h index f014cf0c3f..86fb1d9af2 100644 --- a/src/AppInstallerCommonCore/Public/winget/ExperimentalFeature.h +++ b/src/AppInstallerCommonCore/Public/winget/ExperimentalFeature.h @@ -26,9 +26,8 @@ namespace AppInstaller::Settings Resume = 0x2, Configuration03 = 0x4, ConfigureSelfElevation = 0x8, - StoreDownload = 0x10, - ConfigureExport = 0x20, - IndexV2 = 0x40, + ConfigureExport = 0x10, + IndexV2 = 0x20, Max, // This MUST always be after all experimental features // Features listed after Max will not be shown with the features command diff --git a/src/AppInstallerCommonCore/Public/winget/MSStoreDownload.h b/src/AppInstallerCommonCore/Public/winget/MSStoreDownload.h index 25fecec056..96a69ef584 100644 --- a/src/AppInstallerCommonCore/Public/winget/MSStoreDownload.h +++ b/src/AppInstallerCommonCore/Public/winget/MSStoreDownload.h @@ -52,6 +52,7 @@ namespace AppInstaller::MSStore AppInstaller::Utility::Architecture m_architecture = AppInstaller::Utility::Architecture::Unknown; AppInstaller::Manifest::PlatformEnum m_platform = AppInstaller::Manifest::PlatformEnum::Unknown; std::string m_locale; + std::unique_ptr m_displayCatalogAuthenticator; std::unique_ptr m_licensingAuthenticator; }; } diff --git a/src/AppInstallerCommonCore/Public/winget/UserSettings.h b/src/AppInstallerCommonCore/Public/winget/UserSettings.h index 45bef7fe20..4203011c1f 100644 --- a/src/AppInstallerCommonCore/Public/winget/UserSettings.h +++ b/src/AppInstallerCommonCore/Public/winget/UserSettings.h @@ -3,6 +3,7 @@ #pragma once #include "AppInstallerStrings.h" #include "AppInstallerLogging.h" +#include "winget/Archive.h" #include "winget/GroupPolicy.h" #include "winget/Resources.h" #include "winget/ManifestCommon.h" @@ -73,7 +74,6 @@ namespace AppInstaller::Settings EFResume, EFConfiguration03, EFConfigureSelfElevation, - EFStoreDownload, EFIndexV2, EFConfigureExport, // Telemetry @@ -89,6 +89,7 @@ namespace AppInstaller::Settings InstallerTypeRequirement, InstallDefaultRoot, InstallSkipDependencies, + ArchiveExtractionMethod, DisableInstallNotes, PortablePackageUserRoot, PortablePackageMachineRoot, @@ -156,8 +157,7 @@ namespace AppInstaller::Settings SETTINGMAPPING_SPECIALIZATION(Setting::EFResume, bool, bool, false, ".experimentalFeatures.resume"sv); SETTINGMAPPING_SPECIALIZATION(Setting::EFConfiguration03, bool, bool, false, ".experimentalFeatures.configuration03"sv); SETTINGMAPPING_SPECIALIZATION(Setting::EFConfigureSelfElevation, bool, bool, false, ".experimentalFeatures.configureSelfElevate"sv); - SETTINGMAPPING_SPECIALIZATION(Setting::EFStoreDownload, bool, bool, false, ".experimentalFeatures.storeDownload"sv); - SETTINGMAPPING_SPECIALIZATION(Setting::EFIndexV2, bool, bool, false, ".experimentalFeatures.indexV2"sv); + SETTINGMAPPING_SPECIALIZATION(Setting::EFIndexV2, bool, bool, true, ".experimentalFeatures.indexV2"sv); SETTINGMAPPING_SPECIALIZATION(Setting::EFConfigureExport, bool, bool, false, ".experimentalFeatures.configureExport"sv); // Telemetry SETTINGMAPPING_SPECIALIZATION(Setting::TelemetryDisable, bool, bool, false, ".telemetry.disable"sv); @@ -171,6 +171,7 @@ namespace AppInstaller::Settings SETTINGMAPPING_SPECIALIZATION(Setting::InstallerTypePreference, std::vector, std::vector, {}, ".installBehavior.preferences.installerTypes"sv); SETTINGMAPPING_SPECIALIZATION(Setting::InstallerTypeRequirement, std::vector, std::vector, {}, ".installBehavior.requirements.installerTypes"sv); SETTINGMAPPING_SPECIALIZATION(Setting::InstallSkipDependencies, bool, bool, false, ".installBehavior.skipDependencies"sv); + SETTINGMAPPING_SPECIALIZATION(Setting::ArchiveExtractionMethod, std::string, Archive::ExtractionMethod, Archive::ExtractionMethod::ShellApi, ".installBehavior.archiveExtractionMethod"sv); SETTINGMAPPING_SPECIALIZATION(Setting::DisableInstallNotes, bool, bool, false, ".installBehavior.disableInstallNotes"sv); SETTINGMAPPING_SPECIALIZATION(Setting::PortablePackageUserRoot, std::string, std::filesystem::path, {}, ".installBehavior.portablePackageUserRoot"sv); SETTINGMAPPING_SPECIALIZATION(Setting::PortablePackageMachineRoot, std::string, std::filesystem::path, {}, ".installBehavior.portablePackageMachineRoot"sv); diff --git a/src/AppInstallerCommonCore/UserSettings.cpp b/src/AppInstallerCommonCore/UserSettings.cpp index 95d39d3745..9654db02bb 100644 --- a/src/AppInstallerCommonCore/UserSettings.cpp +++ b/src/AppInstallerCommonCore/UserSettings.cpp @@ -262,7 +262,6 @@ namespace AppInstaller::Settings WINGET_VALIDATE_PASS_THROUGH(EFResume) WINGET_VALIDATE_PASS_THROUGH(EFConfiguration03) WINGET_VALIDATE_PASS_THROUGH(EFConfigureSelfElevation) - WINGET_VALIDATE_PASS_THROUGH(EFStoreDownload) WINGET_VALIDATE_PASS_THROUGH(EFIndexV2) WINGET_VALIDATE_PASS_THROUGH(EFConfigureExport) WINGET_VALIDATE_PASS_THROUGH(AnonymizePathForDisplay) @@ -289,6 +288,23 @@ namespace AppInstaller::Settings return ValidatePathValue(value); } + WINGET_VALIDATE_SIGNATURE(ArchiveExtractionMethod) + { + static constexpr std::string_view s_archiveExtractionMethod_shellApi = "shellApi"; + static constexpr std::string_view s_archiveExtractionMethod_tar = "tar"; + + if (Utility::CaseInsensitiveEquals(value, s_archiveExtractionMethod_tar)) + { + return Archive::ExtractionMethod::Tar; + } + else if (Utility::CaseInsensitiveEquals(value, s_archiveExtractionMethod_shellApi)) + { + return Archive::ExtractionMethod::ShellApi; + } + + return {}; + } + WINGET_VALIDATE_SIGNATURE(InstallArchitecturePreference) { std::vector archs; diff --git a/src/AppInstallerTestExeInstaller/main.cpp b/src/AppInstallerTestExeInstaller/main.cpp index aed19942bc..7ead74755d 100644 --- a/src/AppInstallerTestExeInstaller/main.cpp +++ b/src/AppInstallerTestExeInstaller/main.cpp @@ -16,6 +16,42 @@ std::wstring_view DefaultProductID = L"{A499DD5E-8DC5-4AD2-911A-BCD0263295E9}"; std::wstring_view DefaultDisplayName = L"AppInstallerTestExeInstaller"; std::wstring_view DefaultDisplayVersion = L"1.0.0.0"; +void WriteModifyRepairScript(std::wofstream& script, const path& repairCompletedTextFilePath, bool isModifyScript) { + std::wstring scriptName = isModifyScript ? L"Modify" : L"Uninstaller"; + script << L" if /I \"%%A\"==\"/repair\" (\n" + << L" ECHO " << scriptName << L" Repair operation for AppInstallerTestExeInstaller.exe completed successfully > \"" << repairCompletedTextFilePath.wstring() << "\"\n" + << L" ECHO " << scriptName << L" Repair operation for AppInstallerTestExeInstaller.exe completed successfully\n" + << L" EXIT /B 0\n" + << L" ) else if /I \"%%A\"==\"/r\" (\n" + << L" ECHO " << scriptName << L" Repair operation for AppInstallerTestExeInstaller.exe completed successfully > \"" << repairCompletedTextFilePath.wstring() << "\"\n" + << L" ECHO " << scriptName << L" Repair operation for AppInstallerTestExeInstaller.exe completed successfully\n" + << L" EXIT /B 0\n" + << L" )"; +} + +void WriteModifyUninstallScript(std::wofstream& script) { + script << L" else if /I \"%%A\"==\"/uninstall\" (\n" + << L" call UninstallTestExe.bat\n" + << L" EXIT /B 0\n" + << L" ) else if /I \"%%A\"==\"/X\" (\n" + << L" call UninstallTestExe.bat\n" + << L" EXIT /B 0\n" + << L" )\n"; +} + +void WriteModifyInvalidOperationScript(std::wofstream& script) { + script << L"echo Invalid operation\n" + << L"EXIT /B 1\n"; +} + +void WriteUninstallerScript(std::wofstream& uninstallerScript, const path& uninstallerOutputTextFilePath, const std::wstring& registryKey, const path& modifyScriptPath, const path& repairCompletedTextFilePath) { + uninstallerScript << "ECHO. >" << uninstallerOutputTextFilePath << "\n"; + uninstallerScript << "ECHO AppInstallerTestExeInstaller.exe uninstalled successfully.\n"; + uninstallerScript << "REG DELETE " << registryKey << " /f\n"; + uninstallerScript << "if exist \"" << modifyScriptPath.wstring() << "\" del \"" << modifyScriptPath.wstring() << "\"\n"; + uninstallerScript << "if exist \"" << repairCompletedTextFilePath.wstring() << "\" del \"" << repairCompletedTextFilePath.wstring() << "\"\n"; +} + path GenerateUninstaller(std::wostream& out, const path& installDirectory, const std::wstring& productID, bool useHKLM) { path uninstallerPath = installDirectory; @@ -26,6 +62,12 @@ path GenerateUninstaller(std::wostream& out, const path& installDirectory, const path uninstallerOutputTextFilePath = installDirectory; uninstallerOutputTextFilePath /= "TestExeUninstalled.txt"; + path repairCompletedTextFilePath = installDirectory; + repairCompletedTextFilePath /= "TestExeRepairCompleted.txt"; + + path modifyScriptPath = installDirectory; + modifyScriptPath /= "ModifyTestExe.bat"; + std::wstring registryKey{ useHKLM ? L"HKEY_LOCAL_MACHINE\\" : L"HKEY_CURRENT_USER\\" }; registryKey += RegistrySubkey; if (!productID.empty()) @@ -39,22 +81,49 @@ path GenerateUninstaller(std::wostream& out, const path& installDirectory, const std::wofstream uninstallerScript(uninstallerPath); uninstallerScript << "@echo off\n"; - uninstallerScript << "ECHO. >" << uninstallerOutputTextFilePath << "\n"; - uninstallerScript << "ECHO AppInstallerTestExeInstaller.exe uninstalled successfully.\n"; - uninstallerScript << "REG DELETE " << registryKey << " /f\n"; + uninstallerScript << L"for %%A in (%*) do (\n"; + WriteModifyRepairScript(uninstallerScript, repairCompletedTextFilePath, false /*isModifyScript*/); + uninstallerScript << ")\n"; + WriteUninstallerScript(uninstallerScript, uninstallerOutputTextFilePath, registryKey, modifyScriptPath, repairCompletedTextFilePath); + uninstallerScript.close(); return uninstallerPath; } +path GenerateModifyPath(const path& installDirectory) +{ + path modifyScriptPath = installDirectory; + modifyScriptPath /= "ModifyTestExe.bat"; + + path repairCompletedTextFilePath = installDirectory; + repairCompletedTextFilePath /= "TestExeRepairCompleted.txt"; + + std::wofstream modifyScript(modifyScriptPath); + + modifyScript << L"@echo off\n"; + modifyScript << L"for %%A in (%*) do (\n"; + WriteModifyRepairScript(modifyScript, repairCompletedTextFilePath, true /*isModifyScript*/); + WriteModifyUninstallScript(modifyScript); + modifyScript << L")\n"; + WriteModifyInvalidOperationScript(modifyScript); + + modifyScript.close(); + + return modifyScriptPath; +} + void WriteToUninstallRegistry( std::wostream& out, const std::wstring& productID, const path& uninstallerPath, + const path& modifyPath, const std::wstring& displayName, const std::wstring& displayVersion, const std::wstring& installLocation, - bool useHKLM) + bool useHKLM, + bool noRepair, + bool noModify) { HKEY hkey; LONG lReg; @@ -62,16 +131,18 @@ void WriteToUninstallRegistry( // String inputs to registry must be of wide char type const wchar_t* publisher = L"Microsoft Corporation"; std::wstring uninstallString = uninstallerPath.wstring(); + std::wstring modifyPathString = modifyPath.wstring(); + DWORD version = 1; std::wstring registryKey{ RegistrySubkey }; - if (!productID.empty()) + if (!productID.empty()) { registryKey += productID; out << "Product Code overridden to: " << registryKey << std::endl; } - else + else { registryKey += DefaultProductID; out << "Default Product Code used: " << registryKey << std::endl; @@ -128,6 +199,32 @@ void WriteToUninstallRegistry( out << "Failed to write InstallLocation value. Error Code: " << res << std::endl; } + // Set ModifyPath Property Value + if (LONG res = RegSetValueEx(hkey, L"ModifyPath", NULL, REG_EXPAND_SZ, (LPBYTE)modifyPath.c_str(), (DWORD)(modifyPath.wstring().length() + 1) * sizeof(wchar_t)) != ERROR_SUCCESS) + { + out << "Failed to write ModifyPath value. Error Code: " << res << std::endl; + } + + if(noRepair) + { + // Set NoRepair Property Value + DWORD noRepairValue = 1; + if (LONG res = RegSetValueEx(hkey, L"NoRepair", NULL, REG_DWORD, (LPBYTE)&noRepairValue, sizeof(noRepairValue)) != ERROR_SUCCESS) + { + out << "Failed to write NoRepair value. Error Code: " << res << std::endl; + } + } + + if(noModify) + { + // Set NoModify Property Value + DWORD noModifyValue = 1; + if (LONG res = RegSetValueEx(hkey, L"NoModify", NULL, REG_DWORD, (LPBYTE)&noModifyValue, sizeof(noModifyValue)) != ERROR_SUCCESS) + { + out << "Failed to write NoModify value. Error Code: " << res << std::endl; + } + } + out << "Write to registry key completed" << std::endl; } else { @@ -137,6 +234,80 @@ void WriteToUninstallRegistry( RegCloseKey(hkey); } +void WriteToFile(const path& filePath, const std::wstringstream& content) +{ + std::wofstream file(filePath, std::ofstream::out); + file << content.str(); + file.close(); +} + +void HandleRepairOperation(const std::wstring& productID, const std::wstringstream& outContent, bool useHKLM) +{ + path installDirectory; + + // Open the registry key + HKEY hKey; + std::wstring registryPath = std::wstring(RegistrySubkey); + + if (!productID.empty()) + { + registryPath += productID; + } + else + { + registryPath += DefaultProductID; + } + + LONG lReg = RegOpenKeyEx(useHKLM ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, registryPath.c_str(), 0, KEY_READ, &hKey); + + if (lReg == ERROR_SUCCESS) + { + // Query the value of the InstallLocation + wchar_t regInstallLocation[MAX_PATH]; + DWORD bufferSize = sizeof(regInstallLocation); + lReg = RegQueryValueEx(hKey, L"InstallLocation", NULL, NULL, (LPBYTE)regInstallLocation, &bufferSize); + + if (lReg == ERROR_SUCCESS) + { + // Convert the InstallLocation to a path + installDirectory = std::wstring(regInstallLocation); + } + + // Close the registry key + RegCloseKey(hKey); + + if(installDirectory.empty()) + { + // We could not find the install location, so we cannot repair + return; + } + } + else + { + // We could not find the uninstall APR registry key, so we cannot repair + return; + } + + path outFilePath = installDirectory; + outFilePath /= "TestExeRepairCompleted.txt"; + WriteToFile(outFilePath, outContent); +} + +void HandleInstallationOperation(std::wostream& out, const path& installDirectory, const std::wstringstream& outContent, const std::wstring& productCode, bool useHKLM, const std::wstring& displayName, const std::wstring& displayVersion, bool noRepair, bool noModify) +{ + path outFilePath = installDirectory; + outFilePath /= "TestExeInstalled.txt"; + + std::wofstream file(outFilePath, std::ofstream::out); + file << outContent.str(); + file.close(); + + path uninstallerPath = GenerateUninstaller(out, installDirectory, productCode, useHKLM); + path modifyPath = GenerateModifyPath(installDirectory); + + WriteToUninstallRegistry(out, productCode, uninstallerPath, modifyPath, displayName, displayVersion, installDirectory.wstring(), useHKLM, noRepair, noModify); +} + // The installer prints all args to an output file and writes to the Uninstall registry key int wmain(int argc, const wchar_t** argv) { @@ -150,6 +321,9 @@ int wmain(int argc, const wchar_t** argv) bool useHKLM = false; bool noOperation = false; int exitCode = 0; + bool isRepair = false; + bool noRepair = false; + bool noModify = false; // Output to cout by default, but swap to a file if requested std::wostream* out = &std::wcout; @@ -246,6 +420,23 @@ int wmain(int argc, const wchar_t** argv) } } + // Supports /repair and /r to emulate repair operation using installer. + else if (_wcsicmp(argv[i], L"/repair") == 0 + || _wcsicmp(argv[i], L"/r") == 0) + { + isRepair = true; + } + + else if (_wcsicmp(argv[i], L"/NoRepair") == 0) + { + noRepair = true; + } + + else if (_wcsicmp(argv[i], L"/NoModify") == 0) + { + noModify = true; + } + // Returns the success exit code to emulate being invoked by another caller. else if (_wcsicmp(argv[i], L"/NoOperation") == 0) { @@ -264,7 +455,7 @@ int wmain(int argc, const wchar_t** argv) execInfo.cbSize = sizeof(execInfo); execInfo.fMask = SEE_MASK_NOCLOSEPROCESS; execInfo.lpFile = aliasToExecute.c_str(); - + if (!aliasArguments.empty()) { execInfo.lpParameters = aliasArguments.c_str(); @@ -288,16 +479,16 @@ int wmain(int argc, const wchar_t** argv) } path outFilePath = installDirectory; - outFilePath /= "TestExeInstalled.txt"; - std::wofstream file(outFilePath, std::ofstream::out); - - file << outContent.str(); - - file.close(); - path uninstallerPath = GenerateUninstaller(*out, installDirectory, productCode, useHKLM); - - WriteToUninstallRegistry(*out, productCode, uninstallerPath, displayName, displayVersion, installDirectory.wstring(), useHKLM); + if (isRepair) + { + outContent << L"\nInstaller Repair operation for AppInstallerTestExeInstaller.exe completed successfully."; + HandleRepairOperation(productCode, outContent, useHKLM); + } + else + { + HandleInstallationOperation(*out, installDirectory, outContent, productCode, useHKLM, displayName, displayVersion, noRepair, noModify); + } return exitCode; } diff --git a/src/CertificateResources/StoreIntermediate1.cer b/src/CertificateResources/StoreIntermediate1.cer index 0673eabbe9..ab1eb8067a 100644 Binary files a/src/CertificateResources/StoreIntermediate1.cer and b/src/CertificateResources/StoreIntermediate1.cer differ diff --git a/src/CertificateResources/StoreLeaf1.cer b/src/CertificateResources/StoreLeaf1.cer index b4b2b64461..d42bb6a79e 100644 Binary files a/src/CertificateResources/StoreLeaf1.cer and b/src/CertificateResources/StoreLeaf1.cer differ diff --git a/src/CertificateResources/StoreLeaf2.cer b/src/CertificateResources/StoreLeaf2.cer index d42bb6a79e..c651194d54 100644 Binary files a/src/CertificateResources/StoreLeaf2.cer and b/src/CertificateResources/StoreLeaf2.cer differ diff --git a/src/WinGetServer/WinMain.cpp b/src/WinGetServer/WinMain.cpp index 11fe1a3749..43378f1fc6 100644 --- a/src/WinGetServer/WinMain.cpp +++ b/src/WinGetServer/WinMain.cpp @@ -16,6 +16,7 @@ #include #include #include +#include // Holds the wwinmain open until COM tells us there are no more server connections wil::unique_event _comServerExitEvent; @@ -100,6 +101,49 @@ extern "C" HRESULT CreateInstance( return S_OK; } +HRESULT InitializeComSecurity() +{ + wil::unique_hlocal_security_descriptor securityDescriptor; + // Allow Self, System, Built-in Admin and App Container access. 3 is COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL + std::string securityDescriptorString = "O:SYG:SYD:(A;;3;;;PS)(A;;3;;;SY)(A;;3;;;BA)(A;;3;;;AC)"; + RETURN_LAST_ERROR_IF(!ConvertStringSecurityDescriptorToSecurityDescriptorA(securityDescriptorString.c_str(), SDDL_REVISION_1, &securityDescriptor, nullptr)); + + // Make absolute security descriptor as CoInitializeSecurity required + SECURITY_DESCRIPTOR absoluteSecurityDescriptor; + DWORD securityDescriptorSize = sizeof(SECURITY_DESCRIPTOR); + + DWORD daclSize = 0; + DWORD saclSize = 0; + DWORD ownerSize = 0; + DWORD groupSize = 0; + + // Get required size + BOOL result = MakeAbsoluteSD(securityDescriptor.get(), &absoluteSecurityDescriptor, &securityDescriptorSize, nullptr, &daclSize, nullptr, &saclSize, nullptr, &ownerSize, nullptr, &groupSize); + RETURN_HR_IF_MSG(E_FAIL, result || GetLastError() != ERROR_INSUFFICIENT_BUFFER, "MakeAbsoluteSD failed to return buffer sizes"); + + std::vector dacl(daclSize); + std::vector sacl(saclSize); + std::vector owner(ownerSize); + std::vector group(groupSize); + + RETURN_LAST_ERROR_IF(!MakeAbsoluteSD(securityDescriptor.get(), &absoluteSecurityDescriptor, &securityDescriptorSize, (PACL)dacl.data(), &daclSize, (PACL)sacl.data(), &saclSize, (PACL)owner.data(), &ownerSize, (PACL)group.data(), &groupSize)); + + // Initialize com security + RETURN_IF_FAILED(CoInitializeSecurity( + &absoluteSecurityDescriptor, // Security descriptor + -1, // Authentication services count. -1 is let com choose. + nullptr, // Authentication services array + nullptr, // Reserved + RPC_C_AUTHN_LEVEL_DEFAULT, // Authentication level. + RPC_C_IMP_LEVEL_IDENTIFY, // Impersonation level. Identify client. + nullptr, // Authentication list + EOAC_NONE, // Additional capabilities + nullptr // Reserved + )); + + return S_OK; +} + int __stdcall wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPWSTR cmdLine, _In_ int) { wil::SetResultLoggingCallback(&WindowsPackageManagerServerWilResultLoggingCallback); @@ -115,8 +159,6 @@ int __stdcall wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPWSTR cmdLine, RETURN_IF_FAILED(globalOptions->Set(COMGLB_EXCEPTION_HANDLING, COMGLB_EXCEPTION_DONOT_HANDLE_ANY)); } - RETURN_IF_FAILED(WindowsPackageManagerServerInitialize()); - // Command line parsing int argc = 0; LPWSTR* argv = CommandLineToArgvW(cmdLine, &argc); @@ -130,18 +172,29 @@ int __stdcall wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPWSTR cmdLine, manualActivation = true; } + // For packaged com activation, initialize com security. + // For manual activation, leave as default. We'll not register objects for manual activation. + if (!manualActivation) + { + // This must be called after IGlobalOptions (fast rundown setting cannot be changed after CoInitializeSecurity) + // This must be called before WindowsPackageManagerServerInitialize (when setting the logs + // to Windows.Storage folders, automatic CoInitializeSecurity is triggered) + RETURN_IF_FAILED(InitializeComSecurity()); + } + + RETURN_IF_FAILED(WindowsPackageManagerServerInitialize()); + _comServerExitEvent.create(); RETURN_IF_FAILED(WindowsPackageManagerServerModuleCreate(&_releaseNotifier)); try { - // Register all the CoCreatableClassWrlCreatorMapInclude classes - RETURN_IF_FAILED(WindowsPackageManagerServerModuleRegister()); - // Manual reset event to notify the client that the server is available. wil::unique_event manualResetEvent; if (manualActivation) { + // For manual activation, do not register com objects + // so that only RPC channel can be used. HANDLE hMutex = NULL; hMutex = CreateMutex(NULL, FALSE, TEXT("WinGetServerMutex")); RETURN_LAST_ERROR_IF_NULL(hMutex); @@ -157,6 +210,11 @@ int __stdcall wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPWSTR cmdLine, manualResetEvent = CreateOrOpenServerStartEvent(); manualResetEvent.SetEvent(); } + else + { + // Register all the CoCreatableClassWrlCreatorMapInclude classes + RETURN_IF_FAILED(WindowsPackageManagerServerModuleRegister()); + } _comServerExitEvent.wait(); @@ -165,7 +223,10 @@ int __stdcall wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPWSTR cmdLine, manualResetEvent.reset(); } - RETURN_IF_FAILED(WindowsPackageManagerServerModuleUnregister()); + if (!manualActivation) + { + RETURN_IF_FAILED(WindowsPackageManagerServerModuleUnregister()); + } } CATCH_RETURN()