Astuces et astuces de perruque

nous utilisons WiX depuis un moment maintenant, et malgré les querelles habituelles sur la facilité d'utilisation, cela se passe raisonnablement bien. Ce que je cherche, ce sont des conseils utiles concernant:

  • mise en place d'un projet WiX (mise en page, références, modèles de fichiers)
  • l'Intégration de WiX dans des solutions, et de construire/processus de mise en liberté
  • configurer les installateurs pour les nouvelles installations et les mises à niveau
  • tout bon pirate WiX vous aimeriez partager
264
demandé sur si618 2009-01-23 03:29:24

30 réponses

  1. conserver les variables dans un fichier séparé wxi inclure. Permet la réutilisation, les variables sont plus rapides à trouver et (si nécessaire) permet une manipulation plus facile par un outil externe.

  2. définir des variables de plate-forme pour les constructions x86 et x64

    <!-- 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. stocker l'emplacement de l'installation dans le registre, permettant des mises à niveau pour trouver le bon emplacement. Exemple, si un utilisateur définit personnalisé répertoire d'installation.

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

    Note : Wix guru Rob Mensching a publié un excellent blog entry qui va plus en détail et fixe un cas de bord lorsque les propriétés sont définies à partir de la ligne de commande.

    des Exemples d'utilisation de 1. 2. et 3.

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

    et

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="$(var.PlatformProgramFilesFolder)">
        <Directory Id="INSTALLLOCATION" Name="$(var.InstallName)">
    
  4. l'approche la plus simple est toujours do major upgrades , car il permet à la fois les nouvelles installations et les mises à niveau dans le MSI simple. UpgradeCode est fixé à une interface unique et ne changera jamais, sauf si nous ne voulons pas mettre à niveau un produit existant.

    Note : Dans WiX 3.5 il y a un nouveau MajorUpgrade l'élément qui rend la vie encore plus facile !

  5. création d'une icône dans Add / Remove Programs

    <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. sur la version construit nous version nos installateurs, la copie du fichier msi à un répertoire de déploiement. Un exemple de ceci en utilisant une cible wixproj appelée de la cible AfterBuild:

    <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. Utiliser la chaleur pour la récolte des fichiers avec des caractères génériques (*) Guid. Utile si vous voulez réutiliser des fichiers WXS à travers plusieurs projets (voir ma réponse sur plusieurs versions du même produit). Par exemple, ce fichier batch récupère automatiquement la sortie RoboHelp.

    @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 
    

    il y a un bit en cours, robocopy élimine les métadonnées de la copie de travail de Subversion avant la récolte; la référence du répertoire racine -dr est définie à notre emplacement d'installation plutôt qu'à TARGETDIR par défaut; -var est utilisé pour créer une variable pour spécifier le répertoire source (web le déploiement de sortie).

  8. manière facile d'inclure la version du produit dans le titre de dialogue de bienvenue en utilisant des chaînes.WXL pour localisation. (Crédit: saschabeaumont . Ajouté comme cette grande pointe est cachée dans un commentaire)

    <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. épargnez-vous un peu de douleur et suivez Conseil de Wim Coehen d'une composante par fichier. Cela vous permet également de laisser tomber (ou wild-card * ) le component GUID .

  10. Rob Mensching a un neat way pour dépister rapidement les problèmes dans les fichiers journaux MSI en cherchant value 3 . Notez les commentaires concernant l'internationalisation.

  11. lors de l'ajout de fonctionnalités conditionnelles, il est plus intuitif de définir le niveau de la fonctionnalité par défaut à 0 (désactivé), puis de définir la niveau de condition à votre valeur désirée. Si vous définissez la fonctionnalité par défaut niveau >= 1, le niveau de condition doit être 0 pour le désactiver, ce qui signifie que la logique de condition doit être le contraire de ce que vous attendez, ce qui peut être déroutant:)

    <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>
    
157
répondu si618 2017-05-23 12:18:18

vérification de l'installation d'IIS:

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

vérification de la compatibilité IIS 6 Metabase installée sur Vista+:

<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>
38
répondu Simon Steele 2009-03-26 15:03:10

conserver toutes les identifications dans des espaces de noms séparés

  • les caractéristiques commencent par F. exemples: F. Documentation, F. binaires, F. SampleCode.
  • les composants commencent par C. Ex: C. ChmFile, C. ReleaseNotes, C. LicenseFile, C. IniFile ,C. Registry
  • CustomActions are CA. Ex: CA.LaunchHelp, CA.UpdateReadyDlg, CA.SetPropertyX
  • les fichiers sont Fi.
  • les répertoires sont Di.
  • et ainsi de suite.

je trouve que cela aide immensément à garder la trace de toutes les différentes pièces d'identité dans toutes les catégories.

34
répondu Cheeso 2009-11-26 04:01:10

question fantastique. J'aimerais voir quelques bonnes pratiques montrées.

j'ai beaucoup de fichiers que je distribue, donc j'ai configuré mon projet en plusieurs fichiers source wxs.

j'ai un fichier source de premier niveau que j'appelle produit.wxs qui contient essentiellement la structure de l'installation, mais pas les composants réels. Ce fichier comporte plusieurs sections:

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

le reste du .les fichiers wix sont composés de Fragments contenant des groupes de composants référencés dans l'étiquette de fonctionnalité du produit.wxs. Mon projet contient un joli regroupement logique des fichiers que je distribue

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

ce n'est pas parfait, mon oo spider sens picote un peu parce que les fragments doivent faire référence à des noms dans le produit.WXS fichier (par exemple le DirectoryRef) mais je trouve plus facile de maintenir qu'un seul grand fichier source.

j'aimerais entendre des commentaires à ce sujet, ou si n'importe qui a de bons pourboires aussi!

25
répondu Peter Tate 2009-02-07 03:16:43

ajouter une case à cocher à la boîte de dialogue sortir pour lancer l'application, ou le fichier d'aide.

...

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

si vous le faites de cette façon, l'apparence" standard " n'est pas tout à fait correcte. La case à cocher est toujours un fond gris, tandis que le dialogue est blanc:

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

une façon de contourner cela est de spécifier votre propre ExitDialog personnalisé, avec une case à cocher autrement situé . Cela fonctionne, mais il semble que beaucoup de travail juste pour changer la couleur d'un contrôle. Une autre façon de résoudre la même chose est de post-traiter le MSI généré pour changer les champs X,Y dans la table de contrôle pour ce particulier Contrôle des cases à cocher. Le code javascript ressemble à ceci:

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();

L'exécution de ce code comme un script en ligne de commande (en utilisant cscript.exe) après que le MSI est généré (à partir de la lumière.exe) va produire un ExitDialog qui semble plus professionnel:

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

20
répondu Cheeso 2011-08-23 20:32:54

La Création De Vivre, De Test, De Formation, De ... versions utilisant les mêmes fichiers source.

en un mot: Créer un code de mise à jour unique pour chaque installateur et définir automatiquement le premier caractère de chaque Guid pour chaque installateur, laissant les 31 restants uniques.

prérequis

suppositions

  • les variables WiX sont utilisées pour définir UpgradeCode, ProductName, InstallName.
  • vous avez déjà un installateur fonctionnel. Je n'essaierais pas tant que tu ne l'auras pas fait.
  • tous vos composants sont conservés dans un fichier (Components.wxs). Ce processus fonctionnera si vous avez plusieurs fichiers, il y aura juste plus de travail à faire.

Structure De Répertoire

  • Configuration.Bibliothèque
    • tous les fichiers wxs (Components, Features, UI Dialogs, ...)
    • commun.Config.wxi (ProductCode="*", ProductVersion, PlatformProgramFilesFolder,...)
  • le programme d'Installation.Live (wixproj)
    • Lien tous de l'Installation.Fichiers de bibliothèque utilisant "Ajouter un fichier existant" - > "ajouter comme lien" (le petit bouton Flèche vers le bas juste à côté du bouton Ajouter dans Visual Studio)
    • Config.wxi (a unique Upgredecode, ProductName, InstallName,...)
  • le programme d'Installation.Test ,...
    • , comme live, mais Config.wxi est configuré pour l'environnement de Test.

Processus

  • Créer La Configuration.Répertoire de la bibliothèque et déplacer tous vos fichiers wxs et wxi (à l'exception de Config.wxi) du projet existant.
  • Créer La Configuration.Live, Programme D'Installation.Test, etc selon wixproj normal.
  • ajouter la cible BeforeBuild dans wixproj dans Setup.Live, etc pour effectuer MSBuild Communauté de Tâche FileUpdate pour modifier les Guid (j'ai utilisé Un pour Vivre, B pour le Test et C pour la formation)
  • ajouter la cible AfterBuild pour inverser les composants.WXS Guids retour à 0.
  • vérifier avec Orca que chaque composant dans chaque MSI a le guid modifié.
  • vérifier que les guids originaux sont restaurés.
  • vérifier que chaque MSI installe (et met à niveau) le produit et l'emplacement corrects.

Exemple De Configuration.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>

Exemple De Configuration.Commun.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>

Exemple De Composants.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">
          ...

Note: je suggère maintenant de laisser L'attribut Guid hors de Component (équivalent de * ), en utilisant un fichier par component et en définissant le fichier comme chemin d'accès. Cela élimine la nécessité d'appeler les cibles ModifyComponentsGuids et RevertComponentsGuids indiquées ci-dessous. Cela pourrait ne pas être possible pour tous vos composants.

Exemple De Configuration.Vivre.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>

réflexions

  • ce processus devrait également fonctionner pour créer différents installateurs pour différents modules de fusion (Live, Test, ... comme caractéristiques) pour le même installateur. Je suis allé avec différents installateurs car il semblait une option plus sûre, Il ya plus de risque que quelqu'un pourrait mettre à niveau en direct au lieu de formation si ils sont sur la même boîte et vous utilisez juste des fonctionnalités pour les différents modules de fusion.
  • si vous utilisez votre MSI pour effectuer des mises à niveau ainsi que de nouvelles installations, c'est-à-dire l'approche de mise à niveau majeure seulement, et vous enregistrez votre emplacement d'installation dans le registre, n'oubliez pas de créer une variable pour le nom de la clé pour chaque installation.
  • nous créons aussi des variables dans chaque configuration.wxi pour activer les noms de répertoire virtuels uniques, les pools d'application, les noms de base de données, et cetera pour chaque installateur.

mise à JOUR 1: Auto-génération les Guids de component suppriment la nécessité d'appeler la tâche FileUpdate si vous créez component avec Guid="* " pour chaque fichier, définissant le fichier comme le chemin d'accès.

mise à jour 2: L'un des problèmes que nous avons rencontré est que si vous ne générez pas automatiquement vos Guid de composants et que la compilation échoue, alors les fichiers temp doivent être supprimés manuellement.

mise à JOUR 3: Trouvé un moyen pour supprimer la dépendance sur svn: externals et la création de fichiers temporaires. Cela rend le processus de construction plus résilient (et est la meilleure option si vous ne pouvez pas Joker vos Guids) et moins fragile s'il y a une défaillance de construction dans la lumière ou la bougie.

mise à jour 4: prise en charge de Instances multiples l'utilisation de transformes d'instance est en WiX 3.0+, certainement vaut également un coup d'oeil.

18
répondu si618 2017-05-23 10:31:16

en utilisant la journalisation de Diagnostic Msi pour obtenir des informations détaillées sur les pannes



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

Package.msi
est le nom de votre paquet et
c:\Package.log
est l'endroit où vous voulez la sortie du log

Codes D'Erreur Msi

Wix Vidéo D'Intro

Oh et Aléatoire Wix vidéo d'intro avec "M. WiX" Rob Mensching est "conceptuel" big picture" utile.

17
répondu Terrance 2010-06-03 14:22:39

utiliser des personnalisations Javascript parce qu'ils sont soooo facile

les gens ont dit que Javascript est la mauvaise chose à utiliser pour MSI CustomActions . Raisons données: difficile de déboguer, difficile de le rendre fiable. Je ne suis pas d'accord. Ce n'est pas difficile à déboguer, certainement pas plus dur que C++. Ses juste différent. J'ai trouvé que L'écriture de personnalisations dans Javascript était super facile, beaucoup plus facile que L'utilisation de C++. Beaucoup plus rapide. Et tout comme fiable.

il n'y a qu'un inconvénient: les personnalisations Javascript peuvent être extraites via Orca, alors qu'une CA C/C++ nécessiterait la rétro-ingénierie. Si vous considérez que votre installateur magic est une propriété intellectuelle protégée, vous voudrez éviter script.

si vous utilisez script, tu as juste besoin de commencer avec un peu de structure. Voici quelques-uns pour vous aider à démarrer.


Javascript "standard" code pour CustomAction:

//
// 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
    };
}

alors, enregistrez l'action personnalisée avec quelque chose comme ceci:

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

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

vous pouvez, bien sûr, insérer autant de fonctions Javascript que vous le souhaitez, pour plusieurs actions personnalisées. Un exemple: J'ai utilisé Javascript pour faire une requête WMI sur IIS, pour obtenir une liste de sites Web existants, sur lesquels un filtre ISAPI pourrait être installé. Cette liste a ensuite été utilisé pour remplir une listbox montré plus tard dans la séquence UI. Tout cela est très facile.

sur IIS7, il n'y a pas de fournisseur D'IMW pour IIS, donc j'ai utilisé l'approche shell.Run() pour invoquer appcmd.exe pour effectuer le travail. Facile.

question connexe: à propos de CustomActions Javascript

17
répondu Cheeso 2017-05-23 11:47:16

Peter Tate a déjà montré comment vous pouvez définir les définitions de groupes de composants réutilisables dans des fragments wix séparés. Quelques astuces supplémentaires liées à ceci:

Annuaire Aliasing

les fragments du groupe de composants n'ont pas besoin de connaître les répertoires définis par le produit principal wxs. Dans votre fragment de groupe de composants, vous pouvez parler d'un dossier comme celui-ci:

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

puis le principal le produit peut alias l'un de ses répertoires (par exemple "productInstallFolder") comme ceci:

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

Graphique De Dépendance

ComponentGroup elements can contain Componentgroupef child elements. C'est génial si vous avez un grand réservoir de composants réutilisables avec un graphe de dépendance complexe entre eux. Vous venez de configurer un groupe Component dans son propre fragment pour chaque composant et de déclarer les dépendances comme ceci:

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

si vous faites maintenant référence au groupe de composants" B "dans votre configuration parce qu'il s'agit d'une dépendance directe de votre application, le groupe de composants" A "s'affichera automatiquement même si l'auteur de l'application ne s'est jamais rendu compte qu'il s'agissait d'une dépendance de"B". Il "fonctionne" aussi longtemps que vous n'avez pas de dépendances circulaires.

réutilisable wixlib

l'idée du graphique de dépendance ci-dessus fonctionne le mieux si vous compilez grand-piscine-o-réutilisable-composants réutilisables wixlib avec éclairée.EXE. Lors de la création d'une configuration d'application, vous pouvez référencer ce fichier wixlib comme un fichier wixobj. Bougie.exe linker élimine automatiquement tous les fragments qui ne sont pas "tirés" par le(S) fichier (s) WXS du produit principal.

12
répondu Wim Coenen 2009-02-26 20:01:28

je suis surpris que personne n'ait mentionné L'utilisation de T4 pour générer le fichier WXS pendant la construction. J'ai appris cela en passant par Henry Lee @ New Age Solutions .

essentiellement, vous créez une tâche MSBuild personnalisée pour exécuter un modèle T4, et ce modèle affiche la sortie WXS juste avant que le projet Wix ne soit compilé. Cela vous permet (en fonction de la façon dont vous l'implémentez) d'inclure automatiquement toutes les sorties d'assemblages à partir de la compilation d'une autre solution (ce qui signifie que vous n'avez plus à modifier le wxs jamais le temps d'ajouter une nouvelle assemblée).

12
répondu Peter T. LaComb Jr. 2009-12-14 21:11:42

Utilisant La Chaleur.exe pour écraser le visage et infliger des "Epic Pwnage" sur douloureusement grande installe

L'expansion sur Si et Robert-P réponses à propos de la chaleur.



Traduction: (En utilisant la chaleur pour éviter de taper des fichiers individuels dans le projet à la main et pour automatiser des constructions pour un processus plus facile dans l'ensemble.)



Wix 2.0 Heat syntaxe detailed

pour les versions plus récentes (pas si différentes que ça des versions plus anciennes, mais il y a des changements de syntaxe potentiellement gênants....) allez dans le répertoire de la Chaleur est de la cmd.exe et tapez juste dans heat mais j'ai un exemple ici pour de l'aide avec les nouvelles versions si nécessaire.

ajouter ce qui suit à votre Build Événement dans visual studio 2010.

(Clic Droit Sur Le Projet - > Propriétés - > Événements De Construction-> Événements De Pré-Construction)



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

-gg 

génère des Guids lorsque la chaleur est exécutée (comme lorsque vous exécutez la commande ci-dessus)

-scom 

Ne pas saisir "fichiers COM"

-sreg 

Ne pas prendre "les Fichiers de Registre"

-sfrag 

Ne pas saisir "Fragments"

-srd 

Ne pas saisir la "racine"

dir

dir indique que vous voulez que Heat regarde dans un dossier

"$(EnviromentVariable)"

le nom de la variable que vous ajouteriez aux variables du préprocesseur dans le (clic droit projet, aller aux Propriétés) Propriétés du projet - > section construire où il est dit définir variables du préprocesseur (suppose studio visuel 2010)

Example:
EnviromentVariable=C:\Project\bin\Debug;
-cg GroupVariable 

le groupe de composants qui sera référencé à partir du fragment créé pour le fichier principal wxs

FragmentDir

le répertoire de fragment où le fragment WXS de sortie sera stocké

FileName.wxs

le nom du fichier

tutoriel complet ici, donc freakin utile

Partie 1 Partie 2



12
répondu Terrance 2017-05-23 12:18:18

y compris les objets COM:

heat génère la plupart (si ce n'est la totalité) des entrées de registre et d'autres configurations nécessaires. Réjouissez-vous!

y compris les objets COM gérés (objets aka, .NET ou C# COM)

L'utilisation de heat sur un objet COM géré vous donnera un document wix presque complet.

Si vous n'avez pas besoin la bibliothèque disponible dans le GAC (c'est - à-dire disponible dans le monde entier: la plupart du temps, vous n'avez pas besoin de cela avec vos assemblages .NET de toute façon-vous avez probablement fait quelque chose de mal à ce point si ce n'est pas prévu pour être une bibliothèque partagée), vous voudrez vous assurer de mettre à jour la clé de registre CodeBase pour être défini à [#ComponentName] . Si vous prévoyez de l'installer sur le GAC (par exemple, vous avez fait quelque nouvelle bibliothèque commune impressionnant que tout le monde voudra utiliser) vous devez supprimer cette entrée, et ajouter deux nouveaux attributs de l'élément File : Assembly et KeyPath . Assembly devrait être réglé à" .net "et KeyPath devrait être réglé à"Oui".

cependant, certains environnements (en particulier tout ce qui a une mémoire gérée telle que les langages de script) auront également besoin d'accéder au Typelib. assurez-vous d'exécuter heat sur votre typelib et l'inclure. heat générera toutes les clés de Registre nécessaires. C'est pas cool ça?

9
répondu Robert P 2009-03-05 22:54:48

installation à C:\ProductName

certaines applications doivent être installées sur C:\ProductName ou quelque chose de similaire, mais 99,9% (si pas 100%) des exemples dans le net install à C:\Program Files\CompanyName\ProductName .

le code suivant peut être utilisé pour définir la propriété TARGETDIR à la racine du lecteur C: (tiré de la liste WiX-users list ):

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

NOTE: par défaut, TARGETDIR ne correspond pas à point à C:\ ! Il plutôt d' ROOTDRIVE qui, à son tour "l'1519250920" racine du lecteur avec le plus d'espace libre ( voir ici ) - et ce n'est pas forcément le C: . Il pourrait y avoir un autre disque dur, une partition, ou un lecteur USB!

alors, quelque part en dessous de votre étiquette <Product ...> , vous avez besoin de les étiquettes de répertoire suivantes comme d'habitude:

<Directory Id="TARGETDIR" Name="SourceDir">
    <Directory Id="APPLICATIONFOLDER" Name="$(var.ProductName)">
        <!-- your content goes here... -->
    </Directory>
</Directory>
8
répondu gehho 2010-08-18 12:38:53

Variables Environnementales

lors de la compilation de vos documents Wxs au Code wixobj, vous pouvez utiliser des variables d'environnement pour déterminer diverses informations. Par exemple, disons que vous souhaitez modifier les fichiers inclus dans un projet. Disons que vous avez une variable d'environnement appelée RELEASE_MODE, que vous avez définie juste avant de construire votre MSI (que ce soit avec un script ou manuellement, cela n'a pas d'importance) dans votre source wix, vous pouvez faire quelque chose comme:

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

et plus tard dans votre code, utilisez-le en place pour changer à la volée votre document wxs, par exemple:

<Icon Id="myicon.ico" SourceFile="$(var.FILESOURCE)" />
7
répondu Robert P 2009-04-09 23:47:57

à l'Aide de la RobM spécial "Rappelez-vous Bien" pattern

http://robmensching.com/blog/posts/2010/5/2/The-WiX-toolsets-Remember-Property-pattern

7
répondu BozoJoe 2010-11-15 21:25:48

Créer une Action Personnalisée pour WIX écrit en code managé (C#) sans Votive

http://www.codeproject.com/KB/install/wixcustomaction.aspx

7
répondu user431821 2010-12-02 11:58:50

Dialogues D'Édition

une bonne capacité à éditer des dialogues est D'utiliser Sharp Developement dans une version 4.0.1.7090 (ou supérieure). Avec l'aide de cet outil une boîte de dialogue autonome (fichiers wxs à partir de sources WiX comme par exemple InstallDirDlg.wxs) peut être ouvert, prévisualisé et édité en mode Design.

7
répondu user432758 2011-05-13 07:48:06

réglage du drapeau IIS enable32BitAppOnWin64 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" />
6
répondu EdmundYeung99 2011-08-24 06:34:01

modifier le "prêt à installer?"dialog (alias VerifyReadyDlg) pour fournir un résumé des choix effectués.

il ressemble à ceci:

texte alternatif http://i46.tinypic.com/s4th7t.jpg

Faire avec un Javascript CustomAction:


code Javascript:

// 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);
}

Déclarer le Javascript CA:

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

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

attachez le CA à un bouton. Dans cet exemple, le CA est déclenché lorsque Next est cliqué à partir du CustomizeDlg:

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

Related SO Question: comment définir, à l'exécution, le texte à afficher dans VerifyReadyDlg?

5
répondu Cheeso 2017-05-23 12:26:22

placer les composants qui peuvent être patchés individuellement à l'intérieur de leurs propres Fragments

il va pour les installateurs de produits et les correctifs que si vous incluez un composant dans un fragment, vous devez inclure tous les des composants dans ce fragment. Dans le cas de la construction d'un installateur, si vous manquez des références de composants, vous obtiendrez une erreur de lien de la part de light.EXE. Cependant, lorsque vous faites un patch, si vous incluez référence d'un seul composant dans un fragment, puis tous les composants modifiés de ce fragment apparaîtront dans votre patch.

comme ceci:

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

au lieu de ceci:

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

aussi, lors de la correction en utilisant le sujet" utiliser purement WiX " de la WiX.fichier d'aide chm, en utilisant cette procédure pour générer le correctif:

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

il ne suffit pas d'avoir la version 1.1 de produit.wixpdb construit en utilisant les composants dans des fragments séparés. Assurez-vous donc de fragmenter correctement votre produit avant l'expédition.

5
répondu Dave Andersen 2010-06-25 18:57:06

printing CLUF from Wix3.0 et plus tard

1) lorsque vous compilez votre code source wix, la lumière.exe doit faire référence à la WixUIExtension.dll, en ligne de commande. Utilisez le commutateur de ligne de commande -ext pour cela.

2) Si lorsque vous ajoutez la référence à la WixUIExtension.dll, votre projet ne parvient pas à compiler, ce qui est très probablement en raison de conflits D'IDs de dialogue, i.e. votre projet utilisait les mêmes IDs de dialogues que certains standard dialogues en Wixiextension.dll, donne des identifiants différents à tes dialogues. C'est assez fréquent problème.

3) Votre dialogue de licence doit avoir le contrôle ScrollableText avec l'id "LicenseText". Wix recherche exactement ce nom de contrôle quand il imprime.

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

et un bouton-poussoir qui se réfère à l'action sur mesure

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

4) Définir CustomAction avec l'Id="PrintEula" comme ceci:

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

Note: BinaryKey est différent dans Wix3.0 comparaison avec Wix2.0 et doit être exactement "WixUIWixca" (sensible à la casse).

lorsque l'utilisateur appuie sur le bouton il/elle sera présenté avec la boîte de dialogue standard choisir L'imprimante et sera en mesure d'imprimer à partir de là.

5
répondu farfareast 2010-11-02 15:11:34
  • nous affichons la version du produit quelque part (minuscule) dans le premier écran de l'interface graphique. Parce que les gens ont tendance à faire des erreurs en choisissant la bonne version à chaque fois. (Et de nous garder les développeurs à la recherche pour les âges..)

  • nous avons mis en place TFSBuild pour générer aussi des transformations (.fichiers mst) avec la configuration pour nos différents environnements. (Nous connaissons tous les environnements, nous devons déployer pour).

depuis que le blog original de Grant Holliday est tombé, j'ai copié collé son contenu ici:


tâche MSBuild pour générer MSI Transformer des fichiers à partir de XMLMarch 11 2008

dans mon post précédent j'ai décrit comment vous pouvez utiliser MSI Transform (*.MST) pour séparer les paramètres de configuration spécifiques à l'environnement d'un paquet MSI Générique.

Bien que cela offre un niveau de flexibilité dans votre configuration, il y a deux côtés en bas des fichiers Transform:

  1. C'est un format binaire
  2. vous ne pouvez pas" éditer "ou" voir " un fichier transform. Vous devez l'appliquer ou le recréer pour voir quels changements il comprend.

heureusement, nous pouvons utiliser la bibliothèque D'objets Microsoft Windows Installer (c:windowssystem32msi.dll) pour ouvrir MSI" bases de données " et de créer des fichiers de transformation.

crédits allez à nouveau à Alex Shevchuk-de MSI à WiX-Partie 7 - personnalisation de l'installation à l'aide de transformes pour nous montrer comment y parvenir avec VbScript. Tout ce que j'ai fait, C'est prendre L'exemple D'Alex et utiliser Interop.WindowsInstaller.dll j'ai mis en place une tâche MSBuild. La Tâche MSBuild

télécharger le code source et l'exemple se transforment.xml ici (~7Kb Zippée VS2008 Solution)


5
répondu thijs 2011-03-18 13:02:43

avant de déployer un paquet install, je contrôle toujours son contenu.

c'est juste un simple appel à la ligne de commande (selon Terrences post) ouvrir la ligne de commande et entrer

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

ceci extraira le contenu du paquet vers un sous-DIR 'Extract' avec le chemin courant.

5
répondu tobaer 2011-05-20 12:46:25

au lieu d'ORCA utiliser Insté qui est un bon outil pour visualiser les tableaux MSI. Aussi il a la capacité de différencier deux paquets par Transformer -> Comparer...

en outre, une version Plus avec des fonctionnalités supplémentaires est disponible. Mais aussi la version gratuite offre une bonne alternative pour Orca.

4
répondu user432758 2011-05-20 12:37:47

enregistrant des assemblages .NET pour COM Interop avec compatibilité x86 /x64

NB ce fragment est essentiellement le même que regasm assemblage.dll /base de code

deux ou trois choses se passent dans cet échantillon, alors voici le code et je vous expliquerai plus tard...

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

si vous vous demandiez, c'est en fait pour un pilote de télescope ASCOM .

tout d'abord, j'ai pris des conseils d'en haut et j'ai créé quelques variables platforma dans un fichier séparé, vous pouvez voir celles dispersées à travers le XML.

la partie if-then-else en haut traite de la compatibilité x86 vs x64. Mon assemblée cible 'N'importe quel CPU' donc sur un système x64, je dois l'enregistrer deux fois, une fois dans le Registre 64 bits et une fois dans les zones 32 bits Wow6432Node . Le si-alors-sinon ensembles de moi pour cela, les valeurs sont utilisées dans un foreach boucle plus tard. De cette façon, je n'ai à écrire les clés de registre qu'une seule fois (principe de DRY).

l'élément de fichier spécifie l'Assemblée réelle dll étant installé et enregistré:

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

rien de révolutionnaire, mais remarquez le Assembly=".net" - cet attribut seul ferait entrer l'assemblée dans le GAC, ce qui n'est pas ce que je voulais. Utiliser l'attribut AssemblyApplication pour revenir à lui-même est simplement une façon d'arrêter Wix mettre le fichier dans le GAC. Maintenant que Wix sait que c'est un assemblage .net, il me permet d'utiliser certaines variables de reliure dans mon XML, comme le !(bind.assemblyFullname.filDriverAssembly) pour obtenir le nom complet de l'assemblage.

4
répondu Tim Long 2011-07-19 23:58:19

définit la propriété DISABLEADVTSHORTCUTS pour forcer tous les raccourcis annoncés dans votre installateur à devenir des raccourcis réguliers, et vous n'avez pas besoin d'inclure une clé de registre factice pour être utilisé comme le chemin de clé.

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

je pense que Windows Installer 4.0 ou plus est un exigence .

3
répondu Dave Andersen 2011-06-16 23:20:48

c'est une belle structure mais d'après mon expérience je me demande comment vous abordez ces conditions:

A. vos installations semblent toutes atterrir dans la même destination. Si un utilisateur a besoin d'installer les 3 versions à la fois, votre processus le permettra. Peuvent-ils dire sans ambiguïté quelle version de chaque exécutable ils déclenchent?

B. Comment traitez-vous les nouveaux fichiers qui existent en TEST et/ou en formation mais qui ne sont pas encore en direct?

2
répondu 2009-02-23 17:07:19

Voici une façon d'aider les grands projets web à vérifier que le nombre de fichiers déployés correspond au nombre de fichiers intégrés dans un MSI (ou un module de fusion). Je viens juste d'exécuter la tâche personnalisée MSBuild contre notre application principale (toujours en développement) et il a ramassé un bon nombre de fichiers manquants, la plupart du temps des images, mais quelques fichiers javascript avaient glissé à travers!

cette approche (en regardant dans la table de fichier de MSI en accrochant dans la cible de WiX projet) pourrait fonctionner pour les autres types d'applications où vous avez accès à une liste complète des fichiers attendus.

2
répondu si618 2017-05-23 12:34:36

effectuer une réinstallation forcée lorsqu'une installation n'autorise pas la désinstallation ou la réinstallation et ne permet pas de revenir en arrière.



Script VBscript utilisé pour modifier une installation qui n'est pas désinstallée pour quelque raison que ce soit..

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)
2
répondu Terrance 2010-08-18 13:28:01

crée une interface utilisateur qui a une action personnalisée qui définira une variable et l'interface utilisateur désactivera/activera le bouton Suivant (ou similaire) basé sur la variable définie dans l'action personnalisée.

pas aussi simple que vous le pensez, pas trop difficile, juste pas documenté nulle part!

Wix Interactions avec les Conditions, les Propriétés Et les Actions Personnalisées

2
répondu Daniel Powell 2017-05-23 11:54:40