UWP .appx file naming - windows

I am building an UWP app and I want to have generated package to be named with the build number in order to distinguish the builds.
So far, I have this configuration in the csproj file:
<Target Name="BeforeBuild">
<Message Text="Updating AssemblyInfo to Version $(VersionNumber)"></Message>
<Message Text="Writing to AssemblyInfo files in $(SolutionRoot)"></Message>
<AssemblyInfo CodeLanguage="CS"
AssemblyCompany="Company"
AssemblyProduct="Product"
AssemblyCopyright="Copyright © Company 2011"
ComVisible="true"
AssemblyVersion="$(BUILD_NUMBER)"
AssemblyFileVersion="$(BUILD_NUMBER)" />
</Target>
All good, I can run the msbuild with the /p:BUILD_NUMBER=1.2.3.4 argument, but this is only reflecting in AssemblyInfo.cs file.
The .appx file will be named as MyApplication.Core_1.0.0.0_x86_Test.appx and not MyApplication.Core_1.2.3.4_x86_Test.appx
How can I use the BUILD_NUMBER information to be reflected in the .appx file name?

The version number in .appx file name is not set by AssemblyInfo. This version number is called Package version number which is set as a value in the Version attribute of the Package/Identity element in the app manifest like:
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
<Identity Name="e12578ad-9b81-44bb-8651-0b58e44e71b8" Publisher="CN=Jay Zuo" Version="1.2.3.0" />
...
</Package>
Once you changed the Version attribute and then run MSBuild, you will get the .appx file named like MyUWPApp_1.2.3.0_x86.appx.
Besides this, we usually change the package version number while creating an app package. This can be done with Microsoft Visual Studio wizard like following:
(source: s-msft.com)

Related

NuGet to copy files into the project directory

I've created a .nuspec file which packages a bunch of .proto files for sharing between projects. This is great. Unfortunately, for the .proto files to be built, they need to be actually copied over to the project directory, not just referenced. Note that this is a .NET Core project.
Right now my definition creates a package that, when used, references the files in the project, but these files still reside in the original .Nuget folder, and that's not really what I need.
Here's the .nuspec definition that I've got right now:
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>GRPCProtoFiles</id>
<version>1.0.0</version>
<authors>Author</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>.proto files NuGet package.</description>
<dependencies>
<dependency id="Google.Protobuf" version="3.14.0"/>
<dependency id="Grpc" version="2.35.0"/>
</dependencies>
<contentFiles>
<files include="any/any/Protos/**/*.proto" buildAction="None" copyToOutput="false" />
</contentFiles>
</metadata>
<files>
<file src="**\*.proto" target="contentFiles\any\any\Protos" exclude="google\**" />
</files>
</package>
I know that "build action" is currently set to "none", but I can get that fixed once the files land in the correct folder upon package installation. As is, if I try to set the build action for the proto files to the correct one (which is Protobuf Compiler) then I get an error, because the files aren't where they're supposed to be.
What am I doing wrong?
EDIT:
OK, I've read up a bit on what might be happening and why. Specifically this answer gave me a lot of insight. However I'm left wondering how I can actually do what I need to do. Right now it seems that what I want to do is impossible with NuGet and I'm using the wrong tool for the job. But besides this one limitation NuGet seems ideal - it's able to pick just the .proto files from the source project and just publish that rather then pre-built libraries for various target systems.
I could, possibly, add a pre-build action to copy the files to the project dir, but I've no idea how to reference the source NuGet package folder (especially if the version changes). Any idea if this problem even has a solution?
I really know your ideas. First, make these proto files be packed into nupkg with Build Action None. And then use pre-build event under the main project to handle the files from the nupkg. The question is that how to use msbuild property to get files from nupkg since Net Core projects use Link properties to references the files under the main project rather than copy the real nuget files into the main project folder.
And under the Link properties, you could not change the Build Action of that file because it actually does not exist under the main project folder and the main project has no duty to handle the file.
There are two functions to solve it:
=============================================
Function one
You could did this directly under nupkg itself and after that, the proto files will be copied automatically during build process with the nuget package. Try the following steps and you should not add any copy task from another main project which install the nuget package.
You have to use <packages_id>.props/targets file into nupkg to get what you want. Refer to this official document.
1) create a file called <packages_id>.props file. In your side, it should be named as GRPCProtoFiles.props so that it will work.
2) add these on the GRPCProtoFiles.props file:
<Project>
<Target Name="CopyFiles" BeforeTargets="Build">
<ItemGroup>
<File Include="$(MSBuildThisFileDirectory)..\contentFiles\**\*.*"></File>
</ItemGroup>
<Copy SourceFiles="#(File)" DestinationFolder="$(ProjectDir)\Protos"></Copy>
</Target>
</Project>
3) add these on the GRPCProtoFiles.nuspec file to include the props file into nupkg:
<file src="build\*.props" target="build" />
The whole GRPCProtoFiles.nuspec file should be like this:
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>GRPCProtoFiles</id>
<version>1.0.0</version>
<authors>Author</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>.proto files NuGet package.</description>
<dependencies>
<dependency id="Google.Protobuf" version="3.14.0"/>
<dependency id="Grpc" version="2.35.0"/>
</dependencies>
<contentFiles>
<files include="any/any/Protos/**/*.proto" buildAction="None" copyToOutput="false" />
</contentFiles>
</metadata>
<files>
<file src="xxx.proto" target="contentFiles\any\any\Protos" exclude="google\**" />
<file src="build\*.props" target="build" />
</files>
</package>
4) then re-pack the new version of nuget project. Before you install the new release version, please clean nuget caches first or just delete all files under C:\Users\xxx\.nuget\packages
After the installation of the nuget package, please click Build button to execute the target.
More similar to this issue.
====================================================
Function Two
You could not do any internal steps for nupkg itself. You could directly copy the file from the external main project.
1) do not do any steps under Function One for your nuget package. Use your old nuget package.
Modify the Project A's csproj file which has installed GRPCProtoFiles nuget package.
Add <GeneratePathProperty>true</GeneratePathProperty> for PackageReference GRPCProtoFiles to generate an exclusive property as $(PkgGRPCProtoFiles) to get the path of the nupkg's content.
The whole is like this:
<ItemGroup>
<PackageReference Include="GRPCProtoFiles" Version="1.0.0">
<GeneratePathProperty>true</GeneratePathProperty>
</PackageReference>
</ItemGroup>
Then, right-click on the Project A-->Properties-->Build Events-->add these under Pre-build event Command Line:
xcopy /s /e /y /i $(PkgGRPCProtoFiles)\contentFiles\any\any\Protos $(ProjectDir)\Protos
Or, add this target into ProjectA.csproj file:
<Target Name="CopyFiles" BeforeTargets="PrepareForBuild">
<ItemGroup>
<File Include="$(PkgGRPCProtoFiles)\contentFiles\**\*.*"></File>
</ItemGroup>
<Copy SourceFiles="#(File)" DestinationFolder="$(ProjectDir)\Protos"></Copy>
</Target>

How to retrieve AssemblyVersionAttribute in MSBuild script

When trying to retrieve the [assembly: AssemblyVersion("1.2.3.4")] present in AssemblyInfo.cs file from a custom MSBuild script, I always get $(Version) value 1.0.0.0 instead of the value written in the file.
Can somebody tell me how to fix this issue? Unfortunately, other entries I have found so far, didn't point me to the right direction.
Actually, you just want to get the assembly dll version by MSBuild rather the nuget package version.
$(Version) is the value of the nuget package version after you pack the lib project. See this official document.
If you want to get the internal assembly dll version, it can be a bit complex but it can be done with some MSBuild tasks.
Use this:
<Target Name="RetrieveIdentities" BeforeTargets="Build">
<GetAssemblyIdentity
AssemblyFiles="$(TargetPath)">
<Output
TaskParameter="Assemblies"
ItemName="MyAssemblyIdentities"/>
</GetAssemblyIdentity>
<Message Text="Version: %(MyAssemblyIdentities.Version)"/>
</Target>
And %(MyAssemblyIdentities.Version) is the value of the AssemblyVersion.

Can I automatically set the AssemblyVersion in a Visual Studio proj file prior to a build?

Can I write a script that reads a text file and writes a value to the proj file of my app in Visual Studio prior to a Build?
Specifically before a build I'd like to read a value from a simple text file in my solution and write it to the AssemblyVersion in the .csproj folder.
1.0.2.0
Reading a version from the file could perform via ReadLinesFromFile built-in task.
.NET Framework:
When a version has been got it's need to pass it to the custom target:
<Target Name="EntryVersion" BeforeTargets="Build">
<Message Text="-----Entry-----" Importance="high"/>
<Message Text=" Write Version " Importance="high"/>
<Message Text="-----Entry-----" Importance="high"/>
<ItemGroup>
<Assembly Include="AssemblyProduct"><_Parameter1>$(Product)</_Parameter1></Assembly>
<Assembly Include="AssemblyCompany"><_Parameter1>$(Company)</_Parameter1></Assembly>
<Assembly Include="AssemblyVersion"><_Parameter1>$(Version)</_Parameter1></Assembly>
</ItemGroup>
<WriteCodeFragment AssemblyAttributes="#(Assembly)" Language="C#" OutputFile="..\GlobalAssemblyInfo.cs"/>
</Target>
This snippet generates the source file that will contain the assembly attributes. Besides, the output file must be included in the projects as a link, the used attributes must be removed from AssemblyInfo.
.NET Core | Standard:
It's possible to use native property Version from MSBuild CLI or override it from the custom target. The value is automatically will be added to the assembly attribute.
If you use ApplicationVersion from Microsoft.Extensions.PlatformAbstractions, then see Issue 237.
ReadLinesFromFile | WriteCodeFragment | Exec

Update Xml File (vsixmanifest)

I'm creating a Visual Studio 2013 Package (vsix) (shameless plug: pMixins ). As part of my quest to use TeamCity as a continuous integration server, I have configured Team City to build the .vsix Package (Visual Studio Package (vsix) - Team City without Visual Studio installed).
Now I want to configure Team City to set the Version in the VSIX Schema:
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest
Version="2.0.0"
xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011"
xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
<Identity Version="1.0" Language="en-US" Publisher="Company" />
Following the advice in Using msbuild I want to update a config file with values from teamcity and How do I update an XML attribute from an MSBuild script? I have updated Microsoft.VsSDK.targets to use XmlPoke with the following Target:
<Target
Name="UpdateVSIXVersion"
BeforeTargets="PrepareForBuild"
Condition="$(VSIXVersion) != '' And $(VSIXVersion) != '*Undefined*'">
<Message Text= "Updating VSIX Version" />
<XmlPoke
XmlInputPath="source.extension.vsixmanifest"
Query="/PackageManifest/Metadata/Identity/#Version"
Value="$(VSIXVersion)">
</XmlPoke>
</Target>
I updated Team City with a system Parameter to set VSIXVersion:
But, when I check TeamCity, it made 0 replacements:
How do I get Team City to correctly update the .vsixmanifest xml?
After much searching I finally found the XmlPoke expects a namespace when the Xml file contains a namespace, even for the default namespace (Modifying .config File in an MSBuild Project).
However, I couldn't find any documentation for the XmlPoke.Namespaces parameter and the above referenced code didn't work. After much trial an error, I finally got it to work with this:
<Target
Name="UpdateVSIXVersion"
BeforeTargets="PrepareForBuild"
Condition="$(VSIXVersion) != '' And $(VSIXVersion) != '*Undefined*'">
<Message Text= "Updating VSIX Version" />
<XmlPoke
XmlInputPath="source.extension.vsixmanifest"
Query="/n:PackageManifest/n:Metadata/n:Identity/#Version"
Value="$(VSIXVersion)"
Namespaces="<Namespace Prefix='n' Uri='http://schemas.microsoft.com/developer/vsx-schema/2011' Name='DoNotKnowWhatThisIsFor-ButItIsRequired' />">
</XmlPoke>
Notes:
This requires MSBuild 12 to be configured on Team City
The Namespaces needs to be escaped.
The Name parameter is required, otherwise MSBuild will error out
The original XPath query had to be updated with the artificial namespace prefix.
MSBuild file is on Github if anyone needs it: https://github.com/ppittle/pMixins/blob/master/tools/vssdk_tools/v12.0/VSSDK/Microsoft.VsSDK.targets

Is there an MSBuild macro for the SharePoint project type package name?

I have a Visual Studio 2010/2012 solution with several SharePoint 2010 projects. On build or package event I want VS to auto-copy the output WSP and PDB files to a common folder at the root of my solution so I don't have to manually grab them from each project's bin\$(Configuration) folder.
I added the following elements to each project file:
<Target Name="CopyPackage">
<Exec WorkingDirectory="$(PackagePath)" Command="copy "$(TargetDir)$(TargetName).wsp" "$(SolutionDir)Builds\$(TargetName).wsp"" ContinueOnError="False" />
<Exec WorkingDirectory="$(PackagePath)" Command="copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)Builds\$(TargetName).pdb"" ContinueOnError="False" />
</Target>
<PropertyGroup>
<BuildDependsOn>$(BuildDependsOn);CreatePackage;CopyPackage</BuildDependsOn>
</PropertyGroup>
So far so good, that works fine.
Each project Package name controls the name of the output WSP file and can be different than the name of the output assembly DLL file.
Visual Studio SharePoint Project Package Name http://imageshack.us/a/img842/322/vsspprojectpackagename.png
In this example the WSP will be named Acme.Edms.SP.ContentTypes.WSP.
It happens that I want my WSP to use a somewhat different name from the project and assembly. But if I change the Package name it breaks the CopyPackage target which uses $(TargetName) that maps to the assembly name.
Is there an MSBuild macro for the (SharePoint) package name so I can fix the above MSBuild elements in my project files?
More generally, does MSBuild have a set of macros specific to the SharePoint project and item types?
Something equivalent to Macros for Build Commands and Properties.
Thanks
Here is the list of SharePoint specific MSBuild properties and there is nothing about package name. So you have to use workaround for that e.g.
First you get lists of package files and pdb files like that:
<ItemGroup>
<PackageFiles Include="$(BasePackagePath)\*.$(PackageExtension)" />
<PdbFiles Include="$(BasePackagePath)\*.pdb)" />
</ItemGroup>
And then you can use it in regular copy command.
I didn't test it but it should work.

Resources