PDA

View Full Version : Move file to trash on Windows



huilui
3rd June 2012, 10:57
Hi guys,

This is my first time trying to implement something using the Windows API... I want to send a file to Trash on Windows. I searched the internet and found a couple more or less helpful pages, and I eventually ended up with the following couple lines of code:



QString filepath = "C:\\some\\file";

QFile f(filepath);
if(!f.exists())
qDebug() << "ERROR: File doesn't exist";

SHFILEOPSTRUCT FileOPStruct;

filepath += '\0';

FileOPStruct.hwnd=NULL;
FileOPStruct.wFunc=FO_DELETE;
FileOPStruct.pFrom=LPCWSTR(filepath.toStdString(). c_str());
FileOPStruct.pTo=NULL;
FileOPStruct.fFlags=FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_ALLOWUNDO | FOF_SILENT;
FileOPStruct.hNameMappings=NULL;
FileOPStruct.lpszProgressTitle=NULL;

if(SHFileOperation(&FileOPStruct))
qDebug() << "ERROR: Deletion failed";
else
qDebug() << "Deleted :)";

The file in QString filepath exists (the check passes just fine), but I always get to "ERROR: Deletion failed", and the file (obviously) is still there. I don't have any previous experience of using the Win API and am just not able to resolve the issue... would anyone mind helping me?

Thanks a million!! :-)

d_stranz
3rd June 2012, 17:17
From a Microsoft Web page (http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795%28v=vs.85%29.aspx) (Google is your friend):


pFrom

Type: PCZZTSTR

Note This string must be double-null terminated.

A pointer to one or more source file names. These names should be fully qualified paths to prevent unexpected results.

Standard MS-DOS wildcard characters, such as "*", are permitted only in the file-name position. Using a wildcard character elsewhere in the string will lead to unpredictable results.

Although this member is declared as a single null-terminated string, it is actually a buffer that can hold multiple null-delimited file names. Each file name is terminated by a single NULL character. The last file name is terminated with a double NULL character ("\0\0") to indicate the end of the buffer.


So in line 13, you are simply pointing pFrom at a string that terminates in a *single* NULL. Not only that, put you are using the QString::toStdString().c_str() (which returns a char * pointer) methods instead of QString::toStdWString().c_str() (which returns w_char *), and then mangling that by casting it to a LPCWSTR. So who knows what the Windows call is seeing when it actually gets called?

You need to create a wchar_t array that is at least two characters longer than the length of your string, do a wide string copy of the QString::toStdWString().c_str() into it, then append an additional '\0' onto the end of that. That wchar_t array is what you give to pFrom before calling the shell method.