Chris Caulfield
Chris Caulfield

Reputation: 455

How to deploy Content generated in a Target to AppX package in a UWP app with MSBuild

I have a C# XAML UWP project created in Visual Studio 2017 and I have some assets that I want to convert and have deployed to the AppX package. However, I am unable to get my converted assets deployed without directly adding them to the AppXPackagePayload.

I have created a simplified test case with a vanilla C# XAML App and a couple text files in a RawData folder. I want the text files converted (copied for now) and deployed to the Data folder in my AppX.

I added the following to my csproj right before the import of the Xaml.CSharp.targets (I added the ConvertedData item type just for debugging):

<ItemGroup>
    <RawData Include="RawData\**\*.*" />
</ItemGroup>
<Target Name="ConvertData" BeforeTargets="Compile" Inputs="@(RawData)" Outputs="Data\%(RawData.RecursiveDir)%(RawData.Filename)%(RawData.Extension)">
  <ItemGroup>
    <ConvertedData Include="Data\%(RawData.RecursiveDir)%(RawData.Filename)%(RawData.Extension)" />
    <Content Include="Data\%(RawData.RecursiveDir)%(RawData.Filename)%(RawData.Extension)" />
  </ItemGroup>
  <Message Importance="high" Text="Creating Data: @(RawData) -> Data\%(RawData.RecursiveDir)%(RawData.Filename)%(RawData.Extension)" />
  <Copy SourceFiles="%(RawData.Identity)" DestinationFiles="Data\%(RawData.RecursiveDir)%(RawData.Filename)%(RawData.Extension)" />
</Target>
<Target Name="DisplayContent" AfterTargets="ConvertData" BeforeTargets="Compile">
  <Message Importance="high" Text="RawData: @(RawData)" />
  <Message Importance="high" Text="ConvertedData: @(ConvertedData)" />
  <Message Importance="high" Text="Content: @(Content)" />
</Target>

The log output when building is this:

1>  Creating Data: RawData\Hello.txt -> Data\Hello.txt
1>  Creating Data: RawData\World.txt -> Data\World.txt
1>  RawData: RawData\Hello.txt;RawData\World.txt
1>  ConvertedData: Data\Hello.txt;Data\World.txt
1>  Content: Properties\Default.rd.xml;Assets\LockScreenLogo.scale-200.png;Assets\SplashScreen.scale-200.png;Assets\Square150x150Logo.scale-200.png;Assets\Square44x44Logo.scale-200.png;Assets\Square44x44Logo.targetsize-24_altform-unplated.png;Assets\StoreLogo.png;Assets\Wide310x150Logo.scale-200.png;Data\Hello.txt;Data\World.txt

Which is as expected. I now have a Data folder in my project folder containing my "converted" text files. However, the files in the Data folder never make it to the AppX folder when the app is deployed even though they are listed as Content. All the other assets that were not generated in a Target do get deployed. It seems as if Content items created in a Target do not get added to the AppXPackagePayload.

If I add the following to the Target's ItemGroup:

<AppxPackagePayload Include="Data\%(RawData.RecursiveDir)%(RawData.Filename)%(RawData.Extension)">
  <TargetPath>Data\%(RawData.RecursiveDir)%(RawData.Filename)%(RawData.Extension)</TargetPath>
</AppxPackagePayload>

Then the items in the Data folder get deployed to the AppX. However, I feel that just adding my items to Content in the Target should be enough to get them deployed. Am I doing something wrong?

Thanks!

Upvotes: 0

Views: 826

Answers (2)

Srdjan Jovcic
Srdjan Jovcic

Reputation: 773

Processing of Content items happens before compilation, so you should replace

BeforeTargets="Compile"

with

BeforeTargets="AssignTargetPaths"

That should do the trick.

Upvotes: 1

Chris Caulfield
Chris Caulfield

Reputation: 455

I have a working solution now which avoids the Target-generated Content items, as well as the explicit AppXPackagePayload. This works because I have a one-to-one mapping between my RawData and Data files so I can put all Content items outside the Target. It doesn't answer why Target-generated Content items do not deploy (and I'd still like to know why that's the case if anyone knows), but it does solve my problem in a clean way, so could be useful to others:

<ItemGroup>
    <RawData Include="RawData\**\*.*">
      <Visible>True</Visible>
    </RawData>
</ItemGroup>
<ItemGroup>
    <Content Include="@(RawData-> 'Data\%(RecursiveDir)%(Filename)%(Extension)')">
      <Visible>True</Visible>
    </Content>
</ItemGroup>
<Target Name="ConvertData" BeforeTargets="Compile" Inputs="@(RawData)" Outputs="Data\%(RawData.RecursiveDir)%(RawData.Filename)%(RawData.Extension)">
  <Copy SourceFiles="%(RawData.Identity)" DestinationFiles="Data\%(RawData.RecursiveDir)%(RawData.Filename)%(RawData.Extension)" />
</Target>

Now my Data files are created in my project folder, and correctly deployed to the AppX folder.

Upvotes: 0

Related Questions