c# - 文件关联导致 Clickonce 安装失败

标签 c# wpf deployment clickonce

我有一个使用 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 的发布->选项来创建关联(将信息放入 .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 的限制。

最佳答案

    - Attempted to perform an unauthorized operation.

此错误表明我们 - 操作被某些保护规则阻止,可能是:

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

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

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

<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. 应用程序只能运行安装它的用户。因此,文件绑定(bind)也仅适用于该用户(因为应用程序文件放入用户配置文件文件夹中)

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

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

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

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

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

  3. 应用程序启动时,您可以运行其他用户的代码 like this 。但是,ClickOnce 是为当前用户安装的,并且此解决方案将无法正常工作。

关于c# - 文件关联导致 Clickonce 安装失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65208576/

相关文章:

c# - PHP mktime() 和 microtime() 在 C# 中等效

c# - wpf 中的设计数据

javascript - 如何检查在使用 ng-test 进行单元测试期间,fdescribe() 和 fit() 从未被调用?

c# - Visual Studio 2015 C# 将应用程序部署到桌面

java - 如何从 NetBeans 部署到 Tomcat?

c# - 安装了两个网格包: The call is ambiguous between the following methods or properties

c# - 无法获得 $http 响应

c# - PhoneGap 开发 ASP.NET MVC 应用程序

c# - 有界数据更改后重新排序 WPF DataGrid

c# - WPF OpenFileDialog 与 MVVM 模式?