2009-07-28 7 views
12

J'ai une application VB6 qui ouvre des fichiers avec leur application associée à l'aide:Quelles raisons pourraient faire échouer ShellExecute?

ShellExecute(0, "open", filename, params, vbNullString, vbNormalFocus) 

Cela fonctionne parfaitement.

Maintenant, j'ai un client (exécutant XP avec Adobe Reader) qui ne peut ouvrir aucun fichier PDF en utilisant la commande ci-dessus. Mais le même fichier est ouvert sans aucun problème lorsque vous double-cliquez dessus à partir de Windows Explorer. J'ai également testé la combinaison nom de fichier/chemin sur ma machine pour exclure ce genre de problèmes.

Je cherche des indices sur ce que je pourrais vérifier pour m'assurer que ShellExecute fonctionne. Ou qu'est-ce qui peut faire échouer ShellExecute de cette façon?

+0

Je suis curieux de savoir pourquoi vous ajoutez vbNullString au nom de fichier. Une raison pour cela? Tout changement si vous ne l'utilisez pas? –

+0

Je pense que l'ajout de 'vbNullString' à la fin de vos chaînes n'est pas nécessaire. Cependant, si je me trompe, vous devrez également l'ajouter à l'option "Ouvrir". – Treb

+0

Ce n'est pas vraiment nécessaire. Je l'ai juste ajouté un jour et maintenant il est toujours là. Puis je l'ai ajouté à cause de la documentation disant que la fonction prend des chaînes terminées par null. – MicSim

Répondre

9

Quelle est la valeur de retour de ShellExecute? Si c'est 0x0000001f (== 31, ce qui signifie SE_ERR_NOASSOC), que selon shellapi.h "Il n'y a pas d'application associée à l'extension de nom de fichier donné.", ce qui signifie que l'enregistrement de l'extension de fichier .pdf a été perdu. Réinstaller Adobe Reader peut vous aider.

+0

C'est la chose étrange, cependant. Pourquoi le format PDF fonctionnerait-il sur le bureau mais pas sur ShellExecute? Très étrange. –

+1

Il se peut qu'Explorer utilise du COM Voodoo;) –

+2

Windows utilise au moins deux façons de décider quelle application appeler pour quelle extension de fichier: Ceux qui sont valides pour tous les utilisateurs sur la machine, et ceux qui sont spécifiques à l'utilisateur. Peut-être que l'utilisateur a joué avec les associations de fichiers pdf (Explorer: Options des dossiers - Types de fichiers). – Treb

3

Jetez un oeil à la valeur de retour de votre appel ShellExecute. De l'MSDN:

Si la fonction réussit, elle retourne une valeur supérieure à 32. Si la fonction échoue, elle renvoie une valeur d'erreur qui indique la cause de l'échec. La valeur de retour est convertie en HINSTANCE pour une compatibilité ascendante avec les applications Windows 16 bits. Ce n'est pas une véritable HINSTANCE, cependant. Il peut être cast uniquement à un int et comparé à 32 ou les codes d'erreur suivants ci-dessous.

0: Le système d'exploitation manque de mémoire ou de ressources.

ERROR_FILE_NOT_FOUND: Le fichier spécifié est introuvable.

ERROR_PATH_NOT_FOUND: Le chemin spécifié n'a pas été trouvé

(...)

+0

Je noterai cette valeur et j'en saurai plus. – MicSim

9

Suite à Thomas de answer, voici quelques constantes VB6 pour les valeurs possibles de retour de ShellExecute, avec des explications possibles (je pense que je à l'origine pris ces à partir de MSDN page, section de valeur de retour). Une valeur de retour de 32 ou moins signifie que l'appel a échoué. La valeur spécifique renvoyée indique ce qui s'est mal passé.

Const ERROR_BAD_FORMAT = 11& 
Const ERROR_FILE_NOT_FOUND = 2&   
Const ERROR_PATH_NOT_FOUND = 3&   ' The specified path was not found. ' 
Const SE_ERR_ACCESSDENIED = 5   ' The operating system denied access to the specified file. ' 
Const SE_ERR_ASSOCINCOMPLETE = 27  ' The file name association is incomplete or invalid. ' 
Const SE_ERR_DDEBUSY = 30    ' The Dynamic Data Exchange (DDE) transaction could not be completed because other DDE transactions were being processed. ' 
Const SE_ERR_DDEFAIL = 29    ' The DDE transaction failed. ' 
Const SE_ERR_DDETIMEOUT = 28    ' The DDE transaction could not be completed because the request timed out. ' 
Const SE_ERR_DLLNOTFOUND = 32   ' The specified dynamic-link library (DLL) was not found. ' 
Const SE_ERR_FNF = 2      ' The specified file was not found. ' 
Const SE_ERR_NOASSOC = 31    ' There is no application associated with the given file name extension. ' 
Const SE_ERR_OOM = 8      ' out of memory ' 
Const SE_ERR_PNF = 3      ' path not found ' 
Const SE_ERR_SHARE = 26     ' A sharing violation occurred. ' 
4

Vous avez « ouvert » comme le verbe, ne faites pas cela, utilisez vbNullString comme le verbe (« Ouvrir » signifie le verbe ouvert, NULL signifie le verbe par défaut (si l'utilisateur n'a pas fixé spécifique par défaut, la valeur par défaut est ouvert, s'il n'y a pas de verbe ouvert pour ce type de fichier, ShellExecute utilise le premier verbe qu'il trouve))

+2

Cela semble être une chose étrange à faire. Si un utilisateur a changé le verbe par défaut en "Modifier" ou "Imprimer", le résultat ne sera pas ce qui était souhaité: voir le document PDF. – Bob77

+0

C'est leur choix. C'est mieux que d'utiliser un verbe qui pourrait ne pas exister. Si vous voulez le meilleur des deux mondes, vous pouvez vérifier si le verbe ouvert existe en premier, et si ce n'est pas le cas, utilisez NULL (Mais de cette façon, vous êtes vraiment en train de visser votre utilisateur, car ils l'ont ignoré) – Anders

+1

la question commence par "Quelles raisons" et c'est une raison valable, donc je ne comprends pas pourquoi vous me votez. (J'ai vu ce problème dans la nature) – Anders

3

au lieu d'utiliser ShellExecute pour « exécuter » le fichier PDF, j'utilise l'API FindExecutable:

Private Const ERROR_FILE_NO_ASSOCIATION  As Long = 31 
Private Const ERROR_FILE_NOT_FOUND   As Long = 2 
Private Const ERROR_PATH_NOT_FOUND   As Long = 3 
Private Const ERROR_FILE_SUCCESS   As Long = 32 
Private Const ERROR_BAD_FORMAT    As Long = 11 

Private Declare Function FindExecutable Lib "shell32.dll" _ 
    Alias "FindExecutableA" _ 
    (ByVal lpFile As String, _ 
    ByVal lpDirectory As String, _ 
    ByVal sResult As String) As Long 


Private Sub OpenDocument(sFile as string, sPath as string) 
    Dim sResult As String 
    Dim lSuccess As Long, lPos as long 

    sResult = Space$(MAX_PATH) 
    lSuccess = FindExecutable(sFile, sPath), sResult) 
    Select Case lSuccess 
     Case ERROR_FILE_NO_ASSOCIATION 
      If Right$(sFile, 3) = "pdf" Then 
       MsgBox "You must have a PDF viewer such as Acrobat Reader to view pdf files." 
      Else 
       MsgBox "There is no registered program to open the selected file." & vbCrLf & sFile 
      End If 
     Case ERROR_FILE_NOT_FOUND: MsgBox "File not found: " & sFile 
     Case ERROR_PATH_NOT_FOUND: MsgBox "Path not found: " & sPath 
     Case ERROR_BAD_FORMAT:  MsgBox "Bad format." 
     Case Is >= ERROR_FILE_SUCCESS: 
      lPos = InStr(sResult, Chr$(0)) 
      If lPos Then sResult = Left$(sResult, lPos - 1) 
      Shell sResult & " " & sPath & sFile, True), vbMaximizedFocus 
    End Select 

End Sub 
+0

+1, intéressant. Par curiosité, pourquoi avez-vous choisi FindExecutable au lieu de ShellExecute? Les codes d'erreur que vous obtenez semblent très similaires, est-ce juste que vous faites ces vérifications avant d'essayer de lancer le fichier? Avez-vous eu des problèmes avec ShellExecute? L'utilisation de FindExecutable vous a aidé à vous déplacer? – Gavin

+0

FindExecutable effectue le travail de recherche du programme qui est enregistré pour s'exécuter en fonction d'une extension de fichier donnée. ShellExecute est idéal pour un appel execute et wait (au lieu de simplement Shell), mais il semble utiliser une méthode d'exécution plus brutale qui entraîne parfois une erreur. J'ai utilisé http://vbnet.mvps.org/index.html?code/system/findexecutable.htm comme source. C'est une ressource fantastique pour l'utilisation de l'API VB-6. –

1
  1. Désinstallez et réinstallez Lecteur Acrobat.
  2. Sous "Documents and Settings", renommez le dossier "username" en "usernamex" (vous devez être connecté avec un utilisateur administrateur différent).
  3. Se reconnecter en tant qu'utilisateur et crée un nouveau dossier "nom d'utilisateur" avec un nouveau registre d'utilisateurs.
  4. Maintenant, cela devrait fonctionner.

Vous pouvez copier des fichiers à partir du dossier UserNameX dans le nouveau dossier de nom d'utilisateur (Bureau, Documents, etc.)

0

est ici une fonction qui se traduit par une des fenêtres numéros d'erreur au texte. Vous pouvez utiliser la valeur de retour comme paramètre et récupérer un message plus convivial.

Private Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" _ 
    (ByVal dwFlags As Long, lpSource As Long, ByVal dwMessageId As Long, _ 
    ByVal dwLanguageId As Long, ByVal lpBuffer As String, _ 
    ByVal nSize As Long, ByVal Arguments As Any) As Long 

Private Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000 
Private Const FORMAT_MESSAGE_IGNORE_INSERTS = &H200 
Private Const MAX_PATH = 260 

Function TranslateDLLError(ByVal lngErrNum As Long) As String 
    Dim sRtrnCode As String * MAX_PATH 
    Dim lRet As Long 

    On Error GoTo errTranslateDLLError(

    sRtrnCode = Space$(256) 
    lRet = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS, 0&, lngErrNum, 0&, sRtrnCode, Len(sRtrnCode), 0&) 
    If lRet > 0 Then 
     Translate_DLL_Error = Replace$(Left(sRtrnCode, lRet), vbCrLf, "") 
    Else 
     Translate_DLL_Error = "Error not found." 
    End If 

    Exit Function 

errTranslateDLLError(: 
    TranslateDLLError(= "Unable to translate system error: " & CStr(lngErrNum) 

End Function 
-1

Essayez ceci. Vous devez associer le fichier PDF à un programme (tel qu'Acrobat x) pour lire des PDF, puis vous pouvez ouvrir des fichiers PDF avec ShellExecute.

+0

L'OP a dit qu'il a ouvert à partir d'Explorer. C'est déjà associé. – Deanna

1

J'ai eu le même problème et il n'était pas possible de changer le code VB6. Donc j'ai dû trouver une autre solution ...

Dans mon cas c'était un fichier avec l'extension ".xyz", mais en réalité c'était un fichier pour Microsoft Word, comme un fichier .doc. Lorsque vous double-cliquez pour la première fois, Windows demande à un programme d'ouvrir le fichier avec. Après cela, le double clic a bien fonctionné. Mais le ShellExecute n'a pas fait. Le problème est que ShellExecute effectue un "clic droit" -> "ouvrir" sur le fichier, et "ouvrir" n'existait pas dans le menu contextuel de mon fichier .xyz. Il y avait juste un "edit" ... Donc le ShellExecute a travaillé avec "edit", mais pas avec "open" comme deuxième paramètre.

Et parce que je n'étais pas capable de changer le code VB6, j'ai ouvert le registre avec regedit. Dans le chemin "HKEY_CLASSES_ROOT \ .doc" la valeur standard était "Word.Document.8", dans "HKEY_CLASSES_ROOT \ .xyz" il y avait juste "xyz_auto_file". J'ai donc simplement changé cette valeur en "Word.Document.8", et tout a parfaitement fonctionné. Maintenant, j'ai le même menu contextuel qu'avec un fichier .doc, quand je clique avec le bouton droit sur mon fichier .xyz.

Et aussi le ShellExecute fonctionne parfaitement ...

+1

Ceci est la même réponse [donnée par Anders] (http://stackoverflow.com/a/1194308/588306) – Deanna

1

J'ai eu le même problème avec un programme existant qui utilise le verbe open au lieu de NULL lorsque vous appelez la fonction ShellExecute. J'ai été en mesure de résoudre le problème en ajoutant le verbe open comme described here en utilisant l'éditeur de registre dans le gestionnaire .pdf (le mien était à HKEY_CLASSES_ROOT\pdf_auto_file). Je pense que c'est un problème dans le programme d'installation d'Adobe Reader qui n'ajoute parfois pas le verbe open lors de l'installation.

Voici l'exportation des valeurs de registre I ajouté:

[HKEY_CLASSES_ROOT\pdf_auto_file\shell\Open\command] 
@="\"C:\\Program Files\\Adobe\\Reader 11.0\\Reader\\AcroRd32.exe\" \"%1\"" 
1

j'ai rencontré le même problème que l'OP dans une application Visual Foxpro 9 compilé après la mise à jour de W7x64 à W10 version publique.

J'ai installé Adobe Acrobat ainsi qu'Adobe Reader. Changer l'association .pdf par défaut de Reader à Acrobat et ... Tout fonctionne!Revenir au lecteur avec l'échec d'origine (code d'erreur 31 - "Aucune application n'est associée à l'extension de nom de fichier donnée."). Beats moi, mais heureusement, je ne dois pas s'inquiéter. Je suis trop vieux pour m'inquiéter et exigera que tous les sites restent avec W7.

association travaille à partir soit explorateur de fichiers

1

Appeler une version Unicode (ShellExecuteW) à partir d'une commande qui ne supporte que ANSII, expérimenté avec une version récente de Inno Setup. ShellExecuteW a fonctionné pour certains arguments de chaîne ANSII mais dans ce cas pas le requis, renvoyant 2 (voir below).
En outre, dans ANSII ou Unicode, la fonction interne d'Inno ShellExec a également échoué avec le code 5 pour la raison que le processus de compilation avait toujours un handle ouvert au fichier.

Questions connexes