1

I am using Kaspersky Internet Security 2018. But when I compile my Delphi application with these codes, my anti-virus application will remove the compiled exe:

function BrowseForFolder(var dpFolder: String; dpTitle: String): Boolean;
var
  dpBrowseInfo: TBrowseInfo;
  dpDisplayName: array[0..255] of Char;
  dpItemIDList: PItemIDList;
begin
  FillChar(dpBrowseInfo, sizeof(dpBrowseInfo), #0);
  with dpBrowseInfo do begin
    hwndOwner := Application.Handle;
    pszDisplayName := @dpDisplayName[0];
    lpszTitle := PChar(dpTitle);
    dpItemIDList := SHBrowseForFolder(dpBrowseInfo);
    ulFlags := BIF_RETURNONLYFSDIRS and BIF_VALIDATE;
  end;
if Assigned(dpItemIDList) then begin
  if SHGetPathFromIDList(dpItemIDList, dpDisplayName) then begin
    dpFolder := dpDisplayName;
    Result := True;
  end else begin
    Result := False;
  end;
end;
end;

What should I do to pop up "Browse folder" menu other than adding my app to whitelist?

  • 1
    It is not unusual for AV tools to flag Delphi apps. Some viruses have been written with Delphi, and one thing that AV tools use to identify viruses is known code byte sequences, some of which seem to be found in common Delphi RTL functions, for instance. About all you can do is report the false positive to your AV vendor, and then whitelist your app. – Remy Lebeau Jul 03 '18 at 21:01
  • 1
    On a side note, you are setting the `dpBrowseInfo.ulFlags` field AFTER calling `SHBrowseForFolders()` instead of BEFORE calling it. And you don't need to specify a buffer for `dpBrowseInfo.pszDisplayName` since you are not actually using the folder's display name after the dialog closes. Also, `SHBrowseForFolder()` is deprecated on Vista+ anyway, you should consider using `IFileDialog` with the `FOS_PICKFOLDERS` flag instead, like the `SHBrowseForFolder()` documentation suggests. – Remy Lebeau Jul 03 '18 at 21:01
  • Just out of curiosity, when is the buffer necessary? I used the deprecated one; because I always try to make my softwares working on every Windows computer. –  Jul 03 '18 at 21:10
  • 1
    "*when is the buffer necessary?*" - when you actually need it, for instance in the `dpBrowseInfo.lpfn` callback function (which you are not using) to make the selected folder name available to something else in your UI. But in your example, using `pszDisplayName` is just wasted overhead. – Remy Lebeau Jul 03 '18 at 21:24
  • You don't need to ignore newer APIs just to maintain compatibility with older OS versions. You can use newer APIs when available, and fallback to older APIs when needed. For example, call `CoCreateInstance(CLSID_FileOpenDialog, ...)` first, and if it is successful (Vista and later), you can use `IFileDialog`, otherwise use `SHBrowseForFolder()` instead (XP and earlier). – Remy Lebeau Jul 03 '18 at 21:27
  • And BTW, I've used `SHBrowseForFolder()` and `SHGetPathFromIDList()` in my apps for years, and have never had any AV tool flag my apps as viruses because of them. You need to get a better AV tool. – Remy Lebeau Jul 03 '18 at 22:25
  • I tried almost every anti-virus softwares and I realized that Kaspersky is my favorite. Because it does not spy on their customers and it does not violate their privacy. I'm sure about that. Also its developers shared source codes to proof that American government's accusations are not true. However, it has false positives; but the truth is "There is no perfect anti-virus software; because they are human-made." –  Jul 03 '18 at 23:07

1 Answers1

0

I have tried every "Browse Folder" dialog types and I have realized that my anti-virus software only allows Vcl.FileCtrl.TSelectDirExtOpt (also it hates other FileCtrl dialogs).

So, I fixed my issue myself like this:

procedure TForm1.gözatDüğmesiClick(Sender: TObject);
  begin
    if not (menü4CB = '1') then begin
      if not (SelectDirectory('Kurulum programının yedekleneceği klasörü seçin', 
        GetSpecialFolderPathFromCSIDL($0011), adres, [sdNewFolder, sdNewUI], nil) = False) then begin
           adresÇubuğu.Text := adres;
      end else begin
      end;
    end;
end;

Thank Remy Lebeau anyway for caring about me.

  • 3
    You are calling the version of `SelectDirectory()` that uses `SHBrowseForFolder()` internally, so you may as well just stick with calling `SHBrowseForFolder()` directly. Which you need to do anyway, since `$0011` is `CSIDL_DRIVES`, which does not have a physical filesystem path, so `GetSpecialFolderPathFromCSIDL(CSIDL_DRIVES)` is meaningless. The `Root` parameter requires a physical filesystem path. If you want to use `CSIDL_DRIVES` as the root, you must call `SHBrowseForFolder()` directly so you can specify the correct `PIDL` in the `BROWSEINFO.pidlRoot` field. – Remy Lebeau Jul 03 '18 at 22:14
  • Ok, I will think about that. Thank you so much. –  Jul 03 '18 at 22:17