Skip to content

Fix Microsoft.AzureCLI 2.53.1 x64/x86 InstallerUrls#123641

Merged
microsoft-github-policy-service[bot] merged 2 commits intomicrosoft:masterfrom
halter73:patch-1
Oct 25, 2023
Merged

Fix Microsoft.AzureCLI 2.53.1 x64/x86 InstallerUrls#123641
microsoft-github-policy-service[bot] merged 2 commits intomicrosoft:masterfrom
halter73:patch-1

Conversation

@halter73
Copy link
Copy Markdown
Member

@halter73 halter73 commented Oct 24, 2023

This now matches what we did for 2.53.0.

I noticed this when I tried to winget upgrade --all and afterwards running winget upgrade still showed Microsoft.AzureCLI as out of date at 2.53.0. In turned out I had the 2.53.0 x64 and 2.53.1 x86 installed side by side.

This exact PR has been opened by community members for at least the last three versions:

@stephengillie @johnstep You probably want to look into fixing the @azclibot. Is that open source?

Microsoft Reviewers: Open in CodeFlow

This now matches what we did for 2.53.0.
@wingetbot
Copy link
Copy Markdown
Collaborator

Service Badge  Service Badge  

@wingetbot
Copy link
Copy Markdown
Collaborator

/AzurePipelines run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@mdanish-kh
Copy link
Copy Markdown
Contributor

@stephengillie @johnstep You probably want to look into fixing the @azclibot. Is that open source?

One more thing if the maintainer of the bot sees this PR:

  • The PR should also include adding ProductCodes in the installer metadata (it helps with package correlation for MSIs). Upgrade to the latest version of winget-create (if that's what being used in its automation) so that ProductCodes are added/updated automatically in new PRs

@wingetbot wingetbot added Azure-Pipeline-Passed Validation pipeline passed. There may still be manual validation requirements. Validation-Completed Validation passed labels Oct 24, 2023
@halter73
Copy link
Copy Markdown
Member Author

You probably want to look into fixing the @azclibot. Is that open source?

/cc @yonzhan @jiasli @bebound

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs-Attention This work item needs to be reviewed by a member of the core team. and removed Needs-Author-Feedback This needs a response from the author. labels Oct 24, 2023
@bebound
Copy link
Copy Markdown
Contributor

bebound commented Oct 25, 2023

I'm not familiar with winget, can we add this info after installation?
Winget installs the 64-bit CLI on 64-bit OS by default now. If you used the 32-bit CLI before, please follow this guide to migrate to 64-bit version: https://review.learn.microsoft.com/cli/azure/install-azure-cli-windows?branch=live&tabs=azure-cli#migrate-to-64-bit-azure-cli

@halter73
Copy link
Copy Markdown
Member Author

Is anyone going to approve or merge this? It leads to issues like what's described in Azure/azure-cli#27492 (comment) as long as anyone tries to upgrade the package. Every hour we wait, more and more people are likely running into problems.

I don't know enough about the packaging rules to know if we should be adding ProductCodes if the @azclibot automation doesn't account for it going forward, but I personally don't care either way. We should definitely fix the bot before this happens for a fifth time though.

@mdanish-kh
Copy link
Copy Markdown
Contributor

mdanish-kh commented Oct 25, 2023

@halter73 I'll approve this for merge if you please resolve the above review comments (#123641 (comment)). ProductCode is one of the fields WinGet client uses for package correlation and it's better to include it in the manifest for MSI packages.

The bot definitely needs fixing, but we should make sure that this version works as intended for majority of users and there aren't any package matching issues

@mdanish-kh
Copy link
Copy Markdown
Contributor

mdanish-kh commented Oct 25, 2023

[Policy] Needs-Author-Feedback

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs-Author-Feedback This needs a response from the author. and removed Needs-Author-Feedback This needs a response from the author. Needs-Attention This work item needs to be reviewed by a member of the core team. labels Oct 25, 2023
Co-authored-by: Muhammad Danish <mdanishkhdev@gmail.com>
auto-merge was automatically disabled October 25, 2023 21:16

Head branch was pushed to by a user without write access

@wingetbot
Copy link
Copy Markdown
Collaborator

/AzurePipelines run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@microsoft-github-policy-service microsoft-github-policy-service bot removed Validation-Completed Validation passed Azure-Pipeline-Passed Validation pipeline passed. There may still be manual validation requirements. Needs-Author-Feedback This needs a response from the author. labels Oct 25, 2023
@microsoft-github-policy-service microsoft-github-policy-service bot added the Moderator-Approved One of the Moderators has reviewed and approved this PR label Oct 25, 2023
@wingetbot wingetbot added Azure-Pipeline-Passed Validation pipeline passed. There may still be manual validation requirements. Validation-Completed Validation passed labels Oct 25, 2023
@microsoft-github-policy-service microsoft-github-policy-service bot merged commit 7831df4 into microsoft:master Oct 25, 2023
@wingetbot
Copy link
Copy Markdown
Collaborator

Publish pipeline succeeded for this Pull Request. Once you refresh your index, this change should be present.

@jiasli
Copy link
Copy Markdown
Member

jiasli commented Nov 16, 2023

@mdanish-kh, I have created issue Azure/azure-cli#27861 to track adding ProductCode to our manifest.

some PowerShell scripting to retrieve the ProductCode.

It seems all other methods require either installing the MSI or other dependencies. Could you please share more detail on this PowerShell scripting? I believe this script will be very helpful for all winget publishers.

I am also wondering if it is possible to programmatically acquire ProductCode during the build process.

@mdanish-kh
Copy link
Copy Markdown
Contributor

mdanish-kh commented Nov 16, 2023

Could you please share more detail on this PowerShell scripting?

@jiasli You can see how it's utilized in Tools/YamlCreate.ps1. I'll attach the relevant code for you here

Windows

Function Get-MSIProperty {
    Param
    (
      [Parameter(Mandatory = $true)]
      [string] $MSIPath,
      [Parameter(Mandatory = $true)]
      [string] $Parameter
    )
    try {
      $windowsInstaller = New-Object -com WindowsInstaller.Installer
      $database = $windowsInstaller.GetType().InvokeMember('OpenDatabase', 'InvokeMethod', $null, $windowsInstaller, @($MSIPath, 0))
      $view = $database.GetType().InvokeMember('OpenView', 'InvokeMethod', $null, $database, ("SELECT Value FROM Property WHERE Property = '$Parameter'"))
      $view.GetType().InvokeMember('Execute', 'InvokeMethod', $null, $view, $null)
      $record = $view.GetType().InvokeMember('Fetch', 'InvokeMethod', $null, $view, $null)
      $outputObject = $($record.GetType().InvokeMember('StringData', 'GetProperty', $null, $record, 1))
      $view.GetType().InvokeMember('Close', 'InvokeMethod', $null, $view, $null)
      [System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($view)
      [System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($database)
      [System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($windowsInstaller)
      [System.GC]::Collect()
      [System.GC]::WaitForPendingFinalizers()
      return $outputObject
    } catch {
      Write-Error -Message $_.ToString()
      break
    }
  }

$MSIFilePath = "$env:USERPROFILE\Downloads\azure-cli-2.53.1.msi"
$ProductCode = ([string](Get-MSIProperty -MSIPath $MSIFilePath -Parameter 'ProductCode') | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches.Value
Write-Host "ProductCode retrieved from $MSIFilePath : $ProductCode"

But looking at the issue, I believe you're looking for a Linux-based solution.

That is also mentioned in the script. You can do

Linux

$MSIFilePath = "/home/user/Downloads/azure-cli-2.53.1.msi"
([string](file $MSIFilePath) | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches.Value

Equivalent bash code

#!/bin/bash
MSIFilePath="/home/user/Downloads/azure-cli-2.53.1.msi"
echo $(file $MSIFilePath | grep -oP '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}')

Also, you may want to look at https://github.com/russellbanks/Komac, a community-developed tool (maintained by @russellbanks) for generating winget manifests. It's cross-platform, so you would be able to run it on Linux and it'll auto retrieve the product code for you, I believe.

@jiasli
Copy link
Copy Markdown
Member

jiasli commented Nov 17, 2023

Thank you @mdanish-kh, but the Revision Number provided by file command and Windows Properties GUI doesn't seem to match the result of Get-WmiObject Win32_Product. For example, for https://azcliprod.blob.core.windows.net/msi/azure-cli-2.54.0-x64.msi, the Revision Number is {8F41B266-5A95-4922-9144-C8BBE1BC8345}:

$ curl https://azcliprod.blob.core.windows.net/msi/azure-cli-2.54.0-x64.msi -O
$ file azure-cli-2.54.0-x64.msi
azure-cli-2.54.0-x64.msi: Composite Document File V2 Document, Little Endian, Os: Windows, Version 10.0, MSI Installer, Code page: 1252, Title: Installation Database, Subject: Microsoft Azure CLI (64-bit), Author: Microsoft Corporation, Keywords: Installer, Comments: This installer database contains the logic and data required to install Microsoft Azure CLI (64-bit)., Template: x64;1033, Revision Number: {8F41B266-5A95-4922-9144-C8BBE1BC8345}, Create Time/Date: Wed Nov  8 05:26:20 2023, Last Saved Time/Date: Wed Nov  8 05:26:20 2023, Number of Pages: 200, Number of Words: 2, Name of Creating Application: Windows Installer XML Toolset (3.10.4.4718), Security: 2

image

But after installing the MSI, Get-WmiObject Win32_Product shows IdentifyingNumber as {C56C2883-5C38-4789-B6BA-4D4B17440AE6}:

> Get-WmiObject Win32_Product | Sort-Object Name | Format-Table IdentifyingNumber, Name, Version -AutoSize
...
{C56C2883-5C38-4789-B6BA-4D4B17440AE6} Microsoft Azure CLI (64-bit)                                   2.54.0

The PowerShell script in #123641 (comment) also gives {C56C2883-5C38-4789-B6BA-4D4B17440AE6}:

> $ProductCode = ([string](Get-MSIProperty -MSIPath $MSIFilePath -Parameter 'ProductCode') | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches.Value
> Write-Host "ProductCode retrieved from $MSIFilePath : $ProductCode"
ProductCode retrieved from C:\Users\xxx\Downloads\azure-cli-2.54.0-x64.msi : {C56C2883-5C38-4789-B6BA-4D4B17440AE6}

Is there anything I am doing wrong?

@jiasli
Copy link
Copy Markdown
Member

jiasli commented Nov 17, 2023

BTW, it seems the script of Get-MSIProperty can't handle invalid file path. Even if I remove the try...catch... statement, the error is pretty vague:

> $MSIFilePath = "$env:USERPROFILE\Downloads\azure-cli-invalid.msi"
> Get-MSIProperty -MSIPath $MSIFilePath -Parameter 'ProductCode'
MethodInvocationException:
Line |
  11 |      $database = $windowsInstaller.GetType().InvokeMember('OpenDatabas …
     |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Exception calling "InvokeMember" with "5" argument(s): "OpenDatabase,DatabasePath,OpenMode"

@jiasli
Copy link
Copy Markdown
Member

jiasli commented Nov 17, 2023

Our MSI expert @heaths suggests using the MSI PowerShell module: https://www.powershellgallery.com/packages/MSI/3.3.4

> Install-Module MSI -Force
> (Get-MSIProperty -Property ProductCode -Path "$env:USERPROFILE\Downloads\azure-cli-2.54.0-x64.msi").Value
{C56C2883-5C38-4789-B6BA-4D4B17440AE6}

This is so far the easiest and most direct way I am aware of to retrieve ProductCode of an MSI.

@mdanish-kh
Copy link
Copy Markdown
Contributor

@jiasli - it looks like I didn't test the script thoroughly enough for the Linux part. Thanks for finding out the correct way, I should probably look to update the YamlCreate.ps1 script too with this finding

@mdanish-kh
Copy link
Copy Markdown
Contributor

mdanish-kh commented Nov 17, 2023

@jiasli Did you get it to work in a Linux environment? I could get the module to work on Windows but still no luck on Linux 👀

image

@jiasli
Copy link
Copy Markdown
Member

jiasli commented Nov 17, 2023

@mdanish-kh, you are welcome. I didn't try it on Linux either.

As described in Azure/azure-cli#27861, I think I am going to extract ProductCode while building the MSI on a Windows agent, save the ProductCode to an ADO artifact as the metadata of the MSI, then use it to build the manifest on a Linux agent.

However, I am not an expert on MSI or the MSI PowerShell module. I think you may report this issue / feature request to the source repo of MSI PowerShell module: https://github.com/heaths/psmsi

@heaths
Copy link
Copy Markdown
Member

heaths commented Nov 17, 2023

It's not going to work on a non-Windows platform because it uses Windows Installer APIs that are only on Windows. Can you not do this on a Windows agent? Otherwise, there is a Rust crate I've used in another project that actually implements the binary format (OLE docs + proprietary compression algorithms MSIs use). I could write a simple CLI that, given a path, extracts ProductCode or any other property if you really need this to work on a linux agent.

But the MSI module will never be cross-platform. That is WAY too much effort for no good reason because you can't use/install MSIs on other platforms, and much of the functionality is geared toward install/modify/uninstall and querying machine state.

@heaths
Copy link
Copy Markdown
Member

heaths commented Nov 17, 2023

Oh, look at that: I basically already wrote it: https://github.com/heaths/msigetprop-rs

image

The only difference is that this requires downloading the repo and installing Rust. You can download an x86_64 version here: https://github.com/heaths/msigetprop-rs/releases/download/v0.1.0/msigetprop-x86_64-unknown-linux-gnu.tar.gz

If you need another build, let me know or feel free to install Rust and build whatever you need yourself.

BTW: the --property parameter is optional and defaults to the ProductCode, but for maintainability and understanding I recommend including it in a pipeline so it's obvious to future maintainers what it's getting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Azure-Pipeline-Passed Validation pipeline passed. There may still be manual validation requirements. Moderator-Approved One of the Moderators has reviewed and approved this PR Publish-Pipeline-Succeeded Validation-Completed Validation passed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants