2010年9月19日 星期日

小冰箱之除霜記

凡那比颱風今天正在肆虐台灣,無聊之餘,想到冰箱裡冷凍櫃的白鬍子太多了,順手把它刮一刮。過了幾小時後,發現除霜盤上的積水滿到快溢出來了,此時如果不將水排出,過沒多久我冰箱就會淹水,但如果稍稍移動除霜盤,那它上面的積水又會不小心濺的到處都是,有夠為難的。

這時想到以前小學教的毛細效應,再配合自己刻意安排的位能差來持續不斷地把高處的水傳遞到低處,並於低處放個小鋼杯去接水,而高地處的連接橋樑就透過一條萬能的抹布就搞定了。如此過沒多久,就可以看到小鋼杯裡盛滿了除霜後的水,真是開心啊!以後除霜就不用弄的到處濕答答了。


補充:20110613

今晚回到家,發現前天除霜後,一直忘了自己有在除霜,原本已將裝滿水的盛水盤,目前都已經結冰了。剛開始,我拿著裝滿熱水的鋼杯盤,疊放在冰塊上,的確有加快溶冰的速度,但...真的等到快睡著了。最後,在我喪失理智的情況下,把冰箱電源關掉,另外拿起吹風機,把溫度調到最高,接著...對著我那結冰的盛水盤狂吹,不到5分鐘,整個冰就化了快1/4,趁著我那排冷管與冰分離的時候,將整個盛水盤抽出,直接拿去沖熱水,不到30分鐘就把這冰都除光了。

2010年9月17日 星期五

在 Console Mode下, 透過 FreeSMTP 定期發通知信

要定期的去發通知信,可以利用 SQL Server 的 SQL Server Agent 或 Windows 排程來觸發。而發信的工具可以使用 SQL Mail 或 FreeSMTP。

最近剛好有機會測試了 FreeSMTP 搭配 Windows 排程的方案。原先主要是想透過撰寫 thread 來完成定期發信功能,但考量在不增加系統 loading 與避免該 thread 莫名被終止,所以才考慮用 windows 排程。然而,原先的 ASP.Net 專案如何用 windows 排程來觸發呢?是個難題。所以,我將發信的功能改寫成 Console Mode,也就是可以用 DOS 指令來執行。但,FreeSMTP 可以用 DOS 指令來發信嗎?猶豫了許久,就寫了一段程式來測試。

首先,建立了一個 console mode 的專案,並在該專案加入了 FreeSMTP.Net.dll 的參考。

接著 Imports Quiksoft.FreeSMTP.SMTP
接著撰寫 DoSend( ) 事件以供 Main( )來叫用。

以下是程式碼節錄:


Imports Quiksoft.FreeSMTP.SMTP

Module Module1

    Sub Main()
        DoSend()
    End Sub

    'Sub that does the sending.
    Sub DoSend()

        '宣告 SMTP
        Dim objSMTP As Quiksoft.FreeSMTP.SMTP

        '設定 SMTP Server        
        objSMTP = New Quiksoft.FreeSMTP.SMTP("3probe.com.tw")

        '設定 信件內容
        Dim objMsg As Quiksoft.FreeSMTP.EmailMessage = New Quiksoft.FreeSMTP.EmailMessage("paladin@3probe.com.tw", _
                                    "paladinlee@3probe.com.tw", _
                                    "paladin", _
                                    "Dear paladin,
這封是我特別給您的 :測試信。", _
                                    Quiksoft.FreeSMTP.BodyPartFormat.HTML)
        '設定信件編碼
        objMsg.CharsetEncoding = System.Text.Encoding.GetEncoding("BIG5")

        '發信
        objSMTP.Send(objMsg)


    End Sub


End Module


直接測試這段程式,信件可以正常寄出,接著自己也加入一項 windows 排程,把內容設定為執行剛剛撰寫好的 console mode 專案的 .exe 執行檔。現下自我感覺良好中,可以開開心心去泡茶了...

2010年9月16日 星期四

利用 ASP.Net 壓縮檔案

若要透過 ASP.Net 將 Web 站台的某些檔案進行壓縮,之後再讓使者下載,這需求透過 DotNetZip 來協助,問題就幾乎解決一大半,剩下的,就是如何讓產生的壓縮檔自動下載到使用者的電腦。

可以到 DotNetZip 下載最新 release 的版本。以目前所抓到的 v1.9版來說,解開之後,只要將 DotNetZip-v1.9\Release 裡的 Ionic.Zip.dll 加入到 Visual Studio 的參考就可完成 DotNetZip 的引用。重點是,這是免費的,作者甚至認為,有了他,就不用去買價值 29 美金的 winzip 了,作者也在網站上介紹他自己撰寫的程式,用以取代 winzip。

要將資料夾壓縮的語法,非常簡潔:

using Ionic.Zip;


using (ZipFile zip = new ZipFile())
{
    //將資料夾加入 zip
    zip.AddDirectory(MapPath(".\\SourceFiles"));

    //產生 zip 檔
    zip.Save(MapPath(".\\") + "MyZipFile.zip");
    
}

產生好壓縮檔後,如何讓這檔案下載到使用者電腦呢?當然,可以在網頁上放個超連結,給使用者點選,但如過進一步想更自動一點,則就是直接將附件檔自動下載。

這時,我在 .aspx 頁面放了一個 iframe ,並去設定這 iframe 的 src 屬性為下載連結。而我下載的連結則是透過 .ashx 來處理(可參考測試程式)。

<iframe id="ifies" runat="server" style="visibility:hidden"></iframe>
</form>

這裡我偷偷埋了一個 iframe,並將他的 visibility 設為隱藏,這樣使用者在網頁上就看不到他的存在了。最後,在產生壓縮檔程式裡頭加上 :

ifies.Attributes["src"] = string.Format("filedownload.ashx?filename={0}&path={1}", "MyZipFile.zip",MapPath(".\\"));

using Ionic.Zip;


using (ZipFile zip = new ZipFile())
{
    //將資料夾加入 zip
    zip.AddDirectory(MapPath(".\\SourceFiles"));

    //產生 zip 檔
    zip.Save(MapPath(".\\") + "MyZipFile.zip");

    //讓網頁執行下載動作
    ifies.Attributes["src"] = string.Format("filedownload.ashx?filename={0}&path={1}", "MyZipFile.zip",MapPath(".\\"));
    
}

最後可以觀察執行結果:

FireFox:直接跳出另存新檔


IE6:第一次會詢問安全性問題


Chrome:直接就幫你下載了


DotNetZip 除了能壓縮,也能解壓縮、支援 Dos 指令來操作,是程式開發人員不可或缺的好工具。

參考:http://dotnetzip.codeplex.com/
測試程式:下載

補充:20100929
最近使用 dotnetzip 時發生一個問題,就是中文檔名的文件,壓縮後都會變成亂碼。還好在一篇文章中有提到解法:

http://cheeso.members.winisp.net/DotNetZipHelp/html/aecbb638-1ecf-807e-b933-5bb1a2a95e81.htm

所以,要壓縮中文檔名時,記得程式要加上:

(承接上面的範例)
zip.ProvisionalAlternateEncoding = System.Text.Encoding.GetEncoding("big5")

2010年9月11日 星期六

你是否習慣問自己問題?



媽媽,為什麼樹上的小鳥會飛?為什麼雞會生蛋?...

還記得自己小時候,也問過一連串類似的問題嗎。如今的你我,又有多少機會再提出這麼多問題了呢?若是說,隨著年紀的增長,經驗多了,知識廣了,所以問題少了,你相信嗎?我比較相信年紀大了,油條了,所以變懶了。

人的大腦,有兩個很重要的能力,一個是思考能力,一個是記憶能力。當你還是小娃兒時,透過哭聲開始了與父母親的基本溝通。而你慢慢開始知道,不舒服、飢餓時,只要哭,就會有人幫你解決。

漸漸地,你開始對這世界產生興趣,日常生活周遭的人事物,對你來說,都是如此的新鮮,此時此刻,你的心中隨時都存有著十萬個「為什麼?』。

你如何去解決心裡頭埋藏的十萬個「為什麼?」,這與你的父母、家庭環境有著密不可分的關係。有些父母亦師亦友,對你的問題無所不談;有些家庭藏書豐厚,或懂得利用圖書資源;此外,尚有權威一言堂的家庭,也有鬼神論者,而這些生長環境都是決定著一個小孩「解決問題」的能力。

快樂的 6 年過去,小孩子開始入學了,學校裡開始傳授更多的學理知識給你,但此刻的你,畢竟童心未泯,還是比較喜歡玩樂。如果遇到高明的老師,他會讓你知道學習與玩樂是可以兼得的。如果遇到普通的老師,則是學習與玩樂只能取其一。更慘的,是遇到玩也不能玩,讀也讀不會的情況,怎麼辦?只好自己四處尋找刺激、快感了。

在求學的年紀,不管有收穫、沒收穫,但上千個日子經過之後,總是會讓既定的思考行為進而成為你潛意識裡的一部分。其實,對人類進化而言,它是有幫助的,將你平日的反應記憶下來,日後如果遇到突發狀況時,不就可以立即反應了嗎?

舉例來說,如果有人說話說到你的痛處時,你的自我防衛心理開始起來,而你這時刻的直覺反應,就是最真實的你。這真實的自己,則是經歷了無數次的思考之後所慢慢塑成的,是日後你遇事決斷時的第一個念頭。

初念淺,轉念深。每個念頭,都是過去經驗所留下。人,總不能老是用老方法來處理事、來生活吧!所以要時時鼓勵自己,再多想一些,再深入一點,去探索每一個思想的盲點。你小時候那種「為什麼,為什麼,為什麼...」的精神還在嗎?把他找回來吧!

2010年9月9日 星期四

透過 jQuery 實現攔截鍵盤的 Ctrl+S 事件

想要在網頁上,允許使用者透過鍵盤的 Ctrl+S 來觸發事件,jQuery 可以幫你。

Ganeshji 在其部落格文章「Ctrl + Key Combination – Simple Jquery Plugin」介紹當如果只需要簡單的 Ctrl+? 鍵,又不想使用類似 js-hotkeys 功能這麼完整的外掛套件時,單單只靠幾行 jQuery 就可以完成了。

Ganeshji 首先使用 jQuery 的擴展定義了自己的 ctrl 函式:

$.ctrl = function(key, callback, args) {
    var isCtrl = false;
    $(document).keydown(function(e) {
        if(!args) args=[]; // IE barks when args is null

        if(e.ctrlKey) isCtrl = true;
        if(e.keyCode == key.charCodeAt(0) && isCtrl) {
            callback.apply(this, args);
            return false;
        }
    }).keyup(function(e) {
        if(e.ctrlKey) isCtrl = false;
    });
};

日後要引用 ctrl 函式,方法如下:

$.ctrl('S', function() {
    alert("Saved");
});

這範例,只要使用 Ctrl + S ,就會觸發 alert("Saved"); 實際上測試了不同瀏覽器,IE, Chrome, 都正常,但 FireFox 有點惱人的問題,就是當執行 Ctrl+S 時,FireFox 會跳出兩次另存新檔的對話視窗,這其實並不是我想要的結果。

為了避免 FireFox 跳出另存新檔的對話視窗,可以去攔截 keypress 的動作,並將原始的 Ctrl+S 事件濾掉。所以加了以下一段程式來完成。

$(window).keypress(function(event) {
      if ((event.which == 115 && event.ctrlKey)){
          event.preventDefault();
      }
    }); 

如此修改後,整個程式就更趨完整了。

附上範例程式:[下載]

參考:
01:Ctrl + Key Combination – Simple Jquery Plugin
02:js-hotkeys

後記:

在 Ganeshji 文章中有提到 js-hotkeys ,實際去玩了一下,發現他在 FireFox 也同樣存在著使用 Ctrl+S 會跳出兩次另存新檔視窗的問題,但用本編文章介紹的方式去攔截 keypress 就可解決。的確, js-hotkeys 真的是解決 web 上使用 keyboard 快捷鍵的好幫手,而 Ganeshji 則是提供了羽量級的解決方案,各位可斟酌使用。

附上 js-hotkeys 的測試程式:[下載]