2010年12月16日 星期四

[C#] 基本網路技術(二) IP 位址與主機名稱轉換

System.Net 命名空間
Dns 類別
System.Net.Sockets 命名空間
SocketException 類別
//引用命名空間
using System.Net;
using System.Net.Sockets;

namespace TestIPAddress {
class Program {
static void Main(string[] args) {
try {
GetIPAddress();
}
catch (SocketException SockEx) {
Console.WriteLine(SockEx.Message);
GetIPAddress();
}
Console.ReadKey();
}
static void GetIPAddress() {
Console.WriteLine("輸入所要解析的主機名稱 (ex: www.pchome.com.tw):");
//取得主機名稱
string pHostName = Console.ReadLine();

IPHostEntry myAddress = Dns.GetHostEntry(pHostName);

Console.WriteLine("{0} 所對應的 IP 位址如下 : ", pHostName);
IPAddress[] myIPAddress = myAddress.AddressList;

foreach (IPAddress add in myIPAddress)
Console.WriteLine(add);

Console.WriteLine("輸入所要解析的 IP 位址 :");
//取得 IP 位址
string pAddress = Console.ReadLine();
IPHostEntry myHostName = Dns.GetHostEntry(pAddress);
Console.WriteLine("{0} 所對應的 主機名稱 如下 : ", pAddress);

Console.WriteLine(myHostName.HostName.ToString());
}
}
}

原文轉載自 http://www.dotblogs.com.tw/atowngit/archive/2010/01/16/13046.aspx

[C#] 基本網路技術(一) 取得主機名稱與 IP

Dns 類別
Dns 成員
IPHostEntry 類別

using System;
using System.Net;
using System.Collections;

class HostName {
static void Main() {
string s = Dns.GetHostName();
Console.WriteLine("主機名稱 :{0} ", s);

IPAddress[] IPS = Dns.GetHostEntry(s).AddressList;
IEnumerator iEnums = IPS.GetEnumerator();
while (iEnums.MoveNext()) {
Console.WriteLine("IP : {0}", iEnums.Current.ToString());
}

Console.ReadKey();
}
}

轉載自原文 http://www.dotblogs.com.tw/atowngit/archive/2010/01/16/13045.aspx

[C#] 基本網路技術(三) 建立 TCP 連線

TcpClient 類別 : 提供 TCP 網路服務的用戶端連接。
TcpListener 類別 : 接聽來自 TCP 網路用戶端的連接。
NetworkStream 類別 : 提供網路存取之資料的基礎資料流。

sample1 Server 端應用程式
//匯入命名空間
using System.Net.Sockets;
namespace TestNetworkServer {
class Program {
static void Main(string[] args) {
System.Net.IPAddress theIPAddress;
//建立 IPAddress 物件(本機)
theIPAddress = System.Net.IPAddress.Parse("127.0.0.1");

//建立監聽物件
TcpListener myTcpListener = new TcpListener(theIPAddress, 36000);
//啟動監聽
myTcpListener.Start();
Console.WriteLine("通訊埠 36000 等待用戶端連線...... !!");
Socket mySocket = myTcpListener.AcceptSocket();
do {
try {
//偵測是否有來自用戶端的連線要求,若是
//用戶端請求連線成功,就會秀出訊息。
if (mySocket.Connected) {
int dataLength;
Console.WriteLine("連線成功 !!");
byte[] myBufferBytes = new byte[1000];
//取得用戶端寫入的資料
dataLength = mySocket.Receive(myBufferBytes);

Console.WriteLine("接收到的資料長度 {0} \n ", dataLength.ToString());
Console.WriteLine("取出用戶端寫入網路資料流的資料內容 :");
Console.WriteLine(Encoding.ASCII.GetString(myBufferBytes, 0, dataLength) + "\n");
Console.WriteLine("按下 [任意鍵] 將資料回傳至用戶端 !!");
Console.ReadLine();
//將接收到的資料回傳給用戶端
mySocket.Send(myBufferBytes, myBufferBytes.Length, 0);
}
}
catch (Exception e) {
Console.WriteLine(e.Message);
mySocket.Close();
break;
}

} while (true);
}
}
}

sample2 Client 端應用程式
using System.Net.Sockets;
namespace TestNetworkClient {
class Program {
//宣告網路資料流變數
NetworkStream myNetworkStream;
//宣告 Tcp 用戶端物件
TcpClient myTcpClient;

static void Main(string[] args) {
Program myNetworkClient = new Program();

Console.WriteLine("輸入連接機名稱 : ");
//取得主機名稱
string hostName = Console.ReadLine();
Console.WriteLine("輸入連接通訊埠 : ");
//取得連線 IP 位址
int connectPort = int.Parse(Console.ReadLine());
//建立 TcpClient 物件
myNetworkClient.myTcpClient = new TcpClient();
try {
//測試連線至遠端主機
myNetworkClient.myTcpClient.Connect(hostName, connectPort);
Console.WriteLine("連線成功 !!\n");
}
catch {
Console.WriteLine
("主機 {0} 通訊埠 {1} 無法連接 !!", hostName, connectPort);
return;
}

myNetworkClient.WriteData();
myNetworkClient.ReadData();
Console.ReadKey();
}

//寫入資料
void WriteData() {
String strTest = "this is a test string !!";
//將字串轉 byte 陣列,使用 ASCII 編碼
Byte[] myBytes = Encoding.ASCII.GetBytes(strTest);

Console.WriteLine("建立網路資料流 !!");
//建立網路資料流
myNetworkStream = myTcpClient.GetStream();

Console.WriteLine("將字串寫入資料流 !!");
//將字串寫入資料流
myNetworkStream.Write(myBytes, 0, myBytes.Length);
}

//讀取資料
void ReadData() {
Console.WriteLine("從網路資料流讀取資料 !!");
//從網路資料流讀取資料
int bufferSize = myTcpClient.ReceiveBufferSize;
byte[] myBufferBytes = new byte[bufferSize];
myNetworkStream.Read(myBufferBytes, 0, bufferSize);
//取得資料並且解碼文字
Console.WriteLine(Encoding.ASCII.GetString(myBufferBytes, 0, bufferSize));
}
}
}

轉載自 http://www.dotblogs.com.tw/atowngit/archive/2010/01/16/13047.aspx

2010年12月9日 星期四

資料庫交易寫法TransactionScope、SqlTransact

資料庫交易寫法TransactionScope、SqlTransact
資料庫沒有了交易是很要命的,無法確保資料庫的正確,此篇就是在介紹交易的寫法。
string strConn = "連線字串"; 
SqlConnection conn = new SqlConnection(strConn);
conn.Open();
SqlTransaction tran = con.BeginTrasaction();
try
{
SqlCommand cmd = new SqlCommand("SQL語法", conn);
cmd.Transaction = tran;
//做你想做的...
//做完以後
tran.Commit();
}
catch
{
tran.Rollback();//發生例外就會滾回去
}
finally
{
conn.Dispose();
}


  using (TransactionScope scope = new TransactionScope()) 
{
string strConn = "連線字串";
SqlConnection conn = new SqlConnection(strConn);
SqlCommand cmd = new SqlCommand("SQL語法", conn);
try
{
conn.Open();
//做你想做的...
//做完以後
scope.Complete();
}
//Mission Accomplished!
catch (Exception ex)
{
}
//發生例外時,會自動rollback

finally
{
cmd.Dispose();
conn.Close();
conn.Dispose();
}
}

搬移大量資料至 SQL Server

ADO.NET 的SqlBulkCopy 類別,用來搬移大量資料蠻好用的,雖然不是什麼新玩意兒,最近有一些需要,因此拿來用,記錄一下:
SqlConnection sqlconn = new SqlConnection(connstring);
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(sqlconn);
using (sqlBulkCopy){ //大量複製的目的資料
sqlBulkCopy.DestinationTableName = destTable; sqlBulkCopy.WriteToServer(dr); //大量複製開始}
sqlconn.Close();

其中的destTable為 SQL Server 目的資料表,dr 則是來源資料,可以是DataReader或是 DataTable等等,來源資料不需要的是 SQL Server,只要能轉成DataReader或是 DataTable即可。

C# 使用SqlBulkCopy將資料批次寫入資料庫

之前demo有介紹利用SqlDataSoure和手動撰寫ADO.NET的方式大量新增資料的方法,雖然已經有效的改善了寫入的速度,但在發現了SqlBulkCopy以後,發現它更是威力強大,現在就來介紹SqlBulkCopy的猛。
  //一開始我們先產生一個DataTable來裝我們要寫入的資料 
DataTable dt = new DataTable();
dt.Columns.Add("id", typeof(int));
dt.Columns.Add("name", typeof(string));

//因為SqlBulkCopy的猛就是大量的一次寫入,所以我們也來跑10萬筆吧
int i;
for (i = 0; i < 100000; i++)
{
DataRow dr = dt.NewRow();
dr["name"] = i.ToString();
dt.Rows.Add(dr);
}

//宣告連結字串
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ASPNETDBConnectionString1"].ConnectionString);

conn.Open();
//宣告SqlBulkCopy
using (SqlBulkCopy sqlBC = new SqlBulkCopy(conn))
{
//設定一個批次量寫入多少筆資料
sqlBC.BatchSize = 1000;
//設定逾時的秒數
sqlBC.BulkCopyTimeout = 60;

//設定 NotifyAfter 屬性,以便在每複製 10000 個資料列至資料表後,呼叫事件處理常式。
sqlBC.NotifyAfter = 10000;
sqlBC.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnSqlRowsCopied);

//設定要寫入的資料庫
sqlBC.DestinationTableName = "dbo.Table1";

//對應資料行
sqlBC.ColumnMappings.Add("id", "id");
sqlBC.ColumnMappings.Add("name", "name");

//開始寫入
sqlBC.WriteToServer(dt);
}
conn.Dispose();
}
void OnSqlRowsCopied(object sender, SqlRowsCopiedEventArgs e)
{
Response.Write("---
");
}

測試環境:SQL2005 Express
測試資料量:10萬筆
測試次數:10次
平均秒數:2.3532秒

太可怕啦,之前的寫法如果真的要寫10萬筆這種大量的資料都需花費一分鐘左右,但使用了SqlBulkCopy卻只要短短的兩秒鐘,下表看的出來如果資料筆數很少就沒必要使用SqlBulkCopy了。

寫入十萬筆資料10次的平均秒數
使用SqlBulkCopy:2.2051
使用AddWithValue:63.418
寫入一萬筆資料10次的平均秒數
使用SqlBulkCopy:0.2188
使用AddWithValue:6.3856
寫入一千筆資料10次的平均秒數
使用SqlBulkCopy:0.0187
使用AddWithValue:0.5805
寫入一百筆資料10次的平均秒數
使用SqlBulkCopy:0.0062
使用AddWithValue:0.0353
寫入十筆資料10次的平均秒數
使用SqlBulkCopy:0.004
使用AddWithValue:0.004

C# 將資料大量寫入資料庫時的優化寫法

當初學者需要利用for迴圈寫入資料時,常常會犯一個錯誤,就是SqlConnection開開關關,迴圈跑100次它就活生生開關一百次,雖然資料量小時看不出影響但這是相當浪費效能與資源的寫法,只要改變寫作習慣就可以避免掉這問題,來看看吧。

demo以GridView1秀出資料後再把它全部寫入到一個名為Table1的資料表。

以下是一般初學者會寫的code
for (int i = 0; i < this.GridView1.Rows.Count; i++) 
{
SqlConnection conn = demotools.getSqlConnection();//此為demo取得SqlConnection的方法
SqlCommand comm = new SqlCommand("INSERT INTO [Table1] ([name]) VALUES (@name)", conn);
conn.Open();
comm.Parameters.AddWithValue("name", this.GridView1.Rows[i].Cells[1].Text);
comm.ExecuteNonQuery();
conn.Dispose();
comm.Dispose();
}

沒錯這樣寫是可以正常的寫入資料庫,但是因為開關連結的方式包含在for迴圈內所以就會發生前文所說得問題,瘋狂的開關,為了節省效能我們應該這樣寫
SqlConnection conn = demotools.getSqlConnection(); 
SqlCommand comm = new SqlCommand("INSERT INTO [Table1] ([name]) VALUES (@name)", conn);
//以上都應該放在for迴圈外(除非你會變動=.=)

int i;
//宣告變數也應該放在外面不應該在for內

conn.Open();//開啟連結拿出來了

for (i = 0; i < this.GridView1.Rows.Count; i++)
{
comm.Parameters.Clear();//清除掉目前宣告出來的Parameters
comm.Parameters.AddWithValue("name", this.GridView1.Rows[i].Cells[1].Text);
comm.ExecuteNonQuery();
}
conn.Dispose();
comm.Dispose();


測試環境:SQL2005 Express
測試資料量:10萬筆
測試次數:10次
平均秒數:64.4867秒

這樣子的寫法是demo目前會的最好的寫法,當然我還很嫩其他的大大一定有更好的寫法還請多指教...當然其中還可以加上交易等判斷但那些不是此篇的重點所以demo以最簡單的方式寫出來,希望此篇對您會有所幫助,或許你懷疑SQL怎麼會那麼慢,請注意測試環境使用的是Express版本,並且10萬筆這種大筆數本來就不太應該用這方法寫...

C# 將資料大量寫入資料庫(使用SqlDataSoure)

上一篇介紹『將資料大量寫入資料庫時的優化寫法』是利用ADO.NET的寫法,但有些開發者習慣或是愛用等因素就是要用SqlDataSoure來完成,所以就出現了此篇文章啦

此篇只列出最重要的部份,您應該看了就懂了,至於頁面上的配置和該在什麼事件處理因人而異,demo就不多介紹了。

此篇的SqlDataSource名稱為SqlDataSource2
this.SqlDataSource2.InsertCommand = "INSERT INTO [Table1] ([name]) VALUES (@name)";//將Inster的SQL語句寫好 
this.SqlDataSource2.InsertParameters.Add("name", TypeCode.String, "");//宣告參數
int i;
for (i = 1; i <= 100; i++)
{
SqlDataSource2.InsertParameters["name"].DefaultValue = string.Format("第{0}筆", i);
SqlDataSource2.Insert();
}

【論譠】使用ASP.NET發送電子報(大量郵件)的一些建議

逛台灣MSDN論譠時,發現璉璉大哥與小朱大哥所提出ASP.NET發送電子報(大量郵件)有講到重點,
所以這裡就引介一下囉!

璉璉大哥:

基本上不要考慮用 網頁 (ASP.NET) 發大量郵件:

1. 預設每個執行緒只能跑 90 秒
2. 共用 AppPool 的網頁其中一個掛的話會導致整個重新啟用,凡是共用同一個 AppPool 的網頁都將被終結
3. 不易管理,例如信件發出去後,發現內容有誤,若用 Windows Form 很快可以暫停,用 asp.net 很麻煩~

小朱大哥:
如果公司資料庫是用 SQL Server 2005,可以考慮使用 Database Mail 來做,簡單又省時。
程式只要負責把寄送名單輸入資料庫,再寫一段呼叫 Database Mail 的程序來發送郵件,其他的就由 Database Mail 來處理即可。

原址網頁:http://social.msdn.microsoft.com/Forums/zh-TW/236/thread/cd6b90d0-c78b-47a3-bfcd-5a5b5a37c83d

介紹好用工具:Bat To Exe Converter

我時常在寫批次檔(Batch, *.bat)幫助我處理一些日常的工作,例如說備份資料庫、建立 SSH Tunnel、或是將所有子目錄下的 .svn 目錄改成 _svn 目錄、…等等。有些 Batch Script 甚至會寫超過一百行,若你想保護辛苦寫的批次檔時,就可以利用 Bat To Exe Converter 幫你轉成 *.exe 執行檔。

簡單的說,這套工具有 4 個特色:

1.隱藏原始碼。(這是無庸置疑的)
2.支援 “沒有互動視窗”的應用程式(Ghost applications),可讓你的程式在背景作業。
3.批次檔轉換後的執行檔可設定應用程式圖示、檔案版本、產品版本、公司名稱、程式描述、版權宣告等應用程式資訊。
4.可以不只將批次檔轉成執行檔,還可以將批次檔相關的檔案、文件或程式也一併結合在一起。
正所謂「一圖解千文」,如下圖示就是此工具唯一的 GUI 操作介面:

下載後的壓縮檔中會有兩個檔案,一個是 Bat_To_Exe_Converter.exe 執行檔,另一個是 help.chm 說明檔,可查詢指令列(Command Line)操作的用法。

若要透過指令列的方式執行轉換動作,至少需要設定 4 個參數才能執行,其參數的說明如下:

1.第一個參數是來源批次檔
2.第二個參數是輸出的執行檔
3.第三個參數是 Icon 的檔案路徑
4.第四個參數是設定你的應用程式類型 ( Console 或 Ghost )
5.第五個之後的參數都是要外掛進來的檔案,也就是要跟這個原本的批次檔一起工作的程式。

範例1:將 a.bat 轉成 a.exe,其中的 "" 代表不要設定 Icon,1 代表轉換成 Console application
Bat_To_Exe_Converter.exe a.bat a.exe "" 1

範例2:將 a.bat 轉成 a.exe,其中的 0 代表轉換成 Ghost application ( 背景作業模式 )
Bat_To_Exe_Converter.exe a.bat a.exe "" 0

範例3:將 a.bat 轉成 a.exe,並且也將 myprogram1.exe 與 test.jpg 兩個檔案都打包放進 a.exe 中,讓 a.exe 在執行時可以引用這兩個檔案。
Bat_To_Exe_Converter.exe a.bat a.exe "" 1 myprogram1.exe test.jpg

另外,我也做了個小測試,情境如下:

我寫一個 a.bat 內容是 type a.txt
然後建立一個 a.txt 內容是 12345
然後執行 Bat_To_Exe_Converter.exe a.bat a.exe "" 1 a.txt 將 a.txt 綁進 a.exe 中
之後將 a.txt 的內容修改成 67890
接者我執行 a.exe 得到的結果是 67890
接者我從該目錄刪除 a.txt 檔案
再執行一次 a.exe 我得到的結果是 12345
由此可知,即便將檔案一併綁進轉換後的執行檔中,原本批次檔讀取的訊息還是先從原本所在的目錄讀取檔案,若讀取不到才會讀取被綁進執行檔中的檔案。

原文轉載 http://blog.miniasp.com/post/2008/10/07/Useful-tool-Bat-to-Exe-Converter.aspx

2010年12月1日 星期三

ASP.NET 4.0 設定 了 validateRequest="false" 仍然會出現 具有潛在危險 Request.QueryString 的錯誤訊息

微軟的asp.net網頁都會預設進行Request Validation,但若是想規避這樣的內建行為。(建議仍要有其他的方法來防範XSS攻擊)

通常我們可以在.aspx中的Page Tag設定:
<@Page Language="C#" validateRequest="False" >

或是直接對整個站台設定Web.Config中 <system.web>下設定全域的
<pages validateRequest="false" />

不過,假如你現在在ASP.NET 4.0 的環境下的話,就算進行上述的設定,可能仍會出現驗證失敗的訊息(潛在危險Request.QueryString的錯誤訊息)

因為ASP.NET4.0與2.0版本在請求驗證的定義上已經有所不同:
ASP.NET Request Validation請求驗證是ASP.NET提供來保護XSS攻擊的一項功能
在先前的ASP.NET(ASP.NET 2.0)網頁,都是預設會進行網頁請求的請求驗證
僅會針對.aspx以及他們的class檔案進行驗證
不過到了ASP.NET 4.0,請求驗證範圍擴大到所有的請求
因為從BeginRequest階段就開始了HttpRequest
因此在這個期間任何的資源要求都會進行請求驗證
而非網頁檔案(.aspx)而已,還包含WebService呼叫以及自訂的http Handlers,都會去驗證http請求的內容
因此在ASP.NET 4.0下,可能在非網頁請求的情況下,仍會發生請求驗證錯誤的訊息
這時為了避免這樣的問題,一樣在Web.Config中 <system.web>下加入下列語句
<httpRuntime requestValidationMode="2.0" />

這樣就可以讓請求驗證只焦點在.aspx網頁上了。

2010年11月13日 星期六

程式人員的心聲(2) v2 - 為啥那人寫 code 感覺用飛的 - 善用快速鍵

話說,剛進入這條不歸路的時候,那時還是用 VB6。
第一次見到師父 ABBY ( 哈哈!!這個英文名字在台灣應該找不到第二個了吧!)
他老人家寫程式碼的時候,我的下巴都快要掉下來啦!! ( 當時我的表情應該就是這樣子吧! )
簡直就是用飛的感覺,這是人類可以辦到的嗎?
無論是寫 code 或是 追 Bug 都幾乎沒用到 mouse
他老人家告訴我幾個訣
真的是受用無窮呀!!就跟騎腳踏車一樣

基本條件
一個好用的鍵盤
最好是那種 104 標準+ 的,和自已喜歡按下去的感覺。( 找到那個 fe 是很重要的 )
一定要可以英文盲打!
這是寫 code 的基本原則,而且是要同時「兩隻手」可以迅雷不及掩耳的速度打完 public void main()
工具一定要支援 Interllisense
這一點尤其重要,別再跟我說「這個有跟沒有一樣呀」,能少打幾個字就少打幾個字啦!
記住自已常用的快速鍵
別跟我說不知道啥是 F5
----------- Visual Studio .NET 系列開發平台 通用 ------------------------------------------
廢話不多說啦!馬上來介紹幾個自已很常用的

選取整行的字 [Home] , [Shift]+[End] ( 這個順序沒差 )
選取一個區塊 [Shift] + [↓] or [↑] 有時要搭配 同一行選字時請再 [Shift] + [Ctrl] + [→] or [←]
選取一個區塊 ( 一行一行 ) [Shift] + [Ctrl] + [↓] or [↑]
選取一個單字 [Shift] + [Ctrl] + [→] or [←]
呼叫出 InterlliSense 小視窗 [Ctrl] + [→] or [Ctrl] + [J] ( 要看當初的鍵盤設定 )
執行程式 [F5] ( 其實我還是常常看到很多人用 mouse )
逐行執行程式 [F11] ( VB6 的話印象是 F8 )
設定/去掉 中斷點 [F9]
進入呼叫 method 的程式區塊 [F12] ( 這個很方便喔!一定要試試 ) ( VB6 的話印象是 F10 )
找東西 [Ctrl] + [F] / 取代 [Ctrl] + [H]
--------- 補充 -------------------
快速切換不同工具/ 文件時 [Alt] + [Tab]
在有頁籤時想要快速切換時 [Ctrl] + [Tab]
其實只要以上 10 個幾乎可以適用在大多數的地方 ( 一開始也用不了這麼多啦! )

原本沒有寫說要寫這方面的,但過了這麼久發現這個部分很多人其實都沒有這麼在意,工具有提供卻沒有用覺得很可惜 ( 這個以前教其他同事就教了至少超過十幾遍了吧 )

這些東西可以供大家參考參考,可以有更多自已的時間 提升平常寫作的效率喔!

經典的一句話「生氣就輸了」

現在在網路的論壇上交流是一件很平常的事!

不過也因為這樣子,當意見相左時常常會有所謂的筆戰。

每次只要一看到,心中可是油然敬佩了起來呀!

任何一種主題都可以吵起來,大到政治小到卡漫都沒有問題! ( 不過有的時候問題太腦殘,大家就會公x )

而且每每吵起來都可以引經敘述之前誰誰誰講過的話!又是在那裡提過的數據!

自然而然地出現了「沒圖沒真相」 ( 口說無憑 )

相反地,若是擺明就是沒結論的話!大家都會有一個共識

「認真就輸了」

「生氣就輸了」

在談判斷只要動到氣,之後就通通都不用談啦!因為會掉入到對方的圈套中。

轉載自http://www.dotblogs.com.tw/franma/archive/2009/07/13/9406.aspx

2010年11月12日 星期五

我們團隊只用版本管控就夠了嗎??

一開始小弟待的開發團隊根本沒有所謂的版本管控,要管控?

那就開發人員自已平常多燒香拜拜啦!

定期備份在自已電腦上的檔案不要掛掉,只要最新的程式沒問題就好!

反正老闆和客戶都只看現在交付給他們的程式。

後來,大部分的團隊也已經能接受用「版本管控」管理所有程式碼是件重要且必須的事。

但!這樣子真的就足夠了嗎??

======= 題外話!===========
小弟的確有看過一些團隊是用「工作單」的數量來決定一個人的績效,光只用數量來決定是一件非常要不得的,畢竟工作(bug) 都有區分成簡單和困難的。若是被分配到困難的成員豈不是很衰??而且也不公平! ( 所以日後該團隊的工作追蹤和會議進度形同批鬥大會,超慘的 )

所以大家要麻就是充數量!要麻就是造假! 這只是增加團隊的 loading 而已。

到最後工作單就沒有人要看! ( 因為大家都在填心酸的 )

那還不如不要填。
===========================

首先 可以先聽到幾種答案!

是不夠!所以我們有自已寫的系統在記錄所有的工作單
不然就是!我們有用一些免錢的系統在幫我們記錄 ( 通常都是 Bug Tracking System 這一類的 ,這和第一點是一樣的問題 )
覺得只有版控不夠!但完全不知道應該要怎麼解決!
只有版本管控就夠了,反正這個專案都只有我一個人!
前兩種都很好!因為已經有這個習慣了!

但程式碼 和 工作項目 彼此之間沒有關聯,就無法很方便地由單找Code 或是 由 Code 找單

若團隊是 3、4的話!人的改變就會比較辛苦了!

若是能認同想要改善也就罷了!但很多時候可能會有結論就是!

反正沒有我也這樣子過來了!天也沒有跨下來呀!程式還是一樣地出貨!

是的!程式還是照樣可以出貨!小弟也是這樣子過來的!程式一樣照寫 :)

久而久之就會發現!團隊只有你自已一個人寫得好沒用呀!要讓大家都跟你一樣利害才行

有時候會發現!怎麼最常常加班的只有你而已! ( 因為最利害的人都負責最多的案子 )

不然每次某個東西要改 ( 或有 Bug ) 時都只能找你,因為當初是你寫的。

但現實上不是只有程式碼管理而已,還有很多其他政治因素。 ( 最痛的就是 一人專案 )

因為,程式碼要自已寫以外

要解決客戶所提出來的需求 ( 還不斷地一直修改 Orz ) 和 動不動就會打給老闆抱怨某個功能又掛了

除此之外還要回答老闆什麼時候才能交貨 ( 不然公司就賠錢啦! )

等等等……

沒錯!現實上不是只有程式開發而已!還包含到管理層面很多很多問題!

只有靠腦子記錄且案子又成功的非人類,實在少之又少。

===========================
若你們家是:「我們家的老闆人超好的!絕對不會壓我們時程,功能隨便我們寫客戶都會買單。 」

記得要多珍惜這種老闆和客戶呀!他們是最棒的衣食父母。( 哭 )
===========================

開發過程的記錄非常的重要,並非只有程式碼而已。

工作單、Bug 都是優先需要記錄的,和程式碼關聯是要幫助我們管理工作成果

有這兩項我們才能知道,目前有那些工作是已知的且還沒有完成的,什麼時候增加的

大約還要花多少時間完成、新產生的 Bug 數量和功能品質量化、程式碼修改是針對那些工作單或 Bug

每次交付工作是完成那些工作項目和Bug、工作單 ( Bug ) 的平均解決速率、等等…

很多時候小弟在講「工作管理」和「版本管控」的關聯時,聽完後覺得我們現在團隊只要有版控就好了呀!

幹麻還要多工作管理??還不是老闆想要追我們的績效?不然就是 PM 不想讓我們忙裡偷閒?

不然就是上有政策、下有對策 工作單就隨便填,反正單子和程式都是我寫的。

其實,這些都是為了要保護自已和提升管理能力,也可以讓其他同儕協助 ( 或帶人 ) 都有記錄

一方面你可以自我掌控開發狀況,另一方面也學會怎麼預估時間。

所以知道工作單和程式碼關聯的重要性後,選擇適合自已團隊的工具就非常重要

簡單一點的工作追蹤可以用 Excel ( 小弟以前就是學約耳的做法!很快!很直覺! )

而程式碼關聯則可以透過 Check in policy 來輔助記錄 ( 我們都不想要有人漏填或是明明無法編譯卻還簽入吧 )

小弟自已屁了這麼多,不外乎之前聽到一位先進說。該不會用了什麼 Team Foundation Server 一切都葯到病除吧?

不不不!!流程的改進!主要因素是「人」呀!工具只能讓我們縮短時間而已。

要做的一樣都不會少! Orz 但團隊工作管理卻一直是大家遇到的問題!

所以,若自已檢視一下自已的團隊

是不是如同小弟講的只有版本管控而已,其他都只記在某一個超人的腦子裡的話!

真的要好好地想想,是不是應該用 Excel 把工作項目記錄到 TFS 上了呢!

小弟自已導入的成果

原本客戶一直抱怨提了需求 ( Bug ) 都沒有人理的情況完全地改善了,因所有的項目都有記錄和排時程。
工作的進度和成果的量化可以提高所有人員的士氣 ( 小弟導入過的團隊都是如此!但這必須是寫真的,而且不是為了績效時才有用 )
人員的支援變得更加容易,可以讓成員在不同專案中調度。因為先前的開發過程都有記錄下來可以供參考。
不用為了交報告而再花很多時間整理,從 TFS 到 Excel 可以馬上弄出我要的報表 ( 包含給客戶看的 加工過報表 )
單子不用擔心會不見! ( 以前用 「紙」時,有時會發生 單子跑到異次元的情況 )
開發人員可以更了解自已工作的流程怎麼和其他人配合
讓每個人都有機會練習和預估時程的能力提高! ( 是的!和 gipi 執行長說的一樣,這需要練習 )
可受管理的專案數量增加

以前 從 VSS ( 或是有人用 SVN ) 搭配 Excel 或 Email 或 紙 時

不是不能,只是會需要大量人力的管理工作進度,還有「道德」上的勸說。

小弟以上所有的工作都有用過「人力」管理過

現在就真的很幸福了,後來改導入 TFS 後原本需要有「專人」管理的部分節省下來

讓同部門成員 和其他部門的人員也可以知道所有專案的全貌

轉載自http://www.dotblogs.com.tw/franma/archive/2010/08/02/16962.aspx

一個團隊最少應該要多少人?

無論是 台灣 還是 大陸的工程師,都會覺得說 寫程式是低階的人在幹的!

所以往往都會覺得要往上爬就是要往管理階段走! PG—>SD—>SA—>PM 等等… ( 中間還有其他角色我們省略 )

而,當然 高層也不是幹假的!即然要這樣子的話!

最後就很容易變成!「一人專案」

放心!從專案時間規劃到程式開發!絕對都可以碰得到!

名義上好聽的是 讓你可以獨立作業、可以讓你操控整個專案!

實際上卻是一人當三人用!

7、8 年前時小弟以前的主管不知去那裡看到的「一條鞭」的管理方法 ( 很怪!這個到現在還是很流行 )

硬是套在「軟體開發」的團隊中,而且覺得就是要一個人搞到底,因為這樣子可以節省溝通成本

所以呢!硬是把 一個團隊共同在維護的專案 ( 同時有 5 個 ) 拆散給 5 個不同的工程師 ( PG )

當然最後的下場很慘!原因有很多!因為 並不是每個人都有辦法可以同時要做 規劃 又要開發、又要顧品質 ( 當然 老闆覺得即然溝通時間省掉了!那麼上線的時間也可以濃縮一下吧! )

導致某些專案客訴問題特多!

因為很容易弊端!比如 原本某些功能測試明明就是有問題,卻硬是要上線!

這個是不是好方法?

小弟覺得這跟本無法解決問題!因為校長兼撞鐘 怎麼可能「忠實地」反應問題出來呢??

所以 一人專案真的不太適合在 軟體的開發作業上 ( 某些神人等級例外 ,各位都知道小弟在說啥 )

無論是自已實作過的團隊 或是 MSF 上所說 真的最少是 三個人

分別是

PM 負責時程規劃、客戶需求
PG 負責程式開發 / 設計
Test 負責產品的品質

也許就會有人說「不行!我們的人力資源有限,不可能因為 10 個案子我們就要統統乘以三 」

沒關係!換個角度想!可以讓 這三個人同時負責 三個專案 不就解決了嗎?? ( 當然會依 數量、性質、人員 的差異而有所不同 )

若是所有的專案都已經進維護階段 且 產品的性質都是一樣 又有 OO 架構的話! 3 個人同時維護 10 個案子也不是不可能的!

而在這裡面最重要的是

如何讓 這三個人可以共同作業、又不會干擾到對方!

這個問題也是困擾了我好久!

比方說 只要一有 bug ,我就要被測試人員 打斷 我開發中的工作,因為他要跟我說發生了什麼 bug

所以,即使是小團隊 也不能忽視這個問題

建置團隊自已的溝通平台是很重要的!

所以 Team Foundation Server 在這個部分幫節省很多建置平台的時間

PM 用 Excel / project 進行管理 和 客戶之間的需求 並且 隨時掌控進度 以便讓其他人員可以專心做份內的事

PG 在 VS 2010 中將這些需求 分幾個大的項目來決定 要執行那些工作 並 將開發好的程式碼可以連結到 需求

Test 依據 PM 所談好的需求 使用 Lab Management 規劃 測試案例 並在每一次 版本測試所找到的 Bug ,開立 Bug 單並記錄發現過程 以便讓 PG 日後可以找得到

爾後,即使團隊需要老闆 增加人手時 也可以很容易讓 新成員 上手 ,因為所有的開發經驗 通通都會在 TFS 中!

所以,並不是小團隊就不需要 開發流程!而是 更需要重視它!因為 人變少了就代表 做事的效率要提高!
( 事情不會變少 )
Orz

轉載自 http://www.dotblogs.com.tw/franma/archive/2010/01/24/13262.aspx

2010年9月9日 星期四

MSSQL 自動產生流水號

說明
SELECT ROW_NUMBER() OVER(ORDER BY [排名欄位] ) AS RNO FROM [資料表]

範例
SELECT ROW_NUMBER() OVER(ORDER BY [Sno] DESC) AS RNO FROM [TableName]

2010年9月8日 星期三

如何動態載入Javascript或CSS

在網頁中,我們多半是在</head>中宣告要Include的js檔或css檔,例如:
<head>
<script type="text/javascript" src="blah.js"></script>
<link src="blah.css" type="text/css" ref="stylesheet"></link>
</head>

在某些情況下,可能需要依狀況動態載入不同的Javascript檔或CSS Stylesheet,要怎麼做呢? 看了以下的範例大家就明白了。
var headID = document.getElementsByTagName("head")[0]; 

var newCss = document.createElement('link');
newCss.type = 'text/css';
newCss.rel = "stylesheet";
newCss.href = "blah.css";
headID.appendChild(newCss);

var newJs = document.createElement('script');
newJs .type = 'text/javascript';
newJs .src= "blah.js";
headID.appendChild(newJs);

2010年9月2日 星期四

javascript 補0

程式
    function padLeft(str, lenght) { //左邊補0
if (str.length >= lenght)
return str;
else
return padLeft("0" + str, lenght);
}

function padRight(str, lenght) { //右邊補0
if (str.length >= lenght)
return str;
else
return padRight(str + "0", lenght);
}

用法
        var numkey = padLeft("10", 4);
alert(numkey);

2010年9月1日 星期三

jQuery神奇的選擇器(Selector)

就像正規運 算式(Regular Expression)的Pattern match一般,jQuery使用了CSS(Cascading Style Sheet)、XPath(XML Path Language)與自訂等三大類的選擇器(Selector)當做$( )函數的參數,讓我們由複雜多樣的DOM結構裡,快速的找出符合樣式的要素。

使用選擇器的三個基本格式是:
序 格式        範例        說明
1 $("HTML標籤")   $("div")      傳回表示所有div要素的jQuery物件
2 $("#要素的ID")   $("#linksLeft")   傳回表示<div id="linksLeft">要素的jQuery物件
3 $(".要素的類別")   $(".blogname")  傳回<div class="blogname">要素的jQuery物件

jQuery 怎麼用來「快速選取元素」並且「做一些事情」呢?請看看程式碼:
$("div").addClass("special");

$("div")        解釋:選取所有 <div>
$("#body")       解釋:選取 id 為 body 的元素
$("div#body")     解釋:選取 id 為 body 的 <div>
$("div.contents p")   解釋:選取 class 為 contents 的 <div> 所包住的所有下層的 <p>
$("div > div")     解釋:選取被 <div> 包住的下一層 <div>
$("div:has(div)")    解釋:和前一個範例相反,這邊是選取至少有包住一個 <div> 的 <div>

[範例1] 選取所有有 target 屬性的 <a>,並且在其節點下加入一段文字
$("a[target]").append(" (Opens in New Window)");  

這是一段原始的 HTML
jsGears  
Google
Amazon

選取有 target 屬性並加入文字後的結果:
jsGears  
Google (Opens in New Window)
Amazon (Opens in New Window)

[範例2] 選取 id 為 body 的元素,並且修改兩個 css 屬性。
$("#body").css({   
border: "1px solid green",
height: "40px"
});

這是一段原始的 HTML :

...

選取 id 為 body 的元素並修改 css 後的結果(示意):

...

[範例3] 在網頁上的表單送出時加入一個判斷,如果 username 這個欄位是空值的話,就顯示 help 這個區塊內的文字。
$("form").submit(function() {   
if ($("input#username").val() == "")
$("span.help").show();
});

可作用在類似以下的 HTML,一開始 span.help 是隱藏的,如果沒有輸入 username,才會顯示:
  



這個欄位必填喔

[範例4] 當 user 點選 id 為 open 的連結時,顯示 id 為 menu 的區塊,並回傳 false 避免瀏覽器真的換頁。
$("a#open").click(function() {   
$("#menu").show();
return false;
});

可作用在類似以下的 HTML:
  
控制面板

[範例5] 將 id 為 menu 的區塊以下拉布幕的動態效果快速顯示:
$("#menu").slideDown("fast");

可作用在類似以下的 HTML,原本隱藏的選單會以動態下拉的方式顯示出來:
  

[範例6] 將所有的 <div> 漸變為寬 300px、文字與邊界寬 20px
$("div").animate({   
width: '300px',
padding: '20px'
}, 'slow');

可作用在類似以下的 HTML:

Hello world!

PS. jQuery 核心程式的 animate 函數能改變的元素屬性並不多,但是可以透過其他 plugin 提供更多的動態效果。

[範例7] 動態效果的 callback 的範例,將所有的 <div> 以 0.5 秒的動態效果隱藏後,再以 0.5 秒的動態效果顯示。hide() 的第二個參數就是一個 callback 函數,其中 $(this) 是原本程式所處理的各個元素。
$("div").hide(500, function(){   
// $(this) 是每一個各別的 <div>
$(this).show(500);
});

可作用在類似以下的 HTML:

Hello world!


jsGears.com!

[範例8] 取得 sample.html 並將找出文件內所有 <div> 下一層的 <h1> 填入原本文件 id 為 body 的元素內
$("#body").load("sample.html div > h1");  

這是一段原始的 HTML :

sample.html 的片段:

Hello world!


This is H2


jsGears.com!



執行程式碼之後的結果:

Hello world!


jsGears.com!



[範例9] 透過 getJSON() 取得 JSON 格式的資料,並透過 callback 函數處理資料
$.getJSON("test.json", function(data){   
for (var idx in data)
$("#menu").append("
  • " + data[idx] + "
  • ");
    });

    這是一段原始的 HTML:
      

    test.json 的內容:
    [   
    "Hello world!",
    "jsGears.com!"
    ]

    執行程式碼之後的結果:
      

    [範例10]抓取DIV內容
    onclick="addition('DivSh_Year');"


    [範例11]抓取DIV內容
    onclick="addition(DivSh_Year);"

    jQuery教學-SliderGallery滑動式相本特效應用



    CSS部分
    body{font-family:Arial, Helvetica, sans-serif;}
    ul ,li{ margin:0; padding:0; list-style-type: none; float:left;}
    #showbox{width:360px; border:solid 1px #eee;}
    #showImg , #showImg table{width:360px; height:300px;}
    #imgList{margin-top:10px; margin-left:3px; padding-bottom:10px; overflow:auto;}
    #imgList span{float:left; display:block; width:22px; margin:2px; line-height:50px;}
    #list{position:relative; float:left; width:350px; height:60px;}
    #list img{width:40px; height:40px;}
    #list{width:300px; float:left; margin:0 2px; overflow:hidden;}
    #list ul{ position:absolute; left:0; top:0; white-space: nowrap;/* 不斷行 */}
    #list ul li{
    display: inline; /* 水平排列 */
    margin:0 4px;
    padding:5px;
    border:solid 1px #eee;
    }
    #list ul li.on{border:solid 2px #ccc;}
    #list ul li img {display: inline-block; /* 水平內顯示為區塊 */}
    /* 秀大圖 */
    #imgB{border:solid 7px #fff;}
    /* 滑入顯示圖片區塊 */
    #overImg{position:absolute; top:-99999; left:-99999; display:none; z-index:100; border:solid 5px #666; padding:5px; background:#fff;}

    HTML的部分







































    轉載自 http://www.minwt.com/?p=1406
    如需範例或DEMO請至原網站瀏覽

    jQuery-將網頁元素名稱標示出來


    不知有沒有人跟我有一樣的困擾? 步入中年後,腦容量似有變小趨勢,每次寫網頁Client Script時,<input>, <select>的欄位名稱老記不住,要用時總是要回HTML Source或用IE Dev Tools去查,查完了一轉頭又忘了,再不然就是切換回Script Editor時搞不清楚剛才寫到哪裡。幾番折騰下來,效率很差,心情很糟。(老了,不中用了~~ 不中用了~~ 不~中~用~了了了了~~~)

    於是我寫了以下的jQuery Plugin,試圖把所有的輸入元素id直接顯示在網頁上,方便對照,也試圖挽救我岌岌可危的事業。
    $.fn.showElemId = function(bgc, fc) {
    return this.each(function() {
    var $elem = $(this);
    //if (!$elem.is(":visible")) return;
    var pos = $elem.offset();
    var html = "" +
    (this.id || "----") +
    "
    ";
    $("body").append(html);
    });
    };
    /* 使用範例: $(":text,select").showElemId(); */

    用Hotmail的註冊畫面做個示範(只查:text,select,不包含:button,:password),如下圖所示,輸入欄位元素名稱一目瞭然,列印出來,就不用每次去HTML Source裡找半天了,真是中年程式開發人員的福音呀

    轉載自 http://blog.darkthread.net/blogs/darkthreadtw/archive/2009/10/13/mark-element-id-with-jquery.aspx

    [jQuery] 如何自動取得所有前端 JavaScript 錯誤以提升網站品質

    這個需求透過 jQuery 來做最方便了,透過 error(fn) 事件即可達成此一目標:
    $(window).error(function(msg, url, line){  
    jQuery.post("/js_error_log.ashx", { msg: msg, url: url, line: line });
    });

    透過這個技巧即可有效獲得即時的前端資訊,看你要儲存到資料庫、EventLog、File、或郵寄出來都可以,不過唯一要小心的地方是當錯誤非常多時,這個錯誤追蹤的量可能會非常大,這時要特別注意程式的寫法,不要因為前端的錯誤槁掛了你的伺服器,而且有查到錯誤就要立即處理,降低錯誤發生的次數與提升網站品質。

    C# 動態新增User Control,並設定屬性值與取屬性值

    新增一個UserControl
    ascx:
    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="CustIDName.ascx.cs" Inherits="UserControl_CustIDName" %>
    <%@ Register Assembly="Joey" Namespace="Joey" TagPrefix="cc1" %>



    .ascx.cs
    using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;

    public partial class UserControl_CustIDName : System.Web.UI.UserControl
    {
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    public string CustID
    {
    get
    { return this.JoeyTextBox1.mTextBox.Text; }
    set
    { this.JoeyTextBox1.mTextBox.Text = value; }

    }
    public string CustName
    {
    get
    { return this.JoeyTextBox2.mTextBox.Text; }
    set
    { this.JoeyTextBox2.mTextBox.Text = value; }

    }
    public string ValidationGroup
    {
    get
    { return this.JoeyTextBox1.ValidationGroup; }
    set
    {
    this.JoeyTextBox1.ValidationGroup = value;
    this.JoeyTextBox2.ValidationGroup = value;
    }
    }
    }

    接著我們在一個空白頁面上,加入一個panel
    using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;

    public partial class LoopAddUserControl : System.Web.UI.Page
    {
    protected void Page_Load(object sender, EventArgs e)
    {
    if (!IsPostBack)
    {
    this.DropDownList1.Items.Add(new ListItem("user control index"));
    for (int i = 0; i < 10; i++)
    {
    this.DropDownList1.Items.Add(new ListItem(i.ToString()));
    }
    }

    for (int index = 0; index < 10; index++)
    {
    Control ctlNewTrial = this.Page.LoadControl("UserControl/CustIDName.ascx");
    SetUserControlProperty(ctlNewTrial, "ID", "Usrctrl" + index.ToString());
    SetUserControlProperty(ctlNewTrial, "CustID", index.ToString());
    SetUserControlProperty(ctlNewTrial, "CustName", index.ToString()+":name");

    this.Panel1.Controls.Add(ctlNewTrial);
    Label br = new Label();
    br.Text = "index=" + index.ToString()+ "
    ";
    this.Panel1.Controls.Add(ctlNewTrial);
    this.Panel1.Controls.Add(br);
    }
    }

    ///
    /// 設定user control的屬性值
    ///

    /// usercontrol by page.loadcontrol()
    /// usercontrol's property
    /// setting property value
    ///
    public void SetUserControlProperty(Control vobjControl, string vstrPropertyName, object vobjValue)
    {
    vobjControl.GetType().GetProperty(vstrPropertyName).SetValue(vobjControl, vobjValue, null);
    }
    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
    ASP.usercontrol_custidname_ascx usrctl1 = (ASP.usercontrol_custidname_ascx)this.Panel1.FindControl("Usrctrl" + this.DropDownList1.SelectedValue);
    if (usrctl1 != null)
    {
    this.TextBox1.Text = usrctl1.CustID;
    this.TextBox2.Text = usrctl1.CustName;
    }
    else
    {
    this.TextBox1.Text = string.Empty;
    this.TextBox2.Text = string.Empty;
    }
    }
    }

    參考文件
    [ASP.NET]動態Load UserControl – part 2 - In 91- 點部落
    WebUserControl之間值得傳遞(使用Interface) - topcat 姍舞之間的極度凝聚- 點部落
    [ASP.NET]動態新增User Control,並設定屬性值與取屬性值 - In 91- 點部落

    2010年8月26日 星期四

    jQuery 外掛 - The Silky Smooth Marquee 文字跑馬燈

    (1)官方網站:remy sharp's b:log
    (2)外掛程式下載:http://remysharp.com/2008/09/10/the-silky-smooth-marquee/
    (3)官方範例:http://remysharp.com/demo/marquee.html

    javascript 垂直輪播(跑馬燈、vertical carousel)

    首先設定一個style(也可以直接放在標籤裡)
    .ann{overflow:hidden;height:20px;}

    這是html的部份,包在外面的div高度跟裡面個別的div高度設定成一樣
    <div id="ann_box" class="ann" style="width:100px;">
    <div id="a1" class="ann"><a href="exp01.php" >exp01</a></div>
    <div id="a2" class="ann"><a href="exp02.php" >exp02</a></div>
    <div id="a3" class="ann"><a href="exp03.php" >exp03</a></div>
    <div id="a4" class="ann"><a href="exp04.php" >exp04</a></div>
    <div id="a5" class="ann"><a href="exp05.php" >exp05</a></div>
    </div>

    這是javascript的部份
    function slideLine(box,stf,delay,speed,h)
    {
    //取得id
    var slideBox = document.getElementById(box);
    //預設值 delay:幾毫秒滾動一次(1000毫秒=1秒)
    // speed:數字越小越快,h:高度
    var delay = delay||1000,speed = speed||20,h = h||20;
    var tid = null,pause = false;
    //setInterval跟setTimeout的用法可以咕狗研究一下~
    var s = function(){tid=setInterval(slide, speed);}
    //主要動作的地方
    var slide = function(){
    //當滑鼠移到上面的時候就會暫停
    if(pause) return;
    //滾動條往下滾動 數字越大會越快但是看起來越不連貫,所以這邊用1
    slideBox.scrollTop += 1;
    //滾動到一個高度(h)的時候就停止
    if(slideBox.scrollTop%h == 0){
    //跟setInterval搭配使用的
    clearInterval(tid);
    //將剛剛滾動上去的前一項加回到整列的最後一項
    slideBox.appendChild(slideBox.getElementsByTagName(stf)[0]);
    //再重設滾動條到最上面
    slideBox.scrollTop = 0;
    //延遲多久再執行一次
    setTimeout(s, delay);
    }
    }
    //滑鼠移上去會暫停 移走會繼續動
    slideBox.onmouseover=function(){pause=true;}
    slideBox.onmouseout=function(){pause=false;}
    //起始的地方,沒有這個就不會動囉
    setTimeout(s, delay);
    }
    //網頁load完會執行一次
    //五個屬性各別是:外面div的id名稱、包在裡面的標籤類型
    //延遲毫秒數、速度、高度
    slideLine('ann_box','div',2000,25,20);

    這是範例 http://ex.hsin.tw/exp06.php

    2010年8月25日 星期三

    JavaScrip 自動輪播頁籤 ( IE 與 Mozilla 通用 )

    CSS
    .ImgTab {cursor:hand} ←這行可有可無,不影響程式執行
    .MsgHide {height:174px;border:1px solid #aaa;padding:10px;font:normal 12px 細明體;display:none}

    HTML ( 以下為完整頁籤架構 )
    <table border="0" cellpadding="0" cellspacing="0">
    <tr>
    <td><img name="Tag_COMM" class="ImgTab" src="Tab_Img10.gif" onmouseover="Rot_Msg(1)" onmouseout="Rot_Msg()" onclick="Pause_Msg()"></td>
    <td><img name="Tag_COMM" class="ImgTab" src="Tab_Img20.gif" onmouseover="Rot_Msg(2)" onmouseout="Rot_Msg()" onclick="Pause_Msg()"></td>
    <td><img name="Tag_COMM" class="ImgTab" src="Tab_Img30.gif" onmouseover="Rot_Msg(3)" onmouseout="Rot_Msg()" onclick="Pause_Msg()"></td>
    </tr>
    <tr><td colspan="3">
    <div id="Tag_IE" name="Tag_FF" class="MsgHide">
    訊息內容...
    </div>
    <div id="Tag_IE" name="Tag_FF" class="MsgHide">
    訊息內容...
    </div>
    <div id="Tag_IE" name="Tag_FF" class="MsgHide">
    訊息內容...
    </div>
    </td></tr>
    </table>

    JavaScript ( 更改輪播速度,範例為3000毫秒 )
    Msg_Timer=setTimeout("Rot_Msg()",3000);

    JQuery 設計資源連結

    jQuery Cycle Plugin
    jQuery Plugin , 圖片輪播器 , 支援非常多的效果

    jCarousel Lite
    JQuery Plugin , 跑馬燈一種 , 可串接多張圖片或 HTML 內容 , 且中途跑馬時資訊不會間斷 , 不同於 <marquee> 效果

    CSS Dock Menu
    大部分是以 CSS 來模仿 Mac OS 的 Dock Menu , 效果非常順暢 , 但要搭配 JQuery 使用

    ColorBox
    ColorBox 是一套類似 lightbox 的 jquery plugin , 但對於 jquery 1.4 相容性比較好

    jCaption
    jQuery Plugin , 可以把 <img> 中的 alt 的文字變為圖說

    2010年8月24日 星期二

    C# 動態載入MATA資訊

            HtmlMeta mata = new HtmlMeta();
    mata.Attributes.Add("http-equiv", "X-UA-Compatible");
    mata.Content = "IE=EmulateIE7";
    this.Page.Header.Controls.Add(mata);

    2010年8月14日 星期六

    使用其他收信軟體收發GMAIL設定方法

    設定您的用戶端,使其符合以下設定:
    內送郵件 (POP3) 伺服器 - 需要 SSL: pop.gmail.com 使用 SSL: 是 通訊埠: 995
    外寄郵件 (SMTP) 伺服器 - 需要 TLS: smtp.gmail.com (使用驗證) 使用驗證: 是 使用 STARTTLS: 是 (某些用戶端稱此為 SSL) 通訊埠: 465 或 587
    帳戶名稱: 您的 Gmail 使用者名稱 (包含 @gmail.com)
    電子郵件地址: 您的完整 Gmail 電子郵件地址 (username@gmail.com)
    密碼: 您的 Gmail 密碼

    除非您是使用最近模式將郵件下載到多個用戶端,否則請確定您已選擇不要在伺服器上保留郵件。 您的 Gmail 設定會決定是否要在伺服器上保留郵件,因此,您在用戶端上的這個設定不會影響 Gmail 處理郵件的方式。

    請注意,若您的用戶端不支援 SMTP 驗證,您就無法透過您的用戶端,使用您的 Gmail 地址傳送郵件。
    參考網址 https://mail.google.com/support/bin/answer.py?hl=b5&answer=13287

    WINDOWS 2003 SERVER SMTP伺服器無法寄信到Hotmail 或 Yahoo 信箱(smtp;550 DY-001 Mail rejected)

    收不到信的部分:

    [3144]05/12/2008 18:14:25.906 450 4.7.1 : Recipient address rejected: Policy Rejection- Please try later.

    收件者的信箱拒收。完整錯誤訊息如下
    Action: failed
    Status: 5.5.0
    Diagnostic-Code: smtp;550 DY-001 Mail rejected by Windows Live Hotmail for policy reasons. We generally do not accept email from dynamic IP's as they are not typically used to deliver unauthenticated SMTP e-mail to an Internet mail server. http://www.spamhaus.org maintains lists of dynamic and residential IP addresses. If you are not an email/network admin please contact your E-mail/Internet Service Provider for help. Email/network admins, please visit http://postmaster.live.com for email delivery information and support

    其原因是
    hotmail 判斷您是浮動 IP 拒收。
    如果您不是浮動 IP 請依他指示的連結處理。

    451 ... Requested mail action not taken: mailbox unavailable
    信箱無法使用。

    請參考以下連結,您的 IP 被列入垃圾郵件黑名單, 而且是整段,112.116.0.0/16,請洽 Hinet 跟換 IP,或是依以下連結的說明處理。
    http://www.spamhaus.org/pbl/query/PBL133756

    不過我想若是使用真正的固定IP來使用SMTP服務時,應該就不會有這樣的問題摟

    WINDOWS 2003 SERVER SMTP伺服器無法寄信(error 5.7.1 Unable to relay for)

    安裝完成後馬上就要測試一下,卻出現[ASP.NET]使用SMTP無法寄信當錯誤訊息是 System.Net.Mail.SmtpFailedRecipientException: 無法使用信箱。 伺服器回應為: 5.7.1 Unable to relay for

    System.Net.Mail.SmtpFailedRecipientException: 無法使用信箱。 伺服器回應為: 5.7.1 Unable to relay for

    若發生以上的錯誤訊息,請注意只需透過設定 步驟如下
    IIS 管理員 - 預設 SMTP 虛擬伺服器 - 內容 - 存取 - 轉接限制 - 轉接 - 原「只有下列清單中的」改為「除了下列的之外的所有」 - 確定 (說明圖片如下)


    WINDOWS 2003 SERVER 架設SMTP伺服器方法

    透過WINDOWS 2003 SERVER 「新增或移除程式」-「新增移除WINDOWS元件」-「WINDOWS 元件精靈」-「選擇E-MAIL Server」之後進行安裝

    安裝完成後,即可在系統管理工具找到「POP3 Service」及在「網際網路資訊服務 (IIS) 管理員」看到「預設 SMTP 虛擬伺服器」,就表示你已經安裝完成瞜

    2010年8月11日 星期三

    C# ListView 之 NumericPagerField 類別 設定分頁分法

    CSS 頁碼屬性
    CurrentPageLabelCssClass 目前頁碼的 CSS 類別。
    NextPreviousButtonCssClass 下一頁和上一頁按鈕的 CSS 類別。
    NumericButtonCssClass 表示頁碼之按鈕的 CSS 類別

    參考 http://msdn.microsoft.com/zh-tw/library/system.web.ui.webcontrols.numericpagerfield(VS.90).aspx

    [jQuery] jquery.scrollable 可以利用鼠標滾輪控制內容顯示


    如果喜歡這類型的控制方法,可以使用mouse wheel 去拉動頁面。更重要的是不影響mouse wheel 正常操作。適當使用可以令website上的控制會更簡單而且可以放更多內容,但又不影響外觀,這是好的工具,值得推薦。
    Demo http://flowplayer.org/tools/scrollable/index.html#

    C# 如何從字符串中刪除 HTML標籤

    using System.Text.RegularExpressions;
    Regex.Replace(字串,@"<(.| \ ñ )*?>", string.Empty)

    C# Left、Right' Mid 都可以用

            public string  StrLeft(string s, int length)
    {
    return s.Substring(0, length);
    }

    public string StrRigth(string s, int length)
    {
    return s.Substring(s.Length - length);
    }

    public string StrMid(string s, int start, int length)
    {
    return s.Substring(start, length);
    }

    str = "123456789"
    Left = str.substring(0,2) = "12"
    Rigth = str.substring(str.length -2) = "89"
    Mid = strsubstring(2,2) = "34"

    using Microsoft.VisualBasic;
    Strings.Right("aaaaa",2);

    2010年8月10日 星期二

    如何使用CSS製作「圖說文繞圖」 (範例實作)

    很多朋友應該都知道如何使用標準的 html 達成簡易的文繞圖效果,作法很簡單,只需要在 img 標籤中加入以下參數即可:align="left" 或是 align="right" ;另外若是文字與圖片緊貼著不好看,你也可以使用 vspace 和 hspace 使圖片與文字之間預留空間。

    以下為完整用法:
    <img src="path.to.image" align="right" hspace="8px" vspace="5px">

    不過眼尖的朋友應該可以發現,使用 hspace 和 vspace 會使圖片的上下及左右皆出現間隔,這樣一來便會讓圖片於相對的內文無法對齊(如上圖所示);且無法順利的加入圖說(caption)。

    以下將介紹如何使用簡單的CSS來製作方便實用的文繞圖效果,且可以漂亮的對齊內文。

    CSS語法
        <style type="text/css">
    .img_left
    {
    float:left;
    }

    .img_right
    {
    float:right;
    }

    </style>
    左邊文繞圖
    <img class="img_left" src="http://f.blog.xuite.net/f7/b7/10055976/blog_6267/txt/126866/126866_8.gif" alt="" />
    右邊文繞圖
    <img class="img_right" src="http://f.blog.xuite.net/f7/b7/10055976/blog_6267/txt/126866/126866_8.gif" alt="" />
    範例:
    /* --- 文繞圖start -------------- */
    div.image-left {
    float: left;
    margin: 0 8px 8px 0;
    }

    div.image-left img {
    border: 1px solid #ccc;
    padding: 4px;
    }

    div.image-left p {
    color: #666;
    font-family: 'Lucida Grande', Lucida Sans Unicode;
    font-size: 9px ;
    margin: 3px 0 0;
    text-align: center ;
    }

    <div class="image-left">
    <img alt="alter text" src="path.to.image" />
    <p>caption caption caption</p>
    </div>

    Exchange 2007 安裝後發信設定筆記 (Socket Error # 10060)

    因要用來寄發EDM,又無註冊網域,僅供內部發信使用時,請注意以下設定

    當發信時出現以下錯誤
    Winsock Error 10060 連線超時
    Message from: to: Connect error in directly sending! Info : Socket Error # 10060

    解決方法 - 原文
    Analyse: You are on a an ISP (such as Earthlink or Mindspring) that blocks their users using any SMTP server other than their own.

    Solutions: To set up Earthlink, Mindspring, or your ISP's SMTP servers for your outgoing email you must click on your account settings in the email client you are using (Outlook Express, Eudora, Netscape etc.)

    In the SMTP (outgoing mail server) field you will enter smtp.earthlink.net (or whatever your dial up or direct access ISP's SMTP server is) as your SMTP server. You must then enter your Earthlink (or your ISP's) username and password for that mail server.

    In Outlook Express it is at the bottom of that same tab. You must uncheck 'My server requires authentication' and click on 'settings' to enter your Earthlink (or your ISP's) username and password.

    Your email will still be from your own domain name, the only difference is in the way it is routed throughout the Internet. Instead of being sent through our servers it is processed through Earthlink (or your ISP's) servers. This allows Earthlink (or your ISP) to monitor its users.

    翻譯後

    分析:你是在一個 ISP(如Earthlink或Mindspring),阻止他們的用戶使用其他任何SMTP服務器比他們自己。

    解決方案:建立Earthlink的,Mindspring,或ISP的SMTP服務器為您的傳出電子郵件,您必須按一下您的帳戶設置中的電子郵件客戶端,您正在使用(Outlook Express中,Eudora和Netscape等)

    在SMTP(發送郵件服務器)字段中,您將進入 smtp.earthlink.net(或者無論您的撥號或直接訪問 ISP的SMTP服務器)作為您的SMTP服務器。然後,您必須輸入您的Earthlink公司(或您的ISP)的用戶名和密碼的郵件服務器。

    在Outlook Express是在底部的相同標籤。您必須取消選中'我的服務器要求身份驗證',點擊'設置'輸入您的Earthlink公司(或您的ISP)的用戶名和密碼。

    您的郵件仍然會從你自己的域名,唯一的區別是它的方式傳送至整個互聯網。而是通過我們的服務器發送它是通過處理 Earthlink公司(或您的ISP)的服務器。這使得EarthLink公司(或您的ISP)來監測其用戶。

    假如看不懂他的說明,那就自己比對下列畫面擷圖的相關設定,自己在思考一下就知道問題出在哪摟,但是若伺服器有對外(即是有實體的網域)時,建議不要如此設定,因為這樣很容易被當作跳板,被駭客或不知名的人透過你的伺服器瘋狂寄發垃圾郵件(因為不需要認證就可以發信),不久的將來你的ISP就會將你封鎖了

    在「伺服器組態」--「集線傳輸」--「接收連接器」

    點選「Client xxxxxxxxxxxxxx」--調整「驗證」及「權限群組」中的安全性設定

    點選「Default xxxxxxxxxxxxxx」--調整「驗證」及「權限群組」中的安全性設定

    EXCHANGE 2007 Key 序號 金鑰

    若不知如何註冊,請參考 Exchange Server 2007 如何輸入產品金鑰

    2010年8月5日 星期四

    Microsoft Visual SourceSafe 2005 (VSS2005) 操作手冊 - 各版本的檔案下載

    步驟一:若要下載各版本檔案資訊,可點選您要下載之版本檔案,點選「Get」

    步驟二:設定要儲存的位置後,按「OK」

    Microsoft Visual SourceSafe 2005 (VSS2005) 操作手冊 - 版本異動紀錄查詢

    步驟一:如上篇,在每個版本的檔案上,選擇你要比對的檔案版本

    步驟二:在「Format」的部分,選擇「SourceSafe」,點選產生「Report」

    步驟三:點選「Preview」

    步驟四:即會出現被異動的行數,並顯示備異動的內容及方式

    Microsoft Visual SourceSafe 2005 (VSS2005) 操作手冊 - 歷史版本查詢

    步驟一:Visual SourceSafe 2005 (VSS2005) 登入畫面

    步驟二:您可以在專案上,看到哪些檔案被「簽出已編輯」

    步驟三:假設你要檢視檔案修改的版本紀錄,你可以在要檢視的檔案上按滑鼠右鍵,選擇「show History」

    步驟四:然後點選「OK」

    步驟五:就可以看到每一個版本及修改的時間、修改的人

    2010年7月27日 星期二

    FILEDECK.NET。5個免空上傳檔案,一次搞定!


    受最近沸沸揚揚的網友之託幫忙介紹一個網站,就是免費空間上傳的網站,一次可以上傳檔案到五個不同的免費空間,雖然說提供的選擇有十個,其實我對於免費空間一點也不熟悉,甚少有機會可以使用到,因為免費空間總是難保資料的永久性啊~

    http://filedeck.net/

    10個免空如下:
    http://www.badongo.com/
    http://rapidshare.com/
    http://www.zshare.net/
    http://www.sendspace.com/
    http://www.megaupload.com/
    http://www.flyupload.com/
    http://www.netload.in/
    http://www.filefactory.com/
    http://www.easy-share.com/
    http://depositfiles.com/


    雖然說有10個免費空間可以選擇,但是勾選時只能勾選五個唷!勾到第六個時就會跳出提醒視窗,選擇上傳檔案必須在50MB以內,我猜可能是考量到某些空間的檔案大小限制,所以就統一到50MB以內,上傳檔案之前別忘了使用條款也要打勾唷!


    還頗喜歡他的上傳介面,可以即時看到上傳進度,這個php怎麼寫啊?誰可以教我啊,我的上傳頁面也想寫成這樣子,不然我自己寫的還頗兩光的!


    上傳好了之後就會有提供一個連結,之後分享檔案就直接給這個連結就對了!


    進去之後網頁會幫忙Check檔案在每一個免空是否還存在,若存在的話就會有一個綠色的勾勾囉!