Windows 8 – Customize Portable Library(黑之章)

在前些日子的Microsoft Developer Day 2012中,我主講一場『可攜性函式庫在Windows 8及Windows Phone 7開發實戰』,內容主要是談如何透過Portable Library開發類別庫,

使其能在不重新編譯情況下共用於Window Phone 7及Metro Style環境。

/黃忠成

 

  在前些日子的Microsoft Developer Day 2012中,我主講一場『可攜性函式庫在Windows 8及Windows Phone 7開發實戰』,內容主要是談如何透過Portable Library開發類別庫,

使其能在不重新編譯情況下共用於Window Phone 7及Metro Style環境。

  事實上,在研究Portable Library的核心實作手法過程中,我成功的製作出私有的Portable Library,這個私有的Portable Library可以讓我使用原本未定義於Metro Style的

類別及函式(like File.Exists),當然,這並不被Windows Store所允許,也無法通過現在或是未來的WACK(Windows Application Certification Kit)的驗證,所以也無法提交至Windows Store,

我的目的其實很簡單,只是純粹想知道Portable Library到底是怎麼做出來而已。

 

黑之章

 

 在Portable Library那場中,有圖1這張投影片。

圖1

在這裡,我暗示了即使位於Metro Style環境中,Full .NET Framework 4.5還是完全存在的,只是被隱藏起來了,問題在於,怎麼隱藏的?

 

.NET Metadata

 

  昨天的Windows Metadata的歷史一文中提及了從.NET Framework 3.5 Client Profile就開始出現的.NET Metadata,Full .NET Framework 4.5就是以這種方式藏起來,在Metro Style環境中,

當使用C#/VB等.NET Language時,所參考的Assemblys都是.NET Metadata,這意味著,如果想要隱藏某個類別或是函式,只要不提供.NET Metadata,那麼開發者就無法在開發應用程式時使用她們。

  哪有沒有辦法使用不存在於.NET Metadata的這些東西呢?方法有兩個,第一種就是Reflection,所以在投影片的最末出現過圖2。

圖2

這張投影片是我最後一天才補上的,因為我刻意隱藏『黑之章』的存在(沒意思藏私,只是講黑之章就得超時)。

Reflection雖然可以讓我們寫出可以通過編譯的程式碼,但事實上Metro Style的沙箱正巧就做在Reflection System上,也就是說這段程式碼在執行時

是會出現安全性錯誤的。

  我真正得知.NET Framework 4.5完整存在於Metro Style App的途徑是透過第二種方式,也就是『自訂Portable Library』。

 

自訂Portable Library

 

  當在Visual Studio 2010中安裝了Portable Library Tools之後,其會把數組.NET Metadata安裝在『C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable』目錄下,

在選擇Portable Library所Target的Platform時,Visual Studio 2010未依據所Target的Platform來決定專案會使用哪個Profile的參考。

圖3

圖4

當得知是使用哪個Profile之後,接著重點就是,我們可以透過IL DASM/ILASM來改造想要改造的.NET Metadata。

先透過IL DASM找到想要改造的mscorlib.dll,然後反組譯成.il檔。

圖5

有了IL檔案之後,接下來就是添加想要對應至真實.NET Framework類別或函式的Metadata,以File.Exists來說,IL Code大概是下面這樣。

 

.class public auto ansi sealed beforefieldinit System.IO.File

       extends System.Object

{

    .method assembly hidebysig specialname rtspecialname

          instance void  .ctor() cil managed

  {

    // Code size       7 (0x7)

    .maxstack  8

    IL_0000:  ldarg.0

    IL_0001:  call       instance void System.Object::.ctor()

    IL_0006:  ret

  } // end of method Thread::.ctor

 

    .method public hidebysig static bool Exists(string path) cil managed

    {

         .maxstack  8

         ldc.i4.0

         ret

    }

}

當然,該放在IL檔案的哪個地方,需要一些基礎的IL知識。

完成後,透過IL ASM編譯。

 

C:/ ilasm mscorlib.il /DLL

最後用輸出的mscorlib.dll置換原本Profile目錄中的mscorlib.dll,結果就是如圖6。

圖6

   有趣的是,透過這個自訂.NET Metadata所編譯出來的Portable Library,執行時期是不需要.NET Metadata的,這是.NET Metadata存在的本質意義,

其只作用於Intellisense與編譯時期。

 

   提醒各位,我不鼓勵各位用這種方式去修改Portable Library Tools內的Profile既有的DLL,我只是要了解Portable Library Tools的核心實作過程才這麼做,

 

但這裡得到的一些觀念及手法,或許哪天可以不僅用於黑之章,還可以用於光明手段。