13

我有一个 ClickOnce 应用程序,我需要能够将 URL 参数传递给它。例如,用户可以单击“http://foo.bar/MyApp.application?flavor=grape”形式的 URL,这将启动我的应用程序,并将“?flavor=grape”查询传递给它。

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

我能想到的一种技巧是将我的应用程序注册为一些足够独特的文件扩展名的文件处理程序,例如 ".bugmaster" 。然后——或者我的理论是这样的——我可以让我的网络服务器生成一个名为“flavor_grape.bugmaster”的文件;用户将单击指向该文件的 URL,然后选择“运行”而不是“保存”,这将启动我的应用程序,然后我的应用程序将解析 URL 参数的文件名。不幸的是,这种方法也不起作用。当从本地文件系统打开“flavor_grape.bugmaster”文件时,它工作得非常好,但是,由于某种原因,当用户尝试从浏览器打开文件时,这不起作用。

有没有人有任何其他想法?

4

2 回答 2

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,或者如果您的限制性公司环境不允许它,那么所有这些都会直接消失。但希望你会发现它很有用,或者至少提供了丰富的信息。

于 2012-06-12T23:34:58.627 回答
2

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

幸运的是,/dest当我在 VS 2017 和现在在 VS 2019 中尝试时没有必要,因此可以简单地忽略该选项。

网址设置步骤:

  1. 制作可执行文件的副本,因为下一个命令会更改文件:

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

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

这会grape_setup.exe发生变化,以便后续运行启动 ClickOnce 应用程序,就好像它是从指定的 URL 打开的一样。

但是等等,最后那是什么#

出于某种原因,我还没有弄清楚, using给了我一个可执行文件,它在 URL 的末尾-url有一个额外的。/MyApp.application用于分隔此字符串,因此#它不会被视为最后一个 URL 参数值的一部分。Using#将其放在片段标识符中,但替代方法是使用&junk=or&_=或 just &

退出可执行文件

使用-url修改可执行文件并删除任何 Authenticode 签名。

不幸的是,它以一种signtool.exe在尝试辞职时中断的方式将其删除:

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

这篇博客文章以及一个名为的工具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用来设置网址,最后用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文件中。

/tis<ManifestTimestampUrl>/t如果不需要时间戳,则可以省略该值。

让构建过程留下一个未签名的引导程序

我找到了另一种获得未签名的方法,setup.exe这减轻了我必须使用delcert.

通过将此添加到我的文件中,构建过程会在as.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

于 2019-06-10T07:49:45.320 回答