Clickonce-Anwendung startet nicht durch Process.Start ( „x.abc“) mit * .abc der Anwendung Clickonce zugeordnet
-
19-09-2019 - |
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:
- Manueller Start der
x.abc
durch Doppelklick aus dem Explorer funktioniert. - Manueller Start des
x.abc
an der Eingabeaufforderung funktioniert. -
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 einTrace
ganz am Anfang der Clickonce-Anwendung wird nie erreicht. - Fremder noch,
Process.Start("x.bat")
mit einer Dateix.bat
die einzige Zeilex.abc
, die entweder nicht die Clickonce-Anwendung starten! Samex.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).
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.