Yalnızca kaldırma işleminde (MSI aracılığıyla) gerçekleşen bir WiX özel eylemi nasıl eklenir?


161

Kaldırma sırasında tüm dizini silmek için bir MSI yükleyicisini ( WiX aracılığıyla oluşturuldu ) değiştirmek istiyorum .

WiX'teki RemoveFileve RemoveFolderseçeneklerini anlıyorum , ancak bunlar yükleme işleminden sonra oluşturulan içeriğin bulunduğu tüm klasörü tekrar tekrar silmek için yeterince sağlam değil.

Benzer Stack Overflow sorusunu fark ettim WiX'i kaldırırken dosyaları kaldırma , ancak bu, klasörü silmek için bir toplu iş komut dosyasına çağrı kullanarak daha kolay yapıp yapamayacağını merak ediyordum.

Bu benim WiX'i ilk kez kullanıyorum ve hala özel eylemleri askıya alıyorum . Kaldırma işleminde toplu iş komut dosyası çalıştıracak özel bir işlemin temel örneği nedir?

Yanıtlar:


188

DÜZENLEME : Belki şu anda hemen cevaba bakınız .


Bu konu uzun süredir baş ağrısıdır. Sonunda anladım. Çevrimiçi bazı çözümler var, ancak hiçbiri gerçekten çalışmıyor. Ve tabii ki hiçbir belge yok. Bu nedenle, aşağıdaki grafikte, kullanılması önerilen birkaç özellik ve çeşitli kurulum senaryoları için sahip oldukları değerler vardır:

alternatif metin

Yani benim durumumda sadece kaldırma işlemlerinde çalışacak bir CA istedim - yükseltmeler değil, onarımlar veya değişiklikler değil. Yukarıdaki tabloya göre kullanmak zorunda kaldım

<Custom Action='CA_ID' Before='other_CA_ID'>
        (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>

Ve işe yaradı!


25
Bu grafikteki değerler doğru mu? Neden REMOVE = "ALL" eklemeniz gerekiyor? NOT UPGRADINGPRODUCTCODE yalnızca bir kaldırma işlemi için (grafiğe göre) geçerlidir, bu nedenle (UPGRADINGPRODUCTCODE DEĞİL) VE (REMOVE = "ALL") yalnızca bir kaldırma işleminde de geçerlidir. REMOVE = "ALL" gereksiz görünüyor.
Todd Ropog

2
@ToddRopog ile aynı fikirdeyim - Örnek ve doğruluk tablosu aynı fikirde değil. Gerçekten doğru mu?
Tim Long

19
Doğruluk tablosu biraz yanlış. UPGRADINGPRODUCTCODE ilk kurulum için de geçerli
Neil


1
Lütfen onaylayın: Yüklü ve MONTAJ farklı şeylerdir, yalnızca Yüklü Windows Installer tarafından ayarlanır. KURULDU çalıştığını düşünmüyorum.
Micha Wiedenmann

140

Yaluna'nın cevabı ile ilgili birden fazla sorun var , özellik adları büyük / küçük harfe duyarlı, Installeddoğru yazım ( INSTALLEDişe yaramayacak). Yukarıdaki tablo şöyle olmalıydı:

resim açıklamasını buraya girin

Ayrıca tam bir onarım ve kaldırma gerçek özellik değerlerini varsayarsak:

resim açıklamasını buraya girin

WiX İfade sözdizimi belgelerine diyor ki:

Bu ifadelerde, özellik adlarını kullanabilirsiniz (büyük / küçük harfe duyarlı olduklarını unutmayın).

Özellikler Windows Installer Kılavuzunda belgelenmiştir (örn. Yüklü )

EDIT: İlk tabloya küçük düzeltme; açıkça "Kaldır" da sadece REMOVEolmak ile olabilir True.


3
KALDIR ayrıca Değişim için ayarlanmış gibi görünüyor
szx

2
'Yükseltme' sütunu, eski sürümün kaldırma sırası veya yeni sürümün yükleme sırası sırasında mı?
Nick Whaley

1
@NickWhaley: Bir süredir bakmadım ama "Yükselt" seçeneğinin sadece kurulu olandan daha büyük bir sürüm yüklerken olduğuna inanıyorum.
ahmd0

1
@ ahmd0, elbette. Ancak RemoveExistingProducts içinde tamamen farklı bir özellik kümesine sahip iç içe bir yükleme var. Yani senin 'Yükseltme' sütununda budur. Yükseltmenin geri kalanı 'Yükle' sütunuyla aynıdır.
Nick Whaley

1
@NickWhaley: REMOVE seçeneği, bir önceki sürümün kaldırıcısının yürütülmesi sırasında Major Upgrades (yani 1.0.0 ila 2.0.0, 1.0.0 ila 1.1.0 değil) için geçerli olacaktır. Yeni sürümler yüklemesinde Büyük bir Yükseltme sırasında Özel Eylem çalıştırmak için, sürüm yükseltmesi için Yükseltme MSI tablonuzda tanımlanan ActionProperty'ye başvurmanız gerekir. symantec.com/connect/articles/msi-upgrade-overview msdn.microsoft.com/en-us/library/aa372379%28v=vs.85%29.aspx
Chaoix

48

Bunu özel bir işlemle yapabilirsiniz. Özel işleminize aşağıdakileri içeren bir referans ekleyebilirsiniz <InstallExecuteSequence>:

<InstallExecuteSequence>
...
  <Custom Action="FileCleaner" After='InstallFinalize'>
          Installed AND NOT UPGRADINGPRODUCTCODE</Custom>

Ardından, Eyleminizi aşağıdakiler altında tanımlamanız gerekecektir <Product>:

<Product> 
...
  <CustomAction Id='FileCleaner' BinaryKey='FileCleanerEXE' 
                ExeCommand='' Return='asyncNoWait'  />

FileCleanerEXE bir ikili (benim durumumda özel eylemi yapan küçük bir c ++ programı) nerede de tanımlanmıştır <Product>:

<Product> 
...
  <Binary Id="FileCleanerEXE" SourceFile="path\to\fileCleaner.exe" />

Bunun gerçek hilesi Installed AND NOT UPGRADINGPRODUCTCODE, özel eylemin koşulu, eyleminizin her yükseltmede çalıştırılacağı durumdur (çünkü bir yükseltme gerçekten bir kaldırmadır ve yeniden yükleyin). Hangi dosyaları siliyorsanız yükseltme sırasında muhtemelen istemezsiniz.

Bir yan notta: Sağladığı güç ve kontrol nedeniyle toplu komut dosyası yerine eylemi yapmak için C ++ programı gibi bir şey kullanma derdinden geçmenizi öneririm - ve "cmd istemi" penceresinin yanıp sönmesini önleyebilirsiniz yükleyiciniz çalışır.


3
25 upvotes ama kabul edilen bir cevap değil. Tesisatçıların dünyasına hoş geldiniz! :)
Christopher Painter

4
Bu gerçekten işe yaramıyor. Kendi yükleme klasörünüzde yüklü olan bir fileCleaner.exe dosyasını yürütmek istediğinizde, bu bir tavuk ve yumurta sorunu CustomActionolacaktır : "After = 'InstallFinalize'" yürütülür. Bu noktada, tüm dosyalar Kurulum klasöründen kaldırılır. Ayrıca fileCleaner.exe. Bu nedenle, bir CustomAction üzerinden çalıştıramazsınız. Bu cevap basitçe yanlış. 42 upvotes merak ediyorum!
Simon

40

Bir toplu iş komut dosyasıyla ilgili en büyük sorun, kullanıcı iptal'i tıkladığında (veya yükleme sırasında bir sorun olduğunda) geri alma işlemidir. Bu senaryoyu işlemenin doğru yolu, RemoveFiles tablosuna geçici satırlar ekleyen bir CustomAction oluşturmaktır. Bu şekilde Windows Installer geri alma durumlarını sizin için işler. Çözümü gördüğünüzde çok daha basit.

Her neyse, yalnızca kaldırma işlemi sırasında bir eylemin yürütülmesi için aşağıdakileri içeren bir Koşul öğesi ekleyin:

REMOVE ~= "ALL"

~ = karşılaştırma case duyarsız diyor (TÜM her zaman uppercaesd olduğunu düşünüyorum bile). Daha fazla bilgi için Koşullar Sözdizimi ile ilgili MSI SDK belgelerine bakın .

Not: Oturduğum ve "Ah, toplu iş dosyası bir kurulum paketinde iyi bir çözüm olurdu" diye düşündüğüm bir durum hiç olmadı. Aslında, içinde bir toplu iş dosyası olan bir yükleme paketi bulmak, yalnızca ürünü geri ödeme için geri göndermemi teşvik eder.


Toplu bir komut dosyası kullanmak üzereydim ve daha sonra PS bölümünü gördüm. Beni kurtardığın için teşekkürler :) Kaldır ~ = "ALL" benim için çalıştı.
ArNumb

12

İşte kullanmak için yerleşik şeyler daha sezgisel hissediyorum bir dizi özellik. Koşullar, ahmd0 tarafından sağlanan doğruluk tablosuna dayanmaktadır.

<!-- truth table for installer varables (install vs uninstall vs repair vs upgrade) https://stackoverflow.com/a/17608049/1721136 -->
 <SetProperty Id="_INSTALL"   After="FindRelatedProducts" Value="1"><![CDATA[Installed="" AND PREVIOUSVERSIONSINSTALLED=""]]></SetProperty>
 <SetProperty Id="_UNINSTALL" After="FindRelatedProducts" Value="1"><![CDATA[PREVIOUSVERSIONSINSTALLED="" AND REMOVE="ALL"]]></SetProperty>
 <SetProperty Id="_CHANGE"    After="FindRelatedProducts" Value="1"><![CDATA[Installed<>"" AND REINSTALL="" AND PREVIOUSVERSIONSINSTALLED<>"" AND REMOVE=""]]></SetProperty>
 <SetProperty Id="_REPAIR"    After="FindRelatedProducts" Value="1"><![CDATA[REINSTALL<>""]]></SetProperty>
 <SetProperty Id="_UPGRADE"   After="FindRelatedProducts" Value="1"><![CDATA[PREVIOUSVERSIONSINSTALLED<>"" ]]></SetProperty>

İşte bazı örnek kullanım:

  <Custom Action="CaptureExistingLocalSettingsValues" After="InstallInitialize">NOT _UNINSTALL</Custom>
  <Custom Action="GetConfigXmlToPersistFromCmdLineArgs" After="InstallInitialize">_INSTALL OR _UPGRADE</Custom>
  <Custom Action="ForgetProperties" Before="InstallFinalize">_UNINSTALL OR _UPGRADE</Custom>
  <Custom Action="SetInstallCustomConfigSettingsArgs" Before="InstallCustomConfigSettings">NOT _UNINSTALL</Custom>
  <Custom Action="InstallCustomConfigSettings" Before="InstallFinalize">NOT _UNINSTALL</Custom>

Sorunlar:


Bu harika bir çözüm. PATCH ve MSIPATCHREMOVE koşullarını da dikkate almayı unutmayın.
Garet Jax

Doğruluk tablonuzda ahmd0 tarafından kullanılan UPGRADINGPRODUCTCODE yerine PREVIOUSVERSIONSINSTALLED kullanmak istediniz mi? MSI özellik başvuru sayfasında ( docs.microsoft.com/en-us/windows/win32/msi/property-reference ) PREVIOUSVERSIONSINSTALLED için herhangi bir başvuru görmüyorum .
Patrick

Mülkleriniz için tahminlerin birçoğu ahmd0'ın tablosundaki tüm satırları dikkate almaz (Yüklü, REINSTALL, UPGRADINGPRODUCTCODE ve REMOVE). Nedenini açıklar mısınız?
Patrick

0

Özel Eylem ayrı olarak C ++ DLL kodlanmış ve DLL kaldırma Bu sözdizimi kullanarak kaldırma uygun işlevi çağırmak için kullanılır:

<CustomAction Id="Uninstall" BinaryKey="Dll_Name" 
              DllEntry="Function_Name" Execute="deferred" />

Yukarıdaki kod bloğunu kullanarak, kaldırma sırasında C ++ DLL'de tanımlanan herhangi bir işlevi çalıştırabildim. FYI, kaldırma işlevim, geçerli kullanıcı verilerini ve kayıt defteri girdilerini temizleme ile ilgili kod içeriyordu.

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.