Get path to "My Documents" folder

Get path to "My Documents" folder

Does anyone have a nice way to get the path the user's "My Documents" directory from Intel Fortran?

publicaciones de 12 / 0 nuevos
Último envío
Para obtener más información sobre las optimizaciones del compilador, consulte el aviso sobre la optimización.

More information: My application includes an installer project in Visual Studio 2010.  Basically, I want to have the installer create a directory to put examples and scratch files in that the application will use.  In the application, when the user wants to open a file, this is the directory I want to be the default that they are taken to.  I can make the installer install the files using the "User's Personal Data" item in the file system tree.  However, I can't seem to figure out how to get the application to know where this is located.  I can get the location of the user's home directory with the "USERPROFILE" environment variable, but there doesn't seem to be an environment variable for the user's documents folder.  I'd like a nice way to do this that works on Windows 7 and beyond (XP is a plus, but not required), that doesn't require me hard-coding what the directory is called (which may vary from system to system).

See the SHGetFolderPath API and its friends, and query the path location for CSIDL_PERSONAL.

CALL GET_ENVIRONMENT_VARIABLE ('USERPROFILE', DATA, LEN_DATA, IO_STATUS, .TRUE.)

For a full list of CSIDL values useable by SHGetFolderPath see

http://msdn.microsoft.com/en-gb/library/windows/desktop/bb762494%28v=vs....

There you can see that CSIDL_MYDOCUMENTS is the same as CSIDL_PERSONAL

All of these CSIDL values are available through the XSystemPath function in the Xeffort library, if you want to avoid working with the API directly.

 

Thanks all!  My solution is below.  It seems to work (note that it requires linking with shell32.lib).  Not sure if there is a better way to deal with the C string?

    program test
    
    use iso_c_binding
    use kernel32
    use ifwinty    

    implicit none
        
    integer :: i
    integer(handle) :: hresult
    character(len=1),dimension(256) :: tmpstr
    character(len=:),allocatable :: MyDocumentsDir
    
    integer(HANDLE),parameter :: CSIDL_PERSONAL = 5    !from Shlobj.h
    
    interface
        function SHGetFolderPathA(hwndOwner,nFolder,hToken,dwFlags,pszPath)
        !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'SHGetFolderPathA' :: SHGetFolderPathA
            import 
            implicit none
            integer(HANDLE) :: SHGetFolderPathA
            integer(HANDLE),value :: hwndOwner
            integer(c_int),value :: nFolder
            integer(HANDLE),value :: hToken
            integer(DWORD),value :: dwFlags
            character(kind=C_CHAR) :: pszPath(*)
        end function SHGetFolderPathA
    end interface
    
    hresult = SHGetFolderPathA( hwndOwner= NULL, &
                                nFolder  = CSIDL_PERSONAL,&
                                hToken   = NULL,&
                                dwFlags  = 0,&
                                pszPath  = tmpstr)
    
    write(*,*) 'hresult=',hresult

    if (hresult==0) then
        !convert array to character string:
        MyDocumentsDir = ''
        do i=1,size(tmpstr)
            if (tmpstr(i)/=C_NULL_CHAR) then
                MyDocumentsDir = MyDocumentsDir//tmpstr(i)
            else
                exit
            end if
        end do
        write(*,*) 'MyDocumentsDir: '//MyDocumentsDir
    else
        write(*,*) 'Error'
    end if
    
    end program test

 

Given that it is the ANSI version you have interfaced to why not make the interface more Fortran friendly by having 

character(len=*) :: pszPath

And then you can get MyDocumentsDir direct from the call without the string array copy? If you wanted the position of the first C_NULL_CHAR you could use INDEX.  Also add !DEC$OBJCOMMENT LIB:"SHELL32.LIB" perhaps.

@Intel is there any plans to add any new APIs to the IFWIN interfaces? There are many missing ones. I note the shell32 interfaces have not been added since 2000. It is after all Visual Fortran for WINDOWS!

 

app4619, yes, we do plan to add APIs. It's a time-consuming process, though. I'll take a look at shell32.

Steve

@Jacob 

You might note that SHGetFolderPath is supperceded SHGetKnownFolderPath which had more options. Also:

You have the function return value as type handle, HRESULT would be better  with ifwinty type LONG (4 bytes) your code should fail on x64 as it will be 8 bytes.

I also note the use of VALUE attribute. This is default for stdcall except for arrays and type character in my understanding.

@steve thanks. Some updates would be appreciated. I know it is time consuming, it consumes some of my time!

 

Thanks for the suggestions!  I did look at SHGetKnownFolderPath, but wasn't sure about the Fortran bindings for the REFKNOWNFOLDERID argument.  I might revisit it later.

Steve, WinINet.lib would also be a good one to have.

Inicie sesión para dejar un comentario.