Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Exception when saving using Application.PersistentDataPath on Windows Phone

Discussion in 'Windows' started by Marzipan, Aug 15, 2014.

  1. Marzipan

    Marzipan

    Joined:
    Feb 21, 2013
    Posts:
    7
    Hello,

    When saving on WP8 (Nokia 520, Unity 4.5.3f3), I get the following exception:

    A first chance exception of type 'System.Exception' occurred in WinRTLegacy.DLL
    Exception: Unsupported uri: c:/data/users/defapps/appdata/{c133a4f8-83a8-4125-a749-a6480c9068c2}/local\autosave.litdsavedgame
    at WinRTLegacy.UnityFileStreams.OpenFile(String uri, FileMode mode)
    at WinRTLegacy.UnityFileStreams.OpenFileForWriting(String uri)
    at System.Xml.XmlTextWriter..ctor(String filename, Encoding encoding)
    at System.Xml.XmlDocument.Save(String filename)


    The file path is generated as follows:

    var path = System.IO.Path.Combine(Application.persistentDataPath, filename);
    ...
    var doc = new XmlDocument();
    ...
    doc.Save(path);

    I tried changing the "\" in the file path to "/" - same result. Anyone have any ideas? This code works fine on Windows / Android / iOS.
     
  2. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    What is the value of the "filename" variable?
     
  3. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,491
    Hi, this might be a bug in our XML implementation. Could you try changing all '/' path separators to '\' ones? If that doesn't work, could you try replacing Application.persistentDataPath with "ms-appdata:///local/"?
     
  4. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,627
    The present implementation of XML classes on Windows Phone/Windows Store Apps only supports URIs, not paths.
    This will be improved in 5.0.
    For now use isostore:/ on WP and ms-appdata:/// uris.
     
  5. Marzipan

    Marzipan

    Joined:
    Feb 21, 2013
    Posts:
    7
    Thanks for your replies.

    Replacing '/' with '\' didn't work. I am trying to use the alternate path prefixes but no success so far. I don't get the "unsupported uri" exception any more but the game acts like no data has been saved. Just to be 100% clear: Should I be replacing:

    var path = System.IO.Path.Combine(Application.persistentDataPath, filename);

    with

    var path = "ms-appdata:///local/" + filename;

    on WP8?
     
  6. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,627
    If it's WP8, not WP8.1, then use isostore:/ uri. Note, that there's only one slash here, rather than 3.
     
  7. Marzipan

    Marzipan

    Joined:
    Feb 21, 2013
    Posts:
    7
    So... I tried but was not able to get a save game saving using the isostore:/ uri (no errors but the code acted like the save game wasn't there - quite possibly I was doing something wrong). I ended up adding some ifdef'd code that followed the example outlined here on how to access isolated storage with xml: http://msdn.microsoft.com/en-us/library/cc838189(v=vs.95).aspx. That worked for me!
     
  8. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,627
    Can you show an example of your code? I tmight be a bug in our XML implementation.
     
  9. konsnos

    konsnos

    Joined:
    Feb 13, 2012
    Posts:
    120
    @Aurimas Cernius
    this is my code, and I get the same behaviour as @Marzipan
    Code (CSharp):
    1.  
    2. private string filePath = "ms-appdata:///local/GameData.dat";
    3.  
    4. XmlSerializer serializer = new XmlSerializer(typeof(PlayerData));
    5.             XmlTextWriter xmlWriter = new XmlTextWriter(filePath, Encoding.UTF8);
    6.             serializer.Serialize(xmlWriter, playerData);
    7.             xmlWriter.Close();
    8.  
    9. bool fileExists = System.IO.File.Exists(filePath);
    10.   Debug.Log(fileExists); // This is false!!!!
    11.  
    No errors. It seems that the file just doesn't get saved.
     
  10. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    konsnos, are you targeting WP8 or WP8.1? As Aurimas suggested, what happens if you change line 2 in your example to this:

    Code (csharp):
    1.  
    2. private string filePath = "isostore:///local/GameData.dat"; //isostore instead of ms-appdata
    3.  
     
  11. konsnos

    konsnos

    Joined:
    Feb 13, 2012
    Posts:
    120
    I'm targetting WP8.1. Did the change you said. File path is "isostore:///local/GameData.dat", and got error.
    Code (CSharp):
    1. An exception of type 'System.IO.IsolatedStorage.IsolatedStorageException' occurred in mscorlib.ni.dll but was not handled in user code
    2. Additional information: Operation not permitted on IsolatedStorageFileStream.
     
  12. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    well, if it's 8.1 then it will be ms-appdata. Try this:

    Code (csharp):
    1.  
    2. var path = @"ms-appdata:///local/";
    3. var exists = System.IO.Directory.Exists(path);
    4. Debug.Log(exists);
    5.  
     
  13. konsnos

    konsnos

    Joined:
    Feb 13, 2012
    Posts:
    120
    Result if false :-S . I didn't expect that. I don't have anything to think of right now. What do you make of this Dustin?
     
  14. konsnos

    konsnos

    Joined:
    Feb 13, 2012
    Posts:
    120
    This though
    Code (CSharp):
    1. var path = Application.persistentDataPath;
    2.             var exists = System.IO.Directory.Exists(path);
    3.             Debug.Log(exists);
    results to true.
    Path is : "C:/Data/Users/DefApps/AppData/{72217BDD-B7FC-45F4-8749-FD3C292BE37B}/local"
     
  15. konsnos

    konsnos

    Joined:
    Feb 13, 2012
    Posts:
    120
    Solved it

    Code (CSharp):
    1. XmlSerializer serializer = new XmlSerializer(typeof(NAMEOFCLASSHERE));
    2. Stream writer = new FileStream(Application.persistentDataPath + "/GameData.dat", FileMode.Create);
    3. serializer.Serialize(writer, YOURCLASSHERE);
    4. writer.Close();
    This works :)

    Code (CSharp):
    1. fileExists = System.IO.File.Exists(Application.persistentDataPath + "/GameData.dat");
    This also works.

    And to load it
    Code (CSharp):
    1. XmlSerializer serializer = new XmlSerializer(typeof(NAMEOFCLASSHERE));
    2. TextReader textReader = new StreamReader(Application.persistentDataPath + "/GameData.dat");
    3. YOURCLASSHERE= serializer.Deserialize(textReader) as NAMEOFCLASSHERE;
    4. textReader.Close();
     
    Last edited: Sep 1, 2014
  16. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
  17. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,797
    Use UnityEngine.Windows.File for all file operations where possible.

    Also when working with paths, sometimes prefixing "file:///" helps
     
  18. konsnos

    konsnos

    Joined:
    Feb 13, 2012
    Posts:
    120
    I can't seem to be able to use that for some reason. Does it need any compiler arguments? Also in the documentation it says "This is an alternative for System.IO.File class." so they must be alike.
     
  19. Tomas1856

    Tomas1856

    Unity Technologies

    Joined:
    Sep 21, 2012
    Posts:
    3,658
    Can you show the code? And attach Editor.log please
     
  20. konsnos

    konsnos

    Joined:
    Feb 13, 2012
    Posts:
    120
    What do you mean Tomas? I just have to add the using inside the cs file and I get this error in Unity Editor:
    Code (CSharp):
    1. Assets/Scripts/blabla.cs(9,19): error CS0234: The type or namespace name `Windows' does not exist in the namespace `UnityEngine'. Are you missing an assembly reference?
    2.  
     
  21. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,627
    Have you wrapped it with UNITY_WINRT define?
     
  22. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,797
  23. konsnos

    konsnos

    Joined:
    Feb 13, 2012
    Posts:
    120
    That seems to work. Thanks!
    It should be stated in the documentation however to make it obvious.
     
  24. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    it is
     
  25. konsnos

    konsnos

    Joined:
    Feb 13, 2012
    Posts:
    120
    Where? I'm referring to Documention at Unity's page, here. Did I miss something? ο.Ο
     
  26. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Like here: http://docs.unity3d.com/Manual/windowsstore-missingtypes.html
    and here: http://docs.unity3d.com/Manual/wp8-1-faq.html
    and here: http://docs.unity3d.com/Manual/PlatformDependentCompilation.html

    WinRTLegacy.dll itself isn't super well documented, but you can put the bits together. You just have to understand the platform differences and put the appropriate symbols where needed. It's impossible for Unity to document every specific scenario, so it does take a bit of work to put it all together.

    The IO stuff is in the Scripting API section but I will agree it's not super clear:
    http://docs.unity3d.com/ScriptReference/Windows.File.html
     
    konsnos likes this.
  27. tgouala-wellfiredLtd

    tgouala-wellfiredLtd

    Joined:
    Jun 8, 2013
    Posts:
    99
    On unity 4.6.0 I could save and load a xml file without any uri. I am using FileStream to do so. The Path.Combine function is from a custom namespace, not from System.IO. It first replace / by \ before to combine the two strings to form the path.

    Code (CSharp):
    1. private void saveXmlDocument(XmlDocument xmlDocument)
    2.     {
    3.         string path = Path.Combine(Application.persistentDataPath, "gameData.xml");
    4.  
    5.         System.IO.Stream fileStream = File.Create(path);
    6.         xmlDocument.Save (fileStream);
    7.         fileStream.Dispose();
    8.     }
    9.  
    10.     private XmlDocument loadXmlDocument()
    11.     {
    12.         XmlDocument xmlDocument = new XmlDocument();
    13.         System.IO.Stream fileStream = null;
    14.         #if NETFX_CORE
    15.         fileStream = File.Open(Path.Combine(Application.persistentDataPath, "gameData.xml"));
    16.         #else
    17.         fileStream = File.Open(Path.Combine(Application.persistentDataPath, "gameData.xml"), FileMode.OpenOrCreate);
    18.         #endif
    19.  
    20.         xmlDocument.Load (fileStream);
    21.         fileStream.Dispose ();
    22.         return xmlDocument;
    23.     }