Several user questions are from people getting a message “CFileException 0” when trying to save a .skp file, and the file is not saved (instead a new file is created, with an extra number). I found out that this problem can be triggered by Ruby extensions that use “Process.spawn()”. This Ruby function causes some handles from the parent process (SketchUp) to be inherited by the child process. It has got an optional argument “close_others”, supposed to prevent that—and the default value should be true—but it doesn’t seem to work on Windows, at least in the version of Ruby within SketchUp 2018. If you don’t know what “inheriting handles” mean, in short, it means that whatever files are currently opened in SketchUp won’t be closed until the child process also closes them (or finishes running). That’s why, on Windows, SketchUp cannot overwrite the file it had opened.
As a workaround, the following (Windows-only) code creates a new process using directly the Windows API, passing it the correct flag “don’t inherit the handles” (it’s one of the zeroes).
require 'fiddle'
require 'fiddle/types'
require 'fiddle/import'
module Kernel32
extend Fiddle::Importer
dlload 'kernel32.dll'
include Fiddle::Win32Types
PROCESS_INFORMATION = struct [
"HANDLE hProcess",
"HANDLE hThread",
"DWORD dwProcessId",
"DWORD dwThreadId"
]
extern 'BOOL CreateProcessA(LPCSTR, PVOID, PVOID, PVOID, BOOL, DWORD, PVOID, PVOID, const char *, struct PROCESS_INFORMATION *)'
extern 'BOOL CloseHandle(HANDLE)'
end
def launch_my_process(cmd)
startinfo = ([0] * 18).pack('Q' * 18)
procinfo = Kernel32::PROCESS_INFORMATION.malloc
procinfo.hProcess = 0
procinfo.hThread = 0
procinfo.dwProcessId = 0
procinfo.dwThreadId = 0
result = Kernel32.CreateProcessA(cmd, nil, nil, nil, 0, 0, nil, nil, startinfo, procinfo)
if result == 0
# failed!
else
Kernel32.CloseHandle(procinfo.hThread)
Kernel32.CloseHandle(procinfo.hProcess)
end
end