in src/Tasks/GenerateResource.cs [2454:2713]
private bool ProcessFile(string inFile, string outFileOrDir)
{
Format inFileFormat = GetFormat(inFile);
if (inFileFormat == Format.Error)
{
// GetFormat would have logged an error.
return false;
}
if (inFileFormat != Format.Assembly) // outFileOrDir is a directory when the input file is an assembly
{
Format outFileFormat = GetFormat(outFileOrDir);
if (outFileFormat == Format.Assembly)
{
_logger.LogErrorFromResources("GenerateResource.CannotWriteAssembly", outFileOrDir);
return false;
}
else if (outFileFormat == Format.Error)
{
return false;
}
}
if (!_extractResWFiles)
{
_logger.LogMessageFromResources("GenerateResource.ProcessingFile", inFile, outFileOrDir);
}
// Reset state
_readers = new List<ReaderInfo>();
try
{
ReadResources(inFile, _useSourcePath, outFileOrDir);
}
catch (ArgumentException ae)
{
if (ae.InnerException is XmlException)
{
XmlException xe = (XmlException) ae.InnerException;
_logger.LogErrorWithCodeFromResources(null, FileUtilities.GetFullPathNoThrow(inFile), xe.LineNumber,
xe.LinePosition, 0, 0, "General.InvalidResxFile", xe.Message);
}
else
{
_logger.LogErrorWithCodeFromResources(null, FileUtilities.GetFullPathNoThrow(inFile), 0, 0, 0, 0,
"General.InvalidResxFile", ae.Message);
}
return false;
}
catch (TextFileException tfe)
{
// Used to pass back error context from ReadTextResources to here.
_logger.LogErrorWithCodeFromResources(null, tfe.FileName, tfe.LineNumber, tfe.LinePosition, 1, 1,
"GenerateResource.MessageTunnel", tfe.Message);
return false;
}
catch (XmlException xe)
{
_logger.LogErrorWithCodeFromResources(null, FileUtilities.GetFullPathNoThrow(inFile), xe.LineNumber,
xe.LinePosition, 0, 0, "General.InvalidResxFile", xe.Message);
return false;
}
catch (Exception e) when (
#if FEATURE_BINARY_SERIALIZATION
e is SerializationException ||
#endif
e is TargetInvocationException)
{
// DDB #9819
// SerializationException and TargetInvocationException can occur when trying to deserialize a type from a resource format (typically with other exceptions inside)
// This is a bug in the type being serialized, so the best we can do is dump diagnostic information and move on to the next input resource file.
_logger.LogErrorWithCodeFromResources(null, FileUtilities.GetFullPathNoThrow(inFile), 0, 0, 0, 0,
"General.InvalidResxFile", e.Message);
// Log the stack, so the problem with the type in the .resx is diagnosable by the customer
_logger.LogErrorFromException(e, /* stack */ true, /* inner exceptions */ true,
FileUtilities.GetFullPathNoThrow(inFile));
return false;
}
catch (Exception e) when (ExceptionHandling.IsIoRelatedException(e))
{
// Regular IO error
_logger.LogErrorWithCodeFromResources(null, FileUtilities.GetFullPathNoThrow(inFile), 0, 0, 0, 0,
"General.InvalidResxFile", e.Message);
return false;
}
string currentOutputFile = null;
string currentOutputDirectory = null;
string currentOutputSourceCodeFile = null;
bool currentOutputDirectoryAlreadyExisted = true;
try
{
if (GetFormat(inFile) == Format.Assembly)
{
#if FEATURE_BINARY_SERIALIZATION
// Prepare cache data
ResGenDependencies.PortableLibraryFile library = new ResGenDependencies.PortableLibraryFile(inFile);
#endif
List<string> resWFilesForThisAssembly = new List<string>();
foreach (ReaderInfo reader in _readers)
{
String currentOutputFileNoPath = reader.outputFileName + ".resw";
currentOutputFile = null;
currentOutputDirectoryAlreadyExisted = true;
string priDirectory = Path.Combine(outFileOrDir ?? String.Empty,
reader.assemblySimpleName);
currentOutputDirectory = Path.Combine(priDirectory,
reader.cultureName ?? String.Empty);
if (!Directory.Exists(currentOutputDirectory))
{
currentOutputDirectoryAlreadyExisted = false;
Directory.CreateDirectory(currentOutputDirectory);
}
currentOutputFile = Path.Combine(currentOutputDirectory, currentOutputFileNoPath);
// For very long resource names, this directory structure may be too deep.
// If so, assume that the name is so long it will already uniquely distinguish itself.
// However for shorter names we'd still prefer to use the assembly simple name
// in the path to avoid conflicts.
currentOutputFile = EnsurePathIsShortEnough(currentOutputFile, currentOutputFileNoPath,
outFileOrDir, reader.cultureName);
if (currentOutputFile == null)
{
// We couldn't generate a file name short enough to handle this. Fail but continue.
continue;
}
// Always write the output file here - other logic prevents us from processing this
// file for incremental builds if everything was up to date.
WriteResources(reader, currentOutputFile);
string escapedOutputFile = EscapingUtilities.Escape(currentOutputFile);
ITaskItem newOutputFile = new TaskItem(escapedOutputFile);
resWFilesForThisAssembly.Add(escapedOutputFile);
newOutputFile.SetMetadata("ResourceIndexName", reader.assemblySimpleName);
#if FEATURE_BINARY_SERIALIZATION
library.AssemblySimpleName = reader.assemblySimpleName;
#endif
if (reader.fromNeutralResources)
{
newOutputFile.SetMetadata("NeutralResourceLanguage", reader.cultureName);
#if FEATURE_BINARY_SERIALIZATION
library.NeutralResourceLanguage = reader.cultureName;
#endif
}
ExtractedResWFiles.Add(newOutputFile);
}
#if FEATURE_BINARY_SERIALIZATION
library.OutputFiles = resWFilesForThisAssembly.ToArray();
_portableLibraryCacheInfo.Add(library);
#endif
}
else
{
currentOutputFile = outFileOrDir;
ErrorUtilities.VerifyThrow(_readers.Count == 1,
"We have no readers, or we have multiple readers & are ignoring subsequent ones. Num readers: {0}",
_readers.Count);
WriteResources(_readers[0], outFileOrDir);
}
if (_stronglyTypedLanguage != null)
{
try
{
ErrorUtilities.VerifyThrow(_readers.Count == 1,
"We have no readers, or we have multiple readers & are ignoring subsequent ones. Num readers: {0}",
_readers.Count);
CreateStronglyTypedResources(_readers[0], outFileOrDir, inFile, out currentOutputSourceCodeFile);
}
catch (Exception e) when (ExceptionHandling.IsIoRelatedException(e))
{
// IO Error
_logger.LogErrorWithCodeFromResources("GenerateResource.CannotWriteSTRFile",
_stronglyTypedFilename, e.Message);
if (File.Exists(outFileOrDir)
&& GetFormat(inFile) != Format.Assembly
// outFileOrDir is a directory when the input file is an assembly
&& GetFormat(outFileOrDir) != Format.Assembly)
// Never delete an assembly since we don't ever actually write to assemblies.
{
RemoveCorruptedFile(outFileOrDir);
}
if (currentOutputSourceCodeFile != null)
{
RemoveCorruptedFile(currentOutputSourceCodeFile);
}
return false;
}
}
}
catch (IOException io)
{
if (currentOutputFile != null)
{
_logger.LogErrorWithCodeFromResources("GenerateResource.CannotWriteOutput",
FileUtilities.GetFullPathNoThrow(currentOutputFile), io.Message);
if (File.Exists(currentOutputFile))
{
if (GetFormat(currentOutputFile) != Format.Assembly)
// Never delete an assembly since we don't ever actually write to assemblies.
{
RemoveCorruptedFile(currentOutputFile);
}
}
}
if (currentOutputDirectory != null &&
currentOutputDirectoryAlreadyExisted == false)
{
// Do not annoy the user by removing an empty directory we did not create.
try
{
Directory.Delete(currentOutputDirectory); // Remove output directory if empty
}
catch (Exception e)
{
// Fail silently (we are not even checking if the call to File.Delete succeeded)
if (ExceptionHandling.IsCriticalException(e))
{
throw;
}
}
}
return false;
}
catch (Exception e) when (
#if FEATURE_BINARY_SERIALIZATION
e is SerializationException ||
#endif
e is TargetInvocationException)
{
// DDB #9819
// SerializationException and TargetInvocationException can occur when trying to serialize a type into a resource format (typically with other exceptions inside)
// This is a bug in the type being serialized, so the best we can do is dump diagnostic information and move on to the next input resource file.
_logger.LogErrorWithCodeFromResources("GenerateResource.CannotWriteOutput",
FileUtilities.GetFullPathNoThrow(inFile), e.Message); // Input file is more useful to log
// Log the stack, so the problem with the type in the .resx is diagnosable by the customer
_logger.LogErrorFromException(e, /* stack */ true, /* inner exceptions */ true,
FileUtilities.GetFullPathNoThrow(inFile));
return false;
}
catch (Exception e) when (ExceptionHandling.IsIoRelatedException(e))
{
// Regular IO error
_logger.LogErrorWithCodeFromResources("GenerateResource.CannotWriteOutput",
FileUtilities.GetFullPathNoThrow(currentOutputFile), e.Message);
return false;
}
return true;
}