プロジェクト設定を C++ プロジェクトと C# プロジェクトの両方のプロパティ シートに統合するために、次のプロパティ シートが作成されました。
<?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 スタイルの更新: これら (Brushes.xaml など) が別のアセンブリにあり、このアセンブリが OutputPath も変更した場合、xaml ResourceDictionary にも同じことが適用されます。これも例外をスローします。
XamlParseException was unhandled for set property Source
with InnerException "Cannot locate resource 'Brushes.xaml'"
全体として、出力場所が xaml リソース名を変更するように見えるため、これらは実行時に何らかの方法で検出できません。奇妙なことに、設計時には問題はありません...
更新: 例外を再現するための最小限の手順:
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>
OutputPath
残りの PropertyGroups のプロパティを 削除します。
<OutputPath>bin\Debug\</OutputPath>
と:
<OutputPath>bin\Release\</OutputPath>
IOException
これにより、 on start for がスローされ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
ただし、これは、このリソースのプロジェクト ファイルで を設定することで修正できます ( MSBuild でビルドした後にテストを実行する場合の MissingManifestResourceException を参照してください (.mresource has path in manifest) )。これは、xaml リソースでは可能ではないようです...
and/
の最後で使用していることに気付いた構成を調べたところ、これらを削除すると機能しているように見えます。以下を参照してください。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
代わりにバックスラッシュを末尾に付ける必要があることに注意してください。そうしないと、これに関する警告が表示されます。