Adding Sourcelist for MSI Repair

Sometimes instead uninstalling MSI, a simple repair would be the best. When distributing your application the sources will become unavailable once the local cache will become empty. So the repair will not work. A solution would be to make the MSI available somewhere. But how making the MSI “knowing” the sources are available somewhere?

  1. In the registry, go to HKCR\installer\Products<product code of the product>\sourcelist\net
    You will notice where the Windows Installer will look to find the msi location. If the path is no longer existing then the repair will not work.
Function AddSourceList {
     <#
     .SYNOPSIS
     Ajoute un chemin au sourcelist d'un MSI
     .DESCRIPTION
     Ajoute un chemin au sourcelist d'un MSI
     .Parameter
     Str_MSIPathAndFile
     Donner un chemin complet d'un MSI incluant le nom du fichier. Le 
MSI doit se trouver dans le répertoire.
     .EXAMPLE
     AddSourcelist MSI
      #>
     [CmdletBinding()]
     param(
         [Parameter(Mandatory=$true)]
         [string]$Str_MSIPathAndFile
     )
     Begin {
             ## Get the name of this function and write header
             [string]${CmdletName} = $PSCmdlet.MyInvocation.MyCommand.Name
             Write-FunctionHeaderOrFooter -CmdletName ${CmdletName} -CmdletBoundParameters $PSBoundParameters -Header
         }
     Process {

         Try {

             $MSIPath=split-path $Str_MSIPathAndFile
             $ProductCode= Get-MsiTableProperty -Path $Str_MSIPathAndFile
             #$productcode='{09AAAB09-6DBA-4DD9-9865-54597D3FBCA8}'
             #$MSIPath='E:\Temp\Logiciels\Antidote 8\msi\druide'

             $Com_WI = New-Object -ComObject WindowsInstaller.Installer

             $codeInvokeMethod = {
                 $type = $this.gettype();
                 $index = $args.count - 1;
                 $methodargs = $args[1..$index]
                 $type.invokeMember($args[0], [System.Reflection.BindingFlags]::InvokeMethod, $null, $this, $methodargs)
             }
             $Com_WI = $Com_WI | Add-Member -MemberType ScriptMethod -Value $codeInvokeMethod -Name InvokeMethod -PassThru

             Try {
                 Write-log 'Ajout du Sourcelist $($MSIPath) au MSI $($Str_MSIPathAndFile) Product code $($productcode.productcode)'
                 $Com_WI.InvokeMethod('AddSource', '$($productcode.productcode)', '', '$($MSIPath)')
             }
             Catch {
                 Write-Log -Message "Failed to resolve registry path [$regKey]. `n$(Resolve-Error)" -Severity 3 -Source ${CmdletName}
                 Continue
             }
         }
         catch {
             Write-Log -Message "Failed to resolve registry path [$regKey]. `n$(Resolve-Error)" -Severity 3 -Source ${CmdletName}
             Continue
         }

     }
     End {
             Write-FunctionHeaderOrFooter -CmdletName ${CmdletName} -Footer
         }

}

After running that function, you will see a second path appeared in the Net section in the registry.
I would suggest PSADTK to include something like that in the toolkit :slight_smile:

Thanks,

1 Like

I have posted about this issue too.

2 Likes