Liberty BASIC Community Forum
« Multi user programs »

Welcome Guest. Please Login or Register.
May 22nd, 2017, 10:26am


Rules|Home|Help|Search|Recent Posts|Notification


« Previous Topic | Next Topic »
Pages: 1 2  Notify Send Topic Print
 hotthread  Author  Topic: Multi user programs  (Read 1029 times)
metro
Full Member
ImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 166
xx Multi user programs
« Thread started on: Sep 10th, 2016, 01:36am »

back for some guidance ,
The last time I networked a program was over 20 years ago with DOS6.22 and or Win3.11.

I now have trouble remembering what I did last week never mind 20 years ago.
I do recall however mapping drives and using Share.exe (vaguely), executing the program from a remote computer was straight forward.

Could someone enlighten me as to how to tackle it now days, I'm guessing each computer would have a copy of the program and I would create a shared location for the data.
thanks in advance

edit: moderator, sorry you may want to move this. forgot which board i was reading
« Last Edit: Sep 10th, 2016, 02:23am by metro » User IP Logged

Win10 64 HP laptop + desktop Mint Linux 64bit
Rod
Global Moderator
ImageImageImageImageImage


member is offline

Avatar

Graphics = goosebumps!


PM

Gender: Male
Posts: 5281
xx Re: Multi user programs
« Reply #1 on: Sep 10th, 2016, 09:38am »

Yes it is about mapping drives and setting up network access which is a Windows issue. You network will probably have one or more shared drive that exists on one machine. You will probably name it E: or H: to avoid conflict with A: B: C: etc.

So your Liberty programs will simply use the path E:\ to reach your central file.

The only issue you need be aware of is that Liberty does not support file locking. You can open the same file multiple times with any PC for reading, but for writing only one PC can have access, and that PC must have exclusive access.

So if you define your application a little more and tell us how many users you expect and what read/write access they will require you will get specific advice.
User IP Logged

metro
Full Member
ImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 166
xx Re: Multi user programs
« Reply #2 on: Sep 10th, 2016, 4:13pm »

Thank-you Rod
My interest was piqued whilst reading a post elsewhere regarding Structured Exception Handling. I've had reasoable success using SQLite for one of my projects and am now trying to get my head around ODBC but may consider just using RAF which strangely I've had little experience with.

I'll be back for more specific advice once I've fleshed out a detailed plan.

Thanks again
« Last Edit: Sep 10th, 2016, 4:14pm by metro » User IP Logged

Win10 64 HP laptop + desktop Mint Linux 64bit
Rod
Global Moderator
ImageImageImageImageImage


member is offline

Avatar

Graphics = goosebumps!


PM

Gender: Male
Posts: 5281
xx Re: Multi user programs
« Reply #3 on: Sep 11th, 2016, 02:58am »

I suppose we need an example of multiuser file access. I have not coded one before because I am not on a network. But of course I don't need one, I can just run multiple programs on this single PC. So nothing to stop us coding an example. Who will be first?
User IP Logged

Mystic
Junior Member
ImageImage


member is offline

Avatar




Homepage PM

Gender: Male
Posts: 97
xx Re: Multi user programs
« Reply #4 on: Sep 12th, 2016, 2:12pm »

I would also recommend using the UNC network path to the computer you have your data on, rather than a drive mapping.

If two computers don't have the same mapping, or lose their mapping, your program won't find the files.

Using the exact UNC path, about the only time the program won't find the files is if the NAS is offline, or someone changes the location of your data files.

I deal with the same thing here at work, and quickly figured out that even though everyone SHOULD be mapped the same, some clever monkeys like to play with their mappings. A direct UNC path removes this issue.

Just some food for thought. smiley
« Last Edit: Sep 12th, 2016, 2:13pm by Mystic » User IP Logged

- Rick
Programming BASIC since the 80's starting with a TRS-80.
metro
Full Member
ImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 166
xx Re: Multi user programs
« Reply #5 on: Sep 12th, 2016, 6:48pm »

thanks for the tip mystic, any chance you can supply a small demo
I obviously am missing something ???
Code:
filedialog "Open text file", "\\LAURIE-HP\BAKDAT\*.txt", fileName$ 


produces a runtime error "string can't hold a string"

PS there is a chance the error occurs because I'm using Linux to access Win10

EDIT:
I have found I can navigate to the shared folder and run the *.exe directly and despite it being extremely slow my program functions correctly.
so can I conclude that a remote user does not need a copy of the program on his/her system we only need a shortcut to the program on the serving computer.
« Last Edit: Sep 12th, 2016, 6:59pm by metro » User IP Logged

Win10 64 HP laptop + desktop Mint Linux 64bit
Chris Iverson
Administrator
ImageImageImageImageImage


member is offline

Avatar

20% Cooler


Homepage PM

Gender: Male
Posts: 2259
xx Re: Multi user programs
« Reply #6 on: Sep 12th, 2016, 7:24pm »

on Sep 12th, 2016, 2:12pm, Mystic wrote:
I would also recommend using the UNC network path to the computer you have your data on, rather than a drive mapping.

If two computers don't have the same mapping, or lose their mapping, your program won't find the files.

Using the exact UNC path, about the only time the program won't find the files is if the NAS is offline, or someone changes the location of your data files.

I deal with the same thing here at work, and quickly figured out that even though everyone SHOULD be mapped the same, some clever monkeys like to play with their mappings. A direct UNC path removes this issue.

Just some food for thought. smiley


While I fully agree with all of this, sadly, I do not believe that LB currently supports UNC paths natively. You would have to drop to Win32 API level to work with UNC paths.
User IP Logged

"Do you believe in destiny?" - Pyrrha Nikos, RWBY
"With what wish will your Soul Gem shine?" - Kyubey, Puella Magi Madoka Magica
metro
Full Member
ImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 166
xx Re: Multi user programs
« Reply #7 on: Sep 12th, 2016, 8:12pm »

Quote:
While I fully agree with all of this, sadly, I do not believe that LB currently supports UNC paths natively. You would have to drop to Win32 API level to work with UNC paths.

quite correct see https://lbpe.wikispaces.com/FastFAQ

Quote:
String can't hold string
You are using an UNC path (\\Server\Share) to access your program.
To make things work you must map the shared drive to a drive letter.

LB does not support UNC paths for the executables.

does anyone have code to demonstrate how to tackle this with API's

thanks in advance
User IP Logged

Win10 64 HP laptop + desktop Mint Linux 64bit
Rod
Global Moderator
ImageImageImageImageImage


member is offline

Avatar

Graphics = goosebumps!


PM

Gender: Male
Posts: 5281
xx Re: Multi user programs
« Reply #8 on: Sep 15th, 2016, 04:31am »

I have played a little and am just getting confused. I don't have a network but am assuming running multiple instances of my Liberty BASIC program will generate the file access error.

But it does not. I can have three or four copies of this program running and they don't appear to ever conflict and error out on file access. On error is never called and the records appear to be getting updated.

I have to assume Windows is managing things in the background and queuing the file access requests, or random access in Liberty is actually shared.

Perhaps I misunderstand.

Code:
print "Writing"
for x= 1 to 100
    result = openDatabase("e:\Database\test.dat")
    if result then
    'write randomly to first ten records
        writer$="01"
        writetime$=time$()+"*"
        r=int(rnd(0)*10+1) '1-10
        put #1,r
        call closeDatabase "#1"
    else
        print "Unable to open file"
        end
    end if
call delay 100
next
print "Done"
wait



function openDatabase(name$)
    'tries 50 times to open name$ returns 1 success 0 failed
    'since #handle$ variables don't work for file opening
    'its #1 as file handle
    openDatabase=0
    while tries<50
        'set the on error event
        on error goto [catch]
        open name$ for random as #1 len=11
        field #1 , 2 as writer$ ,9 as writetime$
        openDatabase=1
        exit while

        [catch]
        print "caught"
        tries=tries+1

        'random delay to stop "race" conflict
        call delay int(rnd(0)*200)
    wend
end function

sub closeDatabase h$
    close #h$
end sub


sub delay ms
    timer ms,[done]
    wait

    [done]
    timer 0
end sub


 
User IP Logged

Chris Iverson
Administrator
ImageImageImageImageImage


member is offline

Avatar

20% Cooler


Homepage PM

Gender: Male
Posts: 2259
xx Re: Multi user programs
« Reply #9 on: Sep 15th, 2016, 7:48pm »

on Sep 15th, 2016, 04:31am, Rod wrote:
I have played a little and am just getting confused. I don't have a network but am assuming running multiple instances of my Liberty BASIC program will generate the file access error.

But it does not. I can have three or four copies of this program running and they don't appear to ever conflict and error out on file access. On error is never called and the records appear to be getting updated.

I have to assume Windows is managing things in the background and queuing the file access requests, or random access in Liberty is actually shared.

Perhaps I misunderstand.

Code:
print "Writing"
for x= 1 to 100
    result = openDatabase("e:\Database\test.dat")
    if result then
    'write randomly to first ten records
        writer$="01"
        writetime$=time$()+"*"
        r=int(rnd(0)*10+1) '1-10
        put #1,r
        call closeDatabase "#1"
    else
        print "Unable to open file"
        end
    end if
call delay 100
next
print "Done"
wait



function openDatabase(name$)
    'tries 50 times to open name$ returns 1 success 0 failed
    'since #handle$ variables don't work for file opening
    'its #1 as file handle
    openDatabase=0
    while tries<50
        'set the on error event
        on error goto [catch]
        open name$ for random as #1 len=11
        field #1 , 2 as writer$ ,9 as writetime$
        openDatabase=1
        exit while

        [catch]
        print "caught"
        tries=tries+1

        'random delay to stop "race" conflict
        call delay int(rnd(0)*200)
    wend
end function

sub closeDatabase h$
    close #h$
end sub


sub delay ms
    timer ms,[done]
    wait

    [done]
    timer 0
end sub


 


Nope, LB just seems to handle RAF files in a weird way. If you're working with RAF files, it doesn't actually hold the file open(from the API/system's point of view). Instead, it opens/closes the file each time you interact with it.

It appears to read the entire file in and/or write it out each time you update it. It just modifies the data internally and writes the entire thing out, if you're storing records.

They're not conflicting with each other because each one is barely holding the file open.

Additionally, LB appears to always open files(whether opened for INPUT, OUTPUT, APPEND, or RANDOM) with FILE_SHARE_READ | FILE_SHARE_WRITE for the share mode, which means any other program is allowed to open the file for reading or writing at any point while LB has the file open, as long as that program's share mode doesn't conflict with the existing handle. (So, be careful: the files you're working with in LB can change out from under you!)

(I figured all this out by using the Process Monitor tool from SysInternals. AMAZINGLY useful for poking around stuff like this.)


metro: I'm putting together a few quick functions to work with the Win32 API file functions.
« Last Edit: Sep 15th, 2016, 7:50pm by Chris Iverson » User IP Logged

"Do you believe in destiny?" - Pyrrha Nikos, RWBY
"With what wish will your Soul Gem shine?" - Kyubey, Puella Magi Madoka Magica
Chris Iverson
Administrator
ImageImageImageImageImage


member is offline

Avatar

20% Cooler


Homepage PM

Gender: Male
Posts: 2259
xx Re: Multi user programs
« Reply #10 on: Sep 16th, 2016, 12:01am »

Creating a second post due to post length.

Here's the beginning of a set of functions to wrap the Win32 File API to be LB-like.

LB functions for CreateFile(), ReadFile(), WriteFile(), CloseHandle(), and SetFileInformation() have been written, as well as LB-like file open/close functions OpenFileForOutput(), OpenFileForInput(), OpenFileForAppend(), and CloseFile().

Just need to try to implement LB-like input and output.

Code:
'========================
'= LB-like API wrappers =
'========================
Function OpenFileForOutput(fileName$)
    dwDesiredAccess = _GENERIC_READ or _GENERIC_WRITE   'LB opens files for GENERIC_READ | GENERIC_WRITE
    dwShareMode = _FILE_SHARE_READ or _FILE_SHARE_WRITE 'LB opens files with share mode FILE_SHARE_READ | FILE_SHARE_WRITE
    lpSecurityAttributes = 0                            'Not specifying an ACL
    dwCreationDisposition = _CREATE_ALWAYS              'CREATE_ALWAYS forces it to open an empty file, even if the file exists.
                                                        '  This matches LB's behavior when opening for OUTPUT.
    dwFlagsAndAttributes = _FILE_ATTRIBUTE_NORMAL       'LB opens files with no attribute set, and does not set any flags
    hTemplateFile = 0                                   'LB never specifies a template file

    OpenFileForOutput = CreateFile(fileName$, dwDesiredAccess, dwShareMode, lpSecurityAttributes,_
        dwCreationDisposition, dwFlagsAndAttibutes, hTemplateFile)
End Function

Function OpenFileForAppend(fileName$)
    dwDesiredAccess = _GENERIC_READ or _GENERIC_WRITE   'LB opens files for GENERIC_READ | GENERIC_WRITE
    dwShareMode = _FILE_SHARE_READ or _FILE_SHARE_WRITE 'LB opens files with share mode FILE_SHARE_READ | FILE_SHARE_WRITE
    lpSecurityAttributes = 0                            'Not specifying an ACL
    dwCreationDisposition = _OPEN_ALWAYS                'OPEN_ALWAYS opens a file if it exists, and creates it if it doesn't.
                                                        '  This matches LB's behavior when opening for APPEND.
    dwFlagsAndAttributes = _FILE_ATTRIBUTE_NORMAL       'LB opens files with no attribute set, and does not set any flags
    hTemplateFile = 0                                   'LB never specifies a template file

    OpenFileForAppend = CreateFile(fileName$, dwDesiredAccess, dwShareMode, lpSecurityAttributes,_
        dwCreationDisposition, dwFlagsAndAttibutes, hTemplateFile)

    'When LB opens a file for APPEND, the file pointer is set to the end of the file.
    'We need to do that manually if using the Win32 API.
    if (OpenFileForAppend <> _INVALID_HANDLE_VALUE) then
        a = SetFilePointer32(OpenFileForAppend, 0, _FILE_END)
    end if
End Function

Function OpenFileForInput(fileName$)
    dwDesiredAccess = _GENERIC_READ or _GENERIC_WRITE   'LB opens files for GENERIC_READ | GENERIC_WRITE
    dwShareMode = _FILE_SHARE_READ or _FILE_SHARE_WRITE 'LB opens files with share mode FILE_SHARE_READ | FILE_SHARE_WRITE
    lpSecurityAttributes = 0                            'Not specifying an ACL
    dwCreationDisposition = _OPEN_EXISTING              'OPEN_EXISTING opens a file if it exists, and fails if it doesn't.
                                                        '  This matches LB's behavior when opening for INPUT.
    dwFlagsAndAttributes = _FILE_ATTRIBUTE_NORMAL       'LB opens files with no attribute set, and does not set any flags
    hTemplateFile = 0                                   'LB never specifies a template file

    OpenFileForInput = CreateFile(fileName$, dwDesiredAccess, dwShareMode, lpSecurityAttributes,_
        dwCreationDisposition, dwFlagsAndAttibutes, hTemplateFile)
End Function

Function CloseFile(hFile)
    CloseFile = CloseHandle(hFile)
End Function


'=========================
'= Direct Win32 Wrappers =
'=========================
Function CreateFile(fileName$, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)
    CallDLL #kernel32, "CreateFileA",_
    fileName$ as ptr,_
    dwDesiredAccess as long,_
    dwShareMode as long,_
    lpSecurityAttributes as ulong,_
    dwCreationDisposition as long,_
    dwFlagsAndAttributes as long,_
    hTemplateFile as ulong,_
    CreateFile as ulong
End Function

Function CloseHandle(hHandle)
    CallDLL #kernel32, "CloseHandle",_
    CloseHandle as long
End Function

Function WriteFile(hFile, lpBuffer$, nNumberOfBytesToWrite, byref lpNumberOfBytesWritten, lpOverlapped)
    struct a, b as long
    a.b.struct = lpNumberOfBytesWritten

    CallDLL #kernel32, "WriteFile",_
    hFile as ulong,_
    lpBuffer$ as ptr,_
    nNumberOfBytesToWrite as long,_
    a as struct,_
    lpOverlapped as ulong,_
    WriteFile as long

    lpNumberOfBytesWritten = a.b.struct
End Function

Function ReadFile(hFile, byref lpBuffer$, nNumberOfBytesToRead, byref lpNumberOfBytesRead, lpOverlapped)
    struct a, b as long
    a.b.struct = lpNumberOfBytesRead

    CallDLL #kernel32, "ReadFile",_
    hFile as ulong,_
    lpBuffer$ as ptr,_
    nNumberOfBytesToRead as long,_
    a as struct,_
    lpOverlapped as ulong,_
    ReadFile as long

    lpNumberOfBytesRead = a.b.struct
End Function

Function SetFilePointer32(hFile, lDistanceToMove, dwMoveMethod)
    CallDLL #kernel32, "SetFilePointer",_
    hFile as ulong,_
    lDistanceToMove as long,_
    0 as long,_
    dwMoveMethod as long,_
    SetFilePointer32 as long
End Function 



Edit: Modified WriteFile() and ReadFile().
« Last Edit: Sep 21st, 2016, 9:38pm by Chris Iverson » User IP Logged

"Do you believe in destiny?" - Pyrrha Nikos, RWBY
"With what wish will your Soul Gem shine?" - Kyubey, Puella Magi Madoka Magica
Rod
Global Moderator
ImageImageImageImageImage


member is offline

Avatar

Graphics = goosebumps!


PM

Gender: Male
Posts: 5281
xx Re: Multi user programs
« Reply #11 on: Sep 16th, 2016, 04:51am »

Ok, if the native commands work and supply shared access why do we need the API? Indeed why did we get recent reports of file access error when it does not happen? I think that was on the official forum.

I understand that data integrity is an issue but that risk remains even with file or record locking.

User IP Logged

Chris Iverson
Administrator
ImageImageImageImageImage


member is offline

Avatar

20% Cooler


Homepage PM

Gender: Male
Posts: 2259
xx Re: Multi user programs
« Reply #12 on: Sep 16th, 2016, 07:58am »

As for the file access error, I'll go ahead and double-check the results I'm seeing. I can speculate a couple reasons for any file access errors when opening files.

1) LB handles files differently internally, and there's some other requirement that's not being met.

2) LB pulls some information from the file first, which may result in an additional CreateFile() call that doesn't have the share mode set.

I'll see if I can confirm the second one, but the first one may be beyond me, if I can't confirm it either way.


Also, the API functions are needed for working with UNC paths/network files. LB does not have native UNC support.
User IP Logged

"Do you believe in destiny?" - Pyrrha Nikos, RWBY
"With what wish will your Soul Gem shine?" - Kyubey, Puella Magi Madoka Magica
metro
Full Member
ImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 166
xx Re: Multi user programs
« Reply #13 on: Sep 16th, 2016, 08:55am »

Thanks Rod & Chris
I had a go at this a few days back and was baffled by the results, I too used API's
https://lbpe.wikispaces.com/FileAPI
Code:
'open a file for append
hFile2 = OpenForAppend("f:\Database\test.dat")

if hFile2 <> INVALID.HANDLE.VALUE then 'file opened successfully
    'Print some text to the file.
    r = writeFile(hFile,"First line of text from prog2")
    r = writeFile(hFile,"Second line of text from prog2")
    r = writeFile(hFile,"Third line of text from prog2")
    'For additional error checking, r could be tested for 0.
    '0 would indicate that the data was not written to the file.
else
print "stopped"
    notice "File Access Error" + chr$(13) + "File could not be opened."
end if
input a    ' to prevent closing whilst second prog attempts to write

call CloseFile hFile

wait

'*****************************************************************
'                 api file handling: subs / functions
'*****************************************************************

function OpenForInput(fileName$)
    'open a file for input.
    calldll #kernel32, "CreateFileA", fileName$ as ptr, _GENERIC_READ as ulong, _
        0 as ulong, 0 as long, _OPEN_EXISTING as ulong, _
        _FILE_ATTRIBUTE_NORMAL as ulong, 0 as long, OpenForInput as long
end function

function OpenForOutput(fileName$)
    'Open a file for output.
    'If file doesn't exist it will be created.
    'If it does exist, it will be opened and the contents erased.

    calldll #kernel32, "CreateFileA", fileName$ as ptr, _GENERIC_WRITE as ulong, _
        0 as ulong, 0 as long, _CREATE_ALWAYS as ulong, _
        _FILE_ATTRIBUTE_NORMAL as ulong, 0 as long, OpenForOutput as long
end function

function OpenForAppend(fileName$)
    'Open a file for append.
    'If the file does not exist it will be created.
    'If it does exist, it will be opened and the file
    'pointer set to the end of the file.

    calldll #kernel32, "CreateFileA", fileName$ as ptr, _GENERIC_WRITE as ulong, _
        0 as ulong, 0 as long, _OPEN_ALWAYS as ulong, _
        _FILE_ATTRIBUTE_NORMAL as ulong, 0 as long, hFile as long

    'set the file pointer to the end of the file
    calldll #kernel32,"SetFilePointer", hFile as long, 0 as long, 0 as long, _
        _FILE_END as ulong, r as ulong

    OpenForAppend = hFile
end function

sub CloseFile hFile
    calldll #kernel32, "CloseHandle", hFile as long, r as long
end sub

function LineInput$(hFile)
    'get 1 line from a file opened with OpenForInput
    'without the carriage return/linefeed.

    struct BytesRead, pcb as ulong
    eoFile(0) = 0 'reset "end of file" indicator
    'i(0) is used as a static file pointer variable

    while x = 0 'depend on exit while to leave loop
        pbBuff$ = space$(512)
        calldll #kernel32,"ReadFile", hFile as long, pbBuff$ as ptr, _
        512 as long, BytesRead as struct, 0 as long, r as long

        if BytesRead.pcb.struct > 0 then
            i = instr(pbBuff$, chr$(13))
            if i > 0 then
                LineInput$ = LineInput$ + left$(pbBuff$,i-1)
                fptr = i + 1 + i(0)
                i(0) = fptr
                calldll #kernel32,"SetFilePointer", hFile as long, fptr as long, 0 as long, _
                    _FILE_BEGIN as ulong, r as ulong
                exit while
            else
                LineInput$ = LineInput$ + pbBuff$
                i(0) = i(0) + len(pbBuff$)
            end if
        else
            eoFile(0) = -1
            i(0) = 0
            exit while
        end if
    wend
end function

function GetFileContent$(hFile)
    'get the entire contents of a file opened with OpenForInput
    struct BytesRead, pcb as ulong

    'set the file pointer to the beginning of the file
    calldll #kernel32,"SetFilePointer", hFile as long, 0 as long, 0 as long, _
        _FILE_BEGIN as ulong, r as ulong

    'Get the file size. As used here, the max file size this will accurately return
    'is 4,294,967,295 bytes.
    calldll #kernel32,"GetFileSize", hFile as long, 0 as ulong, size as ulong

    'read the whole file into pbBuff$
    if size > 0 then
        pbBuff$ = space$(size)
        calldll #kernel32,"ReadFile", hFile as long, pbBuff$ as ptr, _
        size as long, BytesRead as struct, 0 as long, r as long
        GetFileContent$ = pbBuff$
        pbBuff$ = ""
    end if
end function

function writeFile(hFile,data$)
    'print a line of text to a file opened with OpenForOutput or OpenForAppend
    d$ = data$ + chr$(13) + chr$(10)
    struct BytesWritten, pcb as ulong
    BytesToWrite = len(d$)
    calldll #kernel32,"WriteFile", hFile as long, d$ as ptr, _
    BytesToWrite as long, BytesWritten as struct, 0 as long, r as long
    writeFile = BytesWritten.pcb.struct
end function

 

the input statement prevented the file being closed whilst I ran a second version to write to the file but got completely stumped when no error was trapped and the second program never got to write to the file.
I will digest what Chris has presented and take another look over the weekend.

Thanks for your assistance (both of you)

metro
EDIT: forgot to mention, on one attempt I ran prog1 then tried to open f:\Database\test.dat only to get a message that the file did not exist despite it appearing in my file manager
« Last Edit: Sep 16th, 2016, 09:22am by metro » User IP Logged

Win10 64 HP laptop + desktop Mint Linux 64bit
Chris Iverson
Administrator
ImageImageImageImageImage


member is offline

Avatar

20% Cooler


Homepage PM

Gender: Male
Posts: 2259
xx Re: Multi user programs
« Reply #14 on: Sep 17th, 2016, 5:50pm »

New set of functions complete, for now. I can still think of things to add to them.

Add this set under the "LB-like API Wrappers" section

Code:
Function InputLine$(hFile)
    'Get current position in file
    curPos = SetFilePointer32(hFile, 0, _FILE_CURRENT)

    while 1
        bytesToRead = 512
        bytesRead = 0
        readBuf$ = space$(512)
        a = ReadFile(hFile, readBuf$, bytesToRead, bytesRead, 0)

        'If the file read fails, return immediately.
        If a = 0 then
            InputLine$ = ""
            exit while
        End If

        if bytesRead > 0 then
            for x = 1 to bytesRead
                prevChar$ = curChar$
                curChar$ = mid$(readBuf$, x, 1)

                'If we find a CRLF sequence, trim off the CR,
                'set the file pointer to that location(to line up the next input command),
                'and return
                if prevChar$ = chr$(13) and curChar$ = chr$(10) then
                    InputLine$ = left$(InputLine$, len(InputLine$) - 1)

                    newPos = curPos + x
                    a = SetFilePointer32(hFile, newPos, _FILE_BEGIN)

                    foundFlag = 1
                    exit for
                end if

                InputLine$ = InputLine$ + curChar$ 
            next x
        else
            exit while
        end if
        if foundFlag then exit while
    wend
End Function

Function isEOF(hFile)
    curPos = SetFilePointer32(hFile, 0, _FILE_CURRENT)
    If curPos = GetFileSize(hFile) then isEOF = 1
End Function

Function PrintLine(hFile, data$)
    data$ = data$ + chr$(13) + chr$(10)
    lenData = len(data$)
    numBytesWritten = 0

    PrintLine = WriteFile(hFile, data$, lenData, numBytesWritten, 0)
End Function 



And this one to "Direct Win32 Wrappers".

Code:
Function GetFileSize(hFile)
    struct a, b as long

    CallDLL #kernel32, "GetFileSize",_
    hFile as ulong,_
    a as struct,_
    ret as long

    GetFileSize = ret + a.b.struct
End Function 



And here's a test program that reads from a UNC file over the network.

You can replace with whatever UNC file you want, I use \\live.sysinternals.com\Tools\About_This_Site.txt because 1) it's public, and should work the same on every system, and 2) it actually goes over the network, so you don't need to set up another computer or VM to do your own local test.

Feel free to do your own local tests, though!

Code:
Print "Attempting to open test document on SysInternals share."
Print "This may take a while, depending on your internet connection..."
Print
hFile = OpenFileForInput("\\live.sysinternals.com\Tools\About_This_Site.txt")
print hFile

while not(isEOF(hFile))
    a$ = InputLine$(hFile)
    Print a$
wend

a = CloseFile(hFile) 
User IP Logged

"Do you believe in destiny?" - Pyrrha Nikos, RWBY
"With what wish will your Soul Gem shine?" - Kyubey, Puella Magi Madoka Magica
Pages: 1 2  Notify Send Topic Print
« Previous Topic | Next Topic »

Rules|Home|Help|Search|Recent Posts|Notification

Donate $6.99 for 50,000 Ad-Free Pageviews!

| |

This forum powered for FREE by Conforums ©
Sign up for your own Free Message Board today!
Terms of Service | Privacy Policy | Conforums Support | Parental Controls