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.
<code>Function AddSourceList {
     &lt;#
     .SYNOPSIS
     Ajoute un chemin au sourcelist d&#039;un MSI
     .DESCRIPTION
     Ajoute un chemin au sourcelist d&#039;un MSI
     .Parameter
     Str_MSIPathAndFile
     Donner un chemin complet d&#039;un MSI incluant le nom du fichier. Le 
MSI doit se trouver dans le répertoire.
     .EXAMPLE
     AddSourcelist MSI
      #&gt;
     [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=&#039;{09AAAB09-6DBA-4DD9-9865-54597D3FBCA8}&#039;
             #$MSIPath=&#039;E:\Temp\Logiciels\Antidote 8\msi\druide&#039;

             $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 &quot;Ajout du Sourcelist $($MSIPath) au MSI $($Str_MSIPathAndFile) Product code $($productcode.productcode)&quot;
                 $Com_WI.InvokeMethod(&#039;AddSource&#039;, &quot;$($productcode.productcode)&quot;, &#039;&#039;, &quot;$($MSIPath)&quot;)
             }
             Catch {
                 Write-Log -Message &quot;Failed to resolve registry path [$regKey]. </code>

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,

I have posted about this issue too.