星期一, 2月 15, 2016

藉由 WebServices 開放資料

通常在跨系統整合面臨的抉擇:到底要直接開放應用系統後端的資料庫,或是在應用系統上準備一些 WebServices 來服務其他的應用系統?比較安全的作法當然是後者,不過通常被認為成本較高,但果真如此嗎?其實這些輪子通常是已經存在的。以 Oracle 來說可以參考這篇,以 MS SQL 來說可以參考這篇以及這篇

星期三, 1月 20, 2016

IIS + Oracle 的系統開發

  1. .NET Framework 內建 System.Data.OracleClient,已被標為 Obsolete,就別再留戀了。
  2. 開發環境一般會安裝 Oracle Client 與 ODAC (Oracle Data Access Component) 兩者,但事實上只要 ODAC 就夠了。若是要直接連 Oracle 查、改資料這個理由,除了 Oracle Client 之外,DBeaver、TOAD、甚至 Visual Studio 都可以用才對。
  3. ODAC 也有分 XCopy 或其他一大堆帶不同元件的包裝,看來 XCopy 的比較單純,利用解壓後批次檔安裝所有部份比較保險,記得要用系統管理權限,事後還要對安裝路徑加入全域 PATH 環境變數,甚至較舊的作業系統可能還要調整該目錄的安全性,開放給所有 Authenticated Users,如果已經開了 Visual Studio 也要重開才能讀到新的環境變數。
  4. 在 64 位元的作業環境,32 / 64 位元的 ODAC 都可運作,但事實上 32 位元的比較方便,原因是 Visual Studio 附帶的 IIS Express 預設還是 32 位元(設定在 Tools -> Options -> Projects and Solutions -> Web Projects),兩者必須搭配。
  5. ODAC 畢竟還是 Native,其實早就有 Oracle ManagedDataAccess NuGet Package 可用,安裝管理都方便。就算是舊程式轉換也只要改 Namespace (Oracle.DataAccess -> Oracle.ManagedDataAccess) 就好。
  6. 也不再仰賴 tnsnames.ora 設定連線資訊,可以查查 Oracle 有個名詞叫 EZCONNECT。例如我們以前在設定檔寫 DataSource=abc;User Id=... 還要搭配 tnsnames.ora 其中一段 abc=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=...,現在只要改成 DataSource=<HostNameOrIP>:<Port>/abc;User Id=... 就夠了,幹嘛要分兩個地方設定?

星期日, 1月 17, 2016

調校 64 位元環境下的 Visual Studio + IIS Express 執行 32 位元應用程式

過去常在 64 位元環境下的 IIS 接觸到這個議題,通常都是多人共用的測試機或正式機,沒想到為了難搞的 Oracle,連個人開發環境也要講究 32 / 64 位元的參考與執行環境搭配,而且驚訝於許多人們因此被迫放棄了 IIS Express。其實這個問題不難,但由於 IIS Express 一直沒有管理介面,讓人總搞不清楚設定,就參考一下這篇吧。

星期五, 12月 25, 2015

Jenkins + Central Authentication Service, CAS

在 Windows 伺服器上的 Jenkins 要由 https://abc.com/cas 單一簽入的做法:
  1. 取得 https://abc.com 憑證簽署單位的憑證,假設檔名為 StartCom.crt。
  2. 以系統管理員身分在 Jenkins 安裝目錄下命令:jre\bin\keytool.exe -keystore jre\lib\security\cacerts -import -trustcacerts -file StartCom.crt -alias StartCom。
  3. 在 Jenkins 安裝 CAS Plugin,並設定 Security Realm CAS 的 URL、Protocol。

星期二, 12月 15, 2015

CentOS 6 as a Selenium node with Chrome

過去已有 Windows 當 Selenium (web driver) node 的經驗,原本以為換到 Linux 是件很簡單的事,不過實際試著做下來,才知若是 Firefox 還好,Chrome 就很麻煩了:
  1. 若 CentOS 6 還沒有 GUI,要下指令安裝:yum groupinstall "X Window System" "GNOME Desktop Environment" "Desktop" "Chinese Support"。
  2. 若要從遠端操控 CentOS 6 的圖形介面,可以用 VNC。在 CentOS 6 安裝 VNC Server,執行 vncserver :1,用 vncpasswd 命令設遠端連線密碼。從 Mac 連過去甚至 VNC Viewer 都不用裝,在 Safari 瀏覽 vnc://hostname:5901 就可以了。
  3. 在 CentOS 6 安裝 Chrome 已不被 Google 原廠支援,幸好還有位大師指導
  4. 不像 Firefox,所有其他的瀏覽器都需要 Driver 才能與 Selenium hub 溝通,所以要另外下載。所謂「安裝」就是把下載的檔案放在 PATH 所指的路徑即可。
  5. 以上都做了,結果還是不通?可以直接在終端機執行 chromedriver 看是什麼問題,原來還是 libstdc++.so.6 惹的禍。經過上述大師的修正,應該會有兩個以上,可以透過「find / -name libstdc++.so.6」來確認,而且每一個的差異可透過「strings <PATH>/libstdc++.so.6 | grep GLIBC」識別,換另一個版本的也許就好了。
[2016/09/10 補充]
  • CentOS 7 安裝各種 GUI 的說明可參考這篇
  • Chrome 有自動更新的機制,每次事後都要把 /usr/lib64 目錄下的 libstdc++.so.6 指到 /opt/google/chrome/lib 去,否則就是找不到 Chrome Web Driver 的錯誤。

星期六, 12月 12, 2015

Convert .bat to .sh

有一行很簡單的命令:

java -jar a.jar fileB

以上就是 c.bat 批次檔的內容,與 a.jar、fileB 都在同一目錄下,在 Windows 的環境沒問題。既然 Java 是跨平台的,想必可移到 Linux / Mac 的指令稿,但一直不行?也確定這行直接放在終端機跑過沒問題,只是不能從 c.sh 間接地執行。除了 chmod +x 還有別的事要做?後來改成這樣:

#!/bin/bash
java -jar a.jar fileB

結果在 Mac 上是出現這個訊息:

-bash: ./c.sh: /bin/bash^M: bad interpreter: No such file or directory

半信半疑,加了到底是有幫助還是把事情搞得更複雜?幸好看到這篇,在 vi 編輯 c.sh 下兩道指令:

:set ff=unix
:x

終於修好了!

星期三, 12月 09, 2015

C# 對民國年的處理

最近看到很多人自成一格的處理民國年,很醜的就不提了,有的猛一看還不錯:

private string FormatDate0(DateTime dateTime)
{
return dateTime.AddYears(-1911).ToString("yyy/MM/dd");
}

以今天為例,結果是 104/12/09,看來沒問題?但試試 FormatDate0(new Date(2016, 2, 29)) => 105/02/28,知道不行了吧?改進如下:

private string FormatDate1(DateTime dateTime)
{
string returnValue = null;
Calendar taiwanCalendar = new TaiwanCalendar();
int year = taiwanCalendar.GetYear(dateTime);
int month = taiwanCalendar.GetMonth(dateTime);
int day = taiwanCalendar.GetDayOfMonth(dateTime);
returnValue = String.Format("{0:000}/{1:00}/{2:00}", year, month, day);
return returnValue;
}

雖然有點長,但感覺是用比較「正統」的方式在處理。如果真要挑毛病的話,就是年月日必須分開處理,難道沒辦法保留在一起嗎?有人介紹了以下這種:

[SecurityPermission(SecurityAction.Assert, ControlThread = true)]
private string FormatDate2(DateTime dateTime)
{
string returnValue = null;
CultureInfo taiwanCulture = new CultureInfo("zh-TW");
DateTimeFormatInfo formatInfo = taiwanCulture.DateTimeFormat;
Calendar taiwanCalendar = new TaiwanCalendar();
formatInfo.Calendar = taiwanCalendar;
Thread currentThread = Thread.CurrentThread;
currentThread.CurrentCulture = taiwanCulture;
returnValue = dateTime.ToString("yyy/MM/dd");
return returnValue;
}

真的是複雜但優雅!但別急著高興,先不論 SecurityPermission 帶來的一絲不安,有個測試案例結果不太妙,FormatDate2(new Date(2010, 1, 23)) => 99/01/23,開頭的零跑哪去了?怎麼看都是微軟的問題,自力救濟吧:

...
// bugfix begin
//returnValue = dateTime.ToString("yyy/MM/dd");
int year = taiwanCalendar.GetYear(dateTime);
returnValue = String.Format("{0:000}", year);
returnValue += dateTime.ToString("/MM/dd");
// bugfix end
return returnValue;
}

有些畫蛇添足的感覺,看得真不舒服。