nie*_*ras 9 c# msbuild wpf xaml visual-studio-2012
为了将项目设置合并到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>
Run Code Online (Sandbox Code Playgroud)
此属性表将所有构建输出移动到单独的位置OutputRelativePath(在单独的属性表中定义或直接在项目文件中定义)外部目录,其中包含源代码以便于清理等.但是,在设置完成后,构建工作正常并且所有单元测试工作正常,很明显WPF可执行项目并不好,因为使用上面的属性表运行应用程序导致臭名昭着:
IOException was unhandled "Cannot locate resource 'app.xaml'."
Run Code Online (Sandbox Code Playgroud)
为什么更改输出路径会导致此错误?如何确定原因是项目构建输出路径?这可以在生成的代码中看到吗?我找不到?这不是一个错误吗?
注意:使用以下属性表工作,但仅当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>
Run Code Online (Sandbox Code Playgroud)
所以看来,不知何故,输出路径包含AssemblyName属性或类似属性.
在另一个组件中更新XAML样式:如果这些(例如Brushes.xaml)位于另一个程序集中并且此程序集也更改了OutputPath,则同样适用于xaml ResourceDictionary,这也会引发异常:
XamlParseException was unhandled for set property Source
with InnerException "Cannot locate resource 'Brushes.xaml'"
Run Code Online (Sandbox Code Playgroud)
总而言之,输出位置会改变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>
Run Code Online (Sandbox Code Playgroud)
删除OutputPath其余PropertyGroup中的属性,例如
<OutputPath>bin\Debug\</OutputPath>
Run Code Online (Sandbox Code Playgroud)
和:
<OutputPath>bin\Release\</OutputPath>
Run Code Online (Sandbox Code Playgroud)
这应该是一个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
}
Run Code Online (Sandbox Code Playgroud)
可以看到ildasm.exe并打开MANIFEST组件.还可以看出,正常资源也会以输出路径为前缀获取错误的名称.但是,可以通过LogicalName在此资源的项目文件中设置来修复此问题(请参阅使用MSBuild构建后运行测试时的MissingManifestResourceException(.mresource在清单中有路径)).这似乎不适用于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>
Run Code Online (Sandbox Code Playgroud)
我觉得这很奇怪......任何洞察为什么会是这种情况或者如果这确实是真的,我们将不胜感激.需要注意的是,C++ IntDir和OutDir而必须有一个斜杠,否则你将得到这个警告.
将 MSBuild 输出详细程度设置为“诊断”很快就揭示了问题的根源:
1> (TaskId:21)
1> Microsoft (R) Build Task 'ResourcesGenerator' Version '4.0.30319.33440 built by: FX45W81RTMREL'. (TaskId:21)
1> Copyright (C) Microsoft Corporation 2005. All rights reserved. (TaskId:21)
1>
1> (TaskId:21)
1> Generating .resources file: '..\Build/Obj_Exe/WpfApplication8_AnyCPU_Debug/WpfApplication8.g.resources'... (TaskId:21)
1> Reading Resource file: 'C:\Users\hpass_000\Projects\Build\Obj_Exe\WpfApplication8_AnyCPU_Debug\MainWindow.baml'... (TaskId:21)
1> Resource ID is 'mainwindow.baml'. (TaskId:21)
1> Generated .resources file: '..\Build/Obj_Exe/WpfApplication8_AnyCPU_Debug/WpfApplication8.g.resources'.
Run Code Online (Sandbox Code Playgroud)
请注意路径名称中正斜杠和反斜杠的混合。Windows 本身知道如何很好地处理路径名中的正斜杠。但其他软件通常缺乏这种能力,资源生成器任务也缺乏这种能力。这需要一个真正的反斜杠作为路径分隔符,正斜杠在资源名称中有效。使固定:
<OutputPath>$(OutputRelativePath)\$(AssemblyName)_$(Platform)_$(Configuration)\</OutputPath>
<BaseIntermediateOutputPath>$(OutputRelativePath)\Obj_Exe\$(AssemblyName)_$(Platform)</BaseIntermediateOutputPath>
<IntermediateOutputPath>$(BaseIntermediateOutputPath)_$(Configuration)\</IntermediateOutputPath>
Run Code Online (Sandbox Code Playgroud)
换句话说,我只是替换/为\. 这解决了问题。
| 归档时间: |
|
| 查看次数: |
1968 次 |
| 最近记录: |