사용자 지정 설치 작업
많은 게임이 치트 방지 및 기타 미들웨어를 사용합니다. 이러한 구성 요소는 일반적으로 사용자가 게임을 설치할 때 연계 설치됩니다. 사용자가 Microsoft Store를 통해 하나의 게임을 설치하고 다른 배포 채널을 통해 다른 게임을 설치할 수 있습니다. 두 게임이 같은 미들웨어 패키지를 연계 설치하면 플랫폼은 이 사이에 충돌이 없다고 말할 수 있습니다. 게임에는 패키지에 하나 이상의 임의 .exe 또는 .msi 파일이 포함될 수 있으며, 앱 설치 완료를 위해 이를 실행하도록 요청할 수 있습니다. 사용자 정의 설치 작업은 게임 치트 방지 소프트웨어나 기타 재배포 가능 미들웨어를 설치하기 위한 것입니다. 이러한 방식으로 개발자는 Microsoft Store에 제출된 MSIX뿐만 아니라 다른 배포 채널을 통해 제출된 .msi 또는 .exe 파일에서도 정확히 동일한 연계 설치 .exe 파일을 사용할 수 있습니다.
기존의 Win32 앱에서 공유 미들웨어는 일반적으로 독립적인 재배포 가능 파일을 통해 설치되며, 일반적으로 게임 자체에 번들로 묶을 수 있는 자동 압축 풀기 .exe 또는 .msi 형태를 취합니다. 프레임워크 패키지 형식의 Microsoft Store 앱은 종속성 모델의 경우, 프레임워크 패키지는 게임과 번들로 묶이지 않고 Microsoft Store를 통해 별도로 배포됩니다. 이 모델에서 소비하는 앱 매니페스트는 하나 이상의 프레임워크 패키지에 대한 의존성을 선언합니다. 그런 다음 Microsoft Store가 종속 요소의 설치를 연계 방식으로 처리합니다. 많은 재배포 가능 요소를 Microsoft Store에서 프레임워크 패키지로 사용할 수 있지만, 불가피하게 일부 재배포 가능 요소는 여전히 프레임워크 패키지로 사용할 수 없습니다. 이러한 패키지의 경우 해결 방법은 재배포 가능 요소를 게임 패키지 내에 번들로 묶는 것입니다.
.exe 또는 .msi 재배포 가능 파일을 포함하려면 MicrosoftGame.config 파일을 업데이트해야 합니다. 이러한 변경 사항에는 사용하려는 사용자 지정 작업의 유형과 설치 패키지 내의 위치를 선언하는 것이 포함됩니다.
모든 재배포 가능 요소는 패키지에 포함되어야 하며 MicrosoftGame.config에서 선언되어야 합니다. 선언 부분에는 실행 파일의 경로가 포함됩니다. 이 경로는 선언된 폴더 경로를 기준으로 한 상대 경로이므로, 패키지 자체의 루트 경로에 대한 상대 경로이기도 합니다. 선언에는 실행 파일을 실행할 때 전달해야 하는 명령줄 인수도 포함됩니다. 이는 MicrosoftGame.config 파일에 CustomInstallActions 요소를 넣음으로써 수행됩니다.
CustomInstallActions
CustomInstallActions 요소는 어떤 사용자 정의 설치 작업이 실행되어야 하며 언제 실행되어야 하는지를 지정하는 모든 정의를 담습니다. 이 확장의 인스턴스는 매니페스트에서 하나만 선언할 수 있습니다. 확장에는 CustomInstall이라는 하나의 최상위 요소가 있습니다. 여기에는 모든 사용자 정의 작업에 필요한 모든 파일이 담긴 폴더를 지정하는 문자열인 Folder라는 하나의 필수 속성이 있습니다. 이 폴더는 하위 폴더를 포함할 수 있습니다. 개발자는 패키지에 사용자 지정 작업 실행 파일이 사용하는 모든 요소를 포함시키고, 이러한 요소가 적절한 로드 경로에 있도록 해야 합니다.
참고 항목
지정된 폴더에 다른 어떤 주 게임 실행 파일이나 기타 파일을 넣어서는 안 됩니다. 이는 사용자 지정 설치 파일만을 위한 것입니다.
사용자 지정 설치 확장 내에서 앱은 InstallAction, RepairAction, UninstallAction의 하위 요소를 선언할 수 있습니다. 모두 선택 사항이므로 원하는 것을 선언하거나 아무 것도 선언하지 않아도 됩니다. 이러한 각 요소 내에서 하나 이상의 InstallAction, RepairAction 또는 UninstallAction 하위 항목을 지정할 수 있습니다. 플랫폼은 지정된 명령줄 인수를 사용하여 지정된 순서대로 지정된 작업을 실행합니다.
작업 유형
사용자 지정 설치 확장의 세 하위 노드는 특정 사용자 지정 작업의 시기를 지시합니다. 사용자 지정 설치 작업에는 세 가지 유형이 있습니다.
- 설치 작업: 앱의 첫 시작 전에 플랫폼에서 실행하는 작업입니다.
- 복구 작업: 사용자가 복구 또는 초기화를 선택할 때 실행되는 작업입니다.
- 제거 작업: 사용자가 앱을 제거할 때 실행되는 작업입니다.
보통 일부 재배포 가능 요소를 InstallAction으로 연계 설치하도록 지정한 다음 UninstallAction으로 제거하도록 지정합니다. 그러나 설치를 선택했지만 그에 맞는 제거 기능이 없는 경우가 있습니다. 이 상황에서는 앱이 무언가를 설치하지만 제거될 때 이를 그대로 남깁니다. 다른 앱과 공유하는 재배포 가능 요소라면 합당한 일입니다. 마찬가지로, RepairAction은 단순히 InstallAction에 지정된 실행 파일을 다시 선언하는 것일 수 있으며 일반적인 경우입니다. 설치/복구/제거에서 수행하는 각 작업에는 다른 실행 파일이 필요할 수 있습니다. 스키마는 매우 유연합니다. 플랫폼은 아무 작업도 수행할 필요가 없습니다. 각 게임에 적합한 동작을 자유롭게 구성할 수 있습니다.
Important
설치 또는 복구 작업이 실행된 경우에만 제거 작업이 실행됩니다. 시스템에서는 Name 속성을 사용하여 이 상태를 추적합니다. 따라서 설치/복구/제거 작업은 동일한 Name을 포함해야 합니다.
작업의 일부
파일
각 작업에서 실행할 파일을 지정해야 하며, 이는 패키지에 있어야 합니다. 경로를 지정하면 CustomInstallActionsFolder 경로에 대해 명시적으로 상대 경로인 것으로 간주됩니다. 절대 경로는 지정할 수 없습니다. 경로는 백슬래시(\)로 시작해서는 안 됩니다.
이름
작업의 Name을 지정해야 합니다. 이 Name은 상위 Actions 노드 내에서 고유해야 하지만, 서로 다른 Actions 노드 사이에서 공유할 수 있습니다. 예를 들어 InstallAction 및 RepairAction 모두에서 File="MySetup.exe", Name="abc123"으로 지정할 수 있습니다. 반면, 두 개의 InstallAction 요소가 있다면 각 요소에는 서로 다른 Name이 있어야 합니다. 실행 파일이 변경되지 않는 한 패키지 버전에서 동일한 실행 파일에 동일한 Name을 사용해야 합니다. Name은 작업의 ID로 사용되며, 이를 통해 플랫폼이 성공적으로 실행된 작업과 이 작업이 업데이트된 패키지를 위해 실행되어야 하는지 추적할 수 있습니다. 업데이트된 패키지가 이미 성공적으로 실행된 Name을 사용한 사용자 지정 작업을 지정하면, 플랫폼이 업데이트할 때 이 작업을 건너뜁니다.
Important
인수 목록의 차이가 ID의 차이를 나타내지는 않습니다. 업데이트된 패키지에서 다른 인수로 동일한 실행 파일을 실행하려면 다른 Name을 제공해야 합니다. 선언된 Name을 적절하게 구성하고 버전을 추적하는 것은 개발자의 책임입니다.
인수
각 사용자 정의 설치 작업에는 세 번째 요소인 argument가 있습니다. 이 요소로 재배포 가능 요소의 명령을 실행하는 데 필요한 모든 인수를 넣을 수 있습니다.
사용자 지정 작업 사용법
치트 방지 소프트웨어를 설치하려면 일반적으로 사용자가 관리자 권한을 가져야 합니다. 사용자 지정 작업은 매우 강력한 기능이기 때문입니다. 사용자 지정 작업이 있는 모든 패키지에는 관리자 권한이 필요합니다. 관리자 권한으로 실행되는 작업의 경우 Windows는 앱이 첫 번째 실행될 때 UAC(사용자 계정 컨트롤) 메시지를 표시하도록 합니다. 사용자 워크플로는 다음과 같습니다.
- 게임의 Microsoft Store 페이지에는 게임의 요건이 표시됩니다. 여기에는 설치를 위해 관리자 권한이 필요한지, 설치 시 사용자 정의 작업을 실행하는지, 사용자에게 이러한 작업이 어떠한 영향을 미치는지가 포함됩니다. 이 정보는 사용자가 충분한 정보를 바탕으로 게임 구매를 결정하도록 제공하는 것입니다.
- 사용자는 제약 조건과 미치는 영향에 만족할 경우 설치를 클릭합니다.
- 플랫폼은 패키지에 사용자 지정 작업이 포함되어 있음을 감지하고, 사용자 지정 작업을 실행해야 한다는 사실을 기록합니다. 그러나 초기 설치 단계에서는 사용자 지정 작업을 실행하지 않습니다. 대신 사용자가 게임을 처음 시작할 때 사용자 지정 작업이 실행됩니다.
- 게임을 처음 시작할 때, 플랫폼이 사용자 정의 작업을 실행하려고 시도할 때 UAC 메시지가 표시됩니다. 그러면 사용자는 관리자 자격 증명을 입력하고 권한 상승을 수락해야 합니다. 패키지에 여러 사용자 지정 작업이 포함되어 있더라도 사용자는 하나의 UAC 메시지만 받습니다. 사용자 지정 작업 중 하나가 변경되지 않는 한 업데이트에 대한 추가 UAC 메시지는 표시되지 않습니다. 게임이 제거되면 UAC 프롬프트가 표시됩니다.
모든 사용자 정의 작업은 성공 후 제로 복귀합니다. 사용자 지정 작업이 실패하면 플랫폼은 나머지 사용자 지정 작업을 계속 실행하며, 앱도 계속 실행합니다. 각 후속 앱이 시작될 때 플랫폼은 성공할 때까지 실패/완전하지 않은 사용자 정의 작업을 계속 시도합니다. 사용자 정의 작업이 실패하여 앱이 올바르게 작동하지 않으면 사용자는 항상 앱의 설정 페이지로 이동하여 복구 또는 초기화를 선택할 수 있습니다. 복구/초기화는 게임 파일을 다시 다운로드하지 않습니다. 단지 패키지를 다시 등록합니다. 실패했거나 실행되지 않은 사용자 지정 작업을 등록하여 다시 실행합니다. 성공 시 제로 복귀하지 않는 사용자 지정 설치 프로그램이 있는 경우 한 가지 방법은 성공 시 제로 복귀하는, 직접 만든 실행 파일로 이 설치 프로그램을 래핑하는 것입니다.
Microsoft Store 정책에는 연계 실행될 수 있는 미들웨어/재배포 가능 소프트웨어에 대한 지침이 있습니다. 간략히 보면 연계 설치는 게임을 실행하는 데 필요한 공유 소프트웨어를 위한 것입니다. 관련 없는 앱이나 다른 소프트웨어를 설치하려는 것이 아닙니다.
참고 항목
사용자 지정 설치 작업은 메인 MSIXVC 패키지 내에서만 지원됩니다. 프레임워크 패키지, 선택적 패키지, 수정 패키지 또는 기타 유형의 패키지에서는 지원되지 않습니다.
사용자 지정 설치 작업으로 MSI 실행
MSI의 경우 MSI의 이름을 제공하면 플랫폼은 이 파일에서 msiexec.exe를 실행합니다. /i, /f 또는 /x 인수는 선언된 동작(설치, 복구 또는 제거)으로부터 유추되므로 이런 인수는 사용해서는 안 됩니다. /f 스위치에는 옵션을 넣을 수 없습니다. 그러나 msiexec.exe에 일반적으로 사용되는 다른 선택적 인수는 사용할 수 있습니다. 이는 명령줄 인수가 제한되는 유일한 시나리오입니다. MSI가 아닌 작업의 경우 원하는 인수를 사용할 수 있습니다. MSI가 아닌 작업의 경우 플랫폼에서는 인수를 구문 분석하거나 유효성을 검사하지 않습니다. 플랫폼은 실행 파일로 전달하기만 합니다. 올바른 인수를 사용하는 것은 개발자의 책임입니다.
MST(MSI 변환)에 대한 직접적인 지원은 없습니다. MSI/MST에 대한 요건이 있다면, MSI를 실행하고 MST를 적용하기 위해 msiexec를 래핑하는 독립적인 .exe를 만드는 것이 가능한 한 가지 방법일 수 있습니다.
게임 구성 파일 변경
다음 XML 예제는 사용자 정의 설치 작업을 허용하기 위해 MicrosoftGame.config 파일에 적절한 내용을 추가한 것입니다.
<!-- Include CustomInstallActions element. Declare InstallActions,
RepairActions and/or UninstallActions as appropriate for your app. -->
<DesktopRegistration>
<!-- ... -->
<!-- Other entries omitted for brevity. -->
<!-- ... -->
<CustomInstallActions>
<Folder>MyInstallers</Folder>
<InstallActionList>
<InstallAction File="CustomInstaller.exe" Name="TaskName" Arguments="/silent /example" />
</InstallActionList>
<RepairActionList>
<RepairAction File="CustomInstaller.exe" Name="TaskName" Arguments="/silent /repair" />
</RepairActionList>
<UninstallActionList>
<UninstallAction File="CustomInstaller.exe" Name="TaskName" Arguments="/silent /remove" />
</UninstallActionList>
</CustomInstallActions>
</DesktopRegistration>
위 예제에서 모든 실행 파일과 종속 요소는 개발자가 패키지 루트에서 지정한 MyInstallers 폴더에 있어야 합니다. 해당 폴더 내에서 앱에 적합한 하위 폴더 구조를 만들 수 있습니다. 이 예제에서 MySetup.exe의 경로는 <package root>\MyInstallers\Banana\MySetup.exe가 될 것입니다. 실행 파일에 종속 요소가 있을 경우 적절한 폴더나 하위 폴더에 배치해야 합니다.
다음은 게임 개발자가 여러 버전에 걸쳐 매니페스트를 만드는 방법을 보여줍니다.
<!-- v1 of the game. -->
<CustomInstallActions>
<Folder>MyInstallers</Folder>
<InstallActionList>
<InstallAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /example" />
<!-- The platform records the successful install of TaskName_1. -->
</InstallActionList>
<RepairActionList>
<RepairAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /repair" />
</RepairActionList>
<UninstallActionList>
<UninstallAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /remove" />
<!-- The platform records the successful uninstall of TaskName_1. -->
</UninstallActionList>
</CustomInstallActions>
<!-- v2 of the game, where the redist is NOT updated. -->
<CustomInstallActions>
<Folder>MyInstallers</Folder>
<InstallActionList>
<InstallAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /example" />
<!-- The platform detects that we've already installed TaskName_1, so we don't
run it again. Therefore, there's no UAC prompt. -->
</InstallActionList>
<RepairActionList>
<RepairAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /repair" />
</RepairActionList>
<UninstallActionList>
<UninstallAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /remove" />
</UninstallActionList>
</CustomInstallActions>
<!-- v2 of the game, where a redist IS updated. -->
<CustomInstallActions>
<Folder>MyInstallers</Folder>
<InstallActionList>
<InstallAction File="CustomInstaller.exe" Name="TaskName_2" Arguments="/silent /example" />
<!-- The platform detects that we haven't previously run TaskName_2, so we need
to run it this time and show a UAC prompt. -->
</InstallActionList>
<RepairActionList>
<RepairAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /repair" />
</RepairActionList>
<UninstallActionList>
<UninstallAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /remove" />
</UninstallActionList>
</CustomInstallActions>