2012-03-12 5 views
4

パラメータが[#file.Product]スタイルのファイルID参照として渡される遅延カスタムアサインの使用に問題があります。 exe.config]:WiX [#filekey]が解決されておらず、管理対象CustomAction内のパスとして使用可能です

<Component Id="comp.Product.exe.config" 
      Guid="{966DA007-E3F0-4BFE-94ED-63A66F82CA58}" 
      Win64="$(var.Win64)"> 
    <File Id="file.Product.exe.config" 
      Name="Product.exe.config" 
      Source="$(var.SourcePath)\Product.exe.config" 
      KeyPath="yes" /> 
</Component> 

それから私はそうのような遅延カスタムアクションに渡された上で、後にあるConfigurationFileというプロパティを持っている:

<Property Id="ConfigurationFile" 
      Value="[#file.Product.exe.config]" /> 

私は以前にConfigurationFileプロパティ値を割り当て= "[ APPLICATIONROOTDIRECTORY] \ Product.exe.config "はうまくいきましたが、私たちは別のフォルダに設定をインストールする必要があります(この理由はこのトピックとは無関係です)。[#file.Product.exe.config]構文を使用して、設定ファイルの場所をインストーラから解決する必要がありました。

カスタムアクションがパラメータを受け取ると、それはまだ[#file.Product.exe.config]形式(つまり、未解決)であり、問​​題が発生します。私はかなりロギングに基づいてそれが働いているように見えたので、かなりの間混同されました。それはSession.Log()がこのファイル参照を解決し、その結果、ログが引数の実際の内容について私に「横たわっている」という結果になりました。

session.Format() を含むこの文字列を "claning"するさまざまな方法を試してみましたが、結果はInvalidHandleExceptionとなり、レコードを使用しています。

using (Record formatRec = new Record(0)) 
{ 
    formatRec.FormatString = p0; 
    return formatRec.GetString(0) // Or formatRec.ToString(); 
} 

この規則を処理するWiXには、いくつかのカスタムアクションが用意されています。しかし、私はまだ彼らがそれをどのようにして見つけ出す必要があります。これらのカスタムアクションのソースコードに潜んでいるときにはまだ運がありません。

カスタムアクションへの引数は、Session.CustomActionDataから取得されます。

これを処理する良い方法はありますか?

+0

以下の回答は役に立ちましたか? –

答えて

1

灰色の髪の毛があり、汚い言葉がかなり出てきたので、私は解決策を思いついた。それは@ Zachary Youngsの答えに基づいていますが、いくつかの変更が必要でした。

遅延アクションを使用すると、プロパティへのアクセスが許可されません。プロパティを設定するアクションを即時型として実行すると、プロパティの[#filekey]参照がそのまま残ります。以下のソリューションを作品使用

次のように

<!-- Custom action to set update [ConfigurationFile] to the resolved filename --> 
<CustomAction Id="SetResolvedConfigurationFile" 
       BinaryKey="LocusCA" 
       DllEntry='SetResolvedConfigurationFile' 
       Return="check" 
       Execute="immediate" /> 
<!-- Set CustomActionData for MergeConfiguratioFiles custom action --> 
<CustomAction Id="SetMergeConfigurationFiles" 
       Property="MergeConfigurationFiles" 
       Execute="immediate" 
       Value="[ConfigurationFile]" /> 

<!-- Merge settings from old configuration file to the one being installed --> 
<CustomAction Id='MergeConfigurationFiles' 
       BinaryKey="LocusCA" 
       DllEntry='MergeConfigFiles' 
       Return="check" 
       Execute="commit" /> 

<InstallExecuteSequence> 
    <Custom Action="SetResolvedConfigurationFile" Before="InstallFinalize">NOT (WIX_UPGRADE_DETECTED = "") AND NOT (ConfigurationFile = "")</Custom> 
    <Custom Action="SetMergeConfigurationFiles" After="SetResolvedConfigurationFile">NOT (WIX_UPGRADE_DETECTED = "") AND NOT (ConfigurationFile = "")</Custom> 
    <Custom Action="MergeConfigurationFiles" After="SetMergeConfigurationFiles">NOT (WIX_UPGRADE_DETECTED = "") AND NOT (ConfigurationFile = "")</Custom> 
</InstallExecuteSequence> 

カスタムアクションSetResolvedConfigurationFileは次のとおりです。

[CustomAction] 
public static ActionResult SetResolvedConfigurationFile(Session session) 
{ 
    // Set property ResolvedConfigurationFile 
    try 
    { 
     session["ConfigurationFile"] = session.FormatRecord(new Record(1) { FormatString = session["ConfigurationFile"] }); 
    } 
    catch (Exception ex) 
    { 
     session.Log("Unable to find configuration file for merge from property 'ConfigurationFile'): " + ex); 
     return ActionResult.Failure; 
    } 
    return ActionResult.Success; 
} 

[ConfigurationFile]の現在の値を解決するためにsession.FormatRecordを使用して、プロパティに書き戻すと、カスタムアクションの既存の設定が機能します。

注:マージする必要があるファイルはまだ存在しないため、即時実行するために自分のアクションMergeConfigurationFileを変更するショートカットを使用しても機能しません。 )(フォーマットしようとするときInvalidHandleExceptionでMergeConfigurationFile結果内で直接session.FormatRecordを使用して実行すると=「コミット」、およびRecord.ToString()又はRecord.GetStringを使用するだけ【#filekey]参照を返します。

+0

申し訳ありませんこれは古い投稿であることは分かっていますが、これを手に入れることができたかどうか疑問に思っています。私も設定ファイルをマージしようとしていますが、新しい設定ファイルにアクセスする方法を理解できませんか? – Mike

+0

あなたがコメントを投稿して以来、それは長い時間を知っていて、あなたはそれ以来それを理解することができたと思います。合併はうまくいった。マージ自体は、属性Name/idまたはkeyを識別子として使用し、古い設定ファイルから値をコピーすることで、2つのXMLドキュメントを「ちょうど」読み込んでいます。基本的に元のXMLツリーを反復し、現在作業している要素に基づいてXPath式を作成して、アップグレードされる構成ファイルから値を取得します。すべてのアセンブリのリダイレクトを除外することを忘れないでください。リダイレクトが正しくない場合は、非常に厄介な問題が発生する可能性があります。 – bigfoot

4

あなたはtype 51 custom actionは、プロパティを設定する必要があります。

<CustomAction Id="SetProductConfigPath" 
       Property="ConfigurationFile" 
       Value="[#file.Product.exe.config]" 
       Execute="deferred"/> 
<InstallExecute> 
    <Custom Action="SetProductConfigPath" 
      Before="InstallInitialize">/> 
</InstallExecute> 

あなたは「InstallInitialize」以外の何かにスケジュールを調整する必要があるかもしれません。

すべてのCustomActionタイプのリストを参照してくださいブログ記事From MSI to WiX, Part 5 - Custom actions: Introduction、およびブログ投稿Property does not exist or empty when accessed from deferred custom action繰延カスタムアクションの詳細な説明のために。

こちらがお役に立てば幸いです。

+0

悲しいことに、それはうまくいきませんでした。私はプロパティを設定するときにExecute = "deferred"を使用することはできませんが、即時型として終了します(これはタイプ51になります)。 MergeConfigFileFullPath = [ConfigurationFile]プロパティを設定するアクションを実行し、次のステップで[MergeConfigFileFullPath]を渡して実行する必要があるCAのCustomActionDataを設定します。結果は[ConfigurationFile]を直接渡すときと同じ結果になります。 CAに渡される値は、実際のファイル名としてログに記録されるファイル参照[#file.Product.exe.config]です。 – bigfoot

+0

私は、MSIに参照の解決されたファイル名を教えてもらう方法を見つけることができました。後者のアプローチはちょっと複雑で内部作業には深すぎるものがありますが、それは避けるべきことだと思います。 – bigfoot

関連する問題