Applicazione ClickOnce non si avvia attraverso il Processo.Start(“x.abc”) con *.abc associato all'applicazione ClickOnce
-
19-09-2019 - |
Domanda
Ho sviluppato e implementato un'applicazione ClickOnce che registra un file associato, estensione, per esempio *.abc
.Quando faccio clic su un file di nome x.abc
o se di tipo x.abc
dal prompt dei comandi, l'applicazione ClickOnce inizia, e riesco a recuperare il file tramite l'API dedicate.Posso anche lanciare l'applicazione a livello di programmazione con il codice riportato di seguito:
System.Diagnostics.Process.Start ("x.abc");
Tutto funziona bene sul mio Windows Vista a 64 bit, box.
Tuttavia, se cerco di fare esattamente la stessa cosa su Windows 7 (anche a 64 bit ), ho uno strano problema.Ecco cosa vedo:
- Avvio manuale di
x.abc
facendo doppio clic su di esso da una finestra di Explorer funziona. - Avvio manuale di
x.abc
dal prompt dei comandi funziona. Process.Start("x.abc")
non avviare l'applicazione;tuttavia, il processo oggetto restituito mostra che non c'era errore e che l'applicazione ClickOnce in qualche modo è uscito subito.Ma anche unTrace
all'inizio di applicazione ClickOnce non viene mai raggiunto.- Straniero di sicurezza,
Process.Start("x.bat")
con un filex.bat
contenente la rigax.abc
non si avvia l'applicazione ClickOnce sia!Stessox.bat
iniziato da Explorer funziona (naturalmente).
Cercando di analizzare quello che succede con ProcMon
non è stato molto utile, come ClickOnce processo di avvio di un'applicazione è molto difficile da seguire, dal mio punto di vista.Osservo rundll32
arrivare al lavoro, ma nessuna prova di guasto.
Il programma che sta facendo il Process.Start
è una piena fiducia applicazione console con davvero niente di speciale.
Io non riesco a vedere cosa è cambiato rispetto a come le applicazioni ClickOnce sono gestiti su Windows 7 e perché Process.Start
non farei esattamente la stessa di lanciare il file da Esplora risorse.Vale la pena ricordare che l'utilizzo di più versioni avanzate del Start
con il metodo di ProcessStartInfo
e impostazione UseShellExecute
per true
non aiutano.
A partire cmd
con Process.Start
e poi cercando di lancio x.abc
mostra esattamente lo stesso problema.Se metto a confronto le impostazioni di ambiente con un cmd
avviato manualmente, vedo differenze nel modo in cui ProgramFiles
è definito (il primo dei punti di C:\Program Files (x86)
mentre il secondo punta a C:\Program Files
).Le applicazioni avviate dal mio .NET applicazione sono iniziato il 32-bit livello di emulazione (SysWoW64).
Sono stato in grado di riprodurre il mancato avvio di x.abc
a partire da una versione a 32 bit del prompt dei comandi (che è, %windir%\SysWoW64\cmd.exe
) e poi con il comando x.abc
al prompt dei comandi.Ho anche trovato una brutta soluzione, che è quella di avviare un 64-bit prompt dei comandi da un ambiente a 32 bit con il lancio di %windir%\Sysnative\cmd.exe /C x.abc
invece di x.abc
.
Ma io preferirei usare un modo pulito di fare (o di avere un rappresentante di Microsoft mi dicono che questo è effettivamente un problema con Windows 7 e/o ClickOncce e che sarà risolto al più presto).
Soluzione 3
Mi è venuta in mente una .PIPISTRELLO a base di soluzione, che è facile da implementare.Dire che si desidera avviare l'applicazione ClickOnce associati *.abc
file, quindi è sufficiente mettere un file con lo stesso nome, ma con il *.bat
estensione nella stessa cartella, e quindi eseguire il file batch, invece.Ecco lo script batch:
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
Questo potrebbe essere implementato direttamente nel chiamante del *.abc
i file, ma a volte un file batch aiuta nella transizione...
Altri suggerimenti
Sembra che costruire la vostra applicazione utilizzando 'x32' come la piattaforma di destinazione, il che rende Process.Start
la generazione di un x32 bit.E come credo di Windows 7 contiene le associazioni dei file per la versione a 32-bit e 64-bit separatamente le applicazioni.
Se non si dispone di COM o non gestiti a 32-bit dipendenze si potrebbe provare a costruire la propria applicazione per 'Qualsiasi' piattaforma di destinazione, invece di 'x32'.
Ho studiato alcuni ulteriori e trovato che il programma di installazione ClickOnce crea il seguente verbo open per qualsiasi file associato estensione (GUID è unico per ogni applicazione):
rundll32.exe dfshim.dll, ShOpenVerbExtension {dce01888-35e8-4df3-af35-cd971f520d8d} %1
Utilizzando Process Monitor, Ho trovato che la versione a 32 bit non riesce ad aprire HKCU\Software\Classes\Wow6432Node\CLSID\{dce01888-35e8-4df3-af35-cd971f520d8d}
chiave del registro di sistema.(la versione a 64 bit con successo la apre a HKCU\Software\Classes\CLSID\{dce01888-35e8-4df3-af35-cd971f520d8d}
.)
Quindi per me è davvero un ClickOnce bug.Se fossi in te, vorrei utilizzare sporca %WinDir%\system32\cmd.exe /C test.abc
per risolvere il problema.(Che sembra funzionare tentato da x32 Task Manager.
Ho aggiunto questo problema per il Microsoft Connect (aggiornamento 2013-02-13:quel link è marcio).
Avete provato a usare 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);
Si potrebbe anche provare il Shell(); la funzione di una parte del quadro
Che solo potrebbe iniziare a livello di sistema di estensioni come .bat
o anche .txt
, ma non si può sempre lanciare programmi corretti attraverso le estensioni.
Invece di provare questa API o una simile alternativa .NET:
FindExecutable : shell32.dll Alias : "FindExecutableA" / "FindExecutableW" tipo restituito : int parametri : · lpFile Puntatore a una stringa con terminazione null che specifica un il nome del file.Questo può essere un documento o file eseguibile. · lpDirectory Puntatore a una stringa con terminazione null che specifica il directory predefinita. · lpResult Puntatore a un buffer di ricevere il nome del file quando il la funzione restituisce.Il nome del file è un stringa con terminazione null che specifica il il file eseguibile è iniziato quando un “open” associazione file specificato nel lpFile parametro.
Questo restituisce un numero intero maggiore di zero se il successo e il valore char contiene un stringa con terminazione null che punti al file eseguibile che lancia questo file extension quindi si può usare come questa
System.Diagnostics.Process.Start ("program.exe $:\path\x.abc");
Invece di program.exe
, dovrai utilizzare il risultato della funzione API, e potrete utilizzare il percorso per il file separati con uno spazio proprio come una riga di comando.
Come per la mancata applicazione, potrebbe indicare che il programma ha bisogno di diritti amministrativi per eseguire correttamente. cmd
già ho i diritti di amministratore, in modo che possa fare le applicazioni figlio eredita, ma non API di windows. createprocess
consente di utilizzare LPSECURITY gli attributi che possono aiutare nel lancio di questo programma con i privilegi corretti.