Lazarus: How to check if file is in use? - pascal

I need to check if a file is in use before I try to get access to it. Is there way to do it in Lazarus environment?

Open the file with FileOpen(FileName, fmOpenReadWrite or fmShareExclusive) and check the result.
Update (thanks to Ken White's comment). This is not the direct answer to your question as FileOpen actually gets access to the file, but you shouldn't perform the check and then open the file, otherwise you'll get a race condition. You should open the file and then check if the open succeeded.
Opening a file with FileOpen and accessing the file through its handle may seem unfamiliar. You can achieve the same goal when opening a file with e.g. Rewrite inside a try-except block. I am not sure about Lazarus, but in Delphi using try-except with high-level file routines requires explicit resetting IOResult in case of exception (put SetInOutRes(0) into except section), otherwise the following file operation fails.

You don't. You try to open it, and handle the exception if and when you can't.
Checking to see if it's in use first serves no purpose.
Your code to see if it's in use says it's not
--->>> Another app opens the file, locking it
Your code to open file fails
Instead, use a normal try..except block:
try
FS := TFileStream.Create(YourFileName, fmOpenReadWrite, fmShareExclusive);
// Code to use file here
except
// Handle failure to access file
end;

Related

Write to file in use by another program

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.

Deleting a locked file created with TempFile

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.

Determine if file can be deleted on windows in go

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.

load yaml files from outside current directory

I want to load a yaml file from outside the working directory. I use c++. I used YAML::LoadFile("/home/example.yaml") and it complains YAML::BadFile. Please let me know if there is any way to do that.
YAML::LoadFile does nothing else than reading the file via std::ifstream. So your actual problem is that you cannot open the file at all in your application.
Check whether the file exists and has the proper permissions so that your application may open it. Try opening it directly with a std::ifstream and hand that over to YAML::Load so you can inspect the stream directly to see what error occurred.

Does CopyFile place any lock on the source file?

When I copy a file with CopyFile, will the source file be locked in any way?
Say - if the copy operation starts, and then someone wants to open the source file, will it succeed? What if the "someone" requests exclusive access to the file, will his Win32 API call (probably a CreateFile) fail, or will it wait (or whatever) until the copy operation is done?
If somebody requests exclusive access to a file that's already opened, that request will fail. Windows does not have a file open mode that consists of, "If somebody else is using the file, bump him off."
As I recall, CopyFile opens the source file so that others can read, but not write it.

Resources