WiXのトリックとヒント


264

私たちはしばらくの間WiXを使用していますが、使いやすさについての通常の不満にもかかわらず、それはかなり順調に進んでいます。私が探しているのは、以下に関する有用なアドバイスです。

  • WiXプロジェクトのセットアップ(レイアウト、参照、ファイルパターン)
  • ソリューションへのWiXの統合、およびビルド/リリースプロセス
  • 新規インストールおよびアップグレード用のインストーラーの構成
  • 共有したい良いWiXハック

gui4wix.codeplex.comをご覧ください
TarunG

10
建設的でないとして閉鎖?私はこの質問をすることから山を学びました!StackOverflowのから少し一貫性もいいだろう...例えばstackoverflow.com/questions/550632/...
si618

15
それは「203」のアップを得ました、それはそれがその有用性を証明するのに十分です。
TarunG

SOの質問には、明確で正しい答えが必要です。自由回答形式の質問では、実際の問題について人々が尋ねる質問がフロントページから消えます。 faq @Si .:そのポリシーは常にAFAIKにありましたが、今はより適切に施行されています。その質問はほぼ3年前のものです。
ジムダグ

十分に公正なジム、それは自由回答式の質問であり、私が決定するのはSOコミュニティの責任だと思いますが、私とその見た目から、他の多くの人々が考えると、建設的ではないとして閉じることは奇妙に思われると言わざるを得ませんこの質問は有用であることがわかり(例:goo.gl/Zqp2X)、practical, answerable questions based on actual problems that you faceよくある質問の一部と非常によく一致しています。
si618 2012

回答:


157
  1. 変数を別のwxiインクルードファイルに保存します。再利用が可能になり、変数の検索が速くなり、(必要な場合)外部ツールによる操作が容易になります。

  2. x86および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. インストール場所をレジストリに保存し、アップグレードで正しい場所を見つけられるようにします。たとえば、ユーザーがカスタムインストールディレクトリを設定するとします。

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

    :WiXの第一人者、Rob Mensching優れたブログエントリを投稿しました。このエントリでは、コマンドラインからプロパティを設定した場合の詳細と、大文字と小文字の違いが修正されています。

    1. 2.および3.を使用した例

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

    そして

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="$(var.PlatformProgramFilesFolder)">
        <Directory Id="INSTALLLOCATION" Name="$(var.InstallName)">
    
  4. 単一のMSIで新規インストールとアップグレードの両方が可能になるため、最も単純なアプローチは常にメジャーアップグレードを行うことです。UpgradeCodeは一意のGuidに固定されており、既存の製品をアップグレードしない限り、変更されることはありません。

    注意:WiX 3.5には新しいMajorUpgrade要素があり、これにより作業さらに簡単になります。

  5. [プログラムの追加と削除]でアイコンを作成する

    <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. リリースビルドでは、インストーラーをバージョン管理し、msiファイルをデプロイメントディレクトリにコピーします。AfterBuildターゲットから呼び出されたwixprojターゲットを使用したこの例:

    <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. ワイルドカード(*)GUIDを使用してファイルを収穫するために熱を使用します。複数のプロジェクトでWXSファイルを再利用する場合に役立ちます(同じ製品の複数のバージョンに関する私の回答を参照してください)。たとえば、このバッチファイルは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 
    

    少し進んでいますが、robocopyハーベスティングの前にSubversion作業コピーのメタデータを取り除いています。-drルートディレクトリの参照は、当社の設置場所ではなく、デフォルトのTARGETDIRに設定されています。-varソースディレクトリ(Webデプロイメントの出力)を指定する変数を作成するために使用されます。

  8. ローカライズにStrings.wxlを使用して、ウェルカムダイアログのタイトルに製品バージョンを含める簡単な方法。(クレジット:saschabeaumont。この素晴らしいヒントはコメントに隠されているため、追加されました)

    <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. 多少の手間を省き、ファイルごとに1つのコンポーネントを使用するというWim Coehenのアドバイスに従ってください。これにより*コンポーネントGUIDを省略(またはワイルドカード)することもできます

  10. Rob Menschingは、MSIログファイルの問題をすばやく検索して、を検索することで優れた方法を提供しvalue 3ます。国際化に関するコメントに注意してください。

  11. 条件付き機能を追加する場合、デフォルトの機能レベルを0(無効)に設定してから、条件レベルを目的の値に設定する方が直感的です。デフォルトの機能レベル> = 1を設定する場合、それを無効にするには条件レベルを0にする必要があります。つまり、条件ロジックは予想とは逆である必要があり、混乱する可能性があります:)

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

[プログラムの追加と削除]にアイコンを追加することについては、まさに私が探していたものです。これらの3行をどこに貼り付けますか?+1のすばらしさ。
エベレット

私はそれらを<Package>要素の直後(そして明らかにその下)に配置する傾向があります。スキーマの妥当性を確認する wix.sourceforge.net/manual-wix3/schema_index.htm
si618

+ 1、+ 100ができたらいいのに。これは、私が遭遇したWix情報の中で最も有用な1つのビットです。
ティムロング、

ティムありがとう!Rob Mensching、Bob Arson、Wim Coehenなどは、知識を共有するための称賛に値します。
si618

38

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>

IIS 6メタベース互換性が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>

34

すべてのIDを別々の名前空間に保持する

  • 機能はF. 例で始まります:F.Documentation、F.Binaries、F.SampleCode。
  • コンポーネントはC. Exで始まります:C.ChmFile、C.ReleaseNotes、C.LicenseFile、C.IniFile、C.Registry
  • CustomActionsはCA. Ex:CA.LaunchHelp、CA.UpdateReadyDlg、CA.SetPropertyXです。
  • ファイルは Fi.
  • ディレクトリは Di.
  • 等々。

これは、さまざまなカテゴリのすべてのさまざまなIDを追跡するのに非常に役立ちます。


名前空間は使用していませんが、IDを追加しています。例:ExamplesFeature、ChmFileComponent。私はタイピングが大好きだと思います;-)
dvdvorle

25

素晴らしい質問です。いくつかのベストプラクティスをご覧になりたいと思います。

配布するファイルがたくさんあるので、プロジェクトをいくつかのwxsソースファイルに設定しました。

私はProduct.wxsと呼ぶトップレベルのソースファイルを持っています。これには基本的にインストールの構造が含まれていますが、実際のコンポーネントは含まれていません。このファイルにはいくつかのセクションがあります:

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

残りの.wixファイルは、Product.wxsのFeatureタグで参照されるComponentGroupを含むフラグメントで構成されています。私のプロジェクトには、配布するファイルの適切な論理グループが含まれています

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

これは完璧ではありません。OOスパイダーのセンスは少しチクチクします。フラグメントはProduct.wxsファイル(DirectoryRefなど)の名前を参照する必要があるためですが、単一の大きなソースファイルを維持する方が簡単です。

私はこれについてのコメントを聞きたいです、または誰かが何か良いヒントもあれば!


私たちのセットアップもこのアプローチに非常に似ています。同等のProducts.wxsをさまざまな製品の基本セットアップとして使用できるため、これは良いことです。
si618 2009

@ピーターテート:あなたのクモの感覚は正しいです。ディレクトリエイリアスについての私の回答を参照してください。
Wim Coenen、

私は同じアプローチをとります:レイアウト付きのProduct.wxsは静的であり、ビルドタスク(heat.exe)がContent.wxsファイルを生成します
timvw

20

チェックボックスを終了ダイアログに追加して、アプリまたはヘルプファイルを起動します。

...

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

この方法で行うと、「標準」の外観は完全に正しくありません。チェックボックスは常に灰色の背景ですが、ダイアログは白です。

代替テキストhttp://www.dizzymonkeydesign.com/blog/misc/adding-and-customizing-dlgs-in-wix-3/images/exit_dlg_1.gif

これを回避する1つの方法は、独自のカスタムExitDialog指定することです。これは機能しますが、1つのコントロールの色を変更するだけでも多くの作業のようです。同じことを解決する別の方法は、生成されたMSIを後処理して、その特定のCheckBoxコントロールのコントロールテーブルのX、Yフィールドを変更することです。JavaScriptコードは次のようになります。

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

MSIが(light.exeから)生成された後、このコードをコマンドラインスクリプトとして(cscript.exeを使用して)実行すると、より専門的に見えるExitDialogが生成されます。

代替テキストhttp://www.dizzymonkeydesign.com/blog/misc/adding-and-customizing-dlgs-in-wix-3/images/exit_dlg_2.gif


ハ!私のブログではありません。私も読んだ。上記のテキストにブログエントリへのリンクがあります。しかし、彼らは私とは異なる方法でそれを行いました。私のほうが好きです。
Cheeso、2009年

1
jsをありがとう、とても役に立ちました!wxsで変更しなければならないことの1つはWIXUI_EXITDIALOGOPTIONALCHECKBOXWIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed内部で置き換えることです<Publish>
Alexander Kojevnikov

チェックボックスをデフォルトでオンにする方法はありますか?
Alek Davis

デフォルトでボックスをチェックするために、私はこれを使用しました:<Property Id = "WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value = "1" />
Alek Davis

気の利いたソリューションのようですが、どのように使用すればよいですか?wixprojの<AfterBuild>要素内にjsを配置する方法はありますか?または、コマンドラインから実行することを言及しているので、ビルド後のイベントとしての方が優れていますか。この場合、Windows用の優れたjsコマンドラインインタープリターは何ですか。
vanmelle

18

同じソースファイルを使用して、ライブ、テスト、トレーニングなどのバージョンを作成する。

一言で言えば、インストーラごとに一意のUpgradeCodeを作成し、各インストーラの各Guidの最初の文字を自動的に定義し、残りの31は一意のままにします。

前提条件

仮定

  • WiX変数は、UpgradeCode、ProductName、InstallNameを定義するために使用されます。
  • すでに動作しているインストーラーがあります。あなたがそうするまで私はこれを試みませんでした。
  • すべてのコンポーネントは1つのファイル(Components.wxs)に保存されます。このプロセスは、複数のファイルがある場合に機能しますが、実行する必要がある作業は増えます。

ディレクトリ構造

  • Setup.Library
    • すべてのwxsファイル(コンポーネント、機能、UIダイアログなど)
    • Common.Config.wxi(ProductCode = "*"、ProductVersion、PlatformProgramFilesFolder、...)
  • Setup.Live(wixproj)
    • [既存のファイルの追加]-> [リンクとして追加]を使用して、すべてのSetup.Libraryファイルをリンクします(Visual Studioの[追加]ボタンの横にある小さな下矢印ボタン)。
    • Config.wxi(固有のUpgradeCode、ProductName、InstallNameなどがあります)
  • Setup.Test、...
    • ライブどおりですが、Config.wxiはテスト環境用に構成されています。

処理する

  • Setup.Libraryディレクトリを作成し、既存のプロジェクトからすべてのwxsおよびwxiファイル(Config.wxiを除く)を移動します。
  • 通常のwixprojに従ってSetup.Live、Setup.Testなどを作成します。
  • Setup.LiveなどのwixprojにBeforeBuildターゲットを追加して、MSBuildコミュニティタスクFileUpdateを実行し、Guidを変更します(ライブにはA、テストにはB、トレーニングにはCを使用しました)。
  • AfterBuildターゲットを追加して、Components.wxs GUIDを0に戻します。
  • Orcaを使用して、各MSIの各コンポーネントに変更されたGUIDがあることを確認します。
  • 元のGUIDが復元されていることを確認します。
  • 各MSIが正しい製品と場所をインストール(およびアップグレード)していることを確認します。

Config.wxiの例

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

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

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

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

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

Config.Common.wxiの例

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

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

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

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

<?define ProductManufacturer = "Foo Technologies"?>

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

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

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

Components.wxsの例

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

注:コンポーネント*ごとに1つのファイルを使用し、そのファイルをキーパスとして設定して、Guid属性をコンポーネント(と同等)から除外することをお勧めします。これにより、以下に示す呼び出しModifyComponentsGuidsRevertComponentsGuidsターゲットが不要になります。ただし、すべてのコンポーネントでこれが可能なわけではありません。

サンプルSetup.Live.wixproj

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

最終的な考え

  • このプロセスは、同じインストーラーの異なるマージモジュール(機能としてLive、Testなど)の異なるインストーラーを作成する場合にも機能します。安全なオプションのように思われるので、別のインストーラーを使用しました。同じボックス上にいて、異なるマージモジュールの機能を使用している場合、誰かがトレーニングではなくLiveをアップグレードするリスクが高くなります。
  • MSIを使用してアップグレードと新規インストール、つまりメジャーアップグレードのみのアプローチを実行し、インストール場所をレジストリに保存する場合は、インストールごとにキー名の変数を作成してください。
  • また、各Config.wxiに変数を作成して、各インストーラーに対して一意の仮想ディレクトリ名、アプリケーションプール、データベース名などを有効にします。

更新1: コンポーネントを自動生成するGuidsでは、ファイルごとにGuid = "*"を使用してコンポーネントを作成し、ファイルをキーパスとして設定する場合、FileUpdateタスクを呼び出す必要がなくなります。

更新2:私たちが直面している問題の1つは、コンポーネントのGuidを自動生成せず、ビルドが失敗した場合、一時ファイルを手動で削除する必要があることです。

更新3: svn:externalsへの依存と一時ファイルの作成を削除する方法が見つかりました。これにより、ビルドプロセスの弾力性が高まり(Guidをワイルドカードにできない場合は最適なオプションです)、ライトやキャンドルでビルドエラーが発生した場合の脆弱性が少なくなります。

更新4:インスタンス変換を使用した複数インスタンスのサポートはWiX 3.0以降にあり、一見の価値があります。


MSBuildコミュニティタスクリファレンスの+1、そのパッケージが大好き
BozoJoe

17

Msi診断ログを使用して詳細な障害情報を取得する

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

どこ

Package.msi
はパッケージの名前であり、
c:\ Package.log
ログの出力が必要な場所です

Msiエラーコード

Wixイントロビデオ
OhとランダムWixイントロビデオ「Mr. WiX」をフィーチャーRob Menschingは、「概念的な全体像」が役立ちます。


2
+1コマンドラインではなくWix内からログを有効にできれば、はるかに優れています。
si618

3
WiXはそうします。MsiLoggingプロパティを設定します。Windowsインストーラ4.0以降でのみサポートされます。
Rob Mensching、2010年

「Mr. Wix」、ありがとうございました。是非チェックしてください。
Terrance

17

とても簡単なので、Javascript CustomActionsを使用します

人々は、JavascriptはMSI CustomActionsに使うのは間違っていると言っています。理由:デバッグが難しい、信頼性を高めるのが難しい。同意しません。デバッグは難しくなく、C ++よりも難しくありません。ただ違う。JavaScriptでのCustomActionsの記述は、C ++を使用するよりもはるかに簡単であることがわかりました。はるかに高速。信頼性も同様です。

欠点は1つだけです。JavaScriptカスタムアクションはOrcaを介して抽出できるのに対し、C / C ++ CAにはリバースエンジニアリングが必要です。インストーラの魔法を知的財産で保護すると考えている場合は、スクリプトを使用しないでください。

スクリプトを使用する場合は、いくつかの構造から始める必要があります。ここにあなたが始めるためのいくつかがあります。


CustomActionのJavaScript「ボイラープレート」コード:

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

次に、次のようなカスタムアクションを登録します。

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

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

もちろん、複数のカスタムアクションに対して、好きなだけJavaScript関数を挿入できます。1つの例:Javascriptを使用してIISでWMIクエリを実行し、ISAPIフィルターをインストールできる既存のWebサイトのリストを取得しました。次に、このリストを使用して、UIシーケンスの後半に表示されるリストボックスにデータを入力しました。すべて非常に簡単です。

IIS7にはIIS用のWMIプロバイダーがないため、このshell.Run()アプローチを使用してappcmd.exeを呼び出し、作業を実行しました。簡単です。

関連質問:JavaScriptカスタムアクションについて


2
+1 DTFアプローチはセットアップが簡単であると思いますが、JavaScriptも役に立ちます。
si618 2009年

12

Peter Tateは、再利用可能なComponentGroup定義を個別のwixフラグメントで定義する方法をすでに示しています。これに関連するいくつかの追加のトリック:

ディレクトリのエイリアス

コンポーネントグループフラグメントは、メインの製品wxによって定義されたディレクトリについて知る必要はありません。コンポーネントグループフラグメントでは、次のようなフォルダーについて話すことができます。

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

次に、メイン製品は次のようにそのディレクトリの1つ(たとえば、「productInstallFolder」)にエイリアスを設定できます。

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

ディペンデンシーグラフ

ComponentGroup要素には、ComponentGroupRef子要素を含めることができます。これは、再利用可能なコンポーネントの大きなプールがあり、それらの間に複雑な依存関係グラフがある場合に最適です。コンポーネントごとに独自のフラグメントでComponentGroupを設定し、次のように依存関係を宣言します。

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

アプリケーションの直接的な依存関係であるため、セットアップでコンポーネントグループ "B"を参照すると、アプリケーションの作成者が "B"の依存関係であることに気づかなかったとしても、コンポーネントグループ "A"が自動的に読み込まれます。循環的な依存関係がない限り、「機能するだけ」です。

再利用可能なwixlib

上記の依存関係グラフのアイデアは、big-pool-o-reusable-componentsをlit.exeを使用して再利用可能なwixlibにコンパイルする場合に最適です。アプリケーションセットアップを作成するとき、wixobjファイルのようにこのwixlibを参照できます。candle.exeリンカーは、メイン製品のwxsファイルによって「プルイン」されていないフラグメントを自動的に削除します。


12

ビルド中にWXSファイルを生成するためにT4を使用することについて誰も言及しなかったことに驚いています。Henry Lee @ New Age Solutionsを通じてこれについて学びました。

基本的に、カスタムMSBuildタスクを作成してT4テンプレートを実行し、そのテンプレートはWixプロジェクトがコンパイルされる直前にWXSを出力します。これにより、(実装方法に応じて)別のソリューションのコンパイルからのすべてのアセンブリ出力を自動的に含めることができます(つまり、新しいアセンブリを追加するたびにwxを編集する必要がなくなります)。


2
+1本当にいいです。アセンブリについてはそれほど心配していませんが、webプロジェクトでは、プロジェクトに追加されているがWiXには追加されていないaspxページやその他のアーティファクト(画像、CSS)に問題がある可能性があります。
si618 2009

4
将来の訪問者のために、Wix 3.5にはこの収穫を自動的に行うユーティリティheat.exeがあります
Mrchief

@Mrchief-Heatがローカルにコピーされた参照アセンブリを取得するとは思わない-これは明らかに4.0で計画されている。参考:sourceforge.net/tracker/...
ピーターT. LaCombジュニア

Heatは参照されたアセンブリをピックアップしません。
tofutim 2012

T4を使用してWXSファイルを生成する良い例は何ですか?
tofutim 2012

12

Heat.exeを使用して顔を粉砕し、痛みを伴う大規模なインストールで「Epic Pwnage」を引き起こす

熱 に関するSiRobert-Pの答えを拡張します。

翻訳:(個別のファイルを手作業でプロジェクトに入力することを避け、全体的に簡単なプロセスのためにビルドを自動化するために熱を使用します。)

WiX 2.0熱構文の詳細

新しいバージョンの場合(以前のバージョンとまったく異なるわけではありませんが、厄介な構文の変更がある可能性があります...)cmd.exeからHeat is inディレクトリに移動し、heatと入力しますが、ヘルプの例を1つ示します必要に応じて、新しいバージョンで。

以下をVisual Studio 2010のビルドイベントに追加します。
(プロジェクトを右クリック->プロパティ->ビルドイベント->ビルド前イベント)

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

-gg 

(上記のコマンドを実行したときのように)Heatの実行時にGUIDを生成します

-scom 

「COMファイル」を取得しない

-sreg 

「レジストリファイル」を取得しない

-sfrag 

「断片」をつかまない

-srd 

「ルートディレクトリ」をつかまないでください

dir

dirは、Heatでフォルダーを検索することを示します

「$(EnviromentVariable)」

(プロジェクトを右クリックして、プロパティに移動)プロジェクトのプロパティ->ビルドセクションのプリプロセッサ変数に定義するプリプロセッサ変数に追加する変数の名前(ビジュアルスタジオ2010を想定)

例:
EnviromentVariable = C:\ Project \ bin \ Debug;
二重引用符はありませんが、セミコロンで終わります

-cg GroupVariable 

メインwxsファイルに作成されたフラグメントから参照されるComponentGroup

FragmentDir

出力wxsフラグメントが格納されるフラグメントディレクトリ

FileName.wxs

ファイルの名前

完全なチュートリアルはここにあります。

パート1 パート2


わずかに異なる目的のために別の便利なツールがあります:パラフィン(wintellect.com/CS/blogs/jrobbins/archive/2010/03/10/4107.aspx
ralf.w.

9

COMオブジェクトを含む:

heat(すべてではないにしても)ほとんどすべてのレジストリエントリとそれらに必要なその他の構成を生成します。喜んで!

マネージCOMオブジェクト(別名、.NETまたはC#COMオブジェクト)を含む

heatマネージCOMオブジェクトでを使用すると、ほぼ完全なwixドキュメントが得られます。

GACで利用可能なライブラリが必要ない場合(つまり、世界中で利用可能:ほとんどの場合、これは.NETアセンブリで必要ありません-意図されていない場合、おそらくこの時点で何か間違ったことをしたことでしょう。共有ライブラリ)CodeBaseに設定するようにレジストリキーを更新する必要があります[#ComponentName]。GACへのインストールを計画している場合(たとえば、誰もが使用する新しい素晴らしい共通ライブラリを作成した場合)、このエントリを削除し、File要素に2つの新しい属性を追加する必要があります:AssemblyおよびKeyPath。Assemblyは ".net" KeyPathに設定し、 "yes"に設定する必要があります。

ただし、一部の環境(特にスクリプト言語などのマネージメモリを備えた環境)では、Typelibへのアクセスも必要になります。 タイプライブラリで実行heatし、インクルードしてくださいheat必要なすべてのレジストリキーを生成します。なんてクールなの?


8

へのインストール C:\ProductName

一部のアプリケーションはにインストールする必要がありますがC:\ProductName、ネットインストールの例の99.9%(100%ではない場合)はにインストールしC:\Program Files\CompanyName\ProductNameます。

次のコードを使用して、TARGETDIRプロパティをC:ドライブのルートに設定できます(WiXユーザーリストから取得)。

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

注:デフォルトでTARGETDIR ポイントしませんC:\!これは、どちらか一方が最も空き容量の多いドライブROOTDRIVEルートを指しますここを参照)-これは必ずしもC:ドライブであるとは限りません。別のハードドライブ、パーティション、またはUSBドライブがある可能性があります!

次に、<Product ...>タグの下のどこかに、通常どおり次のディレクトリタグが必要です。

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

にインストールする方が簡単ではないでしょうWindowsVolumeか?
Wim Coenen

1
はい。ただし、ここここで指摘されているWindowsVolumeように、プロパティはとして使用できない可能性があるため、回避策を使用する必要がありますDirectory(コンパイラはエラー/警告を出します)。個人的には、この回避策は混乱を招きます。
gehho

7

環境変数

Wxsドキュメントをwixobjコードにコンパイルするとき、環境変数を利用してさまざまな情報を決定できます。たとえば、プロジェクトに含めるファイルを変更するとします。MSIを構築する直前に設定したRELEASE_MODEという環境変数があるとします(スクリプトを使用するか、手動で行うかは関係ありません)。wixソースでは、次のようなことができます。

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

そして、後でコード内で適切に使用して、その場でwxsドキュメントを変更します。例:

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

1
$(Configuration)や$(Platform)などのコンパイル変数も使用できます。また、より多くの束msdn.microsoft.com/en-us/library/aa302186.aspx
si618

1
@Si-今日の少し前に、そのリンクはアクティブではなくなりました。最新のものは見つかりませんでした。
Peter M



7

ダイアログの編集

ダイアログを編集する優れた機能の1つは、バージョン4.0.1.7090以降でSharpDevelopを使用することです。このツールを使用して、スタンドアロンダイアログ(InstallDirDlg.wxsなどのWiXソースからのwxsファイル)をデザインビューで開いてプレビューし、編集できます。


素晴らしい、SharpDevelopがこれをサポートしていることを知りませんでした。
anton.burger

6

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

5

「インストールする準備はできましたか?」を変更します。ダイアログ(別名VerifyReadyDlg)は、行われた選択の概要を提供します。

これは次のようになります:
代替テキストhttp://i46.tinypic.com/s4th7t.jpg

Javascript CustomActionでこれを行います:


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

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>

CAをボタンに接続します。この例では、CustomizeDlgから[次へ]をクリックするとCAが起動します。

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

関連するSO質問:VerifyReadyDlgに表示されるテキストを実行時に設定するにはどうすればよいですか?


これは、JavaScriptがDHTMLスクリプト言語ではなく、Windowsスクリプト言語であるJScriptであるべきではありません。おそらく少し教訓的かもしれませんが、一部の人々を少し混乱させるかもしれません。
caveman_dick

5

個別にパッチを適用できるコンポーネントを独自のフラグメント内に配置します

製品のインストーラーとパッチを作成する場合、フラグメントにコンポーネントを含める場合は、そのフラグメントにすべてのコンポーネントを含める必要があります。インストーラーをビルドする場合、コンポーネントの参照を見逃すと、light.exeからリンクエラーが発生します。ただし、パッチを作成するときに、フラグメントに単一のコンポーネント参照を含めると、そのフラグメントから変更されたすべてのコンポーネントがパッチに表示されます。

このような:

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

これの代わりに:

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

また、WiX.chmヘルプファイルの「Using Purely WiX」トピックを使用してパッチを適用する場合は、次の手順を使用してパッチを生成します。

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

別のフラグメントのコンポーネントを使用して作成されたproduct.wixpdbの1.1バージョンを用意するだけでは十分ではありません。したがって、出荷前に製品を正しく断片化してください。


5

Wix3.0以降からEULAを印刷する

1)wixソースコードをコンパイルするとき、light.exeはコマンドラインでWixUIExtension.dllを参照する必要があります。これには、コマンドラインスイッチ-extを使用します。

2)WixUIExtension.dllへの参照を追加したときにプロジェクトのコンパイルが失敗した場合、これはダイアログIDの衝突が原因である可能性が高いです。つまり、プロジェクトはWixUIExtension.dllのいくつかの標準ダイアログと同じダイアログのIDを使用していましたダイアログに異なるIDを与えます。これはよくある問題です。

3)ライセンスダイアログには、「LicenseText」というIDのScrollableTextコントロールが必要です。Wixは、印刷時にこのコントロール名を正確に検索します。

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

カスタムアクションを参照するPushButton

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

4)次のように、Id = "PrintEula"を使用してCustomActionを定義します。

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

注:BinaryKeyはWix3.0とWix2.0で異なり、正確に「WixUIWixca」でなければなりません(大文字と小文字が区別されます)。

ユーザーがボタンを押すと、標準の[プリンターの選択]ダイアログが表示され、そこから印刷できます。


5
  • GUIの最初の画面のどこかに(小さな)製品バージョンを表示します。なぜなら、人々は毎回正しいバージョンを選ぶのを間違える傾向があるからです。(そして、私たちの開発者に年齢を探し続けさせてください。)

  • TFSBuildをセットアップして、さまざまな環境の構成で変換(.mstファイル)も生成します。(私たちは展開する必要があるすべての環境について知っています)。

Grant Hollidayによる元のブログ投稿がダウンしているため、ここにその内容をコピーして貼り付けました。


XMLMarch 11 2008からMSI変換ファイルを生成するMSBuildタスク

前回の投稿で、MSI変換(* .mst)ファイルを使用して、環境固有の構成設定を一般的なMSIパッケージから分離する方法について説明しました。

これにより、構成にある程度の柔軟性が提供されますが、変換ファイルには2つの欠点があります。

  1. バイナリ形式です
  2. 変換ファイルを「編集」または「表示」することはできません。それを適用または再作成して、含まれる変更を確認する必要があります。

幸い、Microsoft Windowsインストーラーオブジェクトライブラリ(c:windowssystem32msi.dll)を使用してMSI「データベース」を開き、変換ファイルを作成できます。

クレジットは再びAlex Shevchukに送られます– MSIからWiXへ–パート7 – VbScriptでこれを達成する方法を示すための変換を使用したインストールのカスタマイズ 基本的に、私がやったことはすべてAlexの例であり、Interop.WindowsInstaller.dllを使用してMSBuildタスクを実装しました。MSBuildタスク

ここからソースコードとサンプルのtransforms.xmlをダウンロードします(〜7Kb Zipped VS2008 Solution)



2
ローカリゼーションファイルでWelcomeDlgTitleを再定義します-うまくいきます!<String Id = "WelcomeDlgTitle"> {\ WixUI_Font_Bigger} [ProductName] [ProductVersion]セットアップウィザードへようこそ</ String>
saschabeaumont 2009

5

インストールパッケージを展開する前に、その内容を常に制御しています。

コマンドラインでの単純な呼び出しです(Terrences postによると)コマンドラインを開いて入力します

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

これにより、パッケージの内容が現在のパスでサブディレクトリ「抽出」に抽出されます。


4

ORCAの代わりに、MSIテーブルを表示するための優れたツールであるInstEdを使用します。また、Transform-> Compare To ...で2つのパッケージを比較する機能もあります。

さらに、追加機能を備えたPlusバージョンが利用可能です。しかし、無料版もOrcaに代わる優れた選択肢です。


4

x86 / x64互換のCOM相互運用機能のための.NETアセンブリの登録

注意:このフラグメントはREGASM Assembly.dll / codebaseと基本的に同じです

このサンプルではいくつかのことが行われているので、ここにコードを示します。後で説明します...

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

疑問に思っている方は、これは実際にはASCOM望遠鏡ドライバー用です。

まず、上記のアドバイスを参考にして、別のファイルにいくつかのplatforma変数を作成しました。これらの変数はXML全体に散らばっています。

一番上のif-then-else部分は、x86とx64の互換性を扱います。私のアセンブリは「すべてのCPU」をターゲットにしているため、x64システムでは、64ビットのレジストリに1回と32ビットのWow6432Node領域に1回、2回登録する必要があります。if-then-elseがこれを設定し、値はforeach後でループで使用されます。このようにして、レジストリキーを1回作成するだけで済みます(DRYの原則)。

file要素は、インストールおよび登録される実際のアセンブリdllを指定します。

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

革新的なものはありませんが、Assembly=".net"この属性だけでアセンブリがGACに配置されることに注意してください。これは、私が望んでいたことではありません。AssemblyApplication属性を使用してそれ自体を指すことは、WixがファイルをGACに配置するのを停止する方法にすぎません。Wixが.netアセンブリであることを認識!(bind.assemblyFullname.filDriverAssembly)したので、アセンブリのフルネームを取得するなど、XML内で特定のバインダー変数を使用できます。


3

DISABLEADVTSHORTCUTSインストーラーでアドバタイズされたすべてのショートカットが通常のショートカットになるようにプロパティを設定します。キーパスとして使用されるダミーの登録キーを含める必要はありません。

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

Windows Installer 4.0以上が必要だと思います


2

それは素晴らしい構造ですが、私の経験に基づいて、これらの条件にどのように対処するのか疑問に思います:

A.インストールがすべて同じ宛先に到達しているように見えます。ユーザーが3つすべてのバージョンを一度にインストールする必要がある場合、プロセスはこれを許可します。トリガーしているすべての実行可能ファイルのバージョンを明確に伝えることができますか?

B. TESTやTRAININGに存在するが、まだLIVEに存在しない新しいファイルをどのように処理しますか?


こんにちはブレイン、A。いいえ、そうではありません。InstallNameはsvn:externalsによって参照されない唯一のファイルであるConfig.wxiにあります。したがって、これはインストールごと、つまり製品ごとに固有です。そのため、バージョンごとにGUIDを変更します。B. GOTO A. :)これらは、独自のUpgradeCodeを持つ個別のMSIです。
si618 2009

1
ところで、なぜ私の質問に質問で答えたのか理解しましたが、十分な担当者ポイントを獲得したら、質問を回答コメントに移動してください。そうしないと、スレッドを追跡するのが難しくなります。
si618

2

大規模なWebプロジェクトが、デプロイされたファイルの数がMSI(またはマージモジュール)に組み込まれたファイルの数と一致することを確認するのに役立つ方法を次に示します。私はメインアプリケーション(まだ開発中)に対してカスタムMSBuildタスクを実行しただけで、見つからないファイル、主に画像をかなりの数だけ取得しましたが、いくつかのJavaScriptファイルが侵入しました!

このアプローチ(WiXプロジェクトのAfterBuildターゲットにフックすることでMSIのファイルテーブルを調べる)は、予想されるファイルの完全なリストにアクセスできる他のアプリケーションタイプで機能します。


2

インストールがアンインストールまたは再インストールを許可せず、ロールバックしないときに強制再インストールを実行する。

何らかの理由でアンインストールされないインストールを上書きするために使用されるVBscriptスクリプト。

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)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.