Làm cách nào để triển khai nâng cấp trình cài đặt WiX?


233

Trong công việc, chúng tôi sử dụng WiX để xây dựng các gói cài đặt. Chúng tôi muốn việc cài đặt sản phẩm X sẽ dẫn đến việc gỡ cài đặt phiên bản trước của sản phẩm đó trên máy đó.

Tôi đã đọc trên một số nơi trên Internet về một bản nâng cấp lớn nhưng không thể làm cho nó hoạt động. Bất cứ ai cũng có thể vui lòng chỉ định các bước chính xác mà tôi cần phải thực hiện để thêm gỡ cài đặt tính năng phiên bản trước vào WiX?

Câu trả lời:


189

Trong các phiên bản mới nhất (từ phiên bản 3.5.1315.0 beta), bạn có thể sử dụng phần tử MajorUpgrad thay vì sử dụng phần tử của riêng bạn.

Ví dụ: chúng tôi sử dụng mã này để nâng cấp tự động. Nó ngăn chặn hạ cấp, đưa ra thông báo lỗi cục bộ và cũng ngăn nâng cấp phiên bản giống hệt đã có (tức là chỉ các phiên bản thấp hơn được nâng cấp):

<MajorUpgrade
    AllowDowngrades="no" DowngradeErrorMessage="!(loc.NewerVersionInstalled)"
    AllowSameVersionUpgrades="no"
    />

8
Bài đăng trên blog của Bob Arnson về điều này cung cấp rất nhiều thông tin hay.
Dave Andersen

17
Lưu ý: Không được ghi lại ở bất cứ đâu, nhưng <MajorUpgrade>phần tử "" phải được đặt sau <Package> . candleMặt khác, đưa ra lỗi sau: "lỗi CNDL0107: Xác thực lược đồ không thành công với lỗi sau tại dòng 1, cột 473: Phần tử 'Sản phẩm' trong không gian tên ' schemas.microsoft.com/wix/2006/wi ' có phần tử con không hợp lệ ' MajorUpgrad 'trong không gian tên' schemas.microsoft.com/wix/2006/wi '. Danh sách các yếu tố có thể được mong đợi:' Gói '. ".
Cướp

21
+1 Câu trả lời này cần nhận được càng nhiều lượt upvote càng tốt; thật là hấp dẫn khi đi với một câu trả lời có 5 lần nâng cấp, nhưng sử dụng các phương pháp cũ hơn.
Lynn sụp đổ

1
Điểm tốt. Tôi đã thêm một ví dụ để mọi người không bỏ qua nó chỉ vì nó không có!
Kiến

6
Chỉ muốn chỉ ra rằng bạn không cần chỉ định AllowDowngradeshoặc AllowSameVersionUpgrades. Họ mặc định là không có.
Sáng

221

Cuối cùng tôi đã tìm thấy một giải pháp - Tôi đang đăng nó ở đây cho những người khác có thể có cùng một vấn đề (cả 5 bạn):

  • Thay đổi ID sản phẩm thành *
  • Dưới sản phẩm thêm Sau đây:

    <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> 
  • Trong InstallExecuteSequence thêm:

    <RemoveExistingProducts Before="InstallInitialize" /> 

Từ giờ trở đi mỗi khi tôi cài đặt sản phẩm, nó đã gỡ bỏ các phiên bản đã cài đặt trước đó.

Lưu ý: thay thế Id nâng cấp bằng GUID của riêng bạn


153
vâng, học WiX giống như cố gắng tìm ra những câu thần chú tối nghĩa mà ai đó quyết định 'có ý nghĩa' để thực hiện một hành động đơn giản. Kiểu như UNIX.
mmr

6
Ngoài ra, chính xác thì "Thay đổi ID sản phẩm thành *" để làm gì? Nó có tạo ra một Id sản phẩm mới mỗi lần không? Có hậu quả nào cho sản phẩm của bạn không có Id cố định nữa không? - nghe có vẻ quá mức.
Anthony

10
@Antony, @Dror Helper: Tôi khá chắc chắn rằng bạn không nên sử dụng "*" để tạo GUID mới tại đây. GUID bên trong (Id nâng cấp = "") phải được mã hóa cứng và cố định, và nó phải khớp với GUID trong thuộc tính (Product AdvancedCode = "") của bạn.
Jonathan Hartley

37
Tôi nghĩ có lẽ bạn nên chỉnh sửa ví dụ của mình ở đó để KHÔNG có GUID thực tế. Tôi chắc chắn mọi người sẽ sao chép và dán nó và sử dụng nguyên văn. Có thể sử dụng "CỦA BẠN-SẢN PHẨM-UPGRADECODE-GUID-TẠI ĐÂY"?
Brown

12
Có lỗi trong ví dụ của bạn. MSI ProductVersionchỉ hỗ trợ ba trường phiên bản; do đó, lĩnh vực thứ tư sẽ không được so sánh ở tất cả. Xem ghi chú trong VersionMin và VersionMax trong msdn.microsoft.com/en-us/l
Library / aa372379 (VS85) .aspx

89

Sau đây là loại cú pháp tôi sử dụng để nâng cấp chính:

<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>

Như @Brian Gillespie lưu ý, có những nơi khác để lên lịch cho các sản phẩm RemoveEx hiện tại tùy thuộc vào tối ưu hóa mong muốn. Lưu ý PUT-GUID-TẠI ĐÂY phải giống hệt nhau.


2
Tôi đang đọc phần "Nâng cấp và vá lỗi" trong cuốn sách của Nick Ramirez trên Wix tại đây và anh ta nói rằng nếu bạn lên lịch cho RemoveEx Hiện tại Sản phẩm sau InstallInitialize, thì bạn cũng phải lên lịch <InstallExecute After="RemoveExistingProducts" />. Ví dụ của bạn không có điều này - điều đó có nghĩa là cuốn sách sai?
Wim Coenen

3
Tôi không bao giờ lên lịch rõ ràng InstallExecute.
Rob Mensking

1
Tôi không. Trong WiX v3.6, Burn sẽ giúp thực hiện các nâng cấp nhỏ dễ dàng nhưng không có Burn, nó yêu cầu tương tác thủ công từ người dùng (phải cung cấp tùy chọn dòng lệnh) khiến cho Minor Upgrades trở nên vô dụng. :)
Rob Mensking

1
@RobMensching: làm thế nào để bạn tránh cài đặt phiên bản cũ hơn phiên bản mới hơn? Câu trả lời của bạn phù hợp với tôi (ví dụ "nâng cấp lớn" duy nhất mà tôi có thể biên dịch hoàn toàn với WiX v3.5.2519.0), nhưng có thể cài đặt phiên bản cũ hơn (sau đó, tôi thấy cả hai phiên bản trong "Thêm / Xóa chương trình ").
Christian Specht

4
Được rồi, tôi chỉ tìm thấy phần tử MajorUpgrad trong câu trả lời này thực hiện chính xác những gì tôi muốn, bao gồm cả việc ngăn chặn hạ cấp.
Christian Specht

40

Phần tử Nâng cấp bên trong phần tử Sản phẩm, kết hợp với lập lịch hành động thích hợp sẽ thực hiện gỡ cài đặt bạn sau. Hãy chắc chắn liệt kê các mã nâng cấp của tất cả các sản phẩm bạn muốn loại bỏ.

<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>

Lưu ý rằng, nếu bạn cẩn thận với các bản dựng của mình, bạn có thể ngăn mọi người vô tình cài đặt phiên bản cũ hơn của sản phẩm so với phiên bản mới hơn. Đó là những gì trường tối đa dành cho. Khi chúng tôi xây dựng trình cài đặt, chúng tôi đặt Nâng cấp tối đa cho phiên bản đang được xây dựng, nhưng Bao gồmMaximum = "không" để ngăn tình huống này.

Bạn có các lựa chọn liên quan đến việc lên lịch cho RemoveEx hiệnSản phẩm. Tôi thích lập lịch cho nó sau InstallFinalize (thay vì sau InstallInitialize như những người khác đã khuyến nghị):

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

Điều này để lại phiên bản trước của sản phẩm được cài đặt cho đến sau khi các tệp và khóa đăng ký mới được sao chép. Điều này cho phép tôi di chuyển dữ liệu từ phiên bản cũ sang phiên bản mới (ví dụ: bạn đã chuyển lưu trữ tùy chọn người dùng từ sổ đăng ký sang tệp XML, nhưng bạn muốn lịch sự và di chuyển cài đặt của họ). Việc di chuyển này được thực hiện trong một hành động tùy chỉnh bị trì hoãn ngay trước InstallFinalize.

Một lợi ích khác là hiệu quả: nếu có các tệp không thay đổi, Windows Installer không cần sao chép lại chúng khi bạn lên lịch sau InstallFinalize. Nếu bạn lên lịch sau InstallInitialize, phiên bản trước sẽ bị xóa hoàn toàn trước, và sau đó phiên bản mới được cài đặt. Điều này dẫn đến việc xóa và sao chép các tập tin không cần thiết.

Đối với các tùy chọn lập lịch khác, hãy xem chủ đề trợ giúp RemoveEx hiệnSản phẩm trong MSDN. Tuần này, liên kết là: http://msdn.microsoft.com/en-us/l Library / aa371197.aspx


2
@Brian Gillespie: "... nếu có các tệp không thay đổi ..." nghĩa là gì? Các tiêu chí để Windows Installer quyết định khi nào cần thay thế một tệp, Hội đồng, Phần mềm, Kích thước tệp, ...?
donttellya

2
@donttellya +1 đã học được điều này một cách khó khăn. RemoveExistingProductsđã được lên kế hoạch sau đó InstallFinalizevà các dll không được cập nhật vì assemblyVersion không thay đổi nhưng các trường khác như Hội đồng sản xuất. Tôi không muốn bị thương bởi thói quen so sánh tập tin - tôi chỉ muốn ứng dụng trước đó Gone
wal

16

Bạn có thể nên hỏi điều này trong danh sách gửi thư của người dùng WiX .

WiX được sử dụng tốt nhất với sự hiểu biết vững chắc về những gì Windows Installer đang làm. Bạn có thể xem xét nhận " Hướng dẫn dứt khoát cho Windows Installer ".

Hành động loại bỏ một sản phẩm hiện có là hành động RemoveEx hiện sản phẩm . Bởi vì hậu quả của những gì nó phụ thuộc vào nơi được lên lịch - cụ thể là, liệu lỗi có khiến sản phẩm cũ được cài đặt lại hay không và liệu các tệp không thay đổi có được sao chép lại hay không - bạn phải tự lên lịch cho nó.

RemoveExistingProductsxử lý <Upgrade>các phần tử trong cài đặt hiện tại, khớp @Idthuộc tính với UpgradeCode(được chỉ định trong <Product>phần tử) của tất cả các sản phẩm được cài đặt trên hệ thống. Các UpgradeCodeđịnh nghĩa một gia đình của các sản phẩm liên quan. Bất kỳ sản phẩm nào có Mã nâng cấp này, có phiên bản nằm trong phạm vi được chỉ định và trong đó UpgradeVersion/@OnlyDetectthuộc tính là no(hoặc bị bỏ qua), sẽ bị xóa.

Các tài liệu cho RemoveExistingProductsđề cập thiết lập UPGRADINGPRODUCTCODEtài sản. Điều đó có nghĩa là quá trình gỡ cài đặt cho sản phẩm bị xóa sẽ nhận được thuộc tính đó, có giá trị là Product/@Idsản phẩm được cài đặt.

Nếu cài đặt ban đầu của bạn không bao gồm một UpgradeCode, bạn sẽ không thể sử dụng tính năng này.


21
Không còn nghi ngờ gì nữa, Mike biết chính xác những gì anh ta đang nói, tất cả đều tôn trọng, nhưng điều đó khiến tôi thở dài tuyệt vọng khi suy nghĩ về sự lộn xộn trong tâm trí tôi với sự hiểu biết vững chắc về những gì Windows Installer đang làm. Trước khi tôi biết điều đó, tôi sẽ làm công việc tư vấn Java và .NET cho các khách hàng Doanh nghiệp ở các thị trấn trung tâm công nghệ tuyệt vời, vượt ra khỏi đường vành đai, điền vào các báo cáo TPS của tôi và tự hỏi tại sao cuộc sống dường như quá trống rỗng. Tôi nghĩ rằng dự án tiếp theo của tôi có thể cài đặt với NSIS, với tất cả các lỗi của nó, giống như ngôn ngữ giống như lắp ráp phi lý, nó không khiến tôi hiểu Windows Installer đang làm gì.
Jonathan Hartley

2
@Tartley - đi với InnoSetup, điều đó sẽ giúp bạn tiết kiệm ngôn ngữ giống như lắp ráp :) Hãy chắc chắn rằng bạn cũng lấy IStool, nó sẽ giúp ích rất nhiều. Ngoài ra - đồng ý rằng đối với các cài đặt đơn giản, tất cả điều này quá phức tạp, nhưng tôi nghĩ rằng chúng thực sự cần sự phức tạp này để cài đặt một cái gì đó như SQL Server 2008 ...
Roman Starkov

11

Tôi đã sử dụng trang này để giúp tôi hiểu những điều cơ bản về Nâng cấp WiX:

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

Sau đó, tôi đã tạo Trình cài đặt mẫu, (đã cài đặt tệp thử nghiệm), sau đó tạo Trình cài đặt nâng cấp (đã cài đặt 2 tệp thử nghiệm mẫu). Điều này sẽ cung cấp cho bạn một sự hiểu biết cơ bản về cách thức hoạt động của cơ chế.

Và như Mike đã nói trong cuốn sách từ Apress, "The Definitive Guide to Windows Installer", nó sẽ giúp bạn hiểu, nhưng nó không được viết bằng WiX.

Một trang web khác khá hữu ích là trang này:

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


Ví dụ trên trang không hoạt động như mong đợi wix.tramontana.co.hu/tutorial/upgrades-and-modularization/ cảm . Tôi đã chơi với nó. Thậm chí có thể hạ cấp khi trang nói rằng nó sẽ bị cấm
sergtk

10

Tôi đã đọc tài liệu WiX , các ví dụ đã tải xuống, nhưng tôi vẫn gặp nhiều vấn đề với việc nâng cấp. Nâng cấp nhỏ không thực hiện gỡ cài đặt các sản phẩm trước mặc dù có khả năng chỉ định những gỡ cài đặt đó. Tôi đã dành nhiều hơn một ngày để điều tra và thấy rằng WiX 3.5 đã tạo ra một thẻ mới để nâng cấp. Đây là cách sử dụng:

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

Nhưng lý do chính của vấn đề là tài liệu nói rằng sử dụng các tham số " REINSTALL = ALL REINSTALLMODE = nôn " để nâng cấp nhỏ và nhỏ, nhưng không nói rằng các tham số đó là FORBIDDEN cho các nâng cấp lớn - chúng chỉ đơn giản dừng hoạt động. Vì vậy, bạn không nên sử dụng chúng với các nâng cấp lớn.



7

Một điều quan trọng tôi đã bỏ lỡ trong các hướng dẫn trong một thời gian (bị đánh cắp từ http://www.tramontana.co.hu/wix/lesson4.php ) dẫn đến lỗi "Phiên bản khác của sản phẩm này đã được cài đặt":

* Cập nhật nhỏ có nghĩa là những thay đổi nhỏ đối với một hoặc một vài tệp trong đó thay đổi không đảm bảo thay đổi phiên bản sản phẩm (Major.minor.build). Bạn cũng không phải thay đổi GUID sản phẩm. Lưu ý rằng bạn luôn phải thay đổi Gói GUID khi bạn tạo tệp .msi mới khác với các tệp trước đó về mọi mặt. Trình cài đặt theo dõi các chương trình đã cài đặt của bạn và tìm thấy chúng khi người dùng muốn thay đổi hoặc xóa cài đặt bằng các GUID này. Sử dụng cùng một GUID cho các gói khác nhau sẽ gây nhầm lẫn cho Trình cài đặt.

Nâng cấp nhỏ biểu thị những thay đổi trong đó phiên bản sản phẩm sẽ thay đổi. Sửa đổi thuộc tính Phiên bản của thẻ Sản phẩm. Sản phẩm sẽ giữ nguyên, vì vậy bạn không cần thay đổi GUID sản phẩm, nhưng, tất nhiên, hãy nhận Gói GUID mới.

Nâng cấp lớn biểu thị những thay đổi đáng kể như đi từ phiên bản đầy đủ này sang phiên bản khác. Thay đổi mọi thứ: Thuộc tính phiên bản, GUID sản phẩm và gói.


3
Gói: Loại id: Mô tả AutogenGuid: Mã gói GUID cho sản phẩm hoặc mô-đun hợp nhất. Khi biên dịch một sản phẩm, không nên đặt thuộc tính này để cho phép mã gói được tạo cho mỗi bản dựng. Khi biên dịch mô-đun hợp nhất, thuộc tính này phải được đặt thành hướng dẫn mô đun hóa. ---- vì vậy chúng ta không cần chú ý đến id gói, phải không?
Cooper.Wu

Liên kết của bạn đã chết
bam500

5

Tôi đang sử dụng phiên bản WiX (3.0) mới nhất và không thể hoạt động ở trên. Nhưng điều này đã làm việc:

<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>

Lưu ý rằng PUT-GUID-TẠI ĐÂY phải giống với GUID mà bạn đã xác định trong thuộc tính Nâng cấp Mã của Sản phẩm.


2

Dưới đây làm việc cho tôi.

<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>

Vui lòng đảm bảo rằng Mã nâng cấp trong Sản phẩm khớp với Id trong Nâng cấp.


1

Đây là những gì làm việc cho tôi, ngay cả với lớp DOWN lớn :

<Wix ...>
  <Product ...>
    <Property Id="REINSTALLMODE" Value="amus" />
    <MajorUpgrade AllowDowngrades="yes" />
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.