Справка по виртуализации файловой системы Windows Visa / 7 UAC - PullRequest
1 голос
/ 16 мая 2011

Я работаю над программой, которая предназначена для работы в сочетании со старым приложением C ++. Игра под названием Age of Wonders. При работе в Windows Vista или Windows 7 (с включенным UAC) файлы сохранения игры записываются в путь виртуализации, а не в реальный путь.

Так, например;

Оригинал: C: \ Program Files (x86) \ Age of Wonders \ Save

Виртуализованная: C: \ Users \ Имя пользователя \ AppData \ Local \ VirtualStore \ Program Files (x86) \ Age of Wonders \ Save

В моем приложении .Net я загружаю файлы с сервера электронной почты и помещаю их в папку «Сохранить», если при попытке записи по первоначальному пути я получаю исключение неавторизованного доступа, когда включен контроль учетных записей. Windows не конвертирует его автоматически в виртуализованный путь для меня. Я работал над этим, заставляя своих пользователей запускать приложение от имени администратора. Однако я хотел бы сделать более элегантное решение.

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

Я потратил время на поиск в интернете и нашел других людей, которые говорят об этом, но никто не оказывает никакой помощи, которая на самом деле полезна. Вот ссылки, которые я посмотрел;

Должен ли я использовать решение VirtualStore в Vista?

Создание процесса с включенной виртуализацией ФС

http://us.generation -nt.com / ответ / с использованием-settokeninformation-контроль-файлов системы виртуализации перспектива-помощь-37057472.html

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

Итак, ниже у меня есть код для простого приложения Windows Forms. Он имеет одну кнопку и один флажок, флажок предназначен для переключения режима виртуализации, а кнопка записывает небольшой текстовый файл в папку Program Files. Я хочу использовать это для проверки поведения виртуализации. Поэтому я ожидаю, что File.txt будет записан в виртуализированный путь, когда установлен флажок и т. Д.

Если кто-нибудь может помочь мне заполнить пустую функцию, я был бы очень признателен. Заранее спасибо.

using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            string testText = "Dave was here";
            File.WriteAllText("C:\\Program Files\\DaveTest\\File.txt", testText);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }

    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
        SetVirtualization(checkBox1.Checked);
    }

    private void SetVirtualization(bool enabled)
    {
        //What code do I need here, please provide examples than can be used
    }
}

Ответы [ 3 ]

2 голосов
/ 16 мая 2011

Если вы хотите виртуализации, вам нужен 32-битный процесс без манифеста. У вас уже есть 32-битный процесс, поэтому вам нужно избавиться от манифеста.

Я ожидаю, что это будет неудобно для вашего прекрасного блестящего приложения WinForms, поскольку вы отказались бы от современного тематического оформления. Простой обходной путь - это кодирование в отдельном процессе для обработки только той части приложения, которая нуждается в виртуализации. Дополнительным преимуществом этого является то, что остальная часть вашего процесса не должна быть виртуализирована.

1 голос
/ 16 мая 2011

Похоже, что ваше приложение .Net работает как 64-битное приложение. Виртуализация (файл / реестр) отключена для таких приложений.

Можете ли вы скомпилировать приложение под x86? Если так, то это должно сработать.

0 голосов
/ 17 мая 2011

К вашему сведению, я придумал это - который делает то, что хотел;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace VirtualizationTest
{
    public class FileVirtualizationHelper
    {
        #region Win32 API routines

        enum TOKEN_INFORMATION_CLASS
        {
            TokenUser = 1,
            TokenGroups,
            TokenPrivileges,
            TokenOwner,
            TokenPrimaryGroup,
            TokenDefaultDacl,
            TokenSource,
            TokenType,
            TokenImpersonationLevel,
            TokenStatistics,
            TokenRestrictedSids,
            TokenSessionId,
            TokenGroupsAndPrivileges,
            TokenSessionReference,
            TokenSandBoxInert,
            TokenAuditPolicy,
            TokenOrigin,
            MaxTokenInfoClass  // MaxTokenInfoClass should always be the last enum
        }

        const UInt32 MAXIMUM_ALLOWED = 0x2000000;

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern Boolean CloseHandle(IntPtr hSnapshot);

        [DllImport("advapi32", SetLastError = true), System.Security.SuppressUnmanagedCodeSecurityAttribute]
        static extern Boolean OpenProcessToken(IntPtr ProcessHandle, // handle to process
                                            UInt32 DesiredAccess, // desired access to process
                                            ref IntPtr TokenHandle); // handle to open access token

        [DllImport("advapi32.dll", SetLastError = true)]
        static extern Boolean SetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, ref UInt32 TokenInformation, UInt32 TokenInformationLength);

        #endregion

        #region Public Methods

        public static bool Enable()
        {
            return SetVirtualization(true);
        }

        public static bool Disable()
        {
            return SetVirtualization(false);
        }

        #endregion

        #region Private Methods

        private static bool SetVirtualization(bool DoEnable)
        {
            IntPtr Token = (IntPtr)0;
            UInt32 EnableValue = DoEnable ? (UInt32)1 : (UInt32)0;
            UInt32 EnableValueSize = sizeof(UInt32);

            if (!OpenProcessToken(Process.GetCurrentProcess().Handle, MAXIMUM_ALLOWED, ref Token))
            {
                return false;
            }
            if (!SetTokenInformation(Token, (TOKEN_INFORMATION_CLASS)24, ref EnableValue, EnableValueSize))
            {
                CloseHandle(Token);
                return false;
            }
            CloseHandle(Token);
            return true;
        }

        #endregion
    }
}
...