Using Solution Packager properties in cdsproj file

When you download a solution using pac solution clone Power Platform CLI also creates a cdsproj file along with the solution components. You’ll need this cdsproj file to do the subsequent pac solution sync to keep the solution components up to date. When you are ready to deploy the solution you run dotnet build either in Debug mode or Release mode to build Unmanaged or Managed Solution.

The default cdsproj does not really tell you about all the Solution Packager properties you can use. This doesn’t seem to be documented in the Microsoft docs site as well. Below is the default on cdsproj.

cdsproj file with solution packager properties

If you have existing Webresources, Plugin/Workflow assemblies or Reports, it is better to build and/or inject them into the solution rather than getting it straight from an environment. This is because the source code might have been modified and not deployed yet to the environment, or even worse, someone might have accidentally deployed older version of webresource or plugin/workflow assemblies. Building these assets just before the solution and injecting the artifacts into the Solution using Solution Packager is a better approach. In order to do this you’ll need a mapping file.

But, how do you specify the mapping file and other Solution Packager properties in the cdsproj? I have created a demo repository in GitHub for this purpose. If you just want to look at the source code go to

This is the key part that adds the additional Solution Packager properties.

      <SolutionPackageErrorLevel Condition="'$(Configuration)' == 'Debug'">Verbose</SolutionPackageErrorLevel>
      <SolutionPackageErrorLevel Condition="'$(Configuration)' == 'Release'">Info</SolutionPackageErrorLevel>
      <!-- The value for this property has to be passed during runtime when you run dotnet build -->
      <SolutionPackageZipFilePath Condition="'$(SolutionFileVersion)' != '' AND '$(Configuration)' == 'Debug'">$(OutputPath)$(MSBuildProjectName)_v$(SolutionFileVersion)</SolutionPackageZipFilePath>
      <SolutionPackageZipFilePath Condition="'$(SolutionFileVersion)' != '' AND '$(Configuration)' == 'Release'">$(OutputPath)$(MSBuildProjectName)_v$(SolutionFileVersion)</SolutionPackageZipFilePath>

I upgraded the cdsproj file in the repo to dotnet 6, but you can stick with 4.6.2 and just use the Solution Packager props if that’s what you want. With these additional properties you get detailed Solution Packager logs as well as Solution file name with version number and also if it is managed or unmanaged. If you look at tasks.json you can get all the commands that you can run from VSCode.

VSCode run tasks screenshot

Below is a small snippet from tasks.json that shows how you can build the Managed Solution.

$env:solutionversion = (Select-Xml -Path '${workspaceFolder}\src\Solution\src\Other\\Solution.xml' -XPath '//Version' | Select-Object @{ n = 'Version'; e = { $_.Node.'#text' } }).Version.Replace('.', '_');

dotnet build '${workspaceFolder}\src\Solution\' -c:Release -v:normal /p:SolutionFileVersion=$env:solutionversion

There are two mapping files, one for Managed solution and one for Unmanaged solution only because the Plugin assembly which is built in Debug mode is stored in a different path compared to Release mode. When Solution Packager packages the assets, the solution component files are copied over to obj/Debug/Metadata or obj/Release/Metadata which is why we need the “../../../” to get to the root folder in the mapping file. This is clear from the build logs.

donet build logs

I hope this post helps you understand cdsproj file and Solution Packager better.


When I tweeted about this couple of weeks back, Betim messaged that he had a post on the topic as well in the past. So, you can refer his post at for additional information as well.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s