Tech Articles


Calling SHGetKnownFolderPath from PowerBuilder


Up through Windows XP, if you wanted to get the physical location of certain defined folders (e.g. the users Documents folder), you would use the SHGetFolderPath function in the Windows API.  Roland Smith has examples of using that on his Topwiz Software site.  That function continues to work in later versions of Windows, although it's basically a wrapper for the SHGetKnownFolderPath function.

SHGetFolderPath uses CSIDL values, whereas SHGetKnownFolderPath uses KnownFolderID GUIDs.  One difference is that there are a lot more KnownFolderIDs than there are CSIDLs.  That means some of the defined folder locations you may want to get the physical location for can't be accessed through the older SHGetFolderPath method.  And that's exactly the situation I ran into.


I needed to find the user's Downloads folder, and there isn't a CSIDL value for that.  So, I needed to see how to call the SHGetKnownFolderPath function from PowerBuilder.  As with many OLE and Windows API calls, it can save you a lot of time if you can find some Visual Basic code that does what you need to do, and you can convert the syntax.  And fortunately, I found some that did this.



So, with a little tweaking, I ended up with this:

//Local External Functions:

 Function Long CLSIDFromString (ref string lpszGuid, ref blob pGuid ) Library "ole32"   
 Function Long SHGetKnownFolderPath( ref blob nFolder,int dwFlags,uLong hToken , ref long pszPath) LIBRARY "Shell32.dll"   
 Subroutine CopyMemory ( ref String pDest, long pSrc, long ByteLen) Library "kernel32" Alias For "RtlMoveMemory"   
 Subroutine CoTaskMemFree ( long hMem) Library "ole32"   
 Function Long lstrlenW ( long ptr) Library "kernel32"   

//PowerScript

 blob     guid  
 long     ll_rc, ll_folderpointer, ll_folderlen  
 string ls_folder, ls_folder_id  
 ls_folder_id = '{374DE290-123F-4565-9164-39C4925E467B}'  
 IF CLSIDFromString (ls_folder_id, guid ) = 0 THEN  
      IF SHGetKnownFolderPath ( guid, 0, 0, ll_folderpointer ) = 0 THEN  
           IF ll_folderpointer <>0 THEN  
                ll_folderlen = lstrlenW ( ll_folderpointer )  
                If ll_folderlen <> 0 THEN  
                     ls_folder = Space ( ll_folderlen )                      
                     CopyMemory ( ls_folder, ll_folderpointer, ll_folderlen * 2 )  
                END IF  
           END IF  
           CoTaskMemFree ( ll_folderpointer )  
      END IF  
 END IF  
 MessageBox ( "Downloads Folder", ls_folder )  


Hope you find that useful as well.

 

 

 

 

 

 

Comments (1)
Tuesday, Sep 23 2025

I tried this with PB 2022 Build 1892 and it works the first time. The second call causes it to hang for a few seconds and then it aborts.

0

Find Articles by Tag

IDE PowerBuilder Compiler Event Handler Transaction .NET Std Framework Array Performance PBVM Sort Interface Database Object Resize Design Azure PowerServer Web CI/CD PFC Messagging ActiveX iOS 64-bit Stored Procedure .NET DataStore Database Painter SDK DataType UI Themes Windows OS Web Service Proxy TLS/SSL RibbonBar Data Migration MessageBox File Excel DLL Repository Model NativePDF TreeView Configuration RichTextEdit Control Validation SQL Server Filter COM Export Service 32-bit .NET Assembly Script Text PowerScript (PS) DragDrop Authorization Graph PostgreSQL Database Profile Database Table PowerBuilder HTTPClient Event JSON Syntax RESTClient Elevate Conference SQL Database Connection Debug DataWindow JSON Automated Testing Window Installation Charts Platform Menu GhostScript ODBC Testing Web API Debugging OLE Import JSON UI Modernization PBDOM RibbonBar Builder Windows 10 Icons SqlExecutor Visual Studio WebBrowser JSONGenerator Debugger Oracle Linux OS Encryption Jenkins DataWindow Outlook External Functions Mobile SnapDevelop PDF XML PowerBuilder (Appeon) Variable REST Branch & Merge Trial CoderObject Application Database Table Data Import PowerServer Mobile C# Source Control PostgreSQL ODBC driver Deployment Error Expression SVN WinAPI CrypterObject Git Database SnapObjects API Class Encoding OAuth OrcaScript JSONParser Icon Event Handling Open Source PBNI DevOps Database Table Schema Android SOAP BLOB TortoiseGit Source Code TFS Export JSON SqlModelMapper Bug Authentication OAuth 2.0 InfoMaker License UI PDFlib