The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,604 other followers

.NET/C#: When XmlSerializer throws “Unable to generate a temporary class (result=1).” / “error CS2001”

Posted by jpluimers on 2014/02/06

A while ago, I had this error when running an application on a hardened server:

Unhandled Exception:System.InvalidOperationException:
Unable to generate a temporary class (result=1).
error CS2001: Source file 'C:\windows\TEMP\0hocq2nq.0.cs' could not be found  error CS2008: No inputs specified
at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence)
at System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, XmlSerializerCompilerParameters parameters, Assembly assembly, Hashtable assemblies)
at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location, Evidence evidence)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, String defaultNamespace, String location, Evidence evidence)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, String defaultNamespace, String location)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, Type[] extraTypes)

Usually I’m not the first with strange errors, but searching for “Unhandled Exception:System.InvalidOperationException: Unable to generate a temporary class” didn’t get many results.

This was a program running from SSIS under a non-system domain account with very little access.

My first guess was the right now: the XmlSerializer wants to generate a temporary C# file, then compile it into a temporary assembly. Since it cannot generate the C# file because the account does not have access to %windir\TEMP%, the compiler cannot find the (not generated) C# file.

After a few tries, I searched for XmlSerializer without GenerateAssembly, where the first hit ended at Changing where XmlSerializer Outputs Temporary Assemblies – Scott Hanselman.

That post indicated I should try looking for tempFilesLocation in the XmlSerializer context.

That got me these posts:

In this project, I could not change the XmlSerializer to something different, so the trick was finding a directory where the user could write, and specify it like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.xml.serialization>
    <xmlSerializer tempFilesLocation="c:\path\where\the\user\can\write\temp\files"/>
  </system.xml.serialization>
</configuration>

Note: if you have a configSections element in your web.config / app.config, make sure the above settings come after it:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="enterpriselibrary.configurationSettings" type="System.Configuration.IgnoreSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  </configSections>
  <system.xml.serialization>
    <xmlSerializer tempFilesLocation="c:\path\where\the\user\can\write\temp\files"/>
  </system.xml.serialization>
</configuration>

If you don’t, you get a nice exception like this:

Unhandled Exception: System.Configuration.ConfigurationErrorsException:
Configuration system failed to initialize
---> System.Configuration.ConfigurationErrorsException: Only one <configSections> element allowed per config file and if present must be the first child of the root <configuration> element. (\\server\share\app\appName.exe.Config line 13)
at System.Configuration.ConfigurationSchemaErrors.ThrowIfErrors(Boolean ignoreLocal)
at System.Configuration.BaseConfigurationRecord.ThrowIfParseErrors(ConfigurationSchemaErrors schemaErrors)
at System.Configuration.ClientConfigurationSystem.EnsureInit(String configKey)
--- End of inner exception stack trace ---
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location, Evidence evidence)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, String defaultNamespace, String location, Evidence evidence)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, String defaultNamespace, String location)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, Type[] extraTypes)
--- End of inner exception stack trace ---

I am trying to refactor this application in the future, so I am able to change the XmlSerializer into something else. Options from the last post by Kris Ragh MSFT mentioned above:

In that same post, User Paolo Tedesco – Stack Overflow had a deleted answer that is interesting too because of my added emphasis: XmlSerializer always writes temp files, no matter what settings.

Is it possible that you have the XmlSerialization.Compilation switch enabled in the diagnostics section of your config file?

Serialization assemblies should be generated in memory by default if that switch is not specified, and that would remove the problem of finding an always writable location.

Nope – temp files are always generated on disk. Deleting the post.

Some other interesting posts for my reading list that I also found during this journey:

–jeroen

PS: For some kinds of authorization failures on the TEMP directory, you get this exception:

System.UnauthorizedAccessException was unhandled
Message=Access to the temp directory is denied. Identity ‘DOMAIN\USER’ under which XmlSerializer is running does not have sufficient permission to access the temp directory. CodeDom will use the user account the process is using to do the compilation, so if the user doesn’t have access to system temp directory, you will not be able to compile. Use Path.GetTempPath() API to find out the temp directory location.
Source=System.Xml
StackTrace:
at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence)
at System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, XmlSerializerCompilerParameters parameters, Assembly assembly, Hashtable assemblies)
at System.Xml.Serialization.XmlSerializer.GenerateTempAssembly(XmlMapping xmlMapping, Type type, String defaultNamespace, String location, Evidence evidence)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, String defaultNamespace, String location, Evidence evidence)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, Type[] extraTypes)
[/sourecode]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

 
%d bloggers like this: