18

たとえば、関連するファイル拡張子を登録するClickOnceアプリケーションの開発と展開に成功しました*.abc。名前の付いたファイルをクリックするx.abcx.abc、コマンドプロンプトから入力すると、ClickOnceアプリケーションが起動し、専用のAPIを介してファイルを取得できます。次のコードを使用して、プログラムでアプリケーションを起動することもできます。

System.Diagnostics.Process.Start ("x.abc");

私のWindowsVista64ビットボックスではすべて正常に動作します。

ただし、Windows 7(これも64ビット)でまったく同じことを実行しようとすると、非常に奇妙な問題が発生します。これが私が観察するものです:

  1. x.abcエクスプローラーからダブルクリックして手動で起動することができます。
  2. x.abcコマンドプロンプトからの手動起動が機能します。
  3. Process.Start("x.abc")アプリケーションを起動しません。ただし、返されたプロセスオブジェクトは、エラーがなく、ClickOnceアプリケーションが何らかの理由ですぐに終了したことを示しています。ただしTrace、ClickOnceアプリケーションの最初の段階でさえ到達することはありません。
  4. まだ見知らぬ人ですが、1行を含むProcess.Start("x.bat")ファイルでは、ClickOnceアプリケーションも起動しません。同じことがエクスプローラーの作品から始まりました(もちろん)。x.batx.abcx.bat

ProcMon私の観点からすると、アプリケーションを起動するClickOnceプロセスを追跡するのは非常に難しいため、何が起こっているのかを分析しようとしてもあまり役に立ちませんでした。私は仕事に取り掛かることを観察rundll32しますが、失敗の証拠はありません。

を実行しているプログラムProcess.Startは、まったく凝ったものがない完全な信頼コンソールアプリケーションです。

ClickOnceアプリケーションがWindows7でどのように処理されるかに関して何が変わったのかProcess.Start、また、エクスプローラーからファイルを起動するのとまったく同じように動作しないのはなぜかわかりません。Startメソッドのより高度なバージョンを使用しProcessStartInfo、に設定UseShellExecuteしても効果trueがなかったことは言及する価値があります。

最初に起動cmdしてProcess.Startから起動しようとすると、x.abcまったく同じ問題が発生します。環境設定をcmd手動で開始したものと比較すると、ProgramFiles定義方法に違いがあります(最初の設定はを指しC:\Program Files (x86)、2番目の設定はを指しC:\Program Filesます)。.NETアプリケーションから開始されたアプリケーションは、32ビットエミュレーションレイヤー(SysWoW64)で開始されます。

x.abc32ビットバージョンのコマンドプロンプト(つまり、%windir%\SysWoW64\cmd.exe)を起動し、プロンプトで入力することで、の起動の失敗を再現することができましx.abcた。%windir%\Sysnative\cmd.exe /C x.abcまた、醜い回避策を見つけました。これは、の代わりにを起動して、32ビット環境から64ビットのコマンドプロンプトを開始することですx.abc

しかし、私はむしろそれを行うためのクリーンな方法を使用したいと思います(または、Microsoftの担当者に、これは確かにWindows 7やClickOncceの問題であり、まもなく修正されると教えてもらいます)。

4

4 に答える 4

10

Process.Startスポーンをx32ビットプロセスにするターゲットプラットフォームとして「x32」を使用してアプリケーションを構築したようです。そして、私が推測するように、Windows7は32ビットと64ビットのアプリケーションのファイルの関連付けを別々に保存します。

COMまたは管理されていない32ビットの依存関係がない場合は、「x32」ではなく「任意の」ターゲットプラットフォーム用のアプリケーションを構築してみてください。

さらに調査したところ、ClickOnceインストーラーは、関連するファイル拡張子に対して次のオープン動詞を作成することがわかりました(GUIDはアプリケーションごとに一意です)。

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

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タスクマネージャーから試してみました。)

この問題をMicrosoftConnectに追加しました(更新2013-02-13:そのリンクは破損しています)。

于 2009-12-14T15:04:42.603 に答える
0

.batそれは、またはのようなシステム全体の拡張機能を開始するだけかもしれません.txtが、拡張機能を介して常に正しいプログラムを起動できるとは限りません。

代わりに、このAPIまたは.NETの同様の代替手段を試してください。

FindExecutable:shell32.dll エイリアス:"FindExecutableA" / "FindExecutableW" リターンタイプ:int パラメータ: lpFileファイル名を指定するnullで終了する文字列へのポインタ。これは、ドキュメントまたは実行可能ファイルにすることができます。 lpDirectoryデフォルトディレクトリを指定するnullで終了する文字列へのポインタ。 lpResult関数が戻ったときにファイル名を受け取るためのバッファーへのポインター。このファイル名は、lpFileパラメーターで指定されたファイルに対して「オープン」アソシエーションが実行されたときに開始される実行可能ファイルを指定するnullで終了する文字列です。

これは、成功した場合にゼロより大きい整数を返し、char値には、このファイル拡張子を起動する実行可能ファイルを指すnullで終了する文字列が含まれるため、次のように使用できます。

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

の代わりにprogram.exe、API関数の結果を使用し、コマンドラインのようにスペースで区切られたファイルへのパスを使用します。

アプリケーションの失敗については、プログラムを正しく実行するために管理者権限が必要であることを示している可能性があります。cmdすでに管理者権限を取得しているため、子アプリケーションに継承させることはできますが、WindowsAPIには継承させることはできません。正しい特権でこのプログラムを起動するのに役立つLPSECURITYcreateprocess属性を使用できます。

于 2009-12-13T17:10:33.137 に答える
0

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);

Shell();を試すこともできます。フレームワークの一部である機能

于 2009-12-17T20:49:26.907 に答える
0

実装が簡単な.BATベースのソリューションを考え出しました。ファイルに関連付けられたClickOnceアプリケーションを起動するとし*.abcます。次に、同じ名前で*.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

これはファイルの呼び出し元に直接実装できます*.abcが、バッチファイルが移行に役立つ場合があります...

于 2011-02-09T13:44:35.167 に答える