WiX püf noktaları ve ipuçları


264

Bir süredir WiX kullanıyoruz ve kullanım kolaylığı ile ilgili olağan tutuşlara rağmen, gayet iyi gidiyor. Aradığım şey aşağıdakilerle ilgili faydalı tavsiyeler:

  • Bir WiX projesi kurma (düzen, referanslar, dosya modelleri)
  • WiX'i çözümlere entegre etme ve oluşturma / yayınlama işlemleri
  • Yükleyicileri yeni yüklemeler ve yükseltmeler için yapılandırma
  • Paylaşmak istediğiniz iyi WiX saldırıları

gui4wix.codeplex.com bir göz atın
TarunG

10
Yapıcı değil mi? Bu soruyu sorarak yığınları öğrendim! StackOverflow'dan biraz tutarlılık da iyi olurdu ... örn. Stackoverflow.com/questions/550632/…
si618

15
'203' Ups var, yararlılığını kanıtlaması için yeterli.
TarunG

SO sorularının kesin ve doğru bir cevabı olmalıdır; açık uçlu sorular, insanların gerçek sorunlar hakkında sordukları soruları ön sayfadan çıkarır. faq @Si .: Bu politika her zaman AFAIK oldu, ama şimdi daha iyi uygulanıyor; bu soru neredeyse üç yaşında.
Jim Dagg

Yeterince adil Jim, bu açık uçlu bir soru ve sanırım karar vermek SO topluluğuna bağlı, ama şunu söylemeliyim ki, yapıcı değil olarak kapatmanın garip göründüğünü, ben ve görünüşe göre, birçok insan bu soruyu yararlı buldunuz (örneğin, goo.gl/Zqp2X ) ve practical, answerable questions based on actual problems that you faceSSS bölümüne çok iyi uyduğunu .
si618

Yanıtlar:


157
  1. Değişkenleri ayrı bir wxiiçerme dosyasında saklayın . Yeniden kullanımı etkinleştirir, değişkenleri bulmak daha hızlıdır ve (gerekirse) harici bir araç tarafından daha kolay manipülasyona izin verir.

  2. X86 ve x64 derlemeleri için Platform değişkenlerini tanımlama

    <!-- Product name as you want it to appear in Add/Remove Programs-->
    <?if $(var.Platform) = x64 ?>
      <?define ProductName = "Product Name (64 bit)" ?>
      <?define Win64 = "yes" ?>
      <?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
    <?else ?>
      <?define ProductName = "Product Name" ?>
      <?define Win64 = "no" ?>
      <?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
    <?endif ?>
  3. Kurulum konumunu kayıt defterinde saklayarak yükseltmelerin doğru konumu bulmasını sağlayın. Örneğin, bir kullanıcı özel yükleme dizini ayarlarsa.

     <Property Id="INSTALLLOCATION">
        <RegistrySearch Id="RegistrySearch" Type="raw" Root="HKLM" Win64="$(var.Win64)"
                  Key="Software\Company\Product" Name="InstallLocation" />
     </Property>

    Not : WiX guru Rob Mensching , özellikler daha ayrıntılı olarak ele alınan ve özellikler komut satırından ayarlandığında bir uç durumu düzelten mükemmel bir blog girişi yayınladı .

    1. ve 3. kullanan örnekler.

    <?include $(sys.CURRENTDIR)\Config.wxi?>
    <Product ... >
      <Package InstallerVersion="200" InstallPrivileges="elevated"
               InstallScope="perMachine" Platform="$(var.Platform)"
               Compressed="yes" Description="$(var.ProductName)" />

    ve

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="$(var.PlatformProgramFilesFolder)">
        <Directory Id="INSTALLLOCATION" Name="$(var.InstallName)">
  4. En basit yaklaşım her zaman büyük yükseltmeler yapmaktır , çünkü tek MSI'da hem yeni kurulumlara hem de yükseltmelere izin verir. UpgradeCode benzersiz bir Kılavuz'a sabitlenmiştir ve mevcut ürünü yükseltmek istemedikçe asla değişmeyecektir.

    Not : WiX 3.5'te hayatı daha da kolaylaştıran yeni bir MajorUpgrade öğesi var !

  5. Program Ekle / Kaldır'da simge oluşturma

    <Icon Id="Company.ico" SourceFile="..\Tools\Company\Images\Company.ico" />
    <Property Id="ARPPRODUCTICON" Value="Company.ico" />
    <Property Id="ARPHELPLINK" Value="http://www.example.com/" />
  6. Sürüm derlemelerinde, msi dosyasını bir dağıtım dizinine kopyalayarak yükleyicilerimizi sürümlendiririz. AfterBuild hedefinden çağrılan bir wixproj hedefi kullanan buna bir örnek:

    <Target Name="CopyToDeploy" Condition="'$(Configuration)' == 'Release'">
      <!-- Note we append AssemblyFileVersion, changing MSI file name only works with Major Upgrades -->
      <Copy SourceFiles="$(OutputPath)$(OutputName).msi" 
            DestinationFiles="..\Deploy\Setup\$(OutputName) $(AssemblyFileVersion)_$(Platform).msi" />
    </Target>
  7. Wildcard (*) Guid ile dosyaları toplamak için ısı kullanın. WXS dosyalarını birden çok projede yeniden kullanmak istiyorsanız kullanışlıdır (aynı ürünün birden çok sürümünde cevabımı görün). Örneğin, bu toplu iş dosyası otomatik olarak RoboHelp çıktısını toplar.

    @echo off  
    robocopy ..\WebHelp "%TEMP%\WebHelpTemp\WebHelp" /E /NP /PURGE /XD .svn  
    "%WIX%bin\heat" dir "%TEMP%\WebHelp" -nologo -sfrag -suid -ag -srd -dir WebHelp -out WebHelp.wxs -cg WebHelpComponent -dr INSTALLLOCATION -var var.WebDeploySourceDir 

    Biraz oluyor, robocopyHasattan önce Subversion çalışma kopya meta verilerini çıkarıyor; -drkök dizin referans yerine varsayılan TARGETDIR daha bizim yükleme konumuna ayarlanır; -varkaynak dizini (web dağıtım çıktısı) belirtmek için bir değişken oluşturmak için kullanılır.

  8. Yerelleştirme için Strings.wxl dosyasını kullanarak ürün sürümünü hoş geldiniz iletişim kutusu başlığına eklemenin kolay yolu. (Kredi: saschabeaumont . Bu harika ipucu bir yorumda gizlendiği için eklendi)

    <WixLocalization Culture="en-US" xmlns="http://schemas.microsoft.com/wix/2006/localization">
        <String Id="WelcomeDlgTitle">{\WixUI_Font_Bigger}Welcome to the [ProductName] [ProductVersion] Setup Wizard</String>
    </WixLocalization>
  9. Kendinizi biraz acıdan kurtarın ve Wim Coehen'in dosya başına bir bileşen hakkındaki tavsiyelerini takip edin . Bu aynı zamanda bileşen GUID'ini dışarıda bırakmanıza (veya joker olarak *) izin verir .

  10. Rob Mensching, arayarak MSI günlük dosyalarındaki sorunları hızlı bir şekilde izlemenin düzgün bir yoluna sahiptir value 3. Uluslararasılaşma ile ilgili yorumlara dikkat edin.

  11. Koşullu özellikler eklerken, varsayılan özellik düzeyini 0 (devre dışı) olarak ayarlamak ve ardından koşul düzeyini istediğiniz değere ayarlamak daha sezgiseldir. Varsayılan özellik düzeyini> = 1 olarak ayarlarsanız, koşul düzeyini devre dışı bırakmak için 0 olmalıdır, yani koşul mantığı beklediğiniz şeyin tersi olmalıdır, bu da kafa karıştırıcı olabilir :)

    <Feature Id="NewInstallFeature" Level="0" Description="New installation feature" Absent="allow">
      <Condition Level="1">NOT UPGRADEFOUND</Condition>
    </Feature>
    <Feature Id="UpgradeFeature" Level="0" Description="Upgrade feature" Absent="allow">
      <Condition Level="1">UPGRADEFOUND</Condition>
    </Feature>

Simgeyi Program Ekle / Kaldır'a ekleme hakkında tam olarak aradığım şey. Bu üç çizgiyi nereye yapıştırıyorsun? Şeffaflık için +1.
Everett

Onları <Package> öğesinin hemen arkasına (ve açık bir şekilde altına) yerleştirme eğilimindeyim. Geçerlilik şemasına göz atın wix.sourceforge.net/manual-wix3/schema_index.htm
si618

+1, +100 yapabilseydim, bu Tökezlediğim en yararlı Wix bilgisidir.
Tim Long

Teşekkürler Tim! Rob Mensching, Bob Arson, Wim Coehen ve diğerleri bilgilerinin paylaşıldığı için kudosları hak ediyorlar.
si618 20:11

38

IIS'nin yüklü olup olmadığını kontrol etme:

<Property Id="IIS_MAJOR_VERSION">
    <RegistrySearch Id="CheckIISVersion" Root="HKLM" Key="SOFTWARE\Microsoft\InetStp" Name="MajorVersion" Type="raw" />
</Property>

<Condition Message="IIS must be installed">
    Installed OR IIS_MAJOR_VERSION
</Condition>

Vista + üzerinde IIS 6 Metatabanı Uyumluluğunun yüklü olup olmadığını kontrol etme:

<Property Id="IIS_METABASE_COMPAT">
    <RegistrySearch Id="CheckIISMetabase" Root="HKLM" Key="SOFTWARE\Microsoft\InetStp\Components" Name="ADSICompatibility" Type="raw" />
</Property>

<Condition Message="IIS 6 Metabase Compatibility feature must be installed">
    Installed OR ((VersionNT &lt; 600) OR IIS_METABASE_COMPAT)
</Condition>

34

Tüm kimlikleri ayrı ad alanlarında saklayın

  • Özellikler F. Örneklerle başlar : F.Documentation, F.Binaries, F.SampleCode.
  • Bileşenler C. Örn: C.ChmFile, C.ReleaseNotes, C.LicenseFile, C.IniFile, C.Registry ile başlar.
  • CustomActions CA. Örn: CA.LaunchHelp, CA.UpdateReadyDlg, CA.SetPropertyX
  • Dosyalar Fi.
  • Dizinler Di.
  • ve bunun gibi.

Bunun çeşitli kategorilerdeki çeşitli kimlikleri takip etmede çok yardımcı olduğunu düşünüyorum.


Ad alanları kullanmıyorum ama kimlikleri ekliyorum; örneğin: Örnekler Özellik, ChmFileComponent. Ben yazmayı seviyorum sanırım ;-)
dvdvorle

25

Harika bir soru. Gösterilen en iyi uygulamaları görmek isterim.

Dağıttığım çok fazla dosyam var, bu yüzden projemi birkaç wxs kaynak dosyasına ayarladım.

Temelde yükleme yapısını içeren, ancak gerçek bileşenleri değil Product.wxs dediğim bir üst düzey kaynak dosya var. Bu dosyanın birkaç bölümü vardır:

<Product ...>
  <Package ...>
    <Media>... 
   <Condition>s ...
   <Upgrade ..>
   <Directory> 
        ...
   </Directory>
   <Feature>
      <ComponentGroupRef ... > A bunch of these that
   </Feature>
   <UI ...>
   <Property...>
   <Custom Actions...>
   <Install Sequences....
  </Package>
</Product>

.Wix dosyalarının geri kalanı, Product.wxs içindeki Feature etiketinde başvurulan ComponentGroups içeren Parçalardan oluşur. Projem dağıttığım dosyaların hoş bir mantıksal gruplamasını içeriyor

<Fragment>
   <ComponentGroup>
     <ComponentRef>
     ....
    </ComponentGroup>
    <DirectoryRef>
      <Component... for each file
      .... 
    </DirectoryRef>
</Fragment>

Bu mükemmel değil, benim OO örümcek duygusu biraz parçalanıyor çünkü parçaları Product.wxs dosyasındaki isimlere başvurmak zorunda (örn. DirectoryRef) ama ben bu tek bir büyük kaynak dosyasını korumak için daha kolay buluyorum.

Bu konuda yorum duymak isterim, ya da herhangi bir iyi ipucu varsa!


Kurulumumuz da bu yaklaşıma çok benziyor. İyi, çünkü eşdeğer ürünlerimizi çeşitli ürünler için temel kurulumumuz olarak kullanabiliriz.
si618

@Peter Tate: Örümcek duygunuz doğru. Dizin takma adı ile ilgili cevabımı görün.
Wim Coenen

Ben de aynı yaklaşımı benimsiyorum: mizanpajlı Product.wxs statik ve bir yapı görevi (heat.exe) benim Content.wxs dosyasını oluşturur
timvw

20

Uygulamayı veya yardım dosyasını başlatmak için çıkış iletişim kutusuna bir onay kutusu ekleyin.

...

<!-- CA to launch the exe after install -->
<CustomAction Id          ="CA.StartAppOnExit"
              FileKey     ="YourAppExeId"
              ExeCommand  =""
              Execute     ="immediate"
              Impersonate ="yes"
              Return      ="asyncNoWait" />

<!-- CA to launch the help file -->
<CustomAction Id         ="CA.LaunchHelp"
              Directory  ="INSTALLDIR"
              ExeCommand ='[WindowsFolder]hh.exe IirfGuide.chm'
              Execute    ="immediate"
              Return     ="asyncNoWait" />

<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT"
          Value="Launch MyApp when setup exits." />

<UI>
  <Publish Dialog  ="ExitDialog"
           Control ="Finish"
           Order   ="1"
           Event   ="DoAction"
           Value   ="CA.StartAppOnExit">WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT</Publish>
</UI>

Bu şekilde yaparsanız, "standart" görünüm tam olarak doğru değildir. İletişim kutusu beyazken onay kutusu her zaman gri bir arka plandır:

alternatif metin http://www.dizzymonkeydesign.com/blog/misc/adding-and-customizing-dlgs-in-wix-3/images/exit_dlg_1.gif

Bunun bir yolu , farklı konumlandırılmış bir onay kutusuyla kendi özel ExitDialog'unuzu belirtmektir . Bu işe yarıyor, ama sadece bir kontrolün rengini değiştirmek için çok iş gibi görünüyor. Aynı şeyi çözmenin başka bir yolu, oluşturulan MSI'yı belirli CheckBox denetimi için Denetim tablosundaki X, Y alanlarını değiştirmek üzere sonradan işlemektir. Javascript kodu şuna benzer:

var msiOpenDatabaseModeTransact = 1;
var filespec = WScript.Arguments(0);
var installer = new ActiveXObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
var sql = "UPDATE `Control` SET `Control`.`Height` = '18', `Control`.`Width` = '170'," +
          " `Control`.`Y`='243', `Control`.`X`='10' " +
          "WHERE `Control`.`Dialog_`='ExitDialog' AND " + 
          "  `Control`.`Control`='OptionalCheckBox'";
var view = database.OpenView(sql);
view.Execute();
view.Close();
database.Commit();

MSI oluşturulduktan sonra (light.exe'den) bu kodu bir komut satırı komut dosyası olarak çalıştırmak (cscript.exe kullanarak) daha profesyonel görünen bir ExitDialog üretir:

alternatif metin http://www.dizzymonkeydesign.com/blog/misc/adding-and-customizing-dlgs-in-wix-3/images/exit_dlg_2.gif


Ha! Blogum değil. Ben de okudum. Ve yukarıdaki metinde blog girişine bir link var. Ama bunu benden farklı yaptılar. Yolumu daha iyi seviyorum. !!
Cheeso

1
Js için teşekkürler, çok yararlı! Ben wxs değişikliği gerekiyordu bir şey değiştirmek olduğunu WIXUI_EXITDIALOGOPTIONALCHECKBOXile WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed<Publish>
Alexander Kojevnikov

Onay kutusunu varsayılan olarak işaretlemenin bir yolu var mı?
Alek Davis

Kutuyu varsayılan olarak işaretlemek için şunu kullandım: <Property Id = "WIXUI_EXITDIALOGOPTIONALCHECKBOX" Değer = "1" />
Alek Davis

Şık bir çözüm gibi görünüyor, ama nasıl kullanırım? Benim wixproj içinde <AfterBuild> öğesinin içine js koymak için bir yolu var mı? Veya komut satırından çalıştırmaya atıfta bulunduğunuzdan, bir post-build olayı olarak daha iyi, bu durumda Windows için iyi bir js komut satırı yorumlayıcısı nedir?
vanmelle

18

Oluşturma Live, Test, Training, ... aynı kaynak dosyaları kullanarak sürümleri.

Özetle: Her yükleyici için benzersiz UpgradeCode oluşturun ve her yükleyici için her Kılavuzun ilk karakterini otomatik olarak tanımlayın, kalan 31'i benzersiz bırakın.

Ön şartlar

Varsayımlar

  • WiX değişkenleri UpgradeCode, ProductName, InstallName tanımlamak için kullanılır.
  • Zaten çalışan bir yükleyiciniz var. Bunu yapana kadar denemem.
  • Tüm Bileşenleriniz tek bir dosyada (Components.wxs) saklanır. Birden çok dosyanız varsa bu işlem çalışır, daha fazla işiniz olur.

Dizin Yapısı

  • Setup.Library
    • Tüm wxs dosyaları (Bileşenler, Özellikler, UI İletişim Kutuları, ...)
    • Common.Config.wxi (ProductCode = "*", ProductVersion, PlatformProgramFilesFolder, ...)
  • Kurulum.Live (wixproj)
    • "Varolan Dosya Ekle" -> "Bağlantı Olarak Ekle" (Visual Studio'da Ekle düğmesinin hemen yanındaki küçük aşağı ok düğmesi) kullanarak tüm Setup.Library dosyalarını bağlayın
    • Config.wxi (benzersiz UpgradeCode, ProductName, InstallName, ... vardır)
  • Kurulum.Test , ...
    • canlı olarak ancak Config.wxi, Test ortamı için yapılandırılmıştır.

süreç

  • Setup.Library dizinini oluşturun ve tüm wxs ve wxi dosyalarınızı (Config.wxi hariç) varolan projeden taşıyın.
  • Normal wixproj'a göre Setup.Live, Setup.Test vb.
  • Kılavuzları değiştirmek için MSBuild Topluluk Görevi FileUpdate gerçekleştirmek için Setup.Live, vb. İçindeki wixproj'a BeforeBuild hedefi ekleyin (Live için A, Test için B ve eğitim için C kullandım)
  • Components.wxs Kılavuzlarını geri döndürmek için AfterBuild hedefini ekleyin.
  • Orca ile her MSI'daki her bir bileşenin değiştirilmiş kılavuza sahip olduğunu doğrulayın.
  • Orijinal kılavuzların geri yüklendiğini doğrulayın.
  • Her MSI'nın doğru ürünü ve konumu yüklediğini (ve yükselttiğini) doğrulayın.

Örnek Config.wxi

<?xml version="1.0" encoding="utf-8"?>
<Include>
<!-- Upgrade code should not change unless you want to install 
     a new product and have the old product remain installed, 
     that is, both products existing as separate instances. -->
<?define UpgradeCode = "YOUR-GUID-HERE" ?>

<!-- Platform specific variables -->
<?if $(var.Platform) = x64 ?>
  <!-- Product name as you want it to appear in Add/Remove Programs-->
  <?define ProductName = "Foo 64 Bit [Live]" ?>
<?else ?>
  <?define ProductName =  "Foo [Live]" ?>
<?endif ?>

<!-- Directory name used as default installation location -->
<?define InstallName = "Foo [Live]" ?>

<!-- Registry key name used to store installation location -->
<?define InstallNameKey = "FooLive" ?>

<?define VDirName = "FooLive" ?>
<?define AppPoolName = "FooLiveAppPool" ?>
<?define DbName = "BlahBlahLive" ?>
</Include>

Örnek Config.Common.wxi

<?xml version="1.0" encoding="utf-8"?>
<Include>
<!-- Auto-generate ProductCode for each build, release and upgrade -->
<?define ProductCode = "*" ?>

<!-- Note that 4th version (Revision) is ignored by Windows Installer -->
<?define ProductVersion = "1.0.0.0" ?>

<!-- Minimum version supported if product already installed and this is an upgrade -->
<!-- Note that 4th version (Revision) is ignored by Windows Installer -->
<?define MinimumUpgradeVersion = "0.0.0.0" ?>

<!-- Platform specific variables -->
<?if $(var.Platform) = x64 ?>
   <?define Win64 = "yes" ?>
   <?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?else ?>
   <?define Win64 = "no" ?>
   <?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
<?endif ?>

<?define ProductManufacturer = "Foo Technologies"?>

<!-- Decimal Language ID (LCID) for the Product. Used for localization. -->
<?define ProductLanguage = "1033" ?>

<?define WebSiteName = "DefaultWebSite" ?>
<?define WebSitePort = "80" ?>

<?define DbServer = "(local)" ?>
</Include>

Örnek Components.wxs

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <!-- The pre-processor variable which allows the magic to happen :) -->
  <?include $(sys.CURRENTDIR)\Config.wxi?>
  <?include ..\Setup.Library\Config.Common.wxi?>
  <Fragment Id="ComponentsFragment">
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="$(var.PlatformProgramFilesFolder)">
        <Directory Id="INSTALLLOCATION" Name="$(var.InstallName)">
          <Component Id="ProductComponent" Guid="0XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" KeyPath="yes">
          ...

Not: Şimdi, Guid özniteliğini Bileşen (eşdeğeri *) dışında bırakmayı, bileşen başına bir dosya kullanmayı ve dosyayı anahtar yolu olarak ayarlamanızı öneririm. Bu, aşağıda gösterilen arama ModifyComponentsGuidsve RevertComponentsGuidshedeflere olan ihtiyacı ortadan kaldırır . Bu, tüm bileşenleriniz için mümkün olmayabilir.

Örnek Setup.Live.wixproj

<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
<Target Name="BeforeBuild">
  <CallTarget Targets="ModifyComponentsGuids" />
</Target>
<Target Name="AfterBuild">
  <CallTarget Targets="RevertComponentsGuids" />
</Target>
<!-- Modify the first character of every Guid to create unique value for Live, Test and Training builds -->
<Target Name="ModifyComponentsGuids">
  <FileUpdate Files="..\Setup.Library\Components.wxs" Regex="Guid=&quot;([a-f]|[A-F]|\d)" ReplacementText="Guid=&quot;A" />
</Target>
<!-- Revert the first character of every Guid back to initial value -->
<Target Name="RevertComponentsGuids">
  <FileUpdate Files="..\Setup.Library\Components.wxs" Regex="Guid=&quot;([a-f]|[A-F]|\d)" ReplacementText="Guid=&quot;0" />
</Target>

Son düşünceler

  • Bu işlem, aynı yükleyici için farklı birleştirme modülleri (Live, Test, ... as as features) için farklı yükleyiciler oluşturmak için de çalışmalıdır. Daha güvenli bir seçenek gibi göründüğü için farklı yükleyicilerle gittim, aynı kutudaysa birinin Eğitim yerine Live'ı yükseltmesi riski daha fazladır ve sadece farklı birleştirme modülleri için özellikler kullanırsınız.
  • MSI'nızı yeni yükseltmelerin yanı sıra yalnızca büyük yükseltme yaklaşımı gibi yükseltmeler yapmak için kullanıyorsanız ve yükleme konumunuzu kayıt defterine kaydederseniz, her yükleme için anahtar adı için bir değişken oluşturmayı unutmayın.
  • Ayrıca her bir yükleyici için benzersiz sanal dizin adlarını, uygulama havuzlarını, veritabanı adlarını vb. Etkinleştirmek için her Config.wxi dosyasında değişkenler oluştururuz.

GÜNCELLEME 1: Bileşen Kılavuzlarını Otomatik Oluşturma Her bir dosya için Guid = "*" ile bileşen oluşturursanız ve dosyayı anahtar yolu olarak ayarlarsanız FileUpdate görevini çağırma gereksinimini ortadan kaldırır.

GÜNCELLEME 2: Karşılaştığımız sorunlardan biri, bileşen Kılavuzunuzu otomatik olarak oluşturmazsanız ve derleme başarısız olursa, geçici dosyaların manuel olarak silinmesi gerekir.

GÜNCELLEME 3: svn: externals ve geçici dosya oluşturma bağımlılığını kaldırmanın bir yolunu buldu. Bu, oluşturma işlemini daha esnek hale getirir (ve Kılavuzlarınızı joker olarak işaretleyemiyorsanız en iyi seçenektir) ve ışık veya mumda bir yapı hatası varsa daha az kırılgan hale gelir.

GÜNCELLEME 4: Örnek dönüşümlerini kullanan Birden Fazla Örnek desteği WiX 3.0+ sürümündedir, kesinlikle bir göz atmaya değer.


Topluluk Görevleri referansı için +1, bu paketi sevdim
BozoJoe

17

Ayrıntılı hata almak için Msi Tanı günlüğünü kullanma Bilgi

msiexec /i Package.msi /l*v c:\Package.log

Nerede

Package.msi
paketinizin adı ve
C: \ Package.log
kütüğün çıktısını almak istediğiniz yer

MSI Hata Kodları

Wix Giriş Video
Oh ve Rastgele Wix giriş video "Mr. WiX" Rob Mensching "kavramsal büyük resim" yararlıdır.


2
+1 Günlükleri komut satırı yerine Wix içinden etkinleştirebilseydik çok daha iyi olurdu.
si618

3
WiX bunu yapar. MsiLogging özelliğini ayarlayın. Yalnızca Windows Installer 4.0+ tarafından desteklenir.
Rob Mensching

Çok teşekkür ederim "Bay Wix". Bunu kontrol etmeliyim.
Terrance

17

Çok kolay oldukları için Javascript CustomActions kullanın

İnsanlar Javascript'in MSI CustomActions için yanlış bir şey olduğunu söylediler . Verilen nedenler: hata ayıklamak zor, güvenilir hale getirmek zor. Kabul etmiyorum. Hata ayıklamak zor değil, kesinlikle C ++ 'dan daha zor değil. Bu sadece farklı. CustomActions Javascript yazarak süper kolay, C ++ kullanmak çok daha kolay olarak buldum. Çok daha hızlı. Ve aynı derecede güvenilir.

Tek bir dezavantajı var: Javascript CustomActions Orca üzerinden çıkarılabilirken, bir C / C ++ CA tersine mühendislik gerektirir. Yükleyici sihrinizin fikri mülkiyet tarafından korunduğunu düşünüyorsanız komut dosyasından kaçınmak istersiniz.

Komut dosyası kullanıyorsanız, sadece bazı yapılarla başlamanız gerekir. İşte başlamanız için bazı şeyler.


CustomAction için Javascript "boilerplate" kodu:

//
// CustomActions.js 
// 
// Template for WIX Custom Actions written in Javascript.
// 
// 
// Mon, 23 Nov 2009  10:54
// 
// ===================================================================


// http://msdn.microsoft.com/en-us/library/sfw6660x(VS.85).aspx
var Buttons = {
        OkOnly           : 0,
        OkCancel         : 1,
        AbortRetryIgnore : 2,
        YesNoCancel      : 3
};

var Icons = {
        Critical         : 16,
        Question         : 32,
        Exclamation      : 48,
        Information      : 64
};

var MsgKind = {
        Error            : 0x01000000,
        Warning          : 0x02000000,
        User             : 0x03000000,
        Log              : 0x04000000
};

// http://msdn.microsoft.com/en-us/library/aa371254(VS.85).aspx
var MsiActionStatus = {
        None             : 0,
        Ok               : 1, // success
        Cancel           : 2,
        Abort            : 3,
        Retry            : 4, // aka suspend?
        Ignore           : 5  // skip remaining actions; this is not an error.
};


function MyCustomActionInJavascript_CA() {
    try {
        LogMessage("Hello from MyCustomActionInJavascript");
        // ...do work here...
        LogMessage("Goodbye from MyCustomActionInJavascript");
    }
    catch (exc1) {
        Session.Property("CA_EXCEPTION") = exc1.message ;
        LogException(exc1);
        return MsiActionStatus.Abort;
    }
    return MsiActionStatus.Ok;
}

// Pop a message box.  also spool a message into the MSI log, if it is enabled. 
function LogException(exc) {
    var record = Session.Installer.CreateRecord(0);
    record.StringData(0) = "CustomAction: Exception: 0x" + decimalToHexString(exc.number) + " : " + exc.message;
    Session.Message(MsgKind.Error + Icons.Critical + Buttons.btnOkOnly, record);
}


// spool an informational message into the MSI log, if it is enabled. 
function LogMessage(msg) {
    var record = Session.Installer.CreateRecord(0);
    record.StringData(0) = "CustomAction:: " + msg;
    Session.Message(MsgKind.Log, record);
}


// http://msdn.microsoft.com/en-us/library/d5fk67ky(VS.85).aspx
var WindowStyle = {
    Hidden : 0,
    Minimized : 1,
    Maximized : 2
};

// http://msdn.microsoft.com/en-us/library/314cz14s(v=VS.85).aspx
var OpenMode = {
    ForReading : 1,
    ForWriting : 2,
    ForAppending : 8
};

// http://msdn.microsoft.com/en-us/library/a72y2t1c(v=VS.85).aspx
var SpecialFolders = {
    WindowsFolder : 0, 
    SystemFolder :  1, 
    TemporaryFolder : 2
};

// Run a command via cmd.exe from within the MSI
function RunCmd(command)
{
    var wshell = new ActiveXObject("WScript.Shell");
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    var tmpdir = fso.GetSpecialFolder(SpecialFolders.TemporaryFolder);
    var tmpFileName = fso.BuildPath(tmpdir, fso.GetTempName());

    LogMessage("shell.Run("+command+")");

    // use cmd.exe to redirect the output
    var rc = wshell.Run("%comspec% /c " + command + "> " + tmpFileName, WindowStyle.Hidden, true);
    LogMessage("shell.Run rc = "  + rc);

    // here, optionally parse the output of the command 
    if (parseOutput) {
        var textStream = fso.OpenTextFile(tmpFileName, OpenMode.ForReading);
        while (!textStream.AtEndOfStream) {
            var oneLine = textStream.ReadLine();
            var line = ParseOneLine(oneLine);
                ...
        }
        textStream.Close();
    }

    if (deleteOutput) {
        fso.DeleteFile(tmpFileName);
    }

    return {
        rc : rc,
        outputfile : (deleteOutput) ? null : tmpFileName
    };
}

Ardından, özel işlemi şu şekilde kaydedin:

<Fragment>
  <Binary Id="IisScript_CA" SourceFile="CustomActions.js" />

  <CustomAction Id="CA.MyCustomAction"
              BinaryKey="IisScript_CA"
              JScriptCall="MyCustomActionInJavascript_CA"
              Execute="immediate"
              Return="check" />
</Fragmemt>

Elbette, birden fazla özel eylem için istediğiniz kadar Javascript işlevi ekleyebilirsiniz. Bir örnek: Bir ISAPI filtresinin yüklenebileceği varolan web sitelerinin listesini almak için IIS'de WMI sorgusu yapmak için Javascript kullandım. Bu liste daha sonra UI dizisinde daha sonra gösterilen bir liste kutusunu doldurmak için kullanıldı. Hepsi çok kolay.

IIS7'de, IIS için WMI sağlayıcısı olmadığından, shell.Run()uygulamayı gerçekleştirmek için appcmd.exe'yi çağırmak için yaklaşımı kullandım . Kolay.

İlgili soru: Javascript CustomActions Hakkında


2
+1 DTF yaklaşımının kurulumu kolay olduğunu düşünüyorum, ancak javascript de yararlı olabilir.
si618

12

Peter Tate, ayrı wix parçalarında yeniden kullanılabilir ComponentGroup tanımlarını nasıl tanımlayabileceğinizi zaten göstermiştir. Bununla ilgili bazı ek püf noktaları:

Dizin Takma Adları

Bileşen grubu parçalarının, ana ürün wxs tarafından tanımlanan dizinler hakkında bilgi sahibi olması gerekmez. Bileşen grubu parçanızda aşağıdaki gibi bir klasör hakkında konuşabilirsiniz:

<DirectoryRef Id="component1InstallFolder">
...
</DirectoryRef>

Daha sonra ana ürün dizinlerinden birini (ör. "ProductInstallFolder") şöyle taklit edebilir:

<Directory Id="productInstallFolder" Name="ProductName">
   <!-- not subfolders (because no Name attribute) but aliases for parent! -->
   <Directory Id="component1InstallFolder"/> 
   <Directory Id="component2InstallFolder"/> 
</Directory>

Bağımlılık Grafiği

ComponentGroup öğeleri ComponentGroupRef alt öğeleri içerebilir. Aralarında karmaşık bir bağımlılık grafiği olan büyük bir yeniden kullanılabilir bileşen havuzunuz varsa bu harika. Her bileşen için kendi bileşeninde bir ComponentGroup oluşturursunuz ve bunun gibi bağımlılıkları beyan edersiniz:

<ComponentGroup Id="B">
   <ComponentRef Id="_B" />
   <ComponentGroupRef Id="A">
</ComponentGroup>

Şimdi uygulamanızda doğrudan bir bağımlılık olduğu için kurulumunuzda "B" bileşen grubuna başvurursanız, uygulama yazarı "B" bağımlılığı olduğunu hiç fark etmemiş olsa bile otomatik olarak "A" bileşen grubunu çeker. Dairesel bağımlılığınız olmadığı sürece "çalışır".

Yeniden kullanılabilir wixlib

Yukarıdaki bağımlılık grafiği fikri, big-pool-o-reusable-bileşenlerini lit.exe ile yeniden kullanılabilir bir wixlib olarak derlerseniz en iyi sonucu verir. Bir uygulama kurulumu oluştururken, bu wixlib'e bir wixobj dosyası gibi başvurabilirsiniz. Candle.exe bağlayıcısı, ana ürün wxs dosyaları tarafından "içeri çekilmeyen" parçaları otomatik olarak ortadan kaldırır.


12

Hiç kimse oluşturma sırasında WXS dosyasını oluşturmak için T4 kullanarak bahsetmedi şaşırdım. Bunu Henry Lee @ New Age Solutions aracılığıyla öğrendim .

Esasen, bir T4 şablonu yürütmek için özel bir MSBuild görevi oluşturursunuz ve bu şablon WXS'yi Wix projesi derlenmeden hemen önce çıktılar. Bu, (nasıl uyguladığınıza bağlı olarak) başka bir çözüm derlemeden tüm derleme çıktılarını otomatik olarak dahil etmenizi sağlar (yani yeni bir derleme eklediğinizde artık wxs'i düzenlemek zorunda kalmazsınız).


2
+1 gerçekten güzel, montajlar hakkında çok fazla endişelenmiyorum, ancak web projelerimiz aspx sayfaları ve WiX değil, projeye eklenen diğer eserler (resimler, css) ile ilgili sorunlara sahip olabilir.
si618

4
Gelecek ziyaretçiler için, Wix 3.5, bu hasadı otomatik olarak yapan bir yardımcı ısı.exe'ye sahiptir
Mrchief

@Mrchief - Heat'in yerel olarak kopyalanan referanslanmış derlemeleri aldığını düşünmüyorum - bu görünüşe göre 4.0 için planlanmış. Referans: sourceforge.net/tracker/…
Peter T. LaComb Jr.

Isı referans alınan montajları almaz.
tofutim

WXS dosyasını oluşturmak için T4 kullanmanın bazı iyi örnekleri nelerdir?
tofutim

12

Yüzü parçalamak ve acı verici büyük kurulumlarda "Epic Pwnage" uygulamak için Heat.exe'yi kullanma

Si'nin ve Robert-P'nin ısı ile ilgili cevaplarını genişletmek .

Çeviri: (Tek tek dosyaları projeye elle yazmaktan kaçınmak ve genel olarak daha kolay bir işlem için yapıları otomatikleştirmek için ısıyı kullanma.)

WiX 2.0 Heat Syntax detaylı

Daha yeni sürümler için (eski sürümlerden farklı değil ancak potansiyel olarak sinir bozucu sözdizimi değişiklikleri var ....) Dizine gidin Isı cmd.exe'den ve sadece ısı yazın ama yardım için burada bir örnek var gerekirse daha yeni sürümlerle.

Visual Studio 2010'daki Yapı Etkinliğinize aşağıdakileri ekleme.
(Project-> Properties -> Build Events-> Build-Build Events'e sağ tıklayın)

$(WIX)bin\heat.exe" dir "$(EnviromentVariable)" -cg GroupVariable -gg -scom -sreg -sfrag - srd -dr INSTALLLOCATION -var env.LogicPath -out "$(FragmentDir)\FileName.wxs

-İyi oyun 

Isı çalıştırıldığında kılavuzlar oluşturur (yukarıdaki komutu yürütürken olduğu gibi)

-scom 

"COM dosyaları" kapma

-sreg 

"Kayıt Defteri Dosyaları" kapma

-sfrag 

"Parçalar" kapma

-srd 

"Kök Dir" i kapma

dir

dir, Heat'in bir klasöre bakmasını istediğinizi gösterir

"$ (EnviromentVariable)"

(Sağ tıklama projesi, Özelliklere git) proje özellikleri-> Oluştur bölümünde Önişlemci değişkenlerine ekleyeceğiniz değişkenin adı Önişlemci değişkenlerini tanımla (visual studio 2010 olduğunu varsayar)

Misal:
EnviromentVariable = C: \ Projesi \ bin \ Debug;
Çift tırnak yok ama noktalı virgülle bitiyor

-cg Grubu Değişken 

Ana wxs dosyasına oluşturulan parçadan başvurulacak olan ComponentGroup

FragmentDir

Çıktı wxs parçasının saklanacağı parça dizini

FileName.wxs

Dosyanın adı

Burada tam öğretici, çok acayip yararlı

Bölüm 1 Bölüm 2


Biraz farklı amaçlar için başka bir yararlı araç daha var: Parafin ( wintellect.com/CS/blogs/jrobbins/archive/2010/03/10/4107.aspx )
ralf.w.

9

COM Nesneleri dahil:

heatkayıt defteri girdilerini ve bunlar için gereken diğer yapılandırmaları (tümü olmasa da) çoğunu oluşturur. Sevinin!

Yönetilen COM Nesneleri dahil (aka, .NET veya C # COM nesneleri)

heatYönetilen bir COM nesnesinde kullanmak size neredeyse eksiksiz bir wix belgesi verecektir.

GAC'de mevcut olan kütüphaneye ihtiyacınız yoksa (yani, global olarak kullanılabilir: Yine de .NET derlemelerinizle buna ihtiyacınız yoktur - muhtemelen bu noktada yanlış bir şey yaptınız. paylaşılan bir kütüphane) CodeBaseayarlanacak kayıt defteri anahtarını güncellediğinizden emin olmak istersiniz [#ComponentName]. GAC'ye yüklemeyi planlıyorsanız (örneğin, herkesin kullanmak isteyeceği yeni ve harika bir ortak kitaplık oluşturduysanız) bu girişi kaldırmanız ve Fileöğeye iki yeni özellik eklemeniz gerekir : Assemblyve KeyPath. Montaj ".net" ve KeyPath"evet" olarak ayarlanmalıdır.

Bununla birlikte, bazı ortamların (özellikle komut dosyası dilleri gibi yönetilen belleğe sahip her şeyin) Typelib'e de erişmesi gerekecektir. Tipelib üzerinde çalıştığından ve eklediğinden eminheat ol. heatgerekli tüm kayıt defteri anahtarlarını oluşturur. Ne kadar serin?


8

Yükleniyor C:\ProductName

Bazı uygulamaların yüklenmesi C:\ProductNameveya buna benzer bir şeyin yüklenmesi gerekir , ancak net kurulumdaki örneklerin% 99.9'u (% 100 değilse) C:\Program Files\CompanyName\ProductName.

Aşağıdaki kod, TARGETDIRözelliği C:sürücünün kök dizinine ayarlamak için kullanılabilir ( WiX kullanıcıları listesinden alınmıştır ):

<CustomAction Id="AssignTargetDir" Property="TARGETDIR" Value="C:\" Execute="firstSequence" />
<InstallUISequence>
    <Custom Action="AssignTargetDir" Before="CostInitialize">TARGETDIR=""</Custom>
</InstallUISequence>
<InstallExecuteSequence>
    <Custom Action="AssignTargetDir" Before="CostInitialize">TARGETDIR=""</Custom>
</InstallExecuteSequence>

NOT: Varsayılan olarak, TARGETDIR gelmez işaret C:\! Daha çok puan için ROOTDRIVEhangi dönüş noktalarında en çok boş alanın sürücüsünün kökünde ( burada bakınız ) - ve bu mutlaka değil C:sürücü. Başka bir sabit sürücü, bölüm veya USB sürücü olabilir!

Ardından, <Product ...>etiketinizin altında bir yerde , her zamanki gibi aşağıdaki dizin etiketlerine ihtiyacınız vardır:

<Directory Id="TARGETDIR" Name="SourceDir">
    <Directory Id="APPLICATIONFOLDER" Name="$(var.ProductName)">
        <!-- your content goes here... -->
    </Directory>
</Directory>

Sadece yüklemek daha kolay olmaz mıydı WindowsVolume?
Wim Coenen

1
Evet, ancak WindowsVolumeözellik burada ve buradaDirectory işaret edildiği gibi bir (derleyici hata / uyarı verir) olarak kullanılamayabileceğinden geçici bir çözüm kullanmanız gerekir . Şahsen, bu geçici çözümü kafa karıştırıcı buluyorum.
gehho

7

Çevresel değişkenler

Wxs belgelerinizi wixobj koduna derlerken, çeşitli bilgileri belirlemek için çevresel değişkenleri kullanabilirsiniz. Örneğin, bir projeye dahil edilecek dosyaları değiştirmek istediğinizi varsayalım. Diyelim ki, MSI'nızı oluşturmadan hemen önce ayarladığınız RELEASE_MODE adlı bir çevresel değişkeniniz var (bir komut dosyasıyla veya el ile önemli değil) Wix kaynağınızda şöyle bir şey yapabilirsiniz:

<define FILESOURCE = c:\source\output\bin\$(env.RELEASE_MODE) >

ve daha sonra kodunuzda, wxs belgenizi anında değiştirmek için yerinde kullanın, örneğin:

<Icon Id="myicon.ico" SourceFile="$(var.FILESOURCE)" />

1
Ayrıca $ (Configuration) ve $ (Platform) gibi derleme değişkenleri de mevcuttur. Ayrıca msdn.microsoft.com/en-us/library/aa302186.aspx
si618

1
@Si - Bugünden bir süre önce, bu bağlantı artık etkin değil. En yenisini bulamadım.
Peter M



7

İletişim Kutularını Düzenleme

Diyalogları düzenlemek için iyi bir yetenek, SharpDevelop'u 4.0.1.7090 (veya üzeri) sürümde kullanmaktır. Bu aracın yardımıyla Tasarım görünümünde bağımsız bir iletişim kutusu (örneğin, InstallDirDlg.wxs gibi WiX kaynaklarından gelen wxs dosyaları) açılabilir, önizlenebilir ve düzenlenebilir.


Harika, SharpDevelop'un bunu desteklediğini bilmiyordum.
anton.burger

6

IIS enable32BitAppOnWin64 bayrağını ayarlama http://trycatchfail.com/blog/post/WiX-Snippet-change-enable32BitAppOnWin64.aspx

<InstallExecuteSequence>
   <RemoveExistingProducts After="InstallFinalize" />
   <Custom Action="ConfigureAppPool" After="InstallFinalize" >
     <![CDATA[NOT Installed AND VersionNT64 >= 600]]>         
   </Custom>
</InstallExecuteSequence>

<CustomAction Id="ConfigureAppPool" Return="check" Directory="TARGETDIR" ExeCommand="[SystemFolder]inetsrv\appcmd set apppool /apppool.name:[APPPOOLNAME] /enable32BitAppOnWin64:false" />

5

"Yüklemeye hazır mısınız?" iletişim kutusu (aka VerifyReadyDlg olarak da bilinir) seçimlerin bir özetini sunar.

Şuna benzer:
alternatif metin http://i46.tinypic.com/s4th7t.jpg

Bunu bir Javascript CustomAction ile yapın:


Javascript kodu:

// http://msdn.microsoft.com/en-us/library/aa372516(VS.85).aspx
var MsiViewModify = 
    {
        Refresh          : 0,
        Insert           : 1,
        Update           : 2,
        Assign           : 3,
        Replace          : 4,
        Merge            : 5,
        Delete           : 6,
        InsertTemporary  : 7,   // cannot permanently modify the MSI during install
        Validate         : 8,
        ValidateNew      : 9,
        ValidateField    : 10,
        ValidateDelete   : 11
    };


// http://msdn.microsoft.com/en-us/library/sfw6660x(VS.85).aspx
var Buttons = 
    {
        OkOnly           : 0,
        OkCancel         : 1,
        AbortRetryIgnore : 2,
        YesNoCancel      : 3
    };

var Icons= 
    {
        Critical         : 16,
        Question         : 32,
        Exclamation      : 48,
        Information      : 64
    }

var MsgKind =
    {
        Error            : 0x01000000,
        Warning          : 0x02000000,
        User             : 0x03000000,
        Log              : 0x04000000
    };

// http://msdn.microsoft.com/en-us/library/aa371254(VS.85).aspx
var MsiActionStatus = 
    {
        None             : 0,
        Ok               : 1, // success
        Cancel           : 2,
        Abort            : 3,
        Retry            : 4, // aka suspend?
        Ignore           : 5  // skip remaining actions; this is not an error.
    };

function UpdateReadyDialog_CA(sitename)
{
    try 
    {
        // can retrieve properties from the install session like this:
        var selectedWebSiteId = Session.Property("MSI_PROPERTY_HERE");

        // can retrieve requested feature install state like this:
        var fInstallRequested   = Session.FeatureRequestState("F.FeatureName");

        var text1 = "This is line 1 of text in the VerifyReadyDlg";

        var text2 = "This is the second line of custom text";

        var controlView     = Session.Database.OpenView("SELECT * FROM Control");
        controlView.Execute();

        var rec             = Session.Installer.CreateRecord(12);
        rec.StringData(1)   = "VerifyReadyDlg";    // Dialog_
        rec.StringData(2)   = "CustomVerifyText1"; // Control - can be any name
        rec.StringData(3)   = "Text";              // Type
        rec.IntegerData(4)  = 25;                  // X
        rec.IntegerData(5)  = 60;                  // Y
        rec.IntegerData(6)  = 320;                 // Width
        rec.IntegerData(7)  = 85;                  // Height
        rec.IntegerData(8)  = 2;                   // Attributes
        rec.StringData(9)   = "";                  // Property
        rec.StringData(10)  = vText1;              // Text
        rec.StringData(11)  = "";                  // Control_Next
        rec.StringData(12)  = "";                  // Help
        controlView.Modify(MsiViewModify.InsertTemporary, rec);

        rec                 = Session.Installer.CreateRecord(12);
        rec.StringData(1)   = "VerifyReadyDlg";    // Dialog_
        rec.StringData(2)   = "CustomVerifyText2"; // Control - any unique name
        rec.StringData(3)   = "Text";              // Type
        rec.IntegerData(4)  = 25;                  // X
        rec.IntegerData(5)  = 160;                 // Y
        rec.IntegerData(6)  = 320;                 // Width
        rec.IntegerData(7)  = 65;                  // Height
        rec.IntegerData(8)  = 2;                   // Attributes
        rec.StringData(9)   = "";                  // Property
        rec.StringData(10)  = text2;               // Text
        rec.StringData(11)  = "";                  // Control_Next
        rec.StringData(12)  = "";                  // Help
        controlView.Modify(MsiViewModify.InsertTemporary, rec);

        controlView.Close();
    }
    catch (exc1)
    {
        Session.Property("CA_EXCEPTION") = exc1.message ;
        LogException("UpdatePropsWithSelectedWebSite", exc1);
        return MsiActionStatus.Abort;
    }
    return MsiActionStatus.Ok;
}


function LogException(loc, exc)
{
    var record = Session.Installer.CreateRecord(0);
    record.StringData(0) = "Exception {" + loc + "}: " + exc.number + " : " + exc.message;
    Session.Message(MsgKind.Error + Icons.Critical + Buttons.btnOkOnly, record);
}

Javascript CA'sını bildirin:

<Fragment>
  <Binary Id="IisScript_CA" SourceFile="CustomActions.js" />

  <CustomAction Id="CA.UpdateReadyDialog"
              BinaryKey="IisScript_CA"
              JScriptCall="UpdateReadyDialog_CA"
              Execute="immediate"
              Return="check" />
</Fragment>

CA'yı bir düğmeye takın. Bu örnekte, CustomizeDlg'den İleri tıklatıldığında CA tetiklenir:

<UI ...>
  <Publish Dialog="CustomizeDlg" Control="Next" Event="DoAction" 
           Value="CA.UpdateReadyDialog" Order="1"/>
</UI>

İlgili SO Soru: Çalışma zamanında VerifyReadyDlg'de görüntülenecek metni nasıl ayarlayabilirim?


Şüphesiz bu, JScript windows komut dosyası dili değil, JavaScript DHTML komut dosyası dili olmalıdır. Muhtemelen biraz bilgiç, ama bazı insanlar için biraz kafa karıştırıcı olabilir.
caveman_dick

5

Tek tek yamanabilecek Bileşenleri kendi Parçalarının içine yerleştirin

Bu yapım ürün montajcılar ve bir fragmanında herhangi bir bileşeni eklerseniz içermesi gerektiğini yamalar her ikisi için gider tüm bu fragmana bileşenlerin. Bir yükleyici oluşturma durumunda, herhangi bir bileşen referansını kaçırırsanız, light.exe'den bir bağlantı hatası alırsınız. Ancak, bir yama yaptığınızda, bir parçaya tek bir bileşen başvurusu eklerseniz, o parçadan değiştirilen tüm bileşenler yamanızda görünecektir.

bunun gibi:

<Fragment>
    <DirectoryRef Id="SampleProductFolder">
        <Component Id="SampleComponent1" Guid="{C28843DA-EF08-41CC-BA75-D2B99D8A1983}" DiskId="1">
            <File Id="SampleFile1" Source=".\$(var.Version)f\Sample1.txt" />
        </Component>
    </DirectoryRef>
</Fragment>

<Fragment>
    <DirectoryRef Id="SampleProductFolder">
        <Component Id="SampleComponent2" Guid="{6CEA5599-E7B0-4D65-93AA-0F2F64402B22}" DiskId="1">
           <File Id="SampleFile2" Source=".\$(var.Version)f\Sample2.txt" />
        </Component>
    </DirectoryRef>
</Fragment>

<Fragment>
    <DirectoryRef Id="SampleProductFolder">
        <Component Id="SampleComponent3" Guid="{4030BAC9-FAB3-426B-8D1E-DC1E2F72C2FC}" DiskId="1">
           <File Id="SampleFile3" Source=".\$(var.Version)f\Sample3.txt" />
        </Component>
    </DirectoryRef>
</Fragment>

bunun yerine:

<Fragment>
    <DirectoryRef Id="SampleProductFolder">
        <Component Id="SampleComponent1" Guid="{C28843DA-EF08-41CC-BA75-D2B99D8A1983}" DiskId="1">
            <File Id="SampleFile1" Source=".\$(var.Version)\Sample1.txt" />
        </Component>

        <Component Id="SampleComponent2" Guid="{6CEA5599-E7B0-4D65-93AA-0F2F64402B22}" DiskId="1">
           <File Id="SampleFile2" Source=".\$(var.Version)\Sample2.txt" />
        </Component>

        <Component Id="SampleComponent3" Guid="{4030BAC9-FAB3-426B-8D1E-DC1E2F72C2FC}" DiskId="1">
           <File Id="SampleFile3" Source=".\$(var.Version)\Sample3.txt" />
        </Component>
    </DirectoryRef>
</Fragment>

Ayrıca, WiX.chm yardım dosyasındaki "Tamamen WiX Kullanımı" konusunu kullanarak yama eklerken, düzeltme ekini oluşturmak için bu yordamı kullanarak:

torch.exe -p -xi 1.0\product.wixpdb 1.1\product.wixpdb -out patch\diff.wixmst
candle.exe patch.wxs
light.exe patch.wixobj -out patch\patch.wixmsp
pyro.exe patch\patch.wixmsp -out patch\patch.msp -t RTM patch\diff.wixmst

bileşenleri sadece ayrı parçalar halinde kullanılarak product.wixpdb'nin 1.1 sürümüne sahip olmak yeterli değildir. Bu yüzden göndermeden önce ürününüzü doğru şekilde parçaladığınızdan emin olun.


5

EULA'yı Wix3.0 ve sonrasında yazdırma

1) wix kaynak kodunuzu derlediğinizde, light.exe komut satırında WixUIExtension.dll başvurmalıdır. Bunun için -ext komut satırı anahtarını kullanın.

2) WixUIExtension.dll dosyasına başvuruyu eklediğinizde, projeniz derlenemezse, bunun nedeni büyük olasılıkla İletişim Kutusu Kimliklerinin çakışmasıdır, yani projeniz WixUIExtension.dll'deki bazı standart iletişim kutuları ile aynı iletişim kutusu kimliklerini kullanıyordu, iletişim kutularınıza farklı kimlikler verin. Bu oldukça yaygın bir sorundur.

3) Lisans iletişim kutunuzda "LicenseText" kimliğine sahip ScrollableText denetimi olmalıdır. Wix, yazdırıldığında tam olarak bu kontrol adını arar.

<Control Id="LicenseText" Type="ScrollableText" X="20" Y="60" Width="330" Height="160" Sunken="yes" TabSkip="no">
    <Text SourceFile="License.rtf" />
</Control>

ve özel eylemi ifade eden bir Buton

<Control Type="PushButton" Id="PrintButton" Width="57" Height="17" X="19" Y="244" Text="Print">
    <Publish Event="DoAction" Value="PrintEula">1</Publish>
</Control>

4) CustomAction'ı Id = "PrintEula" ile şu şekilde tanımlayın:

<CustomAction Id="PrintEula" BinaryKey="WixUIWixca" DllEntry="PrintEula" Return="ignore" Execute="immediate" />

Not: BinaryKey, Wix3.0'da Wix2.0'a göre farklıdır ve tam olarak "WixUIWixca" (büyük / küçük harfe duyarlı) olmalıdır.

Kullanıcı düğmeye bastığında kendisine standart Yazıcı Seç İletişim Kutusu sunulacak ve oradan yazdırabilecektir.


5
  • Ürün sürümünü GUI'nin ilk ekranında bir yerde (küçük) görüntüleriz. Çünkü insanlar her seferinde doğru sürümü seçerken hata yapma eğilimindedir. (Ve geliştiricilerin yaş aramasını sağlayın ..)

  • TFSBuild'i farklı ortamlarımız için yapılandırmayla dönüşümler (.mst dosyaları) oluşturacak şekilde ayarladık. (Dağıtmamız gereken tüm ortamları biliyoruz).

Grant Holliday'in orijinal web günlüğü yazısı aşağıda olduğundan, içeriğini buraya yapıştırdım:


MSBuild XMLMarch 11 2008'den MSI Transform dosyaları oluşturmak için görev

Önceki yazımda, ortama özgü yapılandırma ayarlarını genel bir MSI paketinden ayırmak için MSI Transform (* .mst) dosyalarını nasıl kullanabileceğinizi anlattım.

Bu, yapılandırmanızda bir düzeyde esneklik sağlamasına rağmen, Transform dosyalarının iki alt tarafı vardır:

  1. İkili biçimdir
  2. Dönüştürme dosyasını "düzenleyemez" veya "görüntüleyemez". Hangi değişiklikleri içerdiğini görmek için uygulamanız veya yeniden oluşturmanız gerekir.

Neyse ki, Microsoft Windows Installer Nesne Kitaplığı'nı (c: windowssystem32msi.dll), MSI “veritabanlarını” açmak ve dönüşüm dosyaları oluşturmak için kullanabiliriz.

Krediler tekrar Alex Shevchuk - MSI'dan WiX'e - Bölüm 7 - VbScript ile bunu nasıl başaracağımızı göstermek için Transforms kullanarak kurulumu özelleştirme. Aslında yaptığım tüm Alex örneği alınır ve Interop.WindowsInstaller.dll kullanarak bir MSBuild görev uyguladım. MSBuild Görevi

İndir burada kaynak kodu ve örnek transforms.xml (~ 7KB Sıkıştırılmış VS2008 Çözümü)



2
WelcomeDlgTitle'ı yerelleştirme dosyamda yeniden tanımlıyoruz - harika çalışıyor! <String Id = "WelcomeDlgTitle"> {\ WixUI_Font_Bigger} [ProductName] [ProductVersion] Kurulum Sihirbazı'na Hoş Geldiniz </String>
saschabeaumont 20:34,

5

Bir yükleme paketini dağıtmadan önce içeriğini her zaman kontrol ederim.

Komut satırında (Terrences post'a göre) sadece basit bir çağrı açın ve komut satırını girin

msiexec /a Package.msi /qb TARGETDIR="%CD%\Extract" /l*vx "%CD\install.log%"

Bu işlem, paket içeriğini geçerli yolla birlikte 'Extract' alt dizinine çıkarır.


4

ORCA yerine MSI tablolarını görüntülemek için iyi bir araç olan InstEd kullanın . Ayrıca Transform -> Karşılaştır ile iki paket ayırma yeteneğine sahiptir ...

Ayrıca , ek işlevselliğe sahip bir Plus sürümü de mevcuttur. Ama aynı zamanda ücretsiz sürümü Orca için iyi bir alternatif sunuyor.


4

X86 / x64 uyumluluğu ile COM derlemeleri için .NET derlemelerini kaydetme

NB Bu parça aslında REGASM Assembly.dll / codebase ile aynıdır

Bu örnekte birkaç şey oluyor, işte kod ve daha sonra açıklayacağım ...

  <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <?include $(sys.CURRENTDIR)\Config.wxi?>
  <?if $(var.Win64) ?>
  <?define CLSIDRoots = "CLSID;Wow6432Node\CLSID"?>
  <?else ?>
  <?define CLSIDRoots = "CLSID"?>
  <?endif?>
  <!-- ASCOM Driver Assembly with related COM registrations -->
  <Fragment>
    <DirectoryRef Id="INSTALLLOCATION" />
  </Fragment>
  <Fragment>
    <ComponentGroup Id="cgAscomDriver">
      <Component Id="cmpAscomDriver" Directory="INSTALLLOCATION" Guid="{0267031F-991D-4D88-A748-00EC6604171E}">
        <File Id="filDriverAssembly" Source="$(var.TiGra.Astronomy.AWRDriveSystem.TargetPath)" KeyPath="yes" Vital="yes" Assembly=".net" AssemblyApplication="filDriverAssembly"  />
        <RegistryKey Root="HKCR" Key="$(var.DriverId)"  Action="createAndRemoveOnUninstall">
          <RegistryValue Type="string" Value="$(var.DriverTypeName)"/>
          <RegistryKey Key="CLSID">
            <RegistryValue Type="string" Value="$(var.DriverGuid)" />
          </RegistryKey>
        </RegistryKey>
        <?foreach CLSID in $(var.CLSIDRoots) ?>
        <RegistryKey Root="HKCR" Key="$(var.CLSID)" Action="none">
          <RegistryKey Key="$(var.DriverGuid)" Action="createAndRemoveOnUninstall">
            <RegistryValue Type="string" Value="$(var.DriverTypeName)"/>
            <RegistryKey Key="InprocServer32">
              <RegistryValue Type="string" Value="mscoree.dll" />
              <RegistryValue Type="string" Name="ThreadingModel" Value="Both"/>
              <RegistryValue Type="string" Name="Class" Value="$(var.DriverTypeName)"/>
              <RegistryValue Type="string" Name="Assembly" Value="!(bind.assemblyFullname.filDriverAssembly)" />
              <RegistryValue Type="string" Name="RuntimeVersion" Value="v2.0.50727"/>
              <RegistryValue Type="string" Name="CodeBase" Value="file:///[#filDriverAssembly]" />
              <RegistryKey Key="!(bind.fileVersion.filDriverAssembly)" >
                <RegistryValue Type="string" Name="Class" Value="$(var.DriverTypeName)"/>
                <RegistryValue Type="string" Name="Assembly" Value="!(bind.assemblyFullname.filDriverAssembly)" />
                <RegistryValue Type="string" Name="RuntimeVersion" Value="v2.0.50727"/>
                <RegistryValue Type="string" Name="CodeBase" Value="file:///[#filDriverAssembly]" />
              </RegistryKey>
            </RegistryKey>
            <RegistryKey Key="ProgId" Action="createAndRemoveOnUninstall">
              <RegistryValue Type="string" Value="$(var.DriverId)" />
            </RegistryKey>
            <RegistryKey Key="Implemented Categories" Action="createAndRemoveOnUninstall" >
              <RegistryKey Key="{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" Action="createAndRemoveOnUninstall" />
            </RegistryKey>
          </RegistryKey>
        </RegistryKey>
        <?endforeach?>
      </Component>
    </ComponentGroup>
  </Fragment>
</Wix>

Merak ediyorsanız, bu aslında bir ASCOM Teleskop Sürücüsü içindir .

İlk olarak, yukarıdan tavsiye aldım ve ayrı bir dosyada bazı platforma değişkenleri oluşturdum, XML aracılığıyla dağılmış olanları görebilirsiniz.

Üstteki if-then-else bölümü x86 ve x64 uyumluluğu ile ilgilidir. Montajım 'Herhangi bir CPU'yu hedefliyor, bu nedenle bir x64 sisteminde, bir kez 64 bit kayıt defterine ve bir kez 32 bit Wow6432Nodealanlara kaydetmem gerekiyor . İf-then-else beni bunun için ayarlar, değerler foreachdaha sonra bir döngüde kullanılır . Bu şekilde, kayıt defteri anahtarlarını yalnızca bir kez yazmam gerekiyor (KURU ilkesi).

Dosya öğesi, kurulmakta ve kaydedilmekte olan gerçek montaj dll'sini belirtir:

<File Id="filDriverAssembly" Source="$(var.TiGra.Astronomy.AWRDriveSystem.TargetPath)" KeyPath="yes" Vital="yes" Assembly=".net" AssemblyApplication="filDriverAssembly"  />

Devrimci bir şey yok, ama dikkat edin Assembly=".net"- bu özellik tek başına meclisin GAC'ye konmasına neden olur, ki bu istediğim DEĞİLDİR. Kullanılması AssemblyApplicationkendisine noktası arkasına niteliği basitçe GAC dosyayı koyarak Wix durdurma yöntemidir. Wix'in bunun bir .net derlemesi olduğunu bildiğine göre, derlemimin !(bind.assemblyFullname.filDriverAssembly)tam adını almak için XML'imdeki belirli bağlayıcı değişkenleri kullanmama izin veriyor .


3

DISABLEADVTSHORTCUTSÖzelliği, yükleyicinizde reklamı yapılan tüm kısayolları normal kısayollar olmaya zorlayacak şekilde ayarlayın ve anahtar yolu olarak kullanmak için bir sahte reg anahtarı eklemenize gerek yoktur.

<Property Id="DISABLEADVTSHORTCUTS" Value="1"/>

Bence Windows Installer 4.0 veya üstü bir gerekliliktir .


2

Güzel bir yapı ama deneyimlerime dayanarak bu koşulları nasıl ele aldığınızı merak ediyorum:

A. Yüklemelerinizin tümü aynı hedefe ulaşmış gibi görünüyor. Bir kullanıcının 3 sürümün tümünü aynı anda yüklemesi gerekiyorsa, işleminiz buna izin verecektir. Her çalıştırılabilir dosyanın hangi sürümünü tetiklediklerini açık bir şekilde söyleyebilirler mi?

B. TEST ve / veya EĞİTİM'de bulunan ancak henüz CANLI olmayan yeni dosyaları nasıl ele alırsınız?


Merhaba Blaine, A. Hayır. InstallName, svn: externals tarafından başvurulan tek dosya olan Config.wxi dosyasındadır. Bu, her kurulum için, yani her ürün için benzersizdir. Bu yüzden her sürüm için Kılavuzları değiştiriyoruz. B. GOTO A. :) Bunlar kendi UpgradeCode'ları olan ayrı MSI'lardır.
si618

1
Bu arada, sorumu neden bir soru ile cevapladığınızı anlıyorum, ancak yeterli sayıda rep puanı aldığınızda, lütfen sorunuzu cevap yorumlarına taşıyın, aksi takdirde iş parçacığını takip etmek zor olacaktır.
si618

2

İşte büyük web projeleri konuşlandırılmış dosya sayısı bir MSI (veya birleştirme modülü) yerleşik dosya sayısını eşleştiğini doğrulamak sağlayacak bir yoldur. Ben sadece bizim ana uygulama (hala geliştirme) karşı özel MSBuild görevi çalıştırmak ve oldukça görüntüleri, çoğunlukla görüntüleri, birkaç eksik dosyaları aldı ama birkaç javascript dosyaları üzerinden kaymış vardı!

Bu yaklaşım (WiX projesinin AfterBuild hedefine bağlanarak MSI'nın Dosya tablosuna bakmak) beklenen dosyaların tam listesine erişebileceğiniz diğer uygulama türleri için işe yarayabilir.


2

Bir yükleme kaldırmaya veya yeniden yüklemeye izin vermediğinde ve geri alınmadığında zorunlu yeniden yükleme gerçekleştirme.

Herhangi bir nedenle kaldırılmayan bir yüklemeyi geçersiz kılmak için kullanılan VBscript betiği.

Dim objShell
set objShell = wscript.createObject("wscript.shell")

iReturn = objShell.Run("CMD /K MsiExec.exe /I ""C:\Users\TheUser\Documents\Visual Studio 2010\Projects\InstallationTarget\HelloInstaller\bin\Debug\HelloInstaller.msi"" REINSTALLMODE=vomus REINSTALL=ALL",,True)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.