Newsgroup: it.comp.lang.c++
Titolo: versione di un programma

devo fare un programma in VisualC++ che installa un cd-rom multimediale, e
dunque deve controllare se sulla macchina è installato un browser e quale
versione.
ho due metodi possibili:
-con la FindExecutable() per vedere cosa è associato ai file html, ma poi
come faccio a ricavare la versione del programma avendo solo il nome del
file (tipo quando si clikka col destro e si sceglie il menu "proprieta" dal
gestione risorse)
-andando a curiosare nel registry, ma: cosa cercare? arrivo fino a
HKEY_LOCAL_MACHINE/software/ poi trovo le sottochiavi Microsoft e Netscape e
poi?
ogni versione del browser inserisce la versione in modo diverso e sotto
chiavi diverse, che sottochiave devo cercare per sapere quale versione è
installata (sia di IE che di Netscape)? e se nelle prossime versioni mi
cambiano ancora i nomi delle chiavi nel registry?
secondo voi qual'è la soluzione migliore?

-con la FindExecutable() per vedere cosa è associato ai file html...
La soluzione sta nel paradigma Document/View di Windows: bisogna pensare ad
oggetti !!! Tu non hai bisogno di sapere quale programma e' associato ai
file html per aprili (anche perche' potrebbe essere associato un editor come
Frontpage) ma devi sapere solo se esiste un browser sulla macchina, e quindi
aprire la pagina html che ti interessa. Sara' poi Windows a richiamare il
browser di default e visualizzare il tutto.
La funzione che ti serve e' quindi ShellExecute usata nel seguente modo:
LONG rc;
rc = ShellExecute(HWND_DESKTOP, "open", "index.html", NULL, NULL, SW_SHOW);
if (rc <= 32) {
    CHAR psz[MAX_PATH];
    lstrcpy(psz, "Impossibile eseguire il programma!");
    switch (rc) {
        case ERROR_FILE_NOT_FOUND:
            lstrcpy(psz, "Impossibile trovare il file specificato!");
            break;
        case ERROR_BAD_FORMAT:
            lstrcpy(psz, "Formato del file non riconosciuto!");
            break;
    }
    MessageBox(HWND_DESKTOP, psz, "Cd rom multimediale", MB_OK |
MB_ICONSTOP);
}
Ciao.
Stefano Tempesta
s.tem...@usa.net
--------------------------------
<<< Think indipendent,
cos' indipendent you can't be >>>

gestione risorse)
Attraverso l'associazione al filetype non hai solo il nome,
bensí il path completo; su quell'eseguibile puoi fare una
LoadLibrary, e sulla handle che da essa ottieni, la FindResource
sul tipo RT_VERSION, identificando e poi caricando la
risorsa di versione dell'eseguibile stesso.  Equivalentemente,
puoi ottenere queste stesse info con GetFileVersionInfo -- v.
la doc in linea relativamente al formato delle info che estrai.
Alex


Quello che sostieni è sicuramente vero in una situazione "ideale" dove tutti
i browser gestiscono le pagine HTML, gli script e le applet java nello
stesso modo; purtroppo non tutti i browser sono compatibili tra di loro e
non tutte le versioni dello stesso browser lavorano nello stesso modo! Può
essere necessario ricorrere ad alcuni "aggiustamenti" diversificando le
pagine per supportare al meglio più browser.
Per conoscere la versione del browser può utilizzare GetFileVersionInfo,
dopo aver recuperato il path dell'eseguibile.
Un'altra soluzione potrebbe essere quella di ricavare le informazioni
relative al browser attraverso javascript (che è supportato dalle ultime
versioni sia di IE che di Netscape) e gestire le eventuali incompatibilità
tra i browser direttamente all'interno delle pagine.
---
Valter Minute
min...@fortech.it
 (the reply address of this message is invalid)
---
Are you looking for a good freeware ScreenSaver? Try FOYD!
http://hotfiles.zdnet.com/cgi-bin/texis/swlib/hotfiles/getit.bin?fcode=000PZ
0
if you want, I can send you the (free) C++ source code.

 la doc in linea relativamente al formato delle info che estrai.
Vorrei fare solo una, anzi due, precisazioni:
1. GetFileVersionInfo funziona solo con file (eseguibili!) Win32, cioe'
sui file Win16 non lavora, questo puo' non essere un problema da poco
per cui la prima soluzione mi sembra piu' funzionale.
2. GetFileVersionInfo e' contenuta nella version.lib che VC non "linka"
per default, quindi bisogna aggiungerla.
 2.1 Menu Projects->Settings
 2.2 Nella edit di Object/Library Modules della linguetta link
     aggiungere version.lib
--
Posted from [194.184.159.36]
via Mailgate.ORG Server - 
http://www.mailgate.org

larisorsa di versione dell'eseguibile stesso.
ciao Alex, ho provato a fare come mi hai detto ma ho dei problemi con la
LoadLibrary(),
quando la chiamo con il nome dell'explorer o del netscape come parametro mi
dà questo errore (con la GetLastError()):
ERROR_BAD_FORMAT (An attempt was made to load a program with an incorrect
format.)
cosa può voler dire? nell'help della LoadLibrary c'è scritto nei Remarks:
Windows 95: If you are using LoadLibrary to load a module that contains a
resource whose numeric identifier is greater than 0x7FFF, LoadLibrary fails.
può essere questa la causa dell'errore nella LoadLibrary? perchè ho provato
a fare la LoadLibrary anche su altri files (tipo la calcolatrice di win e il
paint) e funziona, ma su altri mi da questo ERROR_BAD_FORMAT.
questo è il codice che ho scritto:
 char nomeFileBrowser[_MAX_PATH];
 HINSTANCE nResult=FindExecutable("test.html","",nomeFileBrowser);
 switch ((int)nResult){
 case 0:
  MessageBox("OutOfMemory!");
  break;
 case 31:
  MessageBox("No associacion for .html files");
  break;
 case ERROR_FILE_NOT_FOUND:
  MessageBox("file test.html not found");
  break;
 case ERROR_PATH_NOT_FOUND:
  MessageBox("path not found");
  break;
 case ERROR_BAD_FORMAT:
  MessageBox("invalid file format");
  break;
 default:
  //trovato un browser
  CString stringa="Browser found: ";
  stringa+=(LPCTSTR)nomeFileBrowser;
  //cerco la versione del browser
  HMODULE hBrowserModule=LoadLibrary((LPCTSTR)nomeFileBrowser);
  if (!hBrowserModule){
   DWORD dwErrore=GetLastError();
   char ErrorString[50];
   wsprintf(ErrorString,"errore numero %d nella LoadLibrary()",dwErrore);
   MessageBox(ErrorString);
  };
  HRSRC hVersion=FindResource(hBrowserModule,"ProductVersion",RT_VERSION);
  if (!hVersion){
   DWORD dwErrore=GetLastError();
   char ErrorString[50];
   wsprintf(ErrorString,"errore numero %d nella FindResource()",dwErrore);
   MessageBox(ErrorString);
  };
e poi un'altra cosa: non sono sicuro del terzo parametro della FindResource,
è giusto quello che ho messo, cioè la stringa "productVersion"?
c ya!
/\/\etal Dave
<<<<<< 
DucaCr...@iol.it
 >>>>>>>>
--
Posted from [195.99.97.2]


dopo aver recuperato il path dell'eseguibile.
ho provato anche questa soluzione ma ho incontrato dei problemi (te
pareva... sgrunt!)...
ecco il codice che ho scritto:
  DWORD ParametroInutile, dwBufferSize;
dwBufferSize=GetFileVersionInfoSize((LPSTR)nomeFileBrowser,&ParametroInutile
);
  if (dwBufferSize!=0){
       // info sul file
       LPVOID InfoBuffer=malloc(dwBufferSize);
GetFileVersionInfo((LPTSTR)nomeFileBrowser,ParametroInutile,dwBufferSize,Inf
oBuffer);
       VS_FIXEDFILEINFO FileInfoStruct;
       UINT structLen;
       if
(VerQueryValue(InfoBuffer,"\\",(LPVOID*)&FileInfoStruct,&structLen)==0)
            MessageBox("Errore nella VerQueryValue()");
       char infoString[100];
       wsprintf(infoString,"Product version:
%d",&FileInfoStruct.dwProductVersionMS);
       MessageBox(infoString);
  }
la api che mi da problemi è la VerQueryValue perchè a quanto sembra non
riempie la struttura FileInfoStruct in modo corretto.
Dal debug ho visto che l'unico campo che viene modificato di questa
struttura è il primo (cioè FileInfoStruct.dwSignature) mentre gli altri non
vengono toccati e quindi contengono valori casuali... eppure la la API in
questione non genera errore perchè la MessageBox("Errore nella
VerQueryValue()") non viene eseguita.
mi sa che è un errore stupido, ma non riesco a trovarlo...  (please
aiutatemi!!!)
Guardando i campi della struttura VS_FIXEDFILEINFO mi è venuto qualche
dubbio sui campi che contengono la versione del programma: i due campi
dwProductVersionMS e dwProductVersionLS dovrebbero contenere un numero di
64-bit che rappresenta il "binary version number" del programma.... io come
faccio da questi due campi a capire quale versione di netscape o explorer
sto analizzando? (del tipo versione 3 o versione 4...)
grazie anticipate a tutti per la considerazione e per la pazioenza che
dovete avete per sopportare tutte queste mie domande!
;-)



Attenzione: Non ho la possibilità di verificare l'affermazione che segue,
quindi la possibilità che si riveli una vaccata sono ancora più alte che nei
miei messaggi abituali....
Credo che la parte alta del numero riporti la "Major release" del programma
(se vale 4 con IE4 e 3 con IE3, la mia teoria si rafforza....) mentre la
parte bassa è riferita alla "subrelease" (ex: IE 4.01, Netscape 4.0x...).
Prova a verificare (good luck!).
Il numero di versione è comunque memorizzato in formato in una delle chiavi
contenute all'interno del buffer che ti è stato tornato dalla
GetFileVersionInfo (non ho sottomano la documentazione....).



Ciao non sono Alex, ma spero di poterti aiutare.
Il primo problema  e' proprio nella FindResource, il terzo parametro
e' il nome della risorsa non il nome del campo della risorsa!
Questo significa che devi conoscere il nome e' questo lo puoi fare con
EnumResourceNames, poi il valore ritornato da FindResource devi usarlo
con
LoadResource (secondo problema).
Poi hai l'accesso a VS_VERSION_INFO che e' una pseudo-struttura su cui
e'
piu' facile lavorare con incrementi di puntatore.
Finalmente puoi accedere a una VS_FIXEDFILEINFO che contiene l'agognata
versione del file.
Allego una funzione che puoi richiamare dal tuo codice con la seguente
sintassi:
VS_FIXEDFILEINFO vs_ver;
if (GetFileVerNumber(hBrowserModule, &vs_ver))
  ok
else
  che guaio
Il codice dovrebbe (condizionale perche' non lo compilata!!) essere
usato
sotto MFC dato che ci sono delle TRACE che ti aiutano a capire come
determinare
la versione, pero' con un minimo sforzo gira sotto qualunque compilatore
C (non
necessariamente C++) e sotto qualunque framework.
Per eventuali dubbi puoi rispondere oppure consultare la documentazione.
Vado di corsa e non posso darti troppi dettagli, pero' se me li chiedi
saro' per lieto di risponderti dal NG.
Ciao
 Davide Ficano
BOOL CALLBACK GetVersionProc(HANDLE hModule, LPCTSTR lpszType, 
                             LPTSTR lpszName, LONG lParam)
{
    *((LPTSTR*) lParam) = lpszName;
 
    return TRUE;
}
BOOL GetFileVerNumber(HINSTANCE hInst, VS_FIXEDFILEINFO* pFFI)
{
    LPTSTR pRes;
    HRSRC hResVer;
    HGLOBAL hMem;
    LPWORD pVer;
    // Trova il nome della risorsa RT_VERSION
    if (!EnumResourceNames(hInst, RT_VERSION, 
                            (ENUMRESNAMEPROC)GetVersionProc,
(LONG)&pRes))
        return FALSE;
 
    if (NULL == (hResVer = FindResource(hInst, pRes, RT_VERSION)))
        return FALSE;
    hMem = LoadResource(hInst, hResVer);
    pVer = (LPWORD)LockResource(hMem);
    WORD wLength = *pVer++;
    WORD wValueLength = *pVer++;
    WORD wType = *pVer++;
    // Salta la stringa
    LPWSTR wstr = pVer;
    if(0 != lstrcmpW(wstr, L"VS_VERSION_INFO"))
        return FALSE;
    pVer = (LPWORD)(wstr + sizeof ("VS_VERSION_INFO"));
    TRACE("%d, %d\n", wValueLength, sizeof (VS_FIXEDFILEINFO));
    pFFI = (VS_FIXEDFILEINFO*)(pVer + 1);
    int VerLow  = LOWORD(pFFI->dwFileVersionMS);
    int VerHigh = HIWORD(pFFI->dwFileVersionMS);
    TRACE("Versione file %d.%d\n", VerHigh, VerLow);
    return TRUE;
}
--
Posted from [194.184.159.36]


GetFileVersionInfo (non ho sottomano la documentazione....).
ho scoperto come funziona.... prima di raccontarvelo tiro una smadonnata
contro la documentazione del VC++ che ha nascosto per bene queste info....
(sgrunt)
la "binary version" è memorizzata nella struttura in due campi di tipo DWORD
(32-bit ciascuno) ma in realtà sono 4 numeri di 16-bit che rappresentano la
versione nella forma x1.x2.x3.x4
grazie a tutti per l'aiuto!!!!
(temo che sentirete ancora molte mie domande durante il prossimo
mesetto....)
c ya!
/\/\etal Dave.
<<<<<<<<< 
DucaCr...@iol.il
 >>>>>>>>
--
Posted from [195.99.97.2]


Ecco un programmino-giocattolo che
potrebbe farti comodo:
#include <stdio.h>
#include <windows.h>
int showVer(const char* prog);
int main(int args, char* argv[]) {
    for(int i=1; i<args; ++i)
        showVer(argv[i]);
    return 0;
}
int err(const char* msg)
{
    DWORD dw = GetLastError();
    printf("%s (%d)\n", msg, dw);
    return 0;
}
int
showVer(const char* prog)
{
    printf("Examining (%s)\n", prog);
    DWORD boh;
    DWORD siz = GetFileVersionInfoSize((char*)prog, &boh);
    if(!siz)
        return err("Cannot find version-info");
    printf("size=%d ", siz);
    void* buf = malloc(siz);
    BOOL res = GetFileVersionInfo((char*)prog, boh,
        siz, buf);
    if(!res)
        return err("Cannot get version-info");
    printf("gfvi ");
    void* pv = 0;
    UINT len = 0;
    res = VerQueryValue(buf, "\\", &pv, &len);
    if(!res)
        return err("Cannot query root value");
    printf("len=%d\n", len);
    VS_FIXEDFILEINFO* pin = (VS_FIXEDFILEINFO*)pv;
    DWORD sig = pin->dwSignature;
    printf("signature=%x ", sig);
    if(sig != 0xFEEF04BD) {
        printf("???\n");
        return 0;
    }
    printf("Ok\n");
    printf("File version: %x - %x\n",
        pin->dwFileVersionMS,
        pin->dwFileVersionLS);
    printf("Prod version: %x - %x\n",
        pin->dwProductVersionMS,
        pin->dwProductVersionLS);
    return 1;
}
(Confermo, come altri hanno gia` ricordato e
mi ero scordato di dire, che va linkato con la
version.lib).
Questo e' il suo output facendogli esaminare
l'Internet Explorer 4, ultimissimo release e SP,
su Windows NT 4.0 idem idem:
Examining (C:\PROGRA~2\Plus!\MICROS~1\iexplore.exe)
size=2286 gfvi len=52
signature=feef04bd Ok
File version: 40048 - c260000
Prod version: 40048 - c260000
Le Properties|Version dello stesso eseguibile
danno una "File Version" di "4.72.3110.0", con
le quattro halfword in corrispondenza con le
halfword delle versioni suddette (4, 0x0048=72,
0x0c26=3110, 0=0).
Girando lo stesso giocattolino su netscape.exe
corrispondente a Navigator 4.05, si hanno
version di 40005 - 10030 (e infatti, da Explorer,
si vede 4.5.1.48 per lo stesso eseguibile).
Alex