April 2008 - Posts

NOTES-PDF轉文字檔筆記

PDF轉檔的工具很多,以免費為前題,以下是我找到的一些資源。

  • 線上PDF文件保護解除工具
    上傳有列印、複製保護的PDF檔案後可立即下載解鎖後的版本(不過需上傳文件到Internet,有文件內容外洩的疑慮)
    http://www.ensode.net/pdf-crack.jsf
  • 免費的PDF檔合併/分割工具
    電腦玩物有很棒的說明,這裡就不囉嗦了。 我測試了手上幾個pdf檔,pdfsam新版Beta會發生錯誤,最後改用電腦玩物用的0.7sr1舊版才正常。
  • PDF轉HTML的免費工具
    SourceForge的開放源碼專案,我測試處理中文會有問題
    http://pdftohtml.sourceforge.net/
  • 線上PDF轉TEXT
    上傳PDF後,可檢視轉換後的TEXT,格式很接近原始檔、中文也沒問題,結果可另存為ZIP起來的文字檔。(一樣有文件外洩的風險)
    http://pdftextonline.com/
  • 偷用GMail的PDF轉HTML功能
    GMail的附件上傳後,可以View as HTML,可以借來用用。
    http://labnol.blogspot.com/2005/12/convert-doc-xls-ppt-rtf-pdf-to-html.html
  • Acrobat Reader內建另存文字檔功能
    繞了一大圈,沒想到Acrobat Reader本身就內建有另存文字檔功能...
    不過測試表格式文字時,轉好的文字都擠在一起,格式不如pdftextonline.com漂亮
  • Adobe官方提供的線上轉換服務
    支援Text及HTML 3.2兩種轉換格式,可以給URL直接轉換,也可以把PDF當成附件寄給pdf2txt@adobe.com, pdf2html@adobe.com。(網友的使用經驗)
    http://www.adobe.com/products/acrobat/access_onlinetools.html  (一樣也有外洩風險)
  • 微軟Office OCR大法(For Office 2003+ Users)
    從Office 2003起,微軟加入了一個Office Document Imaging的工具,可以將圖檔OCR成Word檔。所以可以用PDF->列成TIF->OCR->轉成Word的做法,不過挺繞路的,且效果普普。參考文章
    不過這一招可以用直接用在螢幕擷取圖檔轉文字上,效果還過得去,聊勝於無。
TIPS-為WebControl過磅

在使用人數眾多或網路頻寬受限的情境下,Web Server與Browser間傳輸資料量變得格外重要,跟航空公司對行李重量"斤斤計較"一般。除了Web Control產生的HTML之外,另一項隱藏成本是ViewState,在頁面上無嗅無味,但每次檢視頁面時都會千里迢迢從Web送到Client,PostBack時又風塵僕僕地從Browser趕回Web Server,殺傷力驚人。

要深究網頁的傳輸量,除了借用Fiddler、HttpWatch這類工具去測量HTTP往來資料量外,ASP.NET本身有個好功能,可以分析各Web Control所"貢獻"的HTML內容大小及ViewState大小,等於可以為每個Web Control精密過磅,找出拖累傳輸效能的元凶。

方法很簡單,在ASPX宣告上加上Trace="true"即可,例如:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="WebForm1.aspx.cs" Inherits="WebForm1" Trace="true" %>

此時再檢視網頁,你就可以看到如下的資料量拆解分析,很好用吧!

Control Tree
Control UniqueID Type Render Size Bytes (including children) ViewState Size Bytes (excluding children) ControlState Size Bytes (excluding children)
__Page ASP.webform1_aspx 809 0 0
    ctl02 System.Web.UI.LiteralControl 174 0 0
    ctl00 System.Web.UI.HtmlControls.HtmlHead 46 0 0
        ctl01 System.Web.UI.HtmlControls.HtmlTitle 33 0 0
    ctl03 System.Web.UI.LiteralControl 14 0 0
    form1 System.Web.UI.HtmlControls.HtmlForm 555 0 0
        ctl04 System.Web.UI.LiteralControl 21 0 0
        Label1 System.Web.UI.WebControls.Label 30 0 0
        TextBox1 System.Web.UI.WebControls.TextBox 51 0 0
        Button1 System.Web.UI.WebControls.Button 66 0 0
        ctl05 System.Web.UI.LiteralControl 18 0 0
    ctl06 System.Web.UI.LiteralControl 20 0 0

補充一點,ASP.NET 2.0在ViewState儲存策略上做了改變,採取Data/Control分離的做法,即使你將EnableViewState設為false時,資料本身不會被保留,但Control的一些外觀屬性如果放在ControlState中,就得以保存。詳細介紹可以看MSDN (中文說明)。

TIPS-如何將HTML色碼轉成.NET Color Object?

要怎麼把#77aaff這種HTML色碼轉成.NET中的Color物件呢? (我最常用到的情境是將設計師配好的色系套在WinForm上)

多說無益,直接看Code,解說都放在註解中:

static void testColorTrans()
{
    Color c;
    //我有一個HTML色碼,要怎麼換成.NET Color物件呢?
    string htmlClr = "#77aaff";
    //有了,Color.FromArgb可以用
    c = Color.FromArgb(Convert.ToInt32(htmlClr.Replace("#", ""), 16));
    //其實有更快的方法, ConvertTranslator
    c = ColorTranslator.FromHtml(htmlClr);
    //而且也可以將Color還原回HTML色碼
    Console.WriteLine(ColorTranslator.ToHtml(c));
    //不過有個小問題,如果是Color.Blue這種具名顏色
    c = Color.Blue;
    //會得到ToHtml()會傳回"Blue"字串
    Console.WriteLine(ColorTranslator.ToHtml(c));
    //如果堅持一定要換成色碼,就得花點功夫了
    //謎之聲: 明明Blue在HTML就可用,不知為什麼要這麼堅持??
    Console.WriteLine(
        String.Format("#{0:x2}{1:x2}{2:x2}",
        c.R, c.G, c.B));
    //另外介紹幾個相關函數
    //Color.FromName可以轉換具名顏色
    c = Color.FromName("blue");
    //還有一個看起來較麻煩的WebColorConverter
    //我目前還沒想出不用ColorTranslator要用它的理由
    System.Web.UI.WebControls.WebColorConverter wcc =
        new System.Web.UI.WebControls.WebColorConverter();
    c = (Color)wcc.ConvertFromString(htmlClr);
}
Posted 28 April 2008 09:51 AM by Jeffrey | no comments
Filed under: ,
[震怒]超不敬業的詐騙集團

昨天晚上10點,手機有通來電顯示+886229437176(事後查了一下Google,原來這是東森購物的電話,常被詐騙集團假冒),接起來,一個大陸口音的女子,講話有點含糊...

騙: "李先生嗎? 你好,我們是糊糊糊(我懂不出她說什麼,現在看來,當時說的應是東森)購物公司,請問一下,你在4月23日有訂一個書,收到了嗎?"
     (專業客服人員含魯蛋? 失敗! 晚上10點連絡客人? 失敗! 最糟的是,我根本沒在購物公司買書,根本沒掌握資料就想亂槍打鳥,太不用心,失敗中的失敗!)
我: "沒有耶,你說我訂了什麼? 付錢了嗎?"
     (超亢奮! 終於輪到我有榮幸接詐騙電話了,我們來玩吧?)
騙: "呃... 有,是用信用卡"
     (這位客人怎麼反應這麼激烈? 不知在興奮什麼)
我: "我沒有訂耶,資料上是那一張信用卡?"
     (應該是想搞信用卡相關的議題吧? 那我來引導你好了)
騙: "呃... 信用卡的號碼是1423..."
     (糟了,這傢伙居然不照劇本來,幸好話術手冊第4頁有這一段)
我: "是那一家銀行的?" 
     (嘿,一般人在講信用卡時不是該先報銀行嗎? 怎麼直接唸卡號? 我試圖想扮演好"一般人"的角色,主動詢問銀行。但壞在我沒耐性等到她報完卡號就插嘴問話,害她受驚了)
騙: "什麼?"
     (開始有點慌了手腳)
我: "我說,信用卡是那一家銀行的?"
     (一時興奮,口氣操之過急,接著砸鍋了...)
騙: "呃... 呃... 是新光的"
     (看起來應該已亂了方寸)
我: "可是我沒有新光的卡耶"
     (夠聰明吧,我這麼回答,讓你可以接話繼續演"卡被盜刷要進行ATM處置"的橋段)
騙: "這樣哦,那沒事了!"

還來不及反應,小姐已經掛掉電話,留下錯愕的我久久無法言語...

喂喂喂,小姐,我的卡被盜刷,你不用協助我連絡"警方"處理? 沒有"金資中心"的主任向我解說解決方法? 不用導引我去ATM用"英文介面"操作停止扣款? 你們購物公司收不到錢就這樣算了? 我們之間應該還有好多好多話要講,這麼可以用一句"那沒事了"就把我打發?

本來想好好體驗"被詐騙"的樂趣,卻無預警跌入無底的深淵。別人都可以體驗精彩的警官+金資中心+ATM操作的完整過程,為什麼我的卡被"盜刷",卻以一句"是盜刷的話就沒事"收場。好像去吃喜酒,眼看別桌在啃紅蟳嚼干貝吞魚翅啖佛跳牆,我卻只吃到拼盤就不再上菜;好像心癢難耐的花痴,故做矜持端莊地跟男友吃完晚餐看完電影,正等待受邀上山看夜景展開重頭戲,卻得到一句: "時間晚了,我先回家囉!"

這一點也不公平! 難道我表演得這麼差,連受騙者的角色都扮演不好嗎?

痛定思痛,下回我會更努力扮演好"受騙者"的角色,詐騙集團,再給我一次機會吧!

Posted 27 April 2008 02:37 AM by Jeffrey | 5 comment(s)
Filed under:
二格山綠豆湯最後一瞥

在蝌蚪的網站上看見二格山綠豆湯要拆掉的消息。

雖然爬過無數次(當然,比不上142大哥)二格山,但出名的綠豆湯卻一次都沒喝過。大部分是因為我爬得早,有時下山時才看見老阿公老闆挑扁檐跟老闆娘正爬上山;再不然就是人到了但還沒生火。只有一次,大熱天連攻二格+筆架,飲料耗盡,口渴到瀕死之際,在此買過一次救命用的舒跑。

於是,趕在拆除期限4/27前,今早再去拜訪了一次。7:15由大榕樹出發,走好漢坡,8:02分就登頂,47分鐘的記錄還不賴。檢查上回留在二格山的標記還在,接著就趕往綠豆湯,還好還好,還沒拆,至少看到最後一眼並拍了照留念。(在店內的確看到限時拆除的公文告示)

時間還允許,加上今天體力尚有餘,決定連攻猴山岳。

穿過阿柔洋產業道路時,剛好遇到"魔鬼騎士團"正攻上了令人喪膽的魔鬼坡道頂端,嘿嘿嘿... 騎士們,坡度60度的碎心坡正等著你們。

大約一個小時後,攻上猴山岳前峰。可惜今天空氣迷濛,視野不佳。

當然,看到三角點,就代表專屬標記又多攻上一個山頭。不過這回不像前兩次有登山條可以大大方方寄生,著實頭痛了一下,幸好在樹幹上找到先前登山條還是告示牌殘存的一小角。

今天的行程從大榕樹(7:15)->好漢坡->二格山頂(08:02)->綠豆湯(08:30)->阿柔洋(08:55)->鞍部->猴山岳(09:42)->鞍部->大榕樹(10:05),共計2小時50分,新記錄!

小心網路上的詐騙集團

早上聽同事說,不少人收到某同事MSN了一個URL,懷疑是病毒...

過去曾經解剖過一隻木馬,當時第一次見識到不必做什麼傻事(假設沒定期Windows Update不算傻事的話),一開網頁就中鏢的驚人殺傷力。不過,讓木馬/病毒可以長驅直入的關鍵在於Windows未及時修補安全漏洞。我有點納悶,公司環境有強制Windows更新部署、也統一裝了防毒軟體定期更新病毒碼,莫非這回又遇上什麼強勁的敵手,讓MIS建立的防線瞬間瓦解?

想到這裡,身體裡的駭客血液開始沸騰。 盤問細問了被控散播病毒的苦主同事,她才供出說出受害過程:

她的MSN收到一個連結,點選後進入一個網頁,詢問她MSN的帳號、密碼,她就好傻好天真地乖乖填好資料按送出,然後...

聽到這裡,原本興奮跳下床的駭客又爬回去睡回籠覺了。原來不是什麼高階技術、創新技巧,純粹是詐騙集團的手法。

現在大家都知道接到電話、收到問卷時,不會輕易透露姓名、身份證字號、地址、電話或銀行資料,但同樣的意識還沒有充分映對到網路世界裡。MSN的帳號、密碼似乎無涉自己的身家財產,給了沒什麼關係。但細想之下,這些隱密資訊一旦落入歹徒手中,後果還挺可怕的:

  • 歹徒可以"100%假冒"你,用MSN跟你的眾親友連絡,一一送上木馬病毒,害你被罵到臭頭,榮登"白目毒王"的寶座...
  • 如果你的MSN帳號、密碼跟電子郵件相同,歹徒可以泡杯茶,打開你信箱,欣賞二奶寄給你的陳冠希式麻辣合照,再由網拍通知函找到你的連絡電話,打電話詢問你介不介意他貼在Blog上...
  • 如果你的信箱中有某些網站的會員通知信,歹徒可以試著用"忘記密碼"功能寄信到你的信箱,取得或重置你的會員密碼,觸腳就又能向外延伸! (幸好目前網路銀行重要的權益變更都需要到櫃檯辦理,盜用風險有限,但未來透過線上可以處理的業務愈多,風險也會相對升高)

在璉璉的Blog上看到類似的報導(有圖),時間相近,加上請同事指認,確定就是同一個。

其實,不只惡意網站,有些合法的網站也打著自動幫你寄邀請函給MSN好友的藉口,會向你索取MSN帳號密碼。前些時候,收到前同事寄來的一封信:

林志玲 希望成為您 hi5 上的好友!

我設定了 hi5 的個人檔案,並希望將您加入好友,讓我們一同分享相片與建立社交圈。但首先您必須加入 hi5!加入之後,您就可以建立自己的個人檔案、分享照片,並尋找好友。

感謝您, 志玲

我先很謹慎地問了前同事,言承旭跟馬桶小開難道不會介意嗎? 這封邀請函是否是她主動發出或是在不知情狀況下發的? 她回答說是經過她同意發送的,我才放心地連上hi5網站。

依指示新建帳號、填資料,但沒幾下就發現網站跟我索取MSN帳號/密碼以便自動取得我的MSN連絡人清單代寄邀請函。雖然有附上聲明,保證不會儲存我的密碼移作他用,但我還是拒絕把保險箱鑰匙借個第一次見面的陌生人代取文件。即使他衣冠楚楚,客氣又斯文... 你怎麼知道他是不是披著羊皮的狼? 會不會走到半路文件就被偷被搶?

這年頭,小心為上。

【日記】機車擱淺記

今天中午的便當居然出現令人驚豔的生菜沙拉組: 苜宿芽+西洋萵苣+紫萵苣+玉米荀+水果洋芋泥,不過像漿糊的管狀通心粉"焿"是敗筆,剛好順勢成為"BMI標準化計劃"裡減少澱粉攝取的下手對象。

不過,生菜沙拉加半杯通心粉的午餐實在沒"凍桃",下午五點多,"餓"魔就來襲(偏偏左鄰右舍都在吃點心orz),撐到近七點動身回家,一路朝晚餐飛奔而去...

騎到木柵高工附近,等完一顆紅燈,用力催了油門,正等待車身噴出的快感時,忽然傳來很大的噪音,接著車身失去動力,上回摔車的記憶再次浮現腦海,慘了~~~

不過,這次有點不同,減速的同時,車身滑行得很平穩;緩緩用腳將車划到路旁,也未出現破胎時後輪卡住的拖累感。初步檢查,輪胎狀態良好,催油門只有聲音,沒有動力--->研判是皮帶斷了!!

這時陷入兩難: 距我平日保養的機車行約兩公里,說近不近;雖可以打電話請車行將機車載回去修,但得等店家喬時間,暫時無車可用,之後還要奔波好幾趟。最後決定,兩公里,一咬牙就到了(還有瘦身之效哩),儘快把車子搞定,明早就可以如常上班。於是,我的機車"無碳"長征展開了。

推著機車在馬路上走,才發現"有碳"的日子真是爽呀! 平時右手一旋就過場的景色,這回用慢動作在兩側緩緩滑過;忘了自己在推車而不是在走路,居然還不自量力地趕了一個綠燈過馬路,喘到差一點吐出來。想到"吐",才記起現在肚子是空的,還真餓~~~ orz

雖然是推車走,但里程表還是忠實地計程,從案發現場推到機車行大約一千五百米,比我預估的短。車行老板同意我的判斷,推測是皮帶斷了沒錯。只是他有點驚訝,因為他們都會為每台維修的機車建一個Excel檔,記錄每次保養維修記錄,並主動提醒車主定期該做的保養項目(是少數我見過e化程度很高的機車行)。而我的愛駒,就是在2萬到2萬5千公里這段期間沒有保養到"傳動組",才會落得皮帶斷裂擱淺的下場。(老板娘一直堅稱她有提醒過我好幾次該保養傳動組,但我腦海中卻完全沒有任何印象,總之,我們兩個人之中有一個人記憶力出了問題)

修車師傅拆開了變速箱,我第一次見識到離合器的原理。皮帶果真斷了,"普利盤總成"也該換了(普利盤與普利珠的圖片及自動離合原理可以參考這裡),總共2500大洋。不過這些東西本來在25000公里保養時就該更換,並不算額外損失,唯一的損失應該只有機車無碳式行進一千五百米耗費的力氣與時間,還承受了在馬路中央擱淺的行車風險!

最後,把老板娘傳授的保養知識跟大家分享一下。

機車傳動組每20,000到25,000公里應拆開檢查,此時皮帶外側多半會開始有龜裂紋路,內側齒狀也會有些磨損,建議換新。一直拖著不換,就會像我一樣在路上失去動力攔淺。這回是發生紅燈轉綠燈剛起步時(可能也跟歸心似箭、猛催油門有關),四周車輛車速都不快;如果斷在高速行駛時,可就危險了,建議有騎車的朋友要留意。

Posted 24 April 2008 02:16 AM by Jeffrey | no comments
Filed under:
KB-ODP.NET OracleDataReader的資料型別轉換問題

這是同事發現的有趣現象(雖然她完全笑不出來)...

在ORACLE建了以下Table,並塞入一筆資料9.3到NUMBER(6,2)欄位中

CREATE TABLE PRECTEST (N NUMBER(6,2));
INSERT INTO PRECTEST VALUES (9.3);

然後用ODP.NET執行以下的程式

    string cmdStr = "SELECT N FROM PRECTEST";
    using (OracleConnection cn = new OracleConnection(cnStr))
    {
        cn.Open();
        OracleCommand cmd = new OracleCommand(cmdStr, cn);
        OracleDataReader dr = cmd.ExecuteReader();
        dr.Read();
        Console.WriteLine(Convert.ToDouble(dr["N"]).ToString());
        Console.WriteLine(Convert.ToDouble(dr["N"].ToString()).ToString());
        dr.Close();
        cn.Close();
    }

上述的兩行WriteLine,得到的結果不會相同,直接ToDouble會得到9.30000019073486,而ToString後再ToDouble才會得到9.3。

依我的認知,這個差異很像浮點數(Float、Double)所產生的近似誤差,這點之前的文章有提到過。

進一步挖掘,我發現更多有趣的事實:

  1. 同樣的Code,如果用的是System.Data.OracleClient,則不會產生上述的數字差異,所以這個問題只發生在ODP.NET上。
  2. 我檢測了dr.GetDataTypeName(0),System.Data.OracleClient時傳回NUMBER,而ODP.NET則傳回Single。也就是這個誤差源於Single轉Double的過程,Convert.ToDouble(9.3F)可以看到一模一樣的誤差結果。
  3. 我試著將NUMBER(6,2)改成NUMBER(14,2),則ODP.NET dr.GetDataTypeName(0)傳回Double,改成NUMBER(31,2)則傳回Decimal。由這個觀察,可以推論ODP.NET能"聰明地"視數字欄位長度決定自動選用不同的資料類別。
  4. 想要避免這個問題,最好在使用ODP.NET時,先確認數字欄位精確度再決定Convert.ToWhat,但此法在Schema變更時可能會出事。一律用ToDecimal應該是個辦法,再不然,先ToString()再轉應該也OK。

依一般人的直覺想法,Convert.ToDouble(Single),屬於低精確度轉高精確度,不該出現誤差,不過由以上實例來看,要留意此一浮點數特性。

PS: 我在MSDN Library Convert.ToDouble(Single)上加了一則Community Content,這是我第二次在MSDN上塗鴉(第一次在此)。

KB-雙核? 四核? 到底要算幾顆CPU?

又是藏在心中很久的疑問,這幾天被要求提交伺服器規格,被迫花了點時間把它釐清楚。

我們都知道,微軟的Server系列產品,不同的版本可支援處理器(Processor)數與記憶體容量上限不同,以Windows 2003為例,共有Web Edition、Standard Edition、Enterprise Edition、Datacenter Edition等四個版本,其中Web版只支援到兩顆處理器、Standard版4顆、Enterprise版8顆、Datacenter版則可以到32顆。(詳細資料請看這裡)

不過,問題來了! 近代的CPU開始走多核風(Multicore),市面上的CPU,Dual Core雙核已經是基本要求,連Quad Core四核版本的CPU價位也日益平民化。當四核CPU愈來愈普及,雙CPU插座的主機板插上兩顆,Windows Task Manager裡頓時會冒出8顆CPU的使用率上下跳動,爽快歸爽快,另一個問題來了,依據前面所說的,Windows 2003 Standard Edition的CPU上限是4顆CPU,可以安裝在兩顆四核CPU的主機上嗎? 會不會Task Manager裡只能看到4顆CPU? 不然乾脆一點買Enterprise Editiony就不用擔心這麼多了? 別開玩笑了,依據官方報價,Standard與Enterprise版本的價差達四倍呢($999 vs $3,999)!!

因此我們要釐清的問題是,版本比較文件裡所說的4 way SMP support,指的是最多四顆實體的CPU呢? 或是超過一顆四核CPU就破表? (這個問題價值十萬元呢!)

有份官方文件可以精準地回答我們的疑問:

For Microsoft software with processor limits, each processor counts as a single processor regardless of the number of cores and/or threads that the processor contains. For example, Windows Server 2003 R2 Standard Edition can be used on a four-processor system, whether the processors in the system are single-core, hyperthreaded, or multicore.

換句話說,MS的規格文件裡,所提到的n-way SMP,是指"實體上"的n顆CPU,即便它可以開啟Hyper-Thread、或內建雙核或四核,不管Task Manager看到多少個CPU Usage,都只算一顆。所以如果有一台四個CPU Socket的主機器插上四顆四核CPU,在Windows Standard Edition裡看到16條CPU Usage Bar跳動,也是可能的。

題外話,並不是每家軟體廠商都採行像微軟一樣以實體處理器數量(或說Per CPU Socket)為認定基準,有些廠商會訂定每顆核心的換算比例(約當處理器數嗎? XD),例如: 一個核心相當於0.75個處理器,IBM甚至發明了Value Process Unit為CPU的計算能力計價。有興趣的可以看看這篇文章

Posted 21 April 2008 09:58 AM by Jeffrey | 5 comment(s)
Filed under:
【茶包射手專欄】奧妙的MSDTC咒語

之前運作一段時間的電子表單系統,最近又擴充了三台新主機。奇怪的是,在三台新主機上,有個撤銷表單的網頁功能一直出問題,會傳回 Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) 錯誤。

通常,存取權限錯誤可以用抓鬼一哥Process Monitor輕易抓出來,但這次卻不然。ProcMon裡看不到可疑的Registry或File Access Denied訊息。Trace Code發現這段程式啟動了TransactionScope,嗯,很有可能是啟動DTC時發生錯誤所致。

於是,我寫了一個WinForm程式在問題主機上測試TransactionScope功能。奇了!! WinForm的測試是成功的,但ASP.NET呼叫元件Class裡一段TransactionScope的Code,卻會得到Access is denied的錯誤。

迫不得已,我只好修改元件Class,將這段的StackTrace也Log下來,發現錯誤發生在:

Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
   at System.Transactions.Oletx.IDtcProxyShimFactory.ConnectToProxy(String nodeName, Guid resourceManagerIdentifier, IntPtr managedIdentifier, Boolean& nodeNameMatches, UInt32& whereaboutsSize, CoTaskMemHandle& whereaboutsBuffer, IResourceManagerShim& resourceManagerShim)
   at System.Transactions.Oletx.DtcTransactionManager.Initialize()
   at System.Transactions.Oletx.DtcTransactionManager.get_ProxyShimFactory()
   at System.Transactions.TransactionInterop. GetOletxTransactionFromTransmitterPropigationToken(Byte[] propagationToken)
   at System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction tx)
   at System.Transactions.TransactionStateDelegatedBase.EnterState(InternalTransaction tx)
   at System.Transactions.EnlistableStates.Promote(InternalTransaction tx)
   at System.Transactions.Transaction.Promote()
   at System.Transactions.TransactionInterop.ConvertToOletxTransaction(Transaction transaction)
   at System.Transactions.TransactionInterop.GetExportCookie(Transaction transaction, Byte[] whereabouts)
   at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()

由StackTrace可以確認,問題是出在DTC沒錯。有了明確的Keyword,很快就Google到類似的文章。不少人抱怨這問題發生在安裝Windows 2003 SP2之後,也看到有些人宣稱用一段類似"咒語"的東西可以解決問題。

最後,我在這篇文章中查到詳細的解答(請看該文第8則回應):

這個問題源自於MSDTC對Authenticated Users的權限設定被設成(A;;CR;;;AU),而它的正確設定應為(A;;CCLCSWRPLOCRRC;;;AU)。這些看起來像咒語的東西,叫做ACE Strings。依據這個理論,在執行WinForm時用的是管理者權限帳號,有別於ASP.NET使用Network Service,之所以TransactionScope在WinForm OK,在ASP.NET中會失敗,就有了合理的解釋。而這個ACE是指使用Service的權限,應該也解釋了為什麼Process Monitor無法觀察到此段存取權限不足的記錄。所有真相都"大白"了(酪梨壽司別怕,此事與您家老爺無關!),感覺真好!

按照該文的說明,我下了sc sdshow MSDTC,得到以下結果:

C:\>sc sdshow msdtc
D:(A;;CCLCSWRPLOCRRC;;;S-1-2-0)(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOC
RSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CR;;;AU)(A;;CCLCS
WRPWPDTLOCRRC;;;PU)(A;;CCLCSWRPLORC;;;NS)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;W
D)

薑!薑!薑!薑~~~ 這幾台問題主機MSDTC的ACE果然被設成(A;;CR;;;AU),我將上述結果中的(A;;CR;;;AU)置換成(A;;CCLCSWRPLOCRRC;;;AU),再用sc sdset MSDTC重新設定。(這裡不貼出語法,怕大家直接Copy回去RUN會出事;正確的做法是先用sdshow取得各機器的設定值,更換其中AU的部分再sdset,切忌Copy後直接拿到別台RUN)

改完設定再試一次,發現原來Access is denied的錯誤訊息變了,變成Communication with the underlying transaction manager has failed,這就是一般性的DTC錯誤了,IISRESET一次,銷單功能恢復正常。Case Closed!

【荼包射手專欄】無法管理IIS 6.0

在一台安裝Office Sharepoint Server 2007的主機上,使用Computer Management試圖開啟Internet Information Services(IIS) Manager,或直接執行Administrative Tools裡的Internet Information Services(IIS) Manager都會得到以下訊息:

the path specified cannot be used at this time

接著,IIS Manager裡空空如也,無法使用。

Google了一下,有人說IISRESET後會恢復,測試結果,的確在IISRESET後就恢復正常。但我還查到進一步說明的MS KB946517,指明此一問題與IIS ADSI裡的多Thread存取議題有關,最常發生在SharePoint Timer Service(OWSTimer.exe)執行的場合(這不是我第一次與OWSTimer打交道了,感覺上這小子體弱多病)。

由於目前只發生過一次,打算持續觀察一陣子再決定要不要裝Hotfix。

document.querySelector() in IE8

支援CSS Selector是讓我愛上jQuery的主要原因之一,最新在檢視IE8 Beta 1 For Developer的新功能,發現IE8開始支援一些新的W3C規格(http://www.w3.org/TR/selectors-api/),其中document多了querySelector與querySelectorAll兩個函數,簡單來說,它實現的就是jQuery裡令人驚豔的CSS Selector功能。例如以下的範例: (只有IE8可以跑,FF、IE7、或Emulate IE7的IE8都會發生錯誤)

<html><body>
<div><div><span>InnerSpan</span></div></div>
<div><span class="myClass">ClassSpan</span></div>
<script type="text/javascript">
    alert(document.querySelector("div div span").innerHTML);
    alert(document.querySelector("span.myClass").innerHTML);
</script>
</body></html>

目前有實作querySelector的瀏覽器不多(除了IE8之外,另一個是Webkit),但遲早有一天,當它變成大部分瀏覽器都支援的標準功能時,jQuery就可以改寫核心,以內建的querySelectorAll取代用Javascript模擬CSS Selector,效能可望由現在的"爬行"昇級成"飛行"。

Robert Biggs有篇Blog做了有趣的測試,首先比較了Prototype, jQuery, Ext在IE7與IE8上的執行效率,發現IE8的表現稍好,例如: jQuery測試原本在IE7上要跑119,116ms,在IE8上只要97,696ms,快了21秒。(意外發現一件事,Prototype居然比jQuery慢了兩倍)

而最讓人振奮的好消息是--同樣的CSS Selector測試,使用IE8內建的querySelectorAll()只要924ms就可以跑完(Webkit更快,500ms打死),算了一下,97,696->924,加快了100倍以上!!!

期待這個新規格快點普及,屆時對jQuery來說,將如虎添翼。

Posted 17 April 2008 08:08 AM by Jeffrey | no comments
Filed under: ,
解決Consolas在VS2008的中文顯示問題

自從MS搭配VS2005推出了Consolas字型,一下子就成為許多.NET開發者的最愛,對於曾被0與O惡搞的我來說,自然也是首選。

不過,Consolas在VS2005的俏麗模樣...

到了VS2008卻變了樣! 一樣設定Consolas字體,卻因為中文字部分使用微軟正黑體而非細明體,搞得中英混合文字字型有大有小,中文字還小到難以識別,慘不忍睹... (謎之聲: 孩子,想哭就大聲哭出來吧!)

由於Visual Studio的字型設定並不像Word可以為中、英文各設一組,因此要用Consolas就得忍受難看的中文字。今天發現已有大陸同胞動手解決掉這個問題了,透過網路找到雅黑+Consolas的組合字體裝上。Feel so good~~~

關於電池保養的迷思

前幾天為小黑(ThinkPad T43)換了新電池,無意間發現在Thinkpad電源管理說明文件中,有一段介紹如何延長鋰電池壽命,我讀了才驚覺之前一直用錯誤的觀念在保養電池。同時也開始懷疑小黑電池跟之前一顆買不到一年就掛點的Canon 10D電池,其實死於我自以為是呵護的蹂躙... orz

有鑑於此,把這次學到的心得整理一下,如果有人跟我一樣存有錯誤的觀念,記得快點,能救幾顆電池,應該也是功德一件:

  1. 不要將電池置於高溫的環境(O)
    高溫會對電池造成傷害,ThinkPad甚至會在溫度過高時,先暫停充電。電池在低溫下(例如: 雪地)性能也會衰減,不過在雪地裡,手指會比電池先罷工才對。
  2. 電池長期不用時,記得要先充電,以免自行放電過度掛點(O & X)
    這是這回我犯的最大錯誤! 因為先有聽過這樣的說法,所以我習慣電池一沒電就先充飽電放著才安心,一方面也是希望下次要用時,拿起來就是充飽電的立即可用。只是平時多將小黑電池拔起來捨不得用或長期休眠,相機電池則因為相機使用頻率不高,充飽電的電池常常一放就是好幾個月。依據ThinkPad文件的說明,長期不用時,電池電量最好不要超過50%! 電池長期處於充飽狀態,會加速電池性能的老化。
    但空電池放置過久,若自然放電將所有電量耗盡,會讓電池掛點也是事實。所以,如果你的電池很少使用,較好的做法是保持50%以下的電量,並且定期讓它完整地充、放電一次。
  3. 電池可充放電次數有限,且性能會隨充電次數遞減(O)
    沒錯,這是常識。但一些小技巧可以讓衰減的速度減緩,例如: 定期進行一次完整的充放電,具有延年益壽的功效。ThinkPad電池管理的UI上有個Perform Reset功能,可以幫你執行"充飽電->放光電->再充飽電"的定期保養。
  4. 筆記型電腦預設低於95%就開始充電的設定可以減少充電次數,增加電池使用期間(X)
    以廠商的角度,電池屬於消耗品,提供更佳的服務水準比延長電池壽命更重要。(再說,大家電池都用不壞,廠商要怎麼賺錢?) 由於筆記型電腦常會被帶著到處跑,未必到處都有插座可用,自然要儘可能儲存最充沛的電量,以保持最高的可用度。
    但如第2點所說,如果你的筆記型電腦很"宅",一年到頭都儲存95%-100%的高電量,未老先衰便指日可待~~~

這樣想起來,小黑電池捨不得用,但充飽電一放就是好幾個月,結果才一年就變成會直接從60%掉到4%的老頭子;Canon 10D備用電池,每次換下來就立刻充飽電(我還以為這是"即知即行"、"未雨綢繆"等高貴情操的展現呢! orz),因為照相少導致充飽電的備用電池一躺就是好幾個月,結果年初才買,年底就陣亡...

由以上兩個血淋淋的案例,再加上之前操得超凶的X21電池,反而很"長壽"地撐了四年多,我幾乎可以做一個推論: 長期充飽電比經常充放電更具殺傷力!

這麼說來,並不是電池品質有問題,廠商背了黑鍋。真正斷送兩顆電池小命的,是我這個善良又無辜(無知?)的殺人魔... (我一直以為我很照顧它們 orz)

痛定思痛,以下是我重新擬定的"鋰電池長期照護計劃",給大家參考:

  1. 由於我的小黑很"宅",幾乎都有整流器長相左右,用到電池的機會不多。因此設定成電量低於10%才開始充電,並充到100%為止。這樣可以減少充放電的次數,並避免長期處於高電量的狀態造成電池性能衰減。但必須注意,這個策略乃是犠牲機動性換取電池的壽命,每次要帶出場前,記得要提早將電充飽。如果連續一兩個月都沒用到電池,也要做一次完整充放電。
  2. 我的Canon 10D有兩顆電池,沒電時只先充個幾分鐘到半飽,下次要用前再完全充滿。同時改變策略,不要等電池電用光才換電池,想到就更換輪替一下,不要讓電池靜靜地在包包裡沈睡成植物人。
Posted 14 April 2008 09:54 AM by Jeffrey | 2 comment(s)
Filed under:
KB-IE6/IE7對Attribute中Escape字元的處理區別

有個網頁用IE6檢視OK,用IE7卻會有問題,害我抓問題抓到滿身大汗!

我看到的現象是ASPX抓到的Request["p"]裡出現了%2f這類文字,而該URL是由一段Javascript產生的; 這段Javascript去抓某個<a href="BLOCKED SCRIPT...">的href屬性當來源,並做了escape();而這個href屬性是C#在後端計算出來的Base64編碼,且經UrlEncode處理... (看到這裡,大家頭都昏了吧?)

一路追追,總算找到問題的源頭。用以下的例子,可以驗證在IE6跟IE7中會得到不同的結果:

<html><body>
<a href="javascript:boo('%2f');void(0);" id="lnk">LINK</a>
<script type="text/javascript">
document.write(document.getElementById("lnk").href);
</script>
</body></html>

在IE6裡會看到boo('/'),而在IE7裡則會看到boo('%2f')!

換句話說,IE6在取得href時,若發現其中有escape過的內容,會將其unescape還原回原文字;而IE7則是忠實將結果傳回。

這個行為上差別,讓原本在IE6跑得好好的網頁,在IE7裡發生重覆多escape一次的狀況,產生了錯誤。

最後,我解決這個問題的鋸箭法是先檢查抓到的href值中有沒有出現%字元,如果有代表是IE7,則不再做escape。如此可包容二者行為的差異,在IE6/IE7下都不致出錯。

More Posts Next page »

Search

Go

<April 2008>
SunMonTueWedThuFriSat
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910
 
RSS
【工商服務】


BlogLook Score and Rank

Syndication