Creating embedded resource in C# class library if it doesn't exist - c#

I have an issue with a class library; I am preparing a library with an interface that represents a specific data storage signature. The purpose is to use the interface as a basis for implementing a number of specific classes storing configuration information in different formats (text files, xml files, etc.) while retaining the same usage profile to the application using it. I have a problem, though. In this case I am trying to embed an xml file as a resource - this file is one type of format to store configuration data. The file is located as an embedded resource in a subfolder to the project, as shown in the attached illustration.
In the following code snippet it is shown how I have implemented the functionality until now.
public ConfigInfoXmlSource()
{
if (!string.IsNullOrEmpty(Settings.Default.CurrentConfigFile))
FileNameAndPath = Settings.Default.CurrentConfigFile;
else
FileNameAndPath = DefaultConfigFileName + DefaultFileExtension;
// Prepare XML.
System.Reflection.Assembly a = Assembly.GetExecutingAssembly();
XmlDocument doc = new XmlDocument();
Stream manifestResourceStream =
a.GetManifestResourceStream("TestTool.Config.Config1.xml");
if (manifestResourceStream == null)
{
// ???
}
...
doc.Load(manifestResourceStream);
...
}
In the section marked "Prepare XML" I am trying to read a stream from the embedded resource. After the reading, it is tested whether a stream was indeed created. If the file is found, the manifestResourceStream will contain the xml data - so far so good. The problem arises if the file for some reason has been accidentally deleted - in that case I want to create a new file as an embedded resource to replace the deleted file. That is supposed to happen in the conditional in the part shown as "???".
I have tried everything I could think of, searched Google for answers, etc. - to no avail.
Does anyone have a clue to how this is accomplished? Any help will be greatly appreciated.
Thanks in advance.
Best regards.

If you have a embedded resource,it is built into your binaries.It is not an physical file,rather something which is present inside the built file(dll in this case).So,once it is included,I do not think it can ever be deleted. As per my knowledge embedded resource can only be set while building your project binaries and you can not explicitly do it at runtime as it is not needed due to reasons mentioned above.

Related

What could cause an XML file to be filled with null characters?

This is a tricky question. I suspect it will require some advanced knowledge of file systems to answer.
I have a WPF application, "App1," targeting .NET framework 4.0. It has a Settings.settings file that generates a standard App1.exe.config file where default settings are stored. When the user modifies settings, the modifications go in AppData\Roaming\MyCompany\App1\X.X.0.0\user.config. This is all standard .NET behavior. However, on occasion, we've discovered that the user.config file on a customer's machine isn't what it's supposed to be, which causes the application to crash.
The problem looks like this: user.config is about the size it should be if it were filled with XML, but instead of XML it's just a bunch of NUL characters. It's character 0 repeated over and over again. We have no information about what had occurred leading up to this file modification.
We can fix that problem on a customer's device if we just delete user.config because the Common Language Runtime will just generate a new one. They'll lose the changes they've made to the settings, but the changes can be made again.
However, I've encountered this problem in another WPF application, "App2," with another XML file, info.xml. This time it's different because the file is generated by my own code rather than by the CLR. The common themes are that both are C# WPF applications, both are XML files, and in both cases we are completely unable to reproduce the problem in our testing. Could this have something to do with the way C# applications interact with XML files or files in general?
Not only can we not reproduce the problem in our current applications, but I can't even reproduce the problem by writing custom code that generates errors on purpose. I can't find a single XML serialization error or file access error that results in a file that's filled with nulls. So what could be going on?
App1 accesses user.config by calling Upgrade() and Save() and by getting and setting the properties. For example:
if (Settings.Default.UpgradeRequired)
{
Settings.Default.Upgrade();
Settings.Default.UpgradeRequired = false;
Settings.Default.Save();
}
App2 accesses info.xml by serializing and deserializing the XML:
public Info Deserialize(string xmlFile)
{
if (File.Exists(xmlFile) == false)
{
return null;
}
XmlSerializer xmlReadSerializer = new XmlSerializer(typeof(Info));
Info overview = null;
using (StreamReader file = new StreamReader(xmlFile))
{
overview = (Info)xmlReadSerializer.Deserialize(file);
file.Close();
}
return overview;
}
public void Serialize(Info infoObject, string fileName)
{
XmlSerializer writer = new XmlSerializer(typeof(Info));
using (StreamWriter fileWrite = new StreamWriter(fileName))
{
writer.Serialize(fileWrite, infoObject);
fileWrite.Close();
}
}
We've encountered the problem on both Windows 7 and Windows 10. When researching the problem, I came across this post where the same XML problem was encountered in Windows 8.1: Saved files sometime only contains NUL-characters
Is there something I could change in my code to prevent this, or is the problem too deep within the behavior of .NET?
It seems to me that there are three possibilities:
The CLR is writing null characters to the XML files.
The file's memory address pointer gets switched to another location without moving the file contents.
The file system attempts to move the file to another memory address and the file contents get moved but the pointer doesn't get updated.
I feel like 2 and 3 are more likely than 1. This is why I said it may require advanced knowledge of file systems.
I would greatly appreciate any information that might help me reproduce, fix, or work around the problem. Thank you!
It's well known that this can happen if there is power loss. This occurs after a cached write that extends a file (it can be a new or existing file), and power loss occurs shortly thereafter. In this scenario the file has 3 expected possible states when the machine comes back up:
1) The file doesn't exist at all or has its original length, as if the write never happened.
2) The file has the expected length as if the write happened, but the data is zeros.
3) The file has the expected length and the correct data that was written.
State 2 is what you are describing. It occurs because when you do the cached write, NTFS initially just extends the file size accordingly but leaves VDL (valid data length) untouched. Data beyond VDL always reads back as zeros. The data you were intending to write is sitting in memory in the file cache. It will eventually get written to disk, usually within a few seconds, and following that VDL will get advanced on disk to reflect the data written. If power loss occurs before the data is written or before VDL gets increased, you will end up in state 2.
This is fairly easy to repro, for example by copying a file (the copy engine uses cached writes), and then immediately pulling the power plug on your computer.
I had a similar problem and I was able to trace my problem to corrupted HDD.
Description of my problem (all related informations):
Disk attached to mainboard (SATA):
SSD (system),
3 * HDD.
One of the HDD's had a bad blocks and there were even problems reading the disk structure (directories and file listing).
Operation system: Windows 7 x64
file system (on all disks): NTFS
When the system tried to read or write to the corrupted disk (user request or automatic scan or any other reason) and the attempt failed, all write operations (to other disk's) were incorrect. The files created on system disk (mostly configuration files by another applications) were written and were valid (probably because the files were cashed in RAM) on direct check of file content.
Unfortunately, after a restart, all the files (written after the failed write/read access on corrupted drive) had the correct size, but the content of the files was 'zero byte' (exactly like in your case).
Try rule out hardware related problems. You can try to check 'copy' the file (after a change) to a different machine (upload to web/ftp). Or try to save specific content to a fixed file. When the check file on different will be correct, or when the fixed content file will be 'empty', the reason is probably on local machine. Try to change HW components, or reinstall the system.
There is no documented reason for this behavior, as this is happening to users but nobody can tell the origin of this odd conditions.
It might be CLR problem, although this is a very unlikely, the CLR doesn't just write null characters and XML document cannot contain null characters if there's no xsi:nil defined for the nodes.
Anyway, the only documented way to fix this is to delete the corrupted file using this line of code:
try
{
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
}
catch (ConfigurationErrorsException ex)
{
string filename = ex.Filename;
_logger.Error(ex, "Cannot open config file");
if (File.Exists(filename) == true)
{
_logger.Error("Config file {0} content:\n{1}", filename, File.ReadAllText(filename));
File.Delete(filename);
_logger.Error("Config file deleted");
Properties.Settings.Default.Upgrade();
// Properties.Settings.Default.Reload();
// you could optionally restart the app instead
}
else
{
_logger.Error("Config file {0} does not exist", filename);
}
}
It will restore the user.config using the Properties.Settings.Default.Upgrade();
again without null values.
I ran into a similar issue but it was on a server. The server restarted while a program was writing to a file which caused the file to contain all null characters and become unusable to the program writing/reading from it.
So the file looked like this:
The logs showed that the server restarted:
The corrupted file showed that it was last updated at the time of the restart:
I have the same problem, there is an extra "NUL" character at the end of serialized xml file:
I am using XMLWriter like this:
using (var stringWriter = new Utf8StringWriter())
{
using (var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings { Indent = true, IndentChars = "\t", NewLineChars = "\r\n", NewLineHandling = NewLineHandling.Replace }))
{
xmlSerializer.Serialize(xmlWriter, data, nameSpaces);
xml = stringWriter.ToString();
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
if (removeEmptyNodes)
{
RemoveEmptyNodes(xmlDocument);
}
xml = xmlDocument.InnerXml;
}
}

Confused about embedded resources

I have a class library that contains some generic proceesing functionality - call it "Engine".
I include the class library in a number of web applications.
The engine library needs an XML file as input, but the content is unique to each project.
At the moment I manually copy the XML file into each project. The engine always looks for a file in the application route.
However, I've gotten a little confused with regards to embedded resources. In order to validate the XML, I've created an XSD in my engine project and set the Build Action to EmbeddedResource.
I can't see the difference between setting the BuildAction to Content and EmbeddedResource in this case, which has led me to doubt the way that things are currently set up.
I've not a lot of experience at this level, so need some guidance. Any advice would be appreciated.
EmbeddedResource means that the xsd is embedded inside the assembly during build, while Content means it is just copied along to the output folder. You want the embedded resource thing it sounds like.
You can access Embedded resources through code like this:
string resourceName = "SomeNameSpace.SomeFile.xsd";
Assembly assembly = Assembly.GetExecutingAssembly();
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
{
if ( stream == null )
throw new ArgumentException("resource not found", "resourceName");
using (StreamReader reader = new StreamReader(stream))
{
string result = reader.ReadToEnd();
return result;
}
}

C# Reading Video Metadata in Windows (Title,description,year)

Hey everyone just trying to make a program that browses video files and reads the title and description from the files metadata. I found some docs from microsoft here giving whats needed but how do I access these functions? what using namespaces are needed in c#? I would love any help that can be provided.
In that link you posted, scroll to the bottom and click "Shell Metadata Providers". There's more more information and some sample C++ code.
Here are some other relevant links:
Reading/Writing metadata of audio/video files
http://www.codeproject.com/Articles/14535/Accessing-WMF-metadata-with-C
https://social.msdn.microsoft.com/Forums/pt-BR/0f36a3b2-4d3d-4842-88a4-bea493bbbace/read-video-filemov-avi-mpg-etc-meta-data?forum=csharpgeneral
https://web.archive.org/web/20170225230114/https://stackoverflow.com/questions/7396265/c-sharp-to-read-properties-of-video-files
Sorry I can't give you anything more concrete, however it looks like some tag libraries (i.e. for reading MP3 metadata) may work as well, as the metadata for videos seems to be stored in a similar, if not identical, format. That being said, you can give TagLib# a shot.
https://www.nuget.org/packages/taglib/
I've made a simple C# code (portable to Unity, too) csatomreader. It's optimized for speed and can read the atoms over HTTP, too.
E.g. Get title:
using (FileStream stream = new FileStream(fileName, FileMode.Open))
{
var mp4Reader = new AtomReader(stream);
string value = mp4Reader.GetMetaAtomValue(AtomReader.TitleTypeName);
Console.WriteLine($"{atomTypeName}: {value}");
}
If you need to get more metadata values at once, then iterate over ParseAtoms(), e.g. see the GetMetaAtomValue() source.

Read file details (not language dependent)

In C#, I would like to read file details from a specific file.
I've found an interesting thread: Read/Write 'Extended' file properties (C#)
it uses a call to the GetDetailsOf() method on the folder shell object included in shell32.dll.
It works fine but I have an issue: According to the Operating System language, the header string is never the same...('Name' for the filename property on an english Windows, 'Nom' on a french Windows).
So, it's not easy to retrieve specific values with the name of the property as it changes according to the language...
Is there a way to handle this easily?
Some properties are available through the FileInfo object. For example, if you want the creation time of the file you can do:
Fileinfo myFileInfo = new Fileinfo(#"C:\path\to\file");
DateTime ftime = myFileInfo.CreationTime;
Is the FileInfo class not enough for your needs ?
FileInfo info = new FileInfo("fileName");
var name = info.Name;
var creationTime = info.CreationTime;
// etc ...
If not, tell more about which properties you'd like to read from your file.
Update to my answer :
I don't know about a library that would allow to read any type of document properties'
But here are a few ways for the formats you said,
PDF :
Extracting Additional Metadata from a PDF using iTextSharp
Read/Modify PDF Metadata using iTextSharp
So, iText ® is a library that allows you to create and manipulate PDF documents (from their website)
Office : (first link from MS stipulates that it applies to Word as well as Excel documents)
How to: Read from and Write to Document Properties
Listing properties of a word document in C#

Get PNG Image From Native Win32 Resource In .NET

A DLL file contains some images inside PNG resource type.
I can view the PNG images in softwares like Resource Hacker, Anolis Resourcer & Resource Tuner. Check this screenshot of Anolis Resourcer for more details:
Can someone tell me how do I get the PNG image no. 5220 from the DLL file and put it inside a PictureBox? I don't think APIs like LoadImage or LoadBitmap will work.
// get the assembly containing the image
var assembly = Assembly.GetExecutingAssembly();
// set the picturebox image to read the embedded resource
pictureBox1.Image = Image.FromStream(
assembly.GetManifestResourceStream("AssemblyName.test.png")
);
where AssemblyName.test.png is the fully qualified name of the embedded resource inside the assembly.
UPDATE:
It seems that you are trying to extract resources from a native assembly. You may take a look at the following article which illustrates how this could be done using P/Invoke.
The link that Darin posted (which has consequently been marked as the answer) does not contain functional code. I've evaluated the code posted there (http://khason.net/blog/how-to-load-unmanaged-native-resources-from-managed-c-code/) and found that it does not work properly for any Bitmap image embedded in any win32 dll as a bitmap resource.
Additionally, Hans Passant leaves off a myriad of steps effectively rendering his post useless.
The only somewhat close solution that I've been able to find comes from an article written in 2004 for the XP Theme dll junk. You can find the 'GetResourcePNG' method in ThemeManager.cs here http://www.codeproject.com/KB/miscctrl/XPTaskBar.aspx
However, it should be noted that I've been having a lot of difficulty with this method, as the call to bitmap.RotateFlip(RotateFlipType.Rotate180FlipX); causes memory issues when trying to access pngs within authui.dll on my system
Update:
I've found the code listed here (http://www.vbaccelerator.com/home/NET/Code/Controls/Explorer_Bar/ExplorerBar_Control_Source_Code.asp) to be by far the most functional, produce the fewest errors and produces the fastest results. The code is written in c# even though the domain name would indicate otherwise. Using the two classes; ImageUtility and ResourceLibrary, you can easily pull a PNG out of a standard, non-.net resource library/dll:
public static Bitmap GetStandardResourceBitmap(String dllName, String resourceId) {
Bitmap result = null;
using (ResourceLibrary library = new ResourceLibrary() { Filename = dllName }) {
IntPtr hDib = library.GetResource(resourceId, ResourceLibrary.ImageType.IMAGE_BITMAP, ResourceLibrary.ImageLoadOptions.LR_CREATEDIBSECTION);
if (!hDib.Equals(IntPtr.Zero)) {
result = ImageUtility.DibToBitmap(hDib);
ImageUtility.DeleteObject(hDib);
}
}
return result;
}
I chose to have resourceId in my method a String, only because it doesn't require an overload and using numbered resource Ids is as simple as prepending a '#'.
GetStandardResourceBitmap("shell32.dll", "#632");
Cheers
A PNG image is not one of the standard Win32 resource types. It is usually embedded as a binary blob with the named resource type "PNG", although that's not guaranteed. By far the easiest way to figure this out is by opening the file with Visual Studio's File + Open + File command. You'll see the embedded resources organized in a tree, hopefully with a descriptive name, right-click a candidate and select Export to save it to disk.
Doing this programmatically requires a lot of gritty pinvoke. It is tricky because both the resource type and the resource ID can be either a string or an IntPtr so you'll need 4 overloads for FindResource. In order, you'll need LoadLibraryEx() to load the file without executing any of its code. FindResource to get a handle to the resource. SizeOfResource to know how large it is. LoadResource + LockResource to get a pointer to the resource data. Marshal.Copy() to copy the resource data into a byte[]. Clean up with FreeResource and FreeLibrary.

Categories

Resources