Pie*_*aud 17 .net clickonce processstartinfo file-association windows-7
例如,我已经成功开发并部署了ClickOnce应用程序,该应用程序注册了相关的文件扩展名*.abc
.当我单击命名文件x.abc
或x.abc
从命令提示符处键入时,ClickOnce应用程序启动,我可以通过专用API检索文件.我还可以使用以下代码以编程方式启动应用程序:
System.Diagnostics.Process.Start ("x.abc");
Run Code Online (Sandbox Code Playgroud)
我的Windows Vista 64位盒上的一切正常.
但是,如果我尝试在Windows 7(也是64位)上做同样的事情,我有一个非常奇怪的问题.这是我观察到的:
x.abc
从资源管理器中双击手动启动.x.abc
从命令提示符手动启动工作.Process.Start("x.abc")
没有启动申请; 但是,返回的进程对象显示没有错误,并且ClickOnce应用程序以某种方式立即退出.但即使是Trace
在ClickOnce应用程序的最开始,也永远不会到达.Process.Start("x.bat")
的文件也无法启动ClickOnce应用程序!同样从Explorer工作开始(当然).x.bat
x.abc
x.bat
试图分析发生的事情ProcMon
并不是很有帮助,因为从我的观点来看,启动应用程序的ClickOnce过程非常难以遵循.我观察rundll32
到上班,但没有任何失败的证据.
正在执行的程序Process.Start
是一个完全信任的控制台应用程序,真的没什么特别的.
我无法看到在Windows 7上处理ClickOnce应用程序的方式发生了哪些变化,为什么Process.Start
与从Explorer中启动文件完全相同.值得一提的是,使用该Start
方法的更高级版本ProcessStartInfo
并设置UseShellExecute
为true
无效.
开始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:该链接已损坏).
我提出了一个基于 .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
,但有时批处理文件有助于过渡......