可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
In my C# ClickOnce application, there is an auto-incremented publish version in the Project -> Properties -> Publish tab. I'd like to display that version in my menu Help -> About box, but the code I'm using apparently accesses the assembly Version, which is different.
The Assembly Version can be changed manually in the Project -> Properties -> Application -> Assembly Information dialog. So for now, every time before I publish I've been copying the publish version to the assembly version, so my dialog shows the current version of
the application. There must be a better way to do this.
All I really want to do is have an accurate, auto-updated, code-accessible version number.
Here's the code I'm using to access the assembly version number:
public string AssemblyVersion
{
get
{
return Assembly.GetExecutingAssembly().GetName().Version.ToString();
}
}
An alternative would be to find code that accesses the publish version.
回答1:
sylvanaar's last line looks like the way to go, in my experience; but with the caveat that it is only available to deployed versions of the application. For debugging purposes, you might want something like:
static internal string GetVersion()
{
if (ApplicationDeployment.IsNetworkDeployed)
{
return ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString();
}
return "Debug";
}
回答2:
I modified my .csproj file to update the assembly version. I created a configuration called "Public Release" for this, but it's not required to do that.
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<PropertyGroup Condition="'$(BuildingInsideVisualStudio)' == 'true'">
<MSBuildCommunityTasksPath>$(SolutionDir)Tools\MSBuildCommunityTasks</MSBuildCommunityTasksPath>
</PropertyGroup>
<!-- Required Import to use MSBuild Community Tasks -->
<Import Project="$(SolutionDir)Tools\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" Condition="'$(BuildingInsideVisualStudio)' == 'true'" />
<Target Name="BeforeCompile" Condition="'$(BuildingInsideVisualStudio)|$(Configuration)' == 'true|PublicRelease'">
<FormatVersion Version="$(ApplicationVersion)" Revision="$(ApplicationRevision)">
<Output TaskParameter="OutputVersion" PropertyName="AssemblyVersionToUse" />
</FormatVersion>
<AssemblyInfo CodeLanguage="CS" OutputFile="$(ProjectDir)Properties\VersionInfo.cs" AssemblyVersion="$(AssemblyVersionToUse)" AssemblyFileVersion="$(AssemblyVersionToUse)" />
</Target>
The published version may be:
ApplicationDeployment.CurrentDeployment.CurrentVersion
回答3:
I modified sylvanaar's solution for use with VB:
- Microsoft.VisualBasic.targets instead of Microsoft.CSharp.targets
- CodeLanguage="VB" instead of CodeLanguage="CS"
- AssemblyInfo.vb instead of VersionInfo.cs
, differences in paths:
- $(SolutionDir).build instead of $(SolutionDir)Tools\MSBuildCommunityTasks
- $(ProjectDir)AssemblyInfo.vb instead of $(ProjectDir)Properties\VersionInfo.cs
, and to remove conditions:
- Condition="'$(BuildingInsideVisualStudio)' == 'true'"
- Condition="'$(BuildingInsideVisualStudio)|$(Configuration)' == 'true|PublicRelease'"
I also synchronized Company and Product with ClickOnce PublisherName and ProductName respectively and generated a Copyright based on the current date:
- AssemblyCompany="$(PublisherName)"
- AssemblyProduct="$(ProductName)"
- AssemblyCopyright="© $([System.DateTime]::Now.ToString(`yyyy`)) $(PublisherName)"
I ended up adding this to my vbproj file. It requires the MSBuildTasks NuGet package to be installed first:
<Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.targets" />
<PropertyGroup Condition="'$(BuildingInsideVisualStudio)' == 'true'">
<MSBuildCommunityTasksPath>$(SolutionDir).build</MSBuildCommunityTasksPath>
</PropertyGroup>
<Import Project="$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.Targets" Condition="'$(BuildingInsideVisualStudio)' == 'true'" />
<Target Name="BeforeCompile">
<FormatVersion Version="$(ApplicationVersion)" Revision="$(ApplicationRevision)">
<Output TaskParameter="OutputVersion" PropertyName="AssemblyVersionToUse" />
</FormatVersion>
<AssemblyInfo CodeLanguage="VB" OutputFile="$(ProjectDir)AssemblyInfo.vb" AssemblyVersion="$(AssemblyVersionToUse)" AssemblyFileVersion="$(AssemblyVersionToUse)" AssemblyCompany="$(PublisherName)" AssemblyProduct="$(ProductName)" AssemblyCopyright="© $([System.DateTime]::Now.ToString(`yyyy`)) $(PublisherName)"/>
</Target>
I'm not sure how much the location within the project file matters, but I added this to the end of my project file, just before:
</Project>
回答4:
I would like to expand on Sylvanaar's answer, as some of implementation details weren't obvious to me. So:
Manually install community build tasks found at: https://github.com/loresoft/msbuildtasks/releases Note: Don't install by nuget if you clean your packages, as the build will fail before getting a chance to restore the packages, since msbuildtasks are referenced as a task in the build file. I put these in folder next to solution file called .build
Add a completely empty file to your projects properties folder called VersionInfo.cs
3 Remove these lines if they exist in AssemblyInfo.cs
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.*")]
4 Modify your csproj file
<!-- Include the build rules for a C# project. -->
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!--INSERT STARTS HERE-->
<!--note the use of .build directory-->
<PropertyGroup Condition="'$(BuildingInsideVisualStudio)' == 'true'">
<MSBuildCommunityTasksPath>$(SolutionDir)\.build\MSBuildCommunityTasks</MSBuildCommunityTasksPath>
</PropertyGroup>
<!-- Required Import to use MSBuild Community Tasks -->
<Import Project="$(SolutionDir)\.build\MSBuild.Community.Tasks.targets" Condition="'$(BuildingInsideVisualStudio)' == 'true'" />
<Target Name="BeforeCompile" Condition="'$(BuildingInsideVisualStudio)|$(Configuration)' == 'true|Release'">
<FormatVersion Version="$(ApplicationVersion)" Revision="$(ApplicationRevision)">
<Output TaskParameter="OutputVersion" PropertyName="AssemblyVersionToUse" />
</FormatVersion>
<AssemblyInfo CodeLanguage="CS" OutputFile="$(ProjectDir)Properties\VersionInfo.cs" AssemblyVersion="$(AssemblyVersionToUse)" AssemblyFileVersion="$(AssemblyVersionToUse)" />
</Target>
5 Use a method like the following to access the version text:
public string Version()
{
Version version = null;
if (ApplicationDeployment.IsNetworkDeployed)
{
version = ApplicationDeployment.CurrentDeployment.CurrentVersion;
}
else
{
version = typeof(ThisAddIn).Assembly.GetName().Version;
}
return version.ToString();
}
回答5:
I did it the other way around, used a wildcard for my assembly version - 1.0.* - so Visual Studio/MSBuild generated a version number automatically:
// AssemblyInfo.cs
[assembly: AssemblyVersion("1.0.*")]
And then I added the following AfterCompile target to the ClickOnce project to assign synchronize PublishVersion with the assembly version:
<Target Name="AfterCompile">
<GetAssemblyIdentity AssemblyFiles="$(IntermediateOutputPath)$(TargetFileName)">
<Output TaskParameter="Assemblies" ItemName="TargetAssemblyIdentity" />
</GetAssemblyIdentity>
<PropertyGroup>
<PublishVersion>%(TargetAssemblyIdentity.Version)</PublishVersion>
</PropertyGroup>
</Target>