2016-01-29 1 views
0

У меня есть набор InstanceTransforms, определенных на стороне WiX, согласно ниже:Извлечение ProductCodes экземпляра преобразований определяется внутри от MSI с C#

<InstanceTransforms Property="INSTANCEID"> 
    <Instance ProductCode="*" UpgradeCode="$(var.UpgradeCode)" ProductName="ProductName $(var.VersionText) (64 bit)" Id="$(var.InstanceId)"/> 
    <Instance ProductCode="*" UpgradeCode="$(var.UpgradeCode1)" ProductName="ProductName $(var.VersionText) (64 bit)" Id="$(var.InstanceId1)"/> 
    <Instance ProductCode="*" UpgradeCode="$(var.UpgradeCode2)" ProductName="ProductName $(var.VersionText) (64 bit)" Id="$(var.InstanceId2)"/> 
    <Instance ProductCode="*" UpgradeCode="$(var.UpgradeCode3)" ProductName="ProductName $(var.VersionText) (64 bit)" Id="$(var.InstanceId3)"/> 
    <Instance ProductCode="*" UpgradeCode="$(var.UpgradeCode4)" ProductName="ProductName $(var.VersionText) (64 bit)" Id="$(var.InstanceId4)"/> 
</InstanceTransforms> 

Я хотел бы извлечь в ProductCodes из экземпляр преобразует через мой загрузчик, который является приложением Windows C#, которое вызывает .msi. Поскольку эти ProductCodes генерируются динамически во время сборки установщика, я думал, что мне придется запросить msi с помощью сборки Microsoft.Deployment.WindowsInstaller. Однако при рассмотрении .msi с ORCA я не могу найти таблицу, которая позволила бы мне запрашивать ProductCodes экземпляров. В таблице свойств есть элемент ProductCode элемента Product.

Можно ли получить ProductCodes экземплярных преобразований? Когда я пытаюсь такая же версия обновления с теми же установками, я вижу ProductCode соответствующего InstanceTransform в журнале ошибок .msi в:

Указанного экземпляр {8F97345E-DDAD-4F03-9D17-820E929C59FE} с помощью преобразования уже установлено. MSINEWINSTANCE требует нового экземпляра , который не установлен.

Если кто-то может помочь мне с этим, это было бы здорово - спасибо заблаговременно!

+0

Я подозреваю, что вам нужно знать имя и местоположение фактические файлы преобразования, файлы .mst. Затем вы сделаете эквивалент MsiOpenDatabase(), за которым следует MsiDatabaseApplyTransform, затем выполните запрос SQL в таблице Property, чтобы получить ProductCode. – PhilDW

+0

Hiya Phil, большое спасибо за ваш ответ. Я вызываю свой экземпляр с помощью следующих свойств: INSTANCEID = INSTANCEID1 MSINEWINSTANCE = 1 TRANSFORMS = \ ": INSTANCE_TRANSFORM1 \". Поскольку я явно не ссылаюсь на файл .mst, я думал, что мои преобразования будут встроены в сам .msi, а не извне. В таком случае мне нужно будет вызвать MsiOpenDatabase() в самом файле .msi и сначала запросить таблицу _Storage? –

ответ

0

Вот как я это сделал (используя загрузчик). Я просто проверяю наличие следующего доступного экземпляра для преобразования. Вы можете проверить в реестре ключи и получить следующие доступные:

public static string[] CheckRegKeys(Product product) 
    { 
     var productEnvironment = MapProductToString.MapProductEnvironment(product); 
     var productKeys = new string[50]; 

     for (var i = 0; i < productKeys.Length; i++) 
     { 
      if (i < 9) 
      { 
       productKeys[i] = string.Format("{0}#0{1}", productEnvironment, i + 1); 
       continue; 
      } 

      productKeys[i] = string.Format("{0}#{1}", productEnvironment, i + 1); 
     } 

     return productKeys; 
    } 

    public static string FindNextEnvironmentForInstallation(Product product) 
    { 
     var productName = MapProductToString.MapProductToRegistryName(product); 
     var productKeys = CheckRegKeys(product); 
     using (var componentsKey = Registry.LocalMachine.OpenSubKey(string.Format(@"Software\Wow6432Node\{0}", productName), false)) 
     { 
      if (componentsKey == null) 
      { 
       Registry.LocalMachine.CreateSubKey(string.Format(@"Software\Wow6432Node\{0}", productName)); 
       return string.Format("I0{0}", 1); 
      } 

      var environments = componentsKey.GetSubKeyNames(); 
      if (environments.Length <= 0) 
      { 
       var result = string.Format("I0{0}", 1); 
       return result; 

      } 
      for (var i = 0; i < productKeys.Length; i++) 
      { 
       if (environments.Length < i + 1) 
       { 
        if (i < 9) 
        { 
         var result = string.Format("I0{0}", i + 1); 
         return result; 
        } 

        var result2 = string.Format("I{0}", i + 1); 
        return result2; 
       } 
      } 
     } 
     return null; 
    } 

Далее вы посылаете значение Маврикийский:

using (var p = new Process()) 
       { 
        var info = new ProcessStartInfo 
        { 
         WindowStyle = ProcessWindowStyle.Hidden, 
         FileName = @"C:\Windows\System32\cmd.exe", 
         Arguments = string.Format("/c msiexec /i \"{0}\\{6}.msi\" PATHNAME=\"{0}\" SSLCERTPATH=\"{1}\"" + 
         " MSINEWINSTANCE=1 TRANSFORMS=\":{2}\" /L*v \"{0}\\{6}Log.txt\"" 
         , XmlSettings.EnvironmentFolderPath, FindCertificates.SslCertPath, environment), 
         UseShellExecute = false, 
         CreateNoWindow = true 
        }; 
        p.Start(); 
        p.WaitForExit(); 
       } 
Смежные вопросы