excel - sistemas - private declare function showwindow lib user32 64 bit
¿Cómo debo hacer que mi código VBA sea compatible con Windows de 64 bits? (7)
En realidad, la forma correcta de verificar la plataforma de 32 o 64 bits es usar la constante Win64 que se define en todas las versiones de VBA (versiones de 16 bit, 32 bit y 64 bit).
#If Win64 Then
'' Win64=true, Win32=true, Win16= false
#ElseIf Win32 Then
'' Win32=true, Win16=false
#Else
'' Win16=true
#End If
Fuente: VBA ayuda en las constantes del compilador
Tengo una aplicación VBA desarrollada en Excel 2007 y contiene el siguiente código para permitir el acceso a la función ShellExecute
desde Shell32.dll
:
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Originalmente dije:
Aparentemente, la aplicación no se compilará en una versión de 64 bits de Windows (aún usando Office 2007 de 32 bits). Supongo que esto se debe a que la declaración
Declare
necesita actualización.He leído que Office 2010 introdujo un nuevo tiempo de ejecución de VBA (VB7) y que tiene algunas palabras clave nuevas que se pueden usar en la declaración
Declare
para permitir que funcione correctamente en Windows de 64 bits. VB7 también tiene nuevas constantes de compilador predefinidas para admitir la compilación condicional donde se usará la declaración anterior o la nueva, dependiendo de si la aplicación se está ejecutando en Windows de 32 o 64 bits.Sin embargo, dado que estoy atrapado con Office 2007, necesito una solución alternativa. ¿Cuáles son mis opciones? (Realmente preferiría no tener que lanzar 2 versiones separadas de mi aplicación si es posible).
Sin embargo, según la respuesta de David a continuación, me equivoqué acerca de las circunstancias en las que mi declaración Declare
no funcionará. Las únicas circunstancias en las que no funcionará son Office 2010 de 64 bits en Windows de 64 bits. Entonces, Office 2007 no es un problema.
Encontré este código (tenga en cuenta que algunos Long
se cambian a LongPtr
):
Declare PtrSafe Function ShellExecute Lib "shell32.dll" _
Alias "ShellExecuteA" (ByVal hwnd As LongPtr, ByVal lpOperation As String, _
ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As _
String, ByVal nShowCmd As Long) As LongPtr
Office 2007 tiene solo 32 bits, por lo que no hay problema allí. Sus problemas surgen solo con Office 64 bit que tiene versiones de 32 y 64 bits.
No puede esperar admitir usuarios con Office 2010 de 64 bits cuando solo tiene Office 2007. La solución es actualizar.
Si el único Declare
que tiene es ese ShellExecute
entonces no tendrá mucho que hacer una vez que obtenga Office de 64 bits, ¡pero no es realmente viable apoyar a los usuarios cuando no puede ejecutar el programa que envía! ¿Solo piensas qué harías cuando informaran un error?
Para escribir para todas las versiones de Office, use una combinación de las nuevas Constantes de compilador condicional de VBA7 y Win64.
VBA7
determina si el código se está ejecutando en la versión 7 del editor de VB (versión de VBA incluida en Office 2010+).
Win64
determina qué versión (32 bits o 64 bits) de Office se está ejecutando.
#If VBA7 Then
''Code is running VBA7 (2010 or later).
#If Win64 Then
''Code is running in 64-bit version of Microsoft Office.
#Else
''Code is running in 32-bit version of Microsoft Office.
#End If
#Else
''Code is running VBA6 (2007 or earlier).
#End If
Consulte el artículo de soporte de Microsoft para obtener más detalles.
Use PtrSafe y vea cómo funciona en Excel 2010.
Error ortográfico corregido del libro "Microsoft Excel 2010 Power Programming with VBA".
#If vba7 and win64 then
declare ptrsafe function ....
#Else
declare function ....
#End If
val (application.version)> 12.0 no funcionará porque Office 2010 tiene versiones de 32 y 64 bits
Ya he encontrado este problema en personas que usan mis herramientas internas en nuevas máquinas de 64 bits con Office 2010.
todo lo que tenía que hacer era cambiar líneas de código como este:
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
(ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
A esto:
#If VBA7 Then
Private Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
(ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
#Else
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
(ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
#End If
Por supuesto, querrá asegurarse de que la biblioteca que está utilizando esté disponible en ambas máquinas, pero hasta ahora nada de lo que he usado ha sido un problema.
Tenga en cuenta que en el antiguo VB6, PtrSafe ni siquiera es un comando válido, por lo que aparecerá en rojo como si tuviera un error de compilación, pero en realidad nunca dará un error porque el compilador omitirá la primera parte de el bloque if.
Las aplicaciones que usan el código anterior se compilan y se ejecutan perfectamente en Office 2003, 2007 y 2010 32 y 64 bit.
Es probable que esta respuesta esté equivocada al equivocar el contexto . Creo que VBA ahora se ejecuta en el CLR estos días, pero no es así. En cualquier caso, esta respuesta puede ser útil para alguien . O no.
Si ejecuta el modo Office 2010 de 32 bits, es lo mismo que Office 2007. (El "problema" es que Office se ejecuta en modo de 64 bits). Es la fragilidad del contexto de ejecución (VBA / CLR) lo que es importante aquí y la bitidez del VBA / CLR cargado depende de la bitidez del proceso de host.
Entre llamadas de 32/64 bits, las cosas más notables que salen mal son el uso de int
o long
(CLR de tamaño constante) en lugar de IntPtr
(tamaño dinámico basado en bitness) para "tipos de puntero".
La función ShellExecute tiene una firma de:
HINSTANCE ShellExecute(
__in_opt HWND hwnd,
__in_opt LPCTSTR lpOperation,
__in LPCTSTR lpFile,
__in_opt LPCTSTR lpParameters,
__in_opt LPCTSTR lpDirectory,
__in INT nShowCmd
);
En este caso, es importante que HWND sea IntPtr
(esto se debe a que un HWND es un "MANGO" que es void*
/ "puntero vacío") y no long
. Ver pinvoke.net ShellExecute como un ejemplo. (Mientras que algunas "soluciones" son confusas en pinvoke.net, es un buen lugar para mirar inicialmente).
Feliz codificación.
En cuanto a cualquier "nueva sintaxis", no tengo idea.