application ClickOnce ne démarre pas par Process.Start ( « x.abc ») avec * .abc associée à l'application ClickOnce

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

Question

Je l'ai développé avec succès et déployé une application ClickOnce qui enregistre une extension de fichier associé, par exemple *.abc. Lorsque je clique sur un fichier nommé x.abc ou si je tape x.abc de l'invite de commande, l'application ClickOnce démarre, et je peux récupérer le fichier via l'API dédiée. Je peux aussi lancer l'application par programme avec le code suivant:

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

Tout fonctionne très bien sur ma boîte de Windows Vista 64 bits.

Cependant, sur un ordinateur Windows 7 (également 64 bits) si j'essaie de faire exactement la même chose, j'ai un problème très étrange. Voici ce que je vois:

  1. Démarrage manuel de x.abc en double-cliquant dessus de l'explorateur fonctionne.
  2. Démarrage manuel de x.abc des œuvres d'invite de commande.
  3. Process.Start("x.abc") ne démarre pas l'application; cependant, l'objet de processus retourné montre qu'il n'y avait pas d'erreur et que l'application ClickOnce est sorti en quelque sorte immédiatement. Mais même un Trace au début de l'application ClickOnce est jamais atteint.
  4. Stranger encore, Process.Start("x.bat") avec un x.bat de fichier contenant le x.abc une seule ligne ne démarre pas l'application ClickOnce non plus! Même x.bat a commencé à partir de l'explorateur fonctionne (bien sûr).

Essayer d'analyser ce qui se passe avec ProcMon n'a pas été très utile, car le processus ClickOnce de lancement d'une application est très difficile à suivre, de mon point de vue. Je remarque rundll32 rendre au travail, mais aucune preuve de l'échec.

Le programme qui fait la Process.Start est une application console de confiance totale avec vraiment rien de fantaisie.

Je ne vois pas ce qui a changé par rapport à la façon dont les applications ClickOnce sont traitées sur Windows 7 et pourquoi Process.Start ne le ferais pas exactement le même que le lancement du fichier depuis l'explorateur. Il vaut la peine de mentionner que l'utilisation des versions plus avancées de la méthode Start avec ProcessStartInfo et la mise UseShellExecute à true n'a pas aidé non plus.

A partir cmd avec Process.Start puis essayer de lancer x.abc montre exactement le même problème. Si je compare les paramètres d'environnement avec un cmd commencé manuellement, je vois des différences dans la façon dont ProgramFiles est défini (le premier point à C:\Program Files (x86) tandis que les deuxièmes points C:\Program Files). Les applications lancées à partir de mon application .NET sont démarrés sur la couche d'émulation 32 bits (SysWoW64).

J'ai pu reproduire l'échec du lancement de x.abc en démarrant une version 32 bits de l'invite de commande (qui est, %windir%\SysWoW64\cmd.exe), puis en tapant x.abc à l'invite. J'ai aussi trouvé une solution laide, ce qui est de démarrer une invite de commande 64 bits de l'environnement 32 bits en lançant %windir%\Sysnative\cmd.exe /C x.abc au lieu de x.abc.

Mais je préfère utiliser une manière propre de le faire (ou un représentant de Microsoft me dire que c'est en effet un problème avec Windows 7 et / ou ClickOncce et qu'il sera fixé bientôt).

Était-ce utile?

La solution 3

Je suis venu avec une solution à base de .BAT, qui est facile à mettre en œuvre. Dites que vous voulez lancer l'application ClickOnce associée aux fichiers *.abc, alors vous mettez simplement un fichier avec le même nom, mais avec l'extension *.bat dans le même dossier, puis exécutez le fichier de commandes à la place. Voici le 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

Cela pourrait être implémentés directement dans l'appelant des fichiers *.abc, mais parfois un fichier batch aide à la transition ...

Autres conseils

On dirait que vous avez construire votre application à l'aide « x32 » comme la plate-forme cible qui fait Process.Start lancer un processus x32 bits. Et comme je suppose que Windows 7 associations de fichiers stocke pour les applications 32 bits et 64 bits séparément.

Si vous n'avez pas COM ou non gérés dépendances 32 bits, vous pouvez essayer de construire votre demande de « tout » plate-forme cible au lieu de « x32 ».

J'ai étudié un peu plus loin et trouvé que l'installateur ClickOnce crée le verbe ouvert suivant pour toute extension de fichier associé (GUID est unique par application):

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

Utilisation Process Monitor , j'ai trouvé que le 32 bits la version ne parvient pas à ouvrir la clé de registre HKCU\Software\Classes\Wow6432Node\CLSID\{dce01888-35e8-4df3-af35-cd971f520d8d}. (La version de 64 bits, il ouvre avec succès à HKCU\Software\Classes\CLSID\{dce01888-35e8-4df3-af35-cd971f520d8d}.)

Donc, pour moi, il est en effet un bug ClickOnce. Si je devais vous, je voudrais utiliser cette solution de %WinDir%\system32\cmd.exe /C test.abc sale. (Ce qui semble fonctionner -. Essayé de x32 Task Manager)

J'ai ajouté cette question à la Microsoft Connect (mise à jour 13/02/2013: ce lien est pourri).

Avez-vous essayé d'utiliser 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);

Vous pouvez également essayer de Shell (); fonction qui fait partie du cadre

Cela ne pourrait commencer à l'échelle du système des extensions comme .bat ou même .txt, mais il ne peut pas toujours lancer des programmes corrects grâce à des extensions.

Au lieu d'essayer cette API ou une alternative similaire dans .NET :

  

FindExecutable: shell32.dll Alias   : "FindExecutableA" /    "FindExecutableW" type de retour: int paramètres:    · lpFile pointeur sur une chaîne se terminant par NULL spécifiant une   nom de fichier. Cela peut être un document ou   fichier exécutable.    · lpDirectory pointeur sur une chaîne terminée par NULL spécifiant la   répertoire par défaut.    · lpResult pointeur vers un tampon pour recevoir le nom de fichier lorsque le   retour de la fonction. Ce nom de fichier est un   chaîne à zéro terminal spécifiant le   fichier exécutable a commencé quand un « ouvert »   association est exécuté sur le fichier   spécifié dans le paramètre lpFile.

retourne un entier plus grand que zéro si le succès et la valeur char contiendra un null-fin chaîne qui pointe vers l'exécutable qui lance cette extension de fichier alors vous pouvez l'utiliser comme ceci

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

Au lieu de program.exe, vous utiliserez le résultat de la fonction API, et vous allez utiliser le chemin vers le fichier séparé avec un espace comme une ligne de commande.

En ce qui concerne l'échec de l'application, il pourrait indiquer que le programme a besoin de droits d'administrateur pour fonctionner correctement. cmd déjà obtenu des droits d'administration, il peut faire des applications enfants héritent, mais pas l'API Windows. createprocess vous permet d'utiliser LPSECURITY attributs qui peuvent aider à lancer ce programme avec les privilèges corrects.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top