65.9K
CodeProject 正在变化。 阅读更多。
Home

Silverlight 4 中的提升信任

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.60/5 (5投票s)

2010年11月8日

CPOL

4分钟阅读

viewsIcon

41831

downloadIcon

357

增强信任是 SL4 中最重要的功能之一,我的帖子将集中讨论增强信任,包括访问文件系统/隔离存储/注册表、调用 COM 对象和其他可执行文件。

背景

在 Silverlight 4 中,具有增强权限的浏览器外支持得到了显著改进,现在的 OOB 应用程序在访问系统资源方面拥有更多特权,例如能够访问隔离存储操作 COM 对象、访问本地注册表项,甚至调用Microsoft Speech API 进行语音输出。

本质上,为了实现这一点,主要改进在于

  1. Microsoft 为 Silverlight 4 OOB 应用程序提供了请求增强信任的能力。

    来自受信任的应用程序
    您可以将浏览器外应用程序配置为需要增强信任。安装后,这些受信任的应用程序可以绕过安全沙箱的一些限制。例如,受信任的应用程序可以访问用户文件并使用全屏模式,而无需键盘限制。

  2. 来自 .NET 4.0 的一个新概念叫做“后期绑定”,C# 关键字:dynamic 可用于在构建时声明一个不确定类型,在运行时,Microsoft.CSharp.RuntimeBinder 将进行动态构建。

引言

我的帖子将专注于讨论增强信任,如果您在创建 OOB 和请求增强权限方面有任何问题,请阅读下面的文章。

我开发了一个简单的 Silverlight OOB 演示,它将访问本地系统资源,包括

  • 让用户选择一些文件,然后将它们复制到隔离存储。
  • 访问隔离存储以枚举所有文件。
  • 通过调用“Scripting.FileSystemObject”在 C 盘下创建一个 txt 文件,并读取其内容。
  • 使用“WScript.Shell”在 HKEY_CURRENT_USER 下写入注册表项,在 HKEY_LOCAL_MACHINE 下读取注册表项。
    注意:Silverlight OOB 应用程序将没有写入 HKLM 的权限,它只有读取权限。
  • 使用“WScript.Shell”运行位于系统上的其他可执行文件。
  • 将用户在 textbox 中输入的句子进行语音输出。

屏幕截图

安装到系统后,其 UI 如下所示(我知道它真的很糟糕…抱歉笑脸)

mainpage.png

实现

增强权限浏览器外场景下启用,所以我们在 Silverlight 应用程序中需要检查当前是否正在浏览器外运行。

if(Application.Current.IsRunningOutOfBrowser)
    // Access local file, registry, COM, etc.

此外,要调用 COM 对象,我们需要检查 AutomationFactory 是否可用。

if (AutomationFactory.IsAvailable)

好的,现在我们来看看实现增强权限的代码。

  1. 点击按钮——“复制文件到隔离存储访问”,会弹出一个文件打开对话框,截图如下

    openfile.png

    用于打开文件对话框的代码

    OpenFileDialog dlg = new OpenFileDialog 
    	{ Filter = "All files (*.*)|*.*", Multiselect = true };
    var dlgResult = dlg.ShowDialog();

    读取选定的文件并将其复制到隔离存储。

    IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication();
    foreach (FileInfo file in dlg.Files)
    {
        using (Stream fileStream = file.OpenRead())
        {
            using (IsolatedStorageFileStream isoStream =
                new IsolatedStorageFileStream(file.Name, FileMode.Create, iso))
            {
                // Read and write the data block by block until finish
                while (true)
                {
                    byte[] buffer = new byte[100001];
                    int count = fileStream.Read(buffer, 0, buffer.Length);
                    if (count > 0)
                    {
                        isoStream.Write(buffer, 0, count);
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
    }

    用于“从隔离存储加载文件”的代码

    var isoFiles = 
      from files in IsolatedStorageFile.GetUserStoreForApplication().GetFileNames()
                      select files;
  2. 在“C:\WayneTestSL4Fso\WayneTest.txt”下创建一个文本文件,请注意:如果您使用 System.IO.File 执行此类操作,将不会成功,我猜是因为增强信任尚未直接实现在许多托管程序集中。在这里我的演示中,我使用了 Scripting.FileSystemObject
    private String folderPath = "C:\\WayneTestSL4FSO";
    private String filePath = "C:\\WayneTestSL4Fso\\WayneTest.txt";
     
    using (dynamic fso = AutomationFactory.CreateObject("Scripting.FileSystemObject"))
    {
        if (!fso.FolderExists(folderPath)) fso.CreateFolder(folderPath);
        dynamic txtFile = fso.CreateTextFile(filePath);
        txtFile.WriteLine("Some text...");
        txtFile.close();
    }

    附注:当我第一次在 using 语句中使用“dynamic”关键字时,我有点惊讶,我可以简单地尝试释放一个动态对象,而不必检查它是否实现了 IDisposible,因此我尝试运行 using (dynamic x = 8 ),然后我得到了这个笑脸

    incorrectusing.png

    好的,让我们回到读取我刚刚创建的文本文件的代码实现。

    var fileContent = String.Empty;
    
    using (dynamic fso = AutomationFactory.CreateObject("Scripting.FileSystemObject"))
    {
        dynamic file = fso.OpenTextFile(filePath);
        fileContent = file.ReadAll();
    
        file.Close();
    }
  3. 注册表写入/读取,请注意:我们只能写入 HKCU 的注册表,而不能写入 HKLM,我们对 HKLM 条目有读取权限。
    using (dynamic wScript = AutomationFactory.CreateObject("WScript.Shell"))
    {
        // Only has write permission to HKCU
        wScript.RegWrite(@"HKCU\Software\WayneTestRegValue",
                "SomeStrValue", "REG_SZ");
    }
    using (dynamic wScript = AutomationFactory.CreateObject("WScript.Shell"))
    {
        string dotNetRoot =
            wScript.RegRead(@"HKLM\SOFTWARE\Microsoft\.NETFramework\InstallRoot");
    }
  4. 运行另一个本地应用程序
    using (dynamic wScript = AutomationFactory.CreateObject("WScript.Shell"))
    {
        //Refer WScript.Run at: 
        //http://msdn.microsoft.com/en-us/library/d5fk67ky(v=VS.85).aspx
        wScript.Run("iexplore http://wayneye.com", 1, true);
    }

    注意 1WScript.Shell.Run 方法不仅可以接受可执行文件,还可以接受 *.bat、Windows Script Host 文件(*.vbs*.js)或 PowerShell 脚本文件等。

    注意 2:通过运行另一个 EXE 或脚本文件来获得更多权限的意图肯定不会成功,例如,如果我尝试从我的 OOB 应用程序调用下面的 AccessKHLM.js,我将收到一个 80070005 错误代码,表示访问被拒绝。

    var WshShell = WScript.CreateObject("WScript.Shell");
    
    WshShell.RegWrite("HKLM\\Software\\WayneTestValue\\", 1, "REG_BINARY");
    WshShell.Close();

    80070005.png

    如果您双击 Demo.js,您会成功,因为您是 Windows 管理员,而“Silverlight 应用程序在部分信任下运行,这意味着它们在安全沙箱中运行”。有关更多信息,请参考受信任的应用程序

  5. 语音输出一个句子
    using (dynamic speechApi = AutomationFactory.CreateObject("Sapi.SpVoice"))
    {
        speechApi.Speak(this.txtPhonateSource.Text);
    }
  6. 实现右上角“X”关闭按钮的代码。
    using (var wScript = AutomationFactory.CreateObject("WScript.Shell"))
    {
        wScript.Run(@"cmd /k taskkill /IM sllauncher.exe & exit", 0);
    }

    这有点棘手,我在 Google 上搜索了一段时间,发现了一篇很棒的文章 以编程方式退出 Silverlight 4 浏览器外应用程序。本质上,代码调用 WScript.Shell 并运行 cmd 并终止 sllauncher.exe,从而使我们的 OOB 进程被杀死吐舌头的笑脸

结论

通过为 Silverlight OOB 应用程序启用增强信任,我们可以做比以往更多的事情,它为使用 Silverlight 技术开发企业业务应用程序提供了更多信心。昨天,我看到 Scott Guthrie 发布了一篇关于 Silverlight 的博客,他提到 Microsoft 将继续努力开发 Silverlight 的企业业务应用程序(包括在线和 OOB)。

参考文献

© . All rights reserved.