哪些原因可能导致ShellExecute失败?

时间:2009-07-28 12:47:59

标签: winapi file vb6 registry shellexecute

我有一个VB6应用程序,它使用以下命令打开带有相关应用程序的文件:

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

这完美无缺。

现在我有一个客户(使用Adobe Reader运行XP)无法使用上述命令打开任何PDF文件。但是从Windows资源管理器中双击它时,同一个文件正在打开而没有任何问题。我还在我的机器上测试了文件名/路径组合,以排除这些问题。

我正在搜索有关我可以检查的任何提示,以确保ShellExecute正在运行。或者是什么导致ShellExecute以这种方式失败?

13 个答案:

答案 0 :(得分:9)

ShellExecute的返回值是多少?如果它是0x0000001f(== 31,意思是SE_ERR_NOASSOC),那么根据shellapi.h “没有与之关联的应用程序 给定的文件扩展名。“,这意味着.pdf文件扩展名的注册以某种方式丢失。重新安装Adobe Reader可能有所帮助。

答案 1 :(得分:9)

继Thomas的answer之后,这里有一些VB6常量可能返回值ShellExecute,可能的解释(我想我最初是从MSDN page获取这些值,返回值部分) 。返回值为32或更小意味着呼叫失败。返回的具体值表明出了什么问题。

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. '

答案 2 :(得分:4)

你有“打开”作为动词,不要这样做,使用vbNullString作为动词(“打开”表示打开动词,NULL表示默认动词(如果用户没有设置特定默认值,则默认是开放的,如果该文件类型没有开放动词,ShellExecute使用它找到的第一个动词))

答案 3 :(得分:3)

查看ShellExecute来电的返回值。来自MSDN

  

如果函数成功,则返回大于32的值。如果函数失败,则返回指示失败原因的错误值。返回值被强制转换为HINSTANCE,以向后兼容16位Windows应用程序。然而,它不是真正的HINSTANCE。它只能转换为int并与32或以下错误代码进行比较。

     

0:操作系统内存或资源不足。

     

ERROR_FILE_NOT_FOUND:找不到指定的文件。

     

ERROR_PATH_NOT_FOUND:找不到指定的路径

     

(...)

答案 4 :(得分:3)

我没有使用ShellExecute来“执行”PDF文件,而是使用FindExecutable API:

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

答案 5 :(得分:1)

  1. 卸载并重新安装Acrobat Reader。
  2. 在“文档和设置”下,将“username”文件夹重命名为“usernamex”(您应该使用不同的管理员用户登录)。
  3. 以用户身份重新登录,并使用新的用户注册表创建一个新的“用户名”文件夹。
  4. 现在应该可以了。
  5. 您可以将文件从usernamex文件夹复制到新的用户名文件夹(桌面,文档等)

答案 6 :(得分:1)

如果您正在使用

CoInitializeEx(NULL, COINIT_MULTITHREADED)
在代码中

,那么你将不得不创建一个单独的线程来执行via ShellExecute的。 点击此处:Calling Shell Functions and Interfaces from a Multithreaded Apartment

答案 7 :(得分:1)

我遇到了同样的问题,无法更改VB6代码。所以我必须找到另一种解决方案......

在我的情况下,它是一个扩展名为“.xyz”的文件,但实际上它是Microsoft Word的文件,如.doc文件。

首次双击时,Windows会要求程序打开该文件。之后,双击工作正常。但ShellExecute没有。问题是,ShellExecute执行“右键单击” - >文件上“打开”,我的.xyz文件的上下文菜单中不存在“打开”。只有一个“编辑”......所以ShellExecute使用“编辑”,但没有使用“打开”作为第二个参数。

由于我无法更改VB6代码,因此我使用regedit打开了注册表。在路径“HKEY_CLASSES_ROOT \ .doc”中,标准值为“Word.Document.8”,在“HKEY_CLASSES_ROOT \ .xyz”中只有“xyz_auto_file”。所以我把这个值改成了“Word.Document.8”,一切都很完美。现在,当我右键单击.xyz文件时,我有与.doc文件相同的上下文菜单。

而且ShellExecute也能完美运行......

答案 8 :(得分:1)

我在调用ShellExecute函数时使用动词open而不是NULL的现有程序遇到了同样的问题。我能够通过使用注册表编辑器将open动词described here添加到.pdf处理程序(我的HKEY_CLASSES_ROOT\pdf_auto_file)来解决问题。我认为这是Adobe Reader安装程序中的一个问题,有时在安装过程中不会添加open动词。

以下是我添加的注册表值的导出:

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

答案 9 :(得分:1)

在从W7x64更新到W10公开发布版后,我在编译的Visual Foxpro 9应用程序中遇到了与OP相同的问题。

我安装了Adobe Acrobat以及Adobe Reader。将默认.pdf关联从Reader更改为Acrobat和......这一切都有效!在原始故障时更改回Reader(错误代码31 - “没有与给定文件扩展名关联的应用程序。”)。打败了我,但幸运的是我不必担心。我太老了,无法照顾,并要求所有网站都留在W7。

任何关联均可从文件资源管理器

进行

答案 10 :(得分:1)

从仅支持ANSII的命令调用Unicode版本(ShellExecuteW),使用最新版本的Inno Setup。 ShellExecuteW适用于某些ANSII字符串参数,但在这种情况下不是必需的参数,返回2(参见below)。
感兴趣的是,无论是ANSII还是Unicode,Inno的内部函数ShellExec也因代码5而失败,原因是编译过程仍然具有文件的打开句柄。

答案 11 :(得分:0)

这是一个将Windows错误号转换为文本的函数。您可以使用返回值作为参数,并获得更友好的消息。

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

答案 12 :(得分:-1)

试试这个。 您必须将PDF文件与任何程序(例如Acrobat x)相关联才能阅读PDF,然后您可以使用ShellExecute打开PDF文件。