외부 위치로 패키징하여 패키지 ID 부여

기존 데스크톱 앱에 자체 설치 관리자가 있는 경우 패키지 ID의 이점을 활용하기 위해 변경할 필요가 거의 없습니다.

백그라운드 작업, 알림, 라이브 타일, 사용자 지정 컨텍스트 메뉴 확장 및 공유 대상을 비롯한 많은 Windows 확장성 기능은 런타임에 앱에 패키지 ID가 있는 경우에만 데스크톱 앱에서 사용할 수 있습니다. 운영 체제(OS)가 해당 API의 호출자를 식별할 수 있어야 하기 때문입니다. 패키지 ID가 필요한 기능을 참조하세요.

패키징된 앱만 런타임에 패키지 ID를 갖습니다. 패키징된 앱, 패키징되지 않은 앱 및 외부 위치로 패키징하는 앱의 정의는 배포 개요를 참조하세요.

  • Windows 10 버전 2004 및 이전 버전에서 패키지 ID를 앱에 부여하는 유일한 방법은 서명된 MSIX 패키지로 패키징하는 것입니다(코드에서 MSIX 패키지 빌드 참조). 이 경우 ID는 패키지 매니페스트에 지정되며, ID 등록은 매니페스트의 정보에 따라 MSIX 배포 파이프라인에서 처리됩니다. 패키지 매니페스트에서 참조되는 모든 콘텐츠는 MSIX 패키지 안에 있습니다.
  • 하지만 Windows 10 버전 2004부터는 외부 위치가 있는 패키지를 빌드하고 앱에 등록하기만 하면 앱에 패키지 ID를 부여할 수 있습니다. 이렇게 하면 패키지 앱, 특히 외부 위치가 있는 패키지 앱이 됩니다. 일부 데스크톱 앱은 아직 MSIX 패키지 내에 모든 콘텐츠가 표시될 준비가 되지 않았기 때문입니다. 따라서 이 지원을 통해 이러한 앱은 패키지 ID를 가질 수 있습니다. 따라서 패키지 ID가 필요한 Windows 확장성 기능을 사용할 수 있습니다. 자세한 배경 정보는 패키지가 없는 Win32 앱의 ID, 등록 및 활성화 블로그 게시물을 참조하세요.

외부 위치(앱에 패키지 ID를 부여)를 사용하여 패키지를 빌드하고 등록하려면 다음 단계를 수행하십시오.

  1. 외부 위치가 있는 패키지에 대한 패키지 매니페스트 만들기
  2. 외부 위치가 있는 패키지 빌드 및 서명
  3. 데스크톱 애플리케이션 매니페스트에 패키지 ID 메타데이터 추가
  4. 런타임에 외부 위치가 있는 패키지 등록

중요 개념

다음 기능을 사용하면 패키징되지 않은 데스크톱 앱에서 패키지 ID를 얻을 수 있습니다.

외부 위치가 있는 패키지

외부 위치가 있는 패키지에는 패키지 매니페스트가 포함되지만 다른 앱 이진 파일 및 콘텐츠는 없습니다. 외부 위치가 있는 패키지의 매니페스트는 미리 지정된 외부 위치의 패키지 외부에 있는 파일을 참조할 수 있습니다. 위에서 설명한 것과 같이 해당 지원을 사용하면 아직 모든 콘텐츠가 MSIX 패키지 내에 있을 준비가 되지 않은 앱이 패키지 ID가 필요한 Windows 확장성 기능을 사용할 수 있습니다.

참고

외부 위치가 있는 패키지를 사용하는 데스크톱 앱은 MSIX 패키지를 통해 완전히 배포되는 일부 이점을 받지 못합니다. 이러한 이점으로는 변조 방지, 잠긴 위치에 설치, 배포/실행/제거 시 OS의 전체 관리가 있습니다.

외부 콘텐츠 허용

외부 위치가 있는 패키지를 지원하기 위해 패키지 매니페스트 스키마는 이제 Properties 요소 아래에서 선택적 uap10:AllowExternalContent 요소를 지원합니다. 따라서 패키지 매니페스트가 디스크의 특정 위치에서 패키지 외부의 콘텐츠를 참조할 수 있습니다.

예를 들어 C:\Program Files\MyDesktopApp에 앱 실행 파일 및 기타 콘텐츠를 설치하는 기존 패키지되지 않은 데스크톱 앱이 있는 경우 매니페스트에 uap10:AllowExternalContent 요소가 포함된 외부 위치가 있는 패키지를 만들 수 있습니다. 앱 설치 프로세스 중에 또는 앱을 처음 실행할 때 외부 위치가 있는 패키지를 설치하고 C:\Program Files\MyDesktopApp\을 앱에서 사용할 외부 위치로 선언할 수 있습니다.

외부 위치를 사용하여 패키지에 대한 패키지 매니페스트 만들기

외부 위치가 있는 패키지를 만들려면 데스크톱 앱의 패키지 ID와 기타 필수 정보를 선언하는 패키지 매니페스트(AppxManifest.xml이라는 파일)부터 만들어야 합니다. 외부 위치가 있는 패키지의 패키지 매니페스트를 만드는 가장 쉬운 방법은 아래 예제를 사용하되, 스키마 참조를 사용하여 앱에 맞게 사용자 지정하는 것입니다.

패키지 매니페스트에 다음 항목이 포함되어야 합니다.

  • 데스크톱 앱의 ID 특성을 설명하는 Identity 요소
  • Properties 요소 아래의 uap10:AllowExternalContent 요소. 이 요소에는 true 값을 할당해야 합니다. 그러면 패키지 매니페스트가 디스크의 특정 위치에서 패키지 외부의 콘텐츠를 참조할 수 있습니다. 이후에 설치 관리자 또는 앱에서 실행되는 코드에서 외부 위치가 있는 패키지를 등록할 때 외부 위치의 경로를 지정할 것입니다. 매니페스트에서 참조하는 콘텐츠 중 패키지 자체에 없는 콘텐츠는 외부 위치에 설치해야 합니다.
  • TargetDeviceFamily 요소의 MinVersion 특성은 10.0.19000.0 이상 버전으로 설정해야 합니다.
  • Application 요소의 TrustLevel=mediumILRuntimeBehavior=Win32App 특성은 외부 위치가 있는 패키지와 연결된 데스크톱 앱이 레지스트리 및 파일 시스템 가상화와 기타 런타임 변경 없이 패키징되지 않은 표준 데스크톱 앱과 비슷하게 실행된다고 선언합니다.

다음 예제에서는 외부 위치가 있는 패키지 매니페스트(AppxManifest.xml)의 전체 내용을 보여 줍니다. 이 매니페스트에는 패키지 ID가 필요한 windows.sharetarget 확장이 포함되어 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<Package 
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2"
  xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
  xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
  xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
  xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
  IgnorableNamespaces="uap uap2 uap3 rescap desktop uap10">
  <Identity Name="ContosoPhotoStore" ProcessorArchitecture="x64" Publisher="CN=Contoso" Version="1.0.0.0" />
  <Properties>
    <DisplayName>ContosoPhotoStore</DisplayName>
    <PublisherDisplayName>Contoso</PublisherDisplayName>
    <Logo>Assets\storelogo.png</Logo>
    <uap10:AllowExternalContent>true</uap10:AllowExternalContent>
  </Properties>
  <Resources>
    <Resource Language="en-us" />
  </Resources>
  <Dependencies>
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19000.0" MaxVersionTested="10.0.19000.0" />
  </Dependencies>
  <Capabilities>
    <rescap:Capability Name="runFullTrust" />
    <rescap:Capability Name="unvirtualizedResources"/>
  </Capabilities>
  <Applications>
    <Application Id="ContosoPhotoStore" Executable="ContosoPhotoStore.exe" uap10:TrustLevel="mediumIL" uap10:RuntimeBehavior="win32App"> 
      <uap:VisualElements AppListEntry="none" DisplayName="Contoso PhotoStore" Description="Demonstrate photo app" BackgroundColor="transparent" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png">
        <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" Square310x310Logo="Assets\LargeTile.png" Square71x71Logo="Assets\SmallTile.png"></uap:DefaultTile>
        <uap:SplashScreen Image="Assets\SplashScreen.png" />
      </uap:VisualElements>
      <Extensions>
        <uap:Extension Category="windows.shareTarget">
          <uap:ShareTarget Description="Send to ContosoPhotoStore">
            <uap:SupportedFileTypes>
              <uap:FileType>.jpg</uap:FileType>
              <uap:FileType>.png</uap:FileType>
              <uap:FileType>.gif</uap:FileType>
            </uap:SupportedFileTypes>
            <uap:DataFormat>StorageItems</uap:DataFormat>
            <uap:DataFormat>Bitmap</uap:DataFormat>
          </uap:ShareTarget>
        </uap:Extension>
      </Extensions>
    </Application>
  </Applications>
</Package>

외부 위치로 패키지 빌드 및 서명

패키지 매니페스트를 만든 후 Windows SDK에서 MakeAppx.exe 도구 사용하여 외부 위치로 패키지를 빌드합니다. 외부 위치가 있는 패키지에는 매니페스트에서 참조되는 파일이 포함되지 않습니다. 때문에 패키지의 의미 체계 유효성 검사를 건너뛰는 /nv 옵션을 지정해야 합니다.

다음 예제에서는 명령줄에서 외부 위치로 패키지를 만드는 방법을 보여 줍니다.

MakeAppx.exe pack /d <path to directory that contains manifest> /p <output path>\MyPackage.msix /nv

외부 위치가 있는 패키지를 대상 컴퓨터에 성공적으로 설치하려면 대상 컴퓨터에서 신뢰할 수 있는 인증서로 스파스 패키지를 서명해야 합니다. Windows SDK에서 제공하는 SignTool을 사용하여 개발용으로 자체 서명된 새 인증서를 만들어 외부 위치가 있는 패키지에 서명할 수 있습니다.

다음 예제에서는 명령줄에서 외부 위치로 패키지에 서명하는 방법을 보여 줍니다.

SignTool.exe sign /fd SHA256 /a /f <path to certificate>\MyCertificate.pfx /p <certificate password> <path to package with external location>\MyPackage.msix

데스크톱 애플리케이션 매니페스트에 패키지 ID 메타데이터 추가

또한 데스크톱 앱에 병렬 애플리케이션 매니페스트를 포함해야 합니다. 애플리케이션 매니페스트(DPI 인식과 같은 항목을 선언하고 빌드 중에 앱의 .exe에 포함되는 파일)를 참조하세요. 해당 파일에 앱의 ID 특성을 선언하는 특성이 있는 msix 요소를 포함합니다. 이러한 특성의 값은 실행 파일이 시작될 때 OS에서 앱의 ID를 확인하는 데 사용됩니다.

다음 예제에서는 msix 요소가 포함된 병렬 애플리케이션 매니페스트를 보여 줍니다.

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="Contoso.PhotoStoreApp"/>
  <msix xmlns="urn:schemas-microsoft-com:msix.v1"
          publisher="CN=Contoso"
          packageName="ContosoPhotoStore"
          applicationId="ContosoPhotoStore"
        />
</assembly>

msix 요소의 특성은 패키지에 대한 패키지 매니페스트의 이러한 값과 외부 위치와 일치해야 합니다.

  • packageNamepublisher 특성은 각각 패키지 매니페스트에 있는 Identity 요소의 NamePublisher 특성과 일치해야 합니다.
  • applicationId 특성은 패키지 매니페스트에 있는 ApplicationId 특성과 일치해야 합니다.

런타임에 외부 위치에 패키지 등록

패키지 ID를 데스크톱 앱에 부여하려면 앱에서 PackageManager 클래스의 AddPackageByUriAsync 메서드를 사용하여 외부 위치가 있는 패키지를 등록해야 합니다. 이 메서드는 Windows 10 버전 2004부터 사용할 수 있습니다. 앱에 코드를 추가하여 앱이 처음으로 실행될 때 외부 위치가 있는 패키지를 등록할 수도 있고, 데스크톱 앱을 설치할 때 패키지를 등록하는 코드를 실행할 수도 있습니다. 예를 들어 MSI를 사용하여 데스크톱 앱을 설치하는 경우 사용자 지정 작업에서 이 코드를 실행할 수 있습니다.

다음 예제에서는 외부 위치에 패키지를 등록하는 방법을 보여 줍니다. 이 코드는 패키지 매니페스트가 패키지 외부의 콘텐츠를 참조할 수 있는 외부 위치의 경로를 포함하는 AddPackageOptions 개체를 만듭니다. 그런 다음 코드는 이 개체를 AddPackageByUriAsync 메서드에 전달하여 패키지를 외부 위치에 등록합니다. 또한 이 메서드는 외부 위치를 URI로 사용하여 서명된 패키지의 위치를 받습니다. 자세한 예제는 관련 샘플 앱의 StartUp.cs 코드 파일을 참조하세요(이 토픽의 샘플 앱 섹션 참조).

private static bool registerPackageWithExternalLocation(string externalLocation, string pkgPath)
{
    bool registration = false;
    try
    {
        Uri externalUri = new Uri(externalLocation);
        Uri packageUri = new Uri(pkgPath);

        Console.WriteLine("exe Location {0}", externalLocation);
        Console.WriteLine("msix Address {0}", pkgPath);

        Console.WriteLine("  exe Uri {0}", externalUri);
        Console.WriteLine("  msix Uri {0}", packageUri);

        PackageManager packageManager = new PackageManager();

        // Declare use of an external location
        var options = new AddPackageOptions();
        options.ExternalLocationUri = externalUri;

        Windows.Foundation.IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deploymentOperation = packageManager.AddPackageByUriAsync(packageUri, options);

        // Other progress and error-handling code omitted for brevity...
    }
}

샘플 앱

외부 위치가 있는 패키지를 사용하여 패키지 ID를 데스크톱 앱에 부여하는 방법을 보여주는 완전한 기능을 갖춘 샘플 앱은 SparsePackages 샘플을 참조하세요. 샘플을 빌드하고 실행하는 방법에 대한 자세한 내용은 패키지되지 않은 Win32 앱의 ID, 등록 및 활성화 블로그 게시물에서 제공됩니다.

이 샘플에는 다음이 포함됩니다.

  • PhotoStoreDemo라는 WPF 앱의 소스 코드. 시작하는 동안 앱에서는 ID를 사용하여 실행 중인지 확인합니다. ID를 사용하여 실행되지 않는 경우 외부 위치가 있는 패키지를 등록한 다음 앱을 다시 시작합니다. 이 단계를 수행하는 코드는 StartUp.cs를 참조하세요.
  • PhotoStoreDemo.exe.manifest라는 병렬 애플리케이션 매니페스트.
  • AppxManifest.xml이라는 패키지 매니페스트.