【问题标题】:File association causing Clickonce install to fail文件关联导致 Clickonce 安装失败
【发布时间】:2020-12-08 23:41:17
【问题描述】:

我有一个使用 ClickOnce 部署的 WPF 应用程序。它有一个自定义文件关联集,如果打开该文件类型,它可以在应用程序中打开和打开。这一直很好,然后在更新期间突然用户开始收到“应用程序无法启动”错误。

查看错误详细信息,我可以看到:

ERROR DETAILS
    Following errors were detected during this operation.
    * [12/8/2020 3:34:54 PM] System.UnauthorizedAccessException
        - Attempted to perform an unauthorized operation.
        - Source: mscorlib
        - Stack trace:
            at Microsoft.Win32.RegistryKey.Win32Error(Int32 errorCode, String str)
            at Microsoft.Win32.RegistryKey.SetValue(String name, Object value, RegistryValueKind valueKind)
            at System.Deployment.Application.ShellExposure.AddFileAssociation(FileAssociation fileAssociation, DefinitionIdentity subId, Uri deploymentProviderUri)
            at System.Deployment.Application.ShellExposure.AddShellExtensions(DefinitionIdentity subId, Uri deploymentProviderUri, AssemblyManifest appManifest)
            at System.Deployment.Application.ShellExposure.UpdateShellExtensions(SubscriptionState subState, ShellExposureInformation& shellExposureInformation)
            at System.Deployment.Application.ShellExposure.UpdateSubscriptionShellExposure(SubscriptionState subState)
            at System.Deployment.Application.SubscriptionStore.CommitApplication(SubscriptionState& subState, CommitApplicationParams commitParams)
            at System.Deployment.Application.ApplicationActivator.InstallApplication(SubscriptionState& subState, ActivationDescription actDesc)
            at System.Deployment.Application.ApplicationActivator.PerformDeploymentActivation(Uri activationUri, Boolean isShortcut, String textualSubId, String deploymentProviderUrlFromExtension, BrowserSettings browserSettings, String& errorPageUrl, Uri& deploymentUri)
            at System.Deployment.Application.ApplicationActivator.PerformDeploymentActivationWithRetry(Uri activationUri, Boolean isShortcut, String textualSubId, String deploymentProviderUrlFromExtension, BrowserSettings browserSettings, String& errorPageUrl)
--- End of stack trace from previous location where exception was thrown ---
            at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
            at System.Deployment.Application.ApplicationActivator.PerformDeploymentActivationWithRetry(Uri activationUri, Boolean isShortcut, String textualSubId, String deploymentProviderUrlFromExtension, BrowserSettings browserSettings, String& errorPageUrl)
            at System.Deployment.Application.ApplicationActivator.ActivateDeploymentWorker(Object state)

我确定这是文件关联,因为这是 ClickOnce AFIK 唯一触及注册表的内容。删除它后,问题就消失了,但现在该程序没有文件扩展名。我尝试使用提升的权限进行安装,但这也没有解决问题。重新添加扩展会导致问题再次出现。在此更新中,我们没有触及任何底层文件关联或启动逻辑,那么到底是什么导致了这个问题?

有没有人在使用 ClickOnce 和文件关联时遇到过这种情况?

编辑:使用 VS2017 的 Publish->Options 创建关联(将信息放入 .csproj 文件)。

<ItemGroup>
    <FileAssociation Include=".simsp">
      <Visible>False</Visible>
      <Description>My Description</Description>
      <Progid>MyProgram.Proposal</Progid>
      <DefaultIcon>Proposal.ico</DefaultIcon>
    </FileAssociation>
</ItemGroup>

此外,在卸载和删除与该应用程序相关的 AppData 文件后,该应用程序可以正常安装在一台机器上,但不能在同一用户帐户下安装另一台机器(我们使用文件同步来复制桌面)。这令人困惑,因为如果用户路径中的 AppData 文件存在问题,我不确定为什么在注册表项期间安装会失败。

编辑 3:问题似乎是随机发生的,但我们注意到它是在打开文件时发生的,导致 ClickOnce 应用程序打开并更新。到目前为止,对于使用文件同步、具有多个工作站的复制桌面的用户来说,该问题似乎是孤立的。

解决此问题的最佳做法?这可能只是 ClickOnce 的限制。

【问题讨论】:

  • 您的 clickonce 清单是什么样的?你在用fileAssociation吗?
  • @PavelAnikhouski 我正在使用 VS2017 的内置发布设置进入 .csproj 文件。我假设它在发布时在清单中生成。我可以再次创建关联,看看今晚清单说了什么。
  • @PavelAnikhouski 我更新了问题。我猜该关联不会将自己添加到清单中,因为它不存在。这是在 .csproj 文件中生成的内容。想法?

标签: c# wpf deployment clickonce


【解决方案1】:
    - Attempted to perform an unauthorized operation.

这个错误告诉我们 - 操作被某些保护规则阻止,可以是:

  1. UAC
  2. 用户的计算机安全策略
  3. 用户的域安全策略

因此,您可以通过设置 ClickOnce manifest only UAC 来解决。 我创建了 ClickOnce 清单,它至少有一个与应用程序关联的文件,并且它工作正常。 UAC 要求用户执行安装或更新应用程序,一切正常。但所有用户都没有任何文件同步到另一台计算机。如果他们需要我的应用 - 他们将其安装在另一台计算机上,然后根据需要进行更新。

在 .proj 文件中,我有两个 ClicOnce 清单生成的常规部分:

<ItemGroup>
    <FileAssociation Include=".appex">
      <Visible>False</Visible>
      <Description>Exception info file</Description>
      <Progid>My.AppClient</Progid>
      <DefaultIcon>Images\Exception.ico</DefaultIcon>
    </FileAssociation>
  </ItemGroup>

和先决条件部分:

 <ItemGroup>
    <BootstrapperPackage Include=".NETFramework,Version=v4.7">
      <Visible>False</Visible>
      <ProductName>Microsoft .NET Framework 4.7 %28x86 and x64%29</ProductName>
      <Install>true</Install>
    </BootstrapperPackage>
    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
      <Visible>False</Visible>
      <ProductName>.NET Framework 3.5 SP1</ProductName>
      <Install>false</Install>
    </BootstrapperPackage>
    <BootstrapperPackage Include="Microsoft.SqlServer.SQLSysClrTypes.12.0.x64">
      <Visible>False</Visible>
      <ProductName>System types Microsoft® CLR for SQL Server® 2014 %28x64%29</ProductName>
      <Install>true</Install>
    </BootstrapperPackage>    
  </ItemGroup>

所以,让我们想想“编辑 3”中的用户。当您与其他用户共享您的应用程序时使用 ClickOnce,但您的应用程序仅为一个用户安装,而不是为计算机上的所有用户安装。出于此目的,所有新安装或 ClickOnce 对您的应用程序的任何更新都会在 AppData 目录中创建新文件夹:

  1. 安装新版本的应用
  2. 将回滚操作保存到以前的版本
  3. 应用程序只能运行安装它的那个用户。因此,文件绑定也仅适用于该用户(因为应用程序文件进入用户配置文件文件夹)

此外,还有创建注册表设置以从新位置打开您的应用程序。这种组合(注册表设置和带有文件的应用程序文件夹)不适用于拥有大量工作站的用户,它们在工作站之间同步数据。或者您需要将注册表与应用文件夹(全部)正确同步。

但是!在您的应用程序清单中可能包含带有外部包的先决条件(如我在此处显示的),或者您可以将其添加到您的应用程序的新版本中。当用户在一台计算机上更新您的应用程序或安装它,而不是在没有此外部链接的另一台计算机上运行更新的应用程序(正确同步)时,您认为会是什么?应用会崩溃。

因此,在我看来,您的解决方案将是:

  1. 使用WIX 项目创建包,可以在一台计算机上为所有用户安装。并尽量不要将文件存储在用户配置文件夹中,如果没有正确复制到新计算机,可能会损坏应用程序。如果没有正确复制,或者由您的应用程序重写它。您可以在启动时检查任何更新,或注册更新服务,以在后台安装新版本的应用。

  2. 将 ClickOnce 与同步配置文件规则一起使用,以不通过策略复制应用程序文件。用户一旦在计算机上安装了您的应用程序,用户注销后配置文件不会被删除。您的应用程序的文件不得同步。您尝试在应用启动时使用evaluated privilegies 注册文件扩展名。在另一台计算机上,用户运行全新安装,如果他们需要您的应用程序,或更新(如果它已经安装)。在我的经验中,我将所有应用程序设置存储在数据库中。在我的应用程序连接到的数据库服务器名称和数据库名称的用户注册表设置中。

  3. 在应用启动时,您可以运行来自另一个用户 like this 的代码。但是,为当前用户安装 ClickOnce,此解决方案将无法正常工作。

【讨论】:

  • 感谢您的详细回复。不幸的是,由于我们在内部使用的快速部署过程(它是一个内部应用程序),需要没有提升权限的 ClickOnce。查看我们的复制规则,看起来用户“本地”应用程序数据无论如何都不会在桌面之间同步。然而,创建的“快捷方式”会进入“漫游”文件夹。您的回答使我对注册表进行了更多研究。文件关联的 GUID 在更新期间会发生变化。您知道在安装/更新期间还会创建哪些其他注册表项吗?是注册表冲突导致错误吗?
  • 我的应用程序的 ClickOnce 更新存在一些问题。用户运行应用程序,应用程序更新,然后正确启动。当用户关闭应用程序时,可能会出现错误(非常罕见): 1. 桌面上的快捷方式损坏并且无法运行应用程序(未更新,并且链接到以前版本的空文件夹) 2. 以前版本和当前版本有两个快捷方式。一个运行应用程序,另一个没有。所以,ClickOnce 快捷方式是一个链接serverdustibute/AppName.application#AppName.application,Culture=nutral,publicKeyToken=*****,processorArchitecture=msil AppName.application - 是清单文件,在注册表中注册。
  • ClickOnce 在这里存储条目(我检查了我的注册表) HKEY_CURRENT_USER\SOFTWARE\Classes\Software\Microsoft\Windows\CurrentVersion\Deployment HKEY_CURRENT_USER\SOFTWARE\Classes 和 HKCU 的其他一些地方。因此,此条目复制到配置文件已同步的用户的新环境
  • HKEY_CURRENT_USER\SOFTWARE\Classes\Software\Microsoft\Windows\CurrentVersion\Deployment\SideBySide\2.0\Components\ - 全部由 ClickOnce 应用程序安装,使用 guid 显示应用程序以在更新应用程序后存储版本兼容性。这里是应用程序 HKEY_CURRENT_USER\SOFTWARE\Classes HKEY_CURRENT_USER\SOFTWARE\Classes\AppName HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ 的一些注册表以及 HKCU 中的一些其他地方。这个注册表我找到了我的应用程序 HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\bam\State\UserSettings\User SID\app links 的完整路径
  • 在最后一个注册表 (HKLM) 中,您可以看到指向您的应用程序的链接,如下所示 \Device\HarddiskVolume3\Users\{UserName}\AppData\Local\Apps\2.0\OLE34AGA.AQY\CXKHCR6N.EG7 \application_932ad0cc9880ff94_0001.0013_c63a8dc009dccbb3\appName.exe 所以,我认为如果您使用不同的 GUID 进行不同的安装 - 这可能会导致一个大问题。这就是为什么我推荐 WIX 或其他 VS 安装项目来解决多个环境之间同步注册的问题
【解决方案2】:

查看 Stacktrace,我看到顶部的 Registry 命名空间。因此,除了 Maxim 的回答之外,我还要说它发生在 clickonce 尝试设置注册表项的值时。您还可以在 regdit 中设置权限。右键单击一个键,选择权限,并确保为运行应用程序的用户设置了读写。

由于您已经确定了所涉及的注册表项,因此您可能有很好的机会通过向用户授予对这些注册表项的写入权限来解决它。

【讨论】:

  • 发生这种情况的人确实有适当的访问权限,所以我认为这是导致异常的注册表冲突问题。如果它详细说明导致问题的注册表项会很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-06
  • 1970-01-01
  • 2021-11-30
  • 2013-05-22
  • 1970-01-01
相关资源
最近更新 更多