XAML in Xamarin.Forms 基礎篇 電子書

XAML in Xamarin.Forms 基礎篇 電子書
XAML in Xamarin.Forms 基礎篇 電子書

Xamarin.Forms 快速入門 電子書

Xamarin.Forms 快速入門 電子書
Xamarin.Forms 快速入門 電子書
顯示具有 WinRT 標籤的文章。 顯示所有文章
顯示具有 WinRT 標籤的文章。 顯示所有文章

2014/07/22

如何產生較長有效期限的應用程式開發簽名憑證 app package signing certificate

當我們開發好 WinRT / Windows 8.1 市集App後,想要進行側載佈署,這個時候,您會發現到您需要將產生好的側載套件檔案中的 xxx.cer 安裝到您的電腦授權憑證內。


不過,當您檢視這個憑證,您會發現到這個憑證有效期限內只有一年,也就是您當時建立好這個側載安裝套件之後的一年內,都是有效的;然而,若該App超過一年後,並且沒有重新進行側載佈署到使用者電腦上,會因為該程式數位簽名憑證已經到期,導致您的App無法使用。


我使用一個簡單的方式來解決此一問題,那就是把這個程式數位簽名有效期限給他延長一點時間,比如說,10年,那麼,在這十年內,只要這個開發程式簽名憑證沒有過期,那麼,已經側載的App是可以繼續使用的。

首先,開啟命令提示字元視窗,說輸入底下指令

MakeCert /n "CN=Contoso Software, O=Contoso Corporation, C=US" /r /h 0 /eku "1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.10.3.13" /e 07/01/2020 /sv MyCert.pvk MyCert.cer

Pvk2Pfx /pvk MyCert.pvk /pi p@ssw@rd /spc MyCert.cer /pfx MyCert.pfx /po p@ssw@rd

這個時候,在您命令提示字元當時所在的目錄下,會產生出 [MyCert.pfx]檔案,請將這個檔案複製到您Windows Store App的專案根目錄下。

接著,雙擊 [Package.appxmanifest] 檔案,切換到 [封裝] 頁次,點選 [選擇憑證] 按鈕,此時會跳出 [選擇憑證] 的對話視窗,接著點選 [設定憑證(T)...]的下拉選單,我們需要選擇 [從檔案選取...] 項目,這個時候,請在您專案根目錄下選擇 [MyCert.pfx] 檔案。


這樣就完成了將您的程式數位簽名( Code Sign )憑證的有效期限增加超過一年以上的目的。



2014/07/14

進行Windows 8.1 App 側載的時候,該App的憑證是安裝到哪裡了呢?

當我們進行 Windows 8.1 App 側載的時候,系統會要求我們要安裝 App的信任憑證到您的系統中。

下圖為我們要側載的 Windows 8.1 App Package 套件檔案,您可以看到檔案 [未來信Win81通用.Windows_1.0.0.0_AnyCPU_Debug.cer] 就是這個App的憑證。


其實,該憑證被 PowerShell 程式 ( Add-AppDevPackage.ps1 )自動安裝到 本機電腦中的 [受信任的人] 的區域內了,如下圖所示。





進行側載時候,遇到的開發者授權 developer license 之問題

若您需要把您開發的App,側載到其他電腦上,通常您都會遇到這樣的情況,那就是要求您建立一個 developer license ,在這裡,有幾個不錯的 PowerShell 工具可以使用。

在這裡,請按下 [Win Key] + [S] 這兩個組合按鍵,接著,在搜尋小視窗中,輸入 powerShell ,此時,您會看到Windows 8 幫您自動搜尋出與 powerShell 相關的任何事物,此時,請在 [Windows PowerShell] 這個項目上,請您使用滑鼠右擊該項目,選擇使用 [以系統管理員身分執行] 模式,啟動 PowerShell,如下圖所示。



請在開啟的 [系統管理員: Windows PowerShell] 視窗中,輸入底下指令:

Get-WindowsDeveloperLicense

此時,您會看到這台電腦上所擁有的開發者授權是否還有效,以及還剩下多少天就需要重新再度更新。

若您想要更新您電腦上的開發者憑證,請輸入底下指令:
Show-WindowsDeveloperLicenseRegistration

此時,您的電腦上會出現下圖畫面,詢問您是否要 更新您的 Windows 8.1 開發人員授權,點選右下角的 [我同意] 按鈕,即可更新到最新的開發人員授權有效時間。


想要撤銷電腦上的開發人員授權,請輸入底下指令:
Unregister-WindowsDeveloperLicense

當輸入完指令,並且按下 [Enter] 按鈕後,您會在畫面上看到

您即將把開發人員授權從這部電腦移除。
此電腦上的開發人員授權將在 2014/8/2 下午 06:17:17
到期。若將開發人員授權從這部電腦移除,某些應用程式將停止運作。確定要移除此授權?
[Y] 是(Y)  [N] 否(N)  [S] 暫停(S)  [?] 說明 (預設值為 "Y"):

請直接按下 [Enter] 按鍵,即可已將此電腦上的開發人員授權移除,此時,我們再度電腦上擁有的開發人員授權,請輸入底下指令,並且按下 [Enter]

Get-WindowsDeveloperLicense

這個時候,PowerShell 視窗會顯示底下訊息,告知您,這此電腦上沒有開發人員授權

PS C:\Vulcan> Get-WindowsDeveloperLicense
Get-WindowsDeveloperLicense : 此電腦上沒有開發人員授權。
位於 線路:1 字元:1
+ Get-WindowsDeveloperLicense
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Get-WindowsDeveloperLicense],InvalidOperationException
    + FullyQualifiedErrorId : NoRegisteredDeveloperLicense,Microsoft.Windows.DeveloperLicense.Commands.GetWindowsDevel
   operLicenseCommand

2014/07/13

如何手動針對 Windows Store App 側載套件 Sildloading Package,安裝到您的電腦上

當您收到了Windows Store App 側載套件之後,您會看到類似下圖的檔案與目錄,其中 [Add-AppDevPackage.ps1]就是提供您側載的 PowerShell Script,請使用滑鼠右鍵點選該檔案,接著在彈跳功能表中,選擇第二個選項 [用 PowerShell 執行]。


此時,您的 [Windows PowerShell] 命令提示視窗中,會出現底下的文字

找到封裝: C:\Vulcan\未來信\未來信Win81通用\未來信Win81通用.Windows\AppPackages\未來
信Win81通用.Windows_1.0.0.0_AnyCPU_Debug_Test\未來信Win81通用.Windows_1.0.0.0_AnyCPU_Debug.appx
找到憑證: C:\Vulcan\未來信\未來信Win81通用\未來信Win81通用.Windows\AppPackages\未來
信Win81通用.Windows_1.0.0.0_AnyCPU_Debug_Test\未來信Win81通用.Windows_1.0.0.0_AnyCPU_Debug.cer

安裝這個應用程式之前,必須執行下列動作:
        - 取得開發人員授權
        - 安裝簽署憑證
必須有系統管理員認證才能繼續。請接受 UAC 提示,並在系統要求時提供您的系統管理員密碼。
按 Enter 鍵繼續...:

這是因為當您電腦第一次進行 Windows 8.1 Store App 側載的時候,您需要在這台電腦上取得開發人員授權,不過,進行註冊開發人員授權的時候,需要有系統管理員的認證才能夠操作,而且,您也需要擁有 Microsoft Account 帳號。

在我們按下了 [Enter] 按鍵後,接受了 UAC 提示,此時畫面會出現底下對話窗


當您選擇按下了 [我同意] 按鈕,稍後,您會看到 [開發人員授權] 的對話窗,要求您使用您的 Microsoft Account 微軟帳號進行登入驗證;當您輸入完微軟帳號與密碼後,會看到底下小視窗,告知您系統正在取得 Windows 8.1 的開發人員授權


一旦正式取得了開發人員授權,您會看到底下視窗,告知您此次取得的開發人員授權到期日到何時,此時我們按下 [關閉] 按鈕。


接著 [系統管理員: Windows PowerShell] 視窗中,您會看到底下文字

正在取得開發人員授權...
正在安裝憑證...您即將安裝數位憑證

到您電腦的「受信任的人」憑證存放區。這會帶來嚴重的安全性風險,請務必在您信任這個數位憑證的建立者的情
況下才執行這個動作。

使用完這個應用程式之後,您應該手動移除相關的數位憑證。有關執行這個動作的指示,請參閱:
http://go.microsoft.com/fwlink/?LinkId=243053

您確定要繼續嗎?

[Y] 是(Y)  [N] 否(N)  [?] 說明 (預設值為 "N"):

請您輸入大寫的 Y ,並且按下 [Enter] 按鍵。

稍待一段時間,您就會看到這個訊息:

成功:  已成功安裝您的應用程式。
按 Enter 鍵繼續...:

表示您已經成功了側載這個Windows 8.1 Store App了,您可以在 Windows 8.1的桌面查看最新側載安裝好的 App,並且執行他。

總結,若您是第一次在您的電腦上側載 Windows 8.1 Store App,您需要做到底下事情:
安裝這個應用程式之前,必須執行下列動作:

       - 取得開發人員授權
       - 安裝簽署憑證



如何產生 Windows Store App 的側載 Sideloading 的套件 Package

首先,使用 Visual Studio 2013 打開您的Windows Store App專案,從功能表選擇 [專案] > [市集] > 建立應用程式套件,如下圖所示:


請在 [建立應用程式套件] 對話窗中的 您要建置套件以上傳到 Windows 市集嗎?
請選擇 [否] 按鈕,接著點選右下角的 [下一步] 按鈕。

接下來您會看如下圖的對話窗,在 選取要建立的套件和方案組態對應 (左下角),您可以選擇 Neutral,表示該套件可以安裝在任何作業系統下 x86, x64, ARM,接著按下 [建立] 按鈕,則 Visual Studio 會開始幫忙建立這個App 可以用於側載的套件。


當 App 側載套件已經產生完成後,他會告訴您這些套件產生在哪個目錄下,您可以點選這個目錄連結,檔案總管會自動切換到這個目錄下。


當我們用檔案總管打開上圖的路徑後,您會看到如下圖的內容:
其中,下圖紅線框住的目錄,您可以使用任何壓縮工具將其壓縮起來,並且將這個壓縮檔案提供給需要側載的測試人員,他們就可以進行側載了。








2014/07/09

在 Windows 8.1 中,如何將 BitmapImage 的圖片內容透過 WriteableBitmap 寫入到磁碟檔案上

WriteableBitmap 是個很好用的程式庫,因為我們可以透過 WriteableBitmap 任意繪製與產生您所想要的圖片與內容,不過,要如何將 WriteableBitmap 的圖片內容,轉換成為圖片檔案呢(jpg, jpeg, png)?

在底下的程式碼,我們從 App Package 套件中的 Assets 目錄下,讀入一個圖片檔案,並且將這個圖片檔案設定到 BitmapImage 物件中,這是為了要知道這個圖片的長度與寬度。

接著,我們產生一個 WriteableBitmap 物件,在建構式中,我們傳入的 WriteableBitmap 所需要的寬度與高度,接著,將剛剛讀入的圖片檔案,使用 SetSourceAsync 設定到 WriteableBitmap 物件上,接著,我們就可以透過 SaveToFile 這個方法,把這個 WriteableBitmap 寫入到圖片檔案內。

            StorageFile storageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Images/Pages/PageBackground.jpg"));
            IRandomAccessStream stream = await storageFile.OpenAsync(FileAccessMode.Read);
            BitmapImage bitmapImage = new BitmapImage();
            await bitmapImage.SetSourceAsync(stream);
            stream.Seek(0);

            var wb1 = new WriteableBitmap(bitmapImage.PixelWidth, bitmapImage.PixelHeight);
            await wb1.SetSourceAsync(stream);
            StorageFile sf1 = await ApplicationData.Current.LocalFolder.CreateFileAsync("your.png");
            await SaveToFile(wb1, sf1, BitmapEncoder.PngEncoderId);



        public async Task SaveToFile(WriteableBitmap writeableBitmap, IStorageFile outputFile, Guid encoderId)
        {
            try
            {
                Stream stream = writeableBitmap.PixelBuffer.AsStream();
                byte[] pixels = new byte[(uint)stream.Length];
                await stream.ReadAsync(pixels, 0, pixels.Length);

                using (var writeStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
                {
                    var encoder = await BitmapEncoder.CreateAsync(encoderId, writeStream);
                    encoder.SetPixelData(
                        BitmapPixelFormat.Bgra8,
                        BitmapAlphaMode.Premultiplied,
                        (uint)writeableBitmap.PixelWidth,
                        (uint)writeableBitmap.PixelHeight,
                        96,
                        96,
                        pixels);
                    await encoder.FlushAsync();

                    using (var outputStream = writeStream.GetOutputStreamAt(0))
                    {
                        await outputStream.FlushAsync();
                    }
                }
            }
            catch (Exception ex)
            {
                string s = ex.ToString();
            }
        }




2014/07/02

安裝 WinRT App 發生問題之除錯方法

經常有些時候,我們在安裝(不論透過市集或者使用 Sideloading 側載方式)App,有些時候會發生錯誤或者異常,我們可以透過 [事件檢視器] 來查看這些Windows Store App 再進行佈署、安裝、註冊的時候,發生了甚麼問題。

請使用滑鼠右擊螢幕左下方的視窗圖示,此時會彈出下圖對話窗,請選擇 [事件檢視器]


 我們需要觀察 事件檢視器 中的這三個節點上的資料
Application And Services Logs > Microsoft > Windows > AppXDeployment
Application And Services Logs > Microsoft > Windows > AppXDeployment-Server
Application And Services Logs > Microsoft > Windows > AppXPackagingOM


 在下圖中,我們展示了查看某個錯誤訊息,這是屬於 AppXDeployment-Server
我們看到這個訊息顯示了:
錯誤 0x80073CF9: AppX 部署操作失敗。此失敗的特定錯誤文字是: 另一個使用者已安裝此應用程式的未封裝版本。目前的使用者無法使用已封裝的版本來取代此版本。衝突的套件是 CLACOMUSICCORPORATION.MusicPlayAlong,它是由 CN=327F2EE7-B787-4EC2-8B56-6B65F0CBB4FB 發行。

記錄檔名稱:         Microsoft-Windows-AppXDeploymentServer/Operational
來源:            Microsoft-Windows-AppXDeployment-Server
日期:            2014/6/21 下午 08:19:46
事件識別碼:         404
工作類別:          (3)
層級:            錯誤
關鍵字:           AppXDeploymentServer 關鍵字
使用者:           SYSTEM
電腦:            VulcanHome81
描述:
錯誤 0x80073CF9: AppX 部署操作失敗。此失敗的特定錯誤文字是: 另一個使用者已安裝此應用程式的未封裝版本。目前的使用者無法使用已封裝的版本來取代此版本。衝突的套件是 CORPORATION.MPA,它是由 CN=32E7-B787-4EC2-8B56-6B65F4FB 發行。


事件 Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="Microsoft-Windows-AppXDeployment-Server" Guid="{3F471139-ACB7-4A01-B7A7-FF5DA4BA2D43}" />
    <EventID>404</EventID>
    <Version>0</Version>
    <Level>2</Level>
    <Task>3</Task>
    <Opcode>0</Opcode>
    <Keywords>0x4000000000000001</Keywords>
    <TimeCreated SystemTime="2014-06-21T12:19:46.781919400Z" />
    <EventRecordID>63324</EventRecordID>
    <Correlation ActivityID="{2363FD72-8D4A-0001-02FE-63234A8DCF01}" />
    <Execution ProcessID="4572" ThreadID="4944" />
    <Channel>Microsoft-Windows-AppXDeploymentServer/Operational</Channel>
    <Computer>VulcanHome81</Computer>
    <Security UserID="S-1-5-18" />
  </System>
  <EventData>
    <Data Name="SummaryError">另一個使用者已安裝此應用程式的未封裝版本。目前的使用者無法使用已封裝的版本來取代此版本。衝突的套件是 CORPORATION.MPA,它是由 CN=32E7-B787-4EC2-8B56-6B65F4FB 發行。</Data>
    <Data Name="ErrorCode">0x80073cf9</Data>
  </EventData>
</Event>











SuspensionManager & NavigationHelper 之 App Lifecycle生命週期會使用到的相關事件與呼叫順序

想要充分發揮 WinRT & Windows Phone Universal App 效能,您一定要知道應用程式生命週期的相關知識,這裡,做個總結。當從App開始啟動後、到切換到不同的頁面、進入到 Suspend 模式下、重新回到App執行模式下等相關事件的執行順序。

當App在不同執行模式下運作,或者切換頁面的時候,您需要明確的掌握到那些事件會被執行,而且這些事件被呼叫的順序,如此,您方能夠有效的控制App的整體狀態與運作行為。

當App第一次啟動的時候,相關的事件呼叫順序
  • App.OnLaunched 事件(也就是 PreviousExecutionState 為 Nothing)
  • 第一個頁面.OnNavigatedTo 事件
  • 第一個頁面.LoadState 事件

當App進入到 Suspended 模式下,相關事件的呼叫順序
  • App.OnSuspending 事件
  • 第一個頁面.OnNavigatedFrom 事件
  • 第一個頁面.SaveState 事件

使用者把App從 Suspended 模式下,切換為正在顯示的相關事件呼叫順序
  • App.OnResuming 事件

使用者或者作業系統把 App 終止(例如使用者使用工作管理員強制關閉該App),相關事件呼叫順序
  • App.OnSuspending 事件
  • 第一個頁面.OnNavigatedFrom 事件
  • 第一個頁面.SaveState 事件


使用者從第一個頁面切換到第二個頁面的相關事件呼叫順序
  • 第一個頁面.OnNavigatingFrom事件
  • 第一個頁面.SaveState 事件
  • 第一個頁面.OnNavigatedFrom 事件
  • 第二個頁面.LoadState 事件
  • 第二個頁面.OnNavigatedTo 事件

使用者從第二個頁面回到第一個頁面的相關事件呼叫
  • 第二個頁面.OnNavigatingFrom事件
  • 第二個頁面.SaveState 事件
  • 第二個頁面.OnNavigatedFrom 事件
  • 第一個頁面.LoadState 事件
  • 第一個頁面.OnNavigatedTo 事件

使用者再次切換到第二個頁面的相關事件呼叫
  • 第一個頁面.OnNavigatedFrom 事件
  • 第一個頁面.OnNavigatingFrom事件
  • 第一個頁面.SaveState 事件
  • 第一個頁面.OnNavigatedFrom事件
  • 第二個頁面.LoadState 事件
  • 第二個頁面.OnNavigatedTo 事件

App進入到 Suspended 模式下的相關事件呼叫(例如:切換到桌面環境中,或者其他App)
  • App.OnSuspending 事件
  • 第二個頁面.SaveState 事件
  • 第二個頁面.OnNavigatedFrom 事件

App從 Suspended模式下,回到正常運作模式下的相關事件呼叫
  • App.OnResuming


App進入到 Suspended 模式下並且被作業系統強制終止
  • App.OnSuspending 事件
  • 第二個頁面.SaveState 事件
  • 第二個頁面.OnNavigatedFrom 事件

開發 universal app ,如何在程式碼中,標示與切換 Windows store 或者 Windows phone 專用的程式碼

當我們在開發 universal app,讓 App 可以同時在兩個平台上執行,但是,某些情況,我們需要在特定平台上寫入只有該平台才擁有的功能,這個時候,您可以使用 [條件式編譯的符號] 來區隔,Windows Phone 使用 WINDOWS_PHONE_APP,而Windows Store 則使用 WINDOWS_APP。

那麼,我們要如何在 Visual Studio 上換不同平台,看到這些程式碼是否有效呢?
我們使用下圖做說明, NavigationHelper.cs 是共用程式碼區域的C#,在下圖內,我們看到了這行程式碼,只有 Windows Phone 才會使用的,如底下這行程式碼:

Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;

而底下的程式碼,是在 Windows Store App 環境下才會執行的。

                // 只有佔用整個視窗時才適用鍵盤和滑鼠巡覽
                if (this.Page.ActualHeight == Window.Current.Bounds.Height &&
                    this.Page.ActualWidth == Window.Current.Bounds.Width)
                {
                    // 直接接聽視窗,所以不需要焦點
                    Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated +=
                        CoreDispatcher_AcceleratorKeyActivated;
                    Window.Current.CoreWindow.PointerPressed +=
                        this.CoreWindow_PointerPressed;
                }

我們可以使用下圖編號1標示的地方,切換使用不同平台的 [條件式編譯的符號] ,如此,我們就可以看到不同平台的程式碼,是否有問題發生。

在下圖中,我們使用的是 Windows Store App平台的程式碼,您會看到了 Windows Phone 專屬的程式碼變成不可用的灰色了。


在下圖中,我們使用的是 Windows Phone App平台的程式碼,您會看到 Windows Phone 會用到的程式碼變成可用的黑色了。



2014/07/01

在WinRT Windows Phone App 中,想要下載較大的圖片、音樂、二進位檔案的方法

平常我們在 WinRT 或者 Windows Phone App中,想要取得網路上的檔案,可以透過 HttpClient 物件來進行取得這些檔案,不過,當這些網路上的檔案過大的時候,HttpClient 可能無法處理,這個時候我們就可以透過 BackgroundDownloader 物件來幫助我們做到背景下載這些檔案,卻又不會影響到 UI thread 執行緒,也就是不會造成您的 UI 凍結的問題。


            BackgroundDownloader downloader = new BackgroundDownloader();
             StorageFile destinationFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("vulcan.mp3");
            DownloadOperation download = downloader.CreateDownload(new Uri("http://host/path/vulcan.mp3), destinationFile);
            await download.StartAsync();
            ResponseInformation response = download.GetResponseInformation();

在 WinRT & Windows Phone 中,如何將顏色代碼文字,轉換成為 Windows.UI.Color 物件

底下的範例程式碼,提供了如何將顏色的代碼, #FF012345 或者 #012345 這樣的代碼,轉換成為 Windows.UI.Color 的物件。

        public static Color Parse(string color)
        {
            var offset = color.StartsWith("#") ? 1 : 0;

            string tt = color.Substring(offset);

            if (tt.Length > 6)
            {
                var a = Byte.Parse(color.Substring(0 + offset, 2), NumberStyles.HexNumber);
                var r = Byte.Parse(color.Substring(2 + offset, 2), NumberStyles.HexNumber);
                var g = Byte.Parse(color.Substring(4 + offset, 2), NumberStyles.HexNumber);
                var b = Byte.Parse(color.Substring(6 + offset, 2), NumberStyles.HexNumber);

                return Color.FromArgb(a, r, g, b);
            }
            else
            {
                var a = Byte.Parse("FF", NumberStyles.HexNumber);
                var r = Byte.Parse(color.Substring(0 + offset, 2), NumberStyles.HexNumber);
                var g = Byte.Parse(color.Substring(2 + offset, 2), NumberStyles.HexNumber);
                var b = Byte.Parse(color.Substring(4 + offset, 2), NumberStyles.HexNumber);

                return Color.FromArgb(a, r, g, b);
            }
        }



在 WinRT & Windows Phone 中,將非同步呼叫,轉換成為同步呼叫

有些時候,也許您不想要採用非同步方式的呼叫,不過,您所擁有的程式庫 Library ,卻都只有提供非同步方式呼叫的方法,這個時候,您可以採用底下的方式來將非同步的呼叫,轉換成為同步方式的呼叫。

                Task.Factory.StartNew(async () =>
                {
                    await IsolatedStorageJSON< List < AbnormalException > >.SaveToFileAsync("", "AbnormalException", listAbnormalException);
                });


另外,可以採用底下的方式(底下的範例是因為呼叫了 GetFileAsync 會傳回 IAsyncOperation<StorageFile> ,因此,我們可以透過這樣的方式,綁定了 Completed 事件,來判斷或者取回此次非同步呼叫的結果):

        public static void WinRTAsyncIntro()
        {
            IAsyncOperation< StorageFile > asyncOp = KnownFolders.PicturesLibrary.GetFileAsync("vulcan.png");
            asyncOp.Completed = OpCompleted;
        }
        private static void OpCompleted(IAsyncOperation< StorageFile > asyncOp, AsyncStatus status)
        {
                try
                {
                    StorageFile file = asyncOp.GetResults(); 
                }
                catch (Exception ex)
                {
                }

            asyncOp.Close();
        }

這是 GetFileAsync 的語法
public IAsyncOperation<StorageFile> GetFileAsync(
  string name
)

這裡還有另外一個方法,是比較有效率的,尤其是當您在 WinRT 系統下,需要用到 deferral 情境下,可以使用底下的方法,不過,需要特別注意的,這個方法,會造成當時的執行緒被鎖定,若您是在 UI Thread 下呼叫底下方法,會造成您的UI被凍結。

StorageFile myFile = KnownFolders.PicturesLibrary.GetFileAsync("vulcan.png").AsTask().GetAwaiter().GetResult();

2014/06/30

在 Windows 8.1 底下使用 RenderTargetBitmap 來儲存 XAML Element 的圖片

有些時候,我們希望能夠儲存某個頁面或者某個XMAL控制項當時畫面結果,到本機上的圖片檔案中,我們就可以使用底下的程式碼來做到這樣的需求。

首先,我們使用建立個RenderTargetBitmap物件,並且使用了 RenderAsync 方法,產生該 XAML 控制項 gd測試圖片 的影像來源輸入的緩衝區資料流。

接著我們使用了 FileSavePicker 讓使用者選擇要將該圖片檔案儲存到本機的哪個目錄下。

最後,我們就可以透過 BitmapEncoder 物件,SetPixelData 與 FlushAsync 方法,將該影像來源的緩衝區資料流,寫入到檔案內。


            RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
            await renderTargetBitmap.RenderAsync(gd測試圖片);
            // 1. Get the pixels
            IBuffer pixelBuffer = await renderTargetBitmap.GetPixelsAsync();
            var pixels = await renderTargetBitmap.GetPixelsAsync();

            var filePicker = new FileSavePicker();

            filePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;

            var textFileExtension = new[] { ".jpg" };
            var dataFileExtension = new[] { ".png" };

            filePicker.FileTypeChoices.Add("JPG", textFileExtension);
            filePicker.FileTypeChoices.Add("PNG", dataFileExtension);

            IAsyncOperation< storagefile > asyncOp = filePicker.PickSaveFileAsync();
            StorageFile file = await asyncOp;

            if (file == null)
            {
                return;
            }

            
            using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                var encoder = await
                    BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
                byte[] bytes = pixels.ToArray();
                encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                                     BitmapAlphaMode.Ignore,
                                     (uint)gd測試圖片.Width, (uint)gd測試圖片.Height,
                                     96, 96, bytes);

                await encoder.FlushAsync();
            }

2014/06/28

將 Windows 8.1 Store App 透過 Sideload 側載 方式,安裝到您企業內部使用者電腦上

Windows 8.1 的 WinRT Stroe App 與傳統的桌面程式,有著明顯不同的特性,其實,對於程式開發者而言,採用 WinRT Store 架構來開發的App,真的比起傳統的桌面App方便了許多,因為:它是全螢幕的、擁有良好的App運作流程、不會破壞到作業系統與影響其安全運作、可以觸控操作、流暢的表現和互動式的動畫。

單純開發Windows 8.1 Store App,也許不會太困難,因為,只要您具有 C# / VB / JavaScript / C++,立馬就可以馬上來開發,甚至開發出不錯的App;可是,大部分開發出來的App,都會提交到 Windows Store 市集做認證,一旦通過審核,就會在市集的App上,看到您開發出來的App,而使用者就可以透過市集App,下載並且安裝您開發出來的App到他們的電腦上。

可是,當您想要開發 Windows 8.1 Store App,並且想要將這個App (例如 line-of-business LOB 類型)讓企業內部的電腦使用,不過,您不想要透過微軟官方的市集來讓使用者從市集App找到專屬於您企業的App,甚至從市集下載您專屬App到企業員工的電腦上,這可就傷腦精了;因為,到現在為止,微軟並沒有針對 Windows 8.1 平台,推出各企業專屬的市集App,也就是說,想要把您開發出來,並且專屬於自己企業的Windows Store App到企業內部員工的電腦上,就不是這麼簡單的過程,這需要花點時間來處理。

想要佈署Windows 8.1 Store App到使用者的電腦上,而不透過微軟官方的公開市集系統,您可以採用的是 [側載] Sideloading 技術 (側載的應用程式不需要發行到 Windows 市集,也不需要使用已註冊的 Windows 市集開發人員帳戶就能開發。),讓您可以輕鬆地做到這樣的需求。

側載是個方法,可以讓您安裝 Windows Store App到電腦上,但是不透過市集App,這樣,就有幾個問題要考量:

  1. 開發出您企業專屬的 Windows Store App
  2. 如何將App的程式,自動佈署到使用者的電腦上
  3. 如何將這些App程式,安裝到使用者電腦上
  4. 如何進行新版本的App升級

開發出您企業專屬的 Windows Store App
這個部分與您開發可以上傳到微軟市集上的App的技術一樣,差別在於,您的App不需要透過微軟官方的測試與審核,因此,您需要自己透過內建工具來做App相容性的測試,與自己確保App的執行品質與效能。

不過,若是要將 LOB 類型的App透過側載的方式安裝到企業內部電腦上,您所開發的App,需要安裝與設定您企業內部發出的憑證,這個明證並不一定要在信任的憑證授權單位的跟目錄上,只要讓企業內部使用者的電腦可以信任該憑證即可。如果憑證來自於其中一個已經信任的授權單位,您就不需要在目標電腦上部署和管理額外的憑證。

另外要注意的是,若您開發的Windows 8.1 Store App有使用了 Windows 推播通知服務 (WNS) 等功能,則您需要使用 Windows 市集的儀表板,來為該應用程式保留名稱,並且要將您這個應用程式與市集上所指派的發行者名稱產生關聯,而且也要受到您電腦的信任。

如何將App的程式,自動佈署到使用者的電腦上
這裡有著許多來自於微軟的技術、甚至於還有很多第三方的產品可以選擇;微軟這裡也提供了一些需要付費或者免費的解決方案:Windows PowerShell, Microsoft Deployment Toolkit (MDT), System Center Configuration Manager, Windows Intune,至於這些功能是如何、甚至於如何運作,這需要請您們管理 AD Domain 的 IT 技術人員協助您來處理這些需求,畢竟這些範疇不是會寫程式的人,就會處理的。

如何將這些App程式,安裝到使用者電腦上
您企業內部的使用想要享受到側載的功能,必須是 Windows 8.1 Enterprise 企業版 或者是 Professional 專業版,並且要能夠加入網域;這樣您就可以透過群組原則 Group Policy 來設定這些電腦 網域群組原則物件 (GPO),可以接受並安裝,不是來自於市集的 Windows 8.1 Store App (允許安裝信任的應用程式)。

不過,若想要讓其他類型的Windows 8.1作業系統,例如 Windows RT 版本、Professional 專業版,您需要額外購買啟用可以側載的產品金鑰,以便進行企業側載。

要啟用側載產品金鑰,請以系統管理員權限,開啟命令提示字元,然後輸入下列命令來新增側載產品金鑰。

Slmgr /ipk <側載產品金鑰>

輸入下列命令來啟用側載金鑰:
slmgr /ato ec67814b-30e6-4a50-bf7b-d55daf729d1e

另外,我們還需要做到設定有開發人員授權的企業電腦

在電腦中,針對要套用群組原則設定的網域群組原則物件 (GPO) 開啟群組原則管理編輯器,如下方所指定。

  • 按一下以展開 [電腦設定]、[系統管理範本]、[Windows 元件] 及 [應用程式套件部署]。
  • 按兩下 [允許在沒有安裝開發人員授權情況下開發 Windows 市集應用程式] 設定。
  • 在 [允許在沒有安裝開發人員授權情況下開發 Windows 市集應用程式] 視窗中,按一下 [啟用],然後按一下 [確定]。
  • 按兩下 [允許安裝所有信任的應用程式] 設定。
  • 在 [允許安裝所有信任的應用程式] 視窗中,按一下 [啟用],然後按一下 [確定]。

將群組原則設定為允許在沒有安裝開發人員授權情況下開發 Windows 市集應用程式,下列登錄設定會更新為:HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\Appx\AllowDevelopmentWithoutDevLicense = 1
將群組原則設定成允許信任的應用程式後,會更新下列登錄設定:HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\Appx\AllowAllTrustedApps = 1

最後,可以使用 Windows PowerShell 或者任何支援執行 PowerShell指令碼或者Cmdlet的管理工具,在 PowerShell 命令提示字元中輸入底下文字,就可以進行您開發的App,並且側載到使用者電腦上了

add-appxpackage C:\YourEnterprise\YourStoreApp.appx

如何進行新版本的App升級
對於這個問題,是比較棘手的,若您的App是透過市集安裝的,使用者可以透過市集App來了解到他們已經從市集下載、安裝的App,有哪些App已經推出了新版本;使用者只需要透過市集App就可以直接升級這個App到最新版本。若是採用側載方式,則還是需要使用上述的方式來進行,並且我們可能也需要在App中,實作是否有新的版本推出機制。




如何在 Windows 8 App 中,使用 XAML 做到 Responsive 響應式 設計

現在一般網頁開發,大多需要具備Responsive Web Design (RWD) 響應式網頁設計,也就是,能自動針對不同 size 的裝置調整網頁最佳的呈現方式,讓使用者操作經驗更好。

若我們在進行 C# / XAML 的 Windows Phone App 開發的時候,也希望我們的頁面能夠根據手機的轉向,自動進行調整,不需要任何的 [後置程式碼] (Code Behind) C# 程式碼來支援,也就是不需要透過任何的事件來呼叫與執行任何 C# 程式碼,這樣的需求,我們應該要如何做到呢?

這樣的問題是許多第一次接觸 Windows Phone App 的開發者所必定會遇到的問題,讓我們來看看底下的範例說明,在這個範例中,我們有兩個按鈕與一個文字要顯示在同一行中,當手機的轉向是直式的時候,會呈現如下圖的樣貌;這兩個按鈕分別要存在於左右兩邊,文字則需要顯示在兩個按鈕之間,而且中間的文字需要依據當時手機解析度,自動調整最大寬度與高度之可以最多顯示文字。


若手機轉個90度,上述需求需要同時存在,不過,在橫式頁面上,文字可以顯示的寬度會變得更大,而且可以看到的文字字數應該要更多,如同下圖所顯示。


這樣的需求真的可以做到嗎? 我們來看看這個頁面的 XAML 定義。

<!--LayoutRoot 是放置所有頁面的根資料格-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
 
        <!--TitlePanel 包含應用程式的名稱和頁面標題-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="我的應用程式" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
            <TextBlock Text="頁面名稱" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>
 
        <!--ContentPanel - 其他內容置於此-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <!--在這使用 Grid 來將這三個控制項定義在-->
            <Grid Height="100" VerticalAlignment="Top" >
                <!--左邊的按鈕-->
                <Button HorizontalAlignment="Left">Add</Button>
 
                <!--中間的文字-->
                <TextBlock Text="這是要 顯示的 文字內容 這是要 顯示的 文字內容 這是要 顯示的 文字內容 這是要 顯示的 文字內容 這是要 顯示的 文字內容 這是要 顯示的 文字內容 " Margin="100,0,100,0" TextWrapping="Wrap"/>
 
                <!--右邊的按鈕-->
                <Button HorizontalAlignment="Right">Add</Button>
            </Grid>
        </Grid>
 
    </Grid>

我們將這三個控制項使用 Grid 面板(Panel)定義在其裡面,並且記得:
左邊的按鈕
需要使用 HorizontalAlignment="Left",設定該按鈕需要往左對其

右邊的按鈕
需要使用 HorizontalAlignment="Right" ,設定該按鈕需要往右對其

中間的文字
請使用 Margin="100,0,100,0" 設定左右的邊界各為100,目的是要保留文字的左右顯示邊界,不要蓋到按鈕;接著在 TextBlock 控制向上設定屬性 TextWrapping="Wrap" ,讓 TextBlock 根據當時可用的空間,顯示出最多的文字。

這樣就可以做到 [響應式] (Responsive) 的 Windows Phone App 頁面設計技巧了。

若每次要測試手機轉向 直式 / 橫式 的執行結果,都要透過執行程式才能夠看到最後結果,那麼,您對於 Windows Phone 開發工具必定不是十分孰悉,記得這句話,若是可以在設計模式下就可以看到的結果,就要讓您的設計內容可以於設計模式下看到每個頁面的最後執行結果,不需要等到執行時期才能夠看到。(也許您會問說,這樣會有問題,有些頁面上面有許多控制項,裡面的資料需要等到執行時期才能夠透過 C# 程式透過本地檔案或者從網路抓取才能夠讀取出來,並且顯示在頁面上,例如,圖片檔案,JSON內容;不用擔心,您只需要學會設計時期的範例資料的功能,就可以讓您的App的每個頁面,在設計時期的時候,模擬出需要再執行時期才能夠看到的資料,這樣不但可以加入您的程式開發時程,而且可以讓您在設計時期,就可以知道未來執行後的每個頁面真實的樣貌,我會另外寫篇文章告訴大家如何做到這樣的需求)

請在您的 Visual Studio (或者 Blend (這是個好東西,想要成為 Windows Phone 開發專家,一定要學會 Blend) ),使用 [裝置] 視窗來調整您設計時期的頁面螢幕轉向,如下圖所示的紅色方框,左邊的圖示就是讓您的設計時期的手機螢幕轉向成為橫式,而右邊的圖示,就是可以將您設計時期的頁面轉向成為直式。








2014/06/26

在WinRT下,如何取得圖片檔案的內容或者該圖片的縮圖

往往當把圖片檔案儲存到本機的獨立儲存空間 (Isolated Storage),之後想要顯示該圖片,不過,有些時候這些圖片檔案可能會很大,而我們這個時候只想要顯示這些圖片的縮圖大小,作為讓使用者可以快速大量瀏覽或者選取之用,而不想要取得全尺寸的圖片。

這個時候,就可以用到這兩個方法:

StorageFile.GetThumbnailAsync(ThumbnailMode, UInt32, ThumbnailOptions)
依據縮圖的用途、要求的大小以及指定的選項,擷取檔案經過調整的縮圖影像。

StorageFile.GetScaledImageAsThumbnailAsync(ThumbnailMode, UInt32, ThumbnailOptions)
依據縮圖的用途、要求的大小和指定選項,取得縮放影像做為縮圖。

經過這樣的處理,我們就不再需要取得全尺寸的圖片資源,並且透過 XAML 設定來幫我們做圖片的縮放顯示處理,這樣可以大幅提升整體App的運作速度,當您要處理顯示很多圖片的時候,這是個不錯的優化改善方法。

如何針對 StorageFile物件把它關閉起來

一般我們在處理檔案的時候,若不再需要使用該檔案,就需要將這個資源關閉起來,可是,為什麼 StorageFile物件裡面,卻沒有任何關於 Close 這樣的輔助方法呢?

理由很簡單,因為,StorageFile 只是個抽象的路徑名稱,用來代表檔案系統中的某個檔案,也就是說,當您取得了 StorageFile物件後,例如,使用 StorageFolder.GetFileAsync (使用指定的檔案名稱來取得目前資料夾中的單一檔案。)來取得一個 StorageFile 物件,並不代表了這個檔案已經被開啟並且被鎖住了,這個 StorageFile 物件僅僅只是提供了一個參考到這個檔案的資訊而已。

若您實際取得該StorageFile的資料流(Stream),則您才是開始針對該檔案進行存取動作的開始,不過,當對於該檔案的資料流處理動作完成後,記得要將該資料流做關閉(Close)和 Dispose的動作。

您可以依據您的需求,參考底下四種方法,取得您所需求的資料流
StorageFile.OpenAsync 透過檔案開啟隨機存取資料流。

StorageFile.OpenReadAsync 透過目前的檔案開啟隨機存取資料流來讀取檔案內容。

StorageFile.OpenSequentialReadAsync 透過目前的檔案開啟循序存取資料流來讀取檔案內容。

StorageFile.OpenTransactedWriteAsync 開啟可用於異動寫入作業之檔案的隨機存取資料流。

StorageFile storageFile =
      await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(uri);

    var randomAccessStream = await storageFile.OpenReadAsync();
    Stream stream = randomAccessStream.AsStreamForRead();

在WinRT中,有沒有比較輕鬆容易的處理檔案解決方案

當我們在WinRT系統中,想要處理檔案動作,需要透過 StorageFolder取得一個StorageFile,接著要使用相對應的資料流開啟StorageFile指向的檔案,處理完成後,還要關閉與釋放這個資料流,真的有點繁瑣。

我們可以透過 FileIO Class ( 提供協助程式方法用於讀取和寫入檔案,這些檔案是由IStorageFile型別的物件所表示 ) 類別 與 PathIO Class ( 提供 Helper 方法,以使用絕對檔案路徑或 URI 來讀取和寫入檔案 ),來簡化後半段的動作;例如,我們只想針對該檔案讀取所有的文字內容或者將字串寫入到檔案內。

try
{
    if (file != null)
    {
        string fileContent = await PathIO.ReadTextAsync(filePathOrURI);
    }
}
// Handle errors with catch blocks
catch (FileNotFoundException)
{
    // For example, handle file not found
}

在範例中,filePathOrURI 是區域變數,其包含要讀取之檔案的 URI (例如應用程式 URI "ms-appdata://sampleFile.dat") 或檔案系統路徑 (例如 C:\examplepath\sampleFile.dat)。
在 readTextAsync 完成之後,fileContent 變數會取得檔案的內容做為文字字串。接著您可以依適合的情況處理內容。

關於實際更多用法,您可以參考 檔案存取範例

2014/06/25

在WinRT下,如何使用 StorageFile物件,設定該檔案為唯讀

若您有這樣的需求,想要將某個在 Isolated Storage 內的檔案,設定成為唯讀的屬性,此時,您會需要用到:

StorageFile.Properties
取得物件,用以存取檔案的內容相關屬性。

當取得了 StorageFile.Properties屬性後,他是個屬於 StorageItemContentProperties 類型的物件,代表了 提供檔案之內容相關屬性存取權的物件。

參考下列程式碼,您可以設定檔案為唯讀屬性

String key = "System.FileAttributes";
UInt32 FILE_ATTRIBUTES_READONLY = 1;
var pix = Windows.Storage.KnownFolders.PicturesLibrary;

var file = await pix.GetFileAsync("test.jpg");
String[] retrieveList = new String[] { key };

var props = await file.Properties.RetrievePropertiesAsync(retrieveList);

if (props != null)
{
    var temp = (UInt32)props[key] | FILE_ATTRIBUTES_READONLY;
    props[key] = temp;
}
else
{
    props = new Windows.Foundation.Collections.PropertySet();
    props.Add(key, FILE_ATTRIBUTES_READONLY);
}

await file.Properties.SavePropertiesAsync(props);

不需要經由使用者同意,就可以 WinRT App 存取的檔案系統有哪些?

這是個相當不錯的問題,其實我自己也花了不少時間,才逐步清楚這樣的狀況,尤其是在我要取得 [MCSD: Windows Store Apps Using C# 認證] 的時候,必須要對這樣的情境十分孰悉。

原則上,不需要經過使用者同意,而App可以存取的檔案系統只有 套件資料夾 (Package Folder)與應用程式資料資料夾( App Data Folder),若想要存取本機中的 照片、影片、我的文件資料夾,則您需要設定相對應的功能 (Capability),否則,當您存取這些檔案系統的時候,就會產生錯誤。

其中,
套件資料夾 (Package Folder)
可以透過取得 Windows.ApplicationModel.Package.Current.InstalledLocation StorageFolder物件,例如,您可能要針對該App做到可以內建在 OEM 的機器上,並且要存取 StoreManifest.xml 或者 自訂資料 (Custom Data)檔案,這個 StorageFolder 是指向了您的App實際安裝在本機上的目錄路徑。

應用程式資料資料夾( App Data Folder)
Windows.Storage.ApplicationData 是提供對應用程式資料存放區的存取。 應用程式資料是由本機、漫遊或暫時的檔案與設定所組成。
可以該類別透過取得 Windows.Storage.ApplicationData 中的 LocalFolder, RoamingFolder, TemporaryFolder 這三個屬性。

ApplicationData.LocalFolder 取得本機應用程式資料存放區中的根資料夾。
ApplicationData.RoamingFolder 取得漫遊應用程式資料存放區中的根資料夾。
ApplicationData.TemporaryFolder 取得暫存應用程式資料存放區中的根資料夾。

應用程式資料有三個主要類型:
本機:儲存在裝置上,並且跨更新保存。
漫遊:已複製到使用者安裝應用程式的其他裝置。
暫存:隨時可以由系統刪除。

當然,透過應用程式資料資料夾,也可以存取到本機或者漫遊的應用程式設定容器物件。
ApplicationData.LocalSettings 取得本機應用程式資料存放區中的應用程式設定容器。
ApplicationData.RoamingSettings 取得漫遊應用程式資料存放區中的應用程式設定容器。

存取該App中的任何打包的檔案,此時,您就會需要使用到這個套件資料夾,不過,您需要使用 Visual Studio 2013來設定這些資源檔案的類型屬於內容(Content)形式,並且還要設定複製到輸出資料夾內。