XmlSerializer Access Denied - c#

public void SerializeObject(string filename, T data)
{
// Get the path of the save game
string fullpath = filename;
// Open the file, creating it if necessary
//if (container.FileExists(filename))
// container.DeleteFile(filename);
FileStream stream = (FileStream)File.Open(fullpath, FileMode.OpenOrCreate);
try
{
// Convert the object to XML data and put it in the stream
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stream, data); //Thrown HERE
}
finally
{
// Close the file
stream.Close();
}
}
how do I make the above code stop throwing an InvalidOperationException?
The full error message is:
Unable to generate a temporary class (result=1).
error CS0016: Could not write to output file 'c:\Users[MYUSERNAME]\AppData\Local\Temp\czdgjjs0.dll' -- 'Access is denied.
I have no idea how to get around this error.
I am attempting to serialize my Level class which looks like this:
[Serializable]
public class Level : ISerializable
{
public string Name { get; set; }
public int BestTime { get; set; } //In seconds
public List<Block> levelBlocks { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public Level()
{
}
public Level(SerializationInfo info, StreamingContext ctxt)
{
this.Name = (String)info.GetValue("Name", typeof(String));
this.BestTime = (int)info.GetValue("BestTime", typeof(int));
this.levelBlocks = (List<Block>)info.GetValue("Blocks", typeof(List<Block>));
this.Width = (int)info.GetValue("Width", typeof(int));
this.Height = (int)info.GetValue("Height", typeof(int));
}
public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
{
info.AddValue("Name", this.Name);
info.AddValue("BestTime", this.BestTime);
info.AddValue("Blocks", this.levelBlocks);
info.AddValue("Width", this.Width);
info.AddValue("Height", this.Height);
}
}
My blocks class is implemented in a similar way and holds only a Position Vector that is saved.
Below, my save method:
public static void Save()
{
string filename = "saved.xml";
Level toSave = new Level();
toSave.levelBlocks = new List<Block>();
//TODO: build toSave
toSave.Name = "This is a level!";
toSave.BestTime = 0;
foreach (Entity e in EntityController.Entities)
{
if (e is Block)
{
toSave.levelBlocks.Add((Block)e);
if (e.Position.X > toSave.Width)
toSave.Width = (int)e.Position.X;
if (e.Position.Y > toSave.Height)
toSave.Height = (int)e.Position.Y;
}
}
serializer.SerializeObject(filename, toSave);
}
My program is an XNA game.

Use COMODO antivirus and get CS0016 error?
Open COMODO Command Window (Main Window), and check the SANDBOX. If your application is listed as an application that has been flagged 'limited', simply right click and select the option from the popup to add your application as a Trusted Application. Or just uninstall COMODO and reboot.That should resolve the problem with CS0016 error.

The accepted answer here System.InvalidOperationException: Unable to generate a temporary class (result=1) is likely to have a reasonable solution for you.
One possibility they didn't suggest: if you're using ASP.NET is changing the temp directory in the web.config. Check the tempDirectory attribute of the compilation element (info here http://msdn.microsoft.com/en-us/library/s10awwz0.aspx ) and change to somewhere that your ASP.NET process does have access to.
Ultimately, though, your problem is that the process doing the serialization needs to generate and write some code to disk and doesn't have permissions. You can give that process permissions, change the location to somewhere it does have permissions, or use sgen.exe, depending on what works best for your situation.

Related

How can I display my created error list using csvhelper

Apologies as this may seem a dumb question but I am missing something and not sure what to do.
As part of an application I'm making I am using CSVHelper for creating a file which contains details of any errors that may arise when using the application, such as a failure to connect to the database, values missing etc. I had been following this tutorial here: https://www.youtube.com/watch?v=fRaSeLYYrcQ and edited it more to suit my needs. I have an error logging file like so:
public class ErrorLogging
{
public string ErrorType { get; set; }
public string Relation { get; set; }
public string Message { get; set; }
public static List<ErrorLogging> GetErrors(string type, string relating, string message)
{
return new List<ErrorLogging>
{
new ErrorLogging
{
ErrorType = type,
Relation = relating,
Message = message
}
};
}
}
So here I have made it so the column headers in the csv file will be ErrorType, Relating and Message
I also have an export log file:
class ExportLog
{
public static void Log<T>(string path, string file, List<T>report)
{
var csvPath = Path.Combine(path + "\\", file);
using (var streamWriter = new StreamWriter(csvPath))
{
using (var csvWriter = new CsvWriter(streamWriter, CultureInfo.InvariantCulture))
{
csvWriter.WriteRecords(report);
}
}
}
}
In my main file program.cs I then use these by doing something like:
if (validateRoleTitles is not false)
{
log.Information("Roles found");
}
else
{
log.Warning("Roles could not be found");
ErrorLogging.GetErrors("Warning", "Database", "Not all roles found in the database");
}
And I now need to create the csv file with the list of errors by doing something like:
ExportLog.Log(config.ExportFolder, exportFile, "error logging list here");
However I'm not sure how to actually display these lists that I am creating if that makes sense?
As I can not do:
ExportLog.Log(config.ExportFolder, exportFile, ErrorLogging.GetErrors());
since it will be looking for parameters to be passed in. I know I am missing something very obvious here but can't figure out what, any help would be appreciated
So I ended up solving my issue, I had been going about it the wrong way, I did not need to have:
public static List<ErrorLogging> GetErrors(string type, string relating, string message)
{
return new List<ErrorLogging>
{
new ErrorLogging
{
ErrorType = type,
Relation = relating,
Message = message
}
};
}
in ErrorLogging.cs, it simply just needed to be:
public class ErrorLogging
{
public string ErrorType { get; set; }
public string Relation { get; set; }
public string Message { get; set; }
}
Then in program.cs I can declare a new list like so:
List<ErrorLogging> ErrorList = new List<ErrorLogging>();
and then when there is a point I would need to add to the list I can simply do something along the lines of:
ErrorList.Add(new ErrorLogging()
{
ErrorType = "Warning",
Relation = "Database",
Message = "Not all properties found in the database"
});
And then when it comes to creating the csv with the list of errors, I can check whether the list is empty or not, if not empty then create:
if (ErrorList.Any())
{
ExportLog.Log(config.LogFolder, errorLog, ErrorList);
}

Having an issue with my small & simple serializer for xml files

I was using a simple serializer to load an xml file to my game (I'm implementing mod support).
The way I had it first (it's not my own serializer) was like this:
public static EnemyList Load(string path)
{
TextAsset _xml = Resources.Load<TextAsset>(path);
XmlSerializer serializer = new XmlSerializer(typeof(EnemyList));
StringReader reader = new StringReader(_xml.text);
EnemyList enemies = serializer.Deserialize(reader) as EnemyList;
reader.Close();
return enemies;
}
The problem with that is that "Resources.Load" is being used. Since I want the players to write/install mods the Resources folder can't be used here (because as far as I know they can't access the Resources folder). Therefore I created a "Mods" folder in the build folder and in that Mods folder other peoples folders (for example if I would make a mod I would have a folder like "MyMod" and that folder would have other folders like "entities" with an "entities.xml" file) are located. To get all the files from a folder I used DirectoryInfo.
And here is my problem: I'm trying to change the serializer to work with DirectoryInfo. This is the code so far:
public static EnemyList LoadXml(string path)
{
DirectoryInfo direcInfo = new DirectoryInfo(path);
FileInfo[] fileInfo = direcInfo.GetFiles();
XmlSerializer serializer = new XmlSerializer(typeof(EnemyList));
StringReader reader = new StringReader(fileInfo[0].ToString());
EnemyList enemies = serializer.Deserialize(reader) as EnemyList;
reader.Close();
return enemies;
}
but when I start the game I'm getting the Error: XmlException: Data at the root level is invalid. Line 1, position 1.
I've also tried things like File.ReadAllText(path) but I'm getting an "unauthorizedaccessexception".
When I googled that problem I found out that I need to specify a file in the path and not the directory (not just Mods/entities but Mods/entities/entities.xml) but I don't want to just read one single file. I want to ready every xml file that is in there. And even if I change it to entities.xml I'm still getting an Error IOException: Error 267 (couldn't find any answers to fix that)
I hope someone can help me with that. I've already googled but the people on the forum did completely different things, I couldn't apply that to my case.
Thank you in advance!
In case the xml is needed:
First you need to get the path to the directory you want to search in and then loop through each XML File in that Directory. With SearchOption.AllDirectory you also search in all sub directories that are in the current directory.
Loop through your Directory:
string folderWithModFiles = "YourPath";
List<Enemy> enemylist = new List<Enemy>();
foreach (string xmlFile in Directory.EnumerateFiles(folderWithModFiles, "*.xml", SearchOption.AllDirectories)) {
try {
enemylist = SerializeXML(xmlFile);
}
catch(Exception e) {
Debug.LogException(e);
}
}
The try catch is to ensure that no faulty XML files are read.
De-serializing XML File:
private List<Enemy> SerializeXMLS(string filePath) {
using (FileStream fileStream = System.IO.File.Open(filePath, FileMode.Open)) {
var serializer = new XmlSerializer(typeof(EnemyList));
var enemyList = serializer.Deserialize(fileStream) as EnemyList;
// Read the data you need from the XML File
// If the user didn't specify certain things he need to specify,
// you can throw an ArgumentExpection and the file will be skipped
return enemyList.ListOfEnemies;
}
}
}
Example of the EnemyList XML Parse File:
[XmlRoot("Entities")]
[CreateAssetMenu(menuName = "Nations of Cubion/Item/List of Enemies")]
public class EnemyList {
[XmlArray]
[XmlArrayItem("Entity")]
public List<Entity> ListOfEnemies {
get; set;
}
}
public class Entity{
[XmlAttribute("name")]
public string name{
get; set;
}
[XmlElement("mesh")]
public string mesh {
get; set;
}
[XmlElement("material")]
public string material {
get; set;
}
[XmlElement("enemyType")]
public string enemyType {
get; set;
}
[XmlElement("elementType")]
public string elementType {
get; set;
}
[XmlElement("maxHealth")]
public string maxHealth {
get; set;
}
}

Why is my game serializing this class?

So I'm making a game, and it saves users' progress on the computer in a binary file. The User class stores a few things:
Integers for stat values (Serializable)
Strings for the Username and the skin assets
Lists of both the Achievement class and the InventoryItem class, which I have created myself.
Here are the User fields:
public string Username = "";
// ID is used for local identification, as usernames can be changed.
public int ID;
public int Coins = 0;
public List<Achievement> AchievementsCompleted = new List<Achievement>();
public List<InventoryItem> Inventory = new List<InventoryItem>();
public List<string> Skins = new List<string>();
public string CurrentSkinAsset { get; set; }
The Achievement class stores ints, bools, and strings, which are all serializable. The InventoryItem class stores its name (a string) and an InventoryAction, which is a delegate that is called when the item is used.
These are the Achievement class's fields:
public int ID = 0;
public string Name = "";
public bool Earned = false;
public string Description = "";
public string Image;
public AchievmentDifficulty Difficulty;
public int CoinsOnCompletion = 0;
public AchievementMethod OnCompletion;
public AchievementCriteria CompletionCriteria;
public bool Completed = false;
And here are the fields for the InventoryItem class:
InventoryAction actionWhenUsed;
public string Name;
public string AssetName;
The source of the InventoryAction variables are in my XNAGame class. What I mean by this is that the XNAGame class has a method called "UseSword()" or whatever, which it passes into the InventoryItem class. Previously, the methods were stored in the Game1 class, but the Game class, which Game1 inherits from, is not serializable, and there's no way for me to control that. This is why I have an XNAGame class.
I get an error when trying to serialize: "The 'SpriteFont' class is not marked as serializable", or something like that. Well, there is a SpriteFont object in my XNAGame class, and some quick tests showed that this is the source of the issue. Well, I have no control over whether or not the SpriteFont class is Serializable.
Why is the game doing this? Why must all the fields in the XNAGame class be serializable, when all I need is a few methods?
Keep in mind when answering that I'm 13, and may not understand all the terms you're using. If you need any code samples, I'll be glad to provide them for you. Thanks in advance!
EDIT: One solution I have thought of is to store the InventoryAction delegates in a Dictionary, except that this will be a pain and isn't very good programming practice. If this is the only way, I'll accept it, though (Honestly at this point I think this is the best solution).
EDIT 2: Here's the code for the User.Serialize method (I know what I'm doing in inefficient, and I should use a database, blah, blah, blah. I'm fine with what I'm doing now, so bear with me.):
FileStream fileStream = null;
List<User> users;
BinaryFormatter binaryFormatter = new BinaryFormatter();
try
{
if (File.Exists(FILE_PATH) && !IsFileLocked(FILE_PATH))
{
fileStream = File.Open(FILE_PATH, FileMode.Open);
users = (List<User>)binaryFormatter.Deserialize(fileStream);
}
else
{
fileStream = File.Create(FILE_PATH);
users = new List<User>();
}
for (int i = 0; i < users.Count; i++)
{
if (users[i].ID == this.ID)
{
users.Remove(users[i]);
}
}
foreach (Achievement a in AchievementsCompleted)
{
if (a.CompletionCriteria != null)
{
a.CompletionCriteria = null;
}
if (a.OnCompletion != null)
{
a.OnCompletion = null;
}
}
users.Add(this);
fileStream.Position = 0;
binaryFormatter.Serialize(fileStream, users);
You cannot serialize a SpriteFont by design, actually this is possible (.XNB file) but it hasn't been made public.
Solution:
Strip it off your serialized class.
Alternatives:
If for some reasons you must serialize some font, the first thing that comes to my mind would be to roll-out your own font system such as BMFont but that's a daunting task since you'll have to use it everywhere else where you might already do ...
Generate a pre-defined amount of fonts (i.e. Arial/Times/Courier at size 10/11/12 etc ...) using XNA Content app (can't recall its exact name); then store this user preference as two strings. With a string.Format(...) you should be able to load the right font back quite easily.
Alternative 2 is certainly the easiest and won't take more than a few minutes to roll-out.
EDIT
Basically, instead of saving a delegate I do the following:
inventory items have their own type
each type name is de/serialized accordingly
their logic does not happen in the main game class anymore
you don't have to manually match item type / action method
So while you'll end up with more classes, you have concerns separated and you can keep your main loop clean and relatively generic.
Code:
public static class Demo
{
public static void DemoCode()
{
// create new profile
var profile = new UserProfile
{
Name = "Bill",
Gold = 1000000,
Achievements = new List<Achievement>(new[]
{
Achievement.Warrior
}),
Inventory = new Inventory(new[]
{
new FireSpell()
})
};
// save it
using (var stream = File.Create("profile.bin"))
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, profile);
}
// load it
using (var stream = File.OpenRead("profile.bin"))
{
var formatter = new BinaryFormatter();
var deserialize = formatter.Deserialize(stream);
var userProfile = (UserProfile) deserialize;
// set everything on fire :)
var fireSpell = userProfile.Inventory.Items.OfType<FireSpell>().FirstOrDefault();
if (fireSpell != null) fireSpell.Execute("whatever");
}
}
}
[Serializable]
public sealed class UserProfile
{
public string Name { get; set; }
public int Gold { get; set; }
public List<Achievement> Achievements { get; set; }
public Inventory Inventory { get; set; }
}
public enum Achievement
{
Warrior
}
[Serializable]
public sealed class Inventory : ISerializable
{
public Inventory() // for serialization
{
}
public Inventory(SerializationInfo info, StreamingContext context) // for serialization
{
var value = (string) info.GetValue("Items", typeof(string));
var strings = value.Split(';');
var items = strings.Select(s =>
{
var type = Type.GetType(s);
if (type == null) throw new ArgumentNullException(nameof(type));
var instance = Activator.CreateInstance(type);
var item = instance as InventoryItem;
return item;
}).ToArray();
Items = new List<InventoryItem>(items);
}
public Inventory(IEnumerable<InventoryItem> items)
{
if (items == null) throw new ArgumentNullException(nameof(items));
Items = new List<InventoryItem>(items);
}
public List<InventoryItem> Items { get; }
#region ISerializable Members
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
var strings = Items.Select(s => s.GetType().AssemblyQualifiedName).ToArray();
var value = string.Join(";", strings);
info.AddValue("Items", value);
}
#endregion
}
public abstract class InventoryItem
{
public abstract void Execute(params object[] objects);
}
public abstract class Spell : InventoryItem
{
}
public sealed class FireSpell : Spell
{
public override void Execute(params object[] objects)
{
// using 'params object[]' a simple and generic way to pass things if any, i.e.
// var world = objects[0];
// var strength = objects[1];
// now do something with these !
}
}
Okay, so I figured it out.
The best solution was to use a Dictionary in the XNAGame class, which stores two things: an ItemType (an enumeration), and an InventoryAction. Basically, when I use an item, I check it's type and then look up it's method. Thanks to everyone who tried, and I'm sorry if the question was confusing.

AIMLBot C# save brain

I am working with AIMLbot.dll in c#. I saw two functions saveToBinaryFile and loadFromBinaryFile. I think these functions are to store current contents in bot's brain to a file. But it doesn't seems to be working! Means, If I say to remember my name and save the content to GraphMaster.dat file. Next time I load the content of the same file and when I ask my name its giving the wrong answer. My class is as follows.
class AIBot
{
private Bot myBot;
private User myUser;
public AIBot()
{
myBot = new Bot();
myUser = new User("UnknownUser", myBot);
}
public void Initialize()
{
myBot.loadSettings();
myBot.isAcceptingUserInput = false;
myBot.loadAIMLFromFiles();
myBot.isAcceptingUserInput = true;
}
public void Load()
{
if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + #"\Graphmaster.dat"))
myBot.loadFromBinaryFile(AppDomain.CurrentDomain.BaseDirectory + #"\Graphmaster.dat");
}
public string GetResponse(string input)
{
Request r = new Request(input, myUser, myBot);
Result res = myBot.Chat(r);
return (res.Output);
}
public void Save()
{
myBot.saveToBinaryFile(AppDomain.CurrentDomain.BaseDirectory + #"\Graphmaster.dat");
}
}
Can anybody help to point out the problem?
I got a solution for the problem. Hope it will help others.
Save user session like
this.myUser.Predicates.DictionaryAsXML.Save(saveFileDialogDump.FileName);
Load the stored session next time.
this.myUser.Predicates.loadSettings(openFileDialogDump.FileName);

Use Protobuf-net to stream large data files as IEnumerable

I'm trying to use Protobuf-net to save and load data to disk but got stuck.
I have a portfolio of assets that I need to process, and I want to be able to do that as fast as possible. I can already read from a CSV but it would be faster to use a binary file, so I'm looking into Protobuf-Net.
I can't fit all assets into memory so I want to stream them, not load them all into memory.
So what I need to do is expose a large set of records as an IEnumerable. Is this possible with Protobuf-Net? I've tried a couple of things but haven't been able to get it running.
Serializing seems to work, but I haven't been able to read them back in again, I get 0 assets back. Could someone point me in the right direction please? Looked at the methods in the Serializer class but can't find any that covers this case. I this use-case supported by Protobuf-net? I'm using V2 by the way.
Thanks in advance,
Gert-Jan
Here's some sample code I tried:
public partial class MainWindow : Window {
// Generate x Assets
IEnumerable<Asset> GenerateAssets(int Count) {
var rnd = new Random();
for (int i = 1; i < Count; i++) {
yield return new Asset {
ID = i,
EAD = i * 12345,
LGD = (float)rnd.NextDouble(),
PD = (float)rnd.NextDouble()
};
}
}
// write assets to file
private void Write(string path, IEnumerable<Asset> assets){
using (var file = File.Create(path)) {
Serializer.Serialize<IEnumerable<Asset>>(file, assets);
}
}
// read assets from file
IEnumerable<Asset> Read(string path) {
using (var file = File.OpenRead(path)) {
return Serializer.DeserializeItems<Asset>(file, PrefixStyle.None, -1);
}
}
// try it
private void Test() {
Write("Data.bin", GenerateAssets(100)); // this creates a file with binary gibberish that I assume are the assets
var x = Read("Data.bin");
MessageBox.Show(x.Count().ToString()); // returns 0 instead of 100
}
public MainWindow() {
InitializeComponent();
}
private void button2_Click(object sender, RoutedEventArgs e) {
Test();
}
}
[ProtoContract]
class Asset {
[ProtoMember(1)]
public int ID { get; set; }
[ProtoMember(2)]
public double EAD { get; set; }
[ProtoMember(3)]
public float LGD { get; set; }
[ProtoMember(4)]
public float PD { get; set; }
}
figured it out. To deserialize use PrefixBase.Base128 wich apparently is the default.
Now it works like a charm!
GJ
using (var file = File.Create("Data.bin")) {
Serializer.Serialize<IEnumerable<Asset>>(file, Generate(10));
}
using (var file = File.OpenRead("Data.bin")) {
var ps = Serializer.DeserializeItems<Asset>(file, PrefixStyle.Base128, 1);
int i = ps.Count(); // got them all back :-)
}

Categories

Resources