开发者

FileNotFoundException in Visual Studio Setup and Deployment Project when trying to load custom config

I'm trying to call a custom action within my Setup & Deployment project to update some items within the app.config on my app. I've wrapped up the custom config section in the usual way, e.g.:

[ConfigurationProperty("serviceProvider", IsRequired = true)]
public string ServiceProvider
{
    get { return (string)base["serviceProvider"]; }
    set { base["dataProviderFactory"] =开发者_高级运维 value; }
}

I've set the custom action to be called during the Install section of installation just after base.Install(stateSaver). The code is:

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

When I run this, I get this error:

System.Configuration.ConfigurationErrorsException: An error occurred creating the configuration section handler for MyApp: Could not load file or assembly 'MyCompany. MyApp.Configuration' or one of its dependencies. The system cannot find the file specified. (C:\Program Files\MyCompany\MyApp\MyApp.exe.config line 5) ---> System.IO.FileNotFoundException: Could not load file or assembly 'MyCompany.MyApp.Configuration' or one of its dependencies. The system cannot find the file specified.

Line 5 in the config is:

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

The class library with the installer code (that being the only class in that library) has a reference to the config assembly.

Is there something really obvious that I'm missing here? I can't work out why the ref to the config isn't being found.

Any help/suggestions would be very much appreciated.


I managed to find some code on MSDN that provides a working (albeit hacked) way to do this. Link is here: ConfigurationManager, custom config, and installutil / path searching problem.

Wouldn't have found it if not for being able to debug with help from suggestions so thanks to both of you for that.

For reference, my final install code is:

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

}


Check that 'MyCompany.MyApp.Configuration' is marked with copy local=true.

Check also that your project also references the dll's that 'MyCompany.MyApp.Configuration' depend upon.


The Setup Project will call all installer classes that it finds in the project assembly files.

I must admit that I tend to override the Install method within the Installer class.

Here's a direct cut and paste from some code that I have here:

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

}

It creates an xml config file, being called by a Custom action that runs at install and has the following CustomActionData: /Param1="[EDITA1]" /Param2="[EDITA2]" /Param3="[EDITA3]" /Param4="[EDITA4]" /targetdir="[TARGETDIR] "

EDITA1 etc come from a user interface with 4 text boxes. I have deliberately included a space after [TARGETDIR] as without it you'll get some quite odd behaviour as it can't then find the installation directory.

The System.Diagnostics.Debugger.Break() comment allows you to debug from this point if the line is uncommented.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜