2008-02-01

取得MS SQL中資料欄位的描述內容

用ado.net的connection.GetSchema取得資料表結構算是蠻方便的.
但差的一點就是取不到欄位的說明.
因為又要開始寫文件了.而之前寫的SchemaGen不能支援MS SQL 2005.
所以現在正在著手寫SchemaGen 2005版.
另外也練習使用所謂的design pattern來進行...
至於用哪個...先試試看再說...

回到主題.
之前其實有寫過相關的主題.
不過當初主要是說明用T-SQL維護欄位的描述.
現在再針對::fn_listextendedproperty加一些說明

如果要針對某個資料表的某個欄位取得
可以使用下面的語法

select value form ::fn_listextendedproperty(NULL, 'user', 'dbo', 'table', N'資料表名稱', 'column', N'欄位名稱')

如果要取得某個資料表中所有欄位說明的話,可以使用

select * form ::fn_listextendedproperty(NULL, 'user', 'dbo', 'table', N'資料表名稱', 'column',NULL)

另外.如果你的資料表也有設定說明的話,
可以使用下面的語法取得資料表的說明

select * form ::fn_listextendedproperty(NULL, 'user', 'dbo', 'table', N'資料表名稱',NULL,NULL)

當然.要取的所有資料表的說明就是用下面這個

select * form ::fn_listextendedproperty(NULL, 'user', 'dbo', 'table',NULL,NULL,NULL)

另外,上面的參數中有使用NULL的,也可以改用default.意義應該是相同的.例如

select * form ::fn_listextendedproperty(default, 'user', 'dbo', 'table',default,default,default)

而修改或是新增欄位或是資料表說明的話,
可以參考上次寫的T-SQL維護欄位的描述,
使用sp_addextendedproperty及sp_updateextendedproperty來處理

 

相關連結 :

fn_listextendedproperty (Transact-SQL)
http://msdn2.microsoft.com/en-us/library/ms179853.aspx

sp_addextendedproperty (Transact-SQL)
http://msdn2.microsoft.com/en-us/library/ms180047.aspx

sp_updateextendedproperty (Transact-SQL)
http://technet.microsoft.com/zh-tw/library/ms186885.aspx

2008-01-26

玩玩.net的ildasm與ilasm

之前有個朋友拿個vb6的程式給我.
說這是他請別人寫的,需要密碼才能開啟使用,
可是他忘了密碼是甚麼,而且沒有原始碼,
希望看看有沒有辦法"找到".

程式的功能是甚麼已經有點不記得了,因為不是重點.
重點是他的密碼並沒有在資料庫中,因為翻遍資料庫(Access)中的資料表沒有找到任何訊息.
所以猜測密碼應該是在包在程式裡了.

所以直接用十六進位編輯器(ultraedit)開啟那個執行檔.
在檔案中看到password的字樣,而就在附近看到了"疑似"密碼的字串.
然後使用那個密碼試著登入.果然真的是密碼...

不知道各位看了上面這個例子會有甚麼想法!!

回到主題.
今天要介紹的是ildasm跟ilasm的功能.
在msdn上的介紹寫著 :

MSIL 反組譯工具是 MSIL 組譯工具 (Ilasm.exe) 的附屬工具。Ildasm.exe 使用包含 Microsoft Intermediate Language (MSIL) 程式碼的可攜式執行檔 (PE),並建立可以做為 Ilasm.exe 的輸入檔的文字檔。

如果你跟我一樣看了還是不懂他是用來做甚麼的話,那就先往下看.
為了測試,我們要先寫個主控台程式(ConsoleApplication).
主要的功能如下:

讓使用者輸入帳號密碼,
然後判斷是否跟我們設定好的字串相同.
如果相同就顯示welcome,
如果不同就顯示Access Deny.

程式碼如下:

using System;

namespace LoginConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            string UserId = "ajun";
            string UserPwd = "password";

            Console.Write("Please enter your id : ");
            string uid = Console.ReadLine();
            Console.Write("Please enter your password : ");
            string pwd = Console.ReadLine();

            if ((uid == UserId) && (UserPwd == pwd))
            {
                Console.WriteLine("Welcome!");
            }
            else
            {
                Console.WriteLine("Access Deny!");
            }
        }
    }
}

寫好後編譯成exe檔.(假設我們編譯完後的執行檔的名稱為 LoginConsole.exe)
然後開啟一個dos視窗.
因為我是用vs.net 2005.
所以要將路徑切換到到
C:\Windows\Microsoft.NET\Framework\v2.0.50727
因為ildasm.exe是放在這個路徑下.
當然.如果你是透過"Visual Studio 2005命令提示字元"啟動命令視窗的話,就不用切換目錄了.

然後執行下列的指令 :

ildasm LoginConsole.exe

這時就會跳出ildasm的視窗如下 :

ildasm001

點開其中的 Main : void(string[])
就可以看到如下反組譯的視窗畫面

ildasm002

而內容如下 :

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // 程式碼大小       104 (0x68)
  .maxstack  2
  .locals init ([0] string UserId,
           [1] string UserPwd,
           [2] string uid,
           [3] string pwd,
           [4] bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  ldstr      "ajun"
  IL_0006:  stloc.0
  IL_0007:  ldstr      "password"
  IL_000c:  stloc.1
  IL_000d:  ldstr      "Please enter your id : "
  IL_0012:  call       void [mscorlib]System.Console::Write(string)
  IL_0017:  nop
  IL_0018:  call       string [mscorlib]System.Console::ReadLine()
  IL_001d:  stloc.2
  IL_001e:  ldstr      "Please enter your password : "
  IL_0023:  call       void [mscorlib]System.Console::Write(string)
  IL_0028:  nop
  IL_0029:  call       string [mscorlib]System.Console::ReadLine()
  IL_002e:  stloc.3
  IL_002f:  ldloc.2
  IL_0030:  ldloc.0
  IL_0031:  call       bool [mscorlib]System.String::op_Equality(string,
                                                                 string)
  IL_0036:  brfalse.s  IL_0044
  IL_0038:  ldloc.1
  IL_0039:  ldloc.3
  IL_003a:  call       bool [mscorlib]System.String::op_Equality(string,
                                                                 string)
  IL_003f:  ldc.i4.0
  IL_0040:  ceq
  IL_0042:  br.s       IL_0045
  IL_0044:  ldc.i4.1
  IL_0045:  stloc.s    CS$4$0000
  IL_0047:  ldloc.s    CS$4$0000
  IL_0049:  brtrue.s   IL_005a
  IL_004b:  nop
  IL_004c:  ldstr      "Welcome!"
  IL_0051:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0056:  nop
  IL_0057:  nop
  IL_0058:  br.s       IL_0067
  IL_005a:  nop
  IL_005b:  ldstr      "Access Deny!"
  IL_0060:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0065:  nop
  IL_0066:  nop
  IL_0067:  ret
} // end of method Program::Main

而從這內容就可以很清楚的看到我們所設定的帳號密碼.
到這.我想大家應該比較清楚ildasm.exe的功能了.

再來在說一下ilasm.exe,
ildasm是用來做反組譯的,
而ilasm就是用來作組譯用的.
至於怎麼用.看一下下面的用法.

現在我們先用ildasm.exe來產生剛剛所寫的程式的PE檔.
語法如下 :

ildasm /source LoginConsole.exe /out:LoginConsoleFake.txt

其中的/source參數是用來"顯示原始程式行做為註解".
然後我們就可以得到下面這個LoginConsoleFake.txt的檔案.

//  Microsoft (R) .NET Framework IL Disassembler.  Version 2.0.50727.42
//  Copyright (c) Microsoft Corporation.  All rights reserved.

// Metadata version: v2.0.50727
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 2:0:0:0
}
.assembly LoginConsole
{
  .custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = ( 01 00 07 31 2E 30 2E 30 2E 30 00 00 )             // ...1.0.0.0..
  .custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 65 30 31 65 31 37 32 31 2D 37 32 62 63   // ..$e01e1721-72bc
                                                                                                  2D 34 33 61 62 2D 38 65 62 62 2D 34 66 66 38 34   // -43ab-8ebb-4ff84
                                                                                                  31 62 65 34 65 37 36 00 00 )                      // 1be4e76..
  .custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = ( 01 00 00 00 00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = ( 01 00 13 43 6F 70 79 72 69 67 68 74 20 28 43 29   // ...Copyright (C)
                                                                                                  20 20 32 30 30 38 00 00 )                         //   2008..
  .custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = ( 01 00 0C 4C 6F 67 69 6E 43 6F 6E 73 6F 6C 65 00   // ...LoginConsole.
                                                                                                00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = ( 01 00 00 00 00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = ( 01 00 00 00 00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = ( 01 00 00 00 00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = ( 01 00 0C 4C 6F 67 69 6E 43 6F 6E 73 6F 6C 65 00   // ...LoginConsole.
                                                                                              00 )

  // --- 以下為自動加入的自訂屬性,請勿取消註解 -------
  //  .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )

  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
  .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                             63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
  .hash algorithm 0x00008004
  .ver 1:0:0:0
}
.module LoginConsole.exe
// MVID: {71069530-5126-4026-B70A-03F69CFFD29A}
.imagebase 0x00400000
.file alignment 0x00001000
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x009C0000

// =============== CLASS MEMBERS DECLARATION ===================

.class private auto ansi beforefieldinit LoginConsole.Program
       extends [mscorlib]System.Object
{
  .method private hidebysig static void  Main(string[] args) cil managed
  {
    .entrypoint
    // 程式碼大小       104 (0x68)
    .maxstack  2
    .locals init ([0] string UserId,
             [1] string UserPwd,
             [2] string uid,
             [3] string pwd,
             [4] bool CS$4$0000)
    .language '{3F5162F8-07C6-11D3-9053-00C04FA302A1}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}'
// Source File 'D:\Project\LoginConsole\LoginConsole\Program.cs'
//000010:         {
    IL_0000:  nop
//000011:             string UserId = "ajun";
    IL_0001:  ldstr      "ajun"
    IL_0006:  stloc.0
//000012:             string UserPwd = "password";
    IL_0007:  ldstr      "password"
    IL_000c:  stloc.1
//000013:
//000014:             Console.Write("Please enter your id : ");
    IL_000d:  ldstr      "Please enter your id : "
    IL_0012:  call       void [mscorlib]System.Console::Write(string)
    IL_0017:  nop
//000015:             string uid = Console.ReadLine();
    IL_0018:  call       string [mscorlib]System.Console::ReadLine()
    IL_001d:  stloc.2
//000016:             Console.Write("Please enter your password : ");
    IL_001e:  ldstr      "Please enter your password : "
    IL_0023:  call       void [mscorlib]System.Console::Write(string)
    IL_0028:  nop
//000017:             string pwd = Console.ReadLine();
    IL_0029:  call       string [mscorlib]System.Console::ReadLine()
    IL_002e:  stloc.3
//000018:
//000019:             if ((uid == UserId) && (UserPwd == pwd))
    IL_002f:  ldloc.2
    IL_0030:  ldloc.0
    IL_0031:  call       bool [mscorlib]System.String::op_Equality(string,
                                                                   string)
    IL_0036:  brfalse.s  IL_0044

    IL_0038:  ldloc.1
    IL_0039:  ldloc.3
    IL_003a:  call       bool [mscorlib]System.String::op_Equality(string,
                                                                   string)
    IL_003f:  ldc.i4.0
    IL_0040:  ceq
    IL_0042:  br.s       IL_0045

    IL_0044:  ldc.i4.1
    IL_0045:  stloc.s    CS$4$0000
    IL_0047:  ldloc.s    CS$4$0000
    IL_0049:  brtrue.s   IL_005a

//000020:             {
    IL_004b:  nop
//000021:                 Console.WriteLine("Welcome!");
    IL_004c:  ldstr      "Welcome!"
    IL_0051:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_0056:  nop
//000022:             }
    IL_0057:  nop
    IL_0058:  br.s       IL_0067

//000023:             else
//000024:             {
    IL_005a:  nop
//000025:                 Console.WriteLine("Access Deny!");
    IL_005b:  ldstr      "Access Deny!"
    IL_0060:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_0065:  nop
//000026:             }
    IL_0066:  nop
//000027:         }
    IL_0067:  ret
  } // end of method Program::Main

  .method public hidebysig specialname rtspecialname
          instance void  .ctor() cil managed
  {
    // 程式碼大小       7 (0x7)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method Program::.ctor

} // end of class LoginConsole.Program

// =============================================================

// *********** 反組譯作業完成 ***********************
// 警告: 已建立 Win32 資源檔 LoginConsoleFake.res

再來我們將這個檔案做些小調整.
從檔案中我們可以很容易看出哪個是帳號密碼的設定.
所以我們直接改一下密碼.將他改為1234.

IL_0007:  ldstr      "password"
改為
IL_0007:  ldstr      "1234"

存檔後.在dos的視窗輸入下列指令

ilasm LoginConsoleFake.txt

當執行完成後,它會產生一個LoginConsoleFake.exe的檔案.
這時你就可以執行它.然後輸入新的密碼看看!!

我想這時你應該對於ildasm跟ilasm有初步的認識了...
雖然這並不是一個很正面的例子.
但是,我想應該是可以讓人比較有興趣...

其實,ildasm有更正面的用法,
像是黑暗執行緒寫的這篇,

或是你想要看看對於sqlconnection使用using跟使用close()與Dispose(),
在編譯後所進行的動作有甚麼差異.
也都是可以透過這個工具來進行.

最後,你或許會覺得.net的程式就這麼"透明",這麼不安全嗎??
其實有攻就有防.
下個主題或許可以來說一下.net的"混淆器"(obfuscator).

2007-12-27

mssql只取得時間欄位中的日期資料(Get Date from DateTime)

DateTime的欄位內容為 2007/12/27 18:26:29.597
現在想要只取得2007/12/27而且要保持為日期型態.
也就是要取得2007/12/27 00:00:00的結果
原本是想用format的方式來取得字串結果,然後再轉型態.

不過這樣的語法似乎太長了點.
所以改成下面的方式

select dateadd(dd,0,datediff(dd,0,getdate()))

先使用datediff取得該日期的數值,
再使用dateadd去取得此數值所代表的日期.

雖然使用select cast(getdate() as int)雖然也是可以將日期轉為數值,
但是只要超過12:00就會取得隔天的日期(應該是4捨5入的原因)

select cast('2007/12/27 12:00:00' as datetime)
-- 2007-12-27 12:00:00 000
select cast(cast('2007/12/27 12:00:00' as datetime) as int)
-- 39442
select cast('2007/12/27 11:59:59' as datetime)
-- 2007-12-27 11:59:59
select cast(cast('2007/12/27 12:59:59' as datetime) as int)
-- 39941

所以還是使用datediff的方式來取得日期的數值比較好.

2007-12-26

玩玩紙模型

今天發現幾個不錯的紙模型網站

第一彈 : EX-S 鋼彈
EX-S PaperModel_02
原創者的網誌:http://blog.naver.com/7200ss
不過現在很難找到下載點了.所以要用力google一下

GUNDAM紙模型的下載與作品
如果是鋼彈迷的話可以到這挖寶,不過可能手腳要快點.

Canon的Creative Park
裡面的3D-papercraft有許多紙模型可以下載,
如果有打算做個城鎮的話,可以看一下他的craftown,
沒太多錢可以弄個鐵道模型城鎮的話,可以先玩玩這個.
另外他的buildings看起來也是超優的!
 

YAMAHA的Paper Craft
既然是YAMAHA的網站,
主要的當然就是摩托車的紙模型了!
不過除了摩托車外,還有一些動物及日本風情的紙模型也是不錯的!
另外,還有提供紙模型的教學
http://www.yamaha-motor.co.jp/global/entertainment/papercraft/howto/index.html
影片式的教學讓你一看就懂.
http://www.yamaha-motor.co.jp/global/entertainment/papercraft/howto/0002.html

3D紙模型網
我想只要有在玩紙模型的應該都知道這個網站!!

真的要去買台彩色印表機了...
不然我的機器人都只能是鐵灰色的...

2007-12-13

DateTime Formet 與 CultureInfo

今天收到一個問題,
是要將時間格式顯示為
Thu,13 Dec 2007 08:23:41 +08:00

大致上先想到的是取得格林威治時間
也就是用

DateTime.Now.ToUniversalTime().ToString()

因為台灣的時區是 +8,
所以取得的時間會是台灣時間減8小時.

他這樣的格式會顯示
2007/12/13 上午 08:23:41

然後在ToString()的格式加上"r"
如 :

DateTime.Now.ToUniversalTime().ToString("r");

這樣的結果會顯示
Thu, 13 Dec 2007 08:23:41 GMT

已經有點接近我們要的格式了,
不過還少了+08:00
查了一下,可以在格式中加個zzz來達成
但是zzz跟r似乎是不能一起使用.
所以改成如 :

DateTime.Now.ToUniversalTime().ToString("ddd,d MMM yyyy hh:mm:ss zzz");

這樣的結果變成
星期四,13 十二月 2007 08:23:41 +08:00

因為作業系統的地區與語言選項的設定是預設的中文(台灣)
所以會顯示中文字在時間字串中.
所以要再使用CultureInfo改一下.

System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("en-US");
DateTime.Now.ToUniversalTime().ToString("ddd,d MMM yyyy hh:mm:ss zzz",ci);

這時資料就會是以英文(美國)的格式呈現,如下:
Thu,13 Dec 2007 08:23:41 +08:00

上面這樣大致上就可以得到我們要的結果,
不過,每次顯示都要再丟ci進去.
所以,如果不想每次都丟ci的話,
那就是再加一行code
如下

System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("en-US");
System.Threading.Thread.CurrentThread.CurrentCulture = ci;
DateTime.Now.ToUniversalTime().ToString("ddd,d MMM yyyy hh:mm:ss zzz");

到此.收工.

參考資料 :

Standard DateTime Format Strings
http://msdn2.microsoft.com/en-us/library/az4se3k1(VS.71).aspx

Custom DateTime Format Strings Output Examples
http://msdn2.microsoft.com/en-us/library/hzz3aycd.aspx

CultureInfo 類別
http://msdn2.microsoft.com/zh-tw/library/system.globalization.cultureinfo(VS.80).aspx

2007-11-20

C#中??的用法

改用c# 2.0也一年多了,
最近才發現??的用法.

??這個operator的用法如下

string message = null;
string result = message ?? "message is null";
Console.WriteLine(result); //列印出 message is null

 

string message = "I am not null";
string result = message ?? "message is null";
Console.WriteLine(result); // 列印出 I am not null

另外,在數值方面,

int x = null;

這樣是會產生編譯錯誤(Cannot convert null to 'int' because it is a non-nullable value type).
所以如果你就是要宣告一個int而可以是個null的內容的話,
那就是用

int? x = null;

再搭配??的用法如下

int? x = null;
int y = x ?? -1;
Console.WriteLine(y.ToString()); //列印出 -1

2007-11-02

mysql的問題...

不常寫php+mysql的案子,
但最近接了一個簡單的案子,
大致上之前也寫過類似的,
所以想說應該是沒有甚麼問題.
但是寫完後,要佈到客戶那才發現問題一堆.

1.CURRENT_TIMESTAMP無法使用.

因為想要有個欄位自動記錄資料新增的時間,
但mysql 4似乎沒有這個型態.
所以只好改為DateTime,再新增的時候再寫now()取得時間.

2.mysql密碼問題

這個之前在架mambo的時候有遇過,所以還ok.
只要用下面的語法改一下密碼就ok了.
set password for '帳號'@'主機' = old_password('新的密碼');

3.adddate的問題

原本是用adddate(Current_Date(),5)取得五天後的時間點,
但是丟到客戶卻一直出現問題.
後來才發現客戶是用mysql 4.0.13
而我是抓mysql 4.1.22
而4.1.22是可以接受這樣的語法,
但是4.0.13則要使用下列的語法,
adddate(Current_date(),interval 5 day)

看來 php 跟 mysql 還有一堆東西要學...

2007-09-17

SqlParameter設定value為0卻變成null

今天遇到一個不知道是不是bug的問題.
就是當我使用下面語法去產生一個SqlParameter時,

new SqlParameter("@test",0)

程式一直出錯說要設定參數.
看了一下上面所產生的東西,
value竟然是null,
但是如果改為

new SqlParameter("@test",1)

value又變成是正常的1
看來似乎是不讓我直接設0
後來只好改用

new SqlParameter("@test", Convert.ToInt32(0))

這樣就可以正常傳入0了...

updtae:

另一個設定的方式如下(差別在特別指定了SqlDbType)

SqlParameter param = new SqlParameter("@test", SqlDbType.Int);
param.Value = 0;

2007-09-09

freelancer

freelancer : 自由工作者

freelancer這個詞最早是在說中古世紀的自由騎士.
而現在主要是在說提供專業技能但非長期的工作者.

有些人聽到自由工作者可能會想到soho,
但跟soho比較不同的是,soho是指以家為工作場所的,
但是freelancer則可能是跟著工作跑.沒有一個固定的地方.

在台灣,freelancer 似乎比較少聽到,
可能是因為大家對於工作的態度都是想要找一個可以作一輩子的工作.

但是目前企業對於徵人的方式也漸漸在改變,
有越來越多的企業是透過人力公司來找短期的派遣人員,
或是使用短期約聘的條件來徵人,
(之前做過一家人力派遣公司的網站,
發覺現在各大公司的客服人員好像都是派遣的.)
所以也有越來越多人的工作性質類似freelancer.

而我,現在也算是freelancer,
聽到"中古世紀的自由騎士",
感覺似乎很浪漫...
但事實上卻並不是如此.
畢竟,這一切還不都是關係著工作與生活...

目前這樣的工作型態已經有一年多了,
經歷了兩個案子,第一個大約是一年,
現在這個才剛開始沒多久,大約一個多月.
但實際上,再第一年中,以不是整整一年都再做同一個案子,
其中還曾協助其他的案子做過幾天,
所以不計時間長短的話,應該算是四個案子.
所以曾經在一個禮拜跑三個地方.
星期一,三在板橋,
星期四在西門町,
星期二,五在中正紀念堂附近.
因為我做的就是寫程式,
所以一個禮拜是同時進行三個系統的撰寫...

我想,寫程式的應該都會有種情況,
當你上班在寫程式的時候,
寫的最順的時候通常是快下班的時候.
因為早上一來公司,剛睡醒,所有的思緒都還在重組當中.
進辦公室開電腦,還只能在網路上神遊,可能到了中午才能進入寫程式的狀態.
才剛開始想到昨天進度與今天要做的部份,時間已經快一點了.
早上沒吃東西,現在已經快不行了,還是先吃中餐再說...
然後大約下午五六點的時候,正是你的思緒跟系統可以接上軌的時候,
但這時行政人員已經要下班了,
而你這時當然不可能下班,因為你的專案進度在這時才剛要突飛猛進,
所以為了趕進度,也忘了吃晚餐.
等你抬頭看看四周時,如果你的公司能夠看到外面的天空,應該已經是星光點點了...
而外面的車潮也已經散去,
可能只剩下幾隻野狗在路邊翻著垃圾桶.
行人三三兩兩地趕著搭最後一班公車.
偶爾,還能看到一群人搖搖晃晃的招著計程車,很明顯的喝了不少...
這時,你才想起晚餐還沒吃,今天就寫到這個段落.明天再繼續,
然後整理一下東西準備下班去了...

但是當你今天再寫一個新聞管理系統,
明天卻是一個人事管理系統.
每天都是不一樣的系統,今天來是要進入前天的狀況,
所以,一個禮拜做三個不同的案子,
你應該就大約可以知道是個怎樣的情況了.
我還曾經到了中正紀念堂後才發現,
今天是要去大直...
不過現在還好...最多兩個而已...

說完工作內容,再來說說待遇與福利吧.
短期的工作,通常是不要期待有什麼年終獎金,
因為你可能待不滿一年,也可能再過年前就換了.
所以這工作是不會有什麼年終獎金的,
因此,在談待遇的時候,是要將年終攤平各月中的,
一般的資訊軟體或是網路公司的年終可能是兩個月,
也就是保障年薪可能14個月,
那你就是以年薪12個月來計算.
當然,除了薪水外,還要計算其他的福利,
像是公司旅遊,三節獎金,生日禮金,等等的.
甚至有些公司還會有所謂的進修補助等等的.
這些都是可以計算進去的部份.
把你所想要的年薪再加上這些雜七雜八的福利後除以12,
大約就是做freelancer應該要拿到的期望薪資.
另外,因為現在有勞退新制,所以退休金的部份也是可以談的部份,
還有休假等等的也是.
只要記住一件事.該有的福利不能少,大部分的福利都可以用錢計算...

以前,還在唸書的時候,常常都會看日劇,
裡面總是有許多日本上班族的生活情境,
下班後,約些同事,去小酒館喝酒聊天,說說八卦,
那時總是很想以後上班也能像這樣.
但是...現在幾乎完全沒有這樣的機會,只有偶爾回去找之前的同事聚聚餐.

案子之所以需要短期的人力,
就是因為要趕案子,所以當你做這個案子的時候,就是要一直忙到案子結束.
所以不像是待在公司,來上班還能跟同事哈拉,
有時,等你專案裡的同事比較熟悉的時候,案子就要結束了.
去小酒館喝喝酒都很難了,那就更別提什麼員工旅遊了.
我想很多人應該跟我一樣,喜歡這種團體旅遊的感覺.
就像是高中的畢業旅行,一夥人晚上不睡覺,在飯店打牌哈拉,甚至是去夜遊.
但是當freelancer你就別想要有什麼員工旅遊了.
還是多賺點錢,自己去跟團吧...但跟不熟的人去玩,總是比較不好玩!!

好吧.發了一堆牢騷,
今天就先寫到這.改天再繼續...

2007-08-15

用C#改檔名

今天有個需求,
需要有個功能將遠端的檔案用webclient下載下來存成暫存的檔名後,
確定沒有問題再將它更名為原本的檔名.

但是,寫到要更改檔名時,
發現.net的System.IO中似乎沒有rename的功能,
所以需要使用Copy或是Move的方法來達成.

而用Copy的話,會有個問題,就是當檔案大的時候會很慢,
而且還是要需求看是否要刪除原本的檔案.
所以比較合適的方式是用move.
更名的程式片段如下 :

public bool Rename(string  source,string dest)
{
    try
    {
        if  (!(File.Exists(source))) return false;
        string  dest  =  GenDestName(source); 
        if  (File.Exists(dest))
        {
            return false; 
        }
        File.Move(source,  dest); 
    }
    catch(Exception ex)
    {
        throw ex;
    }
}

2007-07-12

這條路就是不斷的學習

走這條路似乎就是這樣,
時常都有一堆假根(Jargon)...

WSE - Web Services Enhancements
http://msdn2.microsoft.com/en-us/webservices/aa740663.aspx
WCF - Windows Communication Foundation
http://wcf.netfx3.com/
WPF - Windows Presentation Foundation
http://wpf.netfx3.com/
WF - Windows Workflow Foundation
http://wf.netfx3.com/

一時看不完,就先紀錄一下...
有關 ASMX 2.0、WSE 3.0 和 WCF 的內容
http://www.microsoft.com/china/MSDN/library/WebServices/WebServices/0601ServiceStation.mspx?mfr=true
WCF 性能有多快?
http://www.dotnettools.org/Blog/article.asp?id=203
WCF系列
http://www.cnblogs.com/artech/category/76626.html

另外 Enterprise Library 目前最新版本為 3.1
Microsoft patterns & practices 中的
software factories 及 Guidance automation Extensions and Guidance automation Toolkit 
是這幾天的目標... 

當開發機是Windows on ARM...

 在MacOS上要使用windows去編譯一些程式常常會遇到一些plamform的問題... - cmake build failed 當使用 cmake -S . -B build 要建立 build system files 原本的專案是在x64上, 所以直接執行會直接使用A...