.Net core 시리즈부터는 App.config 파일을 지원하지 않는다고 하네요.ConfigurationBuilder를 활용해서 값을 쓰고 읽을 순 있으나 runtime 명령어가 먹히진 않는 듯 합니다.
참고로 전 .NET 6에 WPF 프로젝트입니다.
그래도 어찌어찌 방법을 찾아서 해결한 방법 공유드립니다. 저도 이번에 찾아보면서 여러가지 알게 되었습니다. 우선 빌드한 곳에 가면 AppName.deps.json과AppName.runtimesconfig.json 2개 파일이 자동으로 생성이 되고 App에서 실행 될 때 필요한 설정이나 참조들을 해당 파일에서 읽어와 실행합니다.
결과적으로 제가 원했던거는 AppName.exe이 참조하는 resource dll 들을 특정 폴더 ex)Libs에 넣고 싶었던거고 이를 위해서는 몇가지 순서가 있습니다.
- dll들을 Copy할 Destination 경로를 파악하기 위해 deps.josn 파일을 열어 확인
- MSBuild를 사용하여 빌드 완료 후 dll들을 특정폴더에 Move or Copy하는 스크립트 작성
- runtimesconfig.json 파일에서 additionalProbingPaths 로 root 경로 지정
위 방법 말고 찾은 방법 몇가지도 소개해드립니다. (테스트 해보진 않음)
NetBeauty2 (종속성 dll들을 하위디렉토리에 알아서 정리해주는 tool)
AssemblyLoadContext (동적 로드를 위한 Context)
MSBuild를 이용한 자세한 방법은 예시로 설명드립니다.
먼저 deps.json 내에서 dll 경로 확인합니다.
[AppName.deps.json]
"targets": {
".NETCoreApp,Version=v6.0": {},
".NETCoreApp,Version=v6.0/win-x64": {
"AppName/1.1.0": {
"dependencies": {
"CommunityToolkit.Mvvm": "8.0.0",
},
"runtime": {
"AppName.dll": {}
},
"resources": {
"en/AppName.resources.dll": {
"locale": "en"
},
"ko-KR/AppName.resources.dll": {
"locale": "ko-KR"
}
}
},
"CommunityToolkit.Mvvm/8.0.0": {
"runtime": {
"lib/net6.0/CommunityToolkit.Mvvm.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.0.1"
}
}
},
runtime상 App에서 dll을 참조하는 경로를 deps.json 에서 찾기 때문인데요. 문제는 deps.json 안에있는 경로를 빌드 전 수정할수 없다는 것이고 그래서 2번에서 Copy할 때 경로를 참고해야합니다. (deps.json 내 dll 경로를 수정하는 방법도 있지만 그러면 빌드 할 때마다 바꿔줘야 합니다…)
참고할 dll 경로 (dll Name + runtime 섹션에 있는 dll경로까지가 최종 경로)
AppName/1.1.0/en/AppName.resources.dll
AppName/1.1.0/ko-KR/AppName.resources.dll
CommunityToolkit.Mvvm/8.0.0/lib/net6.0/CommunityToolkit.Mvvm.dll
그리고 이를 토대로 프로젝트 파일을 편집합니다.(.csproj)
Libs 폴더에다가 모두 Copy합니다.
<Project Sdk="Microsoft.NET.Sdk">
<!-- 빌드 시 Copy -->
<Target Name="CreateBuildLibs" AfterTargets="Build">
<Message Importance="high" Text="Build directory = $(TargetDir)" />
<Message Importance="high" Text="Publish directory = $(PublishDir)" />
<MakeDir Directories="$(TargetDir)Libs" Condition="!Exists('$(TargetDir)Libs')" />
</Target>
<Target Name="MoveDlls" AfterTargets="CreateBuildLibs">
<Copy SourceFiles="$(TargetDir)CommunityToolkit.Mvvm.dll" DestinationFolder="$(TargetDir)Libs\CommunityToolkit.Mvvm\8.0.0\lib\net6.0" SkipUnchangedFiles="true" />
</Target>
<Target Name="MoveResourceDlls" AfterTargets="CreateBuildLibs">
<Copy SourceFiles="$(TargetDir)en\AppName.resources.dll" DestinationFolder="$(TargetDir)Libs\AppName\1.1.0\en" SkipUnchangedFiles="true" />
<Copy SourceFiles="$(TargetDir)ko-KR\AppName.resources.dll" DestinationFolder="$(TargetDir)Libs\AppName\1.1.0\ko-KR" SkipUnchangedFiles="true" />
</Target>
<!-- 배포 시 Copy -->
<Target Name="CreatePublishLibs" AfterTargets="Publish">
<MakeDir Directories="$(PublishDir)Libs" Condition="!Exists('$(PublishDir)Libs')" />
</Target>
<Target Name="MovePublishDlls" AfterTargets="CreatePublishLibs">
<Copy SourceFiles="$(TargetDir)CommunityToolkit.Mvvm.dll" DestinationFolder="$(PublishDir)Libs\CommunityToolkit.Mvvm\8.0.0\lib\net6.0" SkipUnchangedFiles="true" />
</Target>
<Target Name="MovePublishResourceDlls" AfterTargets="CreatePublishLibs">
<Copy SourceFiles="$(TargetDir)en\AppName.resources.dll" DestinationFolder="$(PublishDir)Libs\AppName\1.1.0\en" SkipUnchangedFiles="true" />
<Copy SourceFiles="$(TargetDir)ko-KR\AppName.resources.dll" DestinationFolder="$(PublishDir)Libs\AppName\1.1.0\ko-KR" SkipUnchangedFiles="true" />
</Target>
여기까지 하고 빌드하면 Libs 경로에 지정한 DestinationFolder로 dll들이 모두 copy된걸 확인 할 수 있습니다.
그리고 AppName.runtimesconfig.json 을 수정해서 Libs 폴더를 root로 보게 해서 deps.json 이 dll 을 잘 찾아가도록 해야합니다.
[AppName.runtimesconfig.json]
{
"runtimeOptions": {
"tfm": "net6.0",
"frameworks": [
{
"name": "Microsoft.NETCore.App",
"version": "6.0.0"
},
{
"name": "Microsoft.WindowsDesktop.App",
"version": "6.0.0"
}
],
"additionalProbingPaths": [
"Libs"
]
}
}
runtimeOptions 내에 additionalProbingPaths 을 추가하여 "Libs"폴더를 보도록 지정합니다.
다만, 이렇게 되면 빌드 할때마다 runtimesconfig.json 을 열어서 수정해줘야 하니 template 파일을 만들어 option을 추가할 수 있습니다.
.csproj가 있는 동일 경로에 runtimeconfig.template.json 파일을 추가합니다.
[runtimeconfig.template.json]
{
"additionalProbingPaths": [
"Libs"
]
}
그리고 빌드하게 되면 알아서 runtimeconfig.template.json 을 읽어서 빌드된 경로에 있는 AppName.runtimesconfig.json 에 runtimeOptions 안에 반영합니다.
일단 과정이 길었는데요… 이렇게 까지 해놓고 .csproj 에서 옮길 dll들 경로만 잘 지정해주면 크게 건드리지 않아도 될 것 같습니다.
하다보니 몇가지 단점이 있긴 합니다. (버전에 따른 경로문제, 하위 디렉토리를 변경할 수 없는 문제 등)
그래도 최소한 언어 resource dll을 한곳에 몰아놓고자 하는 목적은 달성했으니 만족하겠습니다 ㅎㅎ
혹시라도 잘못된 정보를 전달하면 어쩌나 해서 다시 테스트도 해보고 출처들도 다시 찾아보고 했네요.
아래는 제가 참고한 출처 및 사이트들입니다.
주요 내용 포함된 Stackoverflow
runtimeconfig.json MS 공식
runtimeconfig.json schema
runtimeconfig.json example
정령 이게 최선인가에 대한 토론
이외에 찾다보니 AssemblySearchPaths 라는 녀석도 알게되어 소개해드립니다.
프로젝트가 참조하는 dll을 지정된 경로로 설정할 수 있는것 같습니다.
프로젝트 참조 dll 설정
누군가에겐 도움이 되었으면 하네요.