Suppress system() output - c++

First off, I do mostly C#, .Net development so go easy on me if this is a stupid question.
I am implementing an Ericcson open source project to convert an image to another format. The problem is that on conversion an output to a console happens as follows...
1 file(s) copied.
I need to suppress this dialog that pops up. I just want to execute the system command with no output. I think I have isolated the area of the code causing this.
void writeOutputFile(char *dstfile, uint8* img, uint8* alphaimg, int width, int height)
{
char str[300];
if(format!=ETC2PACKAGE_R_NO_MIPMAPS&&format!=ETC2PACKAGE_RG_NO_MIPMAPS)
{
fWritePPM("tmp.ppm",width,height,img,8,false);
//PRINTF("Saved file tmp.ppm \n\n");
}
else if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
{
fWritePPM("tmp.ppm",width,height,img,16,false);
}
if(format==ETC2PACKAGE_RGBA_NO_MIPMAPS||format==ETC2PACKAGE_RGBA1_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
fWritePGM("alphaout.pgm",width,height,alphaimg,false,8);
if(format==ETC2PACKAGE_R_NO_MIPMAPS)
fWritePGM("alphaout.pgm",width,height,alphaimg,false,16);
// Delete destination file if it exists
if(fileExist(dstfile))
{
sprintf(str, "del %s\n",dstfile);
system(str);
}
int q = find_pos_of_extension(dstfile);
if(!strcmp(&dstfile[q],".ppm")&&format!=ETC2PACKAGE_R_NO_MIPMAPS)
{
// Already a .ppm file. Just rename.
sprintf(str,"move tmp.ppm %s\n",dstfile);
//PRINTF("Renaming destination file to %s\n",dstfile);
}
else
{
// Converting from .ppm to other file format
//
// Use your favorite command line image converter program,
// for instance Image Magick. Just make sure the syntax can
// be written as below:
//
// C:\imconv source.ppm dest.jpg
//
if(format==ETC2PACKAGE_RGBA_NO_MIPMAPS||format==ETC2PACKAGE_RGBA1_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
{
// Somewhere after version 6.7.1-2 of ImageMagick the following command gives the wrong result due to a bug.
// sprintf(str,"composite -compose CopyOpacity alphaout.pgm tmp.ppm %s\n",dstfile);
// Instead we read the file and write a tga.
//PRINTF("Converting destination file from .ppm/.pgm to %s with alpha\n",dstfile);
int rw, rh;
unsigned char *pixelsRGB;
unsigned char *pixelsA;
fReadPPM("tmp.ppm", rw, rh, pixelsRGB, 8);
fReadPGM("alphaout.pgm", rw, rh, pixelsA, 8);
fWriteTGAfromRGBandA(dstfile, rw, rh, pixelsRGB, pixelsA, true);
free(pixelsRGB);
free(pixelsA);
sprintf(str,""); // Nothing to execute.
}
else if(format==ETC2PACKAGE_R_NO_MIPMAPS)
{
sprintf(str,"imconv alphaout.pgm %s\n",dstfile);
//PRINTF("Converting destination file from .pgm to %s\n",dstfile);
}
else
{
sprintf(str,"imconv tmp.ppm %s\n",dstfile);
//PRINTF("Converting destination file from .ppm to %s\n",dstfile);
}
}
// Execute system call
system(str);
free(img);
if(alphaimg!=NULL)
free(alphaimg);
}
I am lost at this point about how to suppress the console that pops up. As we iterate through images via a reference to the dll, many many console windows flash on the screen. Need to stop this from happening.
Help is greatly appreciated.

Try doing:
strcat( str, " > nul" ) // for Windows or
//strcat( str, " > /dev/null" ) // for Unix
system( str )
If it doesn't help then this may help:
#include <string>
#include <ShellAPI.h>
int system_no_output( std::string command )
{
command.insert( 0, "/C " );
SHELLEXECUTEINFOA ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = "cmd.exe";
ShExecInfo.lpParameters = command.c_str();
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_HIDE;
ShExecInfo.hInstApp = NULL;
if( ShellExecuteExA( &ShExecInfo ) == FALSE )
return -1;
WaitForSingleObject( ShExecInfo.hProcess, INFINITE );
DWORD rv;
GetExitCodeProcess( ShExecInfo.hProcess, &rv );
CloseHandle( ShExecInfo.hProcess );
return rv;
}
and replace all your system() calls to system_no_output() ones.

To fully suppress the output, redirect both stdout and stderr:
system("command >nul 2>nul");

Take a look here if you're using C#. The class used in C# is ProcessStartInfo.
In the example in the link, look at the OpenWithStartInfo member function which will minimize the console.
As far as doing this in C++, take a look at the spawn family of functions here.

Related

How to get information about a file for programming on windows

In Linux, we can use the function stat() to get a file info, and use the type st.mode to judge the rights of the file before we can do some operation on it. In windows, I make a lot of attempts, but little help.
At first, I want to use the function GetSecurityInfo, but I can't get the handle argument. I did find some solutions, but they all need use fopen function which is exactly what I want to avoid. Becasue I want to not do anything substantial with the file until I can determine what permissions it has.
Then I try the GetFileSecurityA function, but useless. The following is my code, and I get an error code 998 from getlasterror
void GetFilesInfo(std::string& path)
{
char *path1 = new char[1024];
strcpy(path1, path.c_str());
SECURITY_INFORMATION FLAGS = ATTRIBUTE_SECURITY_INFORMATION;
PSECURITY_DESCRIPTOR file_security_descriptor = new char[1024];
LPDWORD minNeedWords = 0;
if(GetFileSecurityA(path1, FLAGS, file_security_descriptor, 1024, minNeedWords) == 0)
error_die("GetFileInfo");
else
std::cout << file_security_descriptor << std::endl;
}
The answer is as previous comments said. I answered the question for completion.
#include <Windows.h>
void main()
{
TCHAR FileName[] = {L"C:\\Users\\Path\\To\\FileName.extension" };
DWORD LengthNeeded = 0;
SECURITY_DESCRIPTOR* sp = (SECURITY_DESCRIPTOR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,100);
BOOL rs = GetFileSecurity(FileName, ATTRIBUTE_SECURITY_INFORMATION, sp,100,&LengthNeeded);
if (!rs)
{
DWORD e = GetLastError();
//return;
}
HeapFree(GetProcessHeap(), 0,sp);
}

Move files to Trash/Recycle Bin in Qt

Is there a Qt function to move files to Recycle Bin instead of truly deleting them, for OSes that support it, or do I need to use OS-specific code?
Since Qt 5.15.0 Alpha, this method has been added, which should be what you were looking for.
bool QFile::moveToTrash()
The corresponding code changes can be found here.
(This issue is old and the corresponding Bugreport at https://bugreports.qt.io/browse/QTBUG-47703 has already been posted, but I currently lack the reputation to comment, and found this to be a useful information.)
Qt doesnt provide a MoveToTrash. Here's a part of my code
for Windows
#ifdef Q_OS_WIN32
#include "windows.h"
void MoveToTrashImpl( QString file ){
QFileInfo fileinfo( file );
if( !fileinfo.exists() )
throw OdtCore::Exception( "File doesnt exists, cant move to trash" );
WCHAR from[ MAX_PATH ];
memset( from, 0, sizeof( from ));
int l = fileinfo.absoluteFilePath().toWCharArray( from );
Q_ASSERT( 0 <= l && l < MAX_PATH );
from[ l ] = '\0';
SHFILEOPSTRUCT fileop;
memset( &fileop, 0, sizeof( fileop ) );
fileop.wFunc = FO_DELETE;
fileop.pFrom = from;
fileop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
int rv = SHFileOperation( &fileop );
if( 0 != rv ){
qDebug() << rv << QString::number( rv ).toInt( 0, 8 );
throw OdtCore::Exception( "move to trash failed" );
}
}
#endif
and for Linux
#ifdef Q_OS_LINUX
bool TrashInitialized = false;
QString TrashPath;
QString TrashPathInfo;
QString TrashPathFiles;
void MoveToTrashImpl( QString file ){
#ifdef QT_GUI_LIB
if( !TrashInitialized ){
QStringList paths;
const char* xdg_data_home = getenv( "XDG_DATA_HOME" );
if( xdg_data_home ){
qDebug() << "XDG_DATA_HOME not yet tested";
QString xdgTrash( xdg_data_home );
paths.append( xdgTrash + "/Trash" );
}
QString home = QStandardPaths::writableLocation( QStandardPaths::HomeLocation );
paths.append( home + "/.local/share/Trash" );
paths.append( home + "/.trash" );
foreach( QString path, paths ){
if( TrashPath.isEmpty() ){
QDir dir( path );
if( dir.exists() ){
TrashPath = path;
}
}
}
if( TrashPath.isEmpty() )
throw Exception( "Cant detect trash folder" );
TrashPathInfo = TrashPath + "/info";
TrashPathFiles = TrashPath + "/files";
if( !QDir( TrashPathInfo ).exists() || !QDir( TrashPathFiles ).exists() )
throw Exception( "Trash doesnt looks like FreeDesktop.org Trash specification" );
TrashInitialized = true;
}
QFileInfo original( file );
if( !original.exists() )
throw Exception( "File doesnt exists, cant move to trash" );
QString info;
info += "[Trash Info]\nPath=";
info += original.absoluteFilePath();
info += "\nDeletionDate=";
info += QDateTime::currentDateTime().toString("yyyy-MM-ddThh:mm:ss.zzzZ");
info += "\n";
QString trashname = original.fileName();
QString infopath = TrashPathInfo + "/" + trashname + ".trashinfo";
QString filepath = TrashPathFiles + "/" + trashname;
int nr = 1;
while( QFileInfo( infopath ).exists() || QFileInfo( filepath ).exists() ){
nr++;
trashname = original.baseName() + "." + QString::number( nr );
if( !original.completeSuffix().isEmpty() ){
trashname += QString( "." ) + original.completeSuffix();
}
infopath = TrashPathInfo + "/" + trashname + ".trashinfo";
filepath = TrashPathFiles + "/" + trashname;
}
QDir dir;
if( !dir.rename( original.absoluteFilePath(), filepath ) ){
throw Exception( "move to trash failed" );
}
File infofile;
infofile.createUtf8( infopath, info );
#else
Q_UNUSED( file );
throw Exception( "Trash in server-mode not supported" );
#endif
}
#endif
There is no API yet.
https://bugreports.qt.io/browse/QTBUG-181
The issue is closed and the fix version is: Some future release
Edit: A new issue has been opened at https://bugreports.qt.io/browse/QTBUG-47703.
Edit Apparently it is now done in 5.15.0 Alpha bool QFile::moveToTrash()
I think that there is no cross-platform way. Simple moving files to "trash" location will not give effect, because user may switch off this possibility.
Maybe, this url will help: http://www.hardcoded.net/articles/send-files-to-trash-on-all-platforms.htm
I'm relatively certain that there is no Qt API that wraps this for all supported platforms. That means, unfortunately, that you will have to write platform-specific code.
I don't know anything about where/how Linux distributions store deleted files, and I imagine that it probably varies depending on which file manager you're using. I believe that moving files to a ~/.Trash folder is the standard way of doing it, but I'm not sure if this is reliable. For example, in the case of files stored on external volumes.
Things are a bit easier on Mac OS X, where there is a supported API to do this: FSMoveObjectToTrashSync, provided by Core Services. At least, that's how I remember you're supposed to do it. The documentation claims that this method is now deprecated in OS X 10.8. I have no idea what the recommended alternative is.
As a Windows programmer, I think that platform is much easier. :-) The basic solution is to call the SHFileOperation function:
#include <Windows.h> // general Windows header file
#include <ShellAPI.h> // for shell functions, like SHFileOperation
#include <string> // (or use QString)
void RecycleFileOnWindows()
{
std::wstring path = L"C:\\Users\\Administrator\\Documents\\deleteme.txt";
path.append(1, L'\0'); // path string must be double nul-terminated
SHFILEOPSTRUCT shfos = {};
shfos.hwnd = nullptr; // handle to window that will own generated windows, if applicable
shfos.wFunc = FO_DELETE;
shfos.pFrom = path.c_str();
shfos.pTo = nullptr; // not used for deletion operations
shfos.fFlags = FOF_ALLOWUNDO; // use the recycle bin
const int retVal = SHFileOperation(&shfos);
if (retVal != 0)
{
// The operation failed...
if (shfos.fAnyOperationsAborted)
{
// ...but that's because the user canceled.
MessageBox(nullptr, L"Operation was canceled", nullptr, MB_OK | MB_ICONINFORMATION);
}
else
{
// ...for one of the other reasons given in the documentation.
MessageBox(nullptr, L"Operation failed", nullptr, MB_OK | MB_ICONERROR);
}
}
}
There are also flags that you can set to customize confirmation, error reporting, and other behavior. The linked documentation contains all the details you need to build upon this basic example.
On Windows Vista and later, the SHFileOperation function has been superseded by the methods provided by the IFileOperation interface. If you're targeting only these later versions of Windows, you should prefer to use this interface. Otherwise, SHFileOperation will continue to work fine.
if(QSysInfo::kernelType()=="linux")
{
QDateTime currentTime(QDateTime::currentDateTime()); // save System time
QString trashFilePath=QDir::homePath()+"/.local/share/Trash/files/"; // trash file path contain delete files
QString trashInfoPath=QDir::homePath()+"/.local/share/Trash/info/"; // trash info path contain delete files information
// create file format for trash info file----- START
QFile infoFile(trashInfoPath+FileName.completeBaseName()+"."+FileName.completeSuffix()+".trashinfo"); //filename+extension+.trashinfo // create file information file in /.local/share/Trash/info/ folder
infoFile.open(QIODevice::ReadWrite);
QTextStream stream(&infoFile); // for write data on open file
stream<<"[Trash Info]"<<endl;
stream<<"Path="+QString(QUrl::toPercentEncoding(FileName.absoluteFilePath(),"~_-./"))<<endl; // convert path string in percentage decoding scheme string
stream<<"DeletionDate="+currentTime.toString("yyyy-MM-dd")+"T"+currentTime.toString("hh:mm:ss")<<endl; // get date and time format YYYY-MM-DDThh:mm:ss
infoFile.close();
// create info file format of trash file----- END
QDir file;
file.rename(FileName.absoluteFilePath(),trashFilePath+FileName.completeBaseName()+"."+FileName.completeSuffix()); // rename(file old path, file trash path)
}
Trash files in linux exist /home/user_name/.local/share/Trash/files/ directory but it also require info file for each trash file which exist in /home/user_name/.local/share/Trash/info/ directory. when we want to move file into trash, actually move file into /home/user_name/.local/share/Trash/files/ directory and create info file in /home/user_name/.local/share/Trash/info/ directory. inside .trashinfo format use percentage decoding scheme for set file path where file existed, info file also contain time and date of deletion.

fontconfig finds no fonts

I'm trying to make my C++ program detect installed fonts on my Win32 machine. I tried fontconfig by taking the library from the GTK+ bundle.
I use the following test code:
#include<fontconfig.h>
FcBool success = FcInit ();
if ( !success ) {
return false;
}
FcConfig *config = FcInitLoadConfigAndFonts ();
if(!config) {
return false;
}
FcChar8 *s, *file;
FcPattern *p = FcPatternCreate();
FcObjectSet *os = FcObjectSetBuild (FC_FAMILY,NULL);
FcFontSet *fs = FcFontList(config, p, os);
LOG("Total fonts: %d\n", fs->nfont);
for (int i=0; fs && i < fs->nfont; i++) {
FcPattern *font = fs->fonts[i];
s = FcNameUnparse(font);
LOG("Font: %s\n", s);
free(s);
if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch) {
LOG("Filename: %s\n", file);
}
}
// destroy objects here ...
Unfortunately this test application only prints:
Total fonts: 0
I know there are fonts installed on my machine and I know that Gimp2.0 detects them, so there must be something wrong with my test code. Does anyone have any idea?
Other than linking the fontconfig-1.dll, I did nothing else. I haven't created any config files or anything, because I couldn't read anywhere about having to do that.
I am open to your suggestions, thanks!
Instead of:
FcConfig *config = FcInitLoadConfigAndFonts ();
Try:
FcConfig *config = FcConfigCreate();
FcConfigAppFontAddDir(config, (const FcChar8 *)"C:\\Windows\\Fonts");
(this is the lazy version, you should adapt it to go off GetWindowsDirectory...)

creating/opening file on disk returns EAGAIN

As title says I'm getting this error while trying to open file for binary writing(mode doesnt seem matter).
My app uses libev to handle sockets(non blocking/epoll backend) and while parsing client packets i want at some point where i receive fileupload message to start writing down to disk data i get from server.
I couldn't google anything about EAGAIN(Resource temporarily unavailable) message and file opening..
These are methods I've tried:
fopen( ... ) returns EAGAIN
using ofstream/fstream's open(...) by creating them on heap(new) returns EAGAIN
using ofstream/fstream's open(...) staticly as class member (ofstream m_ofFile;) works, but strangly compiler generates code which calls ofstream destructor and closes file before exiting class method im calling .open from. Now that contradicts with my C++ knowledge where for class members which are class types, destructors are called right before class owner's..
edit:
#Joachim
You're right, I'm not acually getting this error..(method #1. gonna test method #2 again soon). File opens regulary and i get regular FILE*. That happens in Init(...) function of my class, but then when I call OnFileChunk later on m_hFile is 0 and therefor i cant write to it. Here is complete class code:
class CFileTransferCS
{
wstring m_wszfile;
wstring m_wszLocalUserFolderPath;
int m_nChunkIndex;
int m_nWrittenBytes;
int m_nFileSize;
FILE* m_hFile;
CFileTransferCS( const CFileTransferCS& c ){}
CFileTransferCS& operator=( const CFileTransferCS& c ){}
public:
CFileTransferCS( );
CFileTransferCS( wstring file, uint32_t size );
void OnFileChunk( char* FileChunk, int size );
void Init( wstring file, uint32_t size );
void SetLocalUserLocalPath( wstring path );
};
CFileTransferCS::CFileTransferCS( )
{
m_hFile = NULL;
m_wszLocalUserFolderPath = L"";
m_nChunkIndex = 0;
m_nWrittenBytes = 0;
}
CFileTransferCS::CFileTransferCS( wstring file, uint32_t size )
{
m_nChunkIndex = 0;
m_nWrittenBytes = 0;
m_wszfile = file;
m_nFileSize = size;
wstring wszFullFilePath = m_wszLocalUserFolderPath + m_wszfile.substr( m_wszfile.find_last_of(L"\\") + 1 );
// string fp = string( file.begin(),file.end() );
string fp ="test.bin"; //for testing purposes
this->m_hFile = fopen(fp.c_str(),"wb");
printf("fp: %s hFile %d\n",fp.c_str(),this->m_hFile); //everything's fine here...
if(!this->m_hFile)
{
perror ("cant open file ");
}
}
void CFileTransferCS::SetLocalUserLocalPath( wstring path )
{
m_wszLocalUserFolderPath = path;
}
void CFileTransferCS::Init( wstring file, uint32_t size )
{
// If previous transfer session got interrupted for whatever reason
// close and delete old file and open new one
if( this->m_hFile )
{
printf("init CS transfer: deleting old file///\n");
fclose( this->m_hFile );
string fp = string( file.begin(),file.end() );
if( remove( fp.c_str() ))
{
//cant delete file...
}
}
CFileTransferCS( file, size );
}
void CFileTransferCS::OnFileChunk( char* FileChunk, int size )
{
for (;;)
{
printf("ofc: hFile %d\n",this->m_hFile); //m_hFile is 0 here...
if( !this->m_hFile )
{
// m_pofFile->open("kurac.txt",fstream::out);
printf("file not opened!\n");
break;
}
int nBytesWritten = fwrite( FileChunk, 1, size, this->m_hFile );
if( !nBytesWritten )
{
perror("file write!!\n");
break;
}
m_nWrittenBytes+=size;
if( m_nWrittenBytes == m_nFileSize )
{
fclose( m_hFile );
printf("file uplaod transfer finished!!!\n");
}
break;
}
printf("CFileTransferCS::OnFileChunk size: %d m_nWrittenBytes: %d m_nFileSize: %d\n",size,m_nWrittenBytes,m_nFileSize);
}
final edit:
I got it.. Calling explicitly CFileTransferCS( wstring file, uint32_t size ) constructor made problems.. Calling constructor like this explicitly caused that this pointer in it wasnt original one(that Init function was using) so when i was opening file from it and saving handle to m_hFile, i was doing it in some other object(now im not sure if CFileTransferCS(..) call allocated memory for CFileTransferCS object or it corrupted some other part of memory randomly.. will check it out with IDA later on )
Thanks to everyone and my apologies.
Regards, Mike –
#MikeJacksons answer:
Calling explicitly CFileTransferCS( wstring file, uint32_t size ) constructor made problems. Calling constructor like this explicitly caused that this pointer in it wasnt original one(that Init function was using) so when i was opening file from it and saving handle to m_hFile, i was doing it in some other object(now im not sure if CFileTransferCS(..) call allocated memory for CFileTransferCS object or it corrupted some other part of memory randomly.. will check it out with IDA later on ) Thanks everyone and my apologies.
Removed: CFileTransferCS( file, size );
(No need to appologize Mike, looks like you did a great job hunting down the bug).

Why is RemoveDirectory function not deleting the top most folder?

refer: codeguru.com/forum/showthread.php?t=239271
When using the function below to delete folders, all folders, subfolders and files are getting deleted except for the top most folder. Say for the path c:\folder1\folder2 every thing under folder2 is deleted except for folder2.
BOOL DeleteDirectory(const TCHAR* sPath)
{
HANDLE hFind; // file handle
WIN32_FIND_DATA FindFileData;
TCHAR DirPath[MAX_PATH];
TCHAR FileName[MAX_PATH];
_tcscpy(DirPath,sPath);
_tcscat(DirPath,_T("\\"));
_tcscpy(FileName,sPath);
_tcscat(FileName,_T("\\*")); // searching all files
int nRet = 0;
hFind = FindFirstFile(FileName, &FindFileData); // find the first file
if( hFind != INVALID_HANDLE_VALUE )
{
do
{
if( IsDots(FindFileData.cFileName) )
continue; //if not directory continue
_tcscpy(FileName + _tcslen(DirPath), FindFileData.cFileName);
if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
// we have found a directory, recurse
if( !DeleteDirectory(FileName) )
break; // directory couldn't be deleted
}
else
{
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
_wchmod(FileName, _S_IWRITE); // change read-only file mode
if( !DeleteFile(FileName) )
break; // file couldn't be deleted
}
}while( FindNextFile(hFind, &FindFileData) );
nRet = FindClose(hFind); // closing file handle
}
return RemoveDirectory(sPath); // remove the empty (maybe not) directory and returns zero when RemoveDirectory function fails
}
Any help in finding the issue is appreciated.
During debugging I noticed that the FindClose function was successfully closing the file handle but GetLastError was returning 32 ("The process cannot access the file because it is being used by another process") However I have no clue after trying with process explorer.
Whilst you can delete a directory this way, it's simpler to let the system do it for you by calling SHFileOperation passing FO_DELETE. Remember that you must double null-terminate the string you pass to this API.
I believe you have to close the file handle before the recursive call. Which means after exiting the recursive call you must again set your your file handle to something appropriate.
SHFileOperation may be a better solution; I am just answering the OP's question of why their code wasn't working as intended.
Refer:http://www.codeguru.com/forum/archive/index.php/t-337897.html
Given below is the code to delete directory using SHFileOperation
bool DeleteDirectory(LPCTSTR lpszDir, bool noRecycleBin = true)
{
int len = _tcslen(lpszDir);
TCHAR* pszFrom = new TCHAR[len+4]; //4 to handle wide char
//_tcscpy(pszFrom, lpszDir); //todo:remove warning//;//convet wchar to char*
wcscpy_s (pszFrom, len+2, lpszDir);
pszFrom[len] = 0;
pszFrom[len+1] = 0;
SHFILEOPSTRUCT fileop;
fileop.hwnd = NULL; // no status display
fileop.wFunc = FO_DELETE; // delete operation
fileop.pFrom = pszFrom; // source file name as double null terminated string
fileop.pTo = NULL; // no destination needed
fileop.fFlags = FOF_NOCONFIRMATION|FOF_SILENT; // do not prompt the user
if(!noRecycleBin)
fileop.fFlags |= FOF_ALLOWUNDO;
fileop.fAnyOperationsAborted = FALSE;
fileop.lpszProgressTitle = NULL;
fileop.hNameMappings = NULL;
int ret = SHFileOperation(&fileop); //SHFileOperation returns zero if successful; otherwise nonzero
delete [] pszFrom;
return (0 == ret);
}