Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Can't erase file 2

Status
Not open for further replies.

jimstarr

Programmer
Feb 6, 2001
975
US
Some old code I inherited:

usefile = (ADDBS(SYS(2023))) + "register"
USE IN (usefile)
deletefile = (ADDBS(SYS(2023))) + "register.*"
ERASE &deletefile

On the ERASE command I get error #3, "File is in use." I can't figure this out. Any ideas? Thanks!


Jim
 
is it used with a different alias?

Ali Koumaiha
TeknoSoft Inc.
Michigan
 
Your code opens a a file called register in the temporary path and then attempts to delete it - while it is still open.

Put another USE just before the delete.

Code:
usefile = (ADDBS(SYS(2023))) +  "register"   
USE IN (usefile)   
deletefile = (ADDBS(SYS(2023))) +  "register.*"   
USE
ERASE &deletefile

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.
 
Ali has a good idea in that that file may be open with another alias or within another datasession.

Rest of this off topic, as a sidenote: Griff, you're misunderstanding here.

USE IN (usefile) does close the workarea named register (as that is the value of usefile), only USE (usefile) would open it, but USE IN (usefile) closes it.

Alos, it's not good advice to code a simple pure USE to close something.

In general: "USE IN workarea" does close what is open in the workarea (and not opens anything). "USE filename" opens the file in the current workarea and closes what is open in it. "USE filename IN workarea" does open the file in the given workarea and closes what is in it.

Not using an IN clause let's USE work in the current workarea and not giving a file to open does not open something but only closes what is in the current workarea, that's what a pure USE does. But only giving the IN clause means closeing that, not opening it.

I strongly suggest not to ever use a pure USE without any further clauses to close the current workarea. If you want to close something, do not only select it previously, but say what you want to close via IN. If you want to open something, give a file to open, if you want it not to close something else add an "IN 0". This usage of the in clause is actually nicely done by the inherited code. More accurate would be USE IN SELECT(usefile), which is error prone, even if usefile would not be open. But the IN clause accepts both workare alias names and workarea numbers.

If you don't use the clause, you close whatever is in the current workarea, and that might not be what you expect, EVEN if you SELECT that alias right before USE.

For reasons of multithreading, which can change the workarea, eg via a grid selecting it's rowsource alias or a timer changing workareas. If you can make use of the IN clause, do so, Griff. Not doing so is really a bad habit. Even just for sparing a line of code, make use of the IN clause.

The grid hijacking the current workarea also is a known "bug" or unwanted behavior making REPORT FORM not work in the condition this should report from another table than the grid's rowsource.

If a command offers an IN clause, then use it, whatever command, be it USE, DELETE (non SQL), SET ORDER, etc. The only important command that does not offer the IN clause is LOCATE, we have to live with that.

Griff, I don't want to offend you and it's not like comitting a crime, but for me this is really important, when it comes to usage of third party or inherited code. Much more important to me than usage of mdots to prevent code using fields instead of variables.

In this case the previous programmer hasn't made a mistake in that sense. What is worth changing is ERASE (usefile) instead of using macro sustitution, as that can fail on file names with spaces in them, but that's another story of when to use macro substitution vs name expressions.

Bye, Olaf.
 
Now ON topic again,

What you could simply try is USE IN register or USE IN SELECT("register"), as giving the full file name may fail with the IN clause.

If that doesn't help, we're back to finding out where the file is open additionally to the register alias of the current datasession. As the file is within SYS(2023), which is the temp directory, it's unlikely the file is in use from another user or on another computer, but it might might still be open with another alias or in another datasession.

To see that you can add this code for debugging purposes to detect where and with which alias the file is open. I suggest you do this for debugging and then see what you can do to change how the files is used. In general files in the temp dir should rather be cursors, not tables, cursors close and also erase from disk automatic. Even better, they are more performant than table files on disc, as they mainly remain in RAM memory.

Ok here's code to check if a file is open (as alias) somewhere within the current foxpro session or application:

Code:
Local loFileWorkareas, lcFile
lcFile = (Addbs(Sys(2023))) + "register"

loFileWorkareas = FileWorkareas(lcFile)
If loFileWorkareas.Count>0
   For Each loFileWoarkarea In loFileWorkareas
      ? lcFile + " is open in datasession ", loFileWorkarea.Session, " in workarea alias", loFileWorkarea.Workarea
   EndFor 
Else
   ? "File "+lcFile+" not open."
EndIf

Function FileWorkareas(tcFileToCheck)
   tcFileToCheck = ForceExt(Evl(tcFileToCheck,""),"dbf")
   
   Local loFileWorkareas, loFileWorkarea
   Local lnSession, laUsed[2], laSessions[1]
   loFileWorkareas = Createobject("Collection")
   
   If File(tcFileToCheck)
      ASessions(laSessions)
      For Each lnSession In laSessions
          If AUsed(laUsed,lnSession,tcFileToCheck)>0
             loFileWorkarea = CreateObject("Empty")
             AddProperty(loFileWorkarea,"Session",lnSession)
             AddProperty(loFileWorkarea,"Workarea",laUsed[1])
             loFileWorkareas.Add(loFileWorkarea)
          EndIf
      EndFor
   Endif

   Return loFileWorkareas
Enddefine

Bye, Olaf.
 
minor error: It should be ENDFunction, not Enddefine at the end of the code.
 
Doh Olaf,

No offence taken - I should have read it properly before answering!


Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.
 
Hi Olaf,

On this statement

? lcFile + " is open in datasession ", loFileWorkarea.Session, " in workarea alias", loFileWorkarea.Workarea

I get the error "loFileWorkarea is not found"


Jim
 
Hi jimatarr,

How did you integrate the code into your code? And what version of VFP are you using? My code makes use of the "Empty" base class, available since VFP8, smae goes for the "Collection" class.

If you added the function into a method this can't work, the function needs to be placed into a prg file, eg into the main.prg,
also replace the Enddefine with Endfunction, although this piece of code alone put in a prg works.

The call loFileWorkareas = FileWorkareas(lcFile) must be made and the for each loop does create loFileWorkarea.

Bye, Olaf.
 
I saved all of your code as a prg ("olaf") and am calling it from a method ("DO olaf"). Using VFP9.

BTW,"Endfunction" doesn't work; "Endfunc" does.

Thanks,
Jim
 
Yes, you're right, Endfunc.

Hm, the error is in the For Each line:
Code:
For Each loFileWoarkarea In loFileWorkareas

There it needs to be loFileWorkarea.

Here's test code, opening the browser.dbf in two datasessions and then displaying so:

Code:
Local loFileWorkareas, lcFile, loSession

Use browser In 0
Use browser In 0 Again Alias ClassBrowserData
loSession = CreateObject("Session")
Set Datasession To loSession.DatasessionID
Use browser In 0
lcFile = Dbf("browser")

loFileWorkareas = FileWorkareas(lcFile)
If loFileWorkareas.Count>0
   For Each loFileWorkarea In loFileWorkareas
      ? lcFile + " is open in datasession ", loFileWorkarea.Session, " in workarea alias", loFileWorkarea.Workarea
   EndFor 
Else
   ? "File "+lcFile+" not open."
EndIf

Function FileWorkareas(tcFileToCheck)
   tcFileToCheck = ForceExt(Evl(tcFileToCheck,""),"dbf")
   
   Local loFileWorkareas, loFileWorkarea, lnCount
   Local lnSession, laUsed[2], laSessions[1]
   loFileWorkareas = Createobject("Collection")
   
   If File(tcFileToCheck)
      ASessions(laSessions)
      For Each lnSession In laSessions
          For lnCount = 1 To AUsed(laUsed,lnSession,tcFileToCheck)
             loFileWorkarea = CreateObject("Empty")
             AddProperty(loFileWorkarea,"Session",lnSession)
             AddProperty(loFileWorkarea,"Workarea",laUsed[lnCount,1])
             loFileWorkareas.Add(loFileWorkarea)
          EndFor
      EndFor
   Endif

   Return loFileWorkareas
Enddefine

This also is fixed to report both aliases in datasession 1, which the previous FileWorkareas() function did not do.

Bye, Olaf.
 
Yes, you're right, Endfunc.

Hm, the error is in the For Each line:
Code:
For Each loFileWoarkarea In loFileWorkareas

There it needs to be loFileWorkarea.

Here's test code, opening the browser.dbf in two datasessions and then displaying so:

Code:
Local loFileWorkareas, lcFile, loSession

Use browser In 0
Use browser In 0 Again Alias ClassBrowserData
loSession = CreateObject("Session")
Set Datasession To loSession.DatasessionID
Use browser In 0
lcFile = Dbf("browser")

loFileWorkareas = FileWorkareas(lcFile)
If loFileWorkareas.Count>0
   For Each loFileWorkarea In loFileWorkareas
      ? lcFile + " is open in datasession ", loFileWorkarea.Session, " in workarea alias", loFileWorkarea.Workarea
   EndFor 
Else
   ? "File "+lcFile+" not open."
EndIf

Function FileWorkareas(tcFileToCheck)
   tcFileToCheck = ForceExt(Evl(tcFileToCheck,""),"dbf")
   
   Local loFileWorkareas, loFileWorkarea, lnCount
   Local lnSession, laUsed[2], laSessions[1]
   loFileWorkareas = Createobject("Collection")
   
   If File(tcFileToCheck)
      ASessions(laSessions)
      For Each lnSession In laSessions
          For lnCount = 1 To AUsed(laUsed,lnSession,tcFileToCheck)
             loFileWorkarea = CreateObject("Empty")
             AddProperty(loFileWorkarea,"Session",lnSession)
             AddProperty(loFileWorkarea,"Workarea",laUsed[lnCount,1])
             loFileWorkareas.Add(loFileWorkarea)
          EndFor
      EndFor
   Endif

   Return loFileWorkareas
Endfunc

This also is fixed to report both aliases in datasession 1, which the previous FileWorkareas() function did not do.

Bye, Olaf.
 
Sorry, double posting, I canceled the first one, as it still had the Endfunc line wrong :). This seemed to have worked, but obviously didn't really.

Bye, Olaf.
 
Guys,

The original code is failing because

USE IN (usefile)

expects an *alias* and will ignore a fully pathed file name.
 
dan,

I also said so already.

myself said:
What you could simply try is USE IN register or USE IN SELECT("register"), as giving the full file name may fail with the IN clause.

Admitted, that was also a very late observation.

And nevertheless, if the erase still will error, after that is corrected, the function I gave can show where the file is open.

Bye, Olaf.
 
Olaf and Dan,

I tried "USE IN register" and it works. Much gratitude!!!

Jim

 
Olaf,

I missed that in all the verbiage that covered all manner of contingencies but not the original problem. Sorry.

I particularly like USE IN Select("whatever") and routinely use it to close tables because it won't throw an error if the table isn't actually open.

Dan
 
Yes, I had a little too much time ;).

The problem was quite clear, as IN does only accept a workarea number or alias and not a dbf file name.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top