淺談Windows 8 Metro Style App開發

淺談Windows 8 Metro Style App開發

Windows 應用程式開發沿革

 

早期Windows系統尚未面市前,編寫C/C++語言的最大優勢就是可以自由地存取硬體資源,但是這種自由常常發生程式間互搶資源的問題,因此當時Windows在發展之初就推出了硬體控制層(Hardware Controller Layer, HCL)的概念,也就是將電腦中所有的硬體資源交由Windows進行分配與控制,因此直接存取硬體在Windows上不再是C/C++語言獨有的優勢,而HCL所衍生出來的就是Windows API,任何程式與作業系統的溝通必須透過Windows API來進行。(由於Windows API是在Windows 95時發展出來的,Windows 95是32位元作業系統,所以又稱Win32 API。)因為早期硬體之類的控制是以C/C++語言為主流,因此Windows API發展之初僅提供給C/C++開發人員使用,後來Delphi和VB6也能夠呼叫Windows API。

由於Windows API掌控了整個作業系統的存取,隨著其它程式語言的發展,開發人員對於Windows API的需求愈來愈高,因此也發展出各種不同的技術讓其它非C/C++的程式語言也可以使用Windows API,如早期的DDE(Dynamic Data Exchange)、OLE(Object Linking and Embedding)和COM(Component Object Model)等等技術。

後來隨著物件式導向語言的發展,以應用程式框架(Application Framework)的方式來封裝API的方式逐漸成為主流,如今我們常用的.NET Framework也就是應用程式框架的一種。

在一般的.NET開發使用上,我們並不會發覺Windows API的存在,因為.NET已經事先將一些常用的API進行封裝,因此這些API並不需要以特殊的方式進行存取。但如果需要使用未被封裝的API時,我們會以P/Invoke的方式進行處理。

以下就是一個使用P/Invoke呼叫Windows API的例子。

using System.Runtime.InteropServices;
namespace Beep
{
    class PInvoke
    {
        [DllImport("kernel32.dll")]
        public static extern bool Beep(int frequency, int duration);
        static void Main(string[] args)
        {
            Random random = new Random();
            for (int i = 0; i < 10000; i++)
            {
                Beep(random.Next(10000), 100);
            }
        }
    }
}

 

而Metro Style Application的運作模式與.NET的模式又有些不同...。

Windows Runtime

Metro Style Application是一種可使用C++(原生碼)、.NET(C#/VB)以及JavaScript進行開發的應用程式類型,它透過Windows Runtime(以下簡稱WinRT)做為應用程式與系統核心的溝通層。.NET開發人員應該知道,我們開發的應用程式是編譯成ByteCode(中間碼),執行時需透過CLR將中間碼轉換為機器碼才能執行。而WinRT是一種架構於CLR之下的轉譯器,如果以.NET的角度來説明,我想以CLR中的CLR來看待它會比較容易理解。

.NET的程式開發語言中並不包含JavaScript,但微軟在Metro Style App開發中納入JavaScript,其用意是希望網頁開發人員可以不用學習新的語言就能開發Metro Style App,這與我們過去的認知不同,因為JavaScript原本是使用於網頁的語言,其功能受到瀏覽器的限制,而如今卻要讓它做到與.NET語言一樣的功能...。

將JavaScript納入原有的.NET言語系統中並不太可行,因為.NET中原本就有ASP.NET之類的網頁開發工具,如果讓JavaScript具有與.NET語言般強大的功能,這會有安全風險上的問題,一旦讓JavaScript可以隨意地讀取網頁瀏覽者的電腦,那麼JavaScript語言必定成為駭客最愛的工具。因此在做法上需要一種能將原本.NET語言和JavaScript轉換為通用語言的機制,而此一轉換的機制,我們稱為Projection。透過Projection的轉換機制,不管開發者使用那一種語言,都能夠轉換為統一模型。因此在原本的.NET CLR之下再加入一層的CLR(Projection)就成了Metro Style App能夠支援JavaScript的方式。

WinRT是應平板電腦需要而建構出來的Runtime架構,它依據平板電腦的特性封裝API,例如:重力、速度等Sensor控制、GPS控制等等API。雖然我們可以使用一樣的.NET 開發方式來開發Metro Style App,但它是受到控制的,也就是説它不能支援完整的.NET架構,例如Sliverlight也一樣使用.NET語言進行開發,但是功能受到瀏覽器的限制,無法完整地使用所有的.NET功能。

但我們一樣可以使用.NET語言開發,也一樣將存取底層API的工作交由Runtime處理,所以基本上不需學習太多的知識就能快速上手。我們先看一下Metro Style Application的架構。


image

 

由上圖可以看到Metro Style Application與桌上型應用程式採用完全不同的架構,在介面層(View)中我們可以採用XAML或HTML 5(+CSS 3.0)來進行應用程式的外觀設計;在模組控制層(Model Controller)的部分可支援C、C++、C#、VB和JavaScript。因此我們可歸納出Metro Style Application幾種開發模式:

  • XAML + (C++/C#/VB)
  • HTML 5+JavaScript
  • Microsoft DirectX + C++

這三種開發模式可以滿足大部分的應用程式開發人員,例如:擅長桌上型應用程式開發者可使用XAML + (C++/C#/VB)、擅長網站應用程式的開發者可選用HTML 5 + JavaScript的方式進行開發,而C++則適合講究執行效能的應用程式。由Windows 8軟體架構圖中我們可以看到Metro Style Application存取系統服務都必須透過WinRT API來進行處理。

image

 

Projections

由Windows Runtime架構來看,Metro Style Application是透過Language Projections與下層API進行互動,「Projection」其實就是「晚期繫結」(Binding)。Projections透過介面呼叫的方式讓C、C++、HTML/JavaScript和.NET可以存取下層API。利用這種方式開發者毋需理會如何存取下層API,這部分由Projections進行處理,因此不管開發者使用那一種程式語言都能透過Language Projections存取下層的Windows Runtime API(Library)。這種透過Projections進行處理的運作模式與.NET的CLI/CLR的運作模式有點類似。對於使用.NET的開發人員而言,我們可以將Projections視為「CLR中的CLR」,這種説法可以從下圖中得到印證。


image

 

Windows MetaData

關於Projections還有一個比較特別的地方,如果我們使用.NET或C++開發自訂類別,而此類別將提供給其它不同語言的開發程式使用時,我們必須將組件以WinMD File的方式編譯儲存。而產生的WinMD檔案也就是上圖中Windows MetaData(中繼檔資料),透過WinMetaData可讓Projections知道如何應對到相對的物件。

imageimage

 

如果使用檔案總管檢視C:\Windows\System32\WinMetadata這個目錄,我們可以看到一群以.WinMD為副檔名的檔案。而這些.WinMD檔案也就是開發時期與其它開發語言共同的物件來源。

image

 

事實上在Metro Style Application開發時期所使用到的任何內建物件都是透過這種方式進行引用,這與開發.NET應用程式引用.DLL檔案是有所不同的。但這並不代表我們今後都必須將類別庫編譯為WinMD File,前提是「如果開發的類別庫要提供給其它開發語言使用時」。.NET Framework的基本組成是CLI與CLR,CLI是指通用語言基礎結構(Common Language Infrastructure),它是基於ISO與ECMA標準所開發出來的,.NET CLI規範文件中定義Metadata為:程式結構的資訊,它和開發的語言無關,可以在語言和工具之間被引用....。在.NET中實現CLI的是MSIL,也就是將各種不同的語言編譯成統一的格式,再由CLR(Common Language Runtime)編譯成機器碼執行。而. WinMD File就是編譯後的CLI,它只包含程式的相關資訊,如使用了那些類別庫與所需環境之類的訊息,已經和開發它的語言無關了,即使它不是我們過去所認知的類別庫,但它已經包含了程式的結構、所使用的類別庫等等資訊,在微軟的2012開發者年會上,對於Windows Metadata的說明中有一句:「Same structures, different meanings」既然是相同的結構,那當然也就可以被引用。

如果需要檢視.WinMD檔案的內容,可以使用ILDASM指令來檢視,例如要檢視Windows.Storage.Pickers.winmd檔案,請在命令視窗中將目錄移至C:\Windows\System32\WinMetadata,輸入:


ILDASM Windows.Storage.Pickers.winmd

 

image

 

版本相容性

開發過Android應用程式的人都知道,在建立開發範本時必須先指定未來執行的Android系統版本,而Android開發版本相容性一直為人詬病,這與Android的特性有關,由於Android採用比較開放的政策,因此Android的套件來源並不一致,較無一定的規格。因此當Android版本更新時,若應用程式版本要隨之更版的話,有時候需更動的程式碼會出乎意料得多。

而WinRT的系統物件必須實作IInspectable與IUnknow這兩個介面,因此只要未來版本的Windows系統沒有變更這兩個介面規格,開發過應用程式則不需依Windows版本的變動而重新改寫、編譯。

image