在試圖鞏固項目設置成用於C++和C#項目屬性表,以下屬性表構建:爲什麼修改項目輸出目錄會導致:IOException未處理「無法找到資源'app.xaml'。」
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
Trying to support both C++ and C# projects by introducing derived
properties and setting the appropriate output properties.
-->
<PropertyGroup Label="UserMacros">
<ProjectOrAssemblyName Condition="'$(AssemblyName)'==''">$(ProjectName)</ProjectOrAssemblyName>
<ProjectOrAssemblyName Condition="'$(ProjectName)'==''">$(AssemblyName)</ProjectOrAssemblyName>
<ShortPlatform Condition="'$(Platform)'=='Win32'">x86</ShortPlatform>
<ShortPlatform Condition="'$(Platform)'=='x86'">x86</ShortPlatform>
<ShortPlatform Condition="'$(Platform)'=='x64'">x64</ShortPlatform>
<ShortPlatform Condition="'$(Platform)'=='AnyCPU'">AnyCPU</ShortPlatform>
</PropertyGroup>
<PropertyGroup>
<OutputPath>$(OutputRelativePath)/$(ProjectOrAssemblyName)_$(ShortPlatform)_$(Configuration)/</OutputPath>
<BaseIntermediateOutputPath>$(OutputRelativePath)/Obj_Exe/$(ProjectOrAssemblyName)_$(ShortPlatform)</BaseIntermediateOutputPath>
<IntermediateOutputPath>$(BaseIntermediateOutputPath)_$(Configuration)/</IntermediateOutputPath>
<IntDir>$(IntermediateOutputPath)</IntDir>
<OutDir>$(OutputPath)</OutDir>
</PropertyGroup>
</Project>
該屬性表將移動所有輸出建立一個單獨的地點OutputRelativePath(定義在單獨的屬性表中或直接在項目文件中)包含源代碼的目錄之外,以便於清理等。但是,設置完成並且構建工作正常並且所有單元測試都正常工作後,顯然WPF可執行項目並不好,因爲使用以上屬性表運行應用程序導致臭名昭着:
IOException was unhandled "Cannot locate resource 'app.xaml'."
爲什麼更改輸出路徑會導致此錯誤?如何確定原因是項目構建輸出路徑?這可以在生成的代碼中看到嗎?我找不到?這不是一個錯誤?
注:使用下面的屬性表的作品,但只有當IntermediateOutputPath包含BaseIntermediateOutputPath。
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OutputPath>$(OutputRelativePath)/$(AssemblyName)_$(Platform)_$(Configuration)</OutputPath>
<BaseIntermediateOutputPath>$(OutputRelativePath)/Obj_Exe/$(AssemblyName)_$(Platform)</BaseIntermediateOutputPath>
<IntermediateOutputPath>$(BaseIntermediateOutputPath)_$(Configuration)</IntermediateOutputPath>
</PropertyGroup>
</Project>
因此,看起來,預計輸出路徑包含AssemblyName屬性或類似。
XAML樣式在另一個彙編中的更新:這同樣適用於xaml ResourceDictionary,如果這些是 - 例如Brushes.xaml - 位於另一個組件,該組合已經改變了OutputPath也,這也將引發異常:
XamlParseException was unhandled for set property Source
with InnerException "Cannot locate resource 'Brushes.xaml'"
因此,所有的一切似乎輸出位置改變XAML資源名稱,以便這些不能被發現不知何故,運行時。奇怪的是它是不是在設計時的一個問題...
UPDATE:最少的步驟重現例外:
打開Visual Studio 2013
創建新的C#項目WPF應用程序如XamlIntermediateOutputPathBug
卸載項目
編輯項目文件
第一的PropertyGroup後插入新的PropertyGroup爲:
<PropertyGroup>
<OutputRelativePath>$(ProjectDir)..\Build</OutputRelativePath>
<OutputPath>$(OutputRelativePath)/$(AssemblyName)_$(Platform)_$(Configuration)/</OutputPath>
<BaseIntermediateOutputPath>$(OutputRelativePath)/Obj_Exe/$(AssemblyName)_$(Platform)</BaseIntermediateOutputPath>
<IntermediateOutputPath>$(BaseIntermediateOutputPath)_$(Configuration)/</IntermediateOutputPath>
<IntDir>$(IntermediateOutputPath)</IntDir>
<OutDir>$(OutputPath)</OutDir>
</PropertyGroup>
在例如剩餘PropertyGroups刪除OutputPath
性質
<OutputPath>bin\Debug\</OutputPath>
和:
<OutputPath>bin\Release\</OutputPath>
這應該再扔上啓動IOException
爲mainwindow.xaml
。這是由於$(AssemblyName).g.resources
嵌入資源給出以下名稱:
.mresource public 'Build/Obj_Exe/XamlIntermediateOutputPathBug_AnyCPU_Debug/XamlIntermediateOutputPathBug.g.resources' as Build_Obj_Exe_XamlIntermediateOutputPathBug_AnyCPU_Debug_XamlIntermediateOutputPathBug.g.resources
{
// Offset: 0x00000000 Length: 0x000003BC
}
.mresource public 'Build/Obj_Exe/XamlIntermediateOutputPathBug_AnyCPU_Debug/XamlIntermediateOutputPathBug.Properties.Resources.resources' as Build_Obj_Exe_XamlIntermediateOutputPathBug_AnyCPU_Debug_XamlIntermediateOutputPathBug.Properties.Resources.resources
{
// Offset: 0x000003C0 Length: 0x000000B4
}
如可以用ildasm.exe
可以看出,爲裝配打開MANIFEST
。正如也可以看到的那樣,普通資源的輸出路徑前綴也是錯誤的。但是,可以通過在此資源的項目文件中設置LogicalName
來解決此問題(請參閱MissingManifestResourceException when running tests after building with MSBuild (.mresource has path in manifest))。這似乎並不可能爲XAML資源...
說完看着我發現我使用/
在OutputPath
和IntermediateOutputPath
的端的配置,除去這些似乎工作,見下圖:
<PropertyGroup>
<OutputRelativePath>$(ProjectDir)..\Build</OutputRelativePath>
<OutputPath>$(OutputRelativePath)/$(AssemblyName)_$(Platform)_$(Configuration)</OutputPath>
<BaseIntermediateOutputPath>$(OutputRelativePath)/Obj_Exe/$(AssemblyName)_$(Platform)</BaseIntermediateOutputPath>
<IntermediateOutputPath>$(BaseIntermediateOutputPath)_$(Configuration)</IntermediateOutputPath>
<IntDir>$(IntermediateOutputPath)/</IntDir>
<OutDir>$(OutputPath)/</OutDir>
</PropertyGroup>
我覺得這很奇怪......任何洞察,爲什麼這將是這種情況,或者如果這是事實真的讚賞。請注意,C++ IntDir
和OutDir
必須具有尾部反斜槓,否則您將收到有關此問題的警告。
您可以使用設置爲診斷的日誌記錄進行構建,以查看是否在IOException和XamlParseException發生時獲取更多信息? – Nicodemeus