從Silverlight 3開始,Silverlight Team即提供了Out Of Browser,簡稱為OOB的模式,在這個模式中,Silverlight應用程式可以完全脫離瀏覽器來執行,
此舉揭開了Client端應用程式的另一新頁。
在Silverlight 4中,Silverlight Team更加入了許多新功能,除了顯而易見的列印、音訊及視訊的支援外,在OOB模式中更加入了Elevated Trust支援,
在這個模式下的OOB,不僅可以脫離瀏覽器執行,更可在有限程度下取用原生系統資源
Inside Silverlight 4 OOB Mode
文/黃忠成
Silverlight 4 OOB Mode
從Silverlight 3開始,Silverlight Team即提供了Out Of Browser,簡稱為OOB的模式,在這個模式中,Silverlight應用程式可以完全脫離瀏覽器來執行,
此舉揭開了Client端應用程式的另一新頁。
在Silverlight 4中,Silverlight Team更加入了許多新功能,除了顯而易見的列印、音訊及視訊的支援外,在OOB模式中更加入了Elevated Trust支援,
在這個模式下的OOB,不僅可以脫離瀏覽器執行,更可在有限程度下取用原生系統資源,這使得Silverlight OOB應用程式的應用範圍瞬時擴展。
在OOB加上Elevated Trust模式下,Silverlight應用程式可以直接連接網路,不受Cross-Domain的限制,也可以直接存取客戶端的個人資料夾,例如
My Documents、My Pictures等等,甚至還能使用COM。
由於Silverlight只需要一個小型的CLR,所以相當適合用於Thin-Client的架構下,在持續進化的情況下,無形中Silverlight已經悄悄的從網頁應用程式
橫跨到Native Client了,這符合了Microsoft所提出的RIA(Rich Interactive Application),而不僅僅是RIA(Rich Internet Application)。
Enable OOB Mode
開啟OOB Mode的方法很簡單,只要於Silverlight Project上按右鍵打開應用程式屬性窗,即可見到圖1的設定。
圖1
將【Enable running application out of the browser】打勾,即代表此應用程式可以被使用者安裝於電腦中,當使用者瀏覽此網站時,便可按右鍵來安裝此應用程式。
圖2
圖3
點選確定後,此應用程式會脫離瀏覽器執行,也會出現一個捷徑於開始功能表中。
圖4
圖5
日後使用者只需點選此捷徑,即可開啟此應用程式。
Install OOB Application via Programming
當然,應用程式自己也能提供一個安裝機制供使用者點選,請於Silverlight Page中放入一個Button,然後鍵入以下程式碼。
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace SilverlightApplication10 { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { App.Current.Install(); } } } |
接著啟用OOB模式,這樣一來,當使用者點選此按紐時,便會開啟Install至客戶端的對話盒。
圖6
Silent install OOB Application
除了以上兩種安裝OOB應用程式的方式外,你也可以選擇【Silent Install】,也就是以命令列模式安裝,這種安裝方式不會顯示
任何視窗於使用者電腦上。
C:\temp1>"c:\Program Files (x86)\Microsoft Silverlight\sllauncher.exe" /install: SilverlightApplication10.xap /origin:http://localhost:29162/ClientBin/Silverligh tApplication10.xap /shortcut:startmenu /overwrite |
將此命令放至批次檔(.bat)中,然後與.xap一併封裝給使用者,那麼使用者就能執行.bat來安裝你的OOB應用程式了。
更多的silent install參數請參考: |
Entering into elevated trust mode
在Silverlight 4之前,Silverlight應用程式一直都執行在sandbox(沙箱)中,無法存取本地端的資源,在網路存取部份也受到
Cross-Domain Policy的限制,即使是在OOB模式下也不例外,這使得Silverlight的應用受到了很大的限制。
Silverlight 4中添加了elevated trust模式,在這個模式下,OOB應用程式可以在有限程度下存取本地資源,例如存取
My Documents、My Pictures等目錄下的檔案,或是不受限於Cross-Domain Policy來存取網路。
啟用elevated trust mode的步驟很簡單,只要Silverlight Project的Application設定頁中開啟Out-Of-Browser Settings,
即可勾選此模式。
圖7
當使用者安裝此OOB應用程式時,會被提醒此應用程式將以elevated trust模式安裝。
圖8
Accessing Local Files
在OOB+elevated trust模式下,Silverlight應用程式將可存取部份的本地端資源,如下列程式碼所示:
private void UserControl_Loaded(object sender, RoutedEventArgs e) { using(FileStream fs = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) + "\\調皮貓.jpg",FileMode.Open,FileAccess.Read)) { BitmapImage bmp = new BitmapImage(); bmp.SetSource(fs); image1.Source = bmp; } } |
如果不在OOB+elevated trust模式下,此程式將拋出圖9的錯誤。
圖9
你可以透過App.Current.IsRunningOutOfBrowser屬性來判斷目前程式是否處於OOB模式下:
private void UserControl_Loaded(object sender, RoutedEventArgs e) { if (App.Current.IsRunningOutOfBrowser) { using(FileStream fs = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) + "\\調皮貓.jpg",FileMode.Open,FileAccess.Read)) { BitmapImage bmp = new BitmapImage(); bmp.SetSource(fs); image1.Source = bmp; } } } |
Network Accessing
同樣的,在elevated trust + OOB模式下,你也可以不受Cross-Domain Policy限制來存取網路,如下列程式碼所示:
private void button1_Click(object sender, RoutedEventArgs e) { WebRequest wr = WebRequest.Create("http://www.hinet.net"); wr.BeginGetResponse((IAsyncResult state)=> { WebResponse rep = wr.EndGetResponse(state); Dispatcher.BeginInvoke(() => { MessageBox.Show(rep.ContentLength.ToString()); }); } ,wr); } |
Debugging OOB Application
當開發OOB + elevated trust應用程式時,由於程式可以存取許多本地端資源,因此原本的網頁式除錯就不再適用了(因為當存取本地資源時,
網頁模式會拋出例外),Visual Studio 2010添加了一個OOB專用的除錯模式,請將Silverlight Project設為Startup Project。
圖10
然後於Silverlight Project Application設定中,將Debug頁中的Start Action改為Out-Of-Browser application。
圖11
接著按下F5執行程式,此時便進入了OOB專屬的除錯模式。
Accessing Local Files without limit
雖然OOB + elevated trust可以存取本地檔案,但是依然受限於My Documents、My Pictures等目錄,如果想要存取這
之外的目錄,都會以例外收場。
不過解法也不是沒有,由於OOB + elevated trust可以直接存取COM,只要透過ADODB.Stream或是FileSystemObject等COM物件,
OOB + elevated trust應用程式也是可以越過這道牆的。
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Runtime.InteropServices.Automation; ............ private void UserControl_Loaded(object sender, RoutedEventArgs e) { LoadFromTemp(); } private void LoadFromTemp() { dynamic binStream = AutomationFactory.CreateObject("ADODB.Stream"); binStream.Type = 1; binStream.Open(); binStream.LoadFromFile("C:\\temp1\\調O皮DO貓s.jpg"); dynamic bytes = binStream.Read(); MemoryStream ms = new MemoryStream(bytes); BitmapImage bmp = new BitmapImage(); bmp.SetSource(ms); image1.Source = bmp; } |
當然,這只能在Windows 下執行就是了(別忘了,Silverlight是跨平台的)。
Executing Local Application
那如果想於Silverlight OOB+elevated trust程式中執行外部程式呢?答案一樣是透過COM,有個Windows Script物件
可以達到需求。
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Runtime.InteropServices.Automation; namespace ExecuteExeInOOB { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { dynamic wshell = AutomationFactory.CreateObject("WScript.Shell"); wshell.Run(@"C:\Windows\Notepad.exe", 1, false); } } } |
Executing OOB Application via .NET Application
那Silverlight OOB應用程式是裝在那呢 ?如果我想用程式去喚起某個OOB應用程式,又該如何做呢? OOB應用程式其實只是個.xap檔,
透過sllauncher.exe執行,因此當你查看OOB應用程式的捷徑內容時,會發現其命令列是sllauncher.exe加上一串數字。
圖12
事實上,OOB應用程式是存放於" Local Settings\Application Data\Microsoft\Silverlight\OutOfBrowser"目錄下,裡面有個
index目錄中包含了這些數字與實際xap的對應,透過解析裡面的檔案,可以達到以外部應用程式喚起OOB應用程式的目的。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.Diagnostics; namespace ExecuteOOBApp { public partial class Form1 : Form { private List<XapInfo> _xapInfos = new List<XapInfo>(); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { if (listBox1.SelectedIndex != -1) { XapInfo xi = _xapInfos[listBox1.SelectedIndex]; Process.Start(@"C:\Program Files (x86)\Microsoft Silverlight\sllauncher.exe", xi.XapID + "." + xi.Uri.Host); } } private void Form1_Load(object sender, EventArgs e) { string localAppPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); foreach (string file in Directory.GetFiles(localAppPath+"\\Microsoft\\Silverlight\\OutOfBrowser\\index\\", "*.*")) { using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read)) { if (fs.Length == 0) continue; using (StreamReader sr = new StreamReader(fs, Encoding.Unicode)) { while (!sr.EndOfStream) { string dm = sr.ReadLine(); string[] infos = dm.Split('\t'); Uri uri = new Uri(infos[1], UriKind.Absolute); _xapInfos.Add(new XapInfo() { Uri = uri, XapID = infos[0], XapName = uri.AbsoluteUri }); } } } } listBox1.DisplayMember = "XapName"; listBox1.DataSource = _xapInfos; } } public class XapInfo { public Uri Uri { get; set; } public string XapID { get; set; } public string XapName { get; set; } } } |
圖13
你也可以透過sllanucher.exe來以url執行某個已安裝的OOB應用程式。
C:\temp1>"c:\Program Files (x86)\Microsoft Silverlight\sllauncher.exe" /emulate: SilverlightApplication10.xap /origin:http://localhost:29162/ClientBin/Silverligh tApplication10.xap /overwrite |
Auto Update in OOB
先天上,Silverlight OOB 應用程式擁有自動更新的機制,這也是你為何要在sllauncher.exe後加上origin參數的原因,
不過這個機制預設是關閉的,需要透過程式來啟用。
public partial class App : Application { public App() { this.Startup += this.Application_Startup; this.Exit += this.Application_Exit; this.UnhandledException += this.Application_UnhandledException; InitializeComponent(); if (Application.Current.IsRunningOutOfBrowser) { App.Current.CheckAndDownloadUpdateCompleted += new CheckAndDownloadUpdateCompletedEventHandler( Current_CheckAndDownloadUpdateCompleted); App.Current.CheckAndDownloadUpdateAsync(); } } void Current_CheckAndDownloadUpdateCompleted(object sender, CheckAndDownloadUpdateCompletedEventArgs e) { if (e.Error == null && e.UpdateAvailable) { MessageBox.Show("Application updated, please restart to apply changes."); } } ............. |
一旦啟用自動更新機制後,當使用者執行電腦上的OOB應用程式時,假如有連上網路及遠端的.xap有更新時,便會出現提示更新的訊息。
圖14
按下確定後,此OOB程式便會自動下載新的.xap,關閉後再啟動此應用程式,便是最新版本。
PS: 當 OOB + Elevated Trust時,自動更新的機制需要簽署XAP方能正常運作,如果沒有憑證,可於Silverlight Project Page中建立一個測試用憑證來測試.
圖15
圖15