1. Kyle Bengtson
  2. PowerBuilder
  3. Monday, 23 May 2022 14:42 PM UTC

I have a situation where I'm creating a text file in my application, successfully closing it using FileClose, then using Run("notepad "+[filename]) to display it. All works well except that when I try to create a 2nd text file after that, the file is locked by PB unless I get out of my app. Below is an abbreviated example of my code. Does anyone know a workaround?

for li_loops = 1 to li_count
   li_FileNum = FileOpen("Recipient List.txt", TextMode!, Write!, Shared!, Append!)
   //populate ls_email_list variable from database view
   FileWriteEx(li_FileNum, ls_email_list)
   if li_loops = li_count then
      if FileClose(li_FileNum) = 1 then
         Run("notepad "+"Recipient List.txt")
      end if
   end if
next

Arnd Schmidt Accepted Answer Pending Moderation
  1. Monday, 23 May 2022 16:15 PM UTC
  2. PowerBuilder
  3. # 1

This is your code:

for li_loops = 1 to li_count
   li_FileNum = FileOpen("Recipient List.txt", TextMode!, Write!, Shared!, Append!)
   //populate ls_email_list variable from database view
   FileWriteEx(li_FileNum, ls_email_list)
   if li_loops = li_count then
      if FileClose(li_FileNum) = 1 then
         Run("notepad "+"Recipient List.txt")
      end if
   end if
next

Please count how many times you do a FileOpen() and a FileClose() in the loop for li_count > 1.

hth

Arnd

Comment
  1. Benjamin Gaesslein
  2. Tuesday, 24 May 2022 08:03 AM UTC
Miguel, the file is only opened in notepad on the last iteration. See "if li_loops = li_count then ..." :)

So yes, the Run() command can be put outside of the loop.
  1. Helpful 1
  1. Roland Smith
  2. Tuesday, 24 May 2022 12:54 PM UTC
The problem is that the Run function doesn't wait for the external program to finish.
  1. Helpful
  1. Miguel Leeuwe
  2. Tuesday, 24 May 2022 13:59 PM UTC
Thanks Benjamin, I oversaw that little detail :)
  1. Helpful
There are no comments made yet.
Roland Smith Accepted Answer Pending Moderation
  1. Monday, 23 May 2022 19:54 PM UTC
  2. PowerBuilder
  3. # 2

The built in Run function and ShellExecute do not wait for the external program to finish. Calling it inside a loop will result in more than one app running at the same time.

The latest version of my RunAndWait example has a function ShellRunAndWait which might be what you need.

 

Comment
There are no comments made yet.
Chris Pollach @Appeon Accepted Answer Pending Moderation
  1. Monday, 23 May 2022 15:21 PM UTC
  2. PowerBuilder
  3. # 3

Hi Kyle;

  Try using the ShellExecuteW API to run external processes. 

FYI: https://www.topwizprogramming.com/freecode_runandwait.html

 You could also breakdown that part of your app into a separate EXE to do the Run() command. That would alleviate the main App to continue processing until the Run there was completed, the EXE completes thus, freeing the file lock. Food for thought.

HTH

Regards ... Chris

Comment
There are no comments made yet.
Kyle Bengtson Accepted Answer Pending Moderation
  1. Monday, 23 May 2022 17:55 PM UTC
  2. PowerBuilder
  3. # 4

Great suggestions Chris, but still no luck. I created a separate executable and I used ShellExecuteW in both apps, but I'm still getting a file lock. I created an app called runfile that only does this:

string ls_Null
long ll_rc
SetNull(ls_Null)
ll_rc = ShellExecuteW ( handle( this ), "open", "notepad.exe", "Recipient List.txt", ls_Null, 1)
halt

Then my app that calls it does this:

string ls_Null
long ll_rc
SetNull(ls_Null)
ll_rc = ShellExecuteW ( handle( this ), "open", "runfile.exe", ls_Null, ls_Null, 1)

The operating system still thinks the file is being used by my app, even though the runfile app is what opens it.

Comment
  1. Chris Pollach @Appeon
  2. Monday, 23 May 2022 20:57 PM UTC
Exactly... You needed to create a 2nd App exe that is called from your main App, that opens the file for processing. Then at the end of that file processing, the 2nd App ExE uses a "Halt Close" to terminate which will then relinquish the file lock. ;-)
  1. Helpful
There are no comments made yet.
Kyle Bengtson Accepted Answer Pending Moderation
  1. Monday, 23 May 2022 20:24 PM UTC
  2. PowerBuilder
  3. # 5

Thanks, Roland, I've found another way to skin the cat. I'm using a variable in the file name that increments, that way the same file is not re-used so there's no conflict.

Comment
  1. Arnd Schmidt
  2. Monday, 23 May 2022 22:19 PM UTC
Instead of fixing your code (grabbing multiple FileOpen() Handles but just one FileClose() ?!





  1. Helpful 2
There are no comments made yet.
Brad Mettee Accepted Answer Pending Moderation
  1. Tuesday, 24 May 2022 14:54 PM UTC
  2. PowerBuilder
  3. # 6

I can see multiple possible re-writes for this. It all depends on what is supposed to be in Recipient List at any given time.

1. Open file, loop through 1 to li_count, keep adding to file, run after loop

for li_loops = 1 to li_count
   if li_loops = 1 then
      li_FileNum = FileOpen("Recipient List.txt", TextMode!, Write!, Shared!, Append!)
   end if
   //populate ls_email_list variable from database view
   FileWriteEx(li_FileNum, ls_email_list)
   if li_loops = li_count then
      if FileClose(li_FileNum) = 1 then
         Run("notepad "+"Recipient List.txt")
      end if
   end if
next

2. Recipient list becomes multiple files which need creation/opening with every loop

string ls_Recipients
for li_loops = 1 to li_count
   ls_Recipients = "Recipient List_" + string(li_loops) + ".txt"
   li_FileNum = FileOpen(ls_Recipients, TextMode!, Write!, Shared!, Append!)
   //populate ls_email_list variable from database view
   FileWriteEx(li_FileNum, ls_email_list)
   if FileClose(li_FileNum) = 1 then
      Run("notepad " + ls_Recipients)
   end if
next

3. Recipient list stays single file, but gets opened, and waits for notepad to be closed with each loop

string ls_Recipients
ls_Recipients = "Recipient List.txt"
for li_loops = 1 to li_count
   li_FileNum = FileOpen(ls_Recipients, TextMode!, Write!, Shared!, Replace!)
   //populate ls_email_list variable from database view
   FileWriteEx(li_FileNum, ls_email_list)
   if FileClose(li_FileNum) = 1 then
      uo_RunAndWait.of_Run("notepad.exe " + ls_Recipients, uo_RunAndWait.SW_SHOWNORMAL)
   end if
next

 

Arnd pointed out what's causing the "file is still open" issue. If li_count > 1, then you're opening the file multiple times, but only closing (and releasing) it once. The remaining handles that were allocated stay live until your application is closed. A PB app running in the development environment is an extension of the PB dev environment. Nothing gets released until the Dev Env gets closed (with your app as written in your original post). The above three versions of your function solve that problem, and hopefully one of them should be what you originally needed for it to work right.

 

Comment
  1. Arnd Schmidt
  2. Tuesday, 24 May 2022 15:13 PM UTC
Call me Nobody ;-)

  1. Helpful
  1. Brad Mettee
  2. Tuesday, 24 May 2022 15:27 PM UTC
Thought I'd read the whole thread - needed more caffeine this morning I guess - edited and fixed and appropriate cred given
  1. Helpful
  1. Kyle Bengtson
  2. Tuesday, 24 May 2022 16:10 PM UTC
Thanks everyone! That was the issue, opening the file multiple times but only closing it once (so the extra handles were keeping it live). Not sure what I was thinking, maybe that the file would keep appending but not re-opening. Guess I need a new brand of coffee :-)
  1. Helpful
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.