2011-03-31 84 views
24

Tengo una aplicación de VBA desarrollado en Excel 2007, y contiene el siguiente código para permitir el acceso a la función ShellExecute de Shell32.dll:¿Cómo debo hacer que mi código VBA sea compatible con Windows de 64 bits?

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 me dijeron:

Al parecer, la aplicación no se compilar en una versión de 64 bits de Windows (aún usando Office 2007 de 32 bits). I supone 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 este tiene algunas nuevas palabras clave que se pueden utilizar en la declaración Declare para permitir que funcione correctamente en Windows de 64 bits . VB7 también tiene nuevo compilador predefinido constantes para apoyar condicional compilación donde cualquiera va a utilizar la vieja o nueva declaración , dependiendo de si la aplicación se está ejecutando en 32 o 64 bits de Windows.

Sin embargo, como estoy atascado con Office 2007, necesito una solución alternativa. ¿Cuáles son mis opciones? (Me gustaría realmente prefiero no tener que liberar 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.

Respuesta

44

ya he encontrado con este problema en las personas el uso de mis herramientas in-house en las nuevas máquinas de 64 bits con Office 2010.

todo lo que tenía que hacer era cambiar las 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 

se quiere, por supuesto, quiere asegurarse de que la biblioteca está utilizando está disponible en ambas máquinas, pero hasta ahora nada 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 del bloque if.

code Appearance

Las aplicaciones que utilizan la compilación de código arriba y funcionar perfectamente en Office 2003, 2007, 2010 y 32 y 64 bits.

+1

Si el problema es la oficina de 64 bits, entonces VBA7 no es la respuesta. Necesitas la constante de compilación win64. VBA7 seguirá funcionando en Office 2010 de 32 bits. –

+2

@AnonymousType Estas instrucciones vienen precisamente de la documentación de MSDN en declaraciones VB7 y PtrSafe: http://msdn.microsoft.com/en-us/library/ee691831.aspx La necesidad de utilizar PtrSafe proviene del uso de VB7, no del uso de Office en un sistema de 64 bits. Es meramente una coincidencia que 64 sistemas solo admitan VB7, por lo que esto está matando a dos pájaros de un tiro. – Alain

+3

'#if Win64' solo se necesita en situaciones extrañas en las que realmente necesita cargar dos dlls diferentes o usar funciones con diferentes firmas en sistemas de 32 y 64 bits. Simplemente por hacer que las hojas de cálculo heredadas funcionen en máquinas de 64 bits que fuerzan a VB7, no es necesario. Office 2010 de 32 bits es intencionalmente compatible con todas las hojas de cálculo VB6 heredadas sin modificaciones (según la documentación). – Alain

4

Office 2007 tiene solo 32 bits, por lo que no hay ningún problema. 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 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 usted ¡enviar! ¿Solo piensas qué harías cuando informaran un error?

+0

gracias. El problema con "64-bit" fue informado por un colega, que luego abandonó el edificio, por lo que los detalles eran incompletos y, obviamente, llené los espacios en blanco erróneamente. –

+0

entonces, para aclarar ... ¿Mi enunciado Declare existente funcionará en Office 2007 en Windows de 32 y 64 bits? ¿Y funcionará en Office 2010 en Windows de 32 bits? Pero para Office 2010 en Windows de 64 bits, necesito usar las nuevas características de VB7, ¿y esto significa que necesito una versión de mi aplicación específica para 2010? ¿No hay forma de tener algo compatible con versiones anteriores que admita todas las versiones (como siempre ocurre con las versiones anteriores de Office)? –

+0

debería poder tener una única versión de su código pero realmente quiere probarlo usted mismo. –

0

Probablemente esta respuesta sea errónea en 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 Office 2010 modo de 32 bits, entonces es lo mismo que Office 2007. (El "problema" es Office que se ejecute 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 32/llamadas de 64 bits, cosas más notables que van mal o están utilizando longint (constante de tamaño en CLR) en lugar de IntPtr (dinámico homogéneos y con base en el valor de bits) para los "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 HWND se IntPtr (esto se debe a una HWND es un "mango", que es void*/"puntero nulo") 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).

Happy coding.


En cuanto a cualquier "nueva sintaxis", no tengo ni idea.

+0

La pregunta es VBA, creo. –

+0

@David Heffernan Gracias. Lo estaba confundiendo con VB.NET/VSTO. –

2

Uso PtrSafe y ver cómo funciona en Excel 2010.

errata corregida del libro "Microsoft Excel 2010 Programación de energía con 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 dos versiones de 32 y 64 bits

3

En realidad, la forma correcta de comprobar la plataforma de 32 o 64 bits es usar la constante Win64 que se define en todas las versiones de VBA (versiones de 16 bits, 32 bits y 64 bits).

#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 compilador constantes de

+0

que es el arco del sistema no Excel por cierto – HaveAGuess

+0

@HaveAGuess Según Microsoft [documentación] (https://msdn.microsoft.com/en-us/library/office/gg264421.aspx#Anchor_1) de hecho es la arquitectura de Office y no la arquitectura del sistema. Para citar el artículo: "La constante de compilación condicional de Win64 se utiliza para determinar qué versión (32 bits o 64 bits) de Office se está ejecutando". – pyskell

4

me encontré con este código (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 

fuente: http://www.cadsharp.com/docs/Win32API_PtrSafe.txt

+0

Gracias. Buen recurso. –

Cuestiones relacionadas