Friday Fact: You can use Azure DevOps Pipeline to deploy your Windows App

Posted: February 28, 2025  |  Categories: DevOps

It’s Friday, and you know what that means—it’s time for a Friday Fact! Today, it’s going to be a completely different Friday fact than we are used to, but it’s still very true and valuable.

Do you know that it is possible to create an Azure DevOps Pipeline that deploys a Windows App to an Azure FileShare or Azure Blob Storage for download? You can!

The example we will provide here in this blog post will zip the App Files (.exe, .pdb, .dll, .config, etc.) so the end-user can download the App as a single file.

For this to happen, we need to create a DevOps pipeline that performs the following actions:

  • Triggered when changes to the WinApp Directory files are made;
  • Restore NuGets;
  • Builds the Windows App Solution;
  • Copies the Build Output Files to the Staging Directory;
  • Zip the contents (Optional Step);
  • Upload the Zip to FileShare;

Example of the YAML Pipeline

trigger:
  paths:
    include:
    - NordexWinApp/*

pool:
  vmImage: 'windows-latest'  # Use a Windows agent to build .NET Framework applications

variables:
  buildConfiguration: 'Release'
  artifactName: 'nordexapp.zip'
  fileSharePath: '\\cicdpocwinappfileshare.file.core.windows.net\winappfileshare'  # Replace with your actual file share path
  storageAccountName: 'cicdpocwinappstorage'  # Replace with your storage account name
  containerName: 'downloads'            # Replace with your blob container name

steps:
- script: |
    echo "Build Configuration: $(buildConfiguration)"
    echo "Binaries Directory: $(Build.BinariesDirectory)"
    echo "Work Dir: $(system.defaultworkingdirectory)"
    echo "Art Staging Directory: $(Build.ArtifactStagingDirectory)"
  displayName: 'Print Variables'

- task: NuGetToolInstaller@1
  displayName: 'Use NuGet 5.x'

- task: NuGetCommand@2
  displayName: 'Restore NuGet packages'
  inputs:
    restoreSolution: '**/*.sln'

- task: VSBuild@1
  displayName: 'Build solution'
  inputs:
    solution: '**/*.sln'
    msbuildArgs: '/p:Configuration=Release'
    platform: 'Any CPU'
    configuration: 'Release'

- task: CopyFiles@2
  displayName: 'Copy Files to Staging Directory'
  inputs:
    SourceFolder: '$(system.defaultworkingdirectory)\NordexWinApp\NordexWinApp\bin\$(buildConfiguration)'
    Contents: '**\*'
    TargetFolder: '$(Build.ArtifactStagingDirectory)'

- task: ArchiveFiles@2
  displayName: 'Zip build artifacts'
  inputs:
    rootFolderOrFile: '$(Build.ArtifactStagingDirectory)'
    includeRootFolder: true
    archiveType: 'zip'
    archiveFile: '$(Build.ArtifactStagingDirectory)/zip/$(artifactName)'

- task: WindowsMachineFileCopy@2
  displayName: 'Copy Files to File Share'
  inputs:
    MachineNames: 'cicdpocwinappfileshare.file.core.windows.net'
    SourcePath: '$(Build.ArtifactStagingDirectory)/zip/$(artifactName)'
    TargetPath: '$(fileSharePath)'
    CleanTargetBeforeCopy: true
    # Provide credentials if required by your file share for authentication
    AdminUserName: 'localhost\cicdpocwinappfileshare'
    AdminPassword: '$(FileshareAdminPassword)'

- task: AzureCLI@2
  displayName: 'Upload to Azure Blob Storage'
  inputs:
    azureSubscription: 'WinAppAzureConnection' # Service connection name
    scriptType: 'bash'
    scriptLocation: 'inlineScript'
    inlineScript: |
      az storage blob upload-batch \
        --account-name $(storageAccountName) \
        --destination $(containerName) \
        --source '$(Build.ArtifactStagingDirectory)/zip' \
        --pattern '*' # Upload all files

You can download the YAML Pipeline from GitHub here:

THIS RESOUCE IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND.

Conclusion

We can package a Windows App using an Azure DevOps Pipeline to be downloaded by your users.

To lazy to read? We’ve got you covered! Check out our video version of this content!

If you liked the content or found it helpful and want to help me write more content, you can buy (or help buy) my son a Star Wars Lego! 

Leave a Reply

Your email address will not be published. Required fields are marked *

turbo360

Back to Top