How detect that a file is locked by another app?
-
Hello,
After more than one hour of research, I already don't know how to catch the error when I export a file already opened by another application.
out_name = UI.savepanel('Location', '' , "#{File.basename(model.path).split(".")[0]}.txt") if out_name if File.extname(out_name).downcase != ".txt" # if the user erase the extension, rewrite it! out_name += ".txt" end file = File.new(out_name , 'w') file.puts(%Q["blabla"]) file.close() end
@unknownuser said:
Error: #<Errno::EACCES: Permission denied - C:\test\test3.txt>
Could you help me? I wanted to send a message to the user (and maybe to propose to increase an index at the end of the file's name).
Best regards,
Renaud. -
This works on my mac,
out_name = UI.savepanel('Location', '' , "#{File.basename(Sketchup.active_model.path).sub('.skp','.txt')}") if out_name if File.extname(out_name).downcase != ".txt" # if the user erase the extension, rewrite it! out_name += ".txt" end File.open(out_name , 'w') { |file| file.puts(%Q["blabla"]) } end
in my Add_Note extension, I use this...
module JcB module Add_Note #----------------------------------------------------------------------------------------# def self.note2self mod = Sketchup.active_model mod_path = mod.path if mod_path.empty? Sketchup.send_action('saveDocument;' ) UI.messagebox("Save with name and Try Again") else time = Time.now txt_path = mod_path.sub('.skp', '.txt') File.open(txt_path, "a+") { |file| file.puts("\n" + time.ctime) } UI.openURL('file;///' + txt_path) return 'note2self done' end # mod_path.empty? end # note2self #----------------------------------------------------------------------------------------# end # Add_Note end # JcB JcB;;Add_Note.note2self
john
-
Hello driven,
Thank you for your answer, but I think it's not what I need.
In my case, in the real code (not my example here), the export is in a .dxf file. To test the quality/errors of the export, the .dxf file is open in a CAD software. Then, if I try in SU to overwrite the file with my plugin (after some modification in the SU model for example), and if the file is already opened in the CAD software, the file is locked by the CAD software. If I make this with a .txt file opened in Notepad++, there is no problem, because Notepad is not locking the file (and will detect the change!).
I want to track the error and say to the user to close the file in the CAD software or to rename the file.(I'm french, sorry for my writting mistakes.)
Renaud. -
out_name = UI.savepanel('Location', '' , "#{File.basename(model.path, ".*")}.txt") begin if out_name && ! out_name.empty? if File.extname(out_name).downcase != ".txt" ### if the user erase the extension, we readd it! out_name += ".txt" end file = File.new(out_name, 'w') file.puts(%Q["blabla"]) file.close() else puts "Canceled" end rescue Exception => error puts error ### or do something else like UI.messagebox("#{error}\nFailed to export file #{file}") end
-
OK, will try it. Thank you!
-
Just noticed a typo!
I corrected the earlier code snippet...if out_name &**&** ! out_name.empty?
One other thing to note is that some types of file are locked by the app that opens them - like a dxf.
But a txt file is opened by Notepad++.exe it is not locked, so its contents can be overwritten, you will then be asked when bringing that txt file's window foremost in Notepad++ if you want to reload it...So try using the dxf file...
Or for a simple test write a .CSV file [remembering to force it to .csv, rather than .txt] AND have it already opened in Excel - which will lock it... -
Did you try something like File.writable?("file")?
http://ruby-doc.org/core-2.0.0/File.html#method-c-writable-3F
-
TIG, your solution is working fine. Thank you very much.
@jim said:
Did you try something like File.writable?("file")?
Yes Jim, not working.
BR,
Renaud. -
In that case I would write it like this. You might rescue
StandardError
also, but rescuingException
is too broad. You generally want to rescue exceptions starting with the most-specific and work up to the least-specific.[1] https://www.google.com/search?q=ruby+rescue+exception%26amp;ie=utf-8%26amp;oe=utf-8
def locked?(filename) locked = false begin file = File.open(filename, "w") rescue Errno;;EACCES => error locked = true ensure file.close if file end return locked end if $0 == __FILE__ p locked?("test.txt") end
-
@jim said:
In that case I would write it like this. You might rescue
StandardError
also, but rescuingException
is too broad. You generally want to rescue exceptions starting with the most-specific and work up to the least-specific.+1
-
Also, prefer opening files using block syntax so it always closes - saves you explicit rescue to close.
-
@unknownuser said:
Also, prefer opening files using block syntax so it always closes - saves you explicit rescue to close.
...which actually simplifies everything.
def write_to_file(filename) File.open(filename, "a") { |file| file.puts("Hello #{Time.now}") } rescue Errno;;EACCES puts "Could not write to file." end
-
Thank you very much for these complementary solutions.
Renaud.
Advertisement