cpp: delete folder open by others - c++

If I really want to delete an (empty) folder, even if someone else has it opened, how can this be done with C++?
With a little help from DOS one could :
run NET FILES in a DOS box to determine all open files,
filter out the ids of the folder in question,
run NET FILES id /CLOSE in a DOS box with each id
Finally, call RemoveDirectory().
How to achieve the same purely in C++? (And I do not want to delay until reboot)

This might have worked in DOS but in a modern OS this can not be done.
On Windows you can use MoveFileEx with the MOVEFILE_DELAY_UNTIL_REBOOT flag if the folder is in use.
MoveFileEx(folderName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);

Related

How to call an .exe (C++) from windows console to create a folder in a different directory (or any directory)?

I have been researching a topic unsuccessfully for a couple of days. I'm a C ++ rookie, and as a practice i decided to make a basic (very very basic) copy of a version control system.
I have separated the project into steps. The first step (splited in activities) is:
The user searches, in the windows console, for the directory where the files he wants to track are located. Let's say he reached the desired path: C:\MyProjectFolder\ProjectToTrack>
Once inside ProjectToTrack folder the user applies this command: C:\MyProjectFolder\ProjectToTrack> emi track. "emi" is the name of the .EXE that i created in C ++ and the track parameter tells to the executable to create a hidden folder inside the ProjectToTrack folder.
Note: Obviously emi.exe is not in the path C:\MyProjectFolder\ProjectToTrack, let's say that emi.exe is in C:\ProgramFiles\emi\emi.exe
That's it, once this is done I will pass the second step, but I will take care of that problem later.
For now, after practicing and reviewing documentation i have achieved:
The .exe that creates a hidden folder in the path that was sent to it as a parameter, having said that ...
I also know how to send parameters to an .exe through windows console.
But, what I still can't get is:
Calling to emi.exe (C:\ProgramFiles\emi\emi.exe) through the console from any directory (necessary to track any file in any folder).
When C:\MyProjectFolder\ProjectToTrack> emi track is applied, I know how to send the parameter track to emi.exe, however, it is evident that I must also capture the current path (path i accessed from the console), so that emi.exe knows where to create the hidden trace folder; well, i still don't figure out how to capture and send this path to the main function of the .exe.
I have not found something related to what i need, english is not my default language so maybe i'm not using the correct terms, I hope that what i have said here is understandable.
PS.1. I'm currently trying to build this project using "windows.h", i would appreciate it if your comments were related to this library. Once i have understood this, I will start practicing with portability.
PS.2. I don't want a detailed solution, I just want an opinion or recommendation and maybe some links where to find what I need, I can do the rest.
Thank you!
Calling to emi.exe (C:\ProgramFiles\emi\emi.exe) through the console from any directory (necessary to track any file in any folder).
For this you need to add the folder of your executable (i.e. C:\ProgramFiles\emi) to the system global variable called PATH (both Windows and Linux work this way, and must be MAC OS as well but I never used it).
When C:\MyProjectFolder\ProjectToTrack> emi track is applied, I know how to send the parameter track to emi.exe, however, it is evident that I must also capture the current path (path i accessed from the console), so that emi.exe knows where to create the hidden trace folder; well, i still don't figure out how to capture and send this path to the main function of the .exe.
For this take a look at this STD function here: https://en.cppreference.com/w/cpp/filesystem/current_path (personally I've never used it but must be what's you're looking for).
Good luck with your endeavor!
If the user does not pass in a target path explicitly as a parameter, the EXE can use the Win32 GetCurrentDirectory() function, or in C++17 and later the standard std::filesystem::current_path() function, to retrieve its current "working directory".
If the user navigates a console window to C:\MyProjectFolder\ProjectToTrack and then executes C:\ProgramFiles\emi\emi.exe, the current working directory will initially be C:\MyProjectFolder\ProjectToTrack.

File in use in windows

How to know the process that blocked a file in windows, e.g.: when trying to delete a file that is in use, how to know the process that using that file?
Use Microsoft/Sysinternal's ProcessMonitor. Used to be file FileMon but I think everything is merged in ProcessMonitor now.
I had faced the same issue. I use Process Explorer for this. This is free and is like a task manager tool with advanced features.
Just press Ctrl+F or select Find and type the full or part name of the file or drive you're looking for. Select the file from the search result. This will take you to the bottom part of the window showing the file and the process which is keeping it open.
Just right click and select Close Handle. It will ask for yes / no, select yes and you're done. This tool can also be used if you're unable to safely remove a pen-drive or similar hardware. Just search for the drive letter (eg. G:) and close all the open handles.
Please ensure that you don't mis-use this tool to close handles to
system files, sabotage a system or cause harm to someone.
Hope this helps!
Vivek

Is There a Winapi way to Move a File to The Recycling Bin?

I've looking into a lot of different methods, but most of them require adding a file to System32, while I'm looking for a line that would allow you to move something to the recycle bin without anything being added to a computer, because I want something that would work on all Windows computers immediately. Rest assured that the deletion will not delete any major files and will ask for confirmation. I am thinking of using system("") in C++ to run the line.
See SHFileOperation with FOF_ALLOWUNDO.
There are a number of Recycle-Bin commandline tools mentioned here on alt.comp[1] (It even includes a fully automatic daemon that translates any file delete into 'move-to-recycle-bin')
The most popular seems to be Recycle from CmdUtils by Maddog, which is free and open source (GPL).
[1] Command line delete to recycle bin?

Cannot access INI files in "Program Files"

I wrote this C++ application that needs to check an INI file (“preference.ini”), and eventually modify it (e.g. if the user does not want to see the introduction form anymore). I created it in WinXP, and it works fine on the system where I compiled it (in many locations, including “Program Files”).
Problem:
In Win 7, it works fine if I put the complete program folder under “C”:\” (e.g. “C:\MyProgram”), but if I put it in “C:\Program Files (x86)\MyProgram”, it just retrieves some mysterious data (values not present in my INI file). When I change some settings and save them to file, it (apparently) save the changes (get no errors, but the changes are not there when I go and open the file...
I had some similar issue on a system with another WinXP system (not the one where I compiled it.
I used 'getcwd' to define the path at runtime, and I verified that it is getting it right, even under "Program Files (x86)":
char currentPath[MAXPATH];
getcwd(currentPath, MAXPATH);
std::string licensePath(currentPath);
licensePath.append("\\dat\\preference.ini");'
Any ideas? Thanks in advance for your help.
The answer is as #Kirill has already said - Win7 won't let you write data into Program Files unless you have higher than normal permissions (Run as Administrator). In this case it may be redirecting your file writes so that they still apear to work, but the data itself is not stored in Progam Files.
To add to his answer: In general (unless you want to run your app as an administrator), you should not write any program data to the Program Files folder.
Application settings should be stored in one of the AppData folders. You can get to your user's appdata manually by going to your start menu Search box (Vista/Win7) and typing %appdata%.
To find this location in your code, use SHGetFolderPath with CSIDL_APPDATA (current user) or CSIDL_COMMON_APPDATA (all users).
It could be related to that Windows use virtualization of the file system. You could read here about it. Check if your INI file is located in <root>\Users\<User_name>\AppData\Local\VirtualStore.
Seems to me that the licensePath: getcwd() + "\\dat\\preference.ini" is not what you would expect.
Log this value (console or in a log file) and see what exactly is the value of licencePath is when running you program from different folders.
This article is about game development but has the best description of how and why this happens that I've been able to find
http://msdn.microsoft.com/en-us/library/ee419001(VS.85).aspx
This paragraph from the article describes what is happening most likely -
Attempting to create or write a file
or directory under a folder which does
not grant write permission to the
process will fail under Windows Vista
if the application does not have
administrative privileges. If your
32-bit game executable is running in
legacy mode, because it did not
declare a requested execution level,
its write operations will succeed, but
they will be subjected to
virtualization as described in the
section "UAC Compatibility with Older
Games" later in this article.

C++ : Opening a file in non exclusive mode

I have to develop an application which parses a log file and sends specific data to a server. It has to run on both Linux and Windows.
The problem appears when I want to test the log rolling system (which appends .1 to the name of the creates a new one with the same name). On Windows (haven't tested yet on Linux) I can't rename a file that I have opened with std::ifstream() (exclusive access?) even if I open it in "input mode" (ios::in).
Is there a cross-platform way to open file in a non-exclusive way?
Is there a way to open file in a non-exclusive way,
Yes, using Win32, passing the various FILE_SHARE_Xxxx flags to CreateFile.
is it cross platform?
No, it requires platform-specific code.
Due to annoying backwards compatibility concerns (DOS applications, being single-tasking, assume that nothing can delete a file out from under them, i.e. that they can fclose() and then fopen() without anything going amiss; Win16 preserved this assumption to make porting DOS applications easier, Win32 preserved this assumption to make porting Win16 applications easier, and it's awful), Windows defaults to opening files exclusively.
The underlying OS infrastructure supports deleting/renaming open files (although I believe it does have the restriction that memory-mapped files cannot be deleted, which I think isn't a restriction found on *nix), but the default opening semantics do not.
C++ has no notion of any of this; the C++ operating environment is much the same as the DOS operating environment--no other applications running concurrently, so no need to control file sharing.
It's not the reading operation that's requiring the exclusive mode, it's the rename, because this is essentially the same as moving the file to a new location.
I'm not sure but I don't think this can be done. Try copying the file instead, and later delete/replace the old file when it is no longer read.
Win32 filesystem semantics require that a file you rename not be open (in any mode) at the time you do the rename. You will need to close the file, rename it, and then create the new log file.
Unix filesystem semantics allow you to rename a file that's open because the filename is just a pointer to the inode.
If you are only reading from the file I know it can be done with windows api CreateFile. Just specify FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE as the input to dwShareMode.
Unfortunally this is not crossplatform. But there might be something similar for Linux.
See msdn for more info on CreateFile.
EDIT: Just a quick note about Greg Hewgill comment. I've just tested with the FILE_SHARE* stuff (too be 100% sure). And it is possible to both delete and rename files in windows if you open read only and specify the FILE_SHARE* parameters.
I'd make sure you don't keep files open. This leads to weird stuff if your app crashes for example.
What I'd do:
Abstract (reading / writing / rolling over to a new file) into one class, and arrange closing of the file when you want to roll over to a new one in that class. (this is the neatest way, and since you already have the roll-over code you're already halfway there.)
If you must have multiple read/write access points, need all features of fstreams and don't want to write that complete a wrapper then the only cross platform solution I can think of is to always close the file when you don't need it, and have the roll-over code try to acquire exclusive access to the file a few times when it needs to roll-over before giving up.