Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Migration d'une application de la version 8.0 à la version 11.0
J'utilise les fonctions API Windows pour récupérer la version de l'application. Après, migration en 11, j'ai modifié la déclaration des fonctions comme suit :
FUNCTION ulong GetFileVersionInfoSize & ( REF string lpFilename, REF ulong lpdwHandle ) & LIBRARY "version.dll" alias for "GetFileVersionInfoSizeW"
Ma version est R5.2, avec la version 11 de PB, je récupère R5. (pas le 2)
J'ai aussi essayé la déclaration ci-dessous mais je ne récupère rien :
FUNCTION ulong GetFileVersionInfoSizeA & ( REF string lpFilename, REF ulong lpdwHandle ) & LIBRARY "version.dll" alias for "GetFileVersionInfoSizeA;Ansi"
Avez-vous déjà eu ce problème lié je pense du fait que le version 11, utilise de l'unicode (je suis en Windows 2000).
Cordialement.
Piliers
Hors ligne
FUNCTION ulong GetFileVersionInfoSize & ( REF string lpFilename, REF ulong lpdwHandle ) & LIBRARY "version.dll" alias for "GetFileVersionInfoSizeW;Ansi"
Hors ligne
L'ajout de ';Ansi', ne marche pas, j'avais déjà essayé, je ne récupère rien du tout. Alors qu'avec W tout seule, je récupère une partie de la version soit R5. au lieu de R5.2.
Auriez-vous une autre piste car toutes mes fonctions sont déclarées de la même manière avec W à la fin.
Piliers
Hors ligne
tu peux mettre tout le script d'appel ?
car il n'y a pas que cette fonction...
Hors ligne
La déclaration des fonctions :
FUNCTION ulong GetFileVersionInfoSize & ( REF string lpFilename, REF ulong lpdwHandle ) & LIBRARY "version.dll" alias for "GetFileVersionInfoSizeW" FUNCTION integer GetFileVersionInfo & ( REF string lpFilename, REF ulong lpdwHandle, ulong dwLen, & REF string lpData ) & LIBRARY "version.dll" alias for "GetFileVersionInfoW" FUNCTION boolean VerQueryValue & ( REF string lpBlock, string lpSubBlock, REF long lpBuffer, & REF uint puLen ) & LIBRARY "version.dll" alias for "VerQueryValueW" SUBROUTINE CopyMemory & ( REF string d, long s, long l ) & LIBRARY "kernel32.dll" & ALIAS FOR "RtlMoveMemory" FUNCTION int GetModuleFileName(& ulong hinstModule, & REF string lpszPath, & ulong cchPath) LIBRARY "kernel32" alias for "GetModuleFileNameW" Function Long URLDownloadToFile (& Long pCaller, & String szURL, & String szFileName, & Long dwReserved, & Long lpfnCB ) LIBRARY "urlmon.dll" & ALIAS FOR "URLDownloadToFileW" FUNCTION long SHFileOperation( & REF str_SHFILEOPSTRUCT lpFileOp ) & LIBRARY "SHELL32.DLL" & ALIAS FOR "SHFileOperationW" Function Boolean GetComputerName( & ref String name, & ref uLong len) & Library "Kernel32.DLL" alias for "GetComputerNameW" FUNCTION BOOLEAN FindClose( & ULONG FileHandle) & LIBRARY "kernel32.dll" ALIAS FOR "FindCloseW" FUNCTION LONG FindFirstFile( & STRING lpszSearchFile, & REF str_win32_find_data lpffd) & LIBRARY "kernel32.dll" & ALIAS FOR "FindFirstFileW" FUNCTION BOOLEAN FindNextFile( & ULONG handle, & REF str_win32_find_data str_results) & LIBRARY "kernel32.dll" & ALIAS FOR "FindNextFileW"
L'appel de ces fonctions pour le n° de version :
ulong dwHandle, dwLength string ls_Buff, ls_key, ls_versioninfo uint lui_length long ll_pointer string as_filename = "" integer li_rc string ls_Path unsignedlong lul_handle ls_Path = space(1024) lul_handle = Handle(GetApplication()) GetModuleFilename(lul_handle, ls_Path, 1024) as_filename = ls_Path //dwLength = GetFileVersionInfoSizeA( as_filename, dwHandle ) dwLength = GetFileVersionInfoSize( as_filename, dwHandle ) IF dwLength <= 0 THEN RETURN FALSE END IF ls_Buff = Space( dwLength ) //li_rc = GetFileVersionInfoA( as_filename, dwHandle, dwLength, ls_Buff ) li_rc = GetFileVersionInfo( as_filename, dwHandle, dwLength, ls_Buff ) Messagebox ("le buffer = ",ls_buff) IF li_rc = 0 THEN RETURN FALSE END IF // the strange numbers below represents the country and language // of the version ressource. ls_key = "\StringFileInfo\040904e4\ProductVersion" IF NOT VerQueryValue( ls_buff, ls_key, ll_pointer, lui_length ) OR & lui_length <= 0 THEN ls_versioninfo = "?" ELSE /// N° de version récupéré R5. au lieu de R5.2 ls_versioninfo = Space( lui_length ) CopyMemory( ls_versioninfo, ll_pointer, lui_length ) END IF os_version = ls_versioninfo return true
Merci de ton aide.
Piliers
Hors ligne
je teste ton script... vu que je suis actuellement sur pb11
Hors ligne
// HANDLE GetProcessHeap(VOID); // obtains a handle to the heap of the calling process Function ulong GetProcessHeap() Library "KERNEL32.DLL" // LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, DWORD dwBytes); // allocates a block of memory from a heap Function ulong HeapAlloc (ulong hMem, uint uFlags, ulong uBytes) Library "KERNEL32.DLL" // BOOL HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem); // frees a memory block allocated from a heap Function long HeapFree (ulong hMem, uint uFlags, ulong uMemPoint) Library "KERNEL32.DLL" // LPTSTR lstrcpy(LPTSTR lpString1, LPCTSTR lpString2); // copies a string to a buffer Function ulong lstrcpy (REF string lpString1, ulong lpString2) Library "KERNEL32.DLL" ALIAS FOR "lstrcpy;Ansi" // VOID MoveMemory (PVOID Destination, CONST VOID *Source, SIZE_T Length); // moves a block of memory from one location to another Subroutine MoveMemory (REF string sbytes, ulong lpbytes, ulong uLen) library "KERNEL32.DLL" alias for "RtlMoveMemory;Ansi" // DWORD GetFileVersionInfoSize( LPTSTR lptstrFilename, LPDWORD lpdwHandle); // returns the size, in bytes, of version information about a specified file Function long GetFileVersionInfoSize (string sFile, REF ulong uDummy) library "VERSION.DLL" alias for "GetFileVersionInfoSizeA;Ansi" // BOOL GetFileVersionInfo(LPTSTR lptstrFilename,DWORD dwHandle, DWORD dwLen, LPVOID lpData); // returns version information about a specified file Function long GetFileVersionInfo (REF string sFile, ulong uDummy, ulong uLen, ulong uPoint) library "VERSION.DLL" alias for "GetFileVersionInfoA;Ansi" // BOOL VerQueryValue( const LPVOID pBlock, LPTSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen); // returns selected version information from the specified version-information resource Function long VerQueryValue (ulong uPoint, string sValue, REF ulong uPoint, REF ulong uLen) library "VERSION.DLL" alias for "VerQueryValueA;Ansi" FUNCTION int GetModuleFileName(& ulong hinstModule, & REF string lpszPath, & ulong cchPath) LIBRARY "kernel32" alias for "GetModuleFileNameA;Ansi"
string ls_file, ls_query, ls_version, ls_langcodepage, ls_bytes = space(256) ulong ll_dummy, ll_size, hMem, lpInfo, lpPoint, ll_len long ll_ret int i, arr_int[4] char arr_hex[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'} string ls_Path unsignedlong lul_handle ls_Path = space(1024) lul_handle = Handle(GetApplication()) GetModuleFilename(lul_handle, ls_Path, 1024) ls_file = ls_path // return the number of bytes of the file information for ls_file ll_size = GetFileVersionInfoSize (ls_file, ll_dummy) // obtain handle to the process heap hMem = GetProcessHeap() // allocate the number of bytes needed to store version information on the heap lpInfo = HeapAlloc(hMem, 0, ll_size) // write the file version information to the allocated memory ll_ret = GetFileVersionInfo(ls_file, ll_dummy, ll_size, lpInfo) // lpPoint is a pointer to 4 bytes where the first two bytes // represent the language id and the last two bytes the code page // query the file information on the heap for language id and code page: ls_query = "\VarFileInfo\Translation" ll_ret = VerQueryValue(lpInfo, ls_query, lpPoint, ll_len) // copy the 4 bytes from the heap into a PowerBuilder storage location (ls_bytes) MoveMemory(ls_bytes, lpPoint, ll_len) // on an Intel computer, the little end is stored first (Little Endian) // this means a Hex word like 0x1234 (two bytes) is stored in memory as (0x34 0x12) // copy the 4 bytes into ASCII integers and perform byte swapping: arr_int[1] = asc(mid(ls_bytes, 2, 1)) arr_int[2] = asc(mid(ls_bytes, 1, 1)) arr_int[3] = asc(mid(ls_bytes, 4, 1)) arr_int[4] = asc(mid(ls_bytes, 3, 1)) // to query the FileVersion in a subsequent call to VerQueryValue // we need the language id and code page in a Hex string representation // for example, it may look like 040904E4 - as in: // 04------ = SUBLANG_ENGLISH_USA // --09---- = LANG_ENGLISH // ----04E4 = 1252 = Codepage for Windows:Multilingual // convert the 4 bytes of ASCII integers into a Hex string: for i=1 to 4 if arr_int[i] < 16 then ls_langcodepage = ls_langcodepage + '0' + arr_hex[arr_int[i] +1] else ls_langcodepage = ls_langcodepage + arr_hex[arr_int[i]/16 +1] + arr_hex[mod(arr_int[i], 16) +1] end if next // at this point we could also query for // CompanyName, FileDescription, InternalName, LegalCopyright // ProductName or ProductVersion by replacing the string literal FileVersion below // lpPoint is a pointer to the FileVersion string on the heap: ls_query = "\StringFileInfo\" + ls_langcodepage + "\FileVersion" ll_ret = VerQueryValue(lpInfo, ls_query, lpPoint, ll_len) // copy the version string into a PowerBuilder string location ls_version = space(255) lstrcpy(ls_version, lpPoint) // free the memory on the heap HeapFree(hMem, 0, lpInfo); messagebox("version applicatif",ls_version)
Hors ligne
J'ai remodifié les déclarations des fonctions, et je récupère maintenant un ?.
Piliers
Hors ligne
le code que j'ai mis fonctionne tres bien sur mon poste
Hors ligne
J'ai un souci sur la récupération de la version en ayant comme definition :
FUNCTION boolean VerQueryValueA &
( REF string lpBlock, string lpSubBlock, REF long lpBuffer, &
REF uint puLen ) &
LIBRARY "version.dll" alias for "VerQueryValueA;Ansi"
En script, j'ai cette fonction qui est à false en résultat avec :
ls_buff = è|4
ls_key = "\StringFileInfo\040904E4\ProductVersion"
ll_pointer = 0
lui_length = 0
bb_ret= VerQueryValueA( ls_buff, ls_key, ll_pointer, lui_length )
Je ne comprends pas, en reprenant le code du script, cela ne fonctionne pas non plus.
Si quelqu'un à une idée.
Piliers.
Hors ligne
t'es sur ?
moi, ca fonctionne à donf !
je suis sous pb11.0 xp pack1 .netframe 2.0 et sdk 2.0
en fait,
ls_query = "\StringFileInfo\" + ls_langcodepage + "\FileVersion"
fonctionne bien
mais avec "ProductVersion", ca ne fonctionne pas... pour l'exe de pb11.0
fais le test sur une dll de windows...
Hors ligne
Merci pour le code Krauser
J'ai aussi besoin d'afficher la version renseignée dans l'objet Project depuis mon appli.
J'ai d'abord testé le topic Question à propos des numéros de version de la section conseils pratiques mais ça ne fonctionnait pas du tout.
Par contre, ton code ramène bien la version du fichier exe de PB11.5.
Comme j'ai besoin de la version du fichier exe de mon appli dès son ouverture, j'ai remplacé
lul_handle = Handle(GetApplication()) GetModuleFilename(lul_handle, ls_Path, 1024) ls_file = ls_path
par
ls_file = This.AppName + ".exe"
Mais j'obtenais une version avec des caractères que mon clavier ne connaît même pas.
En débuggant avec les 2 codes ci dessus, je me suis aperçu que le problème vient de la variable ls_langcodepage.
Pour PB, elle prend la valeur 040904E4 alors que pour mon appli, elle prend la valeur 04091252.
Quand j'ai désactivé l'algo de la boucle FOR pour y mettre directement la valeur 040904E4, ça a fonctionnait nickel-chrome!
Sinon, ça pourrait être bien de placer ce code dans une autre section que Migration.
Hors ligne