Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
_File$ is not behaving as expected, cannot determine why
#1
I'm having some difficulties with _Files$ not behaving as expected. A detailed description of the issue can be found in the comments of the code sample below.

To summarize briefly, _Files$ works fine by itself, but when I introduce a number of lines of code that I currently have commented out, those lines for some unknown reason cause _Files$ to no longer work. Again, see the full description in the comments.

My test scenario:

QB64PE 3.14.1
Windows 11 24H2, latest public release (build 26100.2033)
Logged on as an Administrator

If anyone can provide a clue why this is failing, I would really appreciate some insight. I've been at this for a few hours and cannot put my finger on the problem.


Code: (Select All)
$Debug
$Console:Only
Option _Explicit

Dim MountedImageDriveLetter As String
Dim Cmd As String
Dim GetLine As String
Dim count As Integer
Dim FullPathToImage As String
Dim ISO_Path As String
Dim CurrentFile As String
Dim ff1 As Long
Dim FileSpec As String

' This program is placed in a folder that contains a number of files including files that take the form
' "EXPORTED DRIVERS*.iso". The program is supposed to mount each ISO image file (the first powershell command),
' and then it runs another command sending the output of that command to a file called MountInfo.txt. Next,
' we open MountInfo.txt and read 4 lines. The 4th line will contain the drive letter to which the ISO image was
' mounted. We save the drive letter and a colon (D: as an example) in MountedImageDriveLetter$. We then close
' MountInfo.txt and delete it. As a confirmation we print the drive letter to the screen.
'
' Here now is where the problem begins: We use _File$ to retrieve the next file matching the pattern
' "EXPORTED DRIVERS*.iso". However, upon running this command it returns an empty string rather than the next
' file name. Why???? For the life of me I cannot figure it out!

' Please note that I have commented out all of the lines that do the heavy lifting. In the current state, this
' program simply gets the first file name, prints it to the screen, then it gets the next file name. This works
' flawlessly! But when I uncomment all the lines in the DO loop the line "CurrentFile$ = _Files$" simply returns
' an empty string.

' TIP: I suggest running this in debug mode and then start the program paused. Press F4 and add all variables
' to watch. Then press F7 to step through one line at a time. You will see that the first file name is retrieved
' correctly, but when you reach line 68 it fails to get the next file name when the lines in the DO loop are
' uncommented but it does work with those lines commented out.

' Make sure to create a number of files with a .iso extension in the same folder with the program. These should
' be real ISO image files because we are actually mounting them with this program.

ISO_Path$ = _CWD$

FileSpec$ = ISO_Path$ + "\EXPORTED DRIVERS*.iso"

CurrentFile$ = _Files$(FileSpec$)

Do While Len(CurrentFile$) > 0
    '    MountedImageDriveLetter$ = ""
    '    FullPathToImage$ = ISO_Path$ + "\" + CurrentFile$

    '    Cmd$ = "powershell.exe -command " + Chr$(34) + "Mount-DiskImage " + Chr$(34) + "'" + FullPathToImage$ + "'" + Chr$(34) + Chr$(34) + " > NUL"
    '    Shell Cmd$
    '    Cmd$ = "powershell.exe -command " + Chr$(34) + "Get-DiskImage -ImagePath '" + FullPathToImage$ + "' | Get-Volume" + Chr$(34) + " > MountInfo.txt"
    '    Shell Cmd$

    '    ff1 = FreeFile
    '    Open "MountInfo.txt" For Input As #ff1

    '    For count = 1 To 4
    '        Line Input #ff1, GetLine$
    '    Next count

    '    MountedImageDriveLetter$ = Left$(GetLine$, 1) + ":"
    '    Close #ff1
    '    Kill "MountInfo.txt"

    '    Print MountedImageDriveLetter$
    Print CurrentFile$

    CurrentFile$ = _Files$
Loop


End
Reply
#2
It's the use of the KILL statement.  

Code: (Select All)
a$ = _Files$("*.*")

Print 1, a$

t$ = "temp.tmp"
Open t$ For Output As #1
a$ = _Files$
Print 2, a$

Close
a$ = _Files$
Print 3, a$

Kill t$
a$ = _Files$
Print 4, a$


This may be intentional to prevent you from trying to open and access files that could no longer exist any longer.

Best solution would probably be to read all those files into an array first, then process them after.
Reply
#3
Let me make sure that I understand...

Even though the kill command is not removing any of the files that _Files$ is working with are we saying that the problem is simply that we altering the directory contents while we are working with that directory using _Files$?

If I create and then kill that text file in a different location, would that solve the problem? Apologies, I would simply try this myself but I won't be in front of that system until morning.

I had also thought that using an array would be a good workaround, but I wanted to understand why I was having this difficulty.

Thanks for the help!
Reply
#4
From digging into a little more in our Dev channel on Discord:

It looks like a bug/unintentional to me, KILL/FILES/_FILES$ all call into the same logic to do the file searching which has a static `DIR *`, so calling one of them resets the state of `_FILES$`. Presumably it should have it's own separate state.

**************

So it's something likely to change and be fixed in a future release. Until then though, reading it into an array would let you work around the issue.
Reply
#5
(10-10-2024, 09:54 AM)hanness Wrote: Let me make sure that I understand...

Even though the kill command is not removing any of the files that _Files$ is working with are we saying that the problem is simply that we altering the directory contents while we are working with that directory using _Files$?

If I create and then kill that text file in a different location, would that solve the problem? Apologies, I would simply try this myself but I won't be in front of that system until morning.

I had also thought that using an array would be a good workaround, but I wanted to understand why I was having this difficulty.

Thanks for the help!

Although I'm with Steve, that a seperate state should be used here, it wouldn't solve the problem of bad programming you do here. You never should change the floor while you walking on it. Climbing a stairway always becomes dangerous when another guy is randomly removing steps at the same time.

As Steve said, rather read the whole directory into an array and after that's done use the array to modifiy the directory entries as needed.
Reply
#6
Perfect. I'll work around it for now, but I assume that a flag is being raised to hopefully get this looked at in depth at some time in the future as you noted.

Again, thanks for the great help. At least now I know I wasn't doing something completely stupid :-)

BTW, just a word of thanks for such an excellent product. I'm no professional programmer, but QB64PE allows me to automate a great number of tasks. I even have one program that is about 14,000 lines so far. It started off as a simple program to allow me to inject all the latest Windows updates directly into Windows ISO images but it's grown into a library of routines for performing just about every possible task one could imagine with Windows images.

It's all a breeze to do with QB64PE and a ton of fun on top of it.
Reply
#7
(10-10-2024, 01:09 PM)RhoSigma Wrote:
(10-10-2024, 09:54 AM)hanness Wrote: Let me make sure that I understand...

Even though the kill command is not removing any of the files that _Files$ is working with are we saying that the problem is simply that we altering the directory contents while we are working with that directory using _Files$?

If I create and then kill that text file in a different location, would that solve the problem? Apologies, I would simply try this myself but I won't be in front of that system until morning.

I had also thought that using an array would be a good workaround, but I wanted to understand why I was having this difficulty.

Thanks for the help!

Although I'm with Steve, that a seperate state should be used here, it wouldn't solve the problem of bad programming you do here. You never should change the floor while you walking on it. Climbing a stairway always becomes dangerous when another guy is randomly removing steps at the same time.

As Steve said, rather read the whole directory into an array and after that's done use the array to modifiy the directory entries as needed.
I apologize, but that is flat out wrong.

Bear in mind that this happens even if the file I am working with is not in the same directory. Put another way, I can retrieve the names of files one by one using _Files$ and never ever modify a single file in that folder. Even if I perform a kill on a file ON ANOTHER DRIVE it causes the failure of _Files$.

Sorry if my response sounded harsh. I just wanted to make 100% clear that the issue still exists without modifying a single file in the folder on which _Files$ is operating on.
Reply
#8
That's a pretty crazy bug. I hope they can fix that. Sounds like there was some bad programming left in there.
Tread on those who tread on you

Reply
#9
Fixed: https://github.com/QB64-Phoenix-Edition/QB64pe/pull/557

Will be available in the next release.
Reply




Users browsing this thread: 3 Guest(s)