C# 如何在 Windows 窗体上显示 ClickOnce 版本号
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1098112/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to display ClickOnce Version number on Windows Forms
提问by dance2die
I have a windows forms application that is deployed to two different locations.
我有一个部署到两个不同位置的 Windows 窗体应用程序。
- Intranet - ClickOnce
- Internet - Installed on a citrix farm through Windows installer
- 内联网 - ClickOnce
- Internet - 通过 Windows 安装程序安装在 citrix 场上
I display ClickOnce version number for click-once deployed versionApplicationDeployment.IsNetworkDeployed
.
我为单击一次部署版本显示 ClickOnce 版本号ApplicationDeployment.IsNetworkDeployed
。
if (ApplicationDeployment.IsNetworkDeployed)
return ApplicationDeployment.CurrentDeployment.CurrentVersion;
But for the non-click application, I am not sure how to retrieve clickonce version unless I hardcode the version number in assembly info.
但是对于非点击应用程序,除非我在程序集信息中硬编码版本号,否则我不确定如何检索 clickonce 版本。
Is there an automatic way of retrieve ClickOnce version number for non-clickonce deployed version?
是否有自动检索非 clickonce 部署版本的 ClickOnce 版本号的方法?
采纳答案by JaredPar
No I do not believe that there is a way. I believe the ClickOnce information comes from the manifest which will only be available in a ClickOnce deployment. I think that hard coding the version number is your best option.
不,我不相信有办法。我相信 ClickOnce 信息来自清单,该清单仅在 ClickOnce 部署中可用。我认为对版本号进行硬编码是您最好的选择。
回答by Billy Coover
Hard code, or... Keep track on your versions (File, Assembly, Deploy) in a database. Make a call to the database with your Assembly and get the Deploy version.
硬编码,或... 在数据库中跟踪您的版本(文件、程序集、部署)。使用您的程序集调用数据库并获取 Deploy 版本。
This assumes that you are incrementing your versions in a logical way such that each version type has a relationship. It's a lot of work for such a minor problem. I'd personally go with Jared's solution; although I hate hard coding anything.
这假设您以逻辑方式递增版本,以便每个版本类型都有关系。对于这样一个小问题,需要做很多工作。我个人会采用 Jared 的解决方案;虽然我讨厌硬编码任何东西。
回答by RobinDotNet
I would simply make the assembly version of the main assembly the same as the CLickOnce version every time you put out a new version. Then when it runs as a non-clickonce application, just use Reflection to pick up the assembly version.
每次发布新版本时,我都会简单地使主程序集的程序集版本与 CLickOnce 版本相同。然后当它作为非 clickonce 应用程序运行时,只需使用反射来获取程序集版本。
回答by Wilhelm
Using a build component, you could read the click-once version from the project file and write it automatically to the assembly info so both of them are in sync.
使用构建组件,您可以从项目文件中读取单击一次版本并将其自动写入程序集信息,以便两者同步。
回答by cpg
Add an assembly reference to
System.Deployment
to your project.Import the namespace in your class file:
VB.NET:
Imports System.Deployment.Application
C#:
using System.Deployment.Application;
Retrieve the ClickOnce version from the
CurrentVersion
property.You can obtain the current version from the
ApplicationDeployment.CurrentDeployment.CurrentVersion
property. This returns aSystem.Version
object.Note (from MSDN):
CurrentVersion
will differ fromUpdatedVersion
if a new update has been installed but you have not yet calledRestart
. If the deployment manifest is configured to perform automatic updates, you can compare these two values to determine if you should restart the application.NOTE: The
CurrentDeployment
static property is only valid when the application has been deployed with ClickOnce. Therefore before you access this property, you should check theApplicationDeployment.IsNetworkDeployed
property first. It will always return a false in the debug environment.VB.NET:
Dim myVersion as Version If ApplicationDeployment.IsNetworkDeployed Then myVersion = ApplicationDeployment.CurrentDeployment.CurrentVersion End If
C#:
Version myVersion; if (ApplicationDeployment.IsNetworkDeployed) myVersion = ApplicationDeployment.CurrentDeployment.CurrentVersion;
Use the
Version
object:From here on you can use the version information in a label, say on an "About" form, in this way:
VB.NET:
versionLabel.Text = String.Concat("ClickOnce published Version: v", myVersion)
C#:
versionLabel.Text = string.Concat("ClickOnce published Version: v", myVersion);
(
Version
objects are formatted as a four-part number (major.minor.build.revision).)
添加
System.Deployment
对项目的程序集引用。在类文件中导入命名空间:
VB.NET:
Imports System.Deployment.Application
C#:
using System.Deployment.Application;
从
CurrentVersion
属性中检索 ClickOnce 版本。您可以从该
ApplicationDeployment.CurrentDeployment.CurrentVersion
属性中获取当前版本。这将返回一个System.Version
对象。注意(来自 MSDN):
CurrentVersion
将不同于UpdatedVersion
如果已安装新更新但您尚未调用Restart
. 如果部署清单配置为执行自动更新,您可以比较这两个值以确定是否应该重新启动应用程序。注意:
CurrentDeployment
只有在使用 ClickOnce 部署应用程序时,静态属性才有效。因此,在访问此属性之前,应先检查该ApplicationDeployment.IsNetworkDeployed
属性。在调试环境中它总是会返回 false。VB.NET:
Dim myVersion as Version If ApplicationDeployment.IsNetworkDeployed Then myVersion = ApplicationDeployment.CurrentDeployment.CurrentVersion End If
C#:
Version myVersion; if (ApplicationDeployment.IsNetworkDeployed) myVersion = ApplicationDeployment.CurrentDeployment.CurrentVersion;
使用
Version
对象:从这里开始,您可以在标签中使用版本信息,例如在“关于”表单上,以这种方式:
VB.NET:
versionLabel.Text = String.Concat("ClickOnce published Version: v", myVersion)
C#:
versionLabel.Text = string.Concat("ClickOnce published Version: v", myVersion);
(
Version
对象被格式化为四部分数字(major.minor.build.revision)。)
回答by gev
not that it matters three years later, but I ended up just parsing the manifest file with xml reader.
并不是说三年后这很重要,但我最终只是用 xml reader 解析了清单文件。
回答by Vitor Guerreiro
Try thread verification:
尝试线程验证:
if (ApplicationDeployment.IsNetworkDeployed)
{
if (ApplicationDeployment.CurrentDeployment.CurrentVersion != ApplicationDeployment.CurrentDeployment.UpdatedVersion)
{
Application.ExitThread();
Application.Restart();
}
}
回答by bambams
To expand on RobinDotNet's solution:
扩展 RobinDotNet 的解决方案:
Protip: You can automatically run a program or script to do this for you from inside the .csproj file MSBuild configuration every time you build. I did this for one Web application that I am currently maintaining, executing a Cygwin bash shell script to do some version control h4x to calculate a version number from Git history, then pre-process the assembly information source file compiled into the build output.
提示:您可以在每次构建时从 .csproj 文件 MSBuild 配置中自动运行程序或脚本来为您执行此操作。我为当前正在维护的一个 Web 应用程序执行此操作,执行 Cygwin bash shell 脚本以执行一些版本控制 h4x,以从 Git 历史记录计算版本号,然后预处理编译到构建输出中的程序集信息源文件。
A similar thing could be done to parse the ClickOnce version number out of the project file i.e., Project.PropertyGroup.ApplicationRevision
and Project.PropertyGroup.ApplicationVersion
(albeit I don't know what the version string means, but you can just guess until it breaks and fix it then) and insert that version information into the assembly information.
可以做类似的事情来解析项目文件中的 ClickOnce 版本号,即,Project.PropertyGroup.ApplicationRevision
并且Project.PropertyGroup.ApplicationVersion
(尽管我不知道版本字符串的含义,但您可以猜测直到它损坏并修复它)并插入该版本信息转化为装配信息。
I don't know when the ClickOnce version is bumped, but probably after the build process so you may need to tinker with this solution to get the new number compiled in.I guess there's always /*h4x*/ +1
.
我不知道 ClickOnce 版本什么时候被撞了,但可能是在构建过程之后,所以你可能需要修改这个解决方案来编译新的数字。我想总是有/*h4x*/ +1
.
I used Cygwin because *nix scripting is so much better than Windows and interpreted code saves you the trouble of building your pre-build program before building, but you could write the program using whatever technology you wanted (including C#/.NET). The command line for the pre-processor goes inside the PreBuildEvent
:
我使用 Cygwin 是因为 *nix 脚本编写比 Windows 好得多,并且解释代码可以为您省去在构建之前构建预构建程序的麻烦,但是您可以使用任何您想要的技术(包括 C#/.NET)编写程序。预处理器的命令行位于PreBuildEvent
:
<PropertyGroup>
<PreBuildEvent>
$(CYGWIN_ROOT)bin\bash.exe --login -c refresh-version
</PreBuildEvent>
</PropertyGroup>
As you'd imagine, this happens before the build stage so you can effectively pre-process your source code just before compiling it. I didn't want to be automatically editing the Properties\AssemblyInfo.cs
file so to play it safe what I did was create a Properties\VersionInfo.base.cs
file that contained a text template of a class with version information and was marked as BuildAction=None
in the project settings so that it wasn't compiled with the project:
正如您想象的那样,这发生在构建阶段之前,因此您可以在编译之前有效地对源代码进行预处理。我不想自动编辑Properties\AssemblyInfo.cs
文件,所以为了安全起见,我所做的是创建一个Properties\VersionInfo.base.cs
文件,其中包含一个带有版本信息的类的文本模板,并BuildAction=None
在项目设置中标记为,这样它就不会被编译该项目:
using System.Reflection;
using EngiCan.Common.Properties;
[assembly: AssemblyVersion("0.$REVNUM_DIV(100)$.$REVNUM_MOD(100)$.$DIRTY$")]
[assembly: AssemblyRevisionIdentifier("$REVID$")]
(A very dirty, poor-man's placeholder syntax resembling Windows' environment variables with some additional h4x thrown in was used for simplicity's/complexity's sake)
(为了简单/复杂,使用了一个非常脏的、穷人的占位符语法,类似于 Windows 的环境变量,并加入了一些额外的 h4x)
AssemblyRevisionIdentifierAttribute
was a custom attribute that I created to hold the Git SHA1 since it is much more meaningful to developers than a.b.c.d.
AssemblyRevisionIdentifierAttribute
是我创建的用于保存 Git SHA1 的自定义属性,因为它比abcd对开发人员更有意义。
My refresh-version
program would then copy that file to Properties\VersionInfo.cs
, and then do the substitution of the version information that it already calculated/parsed (I used sed(1)
for the substitution, which was another benefit to using Cygwin). Properties\VersionInfo.cs
was compiled into the program. That file can start out empty and you should ignore it by your version control system because it is automatically changing and the information to generate it is already stored elsewhere.
我的refresh-version
程序然后将该文件复制到Properties\VersionInfo.cs
,然后替换它已经计算/解析的版本信息(我用于sed(1)
替换,这是使用 Cygwin 的另一个好处)。Properties\VersionInfo.cs
被编译到程序中。该文件一开始可能是空的,您的版本控制系统应该忽略它,因为它会自动更改,并且生成它的信息已经存储在其他地方。
回答by Lg999
Do a thread verification, insert harded code...
进行线程验证,插入硬代码...