[Win32] Software compatibel maken met Vista en XP

Pagina: 1
Acties:

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 17-09 18:11
Ik maak in mijn software gebruik van File Open/Save vensters en dat deed ik dus eerst met GetSaveFileName.
In Vista is er echter best veel aangepast aan deze vensters, en om de nieuwe functionaliteit te gebruiken moet je dan ook de IFileDialog interface gebruiken.
Het lukte perfect met een if statement om op XP de oude manier te gebruiken, en in Vista de nieuwe manier.

Om de dialog echter verder in te stellen, wil je dan functies als SetDefaultFolder gebruiken.
Om het hiervoor benodigde ShellItem object aan te maken, moet je echter gebruik maken van SHCreateItemFromParsingName.
Dit is een functie die enkel in de Vista-versie van shell32.dll voorkomt.
Het probleem is nu dat na het compileren van mijn programma ik een foutboodschap krijg dat deze functie niet gevonden kan worden als ik het programma start in XP.
Start ik het programma in Vista dan is er geen probleem.

Het probleem is dus dat die functie al word opgezocht tijdens het starten, ook al zal de functie nooit uitgevoerd worden.
Ik kan met Google niets nuttigs vinden omdat dan alle resultaten te maken hebben met het compatibel maken van XP programma's met Vista vanuit een gebruikersstandpunt.
Ik vroeg me dus af hoe jullie hiermee omgaan en of er een handige manier is om dit soort functies in Vista te kunnen gebruiken zonder dat het niet meer werkt in XP.

Ik vermoed dat het met LoadLibrary wel mogelijk zal zijn om enkel in Vista de dll te laden en die functie op te zoeken, maar ik heb het gevoel dat dit behoorlijk omslachtig werkt (dan moet ik ook voor elke functie die ik zo wil gebruiken functie-pointer definities maken denk ik?)

VirtualDJ 2024 - Fast Image Resizer - Instagram


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

LoadLibrary() en GetProcAddress().

.edit: oh wacht, even over je laatste alinea heengelezen :). Ja, dat is dan idd een nadeel. Een andere optie is delayloading, dan doet de compiler het feitelijk automatisch voor je (hij maakt dan thunk functies voor de relevante APIs, en als je die aanroept doet hij vervolgens intern een LoadLibrary en reroute ie de call naar de juiste functie)

Zie de /DELAYLOAD linker optie voor meer details.

[ Voor 89% gewijzigd door .oisyn op 10-09-2009 16:15 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • leuk_he
  • Registratie: Augustus 2000
  • Laatst online: 15-07 15:35

leuk_he

1. Controleer de kabel!

En omdat een voorbeeld vaak beter helpt..


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
ULONGLONG GetDiskFileSize(LPCTSTR pszFilePath)
{
    static BOOL _bInitialized = FALSE;
    static DWORD (WINAPI *_pfnGetCompressedFileSize)(LPCTSTR, LPDWORD) = NULL;

    if (!_bInitialized){
        _bInitialized = TRUE;
        (FARPROC&)_pfnGetCompressedFileSize = GetProcAddress(GetModuleHandle(_T("kernel32.dll")), _TWINAPI("GetCompressedFileSize"));
    }

    // If the file is not compressed nor sparse, 'GetCompressedFileSize' returns the 'normal' file size.
    if (_pfnGetCompressedFileSize)
    {
        ULONGLONG ullCompFileSize;
        LPDWORD pdwCompFileSize = (LPDWORD)&ullCompFileSize;
        pdwCompFileSize[0] = (*_pfnGetCompressedFileSize)(pszFilePath, &pdwCompFileSize[1]);
        if (pdwCompFileSize[0] != INVALID_FILE_SIZE || GetLastError() == NO_ERROR)
            return ullCompFileSize;
    }

    // If 'GetCompressedFileSize' failed or is not available, use the default function
    WIN32_FIND_DATA fd;
    HANDLE hFind = FindFirstFile(pszFilePath, &fd);
    if (hFind == INVALID_HANDLE_VALUE)
        return 0;
    FindClose(hFind);

    return (ULONGLONG)fd.nFileSizeHigh << 32 | (ULONGLONG)fd.nFileSizeLow;
}

Je probeert het een en als de functie nog niet bestaat (dit is code die nog op win95 moest werken) doe je een fallback op de oude methode.

Delay loading werkt ook, maar dan leg je simpelweg de complexittei in de errorhanding/exceptio handling, je ziet de fouten pas als je de betreffende functie aanroept.

[ Voor 6% gewijzigd door leuk_he op 10-09-2009 17:22 ]

Need more data. We want your specs. Ik ben ook maar dom. anders: forum, ff reggen, ff topic maken
En als je een oplossing hebt gevonden laat het ook ujb ff in dit topic horen.


  • Mijzelf
  • Registratie: September 2004
  • Niet online
Adion schreef op donderdag 10 september 2009 @ 11:46:
Ik vermoed dat het met LoadLibrary wel mogelijk zal zijn om enkel in Vista de dll te laden en die functie op te zoeken, maar ik heb het gevoel dat dit behoorlijk omslachtig werkt (dan moet ik ook voor elke functie die ik zo wil gebruiken functie-pointer definities maken denk ik?)
Nee dat hoeft niet. De importtabellen worden door de linker aangemaakt, op grond van het aanwezig zijn van een functieaanroep in de code. Als je SHCreateItemFromParsingName met GetProcAddress() ophaalt, zal de linker alleen deze dus niet in de importtabel stoppen, en kun je de andere functies van shell32.dll op de normale manier gebruiken.
Maar delayloading is inderdaad netter en eenvoudiger.

Acties:
  • 0 Henk 'm!

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 17-09 18:11
Bedankt allemaal, delay loading doet inderdaad exact wat ik wil.
Voor de exception handling is het dan inderdaad belangrijk van op voorhand de vereisten van de functie te controleren, maar dat lijkt niet echt een probleem.

Ik was trouwens ook eens aan het kijken of het niet mogelijk is om de delay-load dll's via een #pragma in te stellen, maar blijkbaar is dit niet meer mogelijk in Visual Studio. (ik vond wel dit artikel dat wat meer uitleg geeft over de werking van delay loading)
Zelf vind ik het wel handig om dit soort instellingen in m'n source files te hebben, zodat dit meteen goed staat als ik de code in een ander project wil gebruiken.

VirtualDJ 2024 - Fast Image Resizer - Instagram