Sometimes we want to publish a clickonce program automatically during our build and deployment process. MS supports to publish a clickonce program by the command line like this by using MSBuild like this:
msbuild name.project /t:publish
At the same time, you can specify the platform and configuration by "p" parameter like this
msbuild name.project /t:publish p:/configuration="Release";platform="x64"
Here is a document "Building ClickOnce Applications from the Command Line" from MSDN for this topic. It looks like this issue has been solved by using this way, while for some complicated case, it is not.
For example, I made a solution (S) which includes 3 projects, A, B and C like the following picture. A and B are targeted at "x64" and "x86" platform, while C is targeted at "anycpu" platform.
S
o if we try publish A project like this,
msbuild a.project /t:publish p:/configuration="Release";platform="x64"
Build errors will happen as there is no platfrom="x64" for C project.
As msbuild can handle solution file (.sln), so maybe the following command can help us,
msbuild s.sln /t:publish p:/configuration="Release";platform="x64"
If you are lucky, you may get the the published clickonce program for "A", while maybe you will get the clickonce program for "B".
Why this will happen? Because both "A" and "B" are publishable projects, and when you try to publish a solution file includes multi-publishable projects, msbuild will publish them one by one. And when msbuild publishes a new project, the publish process will clean all the old files in the folder which is used to hold all the new published files. So if you are lucky and A is last one to be published, you can get it. But in most cases, you will not get the one you want.
Then how can I solve this issue, a "good" solution is to split these solution into two solutions, one includes A project and C project and the other one include B project and C project.
Can I do this without splitting this solution into two solutions files? Yes, you can.
As we have mentioned that both "A" and "B" are publishable projects, so what is a publishable project and who defines the "publishable" projects? Can I define them as "non-publishable" projects so when I try to publish the solution file, then this project won't be published?
To answer this quetion, let's see what /t:publish means?
From the MSBuild Command-Line Reference, you can see that /t:publish means we wish msbuild to excute the publish target. Target is a concept in MSBuild and it can includes many tasks. MS has already defined many Targets and Tasks which are shipped by the .Net Framework. That means you can use msbuild to build/publish your projects without purchasing Visual Studio.
Now you may want to know how MicroSoft defines "publish" targets? and where can you get it so maybe you can modify it to meet your requirements. The targes provided by MS often exists in the directory
%WINDIR%\Microsoft.NET\Framework\vNNNN
Here vNNNN folder is the version folder for the MS .NetFramework. And the publish targets exists in the "Microsoft.Common.targets" file.
Now please copy "
Microsoft.Common.targets" to other directory (Don't modify this file directly or this will make your Visual Studio cannot work correctly), and then open it with your favorite text editor.
See the "Publish Section", and you will find there is a propetry group like this:
<PropertyGroup>
<PublishDependsOn Condition="'$(PublishableProject)'=='true'">
SetGenerateManifests;
Build;
PublishOnly
</PublishDependsOn>
<PublishDependsOn Condition="'$(PublishableProject)'!='true'">
_DeploymentUnpublishable
</PublishDependsOn>
</PropertyGroup>
It looks like if we can make "
PublishableProject"
as "false" then we can avoid publish this project. Is it true? Let's search "
PublishableProject"
in the
"Microsoft.Common.targets" file. And we find some clues:
<!--
The PublishableProject property is used when invoking the publish target on a solution that
contains multiple projects. The property determines which projects should be published, and
which projects should be skipped in the publish target. By default any "Windows Application"
or "Console Application" project type is publishable. However, a project that would otherwise
be published can be skipped by defining the PublishableProject property in the project itself.
-->
In this comments, we can see how MS defines the "Publishale" for projects, and it also tells us we can specify "
PublishableProject" in our project file and set it as "false" or other things which is not equal to "true", then MSbuild will skip publish this project during publish the solution.
So now we can:
- Open you solution file.
- Unload B project.
- Edit the project file of B. Add "PublishableProject" in its project file like this "<PublishableProject>false</PublishableProject>" and save it.
- Close the solution.
- msbuild s.sln /t:publish p:/configuration="Release";platform="x64"
Done Now.
Through the command way, you may meet the following issues:
- No publish.htm file created.
- Version information.
Please google it for the reason and the solutions.
=========================================================================================================================================
PS. During the msbuild solution.sln, acutally msbuild will create a project file which is meet the requirement for msbuild. You can get the file by set a environment like this:
set MSBuildEmitSolution=1
And this project file's name will be like s.sln.metaproject
=========================================================================================================================================
Referenced
documents
- Inside the Microsoft Build Engine:Using MSBuild and Team Foundation Build.
- Automating Builds Using MSBuild.