星期五, 4月 24, 2009

解開intel晶片組driver infinst_autol.exe的方法

又一篇個人筆記。

為了替優秀長官在VAIO Z上安裝Windows Server 2003,之前用nLite做的Windows Server 2003 整合 ich9 driver開機光碟已經不能用,所以只好再找driver來整合。

但是Intel現在已經更新 infinst_autol.exe 的做法,解開安裝後馬上又刪除原始檔,所以我只好輸入infinst_autol.exe /?看有什麼參數可用,最後用infinst_autol.exe -a -f2 C:\temp ,這樣會在C:\temp產生log檔,再從log找到安裝的暫存目錄,這時候就會發現暫存目錄並未刪除。若未加參數時,Log檔會在 C:\Intel\Logs\IntelChipSet.Log,裏面寫的暫存目錄是立即刪除,連安裝過程切換視窗都找不到。

星期一, 4月 20, 2009

列舉目錄下所有檔案的C# class

剛在噗浪上看到有人花了不少時間寫列舉目錄下所有檔案的class,記得當初鳥毅也在CodeProject上找了一會兒,以下是鳥毅改寫的Code(原始出處忘了留:P ),授權以原始出處為準(逃~)
Update:我改寫的class似乎太像(十年前的)Java,請看回應laneser寫的版本,這才是.Net風格呀。
using System;
using System.Collections;
using System.IO;

namespace tenyi.io
{
public class FileExplorer
{
public ArrayList FileList = new ArrayList();
public ArrayList extensionLists = null;
private string myPath = null;
private bool recursive = true;
private DateTime lastDateTime = new DateTime(1, 1, 1);

public DateTime LastDateTime
{
get { return lastDateTime; }
}

public FileExplorer(string path)
{
myPath = path;
recursive = false;
FileList = GetFiles(myPath);
}

public FileExplorer(string path, string filter)
{
myPath = path;
recursive = false;
FileList = GetFiles(myPath, filter);
}

public FileExplorer(string path, ArrayList extensions)
{
myPath = path;
extensionLists = extensions;
recursive = false;
FileList = GetFiles(myPath);
}
public FileExplorer(string path, ArrayList extensions, string filter)
{
myPath = path;
extensionLists = extensions;
recursive = false;
FileList = GetFiles(myPath, filter);
}


public FileExplorer(string path, bool recursive)
{
myPath = path;
recursive = recursive;
FileList = GetFiles(myPath);
}

public FileExplorer(string path, string filter, bool recursive)
{
myPath = path;
recursive = recursive;
FileList = GetFiles(myPath, filter);
}

public FileExplorer(string path, ArrayList extensions, bool recursive)
{
myPath = path;
extensionLists = extensions;
recursive = recursive;
FileList = GetFiles(myPath);
}

public FileExplorer(string path, ArrayList extensions, bool recursive, DateTime theTime)
{
myPath = path;
extensionLists = extensions;
recursive = recursive;
FileList = GetFiles(theTime, FileDateCompare.GreatThan);
}

public ArrayList GetFiles(string strPath)
{
return GetFiles(strPath, null);
}

public ArrayList GetFiles(string strPath, string filter)
{
DirectoryInfo dir = new DirectoryInfo(strPath);
FileInfo[] files;
DirectoryInfo[] dirs;
ArrayList List = new ArrayList();

//if the source dir doesn't exist, throw
if (! dir.Exists)
{
throw new Exception("Source directory doesn't exist: " + strPath);
}

if(filter == null)
{
//get all files in the current dir
files = dir.GetFiles();
}
else
{
files = dir.GetFiles(filter);
}

foreach (FileInfo file in files)
{
if (extensionLists == null)
{
List.Add(new FileData(file.FullName, file.Name, file.Extension, file.Length, file.LastWriteTime));
}
else
{
if (checkFile(file.Extension))
{
List.Add(new FileData(file.FullName, file.Name, file.Extension, file.Length, file.LastWriteTime));
}
}
}

files = null;

//if not recursive, all work is done
if (! recursive)
{
return List;
}

//otherwise, get dirs
dirs = dir.GetDirectories();

//loop through each sub directory in the current dir
string tempDir;
foreach (DirectoryInfo subdir in dirs)
{
tempDir = subdir.FullName;
ArrayList temp = new ArrayList();
temp = GetFiles(tempDir);
for (int i = 0; i < temp.Count; i++)
{
FileData TempData = (FileData) temp[i];
List.Add(new FileData(TempData.FullName, TempData.Name, TempData.Extension, TempData.Length, TempData.LastWriteTime));
}
}
dirs = null;
dir = null;
return List;
}

public ArrayList GetFiles()
{
return GetFiles(myPath);
}

public ArrayList GetFiles(DateTime dt, FileDateCompare state)
{
DirectoryInfo dir = new DirectoryInfo(myPath);
FileInfo[] files;
DirectoryInfo[] dirs;
ArrayList aList = new ArrayList();

//if the source dir doesn't exist, throw
if (! dir.Exists)
{
throw new Exception("Source directory doesn't exist: " + myPath);
}

//get all files in the current dir
files = dir.GetFiles();

//loop through each file
foreach (FileInfo file in files)
{
if (extensionLists == null)
{
if (file.LastWriteTime.CompareTo(dt) > 0)
{
aList.Add(new FileData(file.FullName, file.Name, file.Extension, file.Length, file.LastWriteTime));
if (file.LastWriteTime.CompareTo(lastDateTime) > 0)
{
lastDateTime = file.LastWriteTime;
}
}
}
else
{
if (checkFile(file.Extension))
{
if (file.LastWriteTime.CompareTo(dt) > 0)
{
aList.Add(new FileData(file.FullName, file.Name, file.Extension, file.Length, file.LastWriteTime));
}
if (file.LastWriteTime.CompareTo(lastDateTime) > 0)
{
lastDateTime = file.LastWriteTime;
}
}
}
}

//cleanup
files = null;

//if not recursive, all work is done
if (! recursive)
{
return aList;
}

//otherwise, get dirs
dirs = dir.GetDirectories();

//loop through each sub directory in the current dir
string tempDir;
foreach (DirectoryInfo subdir in dirs)
{
tempDir = subdir.FullName;
ArrayList temp = new ArrayList();
temp = GetFiles(tempDir);
for (int i = 0; i < temp.Count; i++)
{
FileData TempData = (FileData) temp[i];
aList.Add(new FileData(TempData.FullName, TempData.Name, TempData.Extension, TempData.Length, TempData.LastWriteTime));
}
}

//cleanup
dirs = null;
dir = null;
return aList;
}

public ArrayList GetDirectories()
{
return GetDirectories(myPath, null, recursive);
}

public static ArrayList GetDirectories(string path, ArrayList filter, bool isRecursive)
{
DirectoryInfo thisDirectoryInfo = new DirectoryInfo(path);
ArrayList arrayList = new ArrayList();

DirectoryInfo[] subDirectoryInfos;

//if the source dir doesn't exist, throw
if (! thisDirectoryInfo.Exists)
{
throw new Exception("Source directory doesn't exist: " + path);
}

//get dirs
subDirectoryInfos = thisDirectoryInfo.GetDirectories();

//loop through each sub directory in the current dir
string tempDir;
if (subDirectoryInfos.Length == 0)
{
if (filter == null)
{
arrayList.Add(thisDirectoryInfo);
}
else
{
if (filter.Contains(thisDirectoryInfo.Name))
{
arrayList.Add(thisDirectoryInfo);
}
}
}

foreach (DirectoryInfo subdir in subDirectoryInfos)
{
tempDir = subdir.FullName;
ArrayList temp = new ArrayList();
//if not recursive, all work is done
if (isRecursive)
{
temp = GetDirectories(tempDir, filter, isRecursive);
for (int i = 0; i < temp.Count; i++)
{
arrayList.Add(temp[i]);
}
}
else
{
if (filter == null)
{
arrayList.Add(subdir);
}
else
{
if (filter.Contains(subdir.Name))
{
arrayList.Add(subdir);
}
}
}

}

subDirectoryInfos = null;
thisDirectoryInfo = null;
return arrayList;
}

private bool checkFile(string strExtension)
{
bool throwaway = true;
for (int j = 0; j < extensionLists.Count; j++)
{
if (extensionLists[j].ToString().ToLower() == strExtension.ToLower())
{
throwaway = false;
}
}

if (throwaway)
{
return false;
}
else
{
return true;
}
}
}
}

Subversion不能merge時的處理

又是一篇個人筆記。

優秀主管帶領的優秀團隊在MCSD.Net Joseph兄的努力之下,目前已經進到coding階段,Joseph兄指導其他同仁把自己開發的模組放到branch避免干擾,但開始發現SVN令人詬病的merge問題。

由於處於開發初期,某些核心程式還不斷地更新,因此Joseph必須常更新trunk上的程式,而其他成員把trunk合併到自己的branch時常遇到問題。

以下為merge的標準步驟:
  1. 先commit自己的branch
  2. 再update自己的branch(這是因為TortoiseSVN的要求,不做不能merge)
  3. 把trunk合併到自己的branch
  4. 解決衝突
  5. 最後commit解決衝突的branch
  6. 必要時再把branch合併到trunk,方法如1~5。
講起來容易做起來難,尤其是遇到奇怪現象時需要靠經驗解決,有時候設定了svn:ignore的性質變動,會造成每次merge都有衝突,此時砍掉重練branch似乎比較快呀Orz

今天有兩位同事把TortoiseSVN從1.6.0升級到1.6.1後,合併時出現infinite depth的錯誤,個人猜測是.svn裏不知出什麼錯,也是砍掉重練才正常。

結論:終於知道為什麼gslin要把全公司的repository換成Git了。

星期四, 4月 16, 2009

試用多個Subversion GUI Client

為了協助優秀長官的計畫,先協助導入Subversion,我用Apache+SSPI/NTLM整合認證。接著要讓組員們能夠上手svn。要瞭解trunk/branches/tags的用法真是花了不少口水,雖然在公用磁碟有放jserv老大的優秀投影片,但同事們都趕著做案子沒看。我只能個別指導,公司找我這個時薪200元的打雜網管,有些不划算(加班就乘以1.33了呀) =_=

首先建議同事們用TortoiseSVN,在Windows下是首選(我自己用command line),再配合AnkhSVN在Visual Studio整合使用。TortoiseSVN現在有版本圖,與我4年前使用時大不同,穩定性也高。相對之下,RapidSVN就遜多了,在Linux下也會常crash,因此不予考慮。

但是問題來了,有修改目錄性質後,trunk與branch的merge常會發生衝突,TortoiseSVN在這方面雖然有進步,但仍然不強,所以我就試一下其他的Subversion GUI Client。

首先用的是SmartSVN,雖然說功能比較強,但Java的速度就比不上native的client,當然可能與SVNKit實作方式有關,不過時間就是金錢,等到有衝突時再來測,這方面可以參考 http://selainsoft.blogspot.com/2008/01/smartsvn-and-svnkit-javasvn.html 。
接著測eSVN,看來是打算和RapidSVN拼,但從2007年後就沒有新版看來,又是一個無疾而終的專案。再測SubCommander,介面有點類似SmartSVN,但是功能遜多了。

最後一定要提:Subversion的working copy會自動升級,因此若使用最新版的TortoiseSVN後,就無法再使用RapidSVNSubCommander等GUI,只能與SmartSVN beta合併使用,其實會造成困擾,所以若想同時用多種client,只能用舊版的TortoiseSVNAnkhSVN

結論:對大部份的使用者而言,在Windows用TortoiseSVN是最好的選擇;若是idea的瘋狂愛用者,可以選擇SmartSVN。遇到衝突時,就call團隊裏的高手支援吧!

星期三, 4月 15, 2009

用CSS達成BorderColorLight及BorderColorDark的效果

今天在改一個asp的舊網頁,用CSS怎麼都設不出原來用html的BorderColorLight及BorderColorDark畫面好看,後來google找到 http://www.zeali.net/entry/412
原來要放棄CSS的簡單設定法
table
{
border: 3px outlet #ade1ff;
}

要設成類似
table
{
border-top: 3px solid #ade1ff;
border-left: 3px solid #ade1ff;
border-right: 3px solid #4284e4;
border-bottom: 3px solid #4284e4;
padding: 0px;
margin: 0px;
border-spacing: 0px;
border-collapse: collapse;
}

星期三, 4月 01, 2009

機瘟

今天真不是個開玩笑的好日子。

星期一早上,正準備開始寫要交給優秀長官的報告時,有人反映網路磁碟不太穩,到了九點多,整台機器完全連不上去。跑到機房去看,根本整台hang住,連ping都沒反應。只好hard reset,經過2小時漫長的check disk後,幸好沒有嚴重的錯誤,等到13:00也重開成功。沒想到才半小時,機器又當掉了,這次不敢再讓機器慢慢的check disk,重開後先停用NOD32。記得在NOD32 3.0剛發布時也有類似的情況,這次有可能是NOD32 4.0惹得禍,不由得懷念起表現得中規中矩的OfficeScan。

昨天下午公司忽然網路出現異狀,查看之下發現有電腦亂發arp資訊,相信是中了arp病毒。
本部落格的忠實讀者應該記得,敝公司和相關企業是class B broadcast的網段,總公司與分公司也透過VPN連線,約有1000台PC在一個Lan...

因此,整個企業的網路就這樣被一台中毒的PC癱瘓。記得十幾年前,中央大學全校走一個gateway,因為某一台電腦把自己的IP設成gateway而造成全校網路不通。

由於Core Switch是相關企業負責,等了2小時後,相關企業資訊部查出來是敝公司的分部殺的人,小弟只好先拔VPN,今天再去擦屁股找出元兇。

早上八點就趕往分部,沒想到遇到白爛司機,說話比史特龍還不清楚,假設史特龍含了一顆蛋,他大概含了兩顆蛋。雖然敝公司分部位於市郊,但好歹也算是台北市,居然有司機路搞不清楚,叫他走平面就硬給我走高架橋,多繞了兩公里;又在單行道開過頭,害我平時150元能到的地方硬是跑到220元。

由於借了部門經理的高檔Notebook出門,當然到了分部就把Notebook接上switch hub,用二分法找出元兇,這部份花不到半小時就搞定。但因為分部的網路線拉得很怪異,本來想用埠號找出元兇實行上很困難,只好在SZ上偷偷地裝了WinPcapWireShark,其實這個狀況用SmartSniff就夠了,因為我是把連到元兇的網路線直接插上SZ,只要能看到IP或Windows機器名稱即可。找到機器後用Trendmicro提供的好工具iClean去掃毒,可惜沒掃完iClean就hang住,試了幾次無效只好帶回公司重灌。

回到公司已經中午,下午處理些雜事後幫優秀長官的team開了一個Subversion Repository,再把對應網域權限設好(請參考:Subversion+Apache的NTLM/SSPI認證)。正當MCSD.Net同事把他的Rainbow Portal Project丟上去到一半時,就爆炸了當機了。

雖然快下班了但我也只好跑到機房去看發生什麼事情,當KVM切換到那台Subversion Server時出現美麗的藍天白雲....是藍屏死機。重開機兩次都無法啟動,安全模式也進不去。不知道該說幸還是不幸,由於是一般的爛PC,所以就整台抱到我的座位上開始分屍拆機。把硬碟拆下用自費買的usb線接上我的Win7掃描磁碟,掃描在Stage2不到一半就卡住了,Win7確實優秀,若是XP可能會整台hang住,Win7只要把CMD視窗關掉就沒事。

慶幸的是只有系統碟掛點,Subversion Repository依然健在,利用去年備份的tib檔,拿了另一顆80GB IDE硬碟,快速地重建回來。當然得退出網域重新加入,再更新ApacheSubversion和一堆阿里不達的東西,以及最重要的Windows Update。所以整台修好又過了一個多鐘頭,原本預訂今天要交給優秀長官的報告依然一字未動... 答應美麗的MIS小姐要幫她更新的次要SQL Server 也還沒動,又得回家用VPN免費加班。

Today is not my day.
今天真不是個開玩笑的好日子。