1

I'm working on a .NET MAUI project in the context of MVVM architecture and I created two .txt files (15.txt and 19.txt) inside directory Resources\Raw. I set the files' Build action to MauiAsset. Each of these two files contain topology for a matrix of color-coded fields.

What were I expecting: to read the text file's content without obtaining System.IO.FileNotFoundException' in System.Private.CoreLib.dll and to be able to use (invoke) the reader method more than once in a successfull manner.

I experience the following behaviour: in case the mentioned exception is not checked under Debug -> Windows -> Exception Setings -> Common Language Runtime Exceptions then the textfile's content is successfully obtained via the reader method as it's evident by looking at the graphical changes on one of my ContentPages (a matrix of fields appears with plenty of differently colored fields), however at the moment of its invokation an System.IO.FileNotFoundException' in System.Private.CoreLib.dllemerges as part of the logs (alerting message is absent).

However, if the aforementioned exception is checked under Debug -> Windows -> Exception Setings -> Common Language Runtime Exceptions then my application does not even start succesfully.

Inside class GameViewModel:

    /// <summary>
    /// event handler method for choosing 15 as tablesize and reading appropriate table
    /// </summary>
    private async void GameViewModel_ButtonSmallTableClick(object? sender, System.EventArgs e)
    {
        await Navigation.PushAsync(new GamePage
        {
            BindingContext = _gameViewModel
        }); 

        Stream fileStream = await FileSystem.Current.OpenAppPackageFileAsync("15.txt");

        await _gameModel.LoadGameAsync(fileStream);

        _gameViewModel.GameTableNumRows = 15;

        _gameViewModel.GameTableNumCols = 15;

        _gameViewModel.GenerateFields();

    }


    /// <summary>
    /// event handler method for choosing 19 as tablesize and reading appropriate table
    /// </summary>
    private async void GameViewModel_ButtonLargeTableClick(object? sender, System.EventArgs e)
    {
        await Navigation.PushAsync(new GamePage
        {
            BindingContext = _gameViewModel
        }); 

        Stream fileStream = await FileSystem.Current.OpenAppPackageFileAsync("19.txt");

        await _gameModel.LoadGameAsync(fileStream);

        _gameViewModel.GameTableNumRows = 19;

        _gameViewModel.GameTableNumCols = 19;

        _gameViewModel.GenerateFields();

    }

Here's the method definition inside class GameModel:

        /// <summary>
        /// Loading colored matrix.
        /// </summary>
        /// <param name="fileStream">Type of Stream.</param>
        public async Task LoadGameAsync(System.IO.Stream fileStream)
        {
            if (_dataAccess == null)

                throw new InvalidOperationException("No data access is provided.");

            var loadResult = await _dataAccess.LoadAsync(fileStream);

            _gameTable = loadResult.Item1;

            _player = loadResult.Item2;

            _guards = loadResult.Item3;

            IsWon = false;


        }

Finally, here's the persistence-related method:

        /// <summary>
        /// Loading file
        /// </summary>
        /// <param name="path">Filepath.</param>
        /// <returns>Gametable, Player, list of Guards.</returns>
        public async Task<(UInt16[,], Player, List<Guard>)> LoadAsync(String path)
        {
            

            try
            {

                using (StreamReader reader = new StreamReader(path)) 
                {
                    String[] gameFieldTypes;

                    String line = await reader.ReadLineAsync() ?? String.Empty;

                    Int32 tableSize = Int32.Parse(line);

                    UInt16[,] table = new UInt16[tableSize, tableSize]; 

                    Player player = new Player();

                    List<Guard> guards = new List<Guard>();

                    for (Int32 i = 0; i < tableSize; i++)
                    {
                        line = await reader.ReadLineAsync() ?? String.Empty;

                        gameFieldTypes = line.Split(' ');

                        for (Int32 j = 0; j < tableSize; j++)
                        {

                            if (gameFieldTypes[j] == "Empty")
                            {
                                table[j, i] = 0;


                            }

                            if (gameFieldTypes[j] == "Wall")
                            {
                                table[j, i] = 1;


                            }

                            if (gameFieldTypes[j] == "Guard")
                            {
                                table[j, i] = 2;

                                Guard guard = new Guard();

                                guard.X = j;

                                guard.Y = i;

                                guards.Add(guard);

                            }

                            if (gameFieldTypes[j] == "Player")
                            {
                                table[j, i] = 3;

                                player.X = j;

                                player.Y = i;

                            }

                            if (gameFieldTypes[j] == "Exit")
                            {
                                table[j, i] = 4;

                            }

                        }
                    }



                    return (table, player, guards);
                }
            }
            catch
            {
                throw new GameDataException();
            }
        }

EDIT:

Here's the emerging exception: System.IO.FileNotFoundException' in System.Private.CoreLib.dll

Could not find file 'C:\WINDOWS\system32\SuspendedGame'.'

Line throwing exception inside method LoadAsync():

using (StreamReader reader = new StreamReader(path))

And here's the class within which the phrase "SuspendedGame" appears.

public class StoredGameBrowserModel
    {
        private IStore _store; // persistence

        /// <summary>
        /// Event of container being changed.
        /// </summary>
        public event EventHandler? StoreChanged;

        public StoredGameBrowserModel(IStore store)
        {
            _store = store;

            StoredGames = new List<StoredGameModel>();
        }

        /// <summary>
        /// Query of the list of stored colored-field matrices.
        /// </summary>
        public List<StoredGameModel> StoredGames { get; private set; }

        /// <summary>
        /// Updating stored resource files.
        /// </summary>
        public async Task UpdateAsync()
        {
            if (_store == null)
                return;

            StoredGames.Clear();

            // loading saved files
            foreach (String name in await _store.GetFilesAsync())
            {
                
                if (name == "SuspendedGame") // we do not want to load this particular saved file
                    continue;
                
                StoredGames.Add(new StoredGameModel
                {
                    Name = name,
                    Modified = await _store.GetModifiedTimeAsync(name)
                });
            }

            // arranging elements according to their date
            StoredGames = StoredGames.OrderByDescending(item => item.Modified).ToList();
            
            OnSavesChanged();
        }

        private void OnSavesChanged()
        {
            StoreChanged?.Invoke(this, EventArgs.Empty);
        }
    }
curiousMind_85
  • 167
  • 1
  • 8
  • As it works once, try disposing your `Stream` after use. I know `StreamReader` will dispose it, but it's [good practice anyway](https://stackoverflow.com/a/1065196/2385218), and with MAUI there's a lot of additional complication going on to translate down through the layers to the devices. – sellotape Dec 21 '22 at 10:06
  • which line causes the exception, and what does the stack trace show? – Jason Dec 21 '22 at 14:38
  • 1
    The original exception turned out to be System.IO.FileNotFoundException' in System.Private.CoreLib.dll despite being able to load the file content. Also, the second invokation produced a delayed visual result in terms of graphical elements. So, I believed it to be non-functional, but it's a matter of graphical activity, I guess. – curiousMind_85 Dec 21 '22 at 19:52
  • 1
    Did you try to debug to find which line caused this error? – Liyun Zhang - MSFT Dec 22 '22 at 09:40
  • I've just found it! Please help me! System.IO.FileNotFoundException: 'Could not find file 'C:\WINDOWS\system32\SuspendedGame'.' – curiousMind_85 Dec 22 '22 at 17:32
  • I've also included the source class in my post above. – curiousMind_85 Dec 22 '22 at 17:45
  • So the error message shows cause clearly. The path(C:\WINDOWS\system32\SuspendedGame) is not correct. Did you check if there is a such file or not? – Liyun Zhang - MSFT Dec 23 '22 at 09:29

1 Answers1

0

Solution:

inserting the following code at the beginning of the method body of LoadAsync():

if (!String.IsNullOrEmpty(_basePath))
    path = Path.Combine(_basePath, path);

Reasoning:

the prefix library path was missing from the content of the method parameter.

curiousMind_85
  • 167
  • 1
  • 8