13

我有一个 VB6 应用程序,它使用以下方法打开文件及其关联的应用程序:

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

这完美地工作。

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

我正在寻找任何关于我可以检查以确保ShellExecute工作正常的提示。或者是什么导致 ShellExecute 以这种方式失败?

4

13 回答 13

10

ShellExecute 的返回值是多少?如果它是 0x0000001f(== 31,意思是SE_ERR_NOASSOC),则根据 shellapi.h “没有与给定文件扩展名关联的应用程序”。,这意味着 .pdf 文件扩展名的注册不知何故丢失了。重新安装 Adob​​e Reader 可能会有所帮助。

于 2009-07-28T13:02:51.463 回答
10

除了 Thomas 的回答之外,这里有一些用于ShellExecute可能返回值的 VB6 常量,以及可能的解释(我想我最初是从 MSDN页面的返回值部分获取这些的)。返回值小于等于 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. '
于 2009-07-28T13:10:47.940 回答
5

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

于 2009-07-28T14:03:18.750 回答
3

看看你的ShellExecute调用的返回值。从MSDN

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

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

ERROR_FILE_NOT_FOUND: 指定的文件未找到。

ERROR_PATH_NOT_FOUND: 没有找到指定的路径

(...)

于 2009-07-28T13:09:48.610 回答
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
于 2009-07-30T20:07:37.343 回答
2

如果你正在使用

CoInitializeEx(NULL, COINIT_MULTITHREADED)

在您的代码中,那么您将必须创建一个单独的线程以通过 ShellExecute 执行。在此处查看更多信息:从多线程单元调用 Shell 函数和接口

于 2010-02-19T12:46:20.037 回答
1
  1. 卸载并重新安装 Acrobat Reader。
  2. 在“文档和设置”下,将“用户名”文件夹重命名为“用户名x”(您应该使用不同的管理员用户登录)。
  3. 以用户身份重新登录,它会使用新的用户注册表创建一个新的“用户名”文件夹。
  4. 现在它应该可以工作了。

您可以将文件从 usernamex 文件夹复制到新的用户名文件夹(桌面、文档等)

于 2009-11-25T07:56:02.400 回答
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 也可以完美运行...

于 2014-09-10T11:48:33.463 回答
1

open对于使用动词而不是NULL调用ShellExecute函数的现有程序,我遇到了同样的问题。我能够通过使用注册表编辑器将此处描述open的动词添加到处理程序中来解决问题(我的是 at )。我认为这是 Adob​​e Reader 安装程序中的一个问题,有时在安装过程中不会添加动词。.pdfHKEY_CLASSES_ROOT\pdf_auto_fileopen

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

[HKEY_CLASSES_ROOT\pdf_auto_file\shell\Open\command]
@="\"C:\\Program Files\\Adobe\\Reader 11.0\\Reader\\AcroRd32.exe\" \"%1\""
于 2015-03-04T17:41:26.833 回答
1

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

我安装了 Adob​​e Acrobat 以及 Adob​​e Reader。将默认的 .pdf 关联从 Reader 更改为 Acrobat 并且...一切正常!更改回 Reader 并出现原始故障(错误代码 31 -“没有与给定文件扩展名关联的应用程序。”)。打败我,但幸运的是我不必担心。我太老了,不在乎,将要求所有网站都使用 W7。

任何一个关联都可以从文件资源管理器中工作

于 2015-09-02T21:04:46.390 回答
1

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

于 2017-06-26T17:50:25.510 回答
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
于 2009-11-25T13:18:33.683 回答
-1

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

于 2012-05-10T14:24:21.437 回答