Project.Build does not work with DeployOnBuild=true - msbuild

My code is as follows:
...
propertyGroup1.AddProperty("DeployOnBuild", "true");
propertyGroup1.AddProperty("DeployTarget", "MSDeployPublish");
propertyGroup1.AddProperty("MSDeployServiceUrl", "localhost");
propertyGroup1.AddProperty("DeployIisAppPath", "local.projects.com");
propertyGroup1.AddProperty("MSDeployPublishMethod", "InProc");
propertyGroup1.AddProperty("AllowUntrustedCertificate", "true");
...
cSharpProject.ProjectCollection.RegisterLogger(cSharpLogger);
try {
buildResult = cSharpProject.Build();
...
buildResult is set to false. However, it does not raise any error to the logger. And the project is not deployed.
I'm running my exe in Administrator mode.
Any help is apprecited.
Thanks
Chris
hint: CSAutoParameterize.parameters and other subfolders have not been created.

<Target Name="WebPublish">
<MsBuild Projects="MyProject.csproj" Properties="DeployOnBuild=true;DeployTarget=MSDeployPublish;MSDeployServiceUrl=localhost;DeployIisAppPath=local.website.com;MSDeployPublishMethod=RemoteAgent;AllowUntrustedCertificate=true;Username=someuser;password=somepassword" />
</Target>
I was able to add this target to the project and call just that specific target.

Related

.NetCore: How to include folder in production?

So I have this code to send email. The code tries to find the .cshtml for the email template.
This is my folder hierarchy:
Project
-- Email
---- EmailConfirmation.cshtml
---- ResetPassword.cshtml
This is the code to find the template:
public static string GetEmailTemplate(string templateName)
{
string path = Path.Combine(Config.Env.ContentRootPath, "Email", templateName);
string content = "";
// This text is added only once to the file.
if (File.Exists(path))
{
// Create a file to write to.
content = File.ReadAllText(path);
}
else
{
throw new Exception("The email template could not be found");
}
return content;
}
In Debug, this runs perfectly, but in production, the code cannot find the template.
How can I include the template in publish package?
I tried this in my .csproj:
<ItemGroup>
<Folder Include="ClientApp\" />
<Folder Include="Migrations\" />
<Views Include="Email\**" />
</ItemGroup>
It is not working.
Edit
I tried to set this:
But still not working.
So my problem was the Email folder was not copied to the published package. Add this code to .csproj:
<ItemGroup>
<None Include="Email\EmailConfirmation.cshtml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Email\ResetPassword.cshtml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Or you can set it in the project explorer like this:
For some reason, the build action has to be set to None, because .NetCore will treat Content differently and the folder will not be copied to the publishing package (maybe the content will be merge into .dll, I do not know).
Could you try this ?
string workingDirectory = Environment.CurrentDirectory;
string projectDirectory=Directory.GetParent(workingDirectory).Parent.Parent.FullName;
It will give you the Path to the project directory. Then you complete with the subdirectory which leads to your file.

Controller not being discovered in asp.net core F#

I am trying to setup a unit test in F# with asp.net core. with the code below. but the code to the server fails with a 404 Not found.
Is there a reason why the controller is being discovered by the framework ?
module Tests
open System
open Xunit
open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Hosting
open Microsoft.AspNetCore.Mvc
open Microsoft.Extensions.DependencyInjection
type Startup () =
member __.ConfigureServices(services: IServiceCollection) =
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2) |> ignore
member __.Configure(app: IApplicationBuilder, env: IHostingEnvironment) =
app.UseMvc() |> ignore
[<Route("api")>]
[<ApiController>]
type TestController() =
inherit ControllerBase()
[<HttpGet("testGet")>]
member __.TestGet() =
121221
[<HttpPost("testPost")>]
member __.TestPost() =
String.Empty
let buildHost(baseAdress:string) =
Microsoft.AspNetCore.WebHost
.CreateDefaultBuilder()
.UseStartup<Startup>()
.UseUrls(baseAdress)
.Build()
[<Fact>]
let ``My test`` () =
let baseAdress = "https://localhost:9000"
use host = buildHost(baseAdress)
host.RunAsync() |> ignore
let client = new System.Net.Http.HttpClient(BaseAddress = new System.Uri(baseAdress))
let result = client.GetAsync("api/testGet").Result
Assert.Equal(System.Net.HttpStatusCode.OK, result.StatusCode)
Assert.True(result.IsSuccessStatusCode, result.Content.ReadAsStringAsync().Result )
Here is the content of the fsproj File
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<IsPackable>false</IsPackable>
<GenerateProgramFile>false</GenerateProgramFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="Tests.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="Microsoft.NETCore.App" Version="2.2.2" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="coverlet.collector" Version="1.0.1" />
</ItemGroup>
</Project>
Except the reasons commented above by #Kirk Larkin, you need put your controller into a namespace instead of module directly.
namespace App //<------------- put your controller into a namespace
// ... open
type Startup () =
...
[<Route("api")>]
[<ApiController>]
type TestController() =
...
module Tests=
// ... open
let buildHost(baseAdress:string) =
Microsoft.AspNetCore.WebHost
.CreateDefaultBuilder()
.UseStartup<Startup>()
.UseUrls(baseAdress)
.Build()
[<Fact>]
let ``My test`` () =
...
Also note you're starting the server by an asynchronous method host.RunAsync() |> ignore. Although the above test code works fine for me, there's a chance your HttpClient will send requests before the server is ready. A good way is to add a reference to the Microsoft.AspNetCore.TestHost package and using the built-in TestHost instead:
let hostBuilder =
Microsoft.AspNetCore.WebHost
.CreateDefaultBuilder()
.UseStartup<Startup>()
use server = new Microsoft.AspNetCore.TestHost.TestServer(hostBuilder)
use client = server.CreateClient()
let result = client.GetAsync("api/testGet").Result // a quick & dirty test
Assert.Equal(System.Net.HttpStatusCode.OK, result.StatusCode)
Assert.True(result.IsSuccessStatusCode, result.Content.ReadAsStringAsync().Result )
[Edit]:
I'm now sure it is a behavior by design. See source code on GitHub:
// We only consider public top-level classes as controllers. IsPublic returns false for nested
// classes, regardless of visibility modifiers
if (!typeInfo.IsPublic)
{
return false;
}
Since the class within a F# module will be compiled into a nested class, it won't be considered as a Controller at all.
On top of the answer that #itminus provided. the issue can be resolved by configuring the application manager in configureServices like so
member this.ConfigureServices(services: IServiceCollection) =
services
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.ConfigureApplicationPartManager(fun m ->
m.FeatureProviders.Add
{
new Microsoft.AspNetCore.Mvc.Controllers.ControllerFeatureProvider() with
member __.IsController (typeInfo:System.Reflection.TypeInfo) =
(typeof<ControllerBase>.IsAssignableFrom(typeInfo)) || base. IsController(typeInfo)
}
) |> ignore
services.AddRouteAnalyzer() |> ignore

dotnet core F# console proj. How to load/open a module?

RaceConditionTest.fs
namespace FConsole
module RaceConditionTest =
let test x =
...
Program.fs
open System
open FConsole
[<EntryPoint>]
let main argv =
RaceConditionTest.test 1000
0 // return an integer exit code
Then I run my console app (linux)
$ dotnet run
error FS0039: The namespace or module 'FConsole' is not defined.
There is only one test method in RaceConditionTest.fs
Is the order of files the problem? if so, How do I indicate the order of *.fs files?
as #boran suggested in his comments there is this FConsoleProject.fsproj
I just added my file before Program.fs
<ItemGroup>
<Compile Include="RaceConditionTest.fs" />
<Compile Include="Program.fs" />
</ItemGroup>

MSBuild exec task without blocking

Would anyone happen to know a trick that will keep this MSBuild task from blocking? I really just want the explorer to open and the build script to keep on going. Currently it blocks at the Exec task until the explorer window is closed.
<Target Name="OpenExplorer">
<Exec Command='explorer.exe "$(DestinationDir)"' IgnoreExitCode="true" />
</Target>
Thanks!
Edit: I was hoping to avoid creating a custom task for this. Perhaps some command line magic exists that could be placed inline for the Command?
Here is an easy way to execute processes asynchronously by only using msbuild and inline tasks. This is only for MSBuild V4.0 and up (God bless the MSBuild guys for adding this feature!). You don't need the any external extension packs.
Effectively, we are taking the code suggested above and putting it in an inline task. Feel free to fiddle with the code to suite your needs.
The point of this solution is that it lets you achieve the result without the headache of creating a separate dll for the custom task. The implementation in the extension pack is definitely more solid but this works as a quick 'n dirty way of solving this issue. You can also customise exactly how you want it to run.
<!--Launch a Process in Parallel-->
<UsingTask TaskName="ExecAsync" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<!--The file path is the full path to the executable file to run-->
<FilePath ParameterType="System.String" Required="true" />
<!--The arguments should contain all the command line arguments that need to be sent to the application-->
<Arguments ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs">
<![CDATA[
string name = System.IO.Path.GetFileNameWithoutExtension(FilePath);
Log.LogMessage("Starting {0}...", name);
System.Diagnostics.ProcessStartInfo processStartInfo = new System.Diagnostics.ProcessStartInfo(FilePath, Arguments);
processStartInfo.UseShellExecute = true;
System.Diagnostics.Process.Start(processStartInfo);
Log.LogMessage("Finished running process {0}.", name);
]]>
</Code>
</Task>
</UsingTask>
You can then call the ExecAsync task from within your normal script in the following fashion. Note: My script below is used to gather code coverage for an application.
<!--Start listening for coverage data:-->
<Message Text="Starting to listen for coverage..."/>
<ExecAsync FilePath='$(VSPerfCmdExePath)' Arguments='/start:coverage /output:"$(CoverageFilePath)"' ContinueOnError='true'/>
<Message Text="Listening for coverage..."/>
<!--Start App with Coverage:-->
<Message Text="Starting App..."/>
<Exec Command='"$(AppCoverageLatestExePath)"' ContinueOnError='true' WorkingDirectory='$(AppCoverageLatestFolder)'/>
<Message Text="App shut down."/>
<!--Stop gathering coverage results:-->
<Message Text="Stopping listening for coverage..."/>
<Exec Command='"$(VSPerfCmdExePath)" /shutdown'/>
<Message Text="Coverage shut down."/>
Here is a description of what is happening there:
First I kick the performance tool off so that it listens for
coverage. I do this using our AsyncExec task because normally the
tool blocks when running in MSBuild (see here).
Next, we start our program that we want to gather coverage on.
Then we shut down the coverage tool once we are done.
You can't do it with the native Exec. But you can write your own that fires asynchronously, as in this example:
public class AsyncExec : Exec {
protected override int ExecuteTool(string pathToTool,
string responseFileCommands,
string commandLineCommands) {
Process process = new Process();
process.StartInfo = GetProcessStartInfo(pathToTool, commandLineCommands);
process.Start();
return 0;
}
protected virtual ProcessStartInfo GetProcessStartInfo(string executable,
string arguments) {
if (arguments.Length > 0x7d00) {
this.Log.LogWarningWithCodeFromResources("ToolTask.CommandTooLong", new object[] { base.GetType().Name });
}
ProcessStartInfo startInfo = new ProcessStartInfo(executable, arguments);
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = true;
string workingDirectory = this.GetWorkingDirectory();
if (workingDirectory != null) {
startInfo.WorkingDirectory = workingDirectory;
}
StringDictionary environmentOverride = this.EnvironmentOverride;
if (environmentOverride != null) {
foreach (DictionaryEntry entry in environmentOverride) {
startInfo.EnvironmentVariables.Remove(entry.Key.ToString());
startInfo.EnvironmentVariables.Add(entry.Key.ToString(), entry.Value.ToString());
}
}
return startInfo;
}
}
which you can then run with:
<AsyncExec Command="..." />
Answered at Starting a program with MSBuild/Web Deployment Project and not waiting for it
<Exec Command="..." Timeout="2000"></Exec>
Try AsyncExec in MSBuild Extension Pack.
The Command in Exec is placed in a batch file and executed. So you can use the "start" keyword in the Command just the same as in a console window. That will do the trick.

Automatically increment "minimum required version" in a ClickOnce deployment?

Is there a way to automatically increment the "minimum required version" fields in a ClickOnce deployment to always equal the current build number? Basically, I always want my deployment to be automatically updated at launch.
I suspect I'm going to need a some pre-/post-build events, but I hope there's an easier way.
I may be a little late with answering this one but I found it difficult to find the solution on google but eventually figured it out so thought I would share.
With MSBuild version 4 (VS2010 and VS2012) this can be achieved by inserting the following target:
<Target Name="AutoSetMinimumRequiredVersion" BeforeTargets="GenerateDeploymentManifest">
<FormatVersion Version="$(ApplicationVersion)" Revision="$(ApplicationRevision)">
<Output PropertyName="MinimumRequiredVersion" TaskParameter="OutputVersion" />
</FormatVersion>
<FormatVersion Version="$(ApplicationVersion)" Revision="$(ApplicationRevision)">
<Output PropertyName="_DeploymentBuiltMinimumRequiredVersion" TaskParameter="OutputVersion" />
</FormatVersion>
</Target>
The $(ApplicationVersion) is the same setting that you can set manually in the project's Publish window in the VS IDE, with the revision part set to an asterisk. The $(ApplicationRevision) is the actual revision being used for the published version. The FormatVersion task is a built-in MSBuild task that formats the two into a single full version number.
This will set the 'Minimum Required Version' to be the same as the 'Publish Version' therefore ensuring that the new deployment will always be installed by users, ie no option to Skip the update.
Of course, if you don't want to set the minimum required version to the publish version and want to use a different source property then it is straight-forward to amend the target, but the principle is the same.
I ended up actually rolling an AddIn to VS that synchronizes all the version numbers, and then builds and publishes with a single click. It was pretty easy.
Public Sub Publish()
Try
Dim startProjName As String = Nothing
Dim targetProj As Project = Nothing
Dim soln As Solution2 = TryCast(Me._applicationObject.DTE.Solution, Solution2)
If soln IsNot Nothing Then
For Each prop As [Property] In soln.Properties
If prop.Name = "StartupProject" Then
startProjName = prop.Value.ToString()
Exit For
End If
Next
If startProjName IsNot Nothing Then
For Each proj As Project In soln.Projects
If proj.Name = startProjName Then
targetProj = proj
Exit For
End If
Next
If targetProj IsNot Nothing Then
Dim currAssemVersionString As String = targetProj.Properties.Item("AssemblyVersion").Value.ToString
Dim currAssemVer As New Version(currAssemVersionString)
Dim newAssemVer As New Version(currAssemVer.Major, currAssemVer.Minor, currAssemVer.Build, currAssemVer.Revision + 1)
targetProj.Properties.Item("AssemblyVersion").Value = newAssemVer.ToString()
targetProj.Properties.Item("AssemblyFileVersion").Value = newAssemVer.ToString()
Dim publishProps As Properties = TryCast(targetProj.Properties.Item("Publish").Value, Properties)
Dim shouldPublish As Boolean = False
If publishProps IsNot Nothing Then
shouldPublish = CBool(publishProps.Item("Install").Value)
If shouldPublish Then
targetProj.Properties.Item("GenerateManifests").Value = "true"
publishProps.Item("ApplicationVersion").Value = newAssemVer.ToString()
publishProps.Item("MinimumRequiredVersion").Value = newAssemVer.ToString()
publishProps.Item("ApplicationRevision").Value = newAssemVer.Revision.ToString()
End If
End If
targetProj.Save()
Dim build As SolutionBuild2 = TryCast(soln.SolutionBuild, SolutionBuild2)
If build IsNot Nothing Then
build.Clean(True)
build.Build(True)
If shouldPublish Then
If build.LastBuildInfo = 0 Then
build.Publish(True)
End If
End If
End If
End If
End If
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Out of the box, I don't belive there is a way. It's not too much effort to spin your own however.
The approach I use is as follows:
1) create a Version.Properties file
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Util-VersionMajor>1</Util-VersionMajor>
<Util-VersionMinor>11</Util-VersionMinor>
<Util-VersionBuild>25</Util-VersionBuild>
<Util-VersionRevision>0</Util-VersionRevision>
<Util-VersionDots>$(Util-VersionMajor).$(Util-VersionMinor).$(Util-VersionBuild).$(Util-VersionRevision)</Util-VersionDots>
<Util-VersionUnders>$(Util-VersionMajor)_$(Util-VersionMinor)_$(Util-VersionBuild)_$(Util-VersionRevision)</Util-VersionUnders>
<MinimumRequiredVersion>$(Util-VersionDots)</MinimumRequiredVersion>
<ApplicationVersion>$(Util-VersionDots)</ApplicationVersion>
<ApplicationRevision>$(Util-VersionRevision)</ApplicationRevision>
</PropertyGroup>
</Project>
2) Import the Version.Properties file into your project files
3) Create a task to increment the version on Build. Here's mine
<Target Name="IncrementVersion" DependsOnTargets="Build" Condition="'$(BuildingInsideVisualStudio)'==''">
<ItemGroup>
<Util-VersionProjectFileItem Include="$(Util-VersionProjectFile)" />
</ItemGroup>
<PropertyGroup>
<Util-VersionProjectFileFullPath>#(Util-VersionProjectFileItem->'%(FullPath)')</Util-VersionProjectFileFullPath>
</PropertyGroup>
<Exec Command=""$(TfCommand)" get /overwrite /force /noprompt "$(Util-VersionProjectFileFullPath)"" Outputs="" />
<Exec Command=""$(TfCommand)" checkout /lock:checkout "$(Util-VersionProjectFileFullPath)"" Outputs="" />
<Version Major="$(Util-VersionMajor)" Minor="$(Util-VersionMinor)" Build="$(Util-VersionBuild)" Revision="$(Util-VersionRevision)" RevisionType="None" BuildType="Increment">
<Output TaskParameter="Major" PropertyName="Util-VersionMajor" />
<Output TaskParameter="Minor" PropertyName="Util-VersionMinor" />
<Output TaskParameter="Build" PropertyName="Util-VersionBuild" />
<Output TaskParameter="Revision" PropertyName="Util-VersionRevision" />
</Version>
<XmlUpdate Prefix="msb" Namespace="http://schemas.microsoft.com/developer/msbuild/2003" XPath="/msb:Project/msb:PropertyGroup/msb:Util-VersionMajor" XmlFileName="$(Util-VersionProjectFile)" Value="$(Util-VersionMajor)" />
<XmlUpdate Prefix="msb" Namespace="http://schemas.microsoft.com/developer/msbuild/2003" XPath="/msb:Project/msb:PropertyGroup/msb:Util-VersionMinor" XmlFileName="$(Util-VersionProjectFile)" Value="$(Util-VersionMinor)" />
<XmlUpdate Prefix="msb" Namespace="http://schemas.microsoft.com/developer/msbuild/2003" XPath="/msb:Project/msb:PropertyGroup/msb:Util-VersionBuild" XmlFileName="$(Util-VersionProjectFile)" Value="$(Util-VersionBuild)" />
<XmlUpdate Prefix="msb" Namespace="http://schemas.microsoft.com/developer/msbuild/2003" XPath="/msb:Project/msb:PropertyGroup/msb:Util-VersionRevision" XmlFileName="$(Util-VersionProjectFile)" Value="$(Util-VersionRevision)" />
<Exec Command=""$(TfCommand)" checkin /override:AutoBuildIncrement /comment:***NO_CI*** "$(Util-VersionProjectFileFullPath)"" />
<Exec Command=""$(TfCommand)" get /overwrite /force /noprompt "$(Util-AssemblyInfoFile)"" Outputs="" />
<Exec Command=""$(TfCommand)" checkout /lock:checkout "$(Util-AssemblyInfoFile)"" Outputs="" />
<AssemblyInfo CodeLanguage="CS" OutputFile="$(Util-AssemblyInfoFile)" AssemblyConfiguration="$(Configuration)" AssemblyVersion="$(Util-VersionMajor).$(Util-VersionMinor).$(Util-VersionBuild).$(Util-VersionRevision)" AssemblyFileVersion="$(Util-VersionMajor).$(Util-VersionMinor).$(Util-VersionBuild).$(Util-VersionRevision)" />
<Exec Command=""$(TfCommand)" checkin /override:AutoBuildIncrement /comment:***NO_CI*** "$(Util-AssemblyInfoFile)"" />
</Target>
Some additional clickonce tricks here http://weblogs.asp.net/sweinstein/archive/2008/08/24/top-5-secrets-of-net-desktop-deployment-wizards.aspx
Here's how I handled this one. First I created a custom task that wraps string replacement:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
namespace SynchBuild
{
public class RemoveAsterisk : Task
{
private string myVersion;
[Required]
public string Version
{
set{myVersion = value;}
}
[Output]
public string ReturnValue
{
get { return myVersion.Replace("*", ""); }
}
public override bool Execute()
{
return true;
}
}
}
So that gets built into SynchBuild.dll which you see referenced in the UsingTask below. Now I tried just overwritting the MinimumRequiredVersion property, but it didn't seem to get picked up, so I just overwrote the GenerateApplicationManifest target by adding the following lines to the end of my csproj file:
<UsingTask AssemblyFile="$(MSBuildExtensionsPath)\WegmansBuildTasks\SynchBuild.dll" TaskName="SynchBuild.RemoveAsterisk" />
<Target Name="GenerateDeploymentManifest" DependsOnTargets="GenerateApplicationManifest" Inputs="
$(MSBuildAllProjects);
#(ApplicationManifest)
" Outputs="#(DeployManifest)">
<RemoveAsterisk Version="$(ApplicationVersion)$(ApplicationRevision)">
<Output TaskParameter="ReturnValue" PropertyName="MinimumRequiredVersion" />
</RemoveAsterisk>
<GenerateDeploymentManifest MinimumRequiredVersion="$(MinimumRequiredVersion)" AssemblyName="$(_DeploymentDeployManifestIdentity)" AssemblyVersion="$(_DeploymentManifestVersion)" CreateDesktopShortcut="$(CreateDesktopShortcut)" DeploymentUrl="$(_DeploymentFormattedDeploymentUrl)" Description="$(Description)" DisallowUrlActivation="$(DisallowUrlActivation)" EntryPoint="#(_DeploymentResolvedDeploymentManifestEntryPoint)" ErrorReportUrl="$(_DeploymentFormattedErrorReportUrl)" Install="$(Install)" MapFileExtensions="$(MapFileExtensions)" MaxTargetPath="$(MaxTargetPath)" OutputManifest="#(DeployManifest)" Platform="$(PlatformTarget)" Product="$(ProductName)" Publisher="$(PublisherName)" SuiteName="$(SuiteName)" SupportUrl="$(_DeploymentFormattedSupportUrl)" TargetCulture="$(TargetCulture)" TargetFrameworkVersion="$(TargetFrameworkVersion)" TrustUrlParameters="$(TrustUrlParameters)" UpdateEnabled="$(UpdateEnabled)" UpdateInterval="$(_DeploymentBuiltUpdateInterval)" UpdateMode="$(UpdateMode)" UpdateUnit="$(_DeploymentBuiltUpdateIntervalUnits)" Condition="'$(GenerateClickOnceManifests)'=='true'">
<Output TaskParameter="OutputManifest" ItemName="FileWrites" />
</GenerateDeploymentManifest>
</Target>
The end result is we take the app version and revision, combine them, remove the asterisk, then set the minimum required version. I have the auto increment app version in my publish properties set so that's how incrementing takes place, then I'm just setting the minimumrequiredversion to always match.I don't use team build, this is just designed so that a developer using visual studio can make all clickonce deployments required. Hope this helps.
If you are publishing your ClickOnce application from Visual Studio then just install the AutoUpdateProjectsMinimumRequiredClickOnceVersion NuGet Package in your project and you're good to go.
If you are publishing from a build server or other script, then you can use the Set-ProjectFilesClickOnceVersion PowerShell script. My blog describes in more detail how to setup your build server to accommodate publishing ClickOnce applications.
Are you looking for Application Updates?
Right clicking on the project in the Solution Explorer and then clicking Publish... is the wrong way to get Application Updates. You have to right-click your project and the click Properties, then click the Publish tab. Click the Updates... button and then check the "The application should check for updates" check box. There you can also specify a minimum required version for the application. (I haven't used that functionality but the Updates functionality is the core reason I use ClickOnce and it works great.)