Automatically installing nokogiri gem(Permission denied - Windows)

plugin

#1

Hi,

I’m struggling having the nokogiri xml gem automatically installed. Since building the library on windows is hard, they provide two gem files, for either 32 or 64bit. I’m using this block to detect a missing library and install the correct gem:

begin
  require 'nokogiri'
rescue LoadError
  if Sketchup.respond_to?(:is_64bit?) && Sketchup.is_64bit?
    puts "Trying to install nokogiri 64bit with " + File.expand_path('../sp/vendor/nokogiri/nokogiri-1.6.5-x64-mingw32.gem', __FILE__)
    Gem.install File.expand_path('../sp/vendor/nokogiri/nokogiri-1.6.5-x64-mingw32.gem', __FILE__)
  else 
    puts "Trying to install nokogiri 32bit with " + File.expand_path('../sp/vendor/nokogiri/nokogiri-1.6.5-x86-mingw32.gem', __FILE__)
    Gem.install File.expand_path('../sp/vendor/nokogiri/nokogiri-1.6.5-x86-mingw32.gem', __FILE__)
  end
  require 'nokogiri'
end

This works perfectly on my machine, but fails on another:

Trying to install nokogiri 64bit with C:/Users/<user>/AppData/Roaming/SketchUp/SketchUp 2015/SketchUp/Plugins/sp/vendor/nokogiri/nokogiri-1.6.5-x64-mingw32.gem
Load error: 
Error: #<Errno::EACCES: Permission denied - O:/.gem>
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/fileutils.rb:245:in `mkdir'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/fileutils.rb:245:in `fu_mkdir'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/fileutils.rb:219:in `block (2 levels) in mkdir_p'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/fileutils.rb:217:in `reverse_each'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/fileutils.rb:217:in `block in mkdir_p'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/fileutils.rb:203:in `each'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/fileutils.rb:203:in `mkdir_p'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/source.rb:123:in `load_specs'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/spec_fetcher.rb:225:in `tuples_for'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/spec_fetcher.rb:196:in `block in available_specs'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/source_list.rb:55:in `each'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/source_list.rb:55:in `each_source'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/spec_fetcher.rb:190:in `available_specs'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/spec_fetcher.rb:76:in `search_for_dependency'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/spec_fetcher.rb:134:in `spec_for_dependency'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/dependency_installer.rb:157:in `find_gems_with_sources'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/dependency_installer.rb:251:in `block in add_found_dependencies'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/dependency_installer.rb:241:in `each'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/dependency_installer.rb:241:in `add_found_dependencies'
C:/Program Files/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/dependency_installer.rb:199:in `gather_dependencies'

This happens also when I move my plugin folder to the ProgramData Sketchup folder and although Sketchup is started with admin privileges. I only care about windows users, but this should work with minimal user input indifferent of their privileges.


#2

That message says the GEM installer is trying to create a folder named “O:/.gem”, probably to hold configuration info, and the current user does not have adequate permission to create a new folder in the base of the O: drive.


#3

But why O:/? I tried 3 different things:

  • Installing the extension from Desktop folder
  • Manually copying the files into the AppData Plugin folder
  • Manually copying the files into the ProgramData Plugin folder

#4

did you try letting SU find and install it?

Gem.install 'nokogirri'

some do work, others fail…

john


#5

It’s likely that O: is somewhere wired into the GEM setup on that machine. This kind of thing can make installing GEMs under SketchUp very frustrating - the GEM install system is complex and obscure.


#6

After trying the same on another laptop (both admin and normal user account worked flawlessly), now tried replicating the error on a VM, but I got a different error:

Gem.install 'nokogiri'
Error: #<NameError: uninitialized constant Gem::Security::OpenSSL>
C:/Program Files (x86)/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/security.rb:355:in `<module:Security>'
C:/Program Files (x86)/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/security.rb:345:in `<top (required)>'
C:/Program Files (x86)/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/core_ext/kernel_require.rb:45:in `require'
C:/Program Files (x86)/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/core_ext/kernel_require.rb:45:in `require'
C:/Program Files (x86)/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/package.rb:43:in `<top (required)>'
C:/Program Files (x86)/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/core_ext/kernel_require.rb:45:in `require'
C:/Program Files (x86)/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/core_ext/kernel_require.rb:45:in `require'
C:/Program Files (x86)/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/dependency_installer.rb:3:in `<top (required)>'
C:/Program Files (x86)/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/core_ext/kernel_require.rb:45:in `require'
C:/Program Files (x86)/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems/core_ext/kernel_require.rb:45:in `require'
C:/Program Files (x86)/SketchUp/SketchUp 2015/Tools/RubyStdLib/rubygems.rb:524:in `install'
<main>:in `<main>'
SketchUp:1:in `eval'

FWIW, it’s the same error I get when trying to start my extension and the downloaded files.

And of course, this error is only thrown with SU2015, not SU2016…


#7

After more collaborating it turns out that O: is an old network drive that no one really knows how to use. It’s registered in the cmd environment variables (set in cmd, not windows environment variables) under HOME and HOMEDRIVE.
After I created the .gem directory itself, it threw several other errors, going 5 levels deep and then crashes looking for another obtuse .gem file in one of the directories.

Will talk to my system administrator, that does seem like a bug that no one else can have. Thanks for your pointers.

Any idea about the other #<NameError: uninitialized constant Gem::Security::OpenSSL I got in my VM only with SU2015?


#8

It’s telling you that the OpenSSL library module is missing or silently failed to load. Ruby Gems Security validates Gems using a cryptographic signature and certificate involving the OpenSSL library. That module is part of the standard library, and I don’t know why it would be ok on some of your machines but bad on the VM unless maybe there is a configuration glitch that keeps Gem from finding it. I think that from command line Ruby you can tell Gems not to bother with validation, but I have no idea how to do that from within SketchUp’s Ruby.


#9

Verify that the SSL certificate path is set.
At the Ruby Console type:

ENV["SSL_CERT_FILE"].inspect

If it is nil, the insert a line in your code:

if ENV["SSL_CERT_FILE"].nil?
  ENV["SSL_CERT_FILE"]= File.dirname(Sketchup.find_support_file("sketchup.exe"))<<
  "/Tools/RubyStdLib/platform_specific/cacert.pem"
end

The second thing is in the first post you used “…” in a pathstring. Never assume what the working directory is.
Use the block form of the Dir::chdir() class method to temporarily change the working directory.

Dir::chdir("C:/some/path/to/some/folder") {
  # do file operations here in that folder
}
# previous working directory is automatically restored

Lastly, the File::expand_path() class method is stupid.

It does nothing more than append the argument string onto the pathstring of the current working directory.

If the current working dir is somewhere other than where you assume it is, strange invalid pathstrings can be the result, which fail in subsequent file operations.

* Many coders assume that it will “devine” the true valid path from the root of a drive, for some relative pathstring argument given. But it does not. As you saw in the “O:/” path error, the current working directory can be set to another logical drive, than the one your relative path exists on.


#10

Oh also others have had issues with nokogirir on Windows.

See this thread:


#11
ENV["SSL_CERT_FILE"].inspect
# "C:/Program Files (x86)/SketchUp/SketchUp 2015/Tools/RubyStdLib/platform_specific/cacert.pem"

File.expand_path returns the absolute path of the first argument, relative to the second argument (which defaults to the current working directory). File.expand_path('../../Gemfile', __FILE__) is an easy and short method to get the absolute path of a file when you know the path relative to the current file and I don’t think that’s stupid. The extra … in the relative path is to eliminate the name of the file in FILE. I still think that’s better than temporarily changing the directory.

I’ve read that other thread before, but according to my system administrator my problems stem from O: being assigned as homedrive in our domain policy, working on that right now. Ruby itself has issues with this being present.


#12

My posting is also for general tips for other readers, also. (I have seen more times than I can count, coders making incorrect assumptions about what the current working directory is, with regard to file operations in general, and using File::expand_path in particular.)

:laughing:

I meant that the method was relatively stupid, as in it did not (or used to not,) have very much “smarts” programmed into it.

Yes using the optional 2nd arg helps greatly if you can provide it. What I said is true if one does not use a 2nd argument. (The length of lines in your code snippet put the 2nd argument out of sight and I had not scrolled over.)

FYI, SketchUp sets the path for gems at load time.
They are in the ENV hash.

ENV["GEM_HOME"]
ENV["GEM_PATH"]

These could be overridden for your specific installation (soon after startup.) Or you could save there pathstrings, change them temporarily, restore them afterward. When nokogiri is requiring other gems, they’ll get downloaded from the rubygems.org server to those paths.

Also HOMEDRIVE, HOMEPATH, and HOME are also in the ENV hash. (SketchUp creates HOME as a copy of USERPROFILE at startup.)

Since ENV is a Ruby interface to SketchUp’s copy of the environment, values can be changed without affecting the system’s copy or any other application’s copy.

An easy way to display the ENV hash in the console:

require "pp"
pp ENV