Part 3 - Create a Jenkins pipeline to deploy MSIX Desktop Apps: Packaging solutions outside VS

Published Feb 14 2022 06:38 AM 1,926 Views






In this third part, it is described how to setup Jenkins pipeline to package a Desktop App to MSIX.


The idea is to package a Java GUI solution developed on Visual Studio Code and package it with the Windows Application Packaging Project available for Visual Studio. Yes, there is still a dependency with Visual Studio. In the next post, part 4, it is described how to package a Desktop application without Visual Studio.



  1. Setup the Jenkins environment: install Jenkins and the required tools.
  2. Packaging a Visual Studio solution: for applications that use Visual Studio IDE, like Windows Forms and WPF.
  3. Packaging a solution developed outside Visual Studio: for applications developed outside VS, i.e., in others IDEs like Eclipse or Visual Studio Code, for Java GUI application.
  4. Packaging using the VB6RegistryTool: despite of the name, the tool can be used by any technology.


1. Java GUI Solution


In this section it will be demonstrated how to create the Java GUI solution with VS Code (you can use your preferred IDE) and then use the Windows Application Packaging Project on Visual Studio 2022 to generate the MSIX file.


In case you prefer, you can skip this step, since the solution is already available on jenkins_msix repo.


You can download VS Code here.


You need Java JDK installed. I am using OpenJDK 11 (Eclipse Temurin JDK more specifically). You can download it from the site or through this directly link.


More information about the steps describe here at Working with GUI applications in VS Code.


Create the Java GUI application


Before starting, make sure you have Maven installed. You can download Maven here.


On VS Code, click on Extensions (CTRL+Shift+X), search for extension pack for java and click on Install to install the extension:





In VS Code, open the Command Palette (Ctrl+Shift+P) and then select the command Maven: Create Maven Project:





Select the option maven-archetype-quickstart in the list:





Select the version 1.4:





Provide the group Id to your project and press Enter:





Provide the artifact Id and press Enter to continue:





Select the destination folder for the project.





You will be prompted to confirm the properties, just press ENTER:





To run the Java application, open the Explorer folders, navigate to demo\src\main\java\com\example\ file and press F5:





Ensure that no errors appear and that the Hello World! appears in the terminal console:





Replace the content by the following code that I extracted from the Create your First Java Frame using Visual Studio Code | Create Java GUI Forms using VS Code video:



package com.example;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class App extends JFrame{

    final private Font mainFont = new Font ("Segoe print", Font.BOLD, 18);
    JTextField tfFirstName, tfLastName;
    JLabel lbWelcome ;

    public void initialize(){

        //Form panel
        JLabel lbFirstName = new JLabel("First name");
        tfFirstName = new JTextField();

        JLabel lbLastName = new JLabel("Last name");
        tfLastName = new JTextField();

        JPanel formPanel = new JPanel();
        formPanel.setLayout(new GridLayout(4, 1, 5,5));
        formPanel.add (lbFirstName);
        formPanel.add (tfFirstName);
        formPanel.add (lbLastName);
        formPanel.add (tfLastName);

        JButton btnOK = new JButton("OK");
        btnOK.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e) {
                String firstName = tfFirstName.getText();
                String lastName = tfLastName.getText();
                lbWelcome.setText("Hello " + firstName + " " + lastName);


        JButton btnClear = new JButton("Clear");

        btnClear.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e) {


        JPanel buttonsPanel = new JPanel();
        buttonsPanel.setLayout(new GridLayout(1,2,5,5));
          lbWelcome = new JLabel();
          JPanel mainPanel = new JPanel();
          mainPanel.setLayout(new BorderLayout());
          mainPanel.setBackground(new Color(128, 128, 255));
          mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
          mainPanel.add(formPanel, BorderLayout.NORTH);
          mainPanel.add(lbWelcome, BorderLayout.CENTER);
          mainPanel.add(buttonsPanel, BorderLayout.SOUTH);

          setMinimumSize(new Dimension(300,400));


    public static void main(String[] args){

        App myFrame = new App();


Press F5 again and make sure that the following UI is displayed:





Navigate to the pom.xml file and replace its content by the following one:



<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="" xmlns:xsi=""


  <!-- FIXME change it to the project's website -->



                <executable>C:\Program Files\Eclipse Adoptium\jdk-\bin\javac</executable>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">


In the command line, navigate to the pom.xml level and run the following command:


mvn clean package





Navigate to the target folder and run the app to make sure that it is working:





Create the the Windows Application Packaging project

The next step is creating the Windows Application Packaging Project to package the Java GUI application.


Open Visual Studio, select Create a new project, select Windows Application Packaging Project and click Next:





Provide the project name MyJavaApp.Packaging and click Create:





We need to provide the Windows operating system target. Provide the build 19041 for the minimum and target version, as that is the Windows 10 SDK that is installed on our Jenkins environment, and click OK:





The solution will be created with the following structure:





Now, we need to include the Java application to the project.


Create the folder MyApp and add the myapp.exe:





Click on the Package.appxmanifest and press F7 to view the code:





Change the Executable value by MyApp\myapp.exe, as follows:





By now, if we can try to build our solution, we will receive the following exception, as the Windows Application Package Project requires a reference to an application:





Edit the MyJavaApp.Packaging project:





Include in the PropertyGroup element, which contains the TargetPlatformVersion, the EntryPointExe entry with the Java relative path to the executable:





Save the project and build the solution to make sure that there are not errors.


Build the application using MSBuild command line

Before creating a Jenkins pipeline, let's make sure that the MSBuild command line that will be used to build our application is working.


Open the Package Manager Console (you can press CTRL+Q and type package manager console):





Before running the following command, make sure to provide the MSBuild.exe PATH available in your environment:



&"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MSBuild.exe" /p:AppxBundlePlatforms=X86 /p:AppxBundle=Never /p:UapAppxPackageBuildMode=Sideloading  /p:AppxPackageSigningEnabled=false


In my case, the msix package file was generated on:







In the next section, it will demonstrate how to build a Jenkins Pipeline for this project.


2. Jenkins Pipeline

Pipeline is a series of tasks required to build, test, and deploy an application.


Create a new job

In the Jenkins Dashboard, click on the New Item option:





Provide the name Java GUI WAP MSIX for the job, select the Pipeline type of job and click on OK to proceed.





In the pipeline configuration page, check the GitHub Project to specify that this is a GitHub project and provide a GitHub URL:




Scroll down under the Pipeline section and change the definition to Pipeline script from SCM





Provide the Repository URL as well. Because this is a public project, we can skip the credentials:





Scroll-down to the Branches to build section, change the branch name to */main, the Jenkins script path to Jenkinsfile02 and click on Save:





Those actions were needed as we want to use the Jenkins pipeline file available in the main branch of the following repo:





Jenkins Pipeline File

In the previous section it was demonstrated how to setup the Jenkins pipeline to use a Jenkins script file available on our GitHub repository.

Follows the Jenkinsfile02 content:


pipeline {
  agent any

  tools {
        maven "Maven 3.8"
        jdk "JDK 11"

  environment {
    MSBUILD = "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Msbuild\\Current\\Bin\\MSBuild.exe"
    CONFIG = 'Release'
    PLATFORM = 'x86'

  stages {
              echo "PATH = ${M2_HOME}\\bin:${PATH}"
              echo "M2_HOME = C:\\Program Files (x86)\\apache-maven"
        stage('Build') {
            steps {
                dir("\\02_WAP\\demo") {
                bat 'mvn clean package'
              always {
                bat 'copy 02_WAP\\demo\\target\\myapp.exe 02_WAP\\MyJavaApp.Packaging\\MyJavaApp.Packaging\\MyApp /y'

    stage('Build MSIX package') {
      steps {
        bat "\"${MSBUILD}\" 02_WAP\\MyJavaApp.Packaging\\MyJavaApp.Packaging.sln /p:Configuration=${env.CONFIG} /p:AppxBundlePlatforms=${env.PLATFORM}  /p:AppxBundle=Never /p:UapAppxPackageBuildMode=Sideloading  /p:AppxPackageSigningEnabled=false"
          always {
           archiveArtifacts artifacts: '**/*.msix', followSymlinks: false


The pipeline directive is the complete script from beginning to end.


The agent directive instructs Jenkins to allocate an executor and workspace for the entire Pipeline. In our case, we are justing saying it can run on any agent. For example, it could be specified that it could run in a Docker container or run on a specific node.


The environment directive specifies a sequence of key-value pairs which will be defined as environment variables for all steps, or stage-specific steps, depending on where the environment directive is located within the Pipeline.


In our case, it is defined the variables MSBUILD that contains the MSBUILD path, the CONFIG with the value Release and PLATFORM with the value x86. Those variables will be used in the command line used to build our application.


The stages block contains on or more stage block, and each stage is going to have one or more steps. In our case, we have two stages that are used to build the Java application and later to package to MSIX.


The post section defines the additional step needed to keep the msix file artifact available in our build, as workspace is a temporary directory.


You can find more details about the Jenkins pipeline syntax in the post Getting started with Pipeline.


Switch back to Jenkins, click on Dashboard and click on the Java GUI WAP MSIX pipeline:





Click on Build Now to start the build:





The job starts by checking out the source code to next restore and build our solution as defined in the Jenkinsfile02.





After the build is done, the build icon will be green and the msix artifact will be available:





The next post demonstrate how to package an application that uses the VB6VirtualRegistry tool to package the application to MSIX. Despite the name, the tool can be used to package any Desktop application.



Version history
Last update:
‎Feb 14 2022 06:41 AM
Updated by: