利用 DataContractJsonSerializer 實現物件序列化與反序列化

12/21/2009
DataContractJsonSerializer 類別是 .NET Framework 3.5 的新成員,它可以用來將物件序列化成 JSON 格式的字串,或者執行反序列化,也就是根據 JSON 格式的字串內容來建立物件,並還原物件的狀態。

亂碼 1/2:Unicode 字元不要用 char 型別來處理

12/16/2009
最近在處理一些中文字的問題時,發現一個已經用了兩年多的程式,碰到一些特別罕見的中文字就無法正確執行。當初寫這個程式時,只有測試一般的 Unicode 字元,而沒有考慮到那些特別罕見的中文字。試看這個例子:

string str = "風";
char ch = s[0];
MessageBox.Show(ch.ToString());

不意外,畫面顯示的結果是 "風"。如果用 str.Length 來取字串長度,得到的結果也是預料中的 1。

對於一般常見或「稍微罕見」的中文字,上面的寫法並不會有問題。但如果碰到特別罕見的中文字就會出狀況了,例如這個:

string str = "𩗴";
char ch = str[0];
MessageBox.Show(ch.ToString());

輸出的結果是.....亂碼。



由於 Unicode 的總字數超過 65536 個字元,有些罕見字的編碼會超過 2 bytes,例如此例的「𩗴」(讀作四聲「ㄅㄥˋ」),這個字的編碼佔 4 bytes,若使用 str[0] 的方式取出第一個字元,就會只抓到整個 Unicode 字元的一半,因而出現亂碼--姑且叫它亂碼 1/2 :p (此例的 str.Length 是多少?)

有關 surrogate pairs 和 combining character sequences 的說明,這裡就偷懶跳過,寫程式時只需牢記:在 .NET 裡面,Unicode 字元必須以字串的方式處理

因此,前面的範例應該改成這樣:

string str = "𩗴";
string ch = StringInfo.GetNextTextElement(str);
MessageBox.Show(ch);

StringInfo 類別隸屬 System.Globalization 命名空間,其 GetNextTextElement 方法可以傳回第一個 Unicode 字元(注意型別是 string),或傳回特定索引位置的字元。詳細用法請參考 MSDN 線上文件

註:這篇的 "𩗴" 字,在網頁上輸入時,是寫成:
  𩗴
  這個數字可以經由呼叫 Char.ConvertToUtf32("𩗴") 得到。

在 Windows 7 上安裝 VS2008 SP1 失敗:vsvars32.bat 無法寫入

12/10/2009
終於把家裡和辦公室的電腦升級完畢,分別裝了 Windows 2008 和 Windows 7。Windows 2008 的部分很順利,但是 Windows 7,在安裝 Visual Studio 2008 SP1 英文版的時候卻失敗了。

我到 VS2008 SP1 安裝光碟的 vs90sp1 目錄下手動執行各個安裝程式,順序是:
  1. VC_x86Runtime.exe
  2. WebDesignerCore_KB945140.msp
  3. WebDesignerCore_KB950278.msp
  4. WinSDK-KB946729.msp
  5. WinSDK-KB946733-enu.msp
  6. WinSDK-KB950424.msp
  7. vstor30sp1-KB949258-x86.msp
  8. VS90sp1-KB945140-X86-ENU.msp (主要是這個)
  9. VC90sp1-KB947888-x86-enu.msp
執行到 VS90sp1-KB945140-X86-ENU.msp 時出現錯誤:

Error 32003. File 'C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\vsvars32.bat' could not be opened for write.

並且問你要 Retry 還是 Cancel,此時你可以立刻修改 Tools 資料夾的安全性:開啟 Tools 資料夾的內容,切到「安全性」頁籤,讓 TrustedInstaller(或者你目前登入的使用者帳戶)有寫入權限。參考下圖:



檔案權限改好之後,再回到剛才的錯誤訊息對話窗按「Retry」就可以繼續完成安裝程序。

Crystal Reports 的網頁列印對話窗無法列印

12/10/2009
這個問題已經是 FAQ 了,我自己也一再碰到,實在很煩人。

問題描述

環境:ASP.NET + Crystal Reports XI R2 SP4 + IE 8.0

Web 應用程式使用 Crystal Reports 來列印報表,當使用者在 CR viewer 視窗中點列印鈕時,新開啟的列印對話窗會掛掉,裡面一片空白,如下圖:



以下是解決此問題的幾個方法,碰到難纏的狀況時,不妨全都用上。

Web.config 裡面加入設定

參考這篇官方文件:
http://devlibrary.businessobjects.com/businessobjectsxir2/en/en/CrystalReports_dotNET_SDK/crsdk_net_doc/doc/crsdk_net_doc/html/crconfeatureprinting.htm

注意裡面的 http://myserver/PrintControl.cab 要改成你的網站 URL。


[2010-4-19] 註:Crystal Reports XI SP 5 的壓縮檔解開後,在 win32\m151.cab 這個壓縮檔裡面藏有 PrintControl.cab 和 PrintControl.dll。

自己打包 PrintControl.dll

PrintControl.dll 可以在這裡找到:
C:\Program Files\Business Objects\Common\3.5\crystalreportviewers115\ActiveXControls\

你可以利用安裝程式製作工具(例如 InnoSetup)把這個 DLL 檔案包起來,並且在安裝時自動註冊 DLL(利用 regsvr32.exe)。以下是我的 InnoSetup 安裝腳本:

[Run]
Filename: regsvr32.exe; Parameters: /s PrintControl.dll; WorkingDir: {sys}
[Setup]
AppName=Crystal Reports 報表預覽元件 (CR11 SP4)
CreateAppDir=false
DisableProgramGroupPage=true
UsePreviousGroup=false
DisableReadyMemo=true
AlwaysShowComponentsList=false
ShowLanguageDialog=auto
Uninstallable=false
AppVerName=11.0
LanguageDetectionMethod=locale
DisableStartupPrompt=false
OutputBaseFilename=SetupPrintControl
[Files]
Source: PrintControl.dll; DestDir: {sys}
[LangOptions]
LanguageName=Chinese
LanguageID=$0404
[Languages]
Name: ChineseTraditional; MessagesFile: compiler:Languages\ChineseTrad-2-5.1.11.isl

如果要使用上述安裝腳本,可以將它們複製到記事本,儲存成 SetupPrintControl.iss,再以 InnoSetup 編譯即可。安裝程式建立完成之後,便可以放在網站上讓使用者自行下載安裝。

調整用戶端的 IE 安全性設定

即使前面兩項都做過了,ActiveX 控制項還是可能被 IE 擋住而無法執行。而且,就算把「網際網路」區域的安全性都調到最寬鬆的設定(所有 ActiveX 都給它啟用),問題可能還是無法解決。碰到這種狀況,可以試試看把你的網站加入 IE 的信任網站(前兩個方法再加上這個動作才真正解決了我的問題)。

考慮有些使用者可能不知道如何設定 IE 的安全性,也可以寫個小程式或 script 幫使用者自動設定 IE。參考這篇文章的做法:How Can I Add a Site to Internet Explorer's Restricted Sites Zone?


註:Crystal Reports viewer 的 Web 應用程式名稱為 "crystalreportsviewer115",路徑指向 C:\Program Files\Business Objects\Common\3.5\crystalreportviewers115。
技術提供:Blogger.