ClickOnce应用程序无法通过与ClickOnce应用程序关联的*.abc的Process.Start("x.abc")启动

Pie*_*aud 17 .net clickonce processstartinfo file-association windows-7

例如,我已经成功开发并部署了ClickOnce应用程序,该应用程序注册了相关的文件扩展名*.abc.当我单击命名文件x.abcx.abc从命令提示符处键入时,ClickOnce应用程序启动,我可以通过专用API检索文件.我还可以使用以下代码以编程方式启动应用程序:

System.Diagnostics.Process.Start ("x.abc");
Run Code Online (Sandbox Code Playgroud)

我的Windows Vista 64位盒上的一切正常.

但是,如果我尝试在Windows 7(也是64位)上做同样的事情,我有一个非常奇怪的问题.这是我观察到的:

  1. x.abc从资源管理器中双击手动启动.
  2. x.abc从命令提示符手动启动工作.
  3. Process.Start("x.abc")没有启动申请; 但是,返回的进程对象显示没有错误,并且ClickOnce应用程序以某种方式立即退出.但即使是Trace在ClickOnce应用程序的最开始,也永远不会到达.
  4. 更奇怪的是,包含单行Process.Start("x.bat")的文件也无法启动ClickOnce应用程序!同样从Explorer工作开始(当然).x.batx.abcx.bat

试图分析发生的事情ProcMon并不是很有帮助,因为从我的观点来看,启动应用程序的ClickOnce过程非常难以遵循.我观察rundll32到上班,但没有任何失败的证据.

正在执行的程序Process.Start是一个完全信任的控制台应用程序,真的没什么特别的.

我无法看到在Windows 7上处理ClickOnce应用程序的方式发生了哪些变化,为什么Process.Start与从Explorer中启动文件完全相同.值得一提的是,使用该Start方法的更高级版本ProcessStartInfo并设置UseShellExecutetrue无效.

开始cmd使用Process.Start,然后尝试推出x.abc正好显示了同样的问题.如果我将环境设置与cmd手动启动进行比较,我会看到如何ProgramFiles定义的差异(第一个指向C:\Program Files (x86)而第二个指向C:\Program Files).从我的.NET应用程序启动的应用程序是在32位仿真层(SysWoW64)上启动的.

我能够x.abc通过启动32位版本的命令提示符(即,%windir%\SysWoW64\cmd.exe)然后x.abc在提示符下键入来重现启动失败.我还发现了一个丑陋的解决方法,即通过启动%windir%\Sysnative\cmd.exe /C x.abc而不是从32位环境启动64位命令提示符x.abc.

但我宁愿使用干净的方式(或者让微软代表告诉我这确实是Windows 7和/或ClickOncce的一个问题,并且很快就会修复).

Reg*_*ent 10

看起来您使用'x32'构建应用程序作为目标平台,这使得Process.Start生成x32位进程.而且我猜Windows 7分别存储32位和64位应用程序的文件关联.

如果您没有COM或非托管32位依赖项,则可以尝试为"任何"目标平台而不是"x32"构建应用程序.

我进一步调查了一下,发现ClickOnce安装程序为任何关联的文件扩展名创建了以下开放动词(GUID对于每个应用程序是唯一的):

rundll32.exe dfshim.dll, ShOpenVerbExtension {dce01888-35e8-4df3-af35-cd971f520d8d} %1
Run Code Online (Sandbox Code Playgroud)

使用Process Monitor,我发现32位版本无法打开HKCU\Software\Classes\Wow6432Node\CLSID\{dce01888-35e8-4df3-af35-cd971f520d8d}注册表项.(64位版本成功打开它HKCU\Software\Classes\CLSID\{dce01888-35e8-4df3-af35-cd971f520d8d}.)

所以对我来说这确实是一个ClickOnce错误.如果我是你,我会使用那个肮脏的%WinDir%\system32\cmd.exe /C test.abc解决方法.(这似乎工作 - 尝试从x32任务管理器.)

我已将此问题添加到Microsoft Connect(更新2013-02-13:该链接已损坏).


Pie*_*aud 0

我提出了一个基于 .BAT 的解决方案,该解决方案很容易实现。假设您要启动与*.abc文件关联的 ClickOnce 应用程序,那么您只需将一个具有相同名称但扩展名的文件*.bat放在同一文件夹中,然后执行批处理文件即可。这是批处理脚本:

if exist "%windir%\sysnative\cmd.exe" goto :mode64bit

rem For a file named "C:\foo\xyz.bat", this will generate the corresponding
rem "C:\foo\xyz.abc" file, built as the concatenation of the drive (%~d0),
rem the folder (%~p0) and the file name (%~n0), plus ".abc":

"%~d0%~p0%~n0.abc"
goto :end

:mode64bit

rem When running in a 32-bit emulation environment on a real 64-bit system,
rem start the 64-bit version of CMD.EXE, and make if start the ".abc" file
rem for us:

C:\Windows\sysnative\cmd.exe /c "%~d0%~p0%~n0.xgen"

:end
Run Code Online (Sandbox Code Playgroud)

这可以直接在文件的调用者中实现*.abc,但有时批处理文件有助于过渡......