2

Using Delphi and Windows API is possible from a PItemIDList to get if the file is a folder or not? With this snippet of code I can get the only the name of the file.

procedure TMain.FolderMonitorFileChange(aSender: TObject; aPIDL: PItemIDList);
var
  FileInfo : SHFILEINFOW;
begin
  SHGetFileInfo(LPCTSTR(aPIDL), 0 , FileInfo, SizeOf(FileInfo), SHGFI_PIDL or SHGFI_DISPLAYNAME or SHGFI_TYPENAME or SHGFI_ATTRIBUTES);
  ShowMessage('File change notification: ' + FileInfo.szDisplayName + ' ' + FileInfo.szTypeName );
end;

Thanks

3
  • Have you looked at stackoverflow.com/questions/3780028/… Commented Jan 24, 2017 at 11:54
  • @Paul He has a PIDL and not a file Commented Jan 24, 2017 at 12:39
  • Call IShellFolder::GetAttributesOf and check for SFGAO_FOLDER. Commented Jan 24, 2017 at 12:42

1 Answer 1

4

For a relative PIDL, you can obtain the IShellFolder interface of the PIDL's parent folder, and then pass the PIDL to the IShellFolder::GetAttributesOf() method.

function IsFolder(Parent: IShellFolder; aChildPIDL: PItemIDList): Boolean;
var
  Attrs: SFGAOF;
begin
  Result := Succeeded(Parent.GetAttributesOf(1, @aChildPidl, @Attrs))
    and (Attrs and SFGAO_FOLDER <> 0);
end;

For an absolute PIDL, you have a few different options:

  • pass the PIDL to SHBindToParent() to convert it to a relative PIDL and retrieve its parent folder's IShellFolder, then call IShellFolder::GetAttributesOf().

    function IsFolder(aPIDL: PItemIDList): Boolean;
    var
      Parent: IShellFolder;
      Child: PItemIDList;
      Attrs: SFGAOF;
    begin
      Result := Succeeded(SHBindToParent(aPidl, IShellFolder, @Parent, @Child))
        and Succeeded(Parent.GetAttributesOf(1, @Child, @Attrs))
        and (Attrs and SFGAO_FOLDER <> 0);
    end;
    
  • pass the PIDL to SHGetFileInfo() using the SHGFI_PIDL flag. Enable the SHGFI_ATTRIBUTES flag to request the item's attributes.

    function IsFolder(aPIDL: PItemIDList): Boolean;
    var
      FileInfo : SHFILEINFO;
    begin
      Result := (SHGetFileInfo(LPCTSTR(aPIDL), 0, @FileInfo, SizeOf(FileInfo), SHGFI_PIDL or  SHGFI_ATTRIBUTES) <> 0)
        and (FileInfo.dwAttributes and SFGAO_FOLDER <> 0);
    end;
    
  • pass the PIDL to SHCreateItemFromIDList() to retrieve an IShellItem interface for it, and then call IShellItem::GetAttributes().

    function IsFolder(aPIDL: PItemIDList): Boolean;
    var
      Item: IShellItem;
      Attrs: SFGAOF;
    begin
      Result := Succeeded(SHCreateItemFromIDList(aPidl, IShellItem, @Item))
        and Succeeded(Item.GetAttributes(SFGAO_FOLDER, @Attrs))
        and (Attrs and SFGAO_FOLDER <> 0);
    end;
    
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks a lot for the help, but the code does not work for me because that event returns to me file changes of a monitorized folder, and when a file is modified all is ok but when i create a file it triggers that the folder that contains that has been changed and the attribute says that is a file, the typename says 'file' and the displayName is the name of the folder.
You asked how to determine whether a PIDL represents a folder or a file. I answered that. The SFGAO_FOLDER attribute is specifically designed for that purpose. Now, you are describing a different issue. Whether the notification gives you a file PIDL or a folder PIDL depends on what you are actually monitoring and how you are monitoring it. But I highly doubt that a folder object would not report itself as a folder in attributes, which makes me think either there is a bug in your code, or an error is being reported that you are not handling.
Yes I asked this because as you can see at the code I receive a 'PItemIDList' with the event, I thought that I do not know how to extract the data of that object. I am using a 'TLMDShellNotify' to monitor a folder and receive the changes using the 'FileChange' event of this object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.