2008-12-27

Unable to load DLL 'sqlceme35.dll'

在下載 Visual Studio Team System 2008 Database Edition GDR 安裝在我的 Vista x64 上之後, 竟然沒辦法建立 Database 專案, 在新增專案的時候, 出現了如下圖的錯誤訊息!

image

搜尋了一下電腦並沒有發現這個檔案, 從名字看起來應該是和 SQL Compact Edition 有關, 可是又無從得知是哪一個套件含有這個檔案, 只好猜猜看了, 和 SQL CE 相關的套件有分 ServerTools, DesignTools, Runtime 三種, 而且又有區分 x86 和 x64 的平台, 而且還得要是 SP1 的版本才行, 實驗了一下後發現 Microsoft SQL Server Compact 3.5 SP1 是 Runtime 套件, Microsoft SQL Server Compact 3.5 SP1 Design Tools 當然就是 DesignTools 套件啦, 至於 ServerTools 我的電腦本並沒有安裝, 所以不管它!

經過一番折騰之後, 原來是我的 Runtime 安裝有問題, 移除後重新安裝就 OK 了!

反正就是 C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v3.5\sqlceme35.dll 檔案要存在就對了! 雖然覺得奇怪, 但現在也無法追究是什麼原因導致它不見的了!

keywords: sqlceme35, sql 2008

Safari 和 ASP.NET Menu 控制項

早在 ASP.NET 剛推出之時就一直強調能夠適應不同的用戶端產出對應的 Markup Code, 可是沒想到 Menu 控制項在 Safari 卻出了問題, 看了一下產出的網頁原始碼, 發現產出的 HTML 不一樣, 當時的第一個直覺反應是想到 ASP.NET CSS Friendly Control Adapter 專案, 應該和它有關, 一定是套用到了不同的 ControlAdapter 才會產出不同的 HTML, 所以如果要解決這個的問題, 應該也可以採用和它相同的技巧才對!

找到 %SystemRoot%\Microsoft.NET\Framework\v2.0.50727\CONFIG\Browsers 資料夾底下的 mozilla.browser 檔案, 裡面明白的寫著

image

就因為那個 controlAdapter 導致 Safari 在產出 Menu 的 HTML 時不如預期, 解決的方法也很簡單, 只要在網站下新增一個 App_Browser 的資夾, 在裡頭新增一個叫 safari.browser 的檔案, 然後在裡頭再一次的 override 掉原來的設定就行了!

<browsers>
    <browser refID="Safari1Plus">
        <capabilities>
            <capability name="xml" value="true" />
        </capabilities>
        <controlAdapters>
            <adapter controlType="System.Web.UI.WebControls.Menu" adapterType="" />
        </controlAdapters>
    </browser>
</browsers>

keywords: safari, controlAdapter, asp.net, Menu

2008-10-04

解決 ADO.NET Data Services 搭配 LINQ to SQL Classes 的問題

在 MSDN 或是網上看到的 ADO.NET Data Services 範例通常都是搭配 ADO.NET Entity Data Model 來展示, 比較少看到使用 LINQ to SQL Classes 的案例, 後來自己試了一下, 才發現原來是因為使用 LINQ to SQL Classes 會有一些小問題, 就是 Table 的 Key 必需要符合 {TableName}ID 的命名原則, 否則就會產生如下圖的伺服器例外, 但如果是使用 ADO.NET Entity Data Model 的話就不會有這樣的問題!

image

 

要解決這個問題是有方法的, 一是打開 .dbml 檔將類別的屬性名稱改成 TableNameID 的格式, 但是這樣好像有點笨, 僅適合用在剛開始開發的階段, 否則光測試就要人命了, 另一種解決方案比較優, 是利用 System.Data.Services.Common.DataServiceKeyAttribute 這個特徵項來標記每個 Table 相關的 partial lass, 如以下的範例:

[DataServiceKey("CustomerID")]
public partial class Customers { }

建議有類似問題的人可以自己新建一個 .cs 檔, 把它和 .dbml 放在一起, 並用類似的命名讓它們在 Solution Browser 裡可以很容易的就被看到, 像是 Northwind.DataServiceKey.cs 之類的, 然後在裡面統一管理所有的 Table classes, 替每個 Table class 加上 DataServiceKey 的特徵項, 這樣子未來才比較好管理! 如果有其他定義 partial method 的需要, 最好再另外建立一個 partial class 檔案來管理, 才不會影響到原來單純的 DataService 定義! 嗯~從這個例子剛好可以實際體會 partial class 在管理上所帶來的好處, 當然前提是命名方式和檔案存放的位罝要先自己規劃好才能享受到它所帶來的好處, 否則打散的類別反而更難了解.

附帶一提, 所有的 Table 都必需要有 key, 如果沒有的話 ADO.NET Data Services 就無法正常運作, 一般來說有經驗的 DBA 是比較不會建立一張沒有 key 的資料表的吧!

其實這個機械式的動作應該由 Visual Studio 幫開發人員處理掉才對, 而不是把這種冗長又容易出錯的工作留給開發人員去處理, 我想 Microsoft 應該也知道這點, 只是可能因為時程或是其他因素而沒有處理到吧!

反正實作上也不會太複雜, 如果有需要的話乾脆就自己寫一小段程式去產生相關的程式碼就可以了, 一時興起寫了兩個版本, 一個使用一般的寫法, 另一個使用 LINQ 的寫法, 很明顯的 LINQ 的語法自然又簡潔多了, 如下:

一般版:

private static void GenerateDataServiceKeyAttributePartialClasses(Assembly asm, StringBuilder sb)
{
    Type[] types = asm.GetTypes();
    foreach (Type t in types)
    {
        object[] attrs = t.GetCustomAttributes(typeof(TableAttribute), true);
        if (attrs.Length == 0) continue;

        List<string> keys = new List<string>();

        PropertyInfo[] pis = t.GetProperties();
        foreach (PropertyInfo pi in pis)
        {
            object[] propAttrs = pi.GetCustomAttributes(typeof(ColumnAttribute), true);
            if (propAttrs.Length == 0) continue;

            if (((ColumnAttribute)propAttrs[0]).IsPrimaryKey)
            {
                keys.Add(pi.Name);
            }
        }
        sb.AppendFormat("\r\n[DataServiceKey(\"{0}\")]\r\n", String.Join(@""", """, keys.ToArray()));
        sb.AppendFormat("public partial class {0} {{ }}\r\n", t.Name);
    }
}

LINQ 版:

private static void GenerateDataServiceKeyAttributePartialClass(Assembly assembly, TextWriter writer)
{
    var tableInfoList = from t in assembly.GetTypes()
                        where t.GetCustomAttributes(typeof(TableAttribute), true).Length == 1
                        select new
                        {
                            TypeName = t.Name,
                            KeyFields = (from p in t.GetProperties()
                                         let columns = p.GetCustomAttributes(typeof(ColumnAttribute), true)
                                         where columns.Length == 1 && ((ColumnAttribute)columns[0]).IsPrimaryKey
                                         select p.Name).ToList()
                        };

    writer.Write("using System.Data.Services.Common;\r\n\r\n");
    foreach (var info in tableInfoList)
    {
        writer.Write("\r\n[DataServiceKey(\"{0}\")]\r\n", String.Join(@""", """, info.KeyFields.ToArray()));
        writer.Write("public partial class {0} {{ }}\r\n", info.TypeName);
    }
}

 

keywords: ado.net, data services

2008-09-27

巢狀 using 排版

原來的格式

using (Rijndael aes = RijndaelManaged.Create())
{
    using (ICryptoTransform cryptor = aes.CreateEncryptor(rgbKey, rgbIV))
    {
        using (CryptoStream cs = new CryptoStream(output, cryptor, CryptoStreamMode.Write))
        {
            byte[] buf = new byte[8192];
            for (int len = 0; (len = input.Read(buf, 0, buf.Length)) > 0; )
            {
                cs.Write(buf, 0, len);
            }
        }
    }
}

調整後的格式

using (Rijndael aes = RijndaelManaged.Create())
using (ICryptoTransform cryptor = aes.CreateEncryptor(rgbKey, rgbIV))
using (CryptoStream cs = new CryptoStream(output, cryptor, CryptoStreamMode.Write))
{
    byte[] buf = new byte[8192];
    for (int len = 0; (len = input.Read(buf, 0, buf.Length)) > 0; )
    {
        cs.Write(buf, 0, len);
    }
}

調整後的程式是不是比較美呢!

 

keywords: c#, coding style

Change default code access security policy with caspol.exe

為了解決讓網頁中的 .NET 元件能夠存取剪貼簿問題, 需要做兩件事, 第一件是先將該網站加入信任網站列表, 第二件是調整 .NET Framework 針對信任網站的預設安全性, 要從 Low Trust 調整為 Medium Trust

第一件事比較簡單, 就略過不提, 第二件事就比較複雜一點, 如果 user 的電腦有裝 .NET Framework SDK 的話(通常是不太可能) 還可以透過系統管理工具裡面的 Microsoft .NET Framework 2.0 Configuration Tool 來調整, 否則的話, 最快最簡單的方式就是透過 caspol.exe 這個 .NET Framework 2.0 提供的指令來完成, 如下:

變更 Trusted 站台預設的安全性為 LocalIntranet - Medium Trust (預設為 Internet - Low Trust)

%WINDIR%\Microsoft.NET\Framework\v2.0.50727\caspol.exe -pp off -m -cg Trusted_Zone LocalIntranet

如果反悔想重設為系統原始設定的話, 可以使用以下指令

%WINDIR%\Microsoft.NET\Framework\v2.0.50727\caspol.exe -pp off -a -reset

 

keywords: .net, security, caspol

Enable trace log of HttpWebRequest

之前為了解決一個 .NET 1.1 的 HttpWebRequest.KeepAlive 屬性所造成的 Proxy-Authenticate 失敗問題, 在尋找答案的過程中不小心又多學到一招關於 .NET 內建的 Trace 功能, 其實早在很久以前就曾經用 Reflector 在 System.Net 下面的類別中看到一些和 Log 有關的程式碼, 只是那時候沒有多去注意該怎麼把那些 Log 資訊顯示出來, 這次碰巧看到, 順便記錄一下!!

啟用 Log 的方式就是仿照以下的格式修改 config 檔, 針對想要觀看 Log 的類別調整一下注解即可! 要注意的是記得在正式出貨前關閉此 Log, 否則效率會很差!

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <system.diagnostics>
        <trace autoflush="true" />

        <sharedListeners>
            <add name="MyTraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="System.Net.trace.log" />
        </sharedListeners>

        <sources>
            <!--
            <source name="System.Net" maxdatasize="1024">
                <listeners>
                    <add name="MyTraceFile"/>
                </listeners>
            </source>
            <source name="System.Net.Sockets" maxdatasize="1024">
                <listeners>
                    <add name="MyTraceFile"/>
                </listeners>
            </source>
            <source name="System.Net.Cache">
                <listeners>
                    <add name="MyTraceFile"/>
                </listeners>
            </source>
            <source name="System.Net.HttpListener">
                <listeners>
                    <add name="MyTraceFile"/>
                </listeners>
            </source>
            -->
        </sources>

        <switches>
            <!--
            <add name="System.Net" value="Verbose" />
            <add name="System.Net.Sockets" value="Verbose" />
            <add name="System.Net.Cache" value="Verbose" />
            <add name="System.Net.HttpListener" value="Verbose" />
            -->
        </switches>
    </system.diagnostics>
</configuration> 

 

keywords: trace, .net, webrequest

2008-08-31

Enable FILESTREAM Feature in SQL 2008

如果在安裝的時候沒有 Enable FILESTREAM 功能的話, 可以在安裝完後, 按以下步驟執行:

image

image

image .

最後再執行以下句子就可以了!

EXEC sys.sp_configure N'filestream access level', N'0'
GO
RECONFIGURE WITH OVERRIDE
GO

keywords: sqlserver, sql2008, FILESTREAM

.NET 1.1 WebRequest KeepAlive 和 WebProxy.Credentials 的奇怪現象

發生在一個 .NET 1.1 的 App 上的問題, 簡化後的程式碼如下:

HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.KeepAlive = false;

request.Proxy = new WebProxy(proxyServer);
request.Proxy.Credentials = new NetworkCredential(userName, password);

HttpWebResponse response = request.GetResponse() as HttpWebResponse;
response.Close();

因為某種原因, 在一開始時刻意將 KeepAlive 屬性設為 false, 導致了這個奇怪現象的發生, 而且只會在 .NET 1.1 底下發生! 症狀是如果 KeepAlive 設為 false 的話, 就會丟出 407 Proxy Authentication Required 的例外, 可是同樣的程式在自家的環境內卻又測不出問題, 所以初步研判應該是 Proxy server 不同的原因所造成, 如果是在 Microsoft ISA Server 的環境中就會發生, 而在 Squid Proxy Server 則沒有這個問題, 這是什麼道理咧?!

道理說穿了很簡單, 因為 Squid Proxy Server 是採用 Basic 的驗證方式, 而 ISA Server 預設卻是 challenge-response 的驗證機制, Basic 的驗證方式是將帳號密碼以 base64 的方式編碼傳送出去, 所以和 server 不需要保持連線, 但是 challenge-response 則必需要保持連線才可以進行驗證, 這就是為什麼當 HttpWebRequest 的 KeepAlive 設成 false 的時候, 在 ISA Server 的環境一直驗證失敗的原因! 而 .NET 2.0 之所以不會發生這個問題是因為有針對這個情況做特別處理, 也就是在進行 challenge-response 驗證時, 會自動將 Proxy-Connection 的 Header 設為 Keep-Alive, 待驗證過後才再設為 Close, 所以不會出問題!

相關知識可以參考 Authentication in WinHttp, Challenge-response authentication 和一篇寫的很詳細的 blog 文章 WebProxy.Credentials does not work when KeepAlive = false in .NET 1.1

keywords: httpwebrequest, proxy, credentials, keepalive

SQL Server 2008 沒有 Surface Area Configuration Tool

好不容易等到 VS2008 SP1 出來, 終於可以順利安裝完 SQL 2008, 卻發現原來在 SQL 2005 內的兩個工具不見了, 它們是:

  • Surface Area Configuration for Services and Connections
  • Surface Area Configuration for Features

它們通常一個是用來設定開放外部電腦透過 TCP/IP 連線, 一個是用來開啟 clr 或是 database mail 的功能用的, 到了 SQL 2008 這個兩個工具都消失了, 那該怎麼做相關的設定呢?

關於第一個 Services and Connections 的設定, 現在可以在 SQL Server Configuration Manager 這個新工具中進行設定, 像 TCP/IP 的設定就可以在 SQL Server Network Configuration\Protocols for [MSSQLSERVER] (<--這個是 instance name) 底下找到!

至於第二個 Features 的設定, 則被移到了 SQL Server Management Studio (SSMS) 去了, 在 Server 上點右鍵, 打開 Facets, 視窗上方會有一個 Facet: 下拉選單, 選到 Surface Area Configuration 之後, 就會看到熟悉的選項了, 如圖:

image

keywords: sqlserver, sql2008, sac, surface area configuration

2008-08-09

透過 FontFamily.GetName 取得特定語系的字型名稱

一個簡單的列舉就可以找出系統內字型的特定語系名稱:

foreach (FontFamily f in FontFamily.Families)
{
    Console.WriteLine(f.GetName(0) + ":" + f.GetName(0x409));
}

在尋找答案的過程, 意外的多學了幾個關於 LanguageID 的小知識, 原來 language ID 是一個 16 bit 的值, 由兩個部分組成, primary language ID 和 secondary language ID, 結構示意圖如下:

image

其中 Sublanguage ID 僅佔了 6 bits, 一閞始困為沒注意到所以導致計算的結果有誤, 後來仔細看才發現原來兩部份的長度是不同的, 舉個實例來說明一下:

//  winnt.h
//
//  Primary language IDs.
#define LANG_CHINESE                     0x04
//
//  Sublanguage IDs.
#define SUBLANG_CHINESE_TRADITIONAL      0x01    // Chinese (Taiwan)

所以 Traditional Chinese 的 language ID 就等於 0x01 << 10 | 0x04 = 0x404

再繼續往下讀 winnt.h, 又出現了一個叫 locale ID 的東西, 順便也記一下!
image 
keywords: font, LanguageID, localeID

使用 ADO.NET 接回 SQL Server 的 PRINT Message

常看到有人被這個問題困擾, 自己以前也曾經被這個問題所苦, 可是其實這個問題是很容易解的, 看範例:

using (SqlConnection conn = new SqlConnection("Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=SSPI"))
{
    conn.InfoMessage += new SqlInfoMessageEventHandler(SqlConnection_InfoMessage);

    conn.Open();
    SqlCommand cmd = conn.CreateCommand();
    cmd.CommandText = "DBCC CHECKIDENT ('HumanResources.Employee', NORESEED)";
    cmd.ExecuteNonQuery();
}

重點就是 SqlConnection.InfoMessage 事件, 可以在事件處理函式中以 e.Message 取得 SQL Server 所輸出的訊息!

順便介紹一個 DBCC 指令 "DBCC CHECKIDENT", 這個指令是用來檢視指定 Table 內有使用自動遞增欄位目前的值, 有需要知道或是想要重設序號為某一個新值的人可以參考該指令的用法!

SQL Server 2008 RTM 出現了

今天在逛微軟網站的時候, 突然發現上週還是 RC0 版本的 SQL Server 2008 的下載連結, RC0 的字樣不見了, 原本預計 7/31 發行的 RTM 版本, 在 8/6 出現在 MSDN 的下載區, 想要嚐鮮的朋友們可以去下載 180 天的試用版來玩玩了!

2008-07-26

用 JavaScript 複製網頁上的圖片到剪貼簿

在 IE 中很簡單就能辦到, 至於其他的瀏覽器......目前還沒這個需求, 先擱著~~~~~

var img = document.getElementsByTagName("IMG")[0];
var rng = document.body.createControlRange();
rng.add(img);
rng.execCommand('Copy');
真是簡單到不行! 可以看出 Microsoft 當初那群規劃設計 IE 的人實在是太厲害了!!
Keywords: clipboard, ie, copy image, javascript

變更 ChartFX 7.0 的輸出路徑

ChartFX 是一個很強大的圖表軟體, 特別是到了 2005 的版本之後, 運用了 DHTML 和 AJAX 的技術, 讓原先要透過安裝 ActiveX 才能達到的效果, 也可以直接在網頁上呈現, 而且互動性也像 ActiveX 一樣的好, 但是代價就是要多付出一些 server 和 client 之間資料的來回傳送!

在實際使用 ChartFX 7.0 開發 Web App 的時候,  發現了一個現象, 就是如果透過 Visual Studio 內建的 WebDev.WebServer.exe 啟動的話, ChartFX 的暫存檔會輸出到 ~/chartfx70/temp/ 底下, 可是當佈署到 IIS 之後, 它會在 WebSite 的根目錄下建立一個 /chartfx70 虛擬目錄, 這時候如果透過 ISA 將內部網站發佈出去的話, 除了要開放該 Web 應用程式的路徑之外, 就還要再多開放一個 /chartfx70 的路徑, 外部的人才可以順利的取得 chart 的內容, 雖然動作不難, 但是還要動到 ISA 的設定也是有點不方便, 所以才想找個方法讓 chartfx 的輸出路徑改變一下!

在 google 上找了很久, 其實沒有找到答案, 但是有找到一點點看起來不太像的線索, 最後還是透過 Reflector 才搞定了這個問題!!

image

正確的步驟就是在 ~/bin 資料夾 ChartFX.WebForms.dll 的所在位置建立一個名為 ChartFX.WebForms.config 檔案, 然後填入以下內容, 並視需要修改其中 Relative 和 Absolute 的值就行了, 至於這兩個節點的內容應該很容易了解, 分別是相對路徑和實體路徑!!

<chartfx>
    <DefaultHandler>ChartFX.WebForms.Internal.OutputFileHandler,ChartFX.WebForms</DefaultHandler>
    <FileOutput>
        <Relative>/Web1/chartfx70</Relative>
        <Absolute>D:\Web1\chartfx70</Absolute>
    </FileOutput>
</chartfx>

/CCITTFaxDecode /ASCII85Decode /DCTDecode

為了要擷取出內嵌在 PDF 檔中的影像, 稍微研究了一下 PDF 的規格, 一開始的目的是要解出其中的 TIFF 檔, 看起來好像挺簡單的, 因為從 PDF 中可以很容易的就把 TIFF 的 stream 取出來 (找到 /Filter /CCITTFaxDecode 的區段, 後續出現被包在 stream.....endstream 中的就是了), 但是結果當然並不是把那段 stream 存檔這麼簡單就行了, 因為 TIFF 本身還有一些檔頭和檔尾資訊必須處理, 所以又得再花精神去研究 TIFF 的規格(TIFF 6.0 Specification).....然後依據 pdf object 的描述自行寫入相關的檔頭和檔尾就可以了(看起來還滿簡單的吧)!

檔頭的部分很簡單, 因為只有 8 個 bytes, 很容易理解, 麻煩的是後面檔尾部分的 IFD (Image File Directory), 那是和 TIFF 內容相關的一些描述, 必須正確的寫入才能看到完整的 TIFF 呈現出來, 細節說來話長, 就先跳過吧, 附上一張簡單的示意圖(擷取自 TIFF 6.0 Specification)!

image 

第一個需求完成之後, 很快的就產生了第二個需求, 因為在 PDF 中除了有 TIFF 之外, 還有 JPG 格式的影像在裡面, 擷取 PDF 影像的功能算只完成了一半, 已經不能回頭了, 只能再繼續前進! 這次遇到的 /Filter 是 [ /ASCII85Decode /DCTDecode ], 這表示該 stream 要經由兩次解碼才能得到原來的影像, 分別是 ASCII85Decode 和 DCTDecode.

什麼是 ASCII85 咧? Wikipedia 上有很詳細的解釋(示意圖如下), 而且還有附上 C# Souce code 的網址, 所以很簡單就完成了第一部分的解碼任務, 至於第二個 /DCTDecode, 其實就是 JPG 的編碼方式, 所以可以直接把第一次解碼後的 stream 直接存成 jpg 檔之後就可以得到原來的影像了!

image

目前還沒有看到第三種格式的影像檔出現在要處理的 PDF 中, 所以就先研究到這兒!

keywords: pdf, tiff, jpg, ascii85 decode, dctdecode

2008-07-25

Failed to initialize the Common Language Runtime (CLR) v2.0.50727 with HRESULT 0x8007000e

奇怪的 SQL Server 問題, 在 Google 上找了很久, 好不容易找到一個看起來好像是解決辦法: http://forums.asp.net/t/1098345.aspx

"Finally found out the solution for it. When you installed SQL server, the installation does not automatically allocate memory to CLR. You need to explicitly allocate atlease 500 MB ram for it."

可是它沒有教說要怎麼 "allocate atlease 500 MB", 真是令人失望!

最後終於在 Microsoft Connect 網站找到答案: http://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=344001

操作步驟: 打開[服務], 停止 SQL Server 服務, 在服務的啟動參數輸入 -g 512, 再啟動 SQL Server 服務就可以了!

後記: 在安裝完 SQL 2005 SP2 之後, 發現原先設定在服務中的參數消失了, 可是問題也消失了, 不知道是不是 SP2 有解決掉這個問題!

2008-06-16

在64-Bit作業系統執行會呼叫到32-Bit元件的程式

前陣子在 64-Bit 的 Windows 2008 上發佈了一個網站程式, 雖然過程中有點小障礙(因為 IIS 7.0 的介面完全不一樣, 很多東西要重新找一遍, 還有 web.config 要透過 appcmd 來作 migrate, 除了這兩個障礙以外, 其他的都還算簡單), 但是還是順利完成

可是後來在做測試的時候, 發現有一個呼叫 COM 元件的網頁一直出現錯誤, google 了一下說是因為在 64-Bit 環境中使用到 32-Bit 資源所導致的, 解決的方法是 you need to change CPU type from “Any CPU”, to “x86″, 可是這是 Web Application, 上述的解決方法根本不可行, 一定還有別的出路, 後來終於在 IIS 的 Application Pools 找到了相關的設定, 只要把 Enable 32-Bit Applications 設為 True 就行了
image

本以為這樣就結束了, 後來發現還有一些 Console Application 和 Windows Service 程式也有相同的問題, 雖然第一時間已經把原始程式找出來, 依上述的方式把 Platform target 從 Any CPU 改為 x86 重 Build 之後把問題解決了, 可是還是覺得很麻煩, 萬一沒有原始程式難道就無解了嗎? 當然不可能, 所以在問題解決之後, 又花了點時間找到了另一個不用重 build 的解決方法:

參考網址: http://www.request-response.com/blog/PermaLink,guid,cf345d71-cdc7-46b9-8c1c-eb21581a9222.aspx

簡單的說就是透過 .NET SDK 所提供的 corflags.exe 程式來改變 Assembly 的檔頭, 像底下這樣

corflags /32BIT+ yourAppName.exe

Silverlight 2 Beta 2 的重大變更

官方文件: http://msdn.microsoft.com/en-us/library/cc645049(VS.95).aspx

2008-04-09

看起來滿好用的 PDF 瀏覽工具

昨天在看 PDF 文件的時候, 想在中間加個書籤, 突然發現 Adobe Reader 既然沒有這個功能, 印象中以前好像可以自行加註解和書籤的啊? 難到是記錯了?

突然在 Adobe 官網發現一個 Flash Application, 叫做 Adobe Digital Edition, 看起來質感還不錯, 適合有很多 PDF 文件的人拿來管理自己的 PDF, 重點是它可以自己加書籤!!

image

有趣的書架

看出其中有趣的地方了嗎? 會寫點程式的人應該都能體會吧!!

出處: Equation Bookshelf

Json.NET on codeplex

在 Codeplex 上看到的一個簡單明瞭的 Json 類別庫!

Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };

string json = JavaScriptConvert.SerializeObject(product);
//{
//  "Name": "Apple",
//  "Expiry": new Date(1230422400000),
//  "Price": 3.99,
//  "Sizes": [
//    "Small",
//    "Medium",
//    "Large"
//  ]
//}

Product deserializedProduct = JavaScriptConvert.DeserializeObject<Product>(json);

自訂類似 flashget:// 的 URL Protocol

想要有類似 flashget:// 或是 ed2k:// 這樣能夠叫起特別程式來服務的功能該怎麼作呢?

想辦法加上類似以下的機碼, 只要換掉紅字的部分即可!

--------------------------------------
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\note]
@="URL:Notepad Protocol"
"URL Protocol"=""

[HKEY_CLASSES_ROOT\note\DefaultIcon]
@="notepad.exe"

[HKEY_CLASSES_ROOT\note\shell]

[HKEY_CLASSES_ROOT\note\shell\open]

[HKEY_CLASSES_ROOT\note\shell\open\command]
@="D:\\note.cmd \"%1\""
--------------------------------------

HttpWebRequest 與 https

HttpWebRequest 透過 SSL 取得網頁資訊時, 如果對方網站的憑證不被自己的電腦所信任的話, 就會出現 "基礎連接已關閉: 無法為 SSL/TLS 安全通道建立信任關係。" 的錯誤, 英文版的錯誤訊息是 "The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.", 在 .NET 1.1 時代曾經用 ServicePointManager.CertificatePolicy 解決過這個問題, 但到了 .NET 2.0 之後, 該方法被列為 obsolete 了, 所以就研究了一下新的方法, 順便做個記錄

// .NET 1.1
ServicePointManager.CertificatePolicy = new AcceptAllCertificatePolicy();

如果是 .NET 1.1, 我們必須自行建立一個像上面範例碼的 AcceptAllCertificatePolicy 類別, 並讓該類實作 ICertificatePolicy 介面, 該介面只有一個方法叫 CheckValidationResult, 回傳 bool 來決定是否接受對方的憑證, 直接 return true 就行了.

public class AcceptAllCertificatePolicy : ICertificatePolicy
{
    public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem)
    {
        return true;
    }
}
.NET 2.0 簡單多了, 只要一行, 透過匿名函式就行了!
// .NET 2.0
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

使用 WebBrowser.DocumentText 載入內容時忽略 JavaScript 錯誤

在 Windows Forms 內放置 WebBrowser 控件時, 如果透過 DocumentText 的方式填入有使用 JavaScript 的網頁的話, 若該網頁的 Script 有錯誤的話, 就會跳出煩人的視窗, 實在很討厭, 試了很多屬性都搞不定, 最後只好使用特殊手段來解決 -- 自行嵌入一段錯誤處理的 JavaScript, 這樣就不會有煩人的錯誤視窗了, 要嵌入的 JavsScript 如下:

"<script type='text/javascript'>window.onerror = function(){};</script>"

升級 SqlServer Management Studio

如果電腦裡有先安裝過 SQL Server Management Studio Express 版本, 然後再安裝 SQL Server 2005 的話, 安裝完成後會發現少了一些工具, 而且管理工具還是停留在 Express 的版本, 該怎麼做才能升級呢?

方法一:

  1. 先從新增移除程式將 Microsoft SQL Server Management Studio Express 移除
  2. 再點選 Microsoft SQL Server 2005, 選擇變更, 然後移除掉 Workstation components 底下的 Client Components
  3. 這時候再安裝一次 SQL Server 2005 就可以順利升級了

方法二:

  1. 直接開啟一個命令提字元, 切換到安裝程式所在的目錄, 直接輸入 setup.exe SKUUPGRADE=1

2008-02-15

WCF 錯誤: 此集合已包含具有配置 http 的位址。此集合中,每一配置最多只能有一個位址。

WCF Service 佈署到 IIS Application Server 之後, 剛開始運作的很順利, 但是後來卻發生以下的問題:

WCF 錯誤: 此集合已包含具有配置 http 的位址。此集合中,每一配置最多只能有一個位址。

剛開始以為是 WCF 有問題, 可是後來重新啟動 IIS 也沒有解決, 所以初步認定應該是設定上的問題, 趕快找 Google 問看看, 輸入錯誤訊息, 搜尋...果然, 找不到想要的, 因為我輸入的是中文...唉...每次都這樣, 只好先嘗試猜測把關鍵字翻譯成英文 collection contains http address, 再搜尋一次, 這一次 Google 終於聽懂我的問題了, 馬上告訴我問題的原因和解決的方法!!

原來是因為 IIS 的站台設定了多重識別才造成這樣的問題, 解決的方法很簡單, 就是在多重識別的設定頁留下一個就好, 其他的移除掉, 問題就可以解決了!!

 

謎之音: 那如果多重識別一定得有多個怎麼辦? 難不成就不能享用 WCF 了嗎?

 

...呃! 我也很想知道, 畢竟只能留一個這樣子的解決方式有點遜, 不算是一個好的解決方案! 那該怎麼做呢, 很簡單, 只要兩個步驟:

  1. 建立一個類別繼承 ServiceHostFactory, 並覆寫 CreateServiceHost 方法, 如下
    public class CustomServiceFactory: ServiceHostFactory
    {
        protected override ServiceHost CreateServiceHost(TypeserviceType, Uri[] baseAddresses)
        {
            return new ServiceHost(serviceType, baseAddresses[0]);
        }
    }
  2. 在原來的 .svc 檔頭部分多加上一個 Factory 屬性的設定, 雖然 intellisense 不會出現, 但是請相信專業, 這個屬性是存在的, 不相信的話請看 Reflector!
    <%@ServiceHost Language="C#" Debug="true" Service="MyCustomService" Factory="CustomServiceFactory"%>

只要這兩步就可以輕鬆解決這個討厭的問題啦!!

2008-02-14

好用的 Visual Studio Extensions

Resource Refactoring Tool

RefactoringTool-Menu.png

Source Code Outliner Power Toy

sco.bmp

好用的 Visualizer for Visual Studio: Mole

從 Visual Studio 2005 以來有個非常好用的功能, 就是在 debug 的時候,  可以用Visualizer 很方便的針對某些類型的變數進行觀察, 比如說 Text Visualizer, XML Visualizer, HTML Visualizer 等等, VS2008 還針對了 IEnumerable 物件也提供了檢視的能力(這麼做會針對該集合物件 enumerate 一次, 所以如果想要檢視集合物件的內容, 要先確認該集合是不會因為被列舉過而有所改變, 否則會發生預期之外的結果), 網路上還有其他人也針對 Visual Studio 寫了一些 Visualizer, 像是 Mole 這個 Visualizer 就超強大, 不論是 ASP.NET, Windows Forms, WPF 都提供了很多好用的 Visualizer, 只能說超好用!!

image

安裝的方法很簡單, 下載解壓後把 Mole.Visualizer.dll 放到
My Documents\Visual Studio 2008\Visualizers
目錄底下就行了!!

VS2008 的相關套件

兩個一定要安裝的套件, 特別是第二個, 改善了很多"慢"的問題

VS 2008 Web Deployment Project Support Released

VS 2008 Web 部署项目版本支持VS 2005 web部署项目提供的所有现有特性,它还添加了如下的其他支持:

  • 从 VS 2005 Web部署项目轻松移植到VS 2008 Web部署项目
  • 只在web部署项目编译成功时才替换输出
  • IIS7支持

VS 2008 Web Development Hot-Fix Roll-Up Available

HTML源码视图的性能问题

  • 在含有多于2层子属性的自定义控件的网页里输入时,源码编辑器会冻结几秒钟。
  • “View Code (查看代码)”的右击上下文菜单命令在web应用项目中需要很长时间才出现。
  • 在打开很大的HTML文件时Visual Studio 会很慢。
  • 在操作带某些标记的很大的文件时,Visual Studio有响应性问题。
  • 在选择很大的HTML文本时,Tab/Shift-Tab (缩进/去缩进,Indent/Un-indent) 操作会很慢。

设计视图的性能问题

  • 在某些页面标记配置下在设计视图中键入很慢。

HTML编辑问题

  • 即使在启用相关选项的情形下,在ClassCssClass属性后面, 引号不会被插入。
  • ServiceReference(服务引用)元素指回到当前网页时,Visual Studio 会死掉。

JavaScript编辑问题

  • 打开JavaScript文件时,客户端脚本的加彩有时会延迟几秒钟。
  • 在当前编辑行之前遇上空字符串属性时,JavaScript IntelliSense不工作。
  • 在用 jQuery 时,JavaScript IntelliSense不工作。

网站build性能问题

  • 在网站( web-site )项目中,在Bin文件夹包含大量的程序集和 .refresh 文件时, Build会很慢。