Results 1 to 4 of 4
  1. #1
    InunoTaishou's Avatar
    Join Date
    Jan 2009
    Gender
    male
    Location
    The Internet
    Posts
    446
    Reputation
    20
    Thanks
    950
    My Mood
    Relaxed

    Moving directories failing

    Been working on this for a week now. The goal is to move everything, directories and files, withing a Base directory (Ex. C:\Windows\) to a sub-directory in the base directory (Ex. C:\Windows\System32\drivers\etc\)

    Currently, I have the program get all of the directories and sub-directories starting at the base and store it in a vector. Afterwards it uses a range for loop to go through the vector, creates the name of that directory in an a folder I'm using for a backup (_wmkdir), and then checks if there are any files in the directory. If there are files, it moves them to the backup (using SHFILEOPSTRUCT). After backing everything up I am moving all of the old directories to a trash folder (again with SHFILEOPSTRUCT. I've tried FO_DELETE and FO_MOVE, the old directories will be deleted either way).

    Now the problem, some directories will fail to be moved to the .trash folder. I don't know why, it's not consistent, and it's not every folder. It does move it but there is still a "ghost" of he old directory. It's not accessible and I can't delete it. If I close the program the ghost directory is gone.

    Is there an easier way or is there a fix?

    Delete and move operations
    Code:
    bool explorer_operation(std::wstring pathFrom, std::wstring pathTo, size_t operation, bool allow_undo = false)
    {
    	for (int i = 0; i != 2; ++i) {
    		pathFrom.push_back('\0');
    		pathTo.push_back('\0');
    	}
    
    	SHFILEOPSTRUCT fileop;
    	fileop.hwnd = NULL;    // no status display
    	fileop.wFunc = operation;
    	fileop.pFrom = pathFrom.c_str();
    	fileop.pTo = pathTo.c_str();
    	fileop.fFlags = FOF_NOCONFIRMATION | FOF_SILENT;  // do not prompt the user
    
    	if (allow_undo)
    		fileop.fFlags |= FOF_ALLOWUNDO;
    
    	fileop.fAnyOperationsAborted = FALSE;
    	fileop.lpszProgressTitle = NULL;
    	fileop.hNameMappings = NULL;
    
    	return (SHFileOperation(&fileop) == 0);
    }
    
    bool file_move(std::wstring from, std::wstring to)
    {
    	return explorer_operation(from, to, FO_MOVE);
    }
    
    bool DeleteDirectory(std::wstring path)
    {
    	return explorer_operation(path, L"", FO_DELETE);
    }
    and the functions that are backing up the old files
    Just a note: sorting the vector does make the paths sort properly for the base directory all the way to the last sub-directory in the base
    Code:
    C:\Windows\
    C:\Windows\System32\
    C:\Windows\System32\en-US\
    C:\Windows\System32\en-US\Licenses\
    C:\Windows\System32\en-US\Licenses\eval\
    C:\Windows\System32\en-US\Licenses\eval\Enterprise\
    Is how the vector is sorted and then I'm going through it in reverse order.

    Code:
    void backupLastVersion(const std::wstring &source, const std::wstring &dest, const std::wstring &testDir)
    {
    	std::wcout << "Backing up last version" << std::endl;
    	vwstr directories, files, dir_to_delete;
    	const std::set<std::wstring> exclude_files{ L"unrar.dll", L"Installer.log", L"installer.log" };
    
    	std::wstring currentDir = format_directory(getWorkingDir());
    	std::wstring lastVer = currentDir;
    	size_t start = 0;
    
    	if ((start = dest.find_last_of('\\')) != std::wstring::npos) {
    		lastVer += { dest.begin() + start + 1, dest.end() };
    	}
    
    	listDirectories(directories, testDir);
    	listFiles(files, testDir);
    
    	for (vwstr::size_type i = 0; i != directories.size(); i++) {
    		listDirectories(directories, directories[i]);
    	}
    
    	std::sort(directories.begin(), directories.end());
    
    	for (auto &wstr : directories) {
    		if (wstr.size() >= testDir.size()) {
    			std::wstring _dest = format_directory(dest + std::wstring{ wstr.begin() + testDir.size(), wstr.end() });
    
    			_wmkdir(_dest.c_str());
    
    			if (listFiles(files, wstr)) {
    				for (auto file : files) {
    					// Get the current file name
    					std::wstring current_file{ file.begin() + file.find_last_of('\\') + 1, file.end() };
    
    					if (file.size() >= testDir.size() &&
    						// If the current file path has the last version directory in it, exclude
    						file.find(lastVer) == std::wstring::npos &&
    						// If the current file path has .rar in it, exclude
    						file.find(L".rar") == std::wstring::npos &&
    						// If the current file name is in the excluded files list, exclude
    						exclude_files.find(current_file) == exclude_files.end()) {
    						// Create the destination path
    						auto _dest = dest + std::wstring{ file.begin() + testDir.size(), file.end() };
    						file_move(file, _dest);
    					}
    				}
    
    				files.clear();
    			}
    			else {
    				std::wcout << L"No files found in directory " << wstr << std::endl;
    			}
    
    			if (wstr != (testDir + L"Data") && wstr != (testDir + L"Data\\lib") && wstr != (testDir + L"Data\\lib\\installer") && wstr.find(L"installer") == std::wstring::npos) {
    				dir_to_delete.push_back(wstr);
    				wstr = L"";
    			}
    		}
    	}
    	std::wcout << L"Created all directories" << std::endl;
    	std::wcout << L"Copied all files" << std::endl;
    	std::cin.get();
    
    	for (auto iter = dir_to_delete.rbegin(); iter != dir_to_delete.rend(); ++iter) {
    		if (*iter != testDir && !iter->empty()) {
    			if (!file_move(format_directory(*iter), L"C:\\Users\\Kyle\\Documents\\Visual Studio 2013\\Projects\\C++ Primer Projects\\Debug\\test\\Data\\lib\\installer\\trash\\")) {
    				std::wcout << L"Error moving directory " << (*iter) << std::endl;
    			}
    			/*
    			if (!DeleteDirectory(format_directory(*iter))) {
    				std::wcout << L"Error deleting directory " << ((*iter) << std::endl;
    			}
    			*/
    		}
    	}
    	std::wcout << L"Moved all directories" << std::endl;
    	std::cin.get();
    
    	std::wcout << L"Backup complete" << std::endl;
    }
    
    DWORD listDirectories(vwstr &directories, const std::wstring dir)
    {
    	if (dir == L"") return 0;
    	// Declare variables, count used for number of directories, hFind for FindFirstFile, data used to store file data
    	DWORD count = 0;
    	HANDLE hFind = INVALID_HANDLE_VALUE;
    	WIN32_FIND_DATA data;
    
    	// Find first file in the current working directory, storying data in data as a reference
    	hFind = FindFirstFile((dir + (dir.back() == '\\' ? L"*" : L"\\*")).c_str(), &data);
    
    	// If hFind is not an invalid handle
    	if (hFind != INVALID_HANDLE_VALUE) {
    		// Go through each file in the directory
    		do
    		{
    			// If the file attributes is a directory
    			if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
    			{
    				// Add directory to my directories (std::vector<std::wstring). if (count > 1) because I want to ignore the "." and ".." directories
    				if (count > 1) {
    					directories.push_back(dir + (dir.back() == '\\' ? L"" : L"\\") + data.cFileName);
    				}	// end if (count > 1)
    
    				// Add 1 to count, used as the return for how many directories found in the current directory
    				count++;
    			}
    		} while (FindNextFile(hFind, &data) != 0);// end while (FindNextFile(hFind, &data) != 0);
    	}
    
    	// Return count of directories found
    	return (count - 2);
    }   // end DWORD listDirectories(std::vector<std::wstring>&, cosnt std::wstring)
    
    DWORD listFiles(vwstr &files, const std::wstring dir)
    {
    	if (dir == L"") return 0;
    	// Declare variables, count used for number of directories, hFind for FindFirstFile, data used to store file data
    	DWORD count = 0;
    	HANDLE hFind = INVALID_HANDLE_VALUE;
    	WIN32_FIND_DATA data;
    
    	// Find first file in the current working directory, storying data in data as a reference
    	hFind = FindFirstFile((dir + (dir.back() == '\\' ? L"*.*" : L"\\*.*")).c_str(), &data);
    
    	// If hFind is not an invalid handle
    	if (hFind != INVALID_HANDLE_VALUE) {
    		// Go through each file in the directory
    		do
    		{
    			// If the file attributes is a directory
    			if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
    			{
    				files.push_back(dir + (dir.back() == '\\' ? L"" : L"\\") + data.cFileName);
    				// Add 1 to count, used as the return for how many directories found in the current directory
    				count++;
    			}
    		} while (FindNextFile(hFind, &data) != 0);// end while (FindNextFile(hFind, &data) != 0);
    	}
    
    	// Return count of directories found
    	return count;
    }   // end DWORD listFiles(vwstr&, const std::wstring)
    I've tried _wrename to move the directories (That completely fails every time) and I've tried doing FO_DELETE and FO_MOVE to get rid of the old unused directories. Files move properly without any problems every time but getting rid of the directories is breaking.
    https://www.mpgh.net/forum/signaturepics/sigpic210976_1.gif

  2. #2
    殺す必要がある唯一のものは殺されるために準備され人 々である。
    Premium Member
    Hitokiri~'s Avatar
    Join Date
    Oct 2012
    Gender
    female
    Location
    Cancer.
    Posts
    1,201
    Reputation
    24
    Thanks
    937
    My Mood
    Bitchy
    I smell journal errors

  3. #3
    InunoTaishou's Avatar
    Join Date
    Jan 2009
    Gender
    male
    Location
    The Internet
    Posts
    446
    Reputation
    20
    Thanks
    950
    My Mood
    Relaxed
    Any recommendations to do file operations?
    https://www.mpgh.net/forum/signaturepics/sigpic210976_1.gif

  4. #4
    InunoTaishou's Avatar
    Join Date
    Jan 2009
    Gender
    male
    Location
    The Internet
    Posts
    446
    Reputation
    20
    Thanks
    950
    My Mood
    Relaxed
    And after another hour of googling I needed to close my HANDLE (FindClose(hFind)) I was using to list all files and directories in a directory

    Code:
        DWORD count = 0;
        HANDLE hFind = INVALID_HANDLE_VALUE;
        WIN32_FIND_DATA data;
    
        hFind = FindFirstFile((dir + (dir.back() == '\\' ? L"*" : L"\\*")).c_str(), &data);
    
        if (hFind != INVALID_HANDLE_VALUE) {
            // go through each file
            do
            {
                // if file is a directory
                if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {
                    // if (count > 1) because I want to ignore the "." and ".." directories
                    if (count > 1) {
                        directories.push_back(dir + (dir.back() == '\\' ? L"" : L"\\") + data.cFileName);
                    }    // end if (count > 1)
    
                    // Add 1 to count, used as the return for how many directories found in the current directory
                    count++;
                }
            } while (FindNextFile(hFind, &data) != 0);    // end do ... while (FindNextFile(hFind, &data) != 0);
        }
    
        FindClose(hFind);
    I knew something was still open but I thought it was some memory being used in SHFileOperation. I was wrong lol
    https://www.mpgh.net/forum/signaturepics/sigpic210976_1.gif

Similar Threads

  1. moving back to kwr
    By Hyperion in forum WarRock - International Hacks
    Replies: 30
    Last Post: 07-02-2007, 09:54 PM
  2. failed account validation error
    By XqwertyX in forum WarRock Korea Hacks
    Replies: 3
    Last Post: 05-17-2007, 03:24 PM
  3. Replies: 10
    Last Post: 03-06-2007, 04:52 PM
  4. Nick Burns + Wang! MOVE!!!
    By arunforce in forum General
    Replies: 4
    Last Post: 02-22-2007, 10:11 PM
  5. MPGH being moved again...
    By Dave84311 in forum News & Announcements
    Replies: 0
    Last Post: 01-31-2007, 01:07 PM