I've got a large folder on an offsite backup machine that gets populated with files by rsync (through deltacopy) every night (running windows xp) from the main work site. I've discovered some annoying folders that cannot be opened, or deleted, or even checked for file sizes. I get the such and such a folder is not accessible, access is denied message when I try to click on it in windows explorer. According to the windows explorer tooltip they are also "empty" and the properties of these folders say 0 bytes and 0 files.
I currently have a C# program that goes through every folder and file and tries to copy the whole backup directory to a dated backup-backup directory, which is how i discovered this problem in the first place. The regular System.IO library seems helpless against these blasted folders. Exceptions are thrown when I even try to access the folder path.
Does anyone have any clue how I could, say, on an access denied exception in my existing copy code, force the delete of these folders so rysnc can recreate the directory again and get the whole thing synced again?
First thing I think of when I see this is time to do a checkdisk. From the sounds of it, it feels more like a file system problem than something solvable the way you want to go about it.
Yes, try the awesome "Process Explorer" from Microsoft (formerly SysInternals).
Although it's for the processes in the windows filesystem, you could search for your folder in the explorer window & it will tell you who is locking it.
Once you release the process, your program would be able to delete the folder.
If that doesn't work, see if you can specify additional parameters to bruteforce the delete in your program.
It sounds like the filenames are either bad or contain characters that are invalid in Win32. Did you try to delete the directories with rd /r? Did you do a dir /x on them and try to delete the files/directories using their short names?
I would say that you first have to figure out why you can't delete the folders. Once you figure that out, you can write a program to fix it.
OK, so now that you know it's a permissions problem, the first step is to take ownership of the files (so you can set the permissions), then change the permissions so that you can delete the files.
Here's code to take ownership of a file:
WindowsIdentity currentUser = System.Security.Principal.WindowsIdentity.GetCurrent();
FileSecurity acl = File.GetAccessControl(filename);
acl.SetOwner(currentUser.User);
File.SetAccessControl(filename, security);
The trouble was that SYSTEM owned these files. I set deltacopy to run as administrator so that administrator would own the files deltacopy makes.
I guess windows is doing its job. The permissions are airtight. But if this happens again someday where I'd have to grab ownership from some other user to the current user (who has administrator permissions) how would I do that in code?
A question for another day I suppose. Thanks again everyone.
Related
StreamWriter can't write in few folders(and no exception thrown) but it can write in different folder locations. What is possible problem?
It is a Folder security issue, account I'm using doesn't have rights to write to that folder. So to write to it
1) Open Folder Property,
2) Navigate to 'Security' tab
3) Click 'Edit' and 'Add' in Newly opened tab
4) enter your pc name/... click 'Ok'
That should solve this issue. Thanks for your comments though :)
File virtualization could be culprit of this behaviour. Since no exception is thrown, file is obviously successfully written, but probably to another folder as Windows sometimes redirects file writes to user-accessible folder. See Common file and registry virtualization issues, specifically Scenario 2.
Virtualization is Microsoft's way how not to break compatibility with older programs that relies on writing files to system folders (such as Program Files, Windows, etc.). Generally, you should avoid writing files to these folders as it is considered bad practise. Instead, write files under Users folder if possible.
Some folder locations may require administrator rights, or you have some paths that even doesn't exist.
This one is proving very difficult to debug. Lets start with my situation:
I have an ASP.Net MVC3 web app developed with C# using .Net 4. Part of the system allows a user to upload a zip file. This is done fine, and the zip file is saved. There is also a Windows service which will periodically look for new zip files, extract them, do some work and then re-zip them back up. (I use System.IO.Compression for the zipping stuff). This part all works fine, after the processing I end up with a structure something like.
Object1Folder
\_ Input.zip
\_ ExtractedFolder
\_ Output.zip
There is also a feature that allows the user to delete the item, and the requirement is to delete the object folder, in this case "Object1Folder". Because I need to delete all sub folders and files I have the following recursive function to do the work...
public static void DeleteDirectory(string directoryPath)
{
string[] files = Directory.GetFiles(directoryPath);
string[] directories = Directory.GetDirectories(directoryPath);
foreach (string file in files)
{
File.SetAttributes(file, FileAttributes.Normal);
File.Delete(file);
}
foreach (string directory in directories)
{
DeleteDirectory(directory);
}
Directory.Delete(directoryPath, true);
}
Which is initially called something like...
DeleteDirectory("C:\\Objects\\Object1Folder");
But it doesn't work! Firstly, there is no error thrown, the code appears to successfully execute, which is annoying. But the result is that only the "Input.zip" file is removed. The "ExtractedFolder" and "Output.zip" file remains.
As far as I can tell, the code is sound. I can't see that it is a case that it doesn't attempt to delete the remaining file and folder. Unfortuantely, we don't have VS installed on the target server so I cannot step through the code and check that it attempts to delete them. Please point out if you can see this being a potential issue though?
My best guesses so far is that it is a permissions issue of some sort. What is interesting (perhaps) is that when I go to manual clean-up the problem (i.e. windows explorer delete of the "Object1Folder" it says "Denied" and asks me to confirm with the admin rights button thing that it does.
I know it's hard for you all to work the problem out, but I am looking for things that I should check to try and solve this problem. What kind of things should I ensure have correct permissions? What permissions do they need? Is there a good way for me to debug this issue? If something else has a hold of those files (maybe from the extraction process of the Windows Service), how can I check if this is the problem?
Some information about that server that might help: It's running "Windows Server 2008 R2 Datacenter" with service pack 1 and is 64-bit. The web app is assigned a user that is a member of both "Users" and "IIS_IUSRS".
Let me know if any of you need some extra information.
Have a look at the eventlog on the server; you might find an exception\error message there.
You could consider using Directory.Delete(path, true) so you delete the folder and all its content in one call (unless I do not understand your code correctly).
Have a look at files being in use. If a file is in use, the OS can't delete it. So make sure you are releasing all files correctly.
Finally, you can't force the files to be not in use so you might end up writing a clean script that runs every night to delete unwanted files and folders.
You really should use a temp destination folder for your unpacked files.
When they have been used you can try deleting them and if that fails just leave them.
The permission to write to a non-temp folder should not really be given to a presentation app residing in the iis.
Hi is it possible to prevent my .exe application on being renamed..?
here is the senario(my problem)
After i Run my program, (lets say i run MyApp.exe)
a unfriendly user suddenly for fun, renamed my MyApp.exe to ... lets say Goodtime.exe
after that. he log-off windows(xp) and then when my program is attempting to run on startup
MyApp.exe , i wont because it got renamed
is it possible to prevent this through codes?
thanks to anyone who would help =)
You can't really attempt to stop this. It's the user's computer and if they want to rename files on their computer they can do.
That is not possible.
However there is an alternative to do that.
You can set the user to have limited rights on his user account to the computer. In that case he cannot rename files in such a way he wanted. This is a restriction provided by the operating system in which only the administrators of the computer can set these restrictions to user accounts.
EDIT
What I mean here is if you are the administrator of the computer, as an alternative you can manually limit the privileges of the users who logs-in to the computer. For a better understanding on what I mean, please read the replies on my post. :)
You can place your application somewhere the user is less likely to go and rename it, like in the program files folder. But you can't stop them actually renaming the application.
If the user isn't an administrator on that machine they won't have permissions to rename files in the Program Files directory by default. One would hope that unfriendly users aren't administrators on the target machine (If they are, they can do a lot worse than renaming one application file).
You can check what name the executable has when it's being run.
But you cannot prevent a user from renaming it.
You might consider using clickonce publishing. For the life of me I can never guarantee I can find the ruddy application after installing it with clickonce so that might stop your friendly user messing with the app? ;-)
Here is some info on ClickOnce Publishing.
In essence, write an application, right click the project/solution, choose "Publish", then follow the wizard.
It won't guarantee the user won't be able to rename and mess with the files, but it'll make it harder.
By permissions way as most folks here explained.
Stupid and waste method is to have a daemon (Service) running accessing this file all time since system boot. That way system wont allow this executable to be renamed unless this daemon is stopped.
you can prevent renaming or moving your exe file while it is running.
Open the exe file within your exe file for reading and deny writing.
Keep this file open as long as it runs.
When I try to delete a file occurs the following exception:
The process cannot access the file ''
because it is being used by another
process.
My code looks like:
string[] files = Directory.GetFiles(#"C:\SEDocumentConverter\SOURCE");
foreach (string file in files)
{
File.Delete(file);
}
How can I solve this problem?
There is no way to delete a file that's currently being used by another process. You have to close whatever program has that file open first, before you can delete it.
If you don't already know which program that is, you can figure it out using Handle or Process Explorer.
You can P/Invoke the Windows MoveFileEx function, and use the MOVEFILE_DELAY_UNTIL_REBOOT flag, with a NULL destination name. This will delete the file when you reboot.
If the file is being used you're out of luck in trying to delete it. I can't tell you based on your code what process might be using the file(s), but try looking here or here or here, or at any of the other questions that show up as related to this one for guidance regarding this issue, and by all means follow the guidance from #Cody Gray about using Process Explorer.
slightly off topic: But it seems from your code that you are trying to delete all files of your folder.
Well instead of deleting them one by one we have another method Directory.Delete(path, True) which will delete the directory as contained in the string named path. Then you may recreate the directory if you want. But your problem may persist here too.
Another way is to find all open handles to the file and close them forcibly.
Works nice for you, bad for any apps which were using the file.
Could try that in UI with SysInternals ProcessExplorer.
Just rename this file. This will do the thing for whoever tries to write to that location.
Notes:
1) Of course the file is not deleted physically yet. Nice to do the MoveFileEx trick mentioned here around to complete the job.
2) If you want to delete a locked file to write smth new in its place (e.g. during build), just rename the file to a GUID name. If you need the folder to be clean, either use an ignored extension / hidden attribute, or rename the file to a path under %TEMP% (if on the same drive).
3) Not all locked files can be renamed, but it works for me for like 90% practical applications. You can move a file without affecting an open read/write/execute handle, it will continue working with the moved file just good (if moved within the same NTFS volume of course).
4) That's what Windows Installer would basically do before it asks you to please reboot somewhen soon: move the file away from your eyes, schedule to be removed upon reboot. Usually the newly-installed app can be used right away.
Practical Use:
My favorite is with MSBuild. Overriding the <Copy/> task with this stuff makes all the build go linux-way. You don't care if a prev version is still running somewhere, can still build&run. The old app keeps using the old version of the files. The new app loads the newly-written version.
Might be moving to %TEMP% if on the same drive (not my case though). I'd just rename them to an extension which is ignored with the current source control client.
I currently store a serialized XML file in the application directory that contains all changes specific to the program operation (not typical system or user configuration). Weeks ago, we started running into problems where it would not save correctly (read my previous question about this).
Long story short, we finally discovered that Windows 7 (and sometimes Vista) has an issue with writing into the application directory (specifically anything under Program Files). Now, if this were a normal configuration file I would simply store it under the user's APPDATA folder, but it is not normal. We run this on our own instrumentation, and misconfigurations are 99% of the reason customers have issues running our software. So we need this file to be accessible such that they can easily find it and email it to us. Appdata is hard enough for experienced users to find, much less very non-technological people.
We've also tried running it as Administrator, and making folder permissions wide open (we have control over every computer it runs on; it will never run on some random person's machine). But, these sometimes work, and sometimes do not.
The worst part is that when I write the file back out, it doesn't even throw an error; it simply writes it to some temporary directory that expires at some unknown point in time. Weeks later, our user will have an issue, and the configuration file is all messed up.
So, my question is where should I be storing this file, if not in Program Files? Should I just put it in APPDATA anyway, and make a small utility that emails it to us automatically in case of a problem? Or can I leave it in Program Files, but change some specific permission or registry key to allow it to operate normally?
It depends on whether or not the user needs to edit the file directly. If not, you should put them in %APPDATA%, which you can access via:
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
Otherwise, you might put it in My Documents:
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
Either way, putting it in Program Files is not a good idea. As you discovered, there are permission issues, even if running as Administrator.
For those users, you could build a button in that would open this directory. You could put it in an inconspicuous place that you could later direct them to.
For users that have an email client on their box, you could have a button that would create a new email with subject and automatically attach the file to the email.