System.Security.SecurityException при создании нового FileStream - PullRequest
1 голос
/ 28 октября 2009

У меня есть обычное .NET-приложение. В этом случае у меня есть часть, которая импортируется MEF. Он хорошо импортирует, но в определенный момент я хочу сохранить список объектов в файл. В этом случае это просто сохранение списка рекордов:

class HighScores
{
    static HighScores()
    {
        CheckTrust();
    }

    [ImportingConstructor]
    public HighScores(
         [Import("/Services/LoggingService", typeof(ILoggingService))] 
         ILoggingService l
        )
    {
        logger = l;

    }

    private ILoggingService logger { get; set; }

    public IEnumerable<HighScore> Scores
    {
        get
        {
            return m_Scores;
        }
    }
    private List<HighScore> m_ScoresUnsorted = new List<HighScore>();
    private readonly ObservableCollection<HighScore> m_Scores = 
        new ObservableCollection<HighScore>();

    public void LogNewHighScore(string name, int score, int level)
    {
        m_ScoresUnsorted.Add(new HighScore(name, score, level));
        CreateObservable();

        if (IsFullTrust)
        {
            Stream stream = null;
            try
            {
                // this line causes exception
                stream = new FileStream("HighScores.dat", 
                         System.IO.FileMode.Create, FileAccess.Write);  
                BinaryFormatter b = new BinaryFormatter();
                b.Serialize(stream, m_ScoresUnsorted);
            }
            catch (Exception e)
            {
                logger.Error("Error writing high scores:", e);
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }
            }
        }
    }

    private void CreateObservable()
    {
        m_ScoresUnsorted.Sort();
        m_Scores.Clear();
        for(int i = m_ScoresUnsorted.Count-1; i >= 0; i--)
        {
            m_Scores.Add(m_ScoresUnsorted[i]);
        }
    }

    static private void CheckTrust()
    {
        try
        {
            FileIOPermission permission =
                new FileIOPermission(PermissionState.Unrestricted);
            s_FullTrust = SecurityManager.IsGranted(permission);
        }
        catch (Exception)
        {
            // ignore
        }
    }

    static private bool s_FullTrust;
    static public bool IsFullTrust
    {
        get
        {
            return s_FullTrust;
        }
    }

}

Я получаю исключение System.Security.SecurityException в новой строке FileStream. Странная вещь в том, что если я просто заменю это на TextWriter, это сработает. Я не понимаю, что я делаю не так.

РЕДАКТИРОВАТЬ : Подробнее ... когда я помещаю этот код в конструктор, он выполняется. Если вы вернетесь к стеку вызовов обратно (при разрыве в приведенном выше примере), он будет выполняться в потоке графического интерфейса. В частности, диспетчер WPF выполняет операцию get для свойства на основе того факта, что произошло событие PropertyChanged. Так что, может быть, это связано с тем, что в WPF переподготовке GUI не разрешено выполнять файловый ввод-вывод? Это имеет смысл ... вы бы не хотели блокировать графический интерфейс для чего-то вроде записи в файл ...

1 Ответ

0 голосов
/ 28 октября 2009

Я смог заставить его работать, взяв функциональность потока и поместив его в «небезопасный» поток ThreadPool, например:

        ThreadPool.UnsafeQueueUserWorkItem(ignoredState =>
        {
            Stream stream = null;
            try
            {
                stream = new FileStream("HighScores.dat", System.IO.FileMode.Create, FileAccess.Write);
                BinaryFormatter b = new BinaryFormatter();
                b.Serialize(stream, "Test String");
            }
            catch (Exception e)
            {
                logger.Error("Error writing high scores:", e);
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }
            }
        }, null);

Конечно, у меня есть куча действительно плохих проблем с синхронизацией, которые мне нужно устранить, но это работает. Я думаю, что я сделаю, это заблокировать поток и сделать копию списка, а затем записать копию на диск. Мне также придется избавиться от логгера, поскольку вы не можете безопасно получить к нему доступ через несколько потоков.

Очень жаль, что я не знаю, почему я должен был сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...