2009-10-19 2 views
3

내 설치 & 배포 프로젝트 내에서 사용자 지정 동작을 호출하여 응용 프로그램의 app.config 내의 일부 항목을 업데이트하려고합니다. 나는 일반적인 방법으로 사용자 지정 설정 섹션, 예컨대 : 나는 사용자 지정 작업을 설정 한Visual Studio 설치 및 배포 프로젝트에서 사용자 지정 구성을로드하려고 할 때 FileNotFoundException이 발생합니다.

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

, 나는이 오류를 얻을 :는 config에

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.

5 호선입니다 :

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

설치 코드와 클래스 라이브러리 (해당 라이브러리의 유일한 클래스 임)에는 config 어셈블리에 대한 참조가 있습니다.

내가 여기에 실종되었다는 것이 정말 명백한가요? 구성에 대한 참조가없는 이유를 해결할 수 없습니다.

어떤 도움이나 제안이라도 대단히 감사하겠습니다.

+0

그냥 테스트하고 그것은 코드가 C 내에서 실행되고 있음을 보인다는 사용자 지정 설정을 세밀하게 할 수없는 이유 \ WINDOWS \ system32를 그렇게이있을 수 있습니다 어셈블리. –

답변

7

MSDN에서이 작업을 수행하기위한 해킹 방법을 제공하는 코드를 발견했습니다. 링크는 여기에 있습니다 : ConfigurationManager, custom config, and installutil/path searching problem.

제안 사항의 도움으로 디버깅 할 수 없다면 발견하지 못했을 것입니다. 덕분에 두 분 모두에게 감사드립니다.

참고로

, 내 최종 설치 코드는 다음과 같습니다

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

} 
+0

이 솔루션을 이용해 주셔서 감사합니다. 구성 섹션을 구성하는 응용 프로그램이 있지만 플러그인 시스템을 통해, 즉 응용 프로그램에서 빌드 시간 동안 참조하지 않습니다. 내가 구성에서 액세스 할 때 성가신 FileNotFound 예외를 보았지만 솔루션을 통해 이제 제대로 해결할 수 있으며 모든 것이 성공합니다! – Alex

1

'MyCompany.MyApp.Configuration'이 copy local = true로 표시되어 있는지 확인하십시오.

또한 프로젝트가 'MyCompany.MyApp.Configuration'이 의존하는 dll을 참조하는지 확인하십시오.

+0

로컬 복사가 true로 설정되고 모든 필요한 참조가 내가 볼 수있는 한 참조되었습니다. (콘솔 응용 프로그램을 통해) 설치 관리자 클래스 외부에서 코드를 실행하면 정상적으로 작동합니다. –

1

설치 프로젝트는 프로젝트 어셈블리 파일에서 찾은 모든 설치 관리자 클래스를 호출합니다.

필자는 Installer 클래스 내에서 Install 메서드를 재정의 (override)하는 경향이 있음을 인정해야합니다.

가 여기에 직접 컷 그리고 내가 여기있는 일부 코드에서 붙여 넣기 : 그것은 설치에서 실행되며 다음 CustomActionData이있는 사용자 지정 작업에 의해 호출되고,하는 XML 설정 파일을 생성

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

} 

:/Param1을 = "[EDITA1]"/ Param2 = "[EDITA2]"/ Param3 = "[EDITA3]"/ Param4 = "[EDITA4]"/ targetdir = "[TARGETDIR]

EDITA1 등은 사용자 인터페이스 4 개의 텍스트 상자. 나는 의도적으로 [TARGETDIR] 뒤에 공백을 포함 시켰습니다. 설치 디렉토리를 찾을 수 없으므로 아주 이상한 행동을 취할 것입니다.

System.Diagnostics.Debugger.Break() 주석을 사용하면 줄의 주석 처리를 해제하면이 지점에서 디버깅 할 수 있습니다.

+0

안녕하세요, 코드 샘플을 보내 주셔서 감사합니다. 문제는 기존 config XML을 객체 유형으로 읽는 것과 더 관련이 있다고 생각합니다. 디버거에 대한 힌트는 엄청난 도움이 될 것입니다, 감사합니다. –

관련 문제