简体   繁体   English

Click-once应用程序如何确定其应用程序标识?

[英]How does a click-once application determine its application identity?

I have a click-once application, which is correctly signed, correctly configured and installs itself without any problem. 我有一个单击一次的应用程序,它已正确签名,正确配置并自行安装,没有任何问题。

It is set to run offline, but install from a specific URL, and if I download and run the setup.exe, it installs updates. 它设置为脱机运行,但是从特定URL安装,如果我下载并运行setup.exe,它会安装更新。

So, it's basically all working... except I cannot print out the version number, or trigger an update from in code. 所以,它基本上都是有效的...除了我不能打印版本号,或从代码中触发更新。 If I try, I get the dreaded: 'Application identity is not set.' 如果我尝试,我会感到害怕:“应用程序标识未设置。”

2017-01-10 13:43:14.8367 ERROR System.Deployment.Application.InvalidDeploymentException: Application identity is not set.
   at System.Deployment.Application.ApplicationDeployment.get_CurrentDeployment()
   at LibDataAgent.Internal.Services.UpdateService.Deployment() System.Deployment.Application.InvalidDeploymentException: Application identity is not set.
   at System.Deployment.Application.ApplicationDeployment.get_CurrentDeployment()
   at LibDataAgent.Internal.Services.UpdateService.Deployment()

I am not running in debug mode, or using a debug build. 我没有在调试模式下运行,也没有使用调试版本。

So here's my actual question: 所以这是我的实际问题:

How, does the click-once code in System.Deployment.Application , at runtime, determine what the application identity is? System.Deployment.Application中的click-once代码在运行时如何确定应用程序标识是什么?

So, there are whole lot other questions around this, but please don't close this as a duplicate, as far as I can tell it is not one. 所以,围绕这个还有很多其他问题,但请不要将其作为副本关闭,据我所知,它不是一个。

Here's a list of things I do not want answers for: 以下列出了我想要的答案:

  • How to sign a click-one application. 如何签署 click-one应用程序。
  • How to set the application identity as you build. 如何在构建时设置应用程序标识。
  • How to find where the click-once application is installed. 如何找到安装点击一次应用在哪里
  • How to make a click-once application work while debugging . 如何在调试时使单击一次应用程序工作。
  • How to check for updates using ApplicationDeployment . 如何使用ApplicationDeployment检查更新。

Just very plainly, exactly what does a click-once application do, at runtime that lets it determine the application identity. 只是很显然, 正是做一个点击一次应用程序做, 在运行时 ,可以让IT部门确定应用程序标识。

Help! 救命!

Notes 笔记

My (thus far fruitless) attempts to solve this have yielded these notes: 我(迄今为止没有结果)尝试解决这个问题已经产生了这些注释:

I'm certain this has something to do with how the application is launched, because executing applications from the command line has never worked with click-once; 我确定这与应用程序的启动方式有关,因为从命令行执行应用程序从未使用过click-once; but executing the same application from the start menu will correctly return IsNetworkDeployed as true. 但是从开始菜单执行相同的应用程序将正确返回IsNetworkDeployed为true。

However, I've not been able to determine what the technical difference is, or why one detects the install correctly and one doesn't. 但是,我无法确定技术差异是什么,或者为什么人们正确检测到安装,而不是。 (or indeed, why this specific application doesn't work from the start menu, when others with no obvious difference do). (或者实际上,为什么这个特定的应用程序不能从开始菜单起作用,当其他人没有明显的区别时)。

Things I've tried that make no difference include: 我试过的事情没有任何区别包括:

  • the working directory for the application. 应用程序的工作目录。
  • launching the application .exe directly or via a shell 直接或通过shell启动应用程序.exe
  • launching the application from a new shortcut 从新的快捷方式启动应用程序

There is some kind magic to the 'MyApplication.appref-ms' that goes into the start menu; 进入开始菜单的'MyApplication.appref-ms'有一些神奇之处; the appref-ms is just a url to the install path: appref-ms只是安装路径的URL:

http://s3-ap-southeast-1.amazonaws.com/blahblah/Dev/MyApplication.application#MyApplication.application, Culture=neutral, PublicKeyToken=fdasdfsafads, processorArchitecture=x86

...which somehow launches a 'click once aware' instance of the application. ...以某种方式启动应用程序的“单击一次识别”实例。 But how? 但是怎么样?

I'll still happily accept an answer that explains how the guts of launching the application actually sets the application context up with an identity, but for now here's my best stab at what's going on for anyone else who finds this question later: 我仍然会愉快地接受一个解释,解释启动应用程序的内容如何实际上将应用程序上下文设置为一个标识,但是现在这是我对最后发现此问题的其他人所做的最好的尝试:

  • ClickOnce applications are launched by hitting the install url, or by using the .appref-ms file on the start menu, which contains the url. 通过点击安装URL或使用包含url的开始菜单上的.appref-ms文件启动ClickOnce应用程序。

  • The application/x-ms-application MIME type handler is invoked for the downloaded file, which launches the 'ClickOnce aware' instance of the application. 为下载的文件调用application/x-ms-application MIME类型处理程序,该文件启动应用程序的“ClickOnce aware”实例。

  • At runtime, the ApplicationContext.Identity is used to determine what the ClickOnce details are, and setup the CurrentDeployment object. 在运行时, ApplicationContext.Identity用于确定ClickOnce详细信息的内容,并设置CurrentDeployment对象。

  • As far as anyone knows, directly launching the deployed executable for a ClickOnce application (in C:\\Users\\Administrator\\AppData\\Local\\Apps\\2.0\\b107ee1... or whatever the install folder is) will always return IsNetworkDeployed as false, and will not be able to self update. 据任何人都知道,直接启动ClickOnce应用程序的部署可执行文件(在C:\\ Users \\ Administrator \\ AppData \\ Local \\ Apps \\ 2.0 \\ b107ee1 ...或安装文件夹中的任何内容)将始终返回IsNetworkDeployed为false,并且无法自我更新。

Practically speaking, this means: 实际上,这意味着:

  • You're looking for the install folder and path to your .exe? 您正在寻找安装文件夹和.exe的路径? Don't bother. 不要打扰。 Even when you know where it is, it won't have the correct ApplicationContext when you run it. 即使你知道它在哪里,当你运行它时它也没有正确的ApplicationContext

  • To spawn a new 'ClickOnce aware' instance of your application launch internet explorer at its install url. 要生成应用程序的新“ClickOnce aware”实例,请在其安装URL上启动Internet Explorer。 You cannot pass command line arguments to it. 您不能将命令行参数传递给它。

eg. 例如。

var url = "http://s3-ap-southeast-1.amazonaws.com/blahblah/Dev/MyApplication.application#MyApplication.application, Culture=neutral, PublicKeyToken=fdasdfsafads, processorArchitecture=x86";
var psi = new ProcessStartInfo
{
    FileName = @"iexplore",
    Arguments = $"\"{url}\"",
};
Process.Start(psi);

(if you want to find the URL, hunt through the start menu for the appref-ms file for the application; the url is contained in it) (如果要查找URL,请通过应用程序的appref-ms文件的开始菜单进行appref-ms ;其中包含URL)

...and how does the executable get launched with an identity? ...以及如何使用身份启动可执行文件?

No idea; 不知道; but this is as far as anyone seems to ever have got with understanding it: 但这是任何人似乎都有理解它:

(tldr; magic. Probably something to do with how CreateProcess is invoked to spawn the appliciation using the ApplicationContext api, in some combination of DFsvc.exe. DFshim.dll and DFdll.dll) (tldr; magic。可能与在一些DFsvc.exe.DFshim.dll和DFdll.dll的组合中调用CreateProcess以使用ApplicationContext api生成应用程序有关。

(The rest of this information is taken from this old blog post by Ian Picknel: http://ianpicknell.blogspot.com.au/2010/03/launching-clickonce-application.html ) (其余信息来自Ian Picknel的这篇旧博客文章: http ://ianpicknell.blogspot.com.au/2010/03/launching-clickonce-application.html)

Once the deployment manifest has been stored in the Temporary Internet Files folder, Internet Explorer then attempts to establish how it should handle the file with the (assumed and actual) .application extension. 部署清单存储在Temporary Internet Files文件夹中后,Internet Explorer将尝试确定如何使用(假定的和实际的).application扩展名处理该文件。 It checks the user-specific file types at HKCU\\Software\\Classes and, if it fails to find an .application sub-key there, checks for machine-specific file types at HKCR. 它检查HKCU \\ Software \\ Classes中的用户特定文件类型,如果在那里找不到.application子密钥,则在HKCR检查机器特定的文件类型。 Via this means it establishes that the .application extension denotes an Application.Manifest file. 通过这意味着它确定.application扩展名表示Application.Manifest文件。 It then uses this information to check the user-specific HKCU\\Software\\Classes\\Application.Manifest and machine-specific HKCR\\Application.Manifest keys to establish the CLSID of a library which handles Application.Manifest files and yields the result {98af66e4-aa41-4226-b80f-0b1a8f34eeb4}. 然后,它使用此信息检查特定于用户的HKCU \\ Software \\ Classes \\ Application.Manifest和特定于机器的HKCR \\ Application.Manifest键,以建立处理Application.Manifest文件并生成结果的库的CLSID {98af66e4- aa41-4226-b80f-0b1a8f34eeb4}。 Finally, it looks up this CLSID in the user-specific HKCU\\Software\\Classes\\CLSID{98af66e4-aa41-4226-b80f-0b1a8f34eeb4} and machine-specific HKCR\\CLSID{98af66e4-aa41-4226-b80f-0b1a8f34eeb4} paths to establish that .application files are handled by C:\\WINDOWS\\system32\\DFshim.dll. 最后,它在用户特定的HKCU \\ Software \\ Classes \\ CLSID {98af66e4-aa41-4226-b80f-0b1a8f34eeb4}和机器特定的HKCR \\ CLSID {98af66e4-aa41-4226-b80f-0b1a8f34eeb4}路径中查找此CLSID确定.application文件由C:\\ WINDOWS \\ system32 \\ DFshim.dll处理。

This is where things start to get a little complicated. 这是事情开始变得有点复杂的地方。 I said earlier that no 'magic' was happening behind the scenes. 我之前说过,幕后没有“神奇”发生。 Well, whilst that was true for the process of retrieving the deployment manifest it most certainly is not true of the process of actually launching the ClickOnce application once the deployment manifest has been retrieved and the handler, DFshim.dll, has been identified. 好吧,虽然在检索部署清单的过程中确实如此,但是一旦检测到部署清单并且已经识别出处理程序DFshim.dll,实际上启动ClickOnce应用程序的过程肯定不是这样。

DFshim.dll is described in the registry as the 'Manifest mime handler' although its file properties describe it as the 'Application Deployment Support Library'. DFshim.dll在注册表中被描述为'Manifest mime handler',尽管它的文件属性将其描述为'Application Deployment Support Library'。 It implements the Internet Explorer MIME handler COM interface. 它实现了Internet Explorer MIME处理程序COM接口。 It is a native 32-bit DLL, written in Microsoft Visual C++ 2005, and was installed into C:\\Windows\\system32 when the .NET Framework 2.0 was installed. 它是一个本机32位DLL,使用Microsoft Visual C ++ 2005编写,并在安装.NET Framework 2.0时安装到C:\\ Windows \\ system32中。

DFshim.dll has a hard-coded reference to DFdll.dll, which it locates by checking the values of HKLM\\SOFTWARE\\Microsoft.NETFramework\\InstallRoot (typically C:\\Windows\\Microsoft.NET\\Framework) and the keys beneath HKLM\\SOFTWARE\\Microsoft.NETFramework\\Policy\\AppPatch (typically v2.0.50727, even if a later version of the Framework is installed). DFshim.dll有一个对DFdll.dll的硬编码引用,它通过检查HKLM \\ SOFTWARE \\ Microsoft.NETFramework \\ InstallRoot(通常是C:\\ Windows \\ Microsoft.NET \\ Framework)和HKLM下面的键来定位它SOFTWARE \\ Microsoft.NETFramework \\ Policy \\ AppPatch(通常是v2.0.50727,即使安装了更高版本的Framework)。 DFdll.dll too is a native 32-bit DLL written in Microsoft Visual C++ 2005. DFdll.dll也是用Microsoft Visual C ++ 2005编写的本机32位DLL。

DFdll.dll uses COM services exposed by DFsvc.exe, which is also located in the .NET Framework folder. DFdll.dll使用DFsvc.exe公开的COM服务,该服务也位于.NET Framework文件夹中。 DFsvc.exe is a standard .NET MSIL assembly. DFsvc.exe是标准的.NET MSIL程序集。 DFsvc contains a single Main method (within the System.Deployment.Application namespace) which simply calls the internal System.Deployment.Application.DFServiceEntryPoint.Initialize method within System.Deployment.dll. DFsvc包含一个Main方法(在System.Deployment.Application命名空间内),它只调用System.Deployment.dll中的内部System.Deployment.Application.DFServiceEntryPoint.Initialize方法。 The Initialize method registers System.Deployment.Application.DeploymentServiceCom with COM via System.Runtime.InteropServices.RegistrationServices (ie it performs the equivalent of CoRegisterClassObject in COM) using the CLSID {33246f92-d56f-4e34-837a-9a49bfc91df3}. Initialize方法使用CLSID {33246f92-d56f-4e34-837a-9a49bfc91df3}通过System.Runtime.InteropServices.RegistrationServices(即它在COM中执行等效的CoRegisterClassObject)向COM注册System.Deployment.Application.DeploymentServiceCom。 This is the means by which its services are made available to DFdll.dll. 这是DFdll.dll可以使用其服务的方法。

The COM service exposed by System.Deployment.Application.DeploymentServiceCom delegates the majority of its methods to other non-ComVisible classes within the System.Deployment.Application namespace. System.Deployment.Application.DeploymentServiceCom公开的COM服务将其大多数方法委托给System.Deployment.Application命名空间中的其他非ComVisible类。 For example, the public ActivateDeployment method calls ActivateDeployment on a new System.Deployment.Application.ApplicationActivator instance, the public CheckForDeploymentUpdate method calls CheckForDeploymentUpdate on System.Deployment.Application.SubscriptionStore, etc. 例如,公共ActivateDeployment方法在新的System.Deployment.Application.ApplicationActivator实例上调用ActivateDeployment,公共CheckForDeploymentUpdate方法在System.Deployment.Application.SubscriptionStore上调用CheckForDeploymentUpdate等。

It is clear that the vast majority of the work surrounding the actual installation and launch of the ClickOnce application is undertaken by classes within the System.Deployment namespace, hosted within DFsvc.exe. 很明显,围绕实际安装和启动ClickOnce应用程序的绝大多数工作都是由DF.vc.exe中托管的System.Deployment命名空间中的类承担的。 DFshim.dll and DFdll.dll appear to primarily be responsible for arbitrating between the COM-based world of Internet Explorer and the .NET-based world of ClickOnce. DFshim.dll和DFdll.dll似乎主要负责在基于COM的Internet Explorer世界和基于.NET的ClickOnce世界之间进行仲裁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM