0

InstallShieldには、XMLファイルの変更*を介してアプリケーションの.configファイルを変更する機能が含まれていますが、複数のインストールパッケージ間で構成設定を共有する場合はどうでしょうか。

私たちの環境では、WPFアプリケーションとWinFormsアプリケーションを提供します。一方は管理コンソールで、もう一方はデータ収集アプリです(ユーザーが必要なものを選択する単一のインストーラー)。また、両方のアプリで使用されるサービスレイヤーのインストーラーも同梱されているため、Webサービスのエンドポイントはお客様の場所ごとに異なります。(実際の環境はもう少し複雑ですが、上記は複雑さの例です)

私たちの方向性は、共通の設定を含む両方のインストーラーの共通の構成設定を持つXMLファイルを作成することです。InstallShieldはこれらの値を読み取り、同じエンドポイントを指すように各アプリケーションの.configファイルを更新します。誰かこれをしましたか?InstallScriptまたはカスタムアクションを使用せずにこれを実行できますか?

  • xml構成ファイルをXMLファイル変更領域にインポートして、構成ファイルからすべての行を読み込み、すべての行に対してXPathを介して追加要求を作成します(例:add [@ key="IsMultiTouch"および@value= "True"])。これは、開発チームからファイルの現在の状態で読み取りたい場所にファイルを再作成し、インストール中にappsettingsの値のみを変更するだけであると思われるため、理想的とは言えません。
4

2 に答える 2

1

[followUp] CtrlGetText()を使用してInstallShieldダイアログから値を取得し、そのデータをdllに渡して、アプリの構成ファイルに含めました。結果の.configファイルエントリには、多数の「�」シーケンスが含まれていました。InstallScriptでそれらをクリーンアップしようとしても、うまくいきませんでした。最終的には、XmlDocumentを文字列に反転し、文字列に対して.Replace( "�"、 "")を実行し、それをXmlDocumentにロードして(有効であることを確認するために)、dll内でそれらをクリーンアップする必要がありました。 。InstallShield!=すごい。[/ファローアップ]

XMLファイルの変更は適切な方向ではないように思われるため、代わりに、機能のインストール後に起動するカスタムアクションを作成しました。カスタムアクションは、アプリケーションの.configファイルに変更を適用してxmlファイルをスピンするマネージアセンブリを呼び出します。

カスタムアクション

#define CO_APPCONFIG_DLL "MyCompany.InstallShield.AppConfig.dll"
#define CO_APPCONFIG_FQNAME "MyCompany.InstallShield.AppConfig.ConfigMgr"

#define CO_APPSETTINGS_NEW "MyApp_AppSettings.xml"
#define CO_APPSETTINGS_CONFIG "MyCompany.IOAnywhere.Dashboard.exe.config"
#define CO_APPSETTINGS_SECTION "CO_dashboard"

//---------------------------------------------------------------------------
// The Installed event is sent after the feature Dashboard
// is installed.
//---------------------------------------------------------------------------
export prototype Dashboard_Installed();
function Dashboard_Installed()
BOOL bResult;
OBJECT oAppConfig;
begin

try
    // Note: the configuration dll is in the support directory
    set oAppConfig = DotNetCoCreateObject(SUPPORTDIR ^ CO_APPCONFIG_DLL, CO_APPCONFIG_FQNAME, "");
catch
    MessageBox("Error Loading" + SUPPORTDIR ^ CO_APPCONFIG_DLL + ": " + Err.Number + " " + Err.Description, INFORMATION); 
    abort;
endcatch;

try
    // Note: the new configuration settings file should be in the same folder as the setup.exe
    bResult = oAppConfig.ConfigureSettings(CO_APPSETTINGS_NEW, TARGETDIR ^ CO_APPSETTINGS_CONFIG, CO_APPSETTINGS_SECTION);
catch
    MessageBox("Verify that the file " + CO_APPSETTINGS_NEW + " exists in the setup directory.  Error calling ConfigureSettings " + SUPPORTDIR ^ CO_APPCONFIG_DLL + " " + Err.Number + " " + Err.Description, INFORMATION);
endcatch;

end;

DLLと呼ばれる

using System;
using System.Xml;

/// <summary>
/// Called by InstallShield Installer process to apply appSettings to an installed applications .config file
/// </summary>
namespace CO.InstallShield.AppConfig
{
    /// <summary>
    /// ConfigMgr is the class that encapsulates functionality related to modifying a .config file
    /// </summary>
    public class ConfigMgr
    {
        /// <summary>
        /// ConfigureSettings applies changes from a common xml file to the applications .config file
        /// </summary>
        /// <remarks>
        /// Ensures required keys for the application are included in the .config file
        /// Applies common settings to the .config file
        /// Applies application specific settings to the .config file
        /// </remarks>
        /// <param name="configFilePath">Path to the xml file that has the setting that need to be applied</param>
        /// <param name="targetAppConfigPath">Path to the .config file for the appliction</param>
        /// <param name="targetAppName">Section in the xml file that has application specific settings</param>
        /// <returns>True if it was able to configure settings</returns>
        public bool ConfigureSettings(string configFilePath, string targetAppConfigPath, string targetAppName)
        {
            bool completed = false;

            try
            {
                XmlDocument configFileDoc = new XmlDocument();
                configFileDoc.Load(configFilePath);

                XmlDocument targetAppConfigDoc = new XmlDocument();
                targetAppConfigDoc.Load(targetAppConfigPath);

                // ensure the appSettings section exists
                AddRequiredSections(ref targetAppConfigDoc);

                // ensure all required keys exist in the target .config file
                AddRequiredKeys(configFileDoc.SelectSingleNode("configuration/" + targetAppName + "/requiredKeys"), ref targetAppConfigDoc);

                // loop through each key in the common section of the configuration file
                AddKeyValues(configFileDoc.SelectSingleNode("configuration/common/appSettings"), ref targetAppConfigDoc);

                // loop through each key in the app specific section of the configuration file - it will override the standard configuration
                AddKeyValues(configFileDoc.SelectSingleNode("configuration/" + targetAppName + "/appSettings"), ref targetAppConfigDoc);

                // save it off
                targetAppConfigDoc.Save(targetAppConfigPath);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                completed = true;
            }
            return completed;
        }
        private void AddRequiredSections(ref XmlDocument targeAppConfigDoc)
        {
            // Ensure the target .config file has an appSettings section... unusual but evidently possible
            if (targeAppConfigDoc.SelectSingleNode("configuration/appSettings") == null)
                targeAppConfigDoc.SelectSingleNode("configuration").AppendChild(targeAppConfigDoc.CreateNode(XmlNodeType.Element, "appSettings", null));
        }
        private void AddKeyValues(XmlNode configAppNodeSet, ref XmlDocument targetAppConfigDoc)
        {
            if (configAppNodeSet == null) return; // Nothing to do

            foreach (XmlNode configNode in configAppNodeSet.SelectNodes("add"))
            {
                XmlNode targetNode = targetAppConfigDoc.SelectSingleNode("configuration/appSettings/add[@key='" + configNode.Attributes["key"].Value + "']");
                if (targetNode != null)
                {
                    targetNode.Attributes["value"].Value = configNode.Attributes["value"].Value;
                }
            }
        }
        private void AddRequiredKeys(XmlNode targetAppNodeSet, ref XmlDocument targetAppConfigDoc)
        {
            if (targetAppNodeSet == null) return; // Nothing to do

            foreach (XmlNode targetNode in targetAppNodeSet.SelectNodes("key"))
            {
                // add the key if it doesn't already exist
                XmlNode appNode = targetAppConfigDoc.SelectSingleNode("configuration/appSettings/add[@key='" + targetNode.Attributes["value"].Value + "']");
                if (appNode == null)
                {
                    appNode = targetAppConfigDoc.SelectSingleNode("configuration/appSettings");
                    XmlNode newAddNode = targetAppConfigDoc.CreateNode(XmlNodeType.Element, "add", null);
                    XmlAttribute newAddNodeKey = targetAppConfigDoc.CreateAttribute("key");
                    newAddNodeKey.Value = targetNode.Attributes["value"].Value;
                    XmlAttribute newAddNodeValue = targetAppConfigDoc.CreateAttribute("value");
                    newAddNodeValue.Value = "NotSet";
                    newAddNode.Attributes.Append(newAddNodeKey);
                    newAddNode.Attributes.Append(newAddNodeValue);
                    appNode.AppendChild(newAddNode);
                }
            }
        }
    }
}
于 2012-06-26T17:14:49.027 に答える
0

インストールの観点からは、remember-property パターンのバリアントに従うことで、これの多くを取得できます。XML ファイルの変更によって参照されるプロパティの値を格納することにより、さまざまな構成情報を共有レジストリ キーに登録する共有コンポーネントを作成します。システム検索を使用して、同じまたは関連するインストールの後続の実行にこれらの値を読み戻そうとします。ただし、このアプローチでは、関連するプロジェクト内の既存の個別の構成ファイルは更新されません。

これに対処するには (個別の構成がそれ自体で役立つ場合もありますが)、単一の共有構成を参照する方法を見つけることをお勧めします。これは、構成ファイルに共有ディレクトリを使用することによる可能性があります。共有レジストリの場所を直接参照し、前述の XML ファイルの変更をスキップすることが原因である可能性があります。

于 2012-06-15T11:49:35.817 に答える