+ Reply to Thread
Results 1 to 19 of 19

Thread: The continuing nightmare known as SHGetFolderPath

  1. #1
    Senior Member
    Join Date
    Dec 2004
    Location
    SF Bay Area
    Posts
    789

    Default The continuing nightmare known as SHGetFolderPath

    Regarding an earlier thread that was Blitz oriented. I need to revist the issue in C++. I'm using VS 6.0, and I can't even get the following snippet to compile. Error messages below C code. Little help?

    Clearly I'm not including the right files but all my googling suggested the following.


    Code:
    #define _WIN32_IE 0x500
    #include <shlobj.h>
    
    #include <windows.h>
    
    
    
    BOOL APIENTRY GetAppSupp(LPWSTR p)
    {
    TCHAR path[MAX_PATH];
    HRESULT hr;
    
    hr = SHGetFolderPath(CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path);
    
    
    if(SUCCEEDED(hr))
       { 
    		hr = 0;
       } 
    else
       { 
    		hr = 0;
       } 
        return TRUE;
    }
    
    
    
    BOOL APIENTRY GetCommAppSupp(LPWSTR p)
    {
    TCHAR path[MAX_PATH];
    HRESULT hr;
    
    hr = SHGetFolderPath(CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, path);
    
    
    if(SUCCEEDED(hr))
       {
    		hr = 0;
       }
    else
       { 
    		hr = 0;
       } 
    
        return TRUE;
    }

    Compiling...
    drmPaths.cpp
    c:\drmpaths\drmpaths.cpp(18) : error C2065: 'SHGetFolderPath' : undeclared identifier
    c:\drmpaths\drmpaths.cpp(18) : error C2065: 'CSIDL_LOCAL_APPDATA' : undeclared identifier
    c:\drmpaths\drmpaths.cpp(18) : error C2065: 'SHGFP_TYPE_CURRENT' : undeclared identifier
    c:\drmpaths\drmpaths.cpp(39) : error C2065: 'CSIDL_COMMON_APPDATA' : undeclared identifier
    Error executing cl.exe.

    drmPaths.obj - 4 error(s), 0 warning(s)



    If I ever build a working way to access app folders from Win95 onward, I will be happy to post the solution to the world.
    Keith Nemitz
    Ordinauteur
    http://www.mousechief.com/

  2. #2
    Senior Member
    Join Date
    Jul 2004
    Location
    Isle of Wight, UK
    Posts
    3,773

    Default

    you also need shellapi shlapi? iirc

    if you google "XBrowseForFolder" someones written a one file class you can call that makes this thing behave nicely. I use it in all my tools and it just works.
    Regards,
    Paul Johnson

    [Great BIG War Game: iOS | Android] [Great Little War Game: iOS | Android] [Fruit Blitz: iOS | Android] [Yachty Deluxe: iOS | Android]

  3. #3
    Senior Member
    Join Date
    Dec 2004
    Location
    SF Bay Area
    Posts
    789

    Default

    Quote Originally Posted by Applewood View Post
    google "XBrowseForFolder" someones written a one file class you can call that makes this thing behave nicely.
    XBrowseForFolder looks like code that allows the user to navigate to folders, but I need a function that retrieves the paths from the OS, without user intervention.

    Adding the include you suggested did not fix any of the errors;

    #include <shellapi.h>

    The other spelling was not found.
    Keith Nemitz
    Ordinauteur
    http://www.mousechief.com/

  4. #4
    Senior Member
    Join Date
    Aug 2004
    Posts
    947

    Default

    Try shlobj.h

  5. #5
    Senior Member
    Join Date
    Dec 2004
    Location
    SF Bay Area
    Posts
    789

    Default

    Quote Originally Posted by Sybixsus View Post
    Try shlobj.h
    That already exists in the code snippet.
    Keith Nemitz
    Ordinauteur
    http://www.mousechief.com/

  6. #6
    Senior Member
    Join Date
    Aug 2004
    Posts
    947

    Default

    Sorry, your code has a scrollbar on my screen and I missed the first few lines. Try adding Wininet.h

  7. #7
    Senior Member
    Join Date
    Dec 2004
    Location
    SF Bay Area
    Posts
    789

    Default

    Nah, no luck with Wininet.h.

    I wonder if my project's parameters aren't set right. All I did was use a wizard to make a default dll project.
    Keith Nemitz
    Ordinauteur
    http://www.mousechief.com/

  8. #8
    Senior Member
    Join Date
    Feb 2007
    Location
    USA/Mexico
    Posts
    309

    Default

    "shlobj.h" is the correct header include, however it MUST be included after windows.h

    For instance, your code [almost, see below] compiled correctly for me by simply moving the #include <shlobj.h> below the #include <windows.h>

    However, it doesn't quite compile just with that (although the messages you are getting should go away).

    According to the defintion of SHGetFolderPath, you need 5 parameters to the function call, the first one being the HWND handle.

    That said, this was also compiled in VS 2005 as a win32 dll, but that should make very little difference in this case (I believe).

    Hope it helps.

    Edit: Apparently the func is deprecated as well.

    http://msdn.microsoft.com/en-us/libr...81(VS.85).aspx
    Last edited by MFS; 06-10-2008 at 07:19 PM. Reason: More info

  9. #9
    Senior Member
    Join Date
    Dec 2004
    Location
    SF Bay Area
    Posts
    789

    Default

    SHGetFolderPath is deprecated. It has been replaced in Vista only with SHGetKnownFolderPath. Unfortunately for backwards compatibility SHGetFolderPath is the only function that can be used. Even then you have to test for the existence of Explorer ver 4.0...

    but I'm just trying to get the first step compiled. Here is the new include arrangement I tried.


    Code:
    #include <windows.h>
    
    #define _WIN32_IE 0x500
    #include <shlobj.h>
    #include <Wininet.h>
    and here is the new error list:

    c:\drmpaths\drmpaths.cpp(8) : warning C4005: '_WIN32_IE' : macro redefinition
    c:\program files\microsoft visual studio\vc98\include\prsht.h(16) : see previous definition of '_WIN32_IE'
    c:\drmpaths\drmpaths.cpp(18) : error C2065: 'SHGetFolderPath' : undeclared identifier
    c:\drmpaths\drmpaths.cpp(18) : error C2065: 'CSIDL_LOCAL_APPDATA' : undeclared identifier
    c:\drmpaths\drmpaths.cpp(18) : error C2065: 'SHGFP_TYPE_CURRENT' : undeclared identifier
    c:\drmpaths\drmpaths.cpp(39) : error C2065: 'CSIDL_COMMON_APPDATA' : undeclared identifier
    Error executing cl.exe.

    drmPaths.dll - 4 error(s), 1 warning(s)




    ...the nightmare continues...
    Keith Nemitz
    Ordinauteur
    http://www.mousechief.com/

  10. #10
    Senior Member
    Join Date
    Feb 2007
    Location
    USA/Mexico
    Posts
    309

    Default

    Hmmm. Odd. I did actually use the stdafx.h created with the empty dll project, but that seems to be the only difference. I fail to see why that is important here though.

    For reference I'll go ahead and post the exact code I tried out that compiles for me. It might not help, but who knows?

    This frustrates me now...because I've used that function in the past on many occasions.

    Code:
    #define _WIN32_IE 0x500
    
    #include "stdafx.h"
    #include <shlobj.h>
    
    BOOL APIENTRY GetAppSupp(LPWSTR p)
    {
    TCHAR path[MAX_PATH];
    HRESULT hr;
    
    hr = SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path);
    
    
    if(SUCCEEDED(hr))
       { 
    		hr = 0;
       } 
    else
       { 
    		hr = 0;
       } 
        return TRUE;
    }
    
    
    
    BOOL APIENTRY GetCommAppSupp(LPWSTR p)
    {
    TCHAR path[MAX_PATH];
    HRESULT hr;
    
    hr = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, path);
    
    
    if(SUCCEEDED(hr))
       {
    		hr = 0;
       }
    else
       { 
    		hr = 0;
       } 
    
        return TRUE;
    }
    Code:
    // stdafx.h : include file for standard system include files,
    // or project specific include files that are used frequently, but
    // are changed infrequently
    //
    
    #pragma once
    
    // Modify the following defines if you have to target a platform prior to the ones specified below.
    // Refer to MSDN for the latest info on corresponding values for different platforms.
    #ifndef WINVER				// Allow use of features specific to Windows XP or later.
    #define WINVER 0x0501		// Change this to the appropriate value to target other versions of Windows.
    #endif
    
    #ifndef _WIN32_WINNT		// Allow use of features specific to Windows XP or later.                   
    #define _WIN32_WINNT 0x0501	// Change this to the appropriate value to target other versions of Windows.
    #endif						
    
    #ifndef _WIN32_WINDOWS		// Allow use of features specific to Windows 98 or later.
    #define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
    #endif
    
    #ifndef _WIN32_IE			// Allow use of features specific to IE 6.0 or later.
    #define _WIN32_IE 0x0600	// Change this to the appropriate value to target other versions of IE.
    #endif
    
    #define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
    // Windows Header Files:
    #include <windows.h>
    
    // C RunTime Header Files
    #include <stdlib.h>
    #include <malloc.h>
    #include <memory.h>
    #include <tchar.h>
    
    
    // TODO: reference additional headers your program requires here

  11. #11
    Senior Member
    Join Date
    Dec 2004
    Location
    SF Bay Area
    Posts
    789

    Default

    I was sure my project must have had problems. So I create a new dll workspace, the minimal one, not the empty one. Then I replaced the .cpp and .h with MFS's code. Now I get a more interesting but basically the same error output.


    Compiling...
    StdAfx.cpp
    NOTE: WINVER has been defined as 0x0500 or greater which enables
    Windows NT 5.0 and Windows 98 features. When these headers were released,
    Windows NT 5.0 beta 1 and Windows 98 beta 2.1 were the current versions.
    For this release when WINVER is defined as 0x0500 or greater, you can only
    build beta or test applications. To build a retail application,
    set WINVER to 0x0400 or visit http://www.microsoft.com/msdn/sdk
    to see if retail Windows NT 5.0 or Windows 98 headers are available.
    See the SDK release notes for more information.
    Compiling...
    testPaths.cpp
    C:\testPaths\testPaths.cpp(11) : error C2065: 'SHGetFolderPath' : undeclared identifier
    C:\testPaths\testPaths.cpp(11) : error C2065: 'CSIDL_LOCAL_APPDATA' : undeclared identifier
    C:\testPaths\testPaths.cpp(11) : error C2065: 'SHGFP_TYPE_CURRENT' : undeclared identifier
    C:\testPaths\testPaths.cpp(32) : error C2065: 'CSIDL_COMMON_APPDATA' : undeclared identifier
    Error executing cl.exe.

    testPaths.dll - 4 error(s), 0 warning(s)
    Keith Nemitz
    Ordinauteur
    http://www.mousechief.com/

  12. #12
    Senior Member
    Join Date
    Feb 2007
    Location
    USA/Mexico
    Posts
    309

    Default

    Blah. I wish this didn't bother me so much

    Anyways, I'm currently chalking it up to differences in the way VS 6.0 and VS 2005 set up the win32 dll projects, etc. I don't have VS 6.0 installed anymore, but I still have a copy around somewhere. I'll install it tomorrow and see what pain it causes me

    In the meantime, have you thought about VS 2005? It is far superior to VS 6.0, although the free express edition would also require you to dl the Platform SDK.

  13. #13
    Senior Member
    Join Date
    Dec 2004
    Location
    SF Bay Area
    Posts
    789

    Default

    Quote Originally Posted by MFS View Post
    In the meantime, have you thought about VS 2005? It is far superior to VS 6.0, although the free express edition would also require you to dl the Platform SDK.
    I'll give that a try. Will the express edition allow me to build a dll? That's very important to my ultimate task.
    Keith Nemitz
    Ordinauteur
    http://www.mousechief.com/

  14. #14
    Senior Member
    Join Date
    Feb 2007
    Location
    USA/Mexico
    Posts
    309

    Default

    You should be able to create dlls once you have the platform sdk installed. I use the professional edition though, so I might not be remembering some express-specific limitations.

    I do remember though, that with the platform sdk installed, I could do everything I needed...

    There are a few more steps to do, to make life easy once both the IDE and platform SDK are dled. I'm looking for the exact link that can help you, and I'll post it in here once I find it.

    Edit: Not the exact link, but it has the necessary information: http://compsci.ca/v3/viewtopic.php?t=15817
    Disregard any DX specific stuff if not applicable for you. The important (and subtle IMO) things are the directory additions, and then editing the text files to add settings (all described in Step 2).

  15. #15
    Senior Member
    Join Date
    Jul 2004
    Location
    Sheffield, UK
    Posts
    694

    Default

    I was using 2005/2003 and the following worked fine.

    Code:
    //#include "Windows.h" // optional
    #include "shlobj.h"
    int main( int argc, char *argv[] )
    {
    	TCHAR szPath[MAX_PATH];
    
    	if(SUCCEEDED(SHGetFolderPath(NULL, 
    		CSIDL_PERSONAL|CSIDL_FLAG_CREATE, 
    		NULL, 
    		0, 
    		szPath))) 
    	{
    		// wipee we compiled
    	}
    }
    you don't need windows.h or any other dependencies, you also need IE 5, it says this in the docs so I don't know why anyone would say 4, as the header is wrapped as such.

    #if (_WIN32_IE >= 0x0500)
    ...
    #ifdef UNICODE
    #define SHGetFolderPath SHGetFolderPathW
    #else
    #define SHGetFolderPath SHGetFolderPathA
    #endif // !UNICODE

    I guess it might be worth you trying to directly access SHGetFOlderPathA but I'm betting it will make no difference.

    What you should do is look at shlobj.h at the top it should define _WIN32_IE for you if it hasn't already been set.

    and check to see if the functions are even declared in the header you're using.

    you can even have some temporary #error poop just to make sure you're working with the correct file and move it to where SHGetFolerPath macros are defined to see if it's even getting that far (if they exist).
    It will be better than including random other headers which will make no difference
    Last edited by Nikster; 06-11-2008 at 01:53 AM.
    --

  16. #16
    Senior Member
    Join Date
    Feb 2005
    Posts
    2,077

    Default

    Shouldn't you be using SHGetSpecialFolderLocation() for this?
    Dr Mal: Practice of Horror PC | Mac
    Crime Solitaire PC | Mac | iOS
    Magicville: Art of Magic PC | Mac
    Desktop Gaming Ltd | Facebook | YouTube | Twitter

  17. #17
    Senior Member
    Join Date
    Jul 2004
    Posts
    132

    Default

    Here is a (slightly modified) snippet of code from the PopCap framework that I've had no problems getting to work:

    Code:
    #include <windows.h>
    #include <shlobj.h>
    
    ...
    
    typedef HRESULT (WINAPI *_SHGetFolderPathFunc_t)(HWND, int, HANDLE, DWORD, LPTSTR);
    
    ...
    
    static void* _getSHGetFolderPath( const char* theDLL, HMODULE *hMod )
    	{
    	_SHGetFolderPathFunc_t pFunc = NULL;
    
    	HMODULE aMod = LoadLibrary( theDLL );
    	if( aMod )
    		{
    		*((void**)&pFunc) = (void*)GetProcAddress( aMod, "SHGetFolderPathA" );
    		if( !pFunc )
    			{
    			FreeLibrary( aMod );
    			aMod = NULL;
    			}
    		}
    
    	*hMod = aMod;
    	return pFunc;
    	}
    
    ...
    
    HMODULE hMod;
    _SHGetFolderPathFunc_t pFunc;
    
    pFunc = (_SHGetFolderPathFunc_t)_getSHGetFolderPath( "shell32.dll", &hMod );
    if( !pFunc )
    	pFunc = (_SHGetFolderPathFunc_t)_getSHGetFolderPath( "shfolder.dll", &hMod );
    
    if( pFunc )
    	{
    	char thePath[MAX_PATH];
    	pFunc( NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, thePath );
    	strcpy_s( (char*)_data_path, MAX_PATH, thePath );
    	FreeLibrary( hMod );
    	}
    else strcpy_s( (char*)_data_path, MAX_PATH, "." ); // use current directory
    HTH
    David

  18. #18
    Senior Member
    Join Date
    Jul 2004
    Location
    Durham, UK
    Posts
    4,873

    Default

    In the docs for every Win32 function there is a section, "Defined In", which tells you which include file the function is defined in.

    Cas

  19. #19
    Senior Member
    Join Date
    Dec 2004
    Location
    SF Bay Area
    Posts
    789

    Default

    Today I was kidnapped by the wife to an all day picnic. I'll try the latest suggestions tomorrow. Thanks for your attentions. I did download and install Visual Studio Express.

    I mistakenly typed Explorer 4. I should have typed Explorer 5.
    Last edited by Musenik; 06-12-2008 at 06:40 PM.
    Keith Nemitz
    Ordinauteur
    http://www.mousechief.com/

+ Reply to Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts