Wednesday, March 4, 2009

app.config에 대해서

csc, vbc, jsc등 커맨드라인으로 컴파일하거나, nant를 사용하여 컴파일 할 때,
사용자가 만든 라이브러리를 reference해서 컴파일 하는 경우,
dll파일이 현재 디렉토리에 있지 않고 다른 곳에 있는 경우가 있다.

즉 nant같으면

<target name="build">
<mkdir dir="${build.dir}">
<csc target="exe" output="${build.dir}/${basename}.exe" debug="${debug}">
<sources>
<include name="*.cs">
</include>
<references>
<lib>
<include name="C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727">
<include name="C:\dev\rensaba\LivedoorServiceApiClient\LivedoorServiceApiClient\bin\Release">
<include name="C:\dev\rensaba\MobileLivedoorApiWrapper\MobileLivedoorApiWrapper\bin\Release">
</include>
<include name="mscorlib.dll">
<include name="System.dll">
<include name="System.Data.dll">
<include name="System.Xml.dll">
<include name="Livedoor.dll">
<include name="LivedoorBatch.dll">
<include name="LivedoorServiceApiClient.dll">
<include name="MobileLivedoorApi.dll">
</include>
</include>
</include>

위와 같이 컴파일 한 경우,
실행하면

<target name="run" depends="build">
<exec program="${basename}.exe" basedir="${build.dir}">
</exec>

어떤 에러가 나오느냐 하면

C:\crowdy\LivedoorTest>bin\CDBAccountTest.exe

ハンドルされていない例外: System.IO.FileNotFoundException: ファイルまたはアセンブリ 'Hosting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。
ファイル名 'Hosting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' です。
場所 Test.CDBAccountTest.Main(String[] args)

警告: アセンブリ バインドのログ記録がオフにされています。
アセンブリ バインドのエラー ログを有効にするには、レジストリ値 [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) を 1 に設定してください。
注意: アセンブリ バインドのエラー ログに関連するパフォーマンス ペナルティがあります。
この機能をオフにするには、レジストリ値 [HKLM\Software\Microsoft\Fusion!EnableLog] を削除します。

와 같은 에러가 나온다.

나는 처음에 저렇게 레퍼런스를 주고 컴파일 하면, static library로 실행파일 안에 함께 Link될 줄 알았다.
이게 무슨 말이냐면, 어셈블리를 찾을 수 없다라는 얘기다.
마치 java에서 jar를 찾을 수 없다라는 얘기와 같다.
java에서 컴파일 할 때, 실행할 때, 모두 외부 라이브러리가 필요한 것처럼, 닷넷에서도 실행할 때 외부라이브러리(어셈블리)정보를 알아야 한다.
그런데 닷넷에서는 -classpath와 같은 옵션은 주지 않는다. 자체로 실행파일이기 때문에.

그렇다면 그 정보는 어디서 가져오나? (어떻게 줄 수 있나?)
바로 app.config를 이용한다.
이 app.config는 IDE에서 빌드하면 debug나 release디렉토리에 <타겟이름>.exe.config (dll 타입인 경우는 .exe.config)로 복사된다.
이 app.config를 이용하여 실행시 default parameter를 주는 것도 가능하고,

<configuration>
<appsettings>
<add key="OperatorName" value="Rita"></add>
<add key="LoggerLevel" value="5"></add>
</appsettings>
</configuration>

string name = System.Configuration.ConfigurationManager.AppSettings["OperatorName"];
Console.Writeline("Welcome " + name);
string level = System.Configuration.ConfigurationManager.AppSettings["LoggerLevel"];
Console.Writeline("Logger level: " + level);

참고로 전체에 영향을 주는 Machine.config파일도 있다.
The machine configuration file, Machine.config, contains settings that apply to an entire computer. This file is located in the %runtime install path%\Config directory. Machine.config contains configuration settings for machine-wide assembly binding, built-in remoting channels, and ASP.NET.
from http://msdn.microsoft.com/en-us/library/ms229697.aspx

또한 잔넹이지만, Nant는 컴파일 할 때 app.config파일을 알아서 복사해 주지 않는다.
수동으로 다음과 같이 하는 방법이 있다고 한다.
간단하게라면
<copy file="${Foo.src.dir}/app.config" tofile="${build.dir}/Foo.exe.config">
from http://kseek.blogspot.com/2005/04/rename-appconfig-to-fooexeconfig-in.html
로 끝나고,

좀 복잡한 프로젝트 라면 다음과 같이 하면 된다.
<foreach item="File" property="exefile">
<in>
<items>
<include name="${build.configuration}/*.exe">
</include>
</items>
<do>

<property name="basename" value="${path::get-file-name-without-extension(exefile)}">
<copy file="${basename}/App.config" tofile="${outputdir}/${basename}.exe.config">
</copy>
</property>
from http://d.hatena.ne.jp/Horiuchi_H/20060529/1148880306

닷넷 프레임웍의 Configuration File Scheme은 굉장히 복잡한데
from http://msdn.microsoft.com/en-us/library/1fk1t1t0.aspx

내가 필요로 하는 샘플은 이쪽 http://blogs.msdn.com/suzcook/archive/2004/05/14/132022.aspx 에 있었다.


<configuration>
<runtime>
<assemblybinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentassembly>
<assemblyidentity name="assemblyName" culture="" publickeytoken="8968ee41e78ce97a">
<codebase version="1.0.0.0" href="http://www.yourwebsite.com/filename.dll">
</codebase>
</assemblyidentity>
</dependentassembly>
</assemblybinding>
이 href부분을 “file:///c:/localfile/filename.dll“ 와 같이 정의하면 된다라고 한다.

또 이 샘플로 내가 필요로 하는 정보가 하나 더 있음을 알게 되었는데,
내 로컬머신에는 닷넷 프레임웍 1.1, 2.0, 3.5가 설치되어 있다.
어떤 버전의 프레임웍으로 실행해야 하는지 정의하는 것도 이 app.config파일에서 하는 것임을 알게 되었다.


<configuration>
<startup>
<requiredruntime version="v1.0.3705">
<supportedruntime version="v1.0.3705">
</supportedruntime>
</requiredruntime>

App.Config를 만드려면

To create App.Config:
1. From Project, select Add New Item…
2. Select "Application Configuration File", and click Add.

from http://blogs.msdn.com/andyhar/archive/2005/06/25/432691.aspx

또는

Right-click the project in the Solution Explorer and choose the Add->New Item... tab.
In the Add New Item window select the Application Configuration File.

from http://download.oracle.com/docs/cd/E13924_01/coh.340/e12192/netsampformapp.htm#BCEGGFDA

Windows WorkFlow의 App.conf를 세팅하려면 http://msdn.microsoft.com/en-us/library/ms734706.aspx

IDE가 아닌 Console App로 자동으로 app.config를 만드는 방법은 없을까?

이 파일은 XML 형식으로 되어 있는데, 이를 전부 외워서 설정하기에는 많은 어려움이 있다.
그래서 설정 툴을 사용하면 되는데, 엔터프라이즈가 설치된 폴더의 bin 폴더 아래에 보면 EntLibConfig.exe 파일이 있다.
바로 이 프로그램이 구성 설정 파일을 손쉽게 그래픽 기반으로 해주는 프로그램이다. 이 프로그램을 이용하면 해당 구성 파일을 손쉽게 편집할 수 있다.
from http://saga21.net/970?TSSESSION=42e9e1052d8b9bd855d134515955372d

위의 블로그에서 본 것이지만, Enterprize Library Configuration 이라는 유틸리티가 app.config파일을 만드는데 도움이 된다.
또 이 app.config의 값은 암호화해서 배포하는 것도 일반적인 것 같다.
java의 Apache Jakarta의 Common처럼 닷넷에서도 자주 쓰이는 라이브러리 기능을 모아서 발표하는 곳이 있었다.
msdn에 소개되어 있지만, Open project이다. 다운로드는 이쪽에서 받고 (글을 쓰는 현재 최신버전은 4.1버전)
http://www.microsoft.com/downloads/thankyou.aspx?familyId=1643758b-2986-47f7-b529-3e41584b6ce5&displayLang=en

하지만,
Microsoft.Practices.EnterpriseLibrary.Common.Configuration.SystemConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
과 같이 정의하는 PublicKeyToken은 뭘 넣어야 하는지 알 수 없다.
FrameWork을 설치하면 이것을 알아내는 유틸리티가 두개가 있다.
이 정보가 이 Post의 핵심.

sn -T MyAssemby.DLL
IlDasm is another utility. Both come with the FrameWork.

from http://www.eggheadcafe.com/conversation.aspx?messageid=32180871&threadid=32180864

p.s.>
sn -T MyAssemby.DLL 이건 emeditor에서 쉽게 만들도록 매크로로 만들어야겠다.

p.s.>
Nant에도 ildasm task가 있기는 하다.
http://nant.sourceforge.net/release/0.85/help/tasks/ildasm.html

p.s.>
또 MS에 Guidance Automation Tookit과
Guidance Automation Extension이 있다. 뭐하는 건지는 따로 나중에 조사해야겠다.

No comments: