Bagaimana cara menerapkan pembaruan penginstal WiX?

233

Di tempat kerja kami menggunakan WiX untuk membangun paket instalasi. Kami ingin instalasi produk X akan menghapus instalasi versi sebelumnya dari produk itu di mesin itu.

Saya telah membaca di beberapa tempat di Internet tentang peningkatan besar tetapi tidak berhasil. Adakah yang bisa menentukan langkah-langkah persis yang harus saya ambil untuk menambahkan menghapus fitur versi sebelumnya ke WiX?

Dror Helper
sumber

Jawaban:

189

Dalam versi terbaru (dari 3.5.1315.0 beta), Anda dapat menggunakan elemen MajorUpgrade alih-alih menggunakan milik Anda.

Misalnya, kami menggunakan kode ini untuk melakukan peningkatan otomatis. Ini mencegah downgrade, memberikan pesan kesalahan yang dilokalkan, dan juga mencegah pemutakhiran versi identik yang sudah ada (yaitu hanya versi yang lebih rendah yang ditingkatkan):

<MajorUpgrade
    AllowDowngrades="no" DowngradeErrorMessage="!(loc.NewerVersionInstalled)"
    AllowSameVersionUpgrades="no"
    />
Semut
sumber
8
Posting blog Bob Arnson tentang ini memberikan banyak informasi bagus.
Dave Andersen
17
Catatan: Tidak didokumentasikan di mana saja, tetapi <MajorUpgrade>elemen " " harus ditempatkan setelahnya <Package> . Jika tidak, candleberikan kesalahan berikut: "kesalahan CNDL0107: Validasi skema gagal dengan kesalahan berikut di baris 1, kolom 473: Elemen 'Produk' di namespace ' schemas.microsoft.com/wix/2006/wi ' memiliki elemen anak yang tidak valid ' MajorUpgrade 'in namespace' schemas.microsoft.com/wix/2006/wi '. Daftar elemen yang mungkin diharapkan:' Paket '. "
Rob W
21
+1 Jawaban ini perlu menerima sebanyak mungkin upvotes; sangat menggoda untuk pergi dengan jawaban yang memiliki 5x upvotes, tetapi menggunakan pendekatan yang lebih tua.
Lynn Crumbling
1
Poin bagus. Saya telah menambahkan contoh agar orang tidak mengabaikannya hanya karena tidak memilikinya!
Semut
6
Hanya ingin menunjukkan Anda tidak perlu menentukan AllowDowngradesatau AllowSameVersionUpgrades. Mereka sudah default ke no.
Luminous
221

Akhirnya saya menemukan solusi - Saya mempostingnya di sini untuk orang lain yang mungkin memiliki masalah yang sama (kalian semua 5):

  • Ubah ID produk menjadi *
  • Di bawah produk tambahkan yang berikut ini:

    <Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
    <Upgrade Id="YOUR_GUID">  
       <UpgradeVersion
          Minimum="1.0.0.0" Maximum="99.0.0.0"
          Property="PREVIOUSVERSIONSINSTALLED"
          IncludeMinimum="yes" IncludeMaximum="no" />
    </Upgrade> 
  • Di bawah InstallExecuteSequence, tambahkan:

    <RemoveExistingProducts Before="InstallInitialize" /> 

Mulai sekarang setiap kali saya menginstal produk itu menghapus versi yang diinstal sebelumnya.

Catatan: ganti Id peningkatan dengan GUID Anda sendiri

Dror Helper
sumber
153
ya, belajar WiX seperti mencoba mencari tahu mantra yang tidak jelas yang seseorang putuskan 'masuk akal' untuk melakukan tindakan sederhana. Jenis seperti UNIX.
mmr
6
Juga, apa sebenarnya yang dilakukan "Ubah ID produk *"? Apakah ini menghasilkan ID produk baru setiap kali? Apakah ada konsekuensi terhadap produk Anda yang tidak memiliki Id tetap lagi? - Kedengarannya seperti berlebihan.
Anthony
10
@Antony, @Dror Helper: Saya cukup yakin Anda tidak boleh menggunakan "*" untuk menghasilkan GUID baru di sini. GUID di dalam (Upgrade Id = "") harus dikodekan dan diperbaiki, dan itu harus cocok dengan GUID dalam atribut (Product UpgradeCode = "") Anda.
Jonathan Hartley
37
Saya pikir Anda mungkin harus mengedit contoh Anda di sana untuk TIDAK memiliki GUID yang sebenarnya. Saya yakin orang-orang akan menyalin dan menempel itu dan menggunakannya kata demi kata. Mungkin menggunakan "PRODUK-ANDA-UPGRADECODE-PANDUAN-DI SINI"?
Brown
12
Ada bug dalam contoh Anda. MSI ProductVersionhanya mendukung tiga bidang versi; oleh karena itu bidang keempat tidak akan dibandingkan sama sekali. Lihat catatan di bawah VersionMin dan VersionMax di msdn.microsoft.com/en-us/library/aa372379(VS.85).aspx
Sridhar Ratnakumar
89

Berikut ini adalah jenis sintaks yang saya gunakan untuk peningkatan besar:

<Product Id="*" UpgradeCode="PUT-GUID-HERE" Version="$(var.ProductVersion)">
 <Upgrade Id="PUT-GUID-HERE">
    <UpgradeVersion OnlyDetect="yes" Minimum="$(var.ProductVersion)" Property="NEWERVERSIONDETECTED" IncludeMinimum="no" />
    <UpgradeVersion OnlyDetect="no" Maximum="$(var.ProductVersion)" Property="OLDERVERSIONBEINGUPGRADED" IncludeMaximum="no" />
</Upgrade>

<InstallExecuteSequence>
    <RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>

Sebagai @Brian Gillespie mencatat ada tempat lain untuk menjadwalkan RemoveExistingProducts tergantung pada optimasi yang diinginkan. Perhatikan bahwa PUT-GUID-HERE harus identik.

Rob Mensching
sumber
2
Saya membaca bagian "Memutakhirkan dan Menambal" di buku Nick Ramirez di Wix di sini, dan dia menyatakan bahwa jika Anda menjadwalkan RemoveExistingProducts setelah InstallInitialize, maka Anda HARUS juga menjadwalkan <InstallExecute After="RemoveExistingProducts" />. Contoh Anda tidak memiliki ini - apakah itu berarti bukunya salah?
Wim Coenen
3
Saya tidak pernah secara eksplisit menjadwalkan InstallExecute.
Rob Mensching
1
Bukan saya. Di WiX v3.6, Burn akan membuat upgrade minor mudah dieksekusi tetapi tanpa Burn itu memerlukan interaksi manual dari pengguna (harus menyediakan opsi baris perintah) yang membuat Minor Upgrade pada dasarnya tidak berguna. :)
Rob Mensching
1
@RobMensching: bagaimana Anda menghindari instalasi versi yang lebih lama dari yang lebih baru? Jawaban Anda berfungsi untuk saya (satu-satunya contoh "peningkatan besar" yang dapat saya kompilasi sama sekali dengan WiX v3.5.2519.0), tetapi mungkin untuk menginstal versi yang lebih lama (setelah itu, saya melihat kedua versi di "Tambah / Hapus Program ").
Christian Specht
4
Oke, saya baru saja menemukan elemen MajorUpgrade dalam jawaban ini yang melakukan persis apa yang saya inginkan, termasuk mencegah penurunan peringkat.
Christian Specht
40

Elemen Upgrade di dalam elemen Produk, dikombinasikan dengan penjadwalan tindakan yang tepat akan melakukan uninstall yang Anda cari. Pastikan untuk mencantumkan kode peningkatan semua produk yang ingin Anda hapus.

<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="00000000-0000-0000-0000-000000000000">
  <UpgradeVersion Minimum="1.0.0.0" Maximum="1.0.5.0" Property="PREVIOUSVERSIONSINSTALLED" IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>

Perhatikan bahwa, jika Anda berhati-hati dengan bangunan Anda, Anda dapat mencegah orang lain memasang versi produk Anda yang lebih lama secara tidak sengaja pada versi yang lebih baru. Untuk itulah bidang Maksimal. Ketika kami membangun installer, kami mengatur UpgradeVersion Maximum ke versi yang sedang dibangun, tetapi IncludeMaximum = "no" untuk mencegah skenario ini.

Anda memiliki pilihan mengenai penjadwalan RemoveExistingProducts. Saya lebih suka menjadwalkannya setelah InstallFinalize (daripada setelah InstallInitialize seperti yang direkomendasikan orang lain):

<InstallExecuteSequence>
  <RemoveExistingProducts After="InstallFinalize"></RemoveExistingProducts>
</InstallExecuteSequence>

Ini meninggalkan versi produk yang diinstal sebelumnya hingga file baru dan kunci registri disalin. Ini memungkinkan saya memigrasikan data dari versi lama ke yang baru (misalnya, Anda telah mengubah penyimpanan preferensi pengguna dari registri ke file XML, tetapi Anda ingin sopan dan memigrasi pengaturannya). Migrasi ini dilakukan dalam tindakan kustom yang ditangguhkan sebelum InstallFinalize.

Manfaat lain adalah efisiensi: jika ada file tidak berubah, Pemasang Windows tidak repot menyalinnya lagi ketika Anda menjadwalkan setelah InstallFinalize. Jika Anda menjadwalkan setelah InstallInitialize, versi sebelumnya sepenuhnya dihapus terlebih dahulu, dan kemudian versi baru diinstal. Ini menghasilkan penghapusan yang tidak perlu dan penyalinan ulang file.

Untuk opsi penjadwalan lainnya, lihat topik bantuan RemoveExistingProducts di MSDN. Minggu ini, tautannya adalah: http://msdn.microsoft.com/en-us/library/aa371197.aspx

Brian Gillespie
sumber
2
@ Brian Gillespie: apa artinya "... jika ada file yang tidak diubah ..."? Apa kriteria untuk Penginstal Windows untuk memutuskan kapan harus mengganti file, AssemblyVersion, AssemblyFileVersion, ukuran file, ...?
donttellya
2
@donttellya +1 mempelajari ini dengan cara yang sulit. RemoveExistingProductsdijadwalkan setelah InstallFinalizedan dll tidak diperbarui karena assemblyVersion tidak berubah tetapi bidang lain seperti AssemblyProduct adalah. Saya tidak ingin berada dalam belas kasihan dari rutin perbandingan file - saya hanya ingin aplikasi sebelumnya PERGI
wal
16

Anda mungkin lebih baik menanyakan hal ini pada milis pengguna WiX .

WiX paling baik digunakan dengan pemahaman yang kuat tentang apa yang dilakukan Penginstal Windows. Anda mungkin mempertimbangkan untuk mendapatkan " Panduan Definitif untuk Pemasang Windows ".

Tindakan yang menghapus produk yang ada adalah tindakan RemoveExistingProducts . Karena konsekuensi dari apa yang dilakukannya tergantung pada tempat dijadwalkannya - yaitu, apakah kegagalan menyebabkan produk lama diinstal ulang, dan apakah file yang tidak diubah disalin lagi - Anda harus menjadwalkannya sendiri.

RemoveExistingProductsmemproses <Upgrade>elemen dalam instalasi saat ini, mencocokkan @Idatribut dengan UpgradeCode(ditentukan dalam <Product>elemen) dari semua produk yang diinstal pada sistem. Yang UpgradeCodemendefinisikan keluarga produk terkait. Produk apa pun yang memiliki UpgradeCode ini, yang versinya termasuk dalam kisaran yang ditentukan, dan di mana UpgradeVersion/@OnlyDetectatributnya no(atau dihilangkan), akan dihapus.

Dokumentasi untuk RemoveExistingProductsmenyebutkan pengaturan UPGRADINGPRODUCTCODEproperti. Ini berarti bahwa proses penghapusan instalasi untuk produk yang dihapus menerima properti itu, yang nilainya adalah Product/@Iduntuk produk yang sedang diinstal.

Jika instalasi asli Anda tidak menyertakan UpgradeCode, Anda tidak akan dapat menggunakan fitur ini.

Mike Dimmick
sumber
21
Tidak diragukan lagi Mike tahu persis apa yang dia bicarakan, semua dengan hormat, tetapi itu membuat saya menghela nafas dengan putus asa untuk merenungkan mengacaukan pikiran saya dengan pemahaman yang kuat tentang apa yang dilakukan Penginstal Windows. Sebelum saya mengetahuinya, saya akan melakukan pekerjaan konsultasi Java dan .NET untuk klien Perusahaan di kota-kota pusat teknologi yang luar biasa, di luar jalan lingkar, mengisi laporan TPS saya dan bertanya-tanya mengapa hidup tampak begitu kosong. Saya pikir proyek saya berikutnya mungkin menginstal dengan NSIS, yang untuk semua kesalahannya, seperti bahasa perakitan yang tidak masuk akal, itu tidak membuat saya mengerti apa yang dilakukan Penginstal Windows.
Jonathan Hartley
2
@ Tartley - pergi dengan InnoSetup, itu akan menghemat bahasa seperti perakitan :) Pastikan Anda mengambil IStool juga, itu sangat membantu. Juga - setuju bahwa untuk instalasi sederhana semua ini terlalu rumit, tapi saya pikir mereka benar-benar membutuhkan kompleksitas ini untuk menginstal sesuatu seperti SQL Server 2008 ...
Roman Starkov
11

Saya menggunakan situs ini untuk membantu saya memahami dasar-dasar tentang Peningkatan WiX:

http://wix.tramontana.co.hu/tutorial/upgrades-and-modularization

Setelah itu saya membuat Penginstal sampel, (menginstal file uji), kemudian membuat installer Upgrade (menginstal 2 file uji sampel). Ini akan memberi Anda pemahaman dasar tentang bagaimana mekanisme bekerja.

Dan seperti yang dikatakan Mike dalam buku dari Apress, "The Definitive Guide to Windows Installer", itu akan membantu Anda memahami, tetapi tidak ditulis menggunakan WiX.

Situs lain yang cukup membantu adalah situs ini:

http://www.wixwiki.com/index.php?title=Main_Page

CheGueVerra
sumber
Contoh pada halaman tidak berfungsi seperti yang diharapkan wix.tramontana.co.hu/tutorial/upgrades-and-modularization/… . Saya bermain dengannya. Bahkan mungkin untuk menurunkan versi ketika halaman menyatakan bahwa itu akan dilarang
sergtk
10

Saya membaca dokumentasi WiX , contoh-contoh yang diunduh, tetapi saya masih memiliki banyak masalah dengan peningkatan. Pembaruan kecil tidak mengeksekusi pencopotan produk sebelumnya meskipun ada kemungkinan untuk menentukan pencopotan tersebut. Saya menghabiskan lebih dari satu hari untuk penyelidikan dan menemukan bahwa WiX 3.5 memperkenalkan tag baru untuk peningkatan. Ini adalah penggunaannya:

<MajorUpgrade Schedule="afterInstallInitialize"
        DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." 
        AllowDowngrades="no" />

Tetapi alasan utama masalah adalah bahwa dokumentasi mengatakan untuk menggunakan parameter " REINSTALL = ALL REINSTALLMODE = vomus " untuk peningkatan kecil dan kecil, tetapi tidak mengatakan bahwa parameter tersebut DILARANG untuk peningkatan besar - mereka hanya berhenti bekerja. Jadi Anda tidak harus menggunakannya dengan peningkatan besar.

Sasha
sumber
7

Saya sarankan melihat tutorial Alex Shevchuk. Dia menjelaskan "peningkatan besar" melalui WiX dengan contoh langsung di Dari MSI ke WiX, Bagian 8 - Peningkatan Besar .

Faraz
sumber
Terima kasih atas tautan ke artikel itu ... sangat fantastis!
Robert P
7

Satu hal penting yang saya lewatkan dari tutorial untuk sementara waktu (dicuri dari http://www.tramontana.co.hu/wix/lesson4.php ) yang menghasilkan kesalahan "Versi lain dari produk ini sudah diinstal":

* Pembaruan kecil kecil berarti perubahan kecil ke satu atau beberapa file di mana perubahan tidak menjamin mengubah versi produk (major.minor.build). Anda juga tidak perlu mengubah GUID Produk. Perhatikan bahwa Anda selalu harus mengubah GUID Paket ketika Anda membuat file .msi baru yang berbeda dari yang sebelumnya dalam hal apa pun. Pemasang melacak program yang Anda instal dan menemukannya ketika pengguna ingin mengubah atau menghapus instalasi menggunakan GUID ini. Menggunakan GUID yang sama untuk paket yang berbeda akan membingungkan Penginstal.

Upgrade kecil menunjukkan perubahan di mana versi produk sudah akan berubah. Ubah atribut Versi dari tag Produk. Produk akan tetap sama, jadi Anda tidak perlu mengubah GUID Produk tetapi, tentu saja, dapatkan GUID Paket baru.

Peningkatan besar menunjukkan perubahan signifikan seperti beralih dari satu versi lengkap ke versi lainnya. Ubah semuanya: Atribut versi, GUID Produk dan Paket.

Daniel Morritt
sumber
3
Paket: Jenis id: Deskripsi AutogenGuid: Kode paket GUID untuk produk atau modul gabungan. Saat mengkompilasi produk, atribut ini tidak boleh ditetapkan untuk memungkinkan kode paket dihasilkan untuk setiap build. Saat menyusun modul gabungan, atribut ini harus disetel ke panduan modularisasi. ---- jadi kita tidak perlu memperhatikan id paket, kan?
Cooper.Wu
Tautan Anda mati
bam500
5

Saya menggunakan versi terbaru WiX (3.0) dan tidak bisa berfungsi di atas. Tapi ini berhasil:

<Product Id="*" UpgradeCode="PUT-GUID-HERE" ... >

<Upgrade Id="PUT-GUID-HERE">
  <UpgradeVersion OnlyDetect="no" Property="PREVIOUSFOUND"
     Minimum="1.0.0.0"  IncludeMinimum="yes"
     Maximum="99.0.0.0" IncludeMaximum="no" />
</Upgrade>

Perhatikan bahwa PUT-GUID-HERE harus sama dengan GUID yang telah Anda tetapkan dalam properti UpgradeCode Produk.

Merill Fernando
sumber
2

Di bawah ini bekerja untuk saya.

<Product Id="*" Name="XXXInstaller" Language="1033" Version="1.0.0.0" 
    Manufacturer="XXXX" UpgradeCode="YOUR_GUID_HERE">
<Package InstallerVersion="xxx" Compressed="yes"/>
<Upgrade Id="YOUR_GUID_HERE">
    <UpgradeVersion Property="REMOVINGTHEOLDVERSION" Minimum="1.0.0.0" 
        RemoveFeatures="ALL" />
</Upgrade>
<InstallExecuteSequence>
    <RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>

Pastikan bahwa UpgradeCode dalam Produk cocok dengan Id dalam Peningkatan.

NishantJ
sumber
1

Inilah yang bekerja untuk saya, bahkan dengan kelas BAWAH utama :

<Wix ...>
  <Product ...>
    <Property Id="REINSTALLMODE" Value="amus" />
    <MajorUpgrade AllowDowngrades="yes" />
Gian Marco Gherardi
sumber