我有一个VB6应用程序,它使用以下命令打开带有相关应用程序的文件:
ShellExecute(0, "open", filename, params, vbNullString, vbNormalFocus)
这完美无缺。
现在我有一个客户(使用Adobe Reader运行XP)无法使用上述命令打开任何PDF文件。但是从Windows资源管理器中双击它时,同一个文件正在打开而没有任何问题。我还在我的机器上测试了文件名/路径组合,以排除这些问题。
我正在搜索有关我可以检查的任何提示,以确保ShellExecute
正在运行。或者是什么导致ShellExecute以这种方式失败?
答案 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)
您可以将文件从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文件。