3

我正在尝试在我的设置和部署项目中调用自定义操作来更新我的应用程序中 app.config 中的某些项目。我以通常的方式结束了自定义配置部分,例如:

[ConfigurationProperty("serviceProvider", IsRequired = true)]
public string ServiceProvider
{
    get { return (string)base["serviceProvider"]; }
    set { base["dataProviderFactory"] = value; }
}

我已经设置了要在安装的安装部分中调用的自定义操作,就在 base.Install(stateSaver) 之后。代码是:

string exePath = string.Format("{0} MyApp.exe", Context.Parameters["DP_TargetDir"]);
SysConfig.Configuration config = ConfigurationManager.OpenExeConfiguration(exePath);
Configuration. MyApp section = Configuration.MyApp)config.GetSection("MyApp");

当我运行这个时,我得到这个错误:

System.Configuration.ConfigurationErrorsException:为 MyApp 创建配置节处理程序时出错:无法加载文件或程序集“MyCompany。MyApp.Configuration' 或其依赖项之一。该系统找不到指定的文件。(C:\Program Files\MyCompany\MyApp\MyApp.exe.config 第 5 行)---> System.IO.FileNotFoundException:无法加载文件或程序集“MyCompany.MyApp.Configuration”或其依赖项之一。该系统找不到指定的文件。

配置中的第 5 行是:

<section name="MyApp"
    type="MyCompany.MyApp.Configuration.MyApp, MyCompany.MyApp.Configuration"
    requirePermission="false" />

带有安装程序代码的类库(这是该库中唯一的类)具有对配置程序集的引用。

我在这里遗漏了一些非常明显的东西吗?我无法弄清楚为什么找不到配置的引用。

任何帮助/建议将不胜感激。

4

3 回答 3

7

我设法在 MSDN 上找到了一些代码,这些代码提供了一种有效的(尽管被黑了)方法来做到这一点。链接在这里:ConfigurationManager、自定义配置和 installutil/路径搜索问题

如果不是因为能够在建议的帮助下进行调试,就不会找到它,所以感谢你们俩。

作为参考,我的最终安装代码是:

public override void Install(IDictionary stateSaver)
{
    base.Install(stateSaver);

    string targetDirectory = Context.Parameters["DP_TargetDir"];
    stateSaver.Add("TargetDir", targetDirectory);

    string exePath = Path.Combine(targetDirectory, "MyApp.exe");

    System.Diagnostics.Debugger.Break();

    ResolveEventHandler tempResolveEventHandler =
        (sender, args) =>
            {
                string simpleName = new AssemblyName(args.Name).Name;
                string path = Path.Combine(targetDirectory, simpleName + ".dll");
                return File.Exists(path)
                    ? Assembly.LoadFrom(path)
                    : null;
            };

    try
    {
        // hook up asm resolve handler  
        AppDomain.CurrentDomain.AssemblyResolve += tempResolveEventHandler;

        System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(exePath);
        Configuration.MyApp section = (Configuration.MyApp) config.Sections["MyApp"];

        if (section != null)
        {
            // "ApplicationSettings.DefaultDatabasePath" is the custom config value I'm updating
            section.ApplicationSettings.DefaultDatabasePath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
            config.Save();
        }
    }
    finally
    {
        // remove asm resolve handler.  
        AppDomain.CurrentDomain.AssemblyResolve -= tempResolveEventHandler;
    }

}
于 2009-10-19T12:31:26.187 回答
1

检查“MyCompany.MyApp.Configuration”是否标有 copy local=true。

还要检查您的项目是否还引用了“MyCompany.MyApp.Configuration”所依赖的 dll。

于 2009-10-19T10:21:06.150 回答
1

安装项目将调用它在项目组装文件中找到的所有安装程序类。

我必须承认我倾向于覆盖 Installer 类中的 Install 方法。

这是我在这里的一些代码的直接剪切和粘贴:

public override void Install(System.Collections.IDictionary stateSaver)
{
    base.Install(stateSaver);

   // System.Diagnostics.Debugger.Break();
    string targetDirectory = Context.Parameters["targetdir"];

    string param1 = Context.Parameters["Param1"];
    string param2 = Context.Parameters["Param2"];
    string param3 = Context.Parameters["Param3"];
    string param4 = Context.Parameters["Param4"];

    string exePath = string.Format("{0}AlarmMonitor.exe", "[SystemFolder]");

    PHPCCTVClassLibrary.CctvSite site = new PHPCCTVClassLibrary.CctvSite();
    site.Name = param1;
    site.EndPoint = string.Format(@"tcp://{0}:5005", param2);
    site.Password = param4;
    site.Username = param3;
    site.AutoReconnect = true;
    site.AlarmHandling = new PHPCCTVClassLibrary.CctvSiteAlarmHandling();
    site.AlarmHandling.Audio = new PHPCCTVClassLibrary.AudioSetup();
    site.AlarmHandling.Audio.AlarmAddedFile = "alarmadded.wav";
    site.AlarmHandling.Audio.AlarmDeletedFile = "alarmdeleted.wav";
    site.AlarmHandling.Audio.AlarmUpdatedFile = "alarmupdated.wav";

    PHPCCTVClassLibrary.CctvSites sites = new PHPCCTVClassLibrary.CctvSites();
    sites.Site = new PHPCCTVClassLibrary.CctvSite[] { site };
    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(PHPCCTVClassLibrary.CctvSites));
    //System.Diagnostics.Debugger.Break();

    System.IO.TextWriter tw = new System.IO.StreamWriter(@"CCTVAlarmConfig.xml", false);
    serializer.Serialize(tw, sites);
    tw.Close();

}

它创建一个 xml 配置文件,由安装时运行的自定义操作调用,并具有以下 CustomActionData:/Param1="[EDITA1]" /Param2="[EDITA2]" /Param3="[EDITA3]" /Param4= "[EDITA4]" /targetdir="[TARGETDIR]"

EDITA1 等来自带有 4 个文本框的用户界面。我故意在 [TARGETDIR] 之后包含一个空格,因为没有它你会得到一些非常奇怪的行为,因为它无法找到安装目录。

如果该行未注释,则 System.Diagnostics.Debugger.Break() 注释允许您从这一点进行调试。

于 2009-10-19T10:28:52.890 回答