Deleting a temporary directory - delphi

I have this code,
showmessage('C:\TEMP\'+openfiles[openfilelist.ItemIndex].ID);
if removedir('C:\TEMP\'+openfiles[openfilelist.ItemIndex].ID) then
showmessage('Removed')
else
showmessage('Failed');
The message shows C:\TEMP\0 and this directory does exist as the program created it earlier and used files inside it and then later deletes them. I can see the files and directories so I know they're there. The program successfully deletes the files but does not remove the directory.
If I hardcode the directory it works - this means that it accepts the string
C:\TEMP\0 but does not accept C:\TEMP\'+openfiles[openfilelist.ItemIndex].ID both equate to C:\TEMP\0. I cannot hardcode these directories, so what can I do? How do I convert from a string + string to whatever removedir() is expecting. I looked this up at Delphi basics and it's expecting a string.
I'm confused, since string + string = string. What is going on?

Make sure that neither your program nor any other program have the directory as their current working directory. When you recompile the program this may no longer be the case, so it may be a red herring that the hardcoded value works for you.

In addition to the other good answers, you should not be storing your temp folder in C:\TEMP. Use the value returned from GetTempFilename, instead. Unlike C:\TEMP, this location (which varies by operating system) will work on all operating systems, and all levels of user access control. This also eliminates the risk that the location you have hardcoded might also be hardcoded into another system.

If I understood correctly, openfiles[openfilelist.ItemIndex].ID is a string that contains number?
If so, did you check that it does not contain blanks? Something like this:
filename := 'C:\TEMP\' + trim(openfiles[openfilelist.ItemIndex].ID);
showmessage(filename);
if removedir(filename) then
showmessage('Removed')
else
showmessage('Failed');

What type of objects are openfiles and openfilelist?
Do they open folders at all, if so they may still be open when your trying to delete the folder.

Related

How to replace an entire file using FileManager

Let's say I have an UIImage cached in my Cache folder:
/.../Cache/Image Cache/<firstImage.id>
Now I want this folder to only ever have 10 image cached at a time, so if a new one comes in I want to take a file and replace the entire file and not just the contents of it. I.e.
/.../Cache/Image Cache/<firstImage.id> becomes
/.../Cache/Image Cache/<secondImage.id>.
As far as I can tell, replaceItem(at:withItemAt:backupItemName:options: only replaces the contents of the file but the file name remains the same. And I'm not too sure what replaceItem(at:withItemAt:backupItemName:options:resultingItemURL:) does even though it might be what I'm looking for (I don't know what an AutoreleasingUnsafeMutablePointer<NSURL?>? was but it sounded dangerous so I decided to leave it alone, specially since it has the word "unsafe" in it).
Is there a straightforward way of doing using an in-built function or is manually deleting the old file and adding the new file the best way? Please let me know.
Thanks in advance!

Convert logical to physical location

I have this logical location: |project://testProject/src/style.css| which I would like to convert to its related physical location. The location is first passed on to a Java file, where I try to convert it using the URIResolverRegistry.getInstance().logicalToPhysical(theLoc); method. The only problem is that it returns the exact location I passed it (the logical location). So it does not get converted. How come? Am I missing something? Or is there maybe another way to solve this?
Actually, project is supposed to be a "physical" URI already. If you want to convert it to an absolute path on the file system, then this is not supported directly.
However, if you are in an Eclipse context and you are free to depend on it, then rascal-eclipse offers this API:
IFile file = new ProjectURIResolver().resolveFile(myLoc);
String absolutePath = file.getLocation().toOSString();

Difference between App.Path and using a ShellObject.Self.Path

I am converting a VB6 application to VB.NET. In the code I am converting, it seems that the developer found the applications path two separate ways. However, it appears that he expects the two methods to produce different results.
Simple question:
What is the difference between calling these two lines of code:
strAppDataPath = CreateObject("Shell.Application").
NameSpace(ssfLOCALAPPDATA).Self.Path
and
strAppDataPath = App.Path
Explanation:
This is the code in question:
strAppDataPath = CreateObject("Shell.Application").
NameSpace(ssfLOCALAPPDATA).Self.Path
strAppDataPath = strAppDataPath & "\DataFolder\"
If (Not objFileSystem.FileExists(strAppDataPath & strAppDataFile)) Then
If (objFileSystem.FileExists(App.Path & strAppDataFile)) Then
...
End If
End If
The application's path is appended with \DataFolder\, and stored in the String strAppDatapath.
We check if the file strAppDataFile does not exist in strAppDatapath. Followed by checking if the file does exist in App.Path.
The concept behind what is going on makes sense to me: If the file doesn't exist in the subfolder, and if the file exists in App.Path, then do .... What I do not understand is why they didn't use one of the method for finding the application's path exclusively.
They don't point to the same path.
App.Path: Path where the currently executing EXE/DLL resides.
CreateObject("Shell.Application").NameSpace(ssfLOCALAPPDATA).Self.Path: Will point to the local (non-roaming) app data user folder. Same as the value in (user) environment variable LOCALAPPDATA.
Since Windows XP, the roaming & local app data paths are preferred places to store user settings and files (instead of the probably rights-restricted app folder).
So what the code does, is:
Look for strAppDataFile in %LOCALAPPDATA%\DataFolder\ (e.g. where "%LOCALAPPDATA%" could point to "C:\Users\UserName\AppData\Local\" on Windows Vista/7)
If not found, look for the same file in the application folder.
Please note that preferably applications should create an application specific sub-directory in local/roaming app data, e.g. use something like:
strAppDataPath = strAppDataPath & "\" & App.ProductName & "\DataFolder\"
' NOTE: Make sure to set the "Product Name" entry in the version information
' of the project settings
that could resolve to something like
"C:\Users\UserName\AppData\Local\My Application\DataFolder\"
My guess is that when the program is installed per-machine, a per-user location under LocalAppData is used. However during development or when installed per-user or as a portable application the application folder is used.
Some programmers use something like the code in question, while others make the decision by comparing App.Path against the ssfPROGRAMFILES path to determine the environment. The latter is probably preferable for a number of reasons but in the degenerate case where only one instance of the program exists on a machine they're equivalent.

Compose path (with boost::filesystem)

I have a file that describes input data, which is split into several other files. In my descriptor file, I first give the path A that tells where all the other files are found.
The originator may set either a relative (to location of the descriptor file) or absolute path.
When my program is called, the user gives the name of the descriptor file. It may not be in the current working directory, so the filename B given may also contain directories.
For my program to always find the input files at the right places, I need to combine this information. If the path A given is absolute, I need to just that one. If it is relative, I need to concatenate it to the path B (i.e. directory portion of the filename).
I thought boost::filesystem::complete may do the job for me. Unfortunately, it seems it is not. I also did not understand how to test wether a path given is absolute or not.
Any ideas?
Actually I was quite misguided first but now found the solution myself. When "base" holds the path A, and filename holds B:
boost::filesystem::path basepath(base), filepath(filename);
if (!basepath.is_complete())
basepath = filepath.remove_leaf() /= basepath;
base = basepath.string();
It works with Linux at least (where it would be very easy to do without boost, but oh well..), still have to test with Windows.

What are the rules for file extensions in Windows and Unix?

i'm currently using File::Basename fileparse to separate out a file's directory, base file name and it's extension using something like this:
my($myfile_name,$mydirectory, $file_extension) = fileparse($$rhash_params{'storage_full_path_location'},'\..{1,4}');
But see that there's a variation where you can actually provide a array of suffixes to the function, the array would contains all the known file extension.
So i'm trying to find a safe way to do this as i've seen that i've got some strange file names to process, i.e. file.0f1.htm, etc.
Question:
Is there a list of commonly used
extension for Windows and Unix
systems? But in my case it's mainly
for Windows.
And is it safe to
assume that all file names in
Windows should have an extension
ending with three letter characters?
And if there's an even better way to do this, please share.
Thanks.
Updates:
So obviously i must be drunk to forgot about those other extension. :)
Thus i've updated the current regex to allow from 1-4chars.
In this case, how should i change my regex line to properly match it?
Or is it an even better idea to look for all those commonly used extension from google and put them into an array to be passed to the function instead? My users are usually either students or teachers.
1. Is there a list of commonly used extension for Windows and Unix
systems? But in my case it's mainly
for Windows.
Yes, loads, all over the internet: http://www.google.com/search?q=common+file+extensions
2. And is it safe to assume that all file names in Windows should have
an extension ending with three letter
characters?
No, it's perfectly possible to use '.c', '.java', etc in Windows.
There are several fault assumptions in your code:
files need not have extensions. For example most binary executables on Unix/Linux/... don't have an extension at all. They are simply calls "bash", "wget", "sed", "Xorg", ...
extensions need not be three characters long, as #Alnitak already told you: ".c", ".java", ".mpeg", ".jpeg", ".html" are all perfectly fine and rather wide-spread extensions
cutting at the last "." is probably saver, but can still fail for files with no extensions or with multiple (or multi-part) extensions such as ".tar.gz", "tar.bz2", which occur rather often in the Unix/Linux/...-World

Resources