ClickOnce application does not start through Process.Start(“x.abc”) with *.abc associated to the ClickOnce application

后端 未结 4 909
心在旅途
心在旅途 2020-12-30 03:02

I have successfully developed and deployed a ClickOnce application which registers an associated file extension, for instance *.abc. When I click on a file name

相关标签:
4条回答
  • 2020-12-30 03:24

    I've come up with a .BAT based solution, which is easy to implement. Say that you want to launch the ClickOnce application associated with *.abc files, then you simply put a file with the same name, but with the *.bat extension in the same folder, and then execute the batch file instead. Here is the batch script:

    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
    

    This could be implemented directly in the caller of the *.abc files, but sometimes a batch file helps in the transition...

    0 讨论(0)
  • 2020-12-30 03:25

    That only might start system wide extensions like .bat or even .txt, but it can't always launch correct programs through extensions.

    Instead try this API or a similar alternative in .NET:

    FindExecutable : shell32.dll Alias : "FindExecutableA" / "FindExecutableW" return type : int parameters : · lpFile Pointer to a null-terminated string specifying a filename. This can be a document or executable file. · lpDirectory Pointer to a null-terminated string specifying the default directory. · lpResult Pointer to a buffer to receive the filename when the function returns. This filename is a null-terminated string specifying the executable file started when an “open” association is run on the file specified in the lpFile parameter.

    This returns an integer bigger than zero if success and the char value will contain a null-terminated string that points to the executable that launches this file extension then you can use it like this

    System.Diagnostics.Process.Start ("program.exe $:\path\x.abc");
    

    Instead of program.exe, you'll use the result of the API function, and you'll use the path to the file separated with a space just like a command line.

    As for the application failure, it might indicate that the program needs administrative rights to run correctly. cmd already got administrative rights, so it can make child applications inherit it, but not windows API. createprocess allows you to use LPSECURITY attributes which can help in launching this program with the correct privileges.

    0 讨论(0)
  • 2020-12-30 03:36

    It looks like you've build your application using 'x32' as the target platform which makes Process.Start spawn a x32-bit process. And as I guess Windows 7 stores file associations for 32-bit and 64-bit applications separately.

    If you don't have COM or unmanaged 32-bit dependencies you could try building your application for 'Any' target platform instead of 'x32'.

    I investigated some further and found that ClickOnce installer creates the following open verb for any associated file extension (GUID is unique per application):

    rundll32.exe dfshim.dll, ShOpenVerbExtension {dce01888-35e8-4df3-af35-cd971f520d8d} %1
    

    Using Process Monitor, I found that the 32-bit version fails to open HKCU\Software\Classes\Wow6432Node\CLSID\{dce01888-35e8-4df3-af35-cd971f520d8d} registry key. (the 64-bit version successfully opens it at HKCU\Software\Classes\CLSID\{dce01888-35e8-4df3-af35-cd971f520d8d}.)

    So for me it is indeed a ClickOnce bug. If I were you, I would use that dirty %WinDir%\system32\cmd.exe /C test.abc workaround. (Which appears to work -- tried from x32 Task Manager.)

    I've added this issue to the Microsoft Connect (update 2013-02-13: that link is rotten).

    0 讨论(0)
  • 2020-12-30 03:46

    Have you tried using ShellExecute(); API?

            [DllImport("Shell32.dll",CharSet=CharSet.Auto)]
        public static extern IntPtr ShellExecute(
            IntPtr hwnd, 
            string lpVerb,
            string lpFile, 
            string lpParameters, 
            string lpDirectory,
            int nShowCmd );
    
    ShellExecute(this.Handle,"open","x.abc","","",3);
    

    You could also try the Shell(); function which is a part of framework

    0 讨论(0)
提交回复
热议问题