2

I am trying to run a command to open a specific location in the explorer.exe and select a specific file:

QUrl url = QUrl::fromUserInput(file.absoluteFilePath());
QString str = "explorer.exe /select,\"" + url.toString() + "\"";
system(str.toStdString().c_str());

This works great with Windows locations.

But since I open as well locations from a NAS and MAC user can create folders there I have a problem with folders like this:

//NAS/FOLDER/With/BackSLASH/file.ext

Since it's possible on a Mac to use slashes for file/folder naming it cannot be recognized by the system() funciton and QString converts it to U+002F.

In Windows explorer it is shown as:

FOLDER•With•BackSLASH

and, if I use the command prompt to navigate into such a folder it shows the folder name as following:

PRODUCER'S NOTES 86

Does anyone have an idea how to handle this special case or how to convert this path to a path which can be passed as argument for the explorer.exe?

/* EDIT 08/31/2018*/

I changed my Code to:

#include <Shlobj.h>
#include <atlstr.h>
void exportManager::BrowseToFile(QString filename)
{
TCHAR tchar[512];
USES_CONVERSION;
_tcscpy(tchar, A2T(filename.toStdString().c_str()));

ITEMIDLIST *pidl = ILCreateFromPath(tchar);
 if (pidl) {
    SHOpenFolderAndSelectItems(pidl, 0, 0, 0);
    ILFree(pidl);
 }
}
....
QString path = qFile.absoluteFilePath();
BrowseToFile(path.replace('/', '\\'));

But this still doesn't solve the Problem with the Backslashes and Slashes in Folder/FileNames. Seems the conversion "filename.toStdString().c_str()" causes the Problem.

If i print (qDebug()) the path it looks like this: //NAS/Folder\uF022With\uF022BackSLASH/file.ext

I found this Question and this Solved my problem. QDesktopServices::openUrl with selecting specified file in explorer

  • Pretty sure you need to use double backslash, as single backslash is considered a byte. Try \\NAS\\FOLDER\\With\\BackSLASH\\file.ext – Michael Strobel Aug 29 '18 at 22:55
  • @MichaelStrobel that only applies to **string literals** at compile-time, not to user-provided data at runtime. – Remy Lebeau Aug 29 '18 at 23:38
  • @Jonas you really should be using the [`SHOpenFolderAndSelectItems()`](https://learn.microsoft.com/en-us/windows/desktop/api/shlobj_core/nf-shlobj_core-shopenfolderandselectitems) function instead of using `system()` to invoke `explorer.exe` via a command line. If you can navigate to the target folder in Explorer, you can also programmably obtain PIDLs to the folder and its files for use with the function. – Remy Lebeau Aug 29 '18 at 23:41
  • Question (maybe not directly relevant; just curious): Why are you not using `QProcess` instead of `system()`? You won't have to call `toStdString().c_str()` as it accepts a `QString`. As you are in Qt realm, you ought to make use of most of its facilities. – Azeem Aug 30 '18 at 05:21
  • Yeah i obviously didn't read the question too well. >. – Michael Strobel Aug 30 '18 at 05:46
  • Thanks for your answers. @remy i updated the code but still have the issue, i think its because of toStdString().c_str() this. – Jonas Sorgenfrei Aug 31 '18 at 22:53
  • @azeem i tried QProcess but there was the same issue with the unix backslashes, so i tried the system call. – Jonas Sorgenfrei Aug 31 '18 at 22:54
  • @JonasSorgenfrei well, for starters, `\uF022` represents a **private use** Unicode codepoint, it is not a real character. So that is the first thing you need to deal with. Second, you shouldn't be converting the `QString` to `std::string` at all, let alone to a `TCHAR[]` buffer. Converting a `QString` with non-ASCII characters in it to `std::string` will loss data. Use `ILCreateFromPathW()` instead, then you can use the `QString`'s Unicode data as-is, passing either `(WCHAR*)filename.data()` or `filename.toStdWString().c_str()` to `ILCreateFromPathW()`, thus ensuring there is no data loss. – Remy Lebeau Aug 31 '18 at 23:59
  • Possible duplicate of [Cross-platform way of constructing an FS path with Qt](https://stackoverflow.com/q/3194725/608639) and [Qt equivalent of PathAppend?](https://stackoverflow.com/q/13014145/608639). Also reference `QDir::separator`. – jww Sep 01 '18 at 00:06

2 Answers2

0

You need to use a function called SHOpenFolderAndSelectItems()to invoke the explorer.exe via command line. This is a sample code to do so:

void BrowseToFile(LPCTSTR filename)
{
    ITEMIDLIST *pidl = ILCreateFromPath(filename);
    if(pidl) {
        SHOpenFolderAndSelectItems(pidl,0,0,0);
        ILFree(pidl);
    }
}

Hope this help; cheers

Hasan Patel
  • 412
  • 7
  • 19
  • Hello @HasanPatel, i tried to use the code with the function call: BrowseToFile((LPCTSTR)"C:\\Windows\\CSUP.txt"); But it didn't work ... Can you tell me what i did wrong? – Jonas Sorgenfrei Aug 31 '18 at 22:20
  • 1
    Okay got it, the Cast was Wrong. I corrected it: TCHAR tchar[512]; USES_CONVERSION; _tcscpy(tchar, A2T(stdStr.c_str())); – Jonas Sorgenfrei Aug 31 '18 at 22:34
0

Qt is multi platform framework so you should take advantage of it as much as it is possible.

There is nice API which will do everything for you without such complications: QDesktopServices::openUrl.


edit: Based on comment there is already a solution on SO for that.
Marek R
  • 32,568
  • 6
  • 55
  • 140