Perform operations in a plugin when its is being uninstalled

First of all, … never use messageboxes (Ie, modal windows) for debugging. (They can fail silently.)
Instead, open the Ruby Console and use the global puts() method to send output to STDOUT.

Okay there are several things incorrect.

(1) Most important. Remove this line:

EXTENSION.define_singleton_method(:mark_as_uninstalled) { super; nil }  

This is replacing the overridden method in your Extension subclass that you defined above. I never said that you should do both. I said that the singleton method could be attached only if a coder was not writing a SketchupExtension subclass.

(2) Frivolous - The use of ||=. It makes no sense to use this operator inside a method upon a non-persistent object reference. Local references (ie, components_path and collection_path,) are transitory. They only exist until the method returns, then are garbage collected automatically as they “go out of scope”.

(3) Minor - Set your own copyright value …

EXTENSION.copyright   = "©2025, Carlos"

… or similar

And a comment on …

moving of MyComponents to be a subfolder of the Components folder operation
has been part of the body of my main.rb for some time and it seems to work fine, I will consider to put that inside the copy_components function.

It is okay to have the copy of extension’s components in the “main.rb” as this would be
a “copy upon first run” scenario, rather than a “copy upon first install” scenario.

Dan, thanks a lot for your reply!

According to your comments I have changed my code to

require 'fileutils' unless defined?(FileUtils)

module MyMain
  module MyPlugin
  
    class Extension < ::SketchupExtension

	  def delete_components
   	    components_path = Sketchup.find_support_file('Components')
	    collection_path = File.join(components_path, 'MyComponents')
	    return unless File.directory?(collection_path)
	    FileUtils.remove_dir(collection_path)
	  end  
		  
	  def mark_as_uninstalled	    
        puts("First Line of mark_as_uninstalled")
        delete_components()
	    super
	    return nil
	  end
    end        # end class Extension 

    # moving of MyComponents to be a subfolder of the Components folder operation 
    # has been part of the body of my main.rb for some time and it seems to work fine, 
    # I will consider to put that inside the copy_components function.

    # get versionNo an integer with the SU version obtained from Sketchup.version

    if versionNo > 16 		  
	EXTENSION = Extension.new("Delete MyComponents during uninstall", "MyPlugin/main")
	EXTENSION.creator     = "Carlos"
	EXTENSION.description = "Delete MyComponents subfolder from the Components folder"
	EXTENSION.version     = "1.0.1"
	EXTENSION.copyright   = "©2025, MyCompany"
        Sketchup.register_extension(EXTENSION, true)
    end	    

  end
end

However, still it seems like my mark_as_uninstalled function is not triggered at uninstall, I am saying that because I cannot see my puts being displayed in the ruby console, neither MyComponents subfolder is being deleted. I did also tried to introduce in the beginning of the function a command that produces an error (that was an order to rename a non-existing file inside the components folder of SketchUp) but I couldn’t see any error message at uninstall which reinforces my suspicion that my mark_as_uninstalled function is not being visited somehow.

regards, Carlos

I would prefer the components are copied during the install rather than at first run. So I will try to insert my code in the “register_from_sketchup” function from your snippet. I can tell that function is being called in my plugin (when it is included), so even though my “mark_as_uninstalled” does not work the extension seems to be registered correctly.

regards, Carlos

What version of SketchUp are you testing under?

Well, this is an old version. But it still should work.

There have been two updates. The latest version is 24.0.594 (rel. 2024.0.2)

Okay found another booboo …

    if versionNo > 16

… results in

Error: #<NameError: undefined local variable or method `versionNo'...>

Change this line to:

    if Sketchup.version.to_i > 16

You could also add an else clause to the if

    if Sketchup.version.to_i > 16
      # extension instantiation and registration
    else
      fail(NotImplementedError,"MyExtension requires SketchUp 2017 or higher.")
    end
1 Like

Dan,

Thanks, I am aware that versionNo was not defined in my pseudocode, tried to explain what it was in the comment above rather than putting the explicit code. I am sorry that was not clear enough. In versionNo I am trying to extract the digits of Sketchup.version before the first ‘.’ character, see the code below

	def self.getSUversionNo
 
      versionchars = Sketchup.version.split('')
	  versionNochars = ''
	  versionchars.each { |c| 
	    if c != '.'
	  	  versionNochars = versionNochars + c
	    else
	      break		 
	    end  
	  }
       
	  return versionNochars.to_i
	  
	end

I didn’t have problems with versionNo in my plugin so far. It is used in multiple units of my plugin so the function above resides in a unit with other general functions that are visible from the rest of units, that’s why I tried to keep it out from the pseudocode.

In any case, I don’t think this is the problem why my “mark_as_unistall” function is not visited. Will install the latest SU24 and let you know what happens.

As mentioned above the shared pseudocode of my main.rb is a simplified version containing the code (I believe) that matters regarding the SketchupExtension class.

Besides this extension class, there is an Importer class defined in my main.rb that was not included in the pseudocode because it seems to work fine before and after including the SketchupExtension class. Do you think having the two of them could be causing the problem?

Apart from that the rest of the code in the body of my main.rb regards, creating buttons and menu items that connect with functions from the rest of units of the plugin. All of it seems to work fine before and after including the SketchupExtension class.

regards, carlos

Why use such convoluted code?

Even Sketchup.version.split('.').first.to_i would return a comparable integer. (But Ruby’s String#to_i will do it alone, ignoring anything to the left of the decimal point character.)

If I were to test it, an exception would be raised and the extension object would not be instantiated or registered.

Secondly, you said this …

That did not resemble “This is pseudocode” … ie, “much simplified”.

Okay? Listen. I have no idea why your edition is not working. And I have no more time to waste. I have my own projects I’m working on.

You’ll need to figure it out yourself since only you can actually see the real code.

I gave a working example that works in SketchUp 2024, that I tested on Windows 11 and Steve tested on MacOS platform. Use the example for what it’s worth or don’t. … whatever.

1 Like

I don’t have that much experience with ruby. Will use your one line command in the following.

That’s alright, I understand. Will try to find a solution myself you have been as always very helpful, Thank you.

regards, Carlos

1 Like