【问题标题】:Dynamic code execution on WinRT in Windows 8 (either C++ or .NET/C#)?Windows 8 中 WinRT 上的动态代码执行(C++ 或 .NET/C#)?
【发布时间】:2011-09-19 15:16:59
【问题描述】:

Windows 8 Metro 下的 WinRT 是否允许动态加载和执行代码?例如,是否可以将 dll 下载到内存或隔离存储并从中运行代码? JIT 将脚本语言编译为本地汇编语言(例如第三方浏览器)的代码是否能够在 WinRT 中执行相同的操作,还是作为“不安全”操作被禁止?

对于在 WinRT 中运行的“托管”代码,此问题的答案是否不同?例如,在托管代码中,您是否可以从 Internet 下载程序集并使其在 MEF 中可发现,或者能够在运行时加载它?你能以某种形式使用 Reflection.Emit 吗?在 C++ 中,您可以运行应用程序在运行时生成的汇编代码,还是在运行时动态加载 DLL(可能是某种形式的 WinRT DLL)?

【问题讨论】:

  • 对于托管,至少,我看不到System.Reflection.Emit,但Expression<T>.Compile 在那里并且似乎正在工作,因此至少可以使用某种形式的运行时代码生成。
  • 要详细了解您可以在 Windows 应用商店应用中使用 C++ 做什么,请查看此Roadmap for Windows Store apps using C++

标签: c# c++ dll windows-8 windows-runtime


【解决方案1】:

通常,您无法在 Metro 风格应用中加载和执行新代码。您可以访问的是您随应用程序提供的内容。

LoadLibrary 和 GetProcAddress 缺失,因此 C++ 无法动态加载代码。
同样,C# 不能,因为没有 Assembly.Load。
JavaScript 可以,但只能在 Web 容器中,而不是在代码的完全信任部分。

所有这一切的原因是,如果应用可以加载和运行任意代码,那么商店的安全/恶意软件保护将毫无意义。

【讨论】:

  • 另外,缺少了VirtualProtect,所以你不能写一些即时编译代码的东西。
【解决方案2】:

实际上,Metro 风格的应用程序可以动态加载和执行代码。 有一些限制; Metro 和桌面应用在关键方面的工作方式略有不同。

机制会有所不同,具体取决于调用者(LoadPackagedLibrary() Assembly.Load() 等)。 Metro 和桌面之间的一个关键区别 - Metro 应用程序只能动态加载应用程序包图中的内容(您的包和 s)和系统代码(否则可以静态加载)。

查看我的帖子了解更多详情 http://social.msdn.microsoft.com/Forums/en-US/wingameswithdirectx/thread/d1ebe727-2d10-430e-96af-46964dda8225

【讨论】:

    【解决方案3】:

    Windows 8 Metro 下的 WinRT 是否允许您动态加载和 执行代码?

    没有。

    例如,是否可以将 dll 下载到内存或隔离存储并从中运行代码?

    没有。

    JIT 将脚本语言编译为本地汇编语言(例如第三方浏览器)的代码是否能够在 WinRT 中执行相同的操作,或者是否作为“不安全”操作被禁止?

    这是被禁止的。

    对于在 WinRT 中运行的“托管”代码,此问题的答案是否不同?

    没有。

    例如,在托管代码中,您能否从 Internet 下载程序集并使其在 MEF 中可发现,或者能够在运行时加载它?

    没有。

    你能以某种形式使用 Reflection.Emit 吗?

    没有。

    在 C++ 中,您能否运行应用程序在运行时生成的汇编代码,或者在运行时动态加载 DLL(可能是某种形式的 WinRT DLL)?

    没有。

    您描述的所有内容都可以绕过 WinRT 的安全保证。

    【讨论】:

    • 它还排除了第三方浏览器、所有脚本引擎庄园(至少是那些使用 JIT 更快地运行脚本的引擎)、任何按时间关键计划发布更新的软件(税务软件等)。 ..)。如果没有 JIT 支持,用 Ruby/Python/etc.. 编写的软件无法运行得尽可能快。大多数主要 PC 游戏在内部使用某种形式的脚本引擎,无论是用于 UI(魔兽世界)还是其他。生成的代码可以在运行时进行验证,以获得较小的性能影响。我看不出这不能成为具有相关应用功能的代理 API 的原因
    • 你不想投票给我,因为你对微软很生气?
    • 我没有对任何人“生气”。这只是一个技术问答。我无意冒犯。
    • 如何绕过安全保证?这个限制并没有限制你可以做什么:你总是可以用解释器动态运行代码。唯一的区别是速度要慢得多。
    【解决方案4】:

    你的问题有点不清楚......所以一些一般性的指针:

    • .NET 应用程序使用 WinRT(但不是新的 UI 模型!)
      在这种情况下,您今天的一切皆有可能(可能不是 OLEDB),而是反射等。

    • 为 Metro UI 构建的 .NET 应用程序
      AFAIK 这是不可能的(参见http://blogs.microsoft.co.il/blogs/sasha/archive/2011/09/17/metro-net-framework-profile-windows-tailored.aspxhttp://tirania.org/blog/),至少只要你想通过 Windows 商店销售......在这个范围之外(Windows 商店),可能会有一些技巧来规避这个限制,正如已经证明的那样一些......但我不会指望那个......也许你可以使用一些 JavaScript(eval 等)来做一些动态的事情,但我目前不确定

    【讨论】:

    • 问题很清楚,是关于 WinRT 的。您正在回答另一个未提出的问题。海报中没有提到运行 WinRT 以外的其他东西的 .NET 应用程序。
    【解决方案5】:

    Windows 10 为此添加了codeGeneration 功能。这允许函数 VirtualAllocFromApp 和 VirtualProtectFromApp 在 WinRT 应用程序中使用,因为 VirtualAlloc 和 VirtualProtect 将在 Win32 中使用。

    【讨论】:

      【解决方案6】:

      为了让它更有趣,IE 10 实际上确实在其 js 代码上执行 JIT,因此 API 显然允许它。

      【讨论】:

      • 是的。我相信从技术上讲,您可以直接从 C++ 使用任何 Win32 api,但如果您的应用程序使用任何非 winrt 或任何不在批准列表中的 win32 api,您的应用程序将无法通过认证。因此,IE 正在使用第三方开发人员无法使用的 API。
      • 或者更确切地说,因为 Win8 上的 IE10 是一个混合 Metro/Win32 应用程序,它可以做标准 Metro-only 应用程序不能做的事情。
      【解决方案7】:

      您可以创建一个 Windows 运行时组件(通用 Windows)C++, 您可以从 c# 代码访问组件,在组件内部您可以调用 LoadPackagedLibrary,它的限制是它只能加载与您的应用程序打包的 DLL。否则与 LoadLibrary 相同。

      您无法下载和动态加载,因为 ApplicationData 和 InstalledLocation 是不同的位置。 (LoadPackagedLibrary 不允许您指定路径)。而且您只能写入 ApplicationData...

      【讨论】:

        【解决方案8】:

        从 AppX 包目录(来自MSDN Forums)加载动态程序集的示例:

        private async Task<IEnumerable<Assembly>> GetAssemblyListAsync()
        {
            var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
        
            List<Assembly> assemblies = new List<Assembly>();
            foreach (StorageFile file in await folder.GetFilesAsync())
            {
                if (file.FileType == ".dll" || file.FileType == ".exe")
                {
                    var name = file.Name.Substring(0, file.Name.Length - file.FileType.Length);
                    Assembly assembly = Assembly.Load(new AssemblyName() { Name = name });
                    assemblies.Add(assembly);
                }
            }
        
            return assemblies;
        }
        

        程序集必须添加到应用程序包中。您不能从外部来源下载它们。

        但是,这种方法在 .NET Native 中不起作用,因为所有内容都合并到一个 DLL 中。您应该在某处保存程序集名称列表(在 Assets 内的一个简单文件中)并为每个项目调用 Assembly.Load

        调试模式下的动态程序集列表示例和发布模式下的预定义程序集名称数组示例(.NET Native 工具链)。

        #if DEBUG
        using Windows.Storage;
        #endif
        
            // ...
        
            IEnumerable<string> assemblyNames;
        
        #if DEBUG
            assemblyNames = Windows.ApplicationModel.Package.Current.InstalledLocation.GetFilesAsync().AsTask().Result
                .Where(file => file.FileType == ".dll" && file.Name.Contains("Business"))
                .Select(file => file.Name.Substring(0, file.Name.Length - file.FileType.Length));
        #else
            assemblyNames = new[] { "California.Business", "Colorado.Business" };
        #endif
        
            foreach (var name in assemblyNames)
            {
                var assembly = Assembly.Load(new AssemblyName() { Name = name });
        
                // Load required types.
                // ...
        
            }
        

        【讨论】:

          【解决方案9】:

          这是可能的,请检查 Windows 8 中的 Google Chrome 应用程序,它们提供了一种在正常模式和 Windows 8 模式之间切换的方法,以保留查看的页面。

          【讨论】:

          • 他们只在浏览器上例外,并且只在 x86 版本的 windows 8 上,而不是 Windows RT。此外,Chrome/FireFox 不是 Windows 商店应用程序。
          猜你喜欢
          • 1970-01-01
          • 2012-12-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-02-09
          • 2014-08-12
          • 1970-01-01
          相关资源
          最近更新 更多