How to delete a file that is using by windows? - delphi

Is there any way to delete a file when its using by any program or other process in windows?
I searched and found this 2 ways:
1- using RunOnce key in Registry;
I'm not gonna use this because i dont want to wait for windows restart or anything else... prefer to do it ontime!
2- using the way declared in this page: http://www.delphipages.com/forum/showthread.php?t=201190
the problem here is its useful under NT windows, i need a way works on all Windowses!
Thank you.

the problem here is its useful under NT windows, i need a way works on all Windowses!
All modern desktop Windowses (XP, Vista, 7) are also NT. Do you really need to work with NT<4 or Win98? Or even Win CE/Mobile/Phone? Probably not.
If you need to delete an open file straight away, about the only thing you can do is attach to each process using debugger privileges, see if it has any handles open on the file, and if so close them underneath it. You can do this the manual way using eg Process Explorer. Many applications won't react well to having their files closed on them; expect them to exception out when they try to do something with the dead handle.
Unfortunately there is no option in Windows to have Unix-style files that can exist attached to a file handle independently of being stored under a filename on disc.

You cant delete a file when someone is using it. No matter how hard you try, windows will not let you. It can work with some files, but in general it does not work.
What you can try is postpone the deletion, when no one is using the file. You can:
1 - use RunOnce, but you dont want that.
2 - Wait in a loop, trying to delete the file. Pseudo code:
DeleteFile
Check if you was able to delete or if file still exists.
if you are able to delete, then exit loop.
That is the best you can do, and what i could remeber.

Try MoveFileEx with MOVEFILE_DELAY_UNTIL_REBOOT flag. Will postpone move or delete action until reboot.
Edit:
If you don't whant to restart the only option is to close those handles. ProcessExplorer does that and works all the time and I have not seen any process to crash. See more info about enumeration handles in a process at
http://www.codeguru.com/forum/archive/index.php/t-176997.html. But keep in mint that you should enumerate all processes in the system and behave different on Vista+ (you need to be elevated)

Your files are most likely locked because some process has a handle open to them. That is the most common reason for the Access denied result when deleting or moving a file.
A really blunt way is to close that handle.
Then Handles tool from SysInternals (you can download the sources too) can do that for you: I have been successfully using that.
Note 1: You need administrative privileges to use it.
Note 2: Closing a handle from another process is considered very rude, and can make that process unstable.

Related

How do I make a simple public read-only WebDAV server with SabreDAV?

I recently began looking into WebDAV, as I found it to be an option for letting me play a Blu-ray folder remotely - i.e. without requiring the viewer to download the whole 24gb ISO first.
Add a WebDAV source in Kodi v18 to a Blu-ray folder - and it actually plays! Very awesome.
The server can also be mounted on Windows with
net use m: http://example.com/webdavfolder/
or in Linux with
sudo mount -t davfs http://example.com/webdavfolder/ /mnt/mywebdav
-and should then (in theory) play with any software media players that supports Blu-ray Disc Java (BD-J), such as PowerDVD and VLC.
vlc bluray:///mnt/mywebdav --bluray-menu
PowerDVD.exe AUTOPLAY BD m:
(Unless of course time-out values has been set too low, which seems to be the case for VLC at the moment).
Anyway, all this is great, except I can't figure out how to make my WebDAV server read-only. Currently anyone can delete files as they wish, and that's of course not optimal.
So far I've only experimented with SabreDAV, because afaik that's the only option I have if I want to keep using my existing webhost. Trying with very minimal setups, because I've read that minimal setups should default to a read-only solution. It just doesn't seem to happen.
I initially used the setup from http://sabre.io/dav/gettingstarted/ and tried removing some lines. Also tried calling chmod 0444 MainFolder -R on the webserver. And I can see that everything does get a read-only attribute. But it changes nothing. It's still possible to delete whatever I want. :-(
What am I missing?
Maybe I'm using the wrong technology for what I want to do? Is there some other/better way of offering a Blu-ray folder for remote viewing? (One that includes the whole experience - i.e. full Java menus etc).
I should probably mention that all of this is of course perfectly legal. It is my own Blu-ray project - not copyright material.
Also: Difficult to decide if this belongs on StackOverflow or SuperUser. I ended up posting it on StackOverflow because SabreDAV is about coding, and because there's no sabredav tag on SuperUser.
You have two options:
Create your own file/directory classes for sabre/dav that simply throw an error when trying to delete. You can basically start with a copy of Sabre\DAV\FS\Directory and Sabre\DAV\FS\File and change the methods that do writing.
Since you're considering just using linux file permissions, really the key thing you are missing is that that 'deleting' is not controlled on the file or directory you're trying to delete. To delete a file or directory in unix, all you need is write permissions on the parent directory. However, I wouldn't recommend going this route as doing this will just cause a weird error in sabre/dav, which might leave clients in a confused state. It would result in a 500 error, not the expected 403 error.

Delphi LoadLibrary Failing to find DLL other directory - any good options?

Two Delphi programs need to load foo.dll, which contains some code that injects a client-auth certificate into a SOAP request. foo.dll resides in c:\fooapp\foo.dll and is normally loaded by c:\fooapp\foo.exe. That works fine. The other program needs the same functionality, but it resides in c:\program files\unwantedstepchild\sadapp.exe. Both aps load the DLL with this code:
FOOLib := LoadLibrary('foo.dll');
...
If FOOLib <> 0 then
begin
FOOProc := GetProcAddress(FOOLib , 'xInjectCert');
FOOProc(myHttpRequest, Data, CertName);
end;
It works great for foo.exe, as the dll is right there. sadapp.exe fails to load the library, so FOOLib is 0, and the rest never gets called. The sadapp.exe program therefore silently fails to inject the cert, and when we test against production, it the cert is missing, do the connection fails. Obviously, we should have fully-qualified the path to the DLL. Without going into a lot of details, there were aspects of the testing that masked this problem until recently, and now it's basically too late to fix in code, as that would require a full regression test, and there isn't time for that.
Since we've painted ourselves into a corner, I need to know if there are any options that I've overlooked. While we can't change the code (for this release), we CAN tweak the installer. I've found that placing c:\fooapp into the path works. As does adding a second copy of foo.dll directly into c:\program files\unwantedstepchild.
c:\fooapp\foo.exe will always be running while sadapp.exe is running, so I was hoping that Windows would find it that way, but apparently not. Is there a way to tell Windows that I really want that same DLL? Maybe a manifest or something? This is the sort of "magic bullet" that I'm looking for.
I know I can:
Modify the windows path, probably in the installer. That's ugly.
Add a second copy of the DLL, directly into the unwantedstepchild folder. Also ugly
Delay the project while we code and test a proper fix. Unacceptable.
Other?
Thanks for any guidance, especially with "Other". I understand that this issue is not necessarily specific to Delphi. Thanks!
The MSDN documentation for LoadLibrary tells you exactly where Windows will search for the DLLs. You either have to hard-code the path to the DLL, put it in the same folder as your app, or put it in one of those default search locations from the LoadLibrary docs.
This is not exactly a solution for the question asked, but it would have helped me, when I stumpled upon this question:
You can extend the search path for LoadLibrary via SetDllDirectory.
From MSDN-Doku:
The search path can be altered using the SetDllDirectory function.
This solution is recommended instead of using SetCurrentDirectory or
hard-coding the full path to the DLL.
You would have needed to add one line before your LoadLibrary call(s):
SetDllDirectory(PChar('c:\fooapp'));
Or you can simply edit the environment variable "path" and place the path to the dll in there. In this case adding ;c:\fooapp to the path should be sufficient. Since the environment changes of a parent effects a child, you can also create a loader application which adjusts the its environment variable then spawns to your application.

How can I detect a debugger or other tool that might be analysing my software?

A very simple situation. I'm working on an application in Delphi 2007 which is often compiled as 'Release' but still runs under a debugger. And occasionally it will run under SilkTest too, for regression testing. While this is quite fun I want to do something special...
I want to detect if my application is running within a debugger/regression-tester and if that's the case, I want the application to know which tool is used! (Thus, when the application crashes, I could report this information in it's error report.)
Any suggestions, solutions?
You can check the parent process that started your application.
With CreateToolhelp32Snapshot/Process32First/Process32Next get the parent PID (PROCESSENTRY32.th32ParentProcessID or TProcessEntry32.th32ParentProcessID) for your application PID. Then get the filename for the parent PID to compare with the applications you want to check for, like SilkTest.
Check this article for code usage.
In addition to IsDebuggerPresent and CheckRemoteDebuggerPresent, you can also query PEB.BeingDebugged (PEB is Process Environment Block, to get PEB you must query TEB, which is the Thread Enviroment Block).
You're probably looking for the IsDebuggerPresent function.
To detect SilkTest, you could try to attach to a DLL which is used only by SilkTest in order to detect its presence. For example, if the Open Agent is attached to a process, Win32HookDll_x86.dll or Win32HookDll_amd64.dll will be present (the names can be easily found out with a tool like Process Explorer.
You can also do
if DebugHook <> 0 then ...

Delphi: Check whether file is in use

I want to write to/delete a file but sometimes I get a crash if the file is in use by another program. How do I check to see whether the file is opened by another process or I can open it for writing?
The problem is, that between the time you check to see if you could get exclusive access and opening the file, something else gets exclusive access to the file, and you get the exception anyway.
The only fool proof way to see if you can get an exclusive lock on a file is to try and get an exclusive lock on the file, if you get it you have it.
If not, you catch the exception, and either
Go do something else
Wait a while and try again
It's one of life’s situations where it's better to ask for forgiveness than permission :)
There is a new way to get the origin of file locking for Vista and up here:
http://www.remkoweijnen.nl/blog/2011/01/03/cannot-access-files-but-need-the-origin/
UserMode:
The best way to write to a locked file is to ask the user to close it in the other process. In batch processes you should ignore such a file and log the problem. Providing the name of the other process is a very good way to find a solution for the user.
Not sure in which programming language you'd like to check if you can write to a file. In Java, java.io.File.canWrite() can do the job for you.
General:
In UNIX-like OS, you can use the lsof command.
If you want to see which program holds a handle to your file, use the Process Monitor (download from MicroSoft).
This tool has a command line interface, so you could use your language's scripting interface (for example java.lang.Process) to run the tool and display a useful error message.
IsFileInUse as given in http://delphi.about.com/cs/adptips1999/a/bltip0999_3.htm

Log File Monitor

Is is possible to open a text file and read the contents while another application is updating the file, in such a way that it does not cause a lock conflict?
I need to monitor a log file from one application which is updated by another application each time an event occurs.
I do check if the file is in use before I try to read it, but that does not seem to work in all cases.
Thanks, Pieter
it depends on how the first app open that file.
i.e when calling CreateFile API to open a file, there is dwShareMode param which tells the api how to open it (if this was given 0, it can't be accessed from other applications IIRC).
otherwise there should be no problem with reading from that file.
if im not mistaken, to check if that file is being opened read only u can call
something like
CreateFile(pchar(fName), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) ;
Download Process Monitor from Sysinternals.
Open the filter dialog and add a "path" filter for your log file.
Start the log-writing application (I'll call this "logwriter").
Look for and click on the event where logwriter does a CreateFile.
Under "Detail", it should have "Desired Access: Generic Write". And it should have "ShareMode: Read", which corresponds to FILE_SHARE_READ in the call to CreateFile. What it means is, "I, logwriter, permit others to read my file".
Now run your log-reading application ("logreader"), and do the same exercise.
The Detail should have "Desired Access: Generic Read". And it should have "ShareMode: Read, Write", which means, "I, logreader, permit others, including logwriter, to read and write to the log file".
Those are the most sensible values, I think, and they will prevent locking. Other combinations may be permissible. There is a table here.
Now, you haven't said what happens when it "does not seem to work in all cases". What to do next will really depend on the details. Hopefully the above will give you enough information to work out what is going wrong.
You won't get a lock conflict because the writing application is very unlikely to have locked the file. Doing what you suggest generally works without problems (it's what the UNIX tail -f command does) and those minor glitches that do occur can be ignored. I've written a couple of log monitoring apps in te past that worked like this, with no problems.
Try using FileSystemWatcher to get events when a file is updated.
A more delphi friendly link
Quite apart from getting the file sharing to work right which may be impossible depending on what the other program requests, some programs will close the file between accesses.
I have had success in the past with my program waiting for the file to become available, then quickly opening it, grabbing the needed data and closing it. At least in DOS an attempt to access a locked file caused a few retries, and I bumped up this setting, so that if the other program tried for the file while I had it they would simply be delayed and never see an error.
I was even able to update the file (I made sure NOT to close it in between!) without the other program ever knowing a thing.
Ugly as sin but we couldn't change the other program so it was the only way to get the job done. It was deployed in-house for years, I never heard a peep from the users of that system. It finally went away when the machinery the other program controlled was retired.
XpoLog will do the trick without changing your env or code, XpoLog log monitor
Avar is right - you are at the mercy of the writing program here. If they are locking the file, then there are a couple of things you can do:
1 - Check for a change in the "last modified" date time - if that changes, then you know something has happened.
2 - If the mod datetime did change, then (depending on the size of the file) it might be good enough to create a copy of the file and check that.
we use "Tail for win32",
i know its not delphi but it might be useful
http://tailforwin32.sourceforge.net/

Resources