How to uninstall with msiexec using product id guid without .msi file present

187,785

Solution 1

Thanks all for the help - turns out it was a WiX issue.

When the Product ID GUID was left explicit & hardcoded as in the question, the resulting .msi had no ProductCode property but a Product ID property instead when inspected with orca.

Once I changed the GUID to '*' to auto-generate, the ProductCode showed up and all works fine with syntax confirmed by the other answers.

Solution 2

"Reference-Style" Answer: This is an alternative answer to the one below with several different options shown. Uninstalling an MSI file from the command line without using msiexec.


The command you specify is correct: msiexec /x {A4BFF20C-A21E-4720-88E5-79D5A5AEB2E8}

If you get "This action is only valid for products that are currently installed" you have used an unrecognized product or package code, and you must find the right one. Often this can be caused by using an erroneous package code instead of a product code to uninstall - a package code changes with every rebuild of an MSI file, and is the only guid you see when you view an msi file's property page. It should work for uninstall, provided you use the right one. No room for error. If you want to find the product code instead, you need to open the MSI. The product code is found in the Property table.


UPDATE, Jan 2018:

With all the registry redirects going on, I am not sure the below registry-based approach is a viable option anymore. I haven't checked properly because I now rely on the following approach using PowerShell: How can I find the product GUID of an installed MSI setup?

Also check this reference-style answer describing different ways to uninstall an MSI package and ways to determine what product version you have installed: Uninstalling an MSI file from the command line without using msiexec


Legacy, registry option:

You can also find the product code by perusing the registry from this base key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall . Press F3 and search for your product name. (If it's a 32-bit installer on a 64-bit machine, it might be under HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall instead).

Legacy, PowerShell option: (largely similar to the new, linked answer above)

Finally, you can find the product code by using PowerShell:

get-wmiobject Win32_Product | Format-Table IdentifyingNumber, Name

enter image description here

Similar post: WiX - Doing a major upgrade on a multi instance install (screenshot of how to find the product code in the MSI).

Solution 3

msiexec.exe /x "{588A9A11-1E20-4B91-8817-2D36ACBBBF9F}" /q 

Solution 4

The good thing is, this one is really easily and deterministically to analyze: Either, the msi package is really not installed on the system or you're doing something wrong. Of course the correct call is:

msiexec /x {A4BFF20C-A21E-4720-88E5-79D5A5AEB2E8}

(Admin rights needed of course- With curly braces without any quotes here- quotes are only needed, if paths or values with blank are specified in the commandline.)
If the message is: "This action is only valid for products that are currently installed", then this is true. Either the package with this ProductCode is not installed or there is a typo.

To verify where the fault is:

  1. First try to right click on the (probably) installed .msi file itself. You will see (besides "Install" and "Repair") an Uninstall entry. Click on that.
    a) If that uninstall works, your msi has another ProductCode than you expect (maybe you have the wrong WiX source or your build has dynamic logging where the ProductCode changes).
    b) If that uninstall gives the same "...only valid for products already installed" the package is not installed (which is obviously a precondition to be able to uninstall it).

  2. If 1.a) was the case, you can look for the correct ProductCode of your package, if you open your msi file with Orca, Insted or another editor/tool. Just google for them. Look there in the table with the name "Property" and search for the string "ProductCode" in the first column. In the second column there is the correct value.

There are no other possibilities.

Just a suggestion for the used commandline: I would add at least the "/qb" for a simple progress bar or "/qn" parameter (the latter for complete silent uninstall, but makes only sense if you are sure it works).

Solution 5

There's no reason for the {} command not to work. The semi-obvious questions are:

  1. You are sure that the product is actually installed! There's something in ARP/Programs&Features.

  2. The original install is in fact visible in the current context. It looks as if it might have been a per-user install, and if you are logged in as somebody else now then it won't know about it - you'd need to log in under the same account as the original install.

  3. If the \windows\installer directory was damaged the cached file would be missing, and that's used to do the uninstall.

Share:
187,785
snoweagle
Author by

snoweagle

Updated on June 13, 2020

Comments

  • snoweagle
    snoweagle almost 4 years

    I'm trying to automate the uninstallation of packages created using WiX for the purposes of changing the installed software stack & configuration without reprovisioning a whole OS. Eventually I'll use powershell scripting to do this but at the moment I can't seem to get my test package to uninstall interactively with cmd.

    If I run:

    msiexec /x '{A4BFF20C-A21E-4720-88E5-79D5A5AEB2E8}'

    msiexec /x A4BFF20C-A21E-4720-88E5-79D5A5AEB2E8

    I get:

    "The installation package could not be opened. Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer Package."

    If I run: msiexec /x {A4BFF20C-A21E-4720-88E5-79D5A5AEB2E8}

    I get:

    "This action is only valid for products that are currently installed"

    I've looked at the windows installer guide, the WiX documentation, msiexec documentation and used orca to go over the .msi myself but I've not really found anything that gives a clear picture of how an uninstall is processed. Is the .msi file required and if not then why does windows installer seem to think it is when given a GUID?

    The WiX code for the .msi installer is:

    <?xml version='1.0' encoding='windows-1252'?>
    <Wix xmlns='htp://schemas.microsoft.com/wix/2006/wi' >
    
      <!--DO NOT COPY / PASTE THE PRODUCT ID GUID BELOW TO YOUR OWN WIX SOURCE -->
    
      <Product Id='A4BFF20C-A21E-4720-88E5-79D5A5AEB2E8' Language='2057' 
               Manufacturer='COMPANYNAME IT-Operations' 
               Name='COMPANYNAMEServerListener' Version='1.0.0' 
               UpgradeCode='PUT-GUID-HERE'>
    
       <Package Id='*' Manufacturer='COMPANYNAME IT-Operations' Compressed='yes' />
       <Media Id='1' Cabinet='COMPANYNAMEServerListener.cab' EmbedCab='yes' />
    
        <Directory Id='TARGETDIR' Name='SourceDir'>
          <Directory Id='ProgramFilesFolder' Name='PFiles'>
          <Directory Id='COMPANYNAME' Name='COMPANYNAME'>
            <Directory Id='INSTALLDIR' Name='COMPANYNAMEServerListener'>
            <Component Id='MainExecutable' Guid='*' >
              <File Id='COMPANYNAMEServerListener.exe' 
                    Source='COMPANYNAMEServerListener.exe' Vital='yes' 
                    KeyPath='yes' />
              <ServiceInstall 
                Id='COMPANYNAMEServerListenerInstall'
                DisplayName='COMPANYNAMEServerListener'
                Description='Accepts and discards TCP connections on port 28028 to indicate that this server is alive and ready to be controlled'
                Name='COMPANYNAMEServerListener'
                Account='NT AUTHORITY\LocalService'
                ErrorControl='normal'
                Start='auto'
                Type='ownProcess'
                Vital='yes'           
              >
                <ServiceDependency Id='tcpip'/>
              </ServiceInstall>
              <ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall" Name="COMPANYNAMEServerListener" Wait="yes" />
            </Component>
            </Directory>
            </Directory>
          </Directory>
          </Directory>
    
        <Feature Id='Complete' Level='1' >
          <ComponentRef Id='MainExecutable' />
        </Feature>
    
        <CustomTable Id ="COMPANYNAMEMetadata">
          <Column Id="Property" Type="string" Category="Identifier" PrimaryKey="yes"/>
          <Column Id="Value" Type="string"/>
          <Row>
          <Data Column="Property">InstallString</Data>
          <Data Column="Value">/qn</Data>
          </Row>
        </CustomTable>
    
    
      </Product>
    </Wix>
    
  • Stein Åsmul
    Stein Åsmul over 10 years
    A final note: you must never hard code a package code in an MSI file for reuse between builds. This will force different MSI files to be treated by Windows Installer as the same file by definition - even if they have different content - this cause a lot of mysterious problems.
  • Stein Åsmul
    Stein Åsmul about 10 years
    Thanks for sharing the fix - another of those quirky problems that result from the flexibility of WIX.
  • Henrik
    Henrik over 9 years
    That doesn't make any sense, according to: stackoverflow.com/questions/10330534/… and Nick Ramirez WiX 3.6 A Developers Guide to WIX, the product Id attribute is the product code. also I cannot reproduce the bug here..
  • Jason
    Jason over 8 years
    I found the uninstall keys to be unreliable, however the powershell command was a big help! One issue though, long names are being truncated, even when outputting to a log file... is there a way to have it display the entire name?
  • Nico Haase
    Nico Haase over 6 years
    Can you give more context to your answer?
  • bitdisaster
    bitdisaster over 5 years
    The reason is you calling it form PowerShell. PowerShell you need the quotation so the product id is treated as a string.
  • Daz
    Daz about 3 years
    Be careful with /q or /qn - if the msi deems a restart necessary it will just restart the computer without prompt or warning. I would use /q /norestart