Sketchup.temp_dir returns short names on windows
When using Sketchup.temp_dir on Windows and the path has a folder component that does not comply with the 8.3 naming scheme, it returns the short name (e.g. C:\Users\MyLongUsername\AppData\Local\Temp becomes C:\Users\MYLONG~1\AppData\Local\Temp).
This can cause all sorts of problems e.g. when comparing this path with paths from other sources that don't have this problem.
The problem might come from the underlying integration of Ruby or general use of the Win32 API, because using regular Ruby functions such as Dir.mktmpdir() produce the same problem.
SketchUp 2018 Windows
Also see: https://stackoverflow.com/questions/52872069/how-to-convert-ruby-string-encoding-to-win32-and-back
This is a messy issue. Is it Windows, Ruby, or SU's implementation of Ruby.
I added a 'long user name' account on Win10, and ENV['TEMP'] and ENV['TMP'] were set by Windows to 8.3 naming. Ruby's Etc.systmpdir did correctly return the long name.
I haven't checked all versions, but newer Ruby versions check ENV['TMPDIR'] before the other ENV settings. You might experiment with setting that to the long name when your code loads...
You are right, it certainly does look a little messy. I checked the environment as suggested and it indeed already contains the short names. The temporary folder detection in Python appears to do the same thing (return the short path).
This makes it look like it's not a SketchUp issue. One could perhaps argue, that it would be cleaner if Ruby would call the Win32 GetLongPathName() function internally, but then again there are probably also reasons against that (even though it looks like that is what Etc.systmpdir does).
Not sure what to say other than that I would kinda implicitly expect the Sketchup API function not to bother with legacy 8.3 file name conventions. That is also what @thomthom appears to expect when he suggested to use it. So I'd tend to lean towards changing that behavior on the SketchUp-side from a user expectation point of view. It might break stuff in some rare cases, though.
This issue also causes a few problems with Ruby CI testing (along with the temp folder being on a different drive than Ruby), so I created a Ruby bug report for it. If a fix is decided on, hopefully it can be backported to 2.5 and maybe 2.4.
Maybe Trimble could consider releasing maintenance builds whenever Ruby has a 'tiny' update, at least for a year or two after release...
Logged SU-41959
We're looking into this again currently, because we are working around this by using Win32API, which now produces deprecation messages. I was wondering whether this has been solved somewhere for newer versions of SketchUp (specifically SketchUp 2021, which now uses Ruby 2.7), @taustin73, @thomthom.
@MSP-Greg, you said that you created a Ruby bug report for it. Is there a link to that bug report, so I can maybe check in on it?
AFIK there's been no changes in SketchUp itself. And I don't have a machine with a long username available right at this moment.
As for Win32API deprecation, Fiddle is a cross platform successor. This ships with Ruby standard library.
@thomthom Thanks for your reply. I am aware of fiddle, but since what we did with it was a workaround to a problems with Sketchup.temp_dir as well as Dir.mktmpdir in the first place, I was hoping that this may have been fixed (probably on the Ruby side) and I could perhaps just use the functions as intended and wouldn't have to port that workaround at all.
Ruby bug report: https://bugs.ruby-lang.org/issues/15247, no responses. I suppose I could post another message.
Part of the problem with this issue is that fixes would be a breaking change, and I suspect that most users of '*nix' based software are aware of issues with file systems. Not necessarily true of Windows SU users.
I just looked thru the Etc c source, and it appears that Ruby doesn't really look up the user's ENV['temp'] setting and translate it to a long name. It looks up ENV['LOCALAPPDATA'], which is stored as a long name, and appends Temp to it.
Have you considered using File.absolute_path? I think it does the short/long path conversion...
You should be able to use the WIN32OLE class.
if Sketchup.platform == :platform_win
require "win32ole"
def get_temp_path
WIN32OLE.new("WScript.Shell").ExpandEnvironmentStrings("%TEMP%")
end
else
def get_temp_path
ENV["TEMP"] || ENV["TMP"]
end
end
REF: Windows Scripting Host object
WshShell Object
ExpandEnvironmentStrings Method
Also, one of the other benefits of using the WSH Shell object is that you can get localized paths to the user's special folders regardless of what language version of Windows they are using.
@DanRathbun
That doesn't work if ENV['TEMP'] is a short filename.
One reference is the Windows runners that GitHub Actions provides. See https://github.com/MSP-Greg/actions-image-testing/actions, click to the most recent run, then the most recent windows job (currently 'Windows-2019'), then view the 'show ENV' step.
The username is runneradmin, which is over 8 characters. So..
ENV KEY VALUE
LOCALAPPDATA C:\Users\runneradmin\AppData\Local
TEMP C:\Users\RUNNER~1\AppData\Local\Temp
TMP C:\Users\RUNNER~1\AppData\Local\Temp
Bummer. I thought it would expand the User~1, but I guess it means that it expands the %name% variable.
So apparently even Windows has left the TEMP with the shortened names for backward compatibility ?
TEMP = ENV["TEMP"]
if TEMP.include?('~') &&
TEMP.start_with?("#{ENV['SYSTEMDRIVE']}\\Users\\") &&
TEMP.end_with?('\AppData\Local\Temp')
TEMP = File.join(ENV['LocalAppData'],'Temp')
end
Windows has left the TEMP with the shortened names for backward compatibility ?
Appears so.
All the recent code testing I did was with stand-alone Ruby master/main.
I just checked with SU 2018 (Ruby 2.2.4), and File.absolute_path ENV['TEMP'] correctly translates a short path to a long path.
Also, checked with SU 2018 & 2021, and Sketchup.temp_dir is static in the sense that changing ENV['Temp'] after SU is running doesn't change it.
I don't have any older versions loaded...
EDIT: There is also the issue of what ENV keys (and in what order) are used to determine the temp path. Somewhere, Ruby uses 'TMPDIR', 'TEMP', and then 'TMP'. I think.
And then there's ETC.systmpdir, which assumes the Windows default, which uses rb_w32_system_tmpdir in win32/win32.c, which is currently :
https://github.com/ruby/ruby/blob/7aaf6676c416/win32/win32.c#L517-L532
I was hoping that this may have been fixed (probably on the Ruby side) and I could perhaps just use the functions as intended and wouldn't have to port that workaround at all.
It looks like GetTempPath is always returning 8.3 for app compatibility, and that using GetLongPathName on that is the canonical way to go. We could do that for Sketchup.temp_dir, but I'm also concerned about compatibility in that it might break existing functions that already use it. But we could make it opt-in to get the long name; Sketchup.temp_dir(longname: true) (or something to that effect.)
... but I'm also concerned about compatibility in that it might break existing functions that already use it. But we could make it opt-in to get the long name;
Sketchup.temp_dir(longname: true)(or something to that effect.)
That would be the best backward compatible way as older versions would ignore the named argument.)
However, this issue only occurs because this method should never have been implemented within the SketchUp API.
It does not belong in the SketchUp API. It belongs in a System library (or gem) like those pointed at by Greg. In this way it can be fixed and updated independently from SketchUp.
If gems are going to be a problem going forward, then a community maintained library would be the best option in my opinion.
And then this method should be deprecated.
Yea, I agree, it wasn't an ideal case for the SketchUp API. Unfortunately there wasn't any good alternative at the time. (Nor at this time for that matter.)
What about SketchUp updating it's own distribution of the Etc libarary ? (This could be a community Git effort.)
We ship what the Ruby project provide. We don't want to be patching Ruby as that causes more work when we update. If anything I'd recommend anyone interested providing a PR to the upstream library.
So we are left with a workaround such as ...
# At the top of an extension submodule or
# ... within some library module (perhaps a mixin):
LOCALAPPDATA ||= File.absolute_path(ENV['LOCALAPPDATA'])
TEMP ||= File.join(LOCALAPPDATA, File.basename(ENV['TEMP']))
For the record here is (one of) the issues on this topic in the Ruby bug tracker: https://bugs.ruby-lang.org/issues/12650
Hi tdapper,
I just tried to reproduce this issue with version SU2023.0 onwards on Windows, and it's not returning short format any more. The issue has been resolved. Could you please confirm the same? thanks
Output :
SketchUp Temp Dir: C:/Users/path/AppData/Local/Temp Ruby Temp Dir: C:/Users/path/AppData/Local/Temp/d20250519-27344-oarbl6