在任何浏览器中将URL参数传递给ClickOnce应用程序

时间:2012-06-12 23:05:56

标签: .net url deployment clickonce

我有一个ClickOnce应用程序,我需要能够将URL参数传递给它。例如,用户可以单击表格的网址" http://foo.bar/MyApp.application?flavor = grape",这将启动我的应用程序,传递"?味道=葡萄"查询它。

不幸的是,看起来这只适用于IE开箱即用。在Firefox和Chrome上,用户必须安装附加组件才能使ClickOnce部署正常运行。我的用户在限制性企业环境中工作,不允许安装任何附加组件或其他任何东西(ClickOnce确实适用于他们)。那么,我该怎么办?

我能想到的一个黑客就是将我的应用程序注册为一个足够独特的文件扩展名的文件处理程序,例如" .bugmaster" 。然后 - 或者我的理论去了 - 我可以让我的网络服务器生成一个名为" flavor_grape.bugmaster&#34 ;;用户将单击指向该文件的URL,然后选择"运行"而不是" Save",这将启动我的应用程序,然后谁将解析URL参数的文件名。不幸的是,这种方法也不起作用。当" flavor_grape.bugmaster"文件是从本地文件系统打开的,但由于某种原因,当用户尝试从浏览器打开文件时,这不起作用。

有没有人有其他想法?

2 个答案:

答案 0 :(得分:12)

ClickOnce有一个很棒的小技巧,你可以直接将参数编码到setup.exe使用的URL中。例如,要创建包含“flavor = grape”参数的setup.exe,可以从命令行运行以下命令:

copy setup.exe setup-for-grape.exe
setup.exe -url="http://foo.bar/MyApp.application?flavor=grape" /dest=setup-for-grape.exe

这使用未记录的/ dest标志将结果输出到setup-for-grape.exe文件,而不是修改原始setup.exe。执行此操作后,setup-for-grape.exe将指向您的URL 将包含您的flavor = grape参数。请注意,如果您使用的是签名,则需要对setup.exe的未签名副本执行此操作,然后在签名时签名。

如果可能的参数选择数量相当有限,您可以为它们生成setup.exe,并从您的网站链接到它们。

另一方面,如果有无限数量的选择,您可以设置一个Web服务,该服务接收一些参数,生成一个带有编码所需参数的setup.exe,然后将其吐回客户端。我已经使用此方法为连接到特定服务器的客户端生成setup.exe - 客户端安装URL中包含编码的服务器连接信息,因此在安装客户端时,它会自动知道要连接的服务器。

当然,如果您不想使用setup.exe,或者您的限制性企业环境不允许使用它,所有这一切都会直接显示在窗口之外。但希望你会发现它很有用,或至少提供信息。

答案 1 :(得分:0)

过去接受的答案可能有用,但是现在使用未记录的/dest参数只是失败了: 无法修改'grape_setup.exe'。该文件可能是只读文件或已锁定。

幸运的是,一年前我在VS 2017和现在的VS 2019中遇到此问题时,/dest并不是必需的,因此可以简单地忽略该选项。

设置URL的步骤:

  1. 复制可执行文件,因为下一条命令会更改该文件:

    COPY setup.exe grape_setup.exe
    
  2. 像这样替换网址:

    grape_setup.exe -url="http://foo.bar/MyApp.application?flavor=grape#"
    

这为您提供了一个可执行程序,该程序可以运行ClickOnce应用程序,就像从指定的URL启动该程序一样。

但是,请问;到底#是什么?

由于某种原因,我仍然没有弄清楚,使用-url给我一个可执行文件,该可执行文件每次启动时都会在URL的末尾受到/MyApp.application的攻击。 #可以单独消费此垃圾,因此不会附加到“ flavor”的值上。我使用了#,因此将其放在fragment identifier中,但它可能是&junk=&_=或只是我想的&

退出可执行文件

使用-url修改可执行文件,从而删除所有Authenticode签名。

不幸的是,它的删除方式在尝试辞职时会中断signtool.exe

SignTool Error: SignedCode::Sign returned error: 0x800700C1
        %1 is not a valid Win32 application.

This blog posttool called delcert阐明了这种情况的发生原因。

这是delcert的输出:

ImageRemoveCertificate failed with error 0x00000057
This happens when there's a listing in IMAGE_DIRECTORY_SECURITY
in the PE's header, but the actual Authenticode signature has been stripped.
Let's fix that ...
Setting both fields to zero ...
Succeeded.

通过此操作,-url以一种不干净的方式删除了签名,delcert可以为我们解决这个问题!

鉴于此,可以通过以下三种方法获取带有URL参数的已签名可执行文件:

  • 在发布之前取消选中“签署ClickOnce清单”,然后使用-url设置URL。最后使用signtool.exe进行签名。
  • 照常发布,然后使用-url设置URL。跟着delcert清除损坏的签名。最后使用signtool.exe进行签名。
  • 照常发布。然后使用delcert删除签名。使用-url设置URL,最后使用signtool.exe签名。

所有这三种方法均应创建相同的可执行文件。第一个要求更改为.csproj。第二个和第三个依赖于第三方软件delcert

这是一个实际的例子:

  1. 将可执行文件的副本复制为grape_setup.exe。 (请参阅第一个示例)

  2. 删除Authenticode签名:

    delcert.exe grape_setup.exe
    
  3. 替换URL以设置我们的参数。 (请参阅第一个示例)

  4. 退出新创建的可执行文件:

    signtool.exe sign /sha1 XYZ /t "http://..." grape_setup.exe
    

项目/sha1文件中<ManifestCertificateThumbprint>的值为.csproj

/t的值同样为<ManifestTimestampUrl>,但是如果不需要时间戳记,则省略/t

在构建过程中留下了未签名的引导程序

我找到了获取未签名的setup.exe的另一种方法,这减轻了我不得不使用delcert之类的软件删除签名的可能性。

通过将其添加到我的.csproj文件中,构建过程会在bin\Release\app.publish\下将未签名的副本保留为unsigned_setup.exe

<Target Name="UnsignedBootstrapper" AfterTargets="_DeploymentGenerateBootstrapper" BeforeTargets="_DeploymentSignClickOnceDeployment">
  <Copy SourceFiles="$(PublishDir)\setup.exe" DestinationFiles="$(PublishDir)\unsigned_setup.exe" />
</Target>

_DeploymentGenerateBootstrapper目标生成引导程序,并_DeploymentSignClickOnceDeployment对其进行签名。上面的目标在两者之间运行,以复制可执行文件。

这在VS 2019中有效,但目标名称在其他版本中可能有所不同。在Options> Project and Solutions> Build and Run下将详细程度设置为“诊断”后,我通过查看构建输出来了解它们。