How to get long file name from ARGV

I want to create a tool that takes some file names as parameters, but when I use this code:

ARGV.each do|a| puts "Argument: #{a}" end 

and I use drag and drop or "send" in Windows, I get a short file name. Thus, a file like "C:\Ruby193\bin\test\New Text Document.txt" becomes C:\Ruby193\bin\test\NEWTEX~1.TXT as an argument.

There is no problem running the script from the command line with long names as parameters.

How to get long file name when I use drag and drop or send?

+7
source share
4 answers

I don't know if it is possible to change the argument you get when dragging, but you can use Win32 getLongPathName() using Win32 Ruby bindings

- edit--
Including @peter solution formatted for readability:

 require 'find' require 'fileutils' require 'Win32API' def get_long_win32_filename(short_name) max_path = 1024 long_name = " " * max_path lfn_size = Win32API.new("kernel32", "GetLongPathName", ['P','P','L'],'L').call(short_name, long_name, max_path) return (1..max_path).include?(lfn_size) ? long_name[0..lfn_size-1] : short_name end ARGV.each do|a| puts a puts get_long_win32_filename(a) end 
+4
source

http://www.varioustopics.com/ruby/518646-rre-ruby-cygwin-and-paths.html

 require 'find' require 'fileutils' require 'Win32API' def get_long_win32_filename(short_name) max_path = 1024 long_name = " " * max_path lfn_size = Win32API.new("kernel32", "GetLongPathName", ['P','P','L'],'L').call(short_name, long_name, max_path) return (1..max_path).include?(lfn_size) ? long_name[0..lfn_size-1] : short_name end ARGV.each do|a| puts a puts get_long_win32_filename(a) end 
+5
source

I learned a lot while trying to figure it out!

However, @peter outranked me with a much simpler solution.

Here is mine, in case someone finds it useful. file_get_long_name.rb

I got an idea: an archive article vb-world.net and converted it to ruby.

 require 'win32ole' def get_long_filename(shortpath, fso = WIN32OLE.new("Scripting.FileSystemObject")) path = case when fso.FolderExists(shortpath) fso.GetFolder(fso.GetAbsolutePathName(shortpath)) when fso.FileExists(shortpath) fso.GetFile(fso.GetAbsolutePathName(shortpath)) else return nil end parts = path.Path.split(/\\/) working = fso.GetDrive(parts.shift).RootFolder longpath = working.Path parts.each do |part| temppath = fso.BuildPath(longpath, part) working = fso.GetFolder(longpath) if fso.FolderExists(temppath) working.SubFolders.each do |sub| longpath = fso.BuildPath(longpath, sub.Name) if part== sub.ShortName || part == sub.Name end elsif fso.FileExists(temppath) working.Files.each do |sub| longpath = fso.BuildPath(longpath, sub.Name) if part== sub.ShortName || part == sub.Name end end end longpath end fso = WIN32OLE.new("Scripting.FileSystemObject") short = "C:\\DOCUME~1\\jamal\\Desktop\\NEWTEX~1.TXT" long = get_long_filename(short, fso) p long # ==> "C:\\Documents and Settings\\jamal\\Desktop\\New Text Document.txt" 
0
source

I found the reason my script got short file names, I made a registry patch to enable drag and drop on ruby ​​scripts and schortcuts as follows

 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\rbfile\ShellEx\DropHandler] @="{86C86720-42A0-1069-A2E8-08002B30309D}" [HKEY_CLASSES_ROOT\rbwfile\ShellEx\DropHandler] @="{86C86720-42A0-1069-A2E8-08002B30309D}" [HKEY_CLASSES_ROOT\RubyFile\ShellEx\DropHandler] @="{86C86720-42A0-1069-A2E8-08002B30309D}" [HKEY_CLASSES_ROOT\RubyWFile\ShellEx\DropHandler] @="{86C86720-42A0-1069-A2E8-08002B30309D}" 

But for LONG filenames, this should be the following:

 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\rbfile\ShellEx\DropHandler] @="{60254CA5-953B-11CF-8C96-00AA00B8708C}" [HKEY_CLASSES_ROOT\rbwfile\ShellEx\DropHandler] @="{60254CA5-953B-11CF-8C96-00AA00B8708C}" [HKEY_CLASSES_ROOT\RubyFile\ShellEx\DropHandler] @="{60254CA5-953B-11CF-8C96-00AA00B8708C}" [HKEY_CLASSES_ROOT\RubyWFile\ShellEx\DropHandler] @="{60254CA5-953B-11CF-8C96-00AA00B8708C}" 
0
source

All Articles