I'm creating a program (doesn't really matter the objective but it happens to be purely to mess around and learn more about windows) which reads and writes to a file which is in use by another program (for example notepad or word).
Obviously I'm having trouble deleting it as I'm getting an access denied error because the file is in use.
My first idea was I should use CloseHandle (kernel32.dll) to close the handle to that file, but I have no clue how to find that handle in the first place.
Any ideas? I'm doing this in Rust, so if there are any language-specific suggestions that would be best but if not, that's more than fine too.
On another note, what would happen to the program after the handle has been closed? Would word or notepad still be able to edit it or would a subsequent save delete the changes made by my program or perhaps it wouldn't even save?
This behaviour you observe is not related to Rust or to any other programming language, since this is system-specific.
The CreateFileA() win32 call offers, thanks to its third parameter (dwShareMode), a means to explicitly specify how sharing could happen with the open file.
Unfortunately (for you) this call is performed beforehand by the other program you try to hijack, not yours; your program cannot do anything, it's too late once the file is open.
Not that on UNIX the situation is different because the path to the file in the file-system is just a reference to the content of this file, as an open() operation is.
Thus, if you remove (rm) the file indicated by this path, you just remove the reference (unlink()) but not its actual content if it is still referenced by an open file descriptor.
The actual deletion of the file content only happens when no reference to it exists anymore.
Related
I have a GUI (lxn/walk) app patcher that downloads a file via ftp, streams it to a temporary file and extracts the contents to update the local files. The remove file command is deferred.
This works unless the user exits the program while the file is downloading, then the file isn’t deleted.
I tried to fix this by doing a graceful exit by catching the signal and removing the file there. But unfortunately it throws an error that the file can’t be deleted because it is being used by another program. Which makes sense because the another program is actually itself still writing to the temporary file.
Now I’m stuck and don’t know what to do to make sure that the temporary file is automatically gone once the patcher is not running. How do I do that correctly?
The file could also be created as a normal file, not just a temp file. I would just like to ask too, where in windows is best to write a temporary file?
Now I’m stuck and don’t know what to do to make sure that the temporary file is automatically gone once the patcher is not running. How do I do that correctly?
There are no guaranteed ways to accomplish this as many things beyond the control of the application can cause it to exit. A power failure or kernel panic due to some hardware issue can crash the machine or force it to be restarted.
A strategy that is in common use is to implement a check on program startup for the status of the previous run. Some applications create a lock file at start and remove it on graceful exit. If this lock file exists when the program is restarted, this means the previous run did not result in a clean exit, and the application can take any corrective action. The exact action to be taken depends on the nature of the application, some refuse to start, others give warnings to users.
I would just like to ask too, where in windows is best to write a temporary file?
Each OS has its own location for temporary files. If you eliminate the dir argument to TempFile, it will create it in the appropriate location, as mentioned in the documentation:
TempFile creates a new temporary file in the directory dir, opens the
file for reading and writing, and returns the resulting *os.File. The
filename is generated by taking pattern and adding a random string to
the end. If pattern includes a "*", the random string replaces the
last "*". If dir is the empty string, TempFile uses the default
directory for temporary files (see os.TempDir). Multiple programs
calling TempFile simultaneously will not choose the same file. The
caller can use f.Name() to find the pathname of the file. It is the
caller's responsibility to remove the file when no longer needed.
From os.TempDir we see the following:
On Unix systems, it returns $TMPDIR if non-empty, else /tmp. On
Windows, it uses GetTempPath, returning the first non-empty value
from %TMP%, %TEMP%, %USERPROFILE%, or the Windows directory. On
Plan 9, it returns /tmp.
The directory is neither guaranteed to exist nor have accessible
permissions.
Is there any reasonable way to determine if a file can be successfully deleted on the Windows platform using the go language?
I've tried using various flags calling os.OpenFile including using os.O_TRUNC all the calls are successful yet remove will fail when the file is in use.
I've also tried using the locking mechanisms specific to Windows (i.e. kern.NewProc("LockFileEx") etc) and these seem to get exclusive locks successfully yet os.Remove (after unlocking) will fail.
I realize that if between the test and the remove call if another process opens the file delete will still fail but this isn't the case here, with my tests I know the file is in use yet I can't find a test to tell me that (other than actually calling os.Remove)
On Windows, the Go os.Remove function uses the Windows DeleteFile function. You must satisfy certain conditions for a Windows file to be deleted. For example, "The DeleteFile function marks a file for deletion on close. Therefore, the file deletion does not occur until the last handle to the file is closed", "The DeleteFile function fails if an application attempts to delete a file that has other handles open for normal I/O", and so on.
I am using an application that stores its cache in a file. The thing is that I don't care about the data, so I would like the file to be removed right after the application finishes. A perfect use case for a temporary file.
Problem - the application is being called from a framework that is embedded inside another framework. So I don't have a place, where I could create the file upfront easily, and if the file does not exist (it can be empty), the application refuses to start.
Solution (as I imagine it) - I would like to have /dev/tmp file, that would help me to fool the application, similarly as we use /dev/null, /dev/zero
How I imagine this to work?
application opens /dev/tmp
kernel creates a temporary file in /tmp directory and gives to the app a file descriptor pointing to it
when file descriptor gets closed, kernel removes automatically the file
Do you know if there is a way I could achieve this behaviour?
EDIT
Apparently there is no such functionality. So forget about my problem (I will solve it somehow) and let me rephrase the question.
Nowadays applications handle temporary files on their own. They create them and remove afterwards. If there would be a /dev/tmp pseudofile, then kernel would manage temporary files for us (even if an application would crash). Do you think it would make sense?
I'm making a simple VB.net application, which basically asks the user for multiple files and later it will need to access the selected files and modify them.
Right now, I'm saving the full paths of the selected files, and in the future, the application will iterate through each path, open the file from such path, and modify it.
The problem with that is that the user could select a file (so the full path is saved) and then they delete or move the file before my application modifies it.
Normally, I'd throw an error saying "File not found", but I'm under the impression that Windows had a feature that would disallow you from deleting/moving/renaming a file because "a program was using it" - which is a feature that would fit way better for my application.
I'm not very advanced with VB.NET, but I suppose that if I "open" a file using my application (with some IO thing), the feature I mentioned earlier would indeed trigger and the user would be unable to modify the file because it is "opened" by my application.
However, since my only desire is to "reserve" files, it seems to be quite wasteful to actually open them when I don't really need to (yet). Is there a way to tell Windows I need a certain file to be intact?
Opening files (with specifying desired sharing mode) is the way to do that.
I don't believe there is anything really wrong with opening multiple files (also you still will not be able to do anything for cases like removing of removable drive). In old times there were restrictions on number of opened files per process, but I it no longer practical limitation - Pushing the Limits of Windows: Handles
There is an easy solution: open each file in exclusive mode.
It should look like this:
Sub test()
Dim FS = System.IO.File.Open("path", IO.FileMode.Open, IO.FileAccess.ReadWrite, IO.FileShare.None)
End Sub
But beware: You have opened a file handle and if you code responsible for closing files fails without terminating the application files will still be locked for very long (till app shuts down).
You can use a using clause or a try/catch/finally clause - I don't know enough about your program to recommend anyone.
I have set up a file extension in the Registry for my program as Windows requires.
In the Registry, under shell/open/command, I've got:
"C:\MyProgramPath\MyProgram.exe" "%1"
This works fine for me. When someone clicks on one or more files associated with my application, my application correctly opens the file(s) but each one is opened in a separate program instance.
Is there any way I can do this and open up all files in one program instance?
This is a rather common question, and it has really nothing to do with Windows file extensions. When you doubleclick a file of your program's custom type, Windows will start the associated application MyProgram.exe and pass the file name %1 as a command-line argument.
Now, if you want only a single instance of your application, you need to do this:
When your program (MyProgram.exe) starts, it should check if there is already an instance of it running.
If there is a previous instance, the new instance of MyProgram.exe should send a message (of some kind, not necessarily a windows message) to the old instance telling it to open the file %1.
The new instance should now terminate itself.
A very simplistic approach
There are several ways of accomplishing this. One of the simplest ways is to set a registry key/value each time your application starts, and remove it when the application exists. Then, when (a new instance of) your application starts, prior to setting this key/value, it should check if it is already set. If, so, follow the steps (2) and (3) above. This might not be the most stable approach (in fact it is a very bad idea, since you cannot guarantee that the app will remove the key/value when it exists if it does so abnormally), but it will give you the basic idea. Other, perhaps better ways, include FindWindow and, even better, the use of mutexes.
Step two might be implemented by sending a windows message (maybe WM_COPYDATA), or by setting a registry value, or, by writing a file, or ... There are many ways of communication between different processess.
The details
Since this is a rather common question, it has been dealt with before. See, for instance, this Delphi-specific article.
You can when using DDE. See http://cc.embarcadero.com/Item/17787 for an example in Delphi.
EDIT:
The link you gave talks about another method: using IDropTarget. This might fit better with your already running drag and drop capabilities.