LB Booster
Programming >> Liberty BASIC language >> Access denied error
http://lbb.conforums.com/index.cgi?board=lblang&action=display&num=1402714632

Access denied error
Post by RobM on Jun 14th, 2014, 02:57am

My program has a function for checking to see if a newer version is available by downloading and reading a 2 line text file. In the following snippet the program will give an access denied error on the 'kill' command, but only on a few machines. The file is downloaded to a folder created in the current user's AppData folder.

Any ideas why it would give an error when trying to kill the file?

I can post more code if needed but it seems pretty straight forward to me.

Code:
    if fileExists(dr$, dr$+"\update.txt") then
      open dr$+"\update.txt" for input as #updatefile
      line input #updatefile, verdat$
      line input #updatefile, descrip$ 
      close #updatefile
      while time$("seconds")< EndTime+6:wend

      kill dr$+"\update.txt"

      RunningVersion=date$(VERDATE$)

      UpdateVersion=date$(verdat$)

      if RunningVersion>UpdateVersion then HaveLatestVersion=1

      if RunningVersion=UpdateVersion then HaveLatestVersion=1

      if RunningVersion<UpdateVersion then HaveLatestVersion=0

      if HaveLatestVersion=1 then [HaveLatestVersion]

      if HaveLatestVersion=0 then [NotLatestVersion]

    end if
 



Re: Access denied error
Post by Richard Russell on Jun 14th, 2014, 07:35am

on Jun 14th, 2014, 02:57am, RobM wrote:
Any ideas why it would give an error when trying to kill the file?

The KILL statement simply calls the DeleteFile API, as you would expect, so the issue is not specific to LBB but a more general Windows-related question. A similar symptom is discussed at Raymond Chen's blog here:

http://blogs.msdn.com/b/oldnewthing/archive/2012/09/07/10347136.aspx

His 'psychic powers' led him to blame anti-virus software so I wouldn't be surprised if that is the case in your situation too.

However I do notice that your program contains a deliberate delay between 'closing' the file and 'killing' it:

Code:
      close #updatefile
      while time$("seconds")< EndTime+6:wend
      kill dr$+"\update.txt" 

This suggests to me that you've had the problem, or something similar, before and have introduced the delay as a workaround (the code which sets EndTime isn't listed). It may be that the delay isn't as effective in LBB as you found it to be in LB 4.04.

As a general rule I would not recommend using a 'tight loop' delay of this kind, because it will keep the CPU 100% occupied while 'waiting' which may partially defeat the object of giving Windows a chance to do something 'in the background'. It may be better to call the Sleep API in a case such as this, which will suspend your process:

Code:
    calldll #kernel32, "Sleep", 6 as long, r as long 

But, ultimately, if a virus scanner is to blame there may be no complete solution other than to trap errors and automatically retry the KILL until it succeeds (or to use a different virus scanner!).

Richard.
Re: Access denied error
Post by RobM on Jun 14th, 2014, 2:32pm

I hadn't considered an anti-virus program might be the problem. A file is being downloaded from the internet so that would make sense.

The delay was put there to let the user see what is happening. Without it the process runs too fast. Using 'sleep' causes the progress bar to stop, which I guess isn't too bad.

This code should run, downloading the file and checking the version.
Code:
    ScrnScl=1
    VERDATE$="5/30/2014"
    dr$=GetSpecialfolder$(26)
    result=MKDIR(dr$;"\Cabinet Planner")
[CheckUpdate]
    EndTime=time$("seconds")+3
    WindowWidth = int(255*ScrnScl)
    WindowHeight = int(100*ScrnScl)
    UpperLeftX=int((DisplayWidth-WindowWidth)/2)
    UpperLeftY=int((DisplayHeight-WindowHeight)/2)
    BackgroundColor$ = "white"

    statictext #splash.st1,"Checking internet connection....",20,int(15/ScrnScl),170,int(20/ScrnScl)

    open "Cabinet Planner update" for dialog_modal as #splash
    #splash,"trapclose [quit.Splash]"

    call createProgressBar hWnd(#splash), 20,int(40/ScrnScl),200,int(20/ScrnScl)
    'check for internet connection
    lpszURL$ = "http://www.cabinetplanner.com"
    FLAG.ICC.FORCE.CONNECTION=1
    open "wininet.dll" for dll as #win
    calldll #win, "InternetCheckConnectionA",_
      lpszURL$ As ptr, _
      FLAG.ICC.FORCE.CONNECTION As Long,_
      dwReserved As Long, _
      result As ulong
    close #win

    while time$("seconds")< EndTime:wend

    if result=1 then print #splash.st1,"Checking version...."

    'download file
    urlfile$="http://cabinetplanner.com/files/update.txt"
    localfile$=dr$+"\update.txt"
    dim info$(10, 10)
    if result=1 then
      open "URLmon" for dll as #url
      calldll #url, "URLDownloadToFileA",_
      0 as long,_ 'null
      urlfile$ as ptr,_ 'url to download
      localfile$ as ptr,_ 'save file name
      0 as long,_ 'reserved, must be 0
      0 as long,_ 'callback address, can be 0
      DownloadToFile as ulong '0=success
      close #url
    end if

    if fileExists(dr$, dr$+"\update.txt") then
      open dr$+"\update.txt" for input as #updatefile
      line input #updatefile, verdat$
      line input #updatefile, descrip$ 
      close #updatefile

      'while time$("seconds")< EndTime+6:wend
      calldll #kernel32, "Sleep", 3000 as long, r as long

      kill dr$+"\update.txt"

      RunningVersion=date$(VERDATE$)

      UpdateVersion=date$(verdat$)

      if RunningVersion>UpdateVersion then HaveLatestVersion=1

      if RunningVersion=UpdateVersion then HaveLatestVersion=1

      if RunningVersion<UpdateVersion then HaveLatestVersion=0

      if HaveLatestVersion=1 then [HaveLatestVersion]

      if HaveLatestVersion=0 then [NotLatestVersion]

    end if

    close #splash

    notice "Unable to download the update, please try again later"

    wait

[NotLatestVersion]
    proloc=833
    prolc$=word$(prolc$,2);" ";word$(prolc$,3);" ";word$(prolc$,4);" ";word$(prolc$,5);" ";word$(prolc$,6);" ";word$(prolc$,7);" ";word$(prolc$,8);" ";word$(prolc$,9);" ";word$(prolc$,10);" ";str$(proloc)
    close #splash
    WindowWidth=int(315*ScrnScl)
    WindowHeight=int(100*ScrnScl)
    UpperLeftX=int((DisplayWidth-WindowWidth)/2)
    UpperLeftY=int((DisplayHeight-WindowHeight)/2)
    BackgroundColor$ = "white"
    statictext #update, "There is a newer version available, install now?", 5, int(10/ScrnScl), 260, int(22/ScrnScl)
    button #update.clos, "Close program and install", [InstallUpdate], UL, 5, int(35/ScrnScl),160,int(22/ScrnScl)
    button #update.can, "Cancel", [CloseUpdate2], UL, 170, int(35/ScrnScl), 60,int(22/ScrnScl)
    button #update.inf, "Info", [UpdateInfo], UL, 235, int(35/ScrnScl), 60,int(22/ScrnScl)
    open "Update" for dialog_modal as #update
    #update, "trapclose [CloseUpdate2]"
    wait
[CloseUpdate2]
    close #update
    if checkupdate=1 then checkupdate=0:return
    wait
[UpdateInfo]
    WindowWidth=int(355*ScrnScl)
    WindowHeight=int(125/ScrnScl)
    UpperLeftX=int((DisplayWidth-WindowWidth)/2)
    UpperLeftY=int((DisplayHeight-WindowHeight)/2)
    BackgroundColor$ = "white"
    statictext #info.txt, "", 5, int(10/ScrnScl), 340, int(110/ScrnScl)
    open "Update" for dialog_modal as #info
    #info, "trapclose [Closeinfo]"
    #info.txt, descrip$ 
    wait
[Closeinfo]
    close #info
    wait
[InstallUpdate]
    close #update
    close #cp
    run DefaultDir$+"\Updater.exe"
    end
[HaveLatestVersion]
    close #splash
    WindowWidth=int(255*ScrnScl)
    WindowHeight=int(100*ScrnScl)
    UpperLeftX=int((DisplayWidth-WindowWidth)/2)
    UpperLeftY=int((DisplayHeight-WindowHeight)/2)
    BackgroundColor$ = "white"
    statictext #updateh, "You have the latest version", 9, int(10/ScrnScl), 200, int(22/ScrnScl)
    button #updateh.default, "OK", [CloseUpdate], UL, 95, int(35/ScrnScl), 60,int(22/ScrnScl)
    open "Update" for dialog_modal as #updateh
    #updateh, "trapclose [CloseUpdate]"
    wait
[CloseUpdate]
    close #updateh
    if checkupdate=1 then checkupdate=0:return
    wait

sub createProgressBar hWnd, xpos, ypos, wide, high
    CallDLL #user32, "GetWindowLongA", hWnd as uLong, _GWL_HINSTANCE as Long, hInst as uLong
    PBM.SETMARQUEE =_WM_USER+10 : style = _WS_CHILD or _WS_VISIBLE or PBM.SETMARQUEE
    class$="msctls_progress32" : title$=""
    calldll #user32, "CreateWindowExA", 0 as long, class$ as ptr, title$ as ptr, style as long, xpos as long, ypos as long, wide as long, high as long, hWnd as ulong, 0 as long, hInst as ulong, 0 as long, createProgressBar as ulong
    calldll #user32, "SendMessageA", createProgressBar as ulong, PBM.SETMARQUEE as long, 1 as long, 100 as long, r as long
end sub

function fileExists(path$, filename$)
  files path$, filename$, info$()
  fileExists = val(info$(0, 0))  'non zero is true
end function

Function GetSpecialfolder$(CSIDL)

    struct IDL, _
    cb As uLong, _
    abID As short

    calldll #shell32, "SHGetSpecialFolderLocation",_
      0 as ulong, _
      CSIDL as ulong, _
      IDL as struct,_
      ret as ulong

    if ret=0 then
      Path$ = Space$(_MAX_PATH)
      id = IDL.cb.struct

      calldll #shell32, "SHGetPathFromIDListA",_
      id as ulong, _
      Path$ as ptr, _
      ret as ulong

      GetSpecialfolder$ = trim$(Path$)

      open "ole32.dll" for dll as #ole32

      calldll #ole32, "CoTaskMemFree",_
      id as ulong,_
      result as void

      close #ole32
    end if

    if GetSpecialfolder$ = "" then GetSpecialfolder$ = "Not Applicable"
End Function
 

Re: Access denied error
Post by Richard Russell on Jun 14th, 2014, 4:24pm

on Jun 14th, 2014, 2:32pm, RobM wrote:
IUsing 'sleep' causes the progress bar to stop, which I guess isn't too bad.

For delays in excess of a few tens of milliseconds you can put a short Sleep in a FOR..NEXT loop. That way the program won't become unresponsive. For example:

Code:
    ' approximately one second delay:
    for n = 1 to 100
      calldll #kernel32, "Sleep", 10 as long, r as long
    next n 

Richard.

Re: Access denied error
Post by RobM on Jun 14th, 2014, 5:23pm

I think I'll try not deleting the file afterward but check for its existence and delete it before downloading the new file. That way if this is because of an AV program having the file open for scanning, it can do its thing without interfering with my program.
Re: Access denied error
Post by RobM on Jul 1st, 2014, 8:42pm

Quick follow up. After making the changes I mentioned above the error seems to have gone away wink