1

Closed

Addin registry access/creation errors when accessed via UNC path

description

On Windows, if the addin registry is accessed using a UNC path (e.g., "\server\share\directory") instead of a local path (e.g., "X:\directory"). Mono.Addins will mangle the path name upon initialization, which can result in a number of different (usually fatal) exceptions. For example, on my workstation MonoDevelop 2.4.1 reports the following error:
 
System.IO.FileNotFoundException: Could not find file '\\irtnog.net\roothome\xenophon\Library\MonoDevelop\addin-db-001\hosts'.
File name: '\\irtnog.net\roothome\xenophon\Library\MonoDevelop\addin-db-001\hosts'
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.Directory.InternalCreateDirectory(String fullPath, String path, DirectorySecurity dirSecurity)
   at System.IO.Directory.CreateDirectory(String path, DirectorySecurity directorySecurity)
   at Mono.Addins.AddinRegistry.CreateHostAddinsFile(String hostFile)
   at Mono.Addins.AddinEngine.Initialize(String configDir, Assembly startupAsm)
   at Mono.Addins.AddinManager.Initialize(String configDir)
   at MonoDevelop.Core.Runtime.Initialize(Boolean updateAddinRegistry)
FATAL ERROR [2011-01-11 13:36:36Z]: MonoDevelop failed to start. Some of the assemblies required to run MonoDevelop (for example gtk
-sharp, gnome-sharp or gtkhtml-sharp) may not be properly installed in the GAC.
System.InvalidOperationException: Add-in engine not initialized.
   at Mono.Addins.AddinEngine.CheckInitialized()
   at Mono.Addins.AddinManager.GetExtensionObjects(String path)
   at MonoDevelop.Ide.DesktopService.Initialize()
   at MonoDevelop.Ide.IdeStartup.Run(String[] args)
   at MonoDevelop.Startup.MonoDevelopMain.Main(String[] args)
 
In my case, the system administrator has set a Group Policy Object (GPO) that redirects the AppData\Roaming folder to a network share, which here is \irtnog.net\root\home\xenophon\Library. However, according to my testing, the error will occur regardless of how Mono.Addins selects the adding registry directory. For example, MonoDevelop raises the same exception if I set MONO_ADDINS_REGISTRY to a UNC path.
 
To work around this problem, one can set MONO_ADDINS_REGISTRY to a local path, even if that path refers to a drive letter mapped to a network share. In my case, U: maps to \irtnog.net\root\home\xenophon, so I can get MonoDevelop to start normally if I set MONO_ADDINS_REGISTRY to "U:\Library\mono.addins".
 
As you can see from my examples, Mono.Addins.Database.Util.GetFullPath() removes the directory separator between the root of the path and its remaining parts. The code assumes that the root includes a trailing directory separator (which is not the case for UNC paths), so in the last line of the method, when it rejoins the root together with the other parts of the path, it neglects to check for a trailing slash in the root and add one in if it is missing.
 
There probably several ways to fix this. I would probably use System.IO.Path.Combine(), because the resulting code would be more portable. My patch (attached) uses the "root" local variable to hold the new path, which is built up using Path.Combine() over each iteration of GetFullPath's for loop. I also renamed "root" to "newPath" to make the variable's revised purpose clearer to other readers and removed the now superfluous "newParts" variable. Please note that my patch is against release 0.5 of Mono.Addins in the unified diff format.

file attachments

Closed Feb 11, 2011 at 7:08 PM by slluis
Closing.

comments

slluis wrote Jan 29, 2011 at 11:43 AM

Thanks the for the bug report. I removed the whole GetFullPath method. It was added because Mono used to have a bug in Path.GetFullPath which caused it to fail when the path did not exist. This was fixed long ago, so there is no need for a private implementation of that method anymore.