api-issue-tracker icon indicating copy to clipboard operation
api-issue-tracker copied to clipboard

Sketchup.temp_dir returns short names on windows

Open tdapper opened this issue 7 years ago • 20 comments

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

tdapper avatar Oct 22 '18 14:10 tdapper

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...

MSP-Greg avatar Oct 22 '18 18:10 MSP-Greg

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.

tdapper avatar Oct 23 '18 08:10 tdapper

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...

MSP-Greg avatar Oct 23 '18 17:10 MSP-Greg

Logged SU-41959

taustin73 avatar Jan 30 '19 23:01 taustin73

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?

tdapper avatar Nov 25 '20 10:11 tdapper

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 avatar Nov 25 '20 12:11 thomthom

@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.

tdapper avatar Nov 25 '20 14:11 tdapper

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...

MSP-Greg avatar Nov 25 '20 15:11 MSP-Greg

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 avatar Nov 25 '20 15:11 DanRathbun

@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

MSP-Greg avatar Nov 25 '20 15:11 MSP-Greg

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

DanRathbun avatar Nov 25 '20 16:11 DanRathbun

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

MSP-Greg avatar Nov 25 '20 16:11 MSP-Greg

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.)

thomthom avatar Nov 30 '20 10:11 thomthom

... 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.

DanRathbun avatar Nov 30 '20 21:11 DanRathbun

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.)

thomthom avatar Dec 01 '20 10:12 thomthom

What about SketchUp updating it's own distribution of the Etc libarary ? (This could be a community Git effort.)

DanRathbun avatar Dec 02 '20 18:12 DanRathbun

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.

thomthom avatar Dec 03 '20 09:12 thomthom

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']))

DanRathbun avatar Dec 06 '20 23:12 DanRathbun

For the record here is (one of) the issues on this topic in the Ruby bug tracker: https://bugs.ruby-lang.org/issues/12650

thomthom avatar Dec 15 '20 09:12 thomthom

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

kalpana-ghodeswar avatar May 19 '25 15:05 kalpana-ghodeswar