I'm trying to make a program that deletes a list of files one by one, using system()
.
The reason I'm using system()
instead of remove()
is because remove()
doesn't support environment variables.
I've tried checking the return value, but my code seems to just always output that it's been deleted, even when it hasn't.
Code:
void fileLoop() {
std::vector<std::string> fileList = { "\"%userprofile%\\test.txt\"" };
while (!inter) {
for (int count = 0; count <= 0; count ) {
std::string moddedstring = "del /F " fileList[count];
DWORD checker = GetFileAttributes((LPCWSTR)fileList[count].c_str());
if (checker == INVALID_FILE_ATTRIBUTES) {
goto next;
}
else {
system(moddedstring.c_str());
MessageBoxW(NULL, L"File found, successfully deleted", L"File Deleted", MB_OK | MB_ICONWARNING);
}
next:
std::cout << "\n";
}
Sleep(500);
}
}
I thought there is some easy way to find this out. I haven't found a way like that yet.
I will be adding more paths later.
Update:
I've tried using OpenProcessToken()
with ExpandEnvironmentStringsForUserW()
to add ENVs
But it complains that my buffer is of type LPCSTR*
even when I set it to LPCSTR
Thanks!
CodePudding user response:
A better way to get the user's profile path is to simply ask the OS directly, via SHGetFolderPath(CSIDL_PROFILE)
or SHGetKnownFolderPath(FOLDERID_Profile)
.
Also, you should use DeleteFileA()
instead of system("del")
. There is no need to spawn an external console process when you can do the deletion directly. Also, because you are interested in error checking, which is much easier if you use the Win32 API directly.
Also, (LPCWSTR)fileList[count].c_str()
will not work like you think. You can't convert a const char*
to a const wchar_t*
using a simple typecast. Drop the typecast and use GetFileAttributesA()
instead.
Or, simply don't bother checking attributes at all. You can call DeleteFileA()
unconditionally and let it tell you if it actually succeeded or failed.
With that said, try something more like this:
#include <shlobj.h>
std::string getUserProfilePath() {
CHAR szPath[MAX_PATH];
if (FAILED(SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, szPath))) {
// error handling...
throw ...;
}
int len = lstrlenA(szPath);
szPath[len] = '\\';
return std::string(szPath, len 1);
/*
PWSTR pszPath;
if (FAILED(SHGetKnownFolderPath(FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pszPath))) {
// error handling...
throw ...;
}
int wlen = lstrlenW(pszPath);
int len = WideCharToMultiByte(0, 0, pszPath, wlen, NULL, 0, NULL, NULL);
if (len == 0) {
// error handling...
throw ...;
}
std::vector<CHAR> buffer(len 1);
len = WideCharToMultiByte(CP_ACP, 0, pszPath, wlen, buffer.data(), len, NULL, NULL);
if (len == 0) {
// error handling...
throw ...;
}
buffer[len] = '\\';
CoTaskMemFree(pszPath);
return std::wstring(buffer.data(), buffer.size());
*/
}
void fileLoop() {
std::vector<std::string> fileList = { getUserProfilePath() "test.txt" };
while (!inter) {
for (size_t count = 0; count < fileList.size(); count) {
if (DeleteFileA(fileList[count].c_str())) {
MessageBoxW(NULL, L"File found, successfully deleted", L"File Deleted", MB_OK | MB_ICONWARNING);
} else {
// error handling...
}
std::cout << "\n";
}
Sleep(500);
}
}
Alternatively, using Unicode strings instead (which you really should use when interacting with the filesystem):
#include <shlobj.h>
std::wstring getUserProfilePath() {
WCHAR szPath[MAX_PATH];
if (FAILED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, szPath))) {
// error handling...
throw ...;
}
int len = lstrlenW(szPath);
szPath[len] = '\\';
return std::wstring(szPath, len 1);
/*
PWSTR pszPath;
if (FAILED(SHGetKnownFolderPath(FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pszPath))) {
// error handling...
throw ...;
}
int len = lstrlenW(pszPath);
std::wstring sPath(len 1, '\0');
std::copy(pszPath, pszPath len, sPath.begin());
sPath[len] = '\\';
CoTaskMemFree(pszPath);
return sPath;
*/
}
void fileLoop() {
std::vector<std::wstring> fileList = { getUserProfilePath() L"test.txt" };
while (!inter) {
for (size_t count = 0; count < fileList.size(); count) {
if (DeleteFileW(fileList[count].c_str())) {
MessageBoxW(NULL, L"File found, successfully deleted", L"File Deleted", MB_OK | MB_ICONWARNING);
} else {
// error handling...
}
std::cout << "\n";
}
Sleep(500);
}
}
Even better, if you are using C 17 or later, consider using the <filesystem>
library instead:
#include <shlobj.h>
#include <filesystem>
using fs = std::filesystem;
fs::path getUserProfilePath() {
WCHAR szPath[MAX_PATH];
if (FAILED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, szPath))) {
// error handling...
throw ...;
}
return szPath;
/*
PWSTR pszPath;
if (FAILED(SHGetKnownFolderPath(FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pszPath))) {
// error handling...
throw ...;
}
fs::path pth(pszPath);
CoTaskMemFree(pszPath);
return pth;
*/
}
void fileLoop() {
std::vector<fs::path> fileList = { getUserProfilePath() / L"test.txt" };
while (!inter) {
for (auto &pth : fileList) {
std::error_code ec;
if (fs::remove(pth, ec)) {
MessageBoxW(NULL, L"File found, successfully deleted", L"File Deleted", MB_OK | MB_ICONWARNING);
} else {
// error handling...
}
std::cout << "\n";
}
Sleep(500);
}
}