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