星期二, 12月 30, 2014

Visual Studio Express + SpecFlow

  1. refer NuGet package: SpecFlow
  2. copy packages\specflow.1.9.0\tools to C:\SpecFlow190Tools
  3. If *.feature.cs can't be generated with "The element <ImportGroup> beneath element <Project> is unrecognized.  C:\Program Files\MSBuild\12.0\bin\Microsoft.CSharp.targets" error message, refer this to create the specflow.exe.config file. OR, modify the project file: <Project ToolVersion="12.0"... (Visual Studio 2013) -> <Project ToolVersion="4.0"... (Visual Studio 2010 / 2012).

Visual Studio Express + NUnit

星期一, 12月 29, 2014

MsDeploy ERROR_SITE_DOES_NOT_EXIST

這個錯誤訊息可能來自於「來源的辨識錯誤」或真正的「目的位置不存在」,要如何讓前者現出原形?修改一些參數:
當沒有指定部署目的時,仍出現原來的錯誤,就可以澄清這並不是真正的「目的位置不存在」。

nth-child / nth-of-type




星期一, 12月 22, 2014

How to make your IIS web application deployed remotely?

  1. Install IIS with extra "Management Service".
  2. Fully installed "Web Deploy" (reference).
  3. Web Management Service running, and related port opened.
  4. Execute this command:msdeploy.exe -verb:sync -allowUntrusted -source:iisApp=<SourceFolder> -dest:iisApp="Default Web Site\<vDir>",wmSvc=<MachineName>,username=...,password=...
  5. If <SourceFolder> is relative and Error "Site ... Doesn't Exist", try absolute path instead.

How to make your VirtualBox Windows Guest echo the IPv4 ping request?

  1. Bridged network on a wired connection.
  2. Control Panel -> Systems and Security -> Windows Firewall -> Advanced Settings -> Inbound Rules -> (Enable) File and Printer Sharing (Echo Request - ICMPv4-In)
  3. (only for my company) If the guest get a 172.16.100.xxx IP with 255.255.255.0 subnet mask and 172.16.100.1 gateway, release the IPAddress and visit 172.16.100.1 by IE, then register your account for a renewed IP.

星期五, 12月 19, 2014

Web Deploy Installation

為了解決遠端部署 IIS 網站的問題,嘗試在命令列使用 msdeploy.exe,一直不成功。原來透過 Web Platform Installer 預設安裝並不支援,又沒機會改變安裝的選項。所以一定要去網路上抓 WebDeployXxx.msi,並且選完整安裝,或至少多挑「IIS Deployment Handler」這一項。安裝後再檢查一下「Web Management Service」是否啟動了。
還有一件要緊事,如果在 WebDeploy 安裝前並沒有 IIS Management Service(在 Windows Features -> Internet Information Services -> Web Management Tools 底下),即使選完整安裝還是不完整,所以順序也很重要哦!

星期三, 11月 05, 2014

星期四, 10月 30, 2014

SonarQube + PostgreSQL 初體驗

SonarQube 是一個軟體品質管理工具。依據官網的說法單獨安裝試跑只要兩分鐘,雖然我實際上達不到這麼神的境界,但也蠻無趣的,所以就試其他題目:把資料庫改指到 PostgreSQL。雖然這資料庫也是第一次碰,不過這些一大堆人用的東西安裝實在都太簡單,難怪 SonarQube 除了一個 MySQL 的資料安裝範例之外,根本就懶得說明其他資料庫產品。比照建了一個 Database、一個權限夠的使用者,語系注意一下也就差不多了。
SonarQube 架構上可分資料庫、網頁伺服器與分析器三大塊,資料庫支援幾種常見的,除了 Oracle 其他都是透過 JDBC,所以原則上大同小異;網頁伺服器就是個 Java 程式,所以也沒什麼難度;比較特別的是在分析器這塊,官網上列出五種:
  • SonarQube Runner
  • Maven
  • SonarQube Ant Task
  • Gradle
  • CI Engine
這些分析器的對象都是軟體專案,所以要餵原始碼進去;也要給一個資料庫放分析結果,用來與下一次分析做比較。稍微讓我卡住一下的是:預設分析器(SonarQube Runner)與網頁伺服器都有資料庫設定,我只先注意到後者,單獨改設到 PostgreSQL 沒效,反而會讓網頁伺服器開不起來。後來想想,應該是先改分析器的資料連線,拿一個範例專案餵,讓分析器丟資料到 PostgreSQL,然後網頁伺服器也連同一個位置才對。

星期五, 10月 17, 2014

TripleDes 的 InitialVector

以前不知初始向量的作用為何,甚至認為它應該算是金鑰的一部份。原來:
  • 金鑰一致、初始向量一致,加解密才會正確。
  • 有時候忽略初始向量,只有金鑰一致也會正確,是因為加密端與解密端的預設初始向量恰好一致,例如都是零。
  • 金鑰不一致,結果很難看。
  • 金鑰一致,初始向量不一致,只會讓前八個位元組的解密結果錯誤,這個長度恰好就是初始向量的長度。

不是強式名稱就夠了

.NET 的組件相依、參考等問題一直不是很好處理,其中最大的原因應該是出問題時的錯誤訊息很不直覺,過去的經驗總以為嚴守「不進 GAC」、「強式名稱」兩原則就可以清楚的找出用錯組件的問題,但這次又嚇到了!狀況是:使用端參考了一個 A 組件,內有界面與類別實作,簡化後的虛擬碼如下:
  • using com.abc;
  • public IA getA() {
  •     Assembly a = Assembly.LoadFrom("A.dll");
  •     Type t = a.GetType("com.abc.A");
  •     Object o = Activator.CreateInstance(t);
  •     return (IA)o;
  • }
上面這段程式,永遠會在第六行拋出 InvalidCastException,著實令人納悶?用 ildasm.exe 確認過 A.dll 的確有 IA 介面與 A 類別實作,強式名稱與上述程式所參考的也一模一樣,怎麼會有這麼奇怪的錯誤呢?後來看到這篇才令我恍然大悟了,原來第六行的 o 在 Load-From Context, IA 在 Default Context,所以就互相看不到對方,當然就轉不過去啦!
但至今仍不解的是,另外開了個小專案想要重現這個問題,但這錯誤又不會發生?到底還有什麼是我還不知道的?

星期四, 10月 09, 2014

搞定 OCSP

過去一直只仰賴 CRL,最近終於把 OCSP 也搞定。其實幾乎全靠著官網的一篇範例程式,加上對憑證鍊的一些粗淺認識,猜到實務上必須怎麼改才能符合自己的情境。
因為 Google App Engine 無法調整一些敏感的系統參數,所以整理的結果不能上雲端,有點可惜。為了怕以後又要花好多時間回想,這次就連測試程式也配套做好留存。

星期五, 10月 03, 2014

Eclipse Dark Theme

新版 Luna 向 Visual Studio 學習優點是件好事(希望 Xamarin 也趕快跟進吧!),但不應該只做一半:最重要的寫程式那一大片竟然還是白底,得另外加 Color Theme 外掛來解決。

星期五, 9月 12, 2014

一個僅見於 Safari 的網頁回應錯誤

有一個 Servlet 要去抓別人的網頁,解析其中的部份回傳給瀏覽器。測試中無意間發現那個「別人的網頁」有一個神奇字元,只要想吐回 Safari 就會有個用戶端「Failed to load resource: Frame load interrupted」錯誤,但在 Chrome 或 Firefox 不會,留個參考。快速驗證的程式碼如下:
PrintWriter writer = response.getWriter();
writer.print((char)26);
writer.print("You can not see this under Safari 7.0.6 (9537.78.2)");

星期四, 8月 28, 2014

Captcha not supported by Safari

意外!還好現在這不是我的問題,以後再找解法。

GAE 資料的異常

有個在 GAE 已好一陣子的專案,因為最近部署前多做了一個清除的動作,導致以下這種令人摸不著頭緒的錯誤:

javax.jdo.JDOUserException: Persistent class "Class blar.blar.blar does not seem to have been enhanced. You may want to rerun the enhancer and check for errors in the output." has no table in the database, but the operation requires it. Please check the specification of the MetaData for this class.

blar.blar.blar 明明就是早八百年前都在讀寫的資料持久化類別,怎麼可能不見?去 Google 一下,原來別人也發生過,而且解法也令人意想不到:
  • 編輯 Project > properties > Google > App Engine > ORM
  • 移除 src/
  • 新增 src/blar/blar/*.java
重新部署上雲端,總算救回來了。

javascript trim() not supported

這應該算蠻常用的功能,但在 IE 8 或更早的版本都不支援,因此要請 jQuery 幫忙,或參考 MDN 上一個漂亮的解法:

if (!String.prototype.trim) {
  String.prototype.trim = function () {
    return this.replace(/^\s+|\s+$/g, '');
  };
}
不過有時候問題的本質並沒這麼複雜,例如只想要確定欄位是否有輸入任何字,但零到多個空白都算是沒輸入的話,其實這樣也夠了:
  • var trimmed = window.document.getElementById("someField").value.replace(/ /g, "");
  • if (trimmed == "") {
  •    alert("nothing");
  • }

建立 MS SQL 資料庫,或當已存在時打掉重建

DECLARE @Database sysname;
DECLARE @Collate varchar(MAX);
SET @Database = 'Your_Database_Name';
SET @Collate = 'Chinese_Taiwan_Stroke_Bin';

IF (@Database LIKE '%[^0-9A-Z_]%')
    RAISERROR('Invalid Characters in Name, %s', 16, 1, @Database);
ELSE
    DECLARE @Quote varchar(MAX);
    SET @Quote = QUOTENAME(@Database);
    USE master;
    IF EXISTS (SELECT * FROM sys.databases WHERE Name = @Database)
        BEGIN
            EXEC('ALTER DATABASE ' + @Quote + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE');
            EXEC('DROP DATABASE ' + @Quote);
        END
    EXEC('CREATE DATABASE ' + @Quote + ' COLLATE ' + @Collate);
    EXEC('ALTER DATABASE ' + @Quote + ' SET MULTI_USER WITH ROLLBACK IMMEDIATE');

星期四, 8月 07, 2014

Web Notifications

新玩意兒!不過暫時只能在非 IE 上跑。可參考 https://developer.mozilla.org/en-US/docs/Web/API/notification

在 html table 列間插入 hr

因為 <hr> 總是會被瀏覽器在排版的時候丟到 <table> 外面去,變通做法如下:

<table style="border-collapse: collapse;">
    <tr>
        <td>1</td>
    </tr>
    <tr>
        <td>2</td>
    </tr>
    <!-- <hr /> -->
    <tr style="border-bottom: 1px solid black;">
        <td>&nbsp;</td>
    </tr>
    <tr>
        <td>&nbsp;</td>
    </tr>
    <tr>
        <td>A</td>
    </tr>
</table>

星期六, 8月 02, 2014

在瀏覽器取得時區

利用 JavaScript,可以取得 GMT±hhmm 這樣的字串,傳回伺服端用以(國際標準時區)日期時間轉字串處理。
  • 34: 因為 getTimezoneOffset() 回傳的是「加上這個值成為 GMT」,與我想要的「GMT 加上這個值成為當地時間」意義相反,所以變號處理。
  • 36: 負值一律變正,已便後續統一處理正值即可。
  • 42: 不是每個時區與 GMT 都恰好只差幾個小時,也有不整除的。
  • 44 ~ 49: 時、分都補滿到兩位數。

星期四, 7月 10, 2014

上了七朵雲

這兩年來只上第一朵雲,其實內容是純靜態的,不涉及後台程式語言,所以大可搬家。這些都是短期或長期免費的,也都搬成功了:
  • my-name.appspot.com
  • my-name.azurewebsite.net
  • my-name.apphb.com
  • my-name.herokuapp.com
  • my-name.elasticbeanstalk.com
  • jbossews-myname.rhcloud.com
  • my-name.cloudcontrolled.com

星期六, 7月 05, 2014

對 ActiveX 授權以限制非法使用

由於 ActiveX 是部署在網頁,下載到使用者的電腦執行,略懂的人就有辦法拿來「再利用」,而且無需發行 ActiveX 一方的同意。雖然網路上也有些專業販賣 ActiveX 元件的公司對自己的心血保護,但他們的做法大多不能防止「一魚多吃」或「非法挪用」的狀況。

利用 url 具有唯一性的特徵,可以用這樣的設計來限制非法使用:
  • 授權檔就是一個 JavaScript,定義其本身預計部署的 url 與「授權書」兩個變數。
  • 申請授權就是決定 url,發行 ActiveX 的一方視為待簽原文,用簽署 ActiveX 的憑證簽出「授權書」。
  • 帶有 ActiveX 的網頁也要引入授權檔。
  • 任一 ActiveX 公開方法都要檢查內部的「授權通過」旗標,若值為否,則直接拋出例外而不執行任何功能。
  • ActiveX 載入時就要檢查授權檔的兩個變數,若能取得,該 url 又確實是其載入的位址,授權書也能通過簽署 ActiveX 憑證的驗簽,則設「授權通過」為真。

星期四, 6月 19, 2014

包不出一個支援多國語系的 ActiveX cab

ActiveX 本身的組件預設會產生在 bin\Debug 目錄下,而各語系資源會在 bin\Debug\[lang] 目錄下,以正體中文為例,會在 bin\Debug\zh-TW 目錄下。只要包裝時 cabarc.exe 下了 -r -p 這兩個參數,雖然多國語系的資源檔都確實進了子目錄,但使用端始終無法將 ActiveX 安裝成功。

但如果在使用端手動將多國語系的子目錄與資源檔補上,多國語系的功能看來是正常的,所以問題應該在 IE 解完 cab 之後的動作,根本就不能處理有子目錄的狀況。

後來的土解法:將 bin\Debug 目錄下的所有子目錄與檔案先包成一個 cab,再把這個 cab、能解這個 cab 的 cabarc.exe 以及其他的檔案再包一個 cab,並寫好用戶端安裝的步驟,第一就是把裏面的 cab 還原到安裝目錄去。

星期一, 6月 16, 2014

在新環境執行舊版 ActiveX 元件

過去有個用 .NET Framework 2 編譯的 ActiveX 元件,一直都沒什麼問題。但現在愈來愈多用戶端是 Windows 8 或 Windows 8.1,內建就是 .NET Framework 4 以上,對於一般的元件來說,可以利用 App.config 或是 Web.config 指定 RuntimeVersion 解決,但 ActiveX 沒機會。要求使用者加裝 .NET Framework 2 是可行,只不過要費許多口舌。所以只好在 ActiveX 下載安裝的過程最後改機碼,將以下
  • ...\Software\Classes\CLSID\{...}\InprocServer32\1.2.3.4
    • RuntimeVersion=v2.0.50727
改成
  • ...\Software\Classes\CLSID\{...}\InprocServer32\1.2.3.4
    • RuntimeVersion=v4.0.30319
當然,也必須有配套判斷,在使用者環境只有 .NET Framework 4 的條件下,才做上述的修改;在 .NET Framework 2 以及 .NET Framework 4 兩者並存的條件下,就沒有必要改。

星期六, 6月 14, 2014

執行 Powershell 指令稿

在 Windows 8.1 預設只能執行單行指令,包了多行的指令稿檔案是受限制的,詳請在。但我們可以下一行指令來開放:
  • Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
記得要用管理權限哦!

自製大頭照

為了護照過期,要做二吋的證件照。請公主用數位相機幫忙,留下幾點備忘:
  • 在白牆白燈的房間照
  • 儘量增加不同方向的光源,以減少陰影
  • 相機正對人頭,距離在一到二公尺之間
  • 用修圖軟體將人頭周圍的背景塗白
  • 用 Photocap 套 4*6 一式八張的樣版
  • 到便利商店洗「立可得」一張六元

星期四, 6月 05, 2014

使用 MSDeploy 安裝憑證

依據這一篇文章,我們知道微軟對於憑證存放區至少分了八塊,再看到這一篇文章,另人失望地寫明「僅支援 My 存放區」。對此高度存疑的我,為了要信任一個懶惰又小氣的安全網站,不死心地嘗試,結果還是突破了 My 的限制,成功地將憑證放到「受信任的人」存放區,我想要訣可能是權限要夠,而且必須同時指定憑證的目標存放區與雜湊值,還有「盡信書(官網)不如無書(官網)」吧?

星期五, 5月 23, 2014

Selenium IEDriverServer.exe (x64) + IE10 慢到爆

凶手不是 IE10 (x64) 就是 IEDriverServer.exe (x64),後者換 32 位元的版本就解決了。原始出處在

星期二, 5月 13, 2014

Mark of the Web

要用 IE 檢視位於本機的網頁,安全性設定還有點繁瑣,所以另一個辦法就是讓瀏覽器認為這是網路上的資源。通常在網頁的前兩行可以加上:

<!doctype html>
<!-- saved from url=(0023)http://www.contoso.com/ -->

其中第一行有點離題了,放在這裹是為了釐清它們之間的順序,第二行才是重頭戲。其實最常用的設定會是下面兩者之一:

<!-- saved from url=(0014)about:internet -->
<!-- saved from url=(0016)http://localhost -->

星期四, 4月 24, 2014

Jenkins 又一難題:LDAP

為了讓 Jenkins 的使用者由 LDAP 接 AD 驗證,參考別人的設定硬是不行。因為每一家的 LDAP 有什麼內容都不會一樣,所以這題也解很久:原來雖然驗證通過了,但後來找使用者所屬群組(其實似乎沒必要)出問題,會導致丟給 acegisecurity 的驗證物件是空的,不過並沒有拋出例外,只有驗證失敗的結果,乍看起來與密碼打錯沒什麼不同,但一直追到很細的記錄才看出些端倪。有圖為證:
其實當初也不懂這有什麼異常,不過先是區分出密碼打錯絕不是長這樣,再苦思、狂搜,最後靈感來自於,狀況類似,多設一個群組的搜尋起點就解決了。

[2019/04/09]
沒想到改用 Single-Sign On 後的多年,還是有機會需要這篇,而且補上兩點:
  • 當 Jenkins 安裝在很舊的 Windows 上,中文可能不是 UTF-8,當做任何欄位設定內容都可能出錯,要儘量避免,例如 Manager DN 就可改為電子郵件格式。
  • 即使沒用到群組,不設群組的相關條件也可能造成問題,可以考慮至少要放個純英文的條件,找不到任何群組也無妨。

星期二, 4月 22, 2014

Jenkins OpenCover

在整合這兩個東西時,以下的問題大概卡了快兩天:
路徑要確實搞懂,可以先在 Visual Studio 利用 Post-Build 單獨先搞清楚 OpenCover、NUnit 的關係,再搬到 Jenkins 一步步比對。
網路上有人提過要安裝 Visual C++ 2010 Redistributable,不過對我在 Windows Server 2008 R2 上的 Jenkins 沒有作用。
最後終於找到解法:Jenkins 服務的帳戶要改成本機的系統管理員,權限夠就過了。

[2015/06/08]
正解有兩種做法:
  • Jenkins 服務的帳戶要被賦予系統管理權限
  • 以系統管理權限在 OpenCover.Console.exe 所在目錄執行 regsvr32 x86\OpenCover.Profiler.dll 或 regsvr32 x64\OpenCover.Profiler.dll

來源出自於這篇文章

星期四, 4月 17, 2014

取得伺服器的加密憑證

openssl s_client -connect hostname:port 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > filename

在 Mac 遠端桌面連線到另一部 Windows 電腦

首先要釐清一點:有兩個微軟出的應用程式,「Remote Desktop Connection Client for Mac」和「Microsoft Remote Desktop」,他們是不同的。前者已經是舊物了,後者有在 Mac App Store 上架,推薦使用。
第一次使用 Microsoft Remote Desktop 遇到個算嚴重的問題,分享 Mac 的目錄竟然不會出現在 Windows 檔案總管?原來分享的名稱是有關係的,Desktop 不行,myDesktop 就可以。

星期二, 4月 15, 2014

查詢 NuGet 套件的所有可下載版本

在 Visual Studio 2010 以後,使用 NuGet 做為套件管理是比較好的做法。但官網上永遠只有一個穩定版,頂多再一個預先釋出版,有時候是不符現實需求的。其實這種一加一的版本限制只在圖形介面,若使用 Package Manager Console 下指令還是可以突破的。不過以下這招實測無效,曾有人回報過是官網的問題:

Get-Package -ListAvailable -Filter <keyword> -AllVersions

以下這個是目前可行的變通做法:

Install-Package <PackageId> -Version〔空格〕〔定位鍵〕

如果只是查詢不要安裝,最後不要按 Enter 就好了。

[2014/08/12]

過去實測無效的指令,如今試來是可以的。

IIS 7.5 虛擬帳戶問題

IIS 7.5 以後,預設使用 ApplicationPoolIdentity 這個身分執行應用程式集區。有許多文章提到將實體目錄授權給這個身分的方法:
  1. 在檔案總管對該目錄按右鍵,選「Properties」、「Security」、「Edit」、「Add」。
  2. 確認「Locations」的內容是本機電腦名稱。
  3. 假設應用程式集區名稱是 DefaultAppPool,在文字方塊內輸入 IIS AppPool\DefaultAppPool,再按「Check Names」,如果名稱解析成功,會有底線。
  4. 賦予讀取權限。
以上都完成後,還是有可能看不到網頁,此時請檢查:
  1. 伺服器、應用程式集區、網站等是否啟動。
  2. 網址不完整時,是否有匹配的預設文件。
  3. 如果接受匿名驗證,匿名使用者對應的身分是否就是 ApplicationPoolIdentity。

星期一, 3月 31, 2014

Ubuntu 12.04 OpenLDAP nodomain

依據這篇說明的做法,在 Ubuntu 12.04 安裝的 OpenLDAP 會參考 /etc/hosts 所設的網域名稱,但實際的結果卻是無效?不論怎麼設,網域名稱都是 nodomain。後來找到解法如下:
http://superuser.com/questions/470825/openldap-slapd-conf-substitutions-ubuntu

星期四, 3月 27, 2014

Minimum JNDI-JDBC requirement

在 Eclipse + Tomcat,做一個最小需求的 JNDI JDBC 連線測試環境:
  1. sqlite jdbc jar
  2. context.xml
  3. web.xml
  4. 部署位置
  5. NewFile.jsp
<%@ page import="java.util.*" %>  
<%@ page import="java.sql.*" %>  
<%@ page import="javax.sql.*" %>  
<%@ page import="javax.naming.*" %>  
<%@ page language="java" contentType="text/html;charset=UTF-8" %>  
<%
Object o = session.getAttribute("m");
HashMap<String, Connection> m = null;
if (o == null) {
m = new HashMap<String, Connection>();
}
else {
m = (HashMap<String, Connection>)o;
}
  Connection con = null;
  try {
  Context initContext = new InitialContext();
  if (initContext == null) {
  out.println("initContext null");
  } else {
  Context envContext = (Context) initContext.lookup("java:/comp/env");
  if (envContext == null) {
  out.println("envContext null");
  } else {
  DataSource ds = (DataSource) envContext.lookup("jdbc/myDataSource");
  if (ds == null) {
  out.println("ds null");
  } else {
  // get connection
  String parameterGet = request.getParameter("get");
  if (parameterGet == null) {
  }
  else {
  int newCount = m.size() + 1;
  while (true) {
  con = ds.getConnection();
    String connectionId = String.valueOf(con.hashCode());
    m.put(connectionId, con);
    if (m.size() == newCount) {
      session.setAttribute("m", m);
    break;
    }
  }
  }
  // close connection
  String parameterClose = request.getParameter("close");
  String pool = request.getParameter("pool");
  if (parameterClose == null || pool == null) {
  }
  else {
  Iterator<Map.Entry<String, Connection>> iter = m.entrySet().iterator();
  while (iter.hasNext()) {
      Map.Entry<String, Connection> entry = (Map.Entry<String, Connection>) iter.next();
      String key = entry.getKey();
if (key.equals(pool)) {
m.remove(key);
session.setAttribute("m", m);
break;
}
  }
  }
  }
  }
  }
  } catch (SQLException sqle) {
  out.println("sqle=" + sqle);
  } finally {
  if (con == null) {
  } else {
  con.close();
  con = null;
  }
  }
  %>  

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Insert title here</title>
</head>
<body>
<form>
<div>Connection Pool:</div>
<select name="pool" size="10">
<%
Iterator<Map.Entry<String, Connection>> iter = m.entrySet().iterator();
while (iter.hasNext()) {
    Map.Entry<String, Connection> entry = (Map.Entry<String, Connection>) iter.next();
    String key = entry.getKey();
    out.println("<option>" + key + "</option>");
}
%>
</select>
<div>
<input type="submit" name="get" value="get" />
<input type="submit" name="close" value="close" />
</div>
</form>
</body>

</html>

星期四, 2月 27, 2014

在 Eclipse 快速建立 Spring Web 專案

這件事可能很簡單,但網路上竟然也找不到類似的文章。多方嘗試後,發現這種做法最乾淨俐落:
  1. 建 Dynamic Web 專案。
  2. 轉換成 Maven 專案。
  3. 需要參考外界的 Jar 時,一律透過 Maven Repository,也就是先上網找好 Maven 的 GroupId、ArtifactId、Version 等,這裏麻煩一點,未來好處多多。
  4. 用 Maven Clean、Maven Install 取代 Build。

驚魂記

授課前一分鐘發現電腦登不進去,太慘了!幸好蘋果線上給了救急的辦法,只把課延後了一小時,不致於開天窗。事後檢討,外接投影機的插拔可能是主因,但這樣會造成平時用的帳戶無法登入?好像是因為解析度不被接受,驗證密碼正確後無法顯示又跳出來。誰叫我那條線為了省幾百元不買原廠的呢?

星期二, 2月 11, 2014

VirtualBox Guest - Guest Network on one Host

很簡單的做法:
  1. 各 Guest 都多加一個網路介面,選擇 Bridged。
  2. 各 Guest 開機後都可以查得自己的網址,其中有一個會是與其他 Guest 在同一網段內,雖然 Ping 可能不通,但也許 Web Services 是通的,至少在 Windows 世界稍微試過的結果是這樣。

Windows Server 2012 R2 Essential

這個版本不太好玩,很基本的 IIS 裝起來都連不進去,還是乖乖用 Standard 比較簡單,也不用 License 就能評估了。

星期二, 1月 28, 2014

抽換 IIS Express SSL 憑證

這件事在一般的網站伺服器都不難(可參考這篇),但誰叫 IIS Express 沒有管理介面這麼陽春呢? 先來談一下在 IIS Express 如何測試 https?其實還真簡單,只要到專案的屬性頁去找「SSL Enabled」設定就可以了,但為什麼不必(也不能)指定憑證與金鑰對呢?其實是在 Visual Studio 2013 Express for Web 安裝過程中,就已建立了一個本機用的伺服器憑證。 為了讓外界訪問非以 localhost 為名的網站(可參考這篇),並且通過 SSL 加密,必須準備另一個憑證來抽換,以下是簡略的步驟:
  1. 雖然是在 Windows 8.1 64 bits + Visual Studio 2013 Express for Web 測試,但必須事先額外安裝的是 Windows 8 SDK(現在好像還是沒看到 Windows 8.1 SDK?),而且使用 x86 目錄(微軟官網自承用 x64 會有問題)下的工具產生一個自簽憑證,命令如下:MakeCert.exe -r -pe -n "CN=yourhostname" -eku 1.3.6.1.5.5.7.3.1 -ss my -sr LocalMachine -sky exchange
  2. 用 MMC 將上述憑證由「個人」區匯出到 pfx 檔案,記得要匯出私鑰與延伸屬性,再匯入到「信任的根憑證」區。注意:一不能用拖拉,二不能刪了舊的。
  3. 準備上述憑證的姆指紋,去除分隔用的空白。
  4. 用以下指令清除舊的安全通道與憑證繫結:netsh http delete sslcert ipport=0.0.0.0:443
  5. 用以下指令建立新的安全通道與憑證繫結:netsh http add sslcert ipport=0.0.0.0:443 appid={214124cd-d05b-4309-9af9-9caa44b2b74a} certhash=thumbprint

關於使用微軟工具處理憑證

此人真是先進! http://blogs.microsoft.co.il/applisec/2008/04/08/creating-x509-certificates-using-makecertexe/

星期一, 1月 27, 2014

解放 IIS Express 的快速做法

IIS Express 通常有兩個限制:
  • 只能藉由 localhost,不能透過真實的主機名稱訪問。
  • 埠號小於 1024 時,必須以系統管理權限啟動。
如果真的深究下去,讀者們可能會發現以上這些敘述不是那麼精準(或直接相關)的,我先承認!不過本篇的重點在如何突破這些限制,做法也很簡單(二選一):
  • 請參考 http://www.hanselman.com/blog/WorkingWithSSLAtDevelopmentTimeIsEasierWithIISExpress.aspx 的附錄 Z,以系統管理權限在命令列執行「C:\Program Files (x86)\IIS Express>IisExpressAdminCmd.exe  setupFriendlyHostnameUrl -url:http://myHostName:80/」。
  • 在 applicationHost.config 新增相關的 binding。
以上這些方式還是有個小小限制,不能將主機名稱設得像 www.abc.com 這種形式,如果一定要,還是請自行修改 hosts 吧!

[2018/08/27] 為了找到正確的 applicationHost.config,還得花一番工夫,所以再補充一下:
  • system tray > Show All Applications > Config
  • change bindingInformation from *:80:localhost to *:80:

星期二, 1月 21, 2014

使用 Eclipse 瀏覽藉由 Maven 管理的專案原始碼

安裝設定需求
  • JDK 最新版,不需設定環境變數等內容
  • Eclipse for Java EE 最新版,會自動搜尋電腦上已安裝的 Java
  • 不需額外安裝 Maven 或插件,使用內建版本即可
做法
  • 隨意新增一個 Maven 專案,groupId 與 artifactId 可以任意填寫,template 選預設的 quickstart 即可。
  • 編輯 pom.xml,新增一個 dependency,groupId、artifactId、version 要填人家正式公佈的,例如 org.jasig.cas / cas-server-webapp / 3.5.2。存檔。
  • 需有網路連線。
  • 在專案上右鍵所出現的選單有 Maven -> Download Sources。
  • 在 Maven Dependencies 展開可見相依的 Jar 檔,進一步展開即可見原始碼。