Vous êtes sur la page 1sur 8

Prototipando llamadas API desde PowerBuilder 7.0.x, 8.0.x, 9.0.x and 10.0.

x
Notas Tcnicas Relacionadas: http://www.sybase.com/detail?id=44545 http://www.sybase.com/detail?id=44648 http://www.sybase.com/detail?id=44474 http://www.sybase.com/detail?id=47705

Documentar las decenas de miles de llamadas a funciones API del entorno de Windows puede ser de mucha ayuda para los usuarios de PowerBuilder, pero documentarlas todas es casi imposible. Despus de cientos de consultas de usuario, el Soporte tcnico de Powersoft ha recopilado las siguientes sugerencias tcnicas para habilitar a los desarrolladores de PowerBuilder para traducir las llamadas a funciones estndar de Microsoft a la sintaxis de PowerBuilder, y para facultar a los desarrolladores para utilizar cualquier llamada a las API externas desde dentro de sus entornos PowerBuilder. La siguiente informacin le ayudar a traducir las llamadas Windows SDK, y as poder llamar una funcin API desde PowerBuilder, independientemente de la versin de PowerBuilder que est utilizando. Paso 1: Convertir una llamada API SDK a un llamada API PowerBuilder Lo primero que se necesita obtener es la sintaxis de la funcin que se convertir. Esto se puede obtener ya sea desde la biblia Windows API o desde MSDN (Microsoft Developers Network). Paso 2: Determinar si es que es una funcin o una Subrutina. Las llamadas a funcin retornar un valor; las subrutinas no. He aqu un ejemplo de una funcin Microsoft:
BOOL GetFileVersionInfo( LPTSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData );

He aqu un ejemplo de una subrutina Microsoft:


VOID GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer);

Paso 3: Convertir los tipos de datos de Microsoft a PowerBuilder. La tabla de equivalencias es la siguiente:
MICROSOFT Bool Char* Colorref Dword Handle Hdc Hfile Hinstance Hwnd PowerBuilder Boolean Ref String Ulong Ulong Ulong Ulong Ulong Ulong Ulong

Int Lparm Lpbyte Lpbword Lpstr,Lpststr Lpfiletime Lpint Lpvoid Mcierror Pbyte Short Structure Uint Void** Word Wparam

Int Ulong Ref Long Ref Ulong Ref String Ref Time Ref Long Ref Struct struct_inst Long Reg Long[#] Int Ref Struct Struct_inst Uint SUBROUTINE Ulong Ulong

Aunque la mayora de los tipos de datos estn listados arriba, pueden faltar algunos. En caso de dudas lea primero la descripcin del tipo de datos. Nota: Si la palabra Callback aparece como un tipo de datos, esta no puede ser ejecutado desde PowerBuilder, las rutinas Callback son funciones que son llamadas desde dentro de otras funciones. Paso 4: Codificar la funcin Global/Local External Function. He aqu una funcin Microsoft:
BOOL GetFileVersionInfo( LPTSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData );

La palabra BOOL representa un cdigo de retorno del tipo booleano , que se traduce como Boolean en PowerBuilder. LPCTSTR significa que es un puntero a una cadena (vea el paso 3). En PowerBuilder, simplemente utilice la palabra ref antes de declarar el string. Un argumento LPVOID indica que se est usando una estructura. En PowerBuilder, cree una estructura, asignndole una variable de instancia para que esta estructura pueda para por referencia. Como resultado, se puede derivar la siguiente declaracin de funcin: Ejemplo PowerBuilder
FUNCTION boolean GetFileVersionInfoA(ref string filename, ulong f_handle, ulong f_length, ref lpdata lpdata2) LIBRARY "version.dll"

Nota: En la seccin aspectos crticos listada a continuacin, recibir una explicacin ms detallada cuando se agrega una A a la funcin de 32 bit. Tambin puede encontrar una tcnica muy til para ayudar a localizar las llamadas a funciones dentro de las DDLs. Paso 5: Crear una Estructura

En este ejemplo en particular se necesita una estructura de manera que es posible que necesite informacin sobre que elementos estn contenidos dentro de esta estructura. El MSDN proporciona esta informacin ya que la funcin que est siendo llamada es una funcin Windows. En el MSDN la estructura aparece de la siguiente manera:
LPDATA = { DWORD dwSignature ; DWORD dwStrucVersion ; DWORD dwFileVersionMS ; DWORD dwFileVersionLS ; DWORD dwProductVersionMS ; DWORD dwProductVersionLS ; DWORD dwFileFlagsMask ; DWORD dwFileFlags ; DWORD dwFileOS ; DWORD dwFileType ; DWORD dwFileSubtype ; DWORD dwFileDateMS ; DWORD dwFileDateLS }

En PB se entrara dentro de la paleta de estructura y en este caso particular todos estos elementos se convertiran a ULONG. Si uno de estos elementos dentro de la estructura es una estructura anidad o rutina callback usted no ser capaz de usar esta funcin dentro de PB. En este caso la nica opcin se crear una DLL en C que sea haga la llamada a esta funcin y llamar entonces la funcin en C desde PB. Paso 6: Escribir el cdigo de la llamada a la Funcin. Ahora que se tiene la declaracin de la funcin, se necesita pasar los argumentos apropiados. Al tomar la funcin GetFileVersionInfoA que figura en el paso 4 se necesitara de los siguientes argumentos: En primer lugar necesita declarar los tipos de datos. Tenga en mente que los nombres de variables no tienen que coincidir necesariamente con la declaracin de la funcin listada en el paso 4.
boolean lb_rtn // Return code string ls_filename // 1st argument - filename ulong lu_hand // 2nd argument - f_handle ulong lu_len // 3rd argument - f_length lpdata lpdata2 // Last argument - assigning an instance of a structure.

Luego viene la parte mas difcil que es la asignacin de los valores a los argumentos. Esta parte puede requerir el uso del MSDN, biblia API o cualquier referencia que este disponible que cubra la funcin a la que se est llamando. En este caso particular la informacin est contenida dentro del MSDN. El primer argumento ls_filename, se debera establecer a la ruta y nombre de archivo del archivo de destino.
ls_filename = "c:\windows\calc.exe" // The calculator would be a good file to test against.

El Segundo argumento lu_hand de acuerdo al MSDN se ignora. Esto probablemente est reservado para que una futura versin de Windows la utilice. Para estar seguros, el argumento se debe fijar en nulo.
setnull(lu_hand)

El tercer argumento lu_len contiene el tamao del buffer de la informacin que ser devuelta dentro de el. Es crtico que el tamao no sea muy pequeo o que la informacin pueda desbordar en otra parte de la memoria causando un GPF o error Dr Watson. En este caso particular, debido a que la estructura contiene 13 elementos que son todos del tipo ulong, el numero de 256 debera ser suficiente para contener la informacin.
lu_len = 256

El ultimo argumento lpdata2 es una instancia de la estructura lpdata y es la que ser poblada por la llamada a la funcin. El script final aparecer entonces como sigue:
boolean lb_rtn string ls_filename ulong lu_hand, lu_len lpdata lpdata2 ls_filename = "c:\windows\calc.exe" // The calculator would be a good file to test against. setnull(lu_hand) lu_len = 256 lb_rtn = GetFileVersionInfoA(ls_filename, lu_hand, lu_len, lpdata2) // Viewing the output ------------------------------------------------------------sle_1.text = string(lpdata2.dwSignature) sle_2.text = string(lpdata2.dwStrucVersion) sle_3.text = string(lpdata2.dwFileVersionMS) sle_4.text = string(lpdata2.dwFileVersionLS) sle_5.text = string(lpdata2.dwProductVersionMS) sle_6.text = string(lpdata2.dwProductVersionLS) sle_7.text = string(lpdata2.dwFileFlagsMask) sle_8.text = string(lpdata2.dwFileFlags) sle_9.text = string(lpdata2.dwFileOS) sle_10.text = string(lpdata2.dwFileType) sle_11.text = string(lpdata2.dwFileSubtype) sle_12.text = string(lpdata2.dwFileDateMS) sle_13.text = string(lpdata2.dwFileDateLS) Messagebox("Return Code", string(lb_rtn)) // -----------------------------------------------------------------------------------------

Aspectos crticos a tener en cuenta fuera de lo tratado:

1.

Algunas funciones son sensibles a las mayculas. Finwdinwowa puede fallar mientras FindWindowA trabaja. 2. Todos los identificadores (handles) en PowerBuilder son ULONG. Utilizar los tipos de datos INT o LONG puede trabajar pero si siempre el identificar seala un rea de memoria alta en los dos ltimos tipos de datos pueden no ser capaces de soportar un nmero tan grande.

3. Asegrese que usted tiene el nombre de funcin correcto. Bajo Windows de 32 bits muchas de las funciones tienen una A (de ANSI). Microsoft nombr las funciones de esta manera para diferencias entre formato (A)-Ansi y (W)-Wide/Unicode. MSDN no siempre tiene una lista de nombres propios para las funciones. Por ejemplo: GetFileVersionInfo aparece como una funcin de 32 bits pero en realidad es GetFileVersionInfoA. 4. Declaracin de funciones Global versus Local. Si la funcin est declarada globalmente esta puede ser llamada desde cualquier lugar en su aplicacin. Si usted declara la funcin como Local External Function esta puede ser llamada nicamente desde la ventana donde es declarada. Las funciones locales utilizan menos recursos que las funciones globales pero las diferencias son muy pequeas. Mensajes de Error Comunes y que pueden Significar: 1. Error: Error opening DLL library <filename> for external function at line <line_number> in the <event name> event of object <object_name> of <window_name>. Posibles Causas: DLL es de 16 bit y es incompatible. DLL no est en el directorio de bsqueda. DLL est conectada a otra DLL que no puede ser encontrada. DLL tiene el mismo nombre de otra que ya est cargada en memoria. DLL est corrupta o en un formato incompatible.

2. Error: Error calling external function <function_name> at line <line_number> in the <event name> event of object <object_name> of <window_name>. Esto probablemente es el resultado de una incorrecta escritura del nombre de la funcin. Para asegurarse verifique que el nombre de la funcin coincide exactamente con el que est en la DLL, incluyendo maysculas y minsculas en el caso de letras. 3. . Error: Specified argument type differs from required argument type at runtime in DLL function <function_name>. (Invalid stack pointer on return from function call) at line <line_number> in <event_name> event of object <object_name> of <window_name>. Este error usualmente indica que el tipo de datos no coincide con el que se espera en la funcin DLL.

4. Receiving garbage from the DLL. i.e. Last name populated as: "*#^&Ryan" Este error es muy probablemente el resultado de que la alineacin de byte est fijada incorrectamente. PowerBuilder espera que le alineacin de byte est fijada en 1 y si usted est usando el compilador MSVC++ por defecto est fijado a 4. Para fijar la alineacin de byte a uno necesita hacer previamente lo siguiente antes de la compilacin a una DLL.

Seleccionar el destino deseado. Hacer clic con el botn secundario y seleccionar Settings (Configuracin) Seleccionar la lengeta C/C++. Seleccionar Code Generation (Generacin de Cdigo) desde la lista desplegable. Seleccionar la alineacin de byte deseada desde la lista desplegable Member Struct.

El switch en DOS para fijar la alineacin de byte a uno es: /ZP1. Un truco muy til para encontrar rpidamente funciones: Existen dos buenos programas para buscar funciones API de Window. 1. http://www.nirsoft.net/utils/dll_export_viewer.html 2. http://www.dependencywalker.com/

Notas Relacionadas: 47626 - External Functions Calls to the DLLs created using Visual C++ 44545 - 32 Bit - Windows API Calls for PowerBuilder 44588 - Dynamically Closing a Non-PowerBuilder Application 47705 - 32 Bit - Win95 and NT Functions - Kernel32.dll, User32.dll, Gdi32.dll 44474 - External Function Calls 44538 - Passing a 32-bit PowerBuilder structure to a 32-bit C DLL Created in Power++

Dynamically Closing a Non-PowerBuilder Application


The following information explains how to close any non-PowerBuilder application that is currently running by the use of API calls. Since PowerBuilder does not have the ability to close another application it is necessary to send a message to the Windows Operating System to find the handle to that application and then to send a destroy message to shut it down.

Declaring Global External Functions:

Note: Declaring a Global or Local Function. 16 Bit - Global/Local External Function Declaration : FUNCTION int SendMessage(uint whnd, uint wmsg,ulong wparam,long lparam) LIBRARY "user.exe" FUNCTION uint FindWindow(long classname, string windowname) LIBRARY "user.exe" Powerscript: string ls_wname uint l_handle, rtn ls_wname = "File Manager" l_handle = FindWindow(0,ls_wname) rtn = Send(l_handle,16,0,0)

Note: The window name is the exact text of what appears in the title bar of the application window. 32 Bit - Global/Local External Function Decl aration: FUNCTION long SendMessageA(ulong whnd,uint wmsg,ulong wParam,ulong lParam) Library "user32.dll" FUNCTION ulong FindWindowA(ulong classname,string windowname) Library "user32.dll" Powerscript: ulong l_handle

long rtn l_handle = FindWindowA(0,"File Manager") rtn = SendMessageA(l_handle,16,0,0)

Vous aimerez peut-être aussi