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

发布于 2024-07-30 01:11:55 字数 365 浏览 8 评论 0原文

我有一个 VB6 应用程序,它使用关联的应用程序打开文件:

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

这工作得很好。

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

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

I have a VB6 application which opens files with their associated application using:

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

This works perfectly.

Now I got a customer (running XP with Adobe Reader) who can't open any PDF file using the above command. But the same file is being opened without any problems when double clicking it from Windows Explorer. I also tested the filename/-path combination on my machine to exclude those kind of problems.

I'm searching for any hints on what I could check to make sure ShellExecute is working. Or what can cause ShellExecute to fail this way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

紫竹語嫣☆ 2024-08-06 01:11:55

根据 Thomas 的答案,这里有一些可能返回的 VB6 常量ShellExecute 的值,以及可能的解释(我我想我最初是从 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. '

Further to Thomas's answer, here's some VB6 constants for possible return values of ShellExecute, with possible explanations (I think I originally took these from the MSDN page, return value section). A return value of 32 or less means the call failed. The specific value returned indicates what went wrong.

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. '
橘和柠 2024-08-06 01:11:55

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

You have "open" as the verb, don't do that, use vbNullString as the verb ("Open" means the open verb, NULL means the default verb (If the user has not set a specific default, the default is open, if there is no open verb for that filetype, ShellExecute uses the first verb it finds))

零度℉ 2024-08-06 01:11:55

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

What's the return value of ShellExecute? If it's 0x0000001f (== 31, meaning SE_ERR_NOASSOC), than according to shellapi.h "There is no application associated with
the given file name extension."
, which means that somehow the registration of the .pdf file extension got lost. Reinstalling Adobe Reader might help.

李白 2024-08-06 01:11:55

查看 ShellExecute 调用的返回值。 来自 MSDN

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

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

ERROR_FILE_NOT_FOUND:找不到指定的文件。

ERROR_PATH_NOT_FOUND:找不到指定的路径

(...)

Have a look at the return value of your ShellExecute call. From the MSDN:

If the function succeeds, it returns a value greater than 32. If the function fails, it returns an error value that indicates the cause of the failure. The return value is cast as an HINSTANCE for backward compatibility with 16-bit Windows applications. It is not a true HINSTANCE, however. It can be cast only to an int and compared to either 32 or the following error codes below.

0: The operating system is out of memory or resources.

ERROR_FILE_NOT_FOUND: The specified file was not found.

ERROR_PATH_NOT_FOUND: The specified path was not found

(...)

放肆 2024-08-06 01:11:55

我没有使用 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

Instead of using ShellExecute to 'execute' the PDF file, I use the 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
暮光沉寂 2024-08-06 01:11:55

如果您在代码中使用

CoInitializeEx(NULL, COINIT_MULTITHREADED)

,那么您将必须创建一个单独的线程来执行
Shell执行。
请在此处查看更多信息:调用 Shell 函数和接口来自多线程单元

If you're using

CoInitializeEx(NULL, COINIT_MULTITHREADED)

in your code, then you will have to create a separate thread for executing via
ShellExecute.
See more here: Calling Shell Functions and Interfaces from a Multithreaded Apartment

从﹋此江山别 2024-08-06 01:11:55
  1. 卸载并重新安装 Acrobat Reader。
  2. 在“文档和设置”下,将“用户名”文件夹重命名为“usernamex”(您应该使用不同的管理员用户登录)。
  3. 以用户身份重新登录,它会创建一个带有新用户注册表的新“用户名”文件夹。
  4. 现在应该可以了。

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

  1. Uninstall and reinstall Acrobat Reader.
  2. Under "Documents and Settings", rename "username" folder to "usernamex" (you should be logged in with different admin user).
  3. Relogin as user and it creates a new "username" folder with a new user registry.
  4. Now it should work.

You can copy files from the usernamex folder to the new username folder (Desktop, Documents, etc.)

谷夏 2024-08-06 01:11:55

我也遇到过同样的问题,并且无法更改 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 也运行得很好......

I've had the same problem and it was not possible to change the VB6-Code. So I had to find another solution...

In my case it was a file with the extension ".xyz", but in reality it was a file for Microsoft Word, like a .doc-file.

When doubleclicking for the first time, Windows asks for a programm to open the file with. After that the doubleclick worked fine. But the ShellExecute didn't. The problem is, that the ShellExecute performs a "right click" -> "open" on the file, and "open" didn't exist in the context menu on my .xyz-file. There was just an "edit"... So the ShellExecute worked with "edit", but not with "open" as the second parameter.

And because I was not able to change the VB6-code, I opened the registry with regedit. In the Path "HKEY_CLASSES_ROOT\.doc" the standard-value was "Word.Document.8", in "HKEY_CLASSES_ROOT\.xyz" there was just "xyz_auto_file". So I changed just this value into "Word.Document.8", and everything worked perfectly. Now I have the same context menu as with a .doc-file, when I right-click on my .xyz-file.

And also the ShellExecute works perfectly...

银河中√捞星星 2024-08-06 01:11:55

我对现有程序遇到了同样的问题,该程序在调用 ShellExecute 函数。 我能够通过添加 open 动词来解决问题,例如 此处描述,使用注册表编辑器进入 .pdf 处理程序(我的位于 HKEY_CLASSES_ROOT\pdf_auto_file)。 我认为这是 Adob​​e Reader 安装程序中的一个问题,有时在安装过程中未添加 open 动词。

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

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

I had the same issue with an existing program that is using the verb open instead of NULL when calling the ShellExecute function. I was able to fix the problem by adding the open verb like described here using the registry editor into the .pdf handler (mine was at HKEY_CLASSES_ROOT\pdf_auto_file). I think this is a problem within the Adobe Reader installer that is sometimes not adding the open verb during installation.

Here is the export of the registry values I added:

[HKEY_CLASSES_ROOT\pdf_auto_file\shell\Open\command]
@="\"C:\\Program Files\\Adobe\\Reader 11.0\\Reader\\AcroRd32.exe\" \"%1\""
温柔戏命师 2024-08-06 01:11:55

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

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

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

I encountered the same problem as the OP within a compiled Visual Foxpro 9 application after updating from W7x64 to W10 public release.

I have Adobe Acrobat installed as well as Adobe Reader. Changing the default .pdf association from Reader to Acrobat and... It all works! Changing back to Reader with original failure (error code 31 - "There is no application associated with the given file-name extension."). Beats me, but fortunately I don't have to worry. I'm too old to care and will require all sites to stay with W7.

Either association works from file explorer

幸福还没到 2024-08-06 01:11:55

从仅支持 ANSII 的命令调用 Unicode 版本 (ShellExecuteW),在最新版本的 Inno Setup 中体验过。 ShellExecuteW 适用于某些 ANSII 字符串参数,但在本例中不是必需的参数,返回 2(请参阅下面的)。
有趣的是,无论是 ANSII 还是 Unicode,Inno 的内部函数 ShellExec 也失败,代码为 5,因为编译过程仍然有该文件的打开句柄。

Calling a Unicode version (ShellExecuteW) from an command which only supports ANSII, experienced with a recent version of Inno Setup. ShellExecuteW worked for some ANSII string arguments but in this case not the required one, returning 2 (see below).
As a matter of interest, in either ANSII or Unicode, Inno's internal function ShellExec also failed with code 5 for the reason the compiling process still had an open handle to the file.

醉酒的小男人 2024-08-06 01:11:55

这是一个将 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

Here's a function that translates a the windows error numbers to text. You can use the return value as the parameter and get back a more friendly message.

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
浪菊怪哟 2024-08-06 01:11:55

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

Try this.
You have to associate the PDF file with any program (such as Acrobat x) to read PDF's, then you can open PDF files with ShellExecute.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文