Clickonce-Anwendung startet nicht durch Process.Start ( „x.abc“) mit * .abc der Anwendung Clickonce zugeordnet

StackOverflow https://stackoverflow.com/questions/1890634

Frage

Ich habe erfolgreich entwickelt und eingesetzt, um eine Clickonce-Anwendung, die eine zugehörige Dateierweiterung registriert, zum Beispiel *.abc. Wenn ich auf einer Datei mit dem Namen x.abc klicken oder wenn ich x.abc von der Eingabeaufforderung eingeben, beginnt die Clickonce-Anwendung, und ich kann die Datei über das dedizierte API abgerufen werden. Ich kann auch die Anwendung starten programmatisch mit dem folgenden Code:

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

Alles funktioniert gut auf meinem Windows Vista 64-Bit-Feld.

Allerdings, wenn ich versuche, genau das gleiche auf einem Windows 7 (auch 64 Bit) zu tun, ich habe ein sehr seltsames Problem. Hier ist, was ich zu beachten:

  1. Manueller Start der x.abc durch Doppelklick aus dem Explorer funktioniert.
  2. Manueller Start des x.abc an der Eingabeaufforderung funktioniert.
  3. Process.Start("x.abc") nicht die Anwendung starten; jedoch kehrte das Prozessobjekt zeigt, dass es nicht Fehler wurde und dass die Clickonce-Anwendung irgendwie sofort verlassen. Aber auch ein Trace ganz am Anfang der Clickonce-Anwendung wird nie erreicht.
  4. Fremder noch, Process.Start("x.bat") mit einer Datei x.bat die einzige Zeile x.abc, die entweder nicht die Clickonce-Anwendung starten! Same x.bat aus dem Explorer gestartet funktioniert (natürlich).

Der Versuch, zu analysieren, was mit ProcMon passiert, war nicht sehr hilfreich, da der Prozess Clickonce eine Anwendung startet sehr schwer zu folgen, aus meiner Sicht. Ich beobachte rundll32 an die Arbeit, aber keine Hinweise auf eine Mißachtung.

Das Programm, das die Process.Start tut, ist eine volle Vertrauen Konsolenanwendung mit wirklich nichts Besonderes.

Ich kann nicht sehen, was in Bezug auf verändert, wie Clickonce-Anwendungen auf Windows behandelt werden 7 und warum Process.Start nicht genau so starten Sie die Datei aus dem Explorer das gleiche tun. Es lohnt sich zu erwähnen, dass fortgeschrittenere Versionen der Start Methode mit ProcessStartInfo mit und UseShellExecute zu true Einstellung nicht auch nicht helfen.

Starten cmd mit Process.Start und dann zu versuchen, x.abc zu starten zeigt genau das gleiche Problem. Wenn ich die Umgebungseinstellungen mit einem cmd vergleichen manuell gestartet, ich sehe Unterschiede, wie ProgramFiles definiert ist (die ersten Punkte auf C:\Program Files (x86) während der zweiten Punkte C:\Program Files). Die Anwendungen von meiner .NET-Anwendung gestartet werden, auf der 32-Bit-Emulationsschicht (SysWoW64) gestartet.

Ich konnte den Fehlstart von x.abc reproduzieren, indem Sie eine 32-Bit-Version von der Eingabeaufforderung starten (das heißt, %windir%\SysWoW64\cmd.exe) und dann an der Eingabeaufforderung eingeben x.abc. Ich habe auch ein hässliches Problem zu umgehen, die durch die Einführung %windir%\Sysnative\cmd.exe /C x.abc statt x.abc eine 64-Bit-Eingabeaufforderung von der 32-Bit-Umgebung zu starten ist.

Aber ich würde lieber eine saubere Art und Weise verwenden, es zu tun (oder habe einen Microsoft-Vertreter sagen mir, dass dies in der Tat ein Problem mit Windows 7 und / oder ClickOncce und dass es bald behoben sein wird).

War es hilfreich?

Lösung 3

Ich habe mit einer .BAT basierten Lösung zu kommen, die einfach zu implementieren ist. Sagen Sie, dass Sie die Clickonce-Anwendung im Zusammenhang mit *.abc Dateien, dann einfach eine Datei setzen mit dem gleichen Namen, aber mit der *.bat Erweiterung im selben Ordner, und führen Sie dann die Batch-Datei stattdessen starten mögen. Hier ist die Batch-Skript:

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

Das in den Anrufern der *.abc Dateien implementiert direkt werden könnte, aber manchmal eine Batch-Datei hilft beim Übergang ...

Andere Tipps

Es sieht aus wie Sie Ihre Anwendung haben bauen mit ‚x32‘ als Zielplattform, die einen x32-Bit-Prozess Process.Start laichen macht. Und wie ich denke, Windows 7 speichert Dateizuordnungen für 32-Bit- und 64-Bit-Anwendungen getrennt.

Wenn Sie nicht über COM oder nicht verwaltete 32-Bit-Abhängigkeiten, die Sie könnten versuchen, Ihre Anwendung Aufbau für ‚Any‘ Zielplattform anstelle von ‚x32‘.

Ich untersuchte einig weiteren und festgestellt, dass Clickonce-Installationsprogramm das folgende offene Verb für jede zugehörige Dateierweiterung erstellt (GUID ist einmalig pro Anwendung):

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

Mit Process Monitor , fand ich, dass der 32-Bit Version schlägt fehl HKCU\Software\Classes\Wow6432Node\CLSID\{dce01888-35e8-4df3-af35-cd971f520d8d} Registrierungsschlüssel zu öffnen. (Die 64-Bit-Version öffnet sie erfolgreich bei HKCU\Software\Classes\CLSID\{dce01888-35e8-4df3-af35-cd971f520d8d}.)

Also für mich ist es in der Tat ein Fehler Clickonce. Wenn ich Sie wäre, würde ich das schmutzige %WinDir%\system32\cmd.exe /C test.abc Abhilfe verwenden. (Welche scheint zu funktionieren -. Versuchte, von x32 Task-Manager)

Ich habe dieses Problem mit dem hinzugefügt Microsoft Connect (Update 2013.02.13: diese Verbindung ist faul).

Haben Sie versucht, mit 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);

Sie könnten auch versuchen, den Shell (); Funktion, die ein Teil des Rahmens ist

Das nur systemweite Erweiterungen wie .bat beginnen könnte oder sogar .txt, aber es kann nicht immer korrekt Programme durch Erweiterungen starten.

Stattdessen versuchen diese API oder eine ähnliche Alternative in .NET :

  

FindExecutable: shell32.dll Alias   : "FindExecutableA" /    "FindExecutableW" Rückgabetyp: int Parameter:    · lpFile Zeiger auf einen nullterminierten String angibt ein   Dateiname. Dies kann ein Dokument sein oder   ausführbare Datei.    · lpDirectory Zeiger auf einen nullterminierten String angibt die   Standardverzeichnis.    · lpResult Zeiger auf einen Puffer, um die Dateinamen zu erhalten, wenn die   Funktion zurückkehrt. Dieser Dateiname ist ein   null-terminierte Zeichenkette die Angabe   ausführbare Datei gestartet wird, wenn eine „offene“   Verein ist auf die Datei ausführen   angegeben im lpFile Parameter.

Dies gibt eine ganze Zahl größer als Null ist, wenn der Erfolg und der char-Wert eine nullterminierte String dass verweist auf die ausführbare Datei, die diese Dateierweiterung startet dann können Sie es wie folgt verwenden

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

Statt program.exe, werden Sie das Ergebnis der API-Funktion verwenden, und Sie werden den Pfad zur Datei mit einem Raum wie eine Befehlszeile getrennt verwendet werden.

Wie für den Ausfall von Anwendungen, könnte dies darauf hinweist, dass das Programm Administratorrechte benötigt um korrekt zu funktionieren. cmd bereits Administratorrechte bekam, so dass es Kind Anwendungen es erben machen können, aber nicht Windows-API. createprocess können Sie LPSECURITY Attribute, die bei der Einführung dieses Programms mit den richtigen Privilegien helfen kann.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top