3

Setup&Deploymentプロジェクト内でカスタムアクションを呼び出して、アプリの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'またはその依存関係の1つ。システムは、指定されたファイルを見つけることができません。(C:\ Program Files \ MyCompany \ MyApp \ MyApp.exe.config line 5)---> System.IO.FileNotFoundException:ファイルまたはアセンブリ'MyCompany.MyApp.Configuration'またはその依存関係の1つを読み込めませんでした。システムは、指定されたファイルを見つけることができません。

構成の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'がcopylocal=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();

}

インストール時に実行され、次の CustomActionData を持つカスタム アクションによって呼び出される xml 構成ファイルを作成します。 "[EDITA4]" /targetdir="[TARGETDIR]"

EDITA1 などは、4 つのテキスト ボックスを備えたユーザー インターフェイスから取得されます。[TARGETDIR] の後に意図的にスペースを入れました。スペースがないと、インストール ディレクトリが見つからないため、非常に奇妙な動作が発生します。

System.Diagnostics.Debugger.Break() コメントを使用すると、行のコメントが解除されていれば、この時点からデバッグできます。

于 2009-10-19T10:28:52.890 に答える