# nichtdeklarierter Bezeichner



## alamos (2. November 2005)

Hallo,

ich mal wieder. Ich probier da gerade was zu programmieren und muss dafür eine Funktion benutzen die heißt: SHGetFolderLocation Leider bekomme ich immer foldende Fehlermeldung:

error C2065: 'SHGetFolderLocation' : nichtdeklarierter Bezeichner
error C2065: 'CSIDL_PROGRAM_FILES' : nichtdeklarierter Bezeichner

beim Aufruf von

```
hr = SHGetFolderLocation(NULL, CSIDL_PROGRAM_FILES, NULL, NULL, &pidlDesktop);
```

Jetzt habe ich mich gefragt woran das liegen kann, denn eine sehr verwandte Funktion, nämlich SHGetDesktopFolder zum Beispiel funktioniert.

Ich habe daraufhin SHGetFolderLocation in der MSDN nachgeschlagen und da steht man muß shlobj.h einbinden, was ich aber längst getan habe. Außerdem habe ich überprüft, ob meine shell32.dll aktuell genug ist und das ist sie. Woran kann denn sowas jetzt liegen? Ist meine shlobj.h alt? Kann mir wer helfen? Ich benutze Visual C++ 6. Gibts da vielleicht irgendwelche Updates die man braucht?

Ciao,

Martin


----------



## deepthroat (2. November 2005)

Hi.

Warum guckst du denn nicht in die MSDN? Da steht das man den Header shlobj.h einbinden muß wenn man die Funktion verwenden will.

Gruß


----------



## alamos (2. November 2005)

Ich habe doch gesagt, ich habe sie eingebunden, aber es geht trotzdem nicht 
Mittlerweile habe ich mir auch mal die shlobj.h angeschaut und festgestellt, dass die 
Funktion da auch nicht auftaucht. Also gehe ich jetz davon aus, dass meine Headerdatei
veraltet ist. Sie ist vom Donnerstag, 23. April 1998, 23:00:00. Hat einer ne neuere Version?


----------



## MCoder (2. November 2005)

Zumindest bei VS6 funktioniert das meines Wissens nur, wenn die entsprechende DLL dynamisch eingebunden wird. Ich hatte das mal für "SHGetFolderPath()" gemacht. Für "SHGetFolderLocation()" müsste das Beispiel entsprechend angepasst werden.


```
#ifndef CSIDL_PROGRAM_FILES
#define CSIDL_PROGRAM_FILES     0x0026
#endif

typedef HRESULT (CALLBACK *PTR_SHGETFOLDERPATH)(HWND, int, HANDLE, DWORD, LPTSTR);

HMODULE hModSHFolder = LoadLibrary(_T("shfolder.dll"));

if( hModSHFolder != NULL )
{
    PTR_SHGETFOLDERPATH pfnSHGetFolderPath;

    (*(FARPROC*)&pfnSHGetFolderPath = GetProcAddress(hModSHFolder, "SHGetFolderPathW"));

    if( pfnSHGetFolderPath )
    {
        TCHAR tchPath[_MAX_PATH];
        pfnSHGetFolderPath(NULL, nFolder, NULL, NULL, tchPath);

        FreeLibrary(hModSHFolder);
    }
}
```


----------



## deepthroat (2. November 2005)

alamos hat gesagt.:
			
		

> Ich habe doch gesagt, ich habe sie eingebunden, aber es geht trotzdem nicht


Oh, so weit hab ich gar nicht gelesen...  :-( 

Sorry.


----------



## alamos (2. November 2005)

@ MCoder: Sorry, aber mit deinem Posting kann ich nicht sehr viel anfangen. Vielleicht fehlt mir da einfach dei Programmiererfahrung.

Ich habe da jetzt so einen Quellcode aus der MSDN, der oben erwähnte Funktion nutzt. Natürlich kann ich ihn nicht ohne Fehler kompilieren aus oben genannten Gründen, aber vielleicht klappt das ja bei jemanden und der kann mir dann seine shobj.h schicken oder so.


```
#include <shlobj.h>
#include <shlwapi.h>
#include <iostream.h>

main()
{
    LPMALLOC pMalloc;
    LPITEMIDLIST pidlProgFiles = NULL;
    LPITEMIDLIST pidlItems = NULL;
    IShellFolder *psfFirstFolder = NULL;
    IShellFolder *psfDeskTop = NULL;
    IShellFolder *psfProgFiles = NULL;
    LPENUMIDLIST ppenum = NULL;
    ULONG celtFetched;
    HRESULT hr;
    STRRET strDispName;
    TCHAR pszDisplayName[MAX_PATH];
    ULONG uAttr;
   
    CoInitialize( NULL );
    hr = SHGetMalloc(&pMalloc);
	
    hr = SHGetFolderLocation(NULL, CSIDL_PROGRAM_FILES, NULL, NULL, &pidlProgFiles);

    hr = SHGetDesktopFolder(&psfDeskTop);

    hr = psfDeskTop->BindToObject(pidlProgFiles, NULL, IID_IShellFolder, (LPVOID *) &psfProgFiles);
    psfDeskTop->Release();

    hr = psfProgFiles->EnumObjects(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &ppenum);

    while( hr = ppenum->Next(1,&pidlItems, &celtFetched) == S_OK && (celtFetched) == 1)
    {
        psfProgFiles->GetDisplayNameOf(pidlItems, SHGDN_INFOLDER, &strDispName);
        StrRetToBuf(&strDispName, pidlItems, pszDisplayName, MAX_PATH);
        cout << pszDisplayName << '\n';
        if(!psfFirstFolder)
        {
            uAttr = SFGAO_FOLDER;
            psfProgFiles->GetAttributesOf(1, (LPCITEMIDLIST *) &pidlItems, &uAttr);
            if(uAttr & SFGAO_FOLDER)
            {
                hr = psfProgFiles->BindToObject(pidlItems, NULL, IID_IShellFolder, (LPVOID *) &psfFirstFolder);
            }
        }
        pMalloc->Free(pidlItems);
    }

    cout << "\n\n";

    ppenum->Release();

    if(psfFirstFolder)
    {
        hr = psfFirstFolder->EnumObjects(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &ppenum);

        while( hr = ppenum->Next(1,&pidlItems, &celtFetched) == S_OK && (celtFetched) == 1)
        {
            psfFirstFolder->GetDisplayNameOf(pidlItems, SHGDN_INFOLDER, &strDispName);
            StrRetToBuf(&strDispName, pidlItems, pszDisplayName, MAX_PATH);
            cout << pszDisplayName << '\n';
            pMalloc->Free(pidlItems);
        }
    }

    ppenum->Release();
    pMalloc->Free(pidlProgFiles);
    pMalloc->Release();
    psfProgFiles->Release();
    psfFirstFolder->Release();

    CoUninitialize();
    return 0;
}
```


----------



## MCoder (2. November 2005)

Ersetze diese Zeile

```
hr = SHGetFolderLocation(NULL, CSIDL_PROGRAM_FILES, NULL, NULL, &pidlProgFiles);
```
durch diesen Block:

```
HMODULE hModSHFolder = LoadLibrary(_T("shfolder.dll"));

if( hModSHFolder )
{
    PTR_SHGETFOLDERLOCATION pfnSHGetFolderLocation;
    
    (*(FARPROC*)&pfnSHGetFolderLocation = GetProcAddress(hModSHFolder, "SHGetFolderLocation"));

    if( pfnSHGetFolderLocation )
    {
        hr = pfnSHGetFolderLocation(NULL, CSIDL_PROGRAM_FILES, NULL, NULL, &pidlProgFiles);
    }
}
```
und füge vor main() diese Zeilen ein:

```
#ifndef CSIDL_PROGRAM_FILES
#define CSIDL_PROGRAM_FILES     0x0026
#endif

typedef HRESULT (CALLBACK *PTR_SHGETFOLDERLOCATION)(HWND, int, HANDLE, DWORD, LPITEMIDLIST);
```


----------



## alamos (2. November 2005)

Das funktioniert leider auch nicht.

Ich verstehe das ganze auch irgendwie nicht. Wieso werden in der MSDN Funktionen erklärt die in der von denen angegebenen Headerdatei gar nich deklariert sind? Das ist doch vollkommen bescheuert.

Die Funktion StrRetToStr() funktioniert übrigens auch nicht, obwohl ich <shlwapi.h>
mit include eingebunden habe und auch die shlwapi.lib dem Projekt hinzugefügt habe.
Hab ich irgendwie die Visual C++ Kinder Edition?


----------



## MCoder (2. November 2005)

Speziell bei der Geschichte mit "SHGetFolderPath" habe ich auch lange gesucht, bis ich die vorher gepostete Lösung gefunden habe. Warum die MSDN-Beispiele nicht so ohne weiteres funktionieren weiss wohl nur MS.

Möglicherweise stecken in dem Code ja noch andere Probleme. Was genau geht denn nicht bzw. was kommen denn jetzt noch für Fehlermeldungen?


----------



## alamos (2. November 2005)

Naja als es so nicht lief habe ich mir überlegt es anders zu machen. Ich habe in meiner Headerdatei shlobj.h eine ähnliche Funktion gefunden namens

SHGetSpecialFolderLocation()

Ist zwar nicht ganz das selbe, aber ein Blick in die MSDN hat mir dann gezeigt, dass es funktionieren sollte. Da es diese Funktion wirklich gibt im Gegensatz zu der SHGetFolderLocation() klappte das auch soweit...


```
hr = SHGetMalloc(&pMalloc);
           hr = SHGetSpecialFolderLocation(hwnd, CSIDL_PROGRAMS, &pidlTarget);
           hr = SHGetDesktopFolder(&psfDesktop);

           hr = psfDesktop->BindToObject(pidlTarget, NULL, IID_IShellFolder, (LPVOID *) &psfTarget);
           psfDesktop->Release();
           hr = psfTarget->EnumObjects(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &ppenum);
```

und das kann man sogar ohne Probleme kompilieren. 
So...
Jetzt bin ich einen Schritt weiter gegangen und wollte alle Dateien bzw. Unterordner aus diesem Verzeichnis erhalten. Das Ergebnis bekommt man mit GetDisplayNameOf() und das Ergebnis ist ein Struct namens STRRET. Jetzt sagt die MSDN dazu, dass es 2 Funktionen gibt:  StrRetToBuf und StrRetToStr die aus dem Struct dann den Buffer bzw String des Dateinamens machen. Diese beiden Funktionen sollen in shlwapi.h stehen, tun sie aber auch nicht. Denn bei folgender Schleife


```
while( hr = ppenum->Next(1,&pidlItems, &celtFetched) == S_OK && (celtFetched) == 1)
          {
	psfTarget->GetDisplayNameOf(pidlItems, SHGDN_INFOLDER, &strDispName);
                StrRetToStr(&strDispName, pidlItems, pszDisplayName, MAX_PATH);


           }
```

bekomm ich dann die Fehlermeldung, dass es den Bezeichner "StrRetToStr" nicht gibt.
Das heißt ganz einfach gesagt: Ich verfüge grob geschätzt nur über die Hälfte der Shell
Funktionen wie sie in der MSDN stehen. Warum weiß ich nicht. Vielleicht kannst du einfach mal in deine shlobj.h schauen ob du so Funktionen hast bzw. benutzen kannst.


----------



## alamos (3. November 2005)

SOOO. Problem gelöst.
Und zwar hab ich mir jetzt die aller neueste SDK runtergeladen und da ist die
SHLOBJ.H 220 KB groiß anstatt nur 120 KB 
So ein Mist, ganzen Tag damit verschwendet.

Danke für die Hilfe MCoder


----------

