帮助 Windows Visa / 7 UAC 文件系统虚拟化



我正在开发一个程序,该程序旨在与旧的C++应用程序结合使用。 一款名为《奇迹时代》的游戏。 在 Windows Vista 或 Windows 7(启用 UAC)下运行时,游戏保存文件将写入虚拟化路径而不是实际路径。

例如;

源语言:C:\程序文件 (x86)\奇迹时代\保存

虚拟化:C:\Users\UserName\AppData\Local\VirtualStore\Program Files (x86)\Age of Wonders\Save

在我的 .Net 应用程序中,我从电子邮件服务器下载文件并将它们放在保存文件夹中,如果我尝试写入原始路径,则在启用 UAC 时会收到未经授权的访问异常。 Windows不会自动将其转换为我的虚拟化路径。 我一直在通过让我的用户以管理员身份运行应用程序来解决此问题。 但是,我想做一个更优雅的解决方案。

我可以编写一些代码来处理异常并在代码中写入虚拟化路径,但我认为更好的解决方案是以某种方式将我的程序切换到一种模式,以便由 Windows 本身而不是在我的代码中完成。 我觉得这将是未来版本的Windows更好的长期解决方案。

花时间在互联网上搜索,我找到了其他人在谈论这个问题,但没有人提供任何实际可用的帮助。 这是我看过的链接;

我应该在Vista上使用VirtualStore解决方案吗?

创建启用了 FS 虚拟化的进程

http://us.generation-nt.com/answer/using-settokeninformation-control-file-system-virtualization-vista-help-37057472.html

我需要解决不涉及用户必须修改其系统设置或创建任何帐户以在等下运行该过程的解决方案。

因此,下面我有一个简单的 Windows 窗体应用程序的代码。 它有一个按钮和一个复选框,该复选框用于切换虚拟化模式,该按钮将一个小文本文件写入程序文件文件夹。 我希望能够使用它来测试虚拟化行为。 所以我希望在选中复选框等时将文件.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
    }
}

如果你想要虚拟化,你需要一个没有清单的 32 位进程。 您似乎已经有一个 32 位进程,因此您需要摆脱清单。

我希望这对您漂亮的闪亮WinForms应用程序来说会很不方便,因为您将放弃现代主题外观。 一个简单的解决方法是在单独的进程中对此进行编码,以便仅处理需要虚拟化的应用程序部分。 这样做的另一个好处是,流程的其余部分不必虚拟化。

看起来你的 .Net 应用程序作为 64 位应用运行。 对此类应用程序禁用虚拟化(文件/注册表)。

您可以将应用程序编译为 x86 吗?如果是这样,那应该可以解决问题。

供参考,我已经想出了这个 - 它确实做了我想做的;

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
    }
}

相关内容

最新更新