顯示具有 C#筆記 標籤的文章。 顯示所有文章
顯示具有 C#筆記 標籤的文章。 顯示所有文章

星期五, 10月 01, 2010

.Net 讀Excel的讀0開頭的數值

原本把Zipcode當數值讀進來
沒想到美國有0開頭的Zipcode
造成存檔時 會少個0
於是就把Excel的儲存格(cell)改成「文字」格式
再由C#讀進Data Table

但事情就是沒這麼順利
有時讀進來是空值
也不知為什麼,後來試了一下
當把儲存格轉成「文字」格式時
該儲存格會變成有小綠標的儲存格(如下圖)

這時是可以讀進來的
但有時是沒有的... 所以要click一下這個儲存格
讓這儲存格有小綠標 這樣就ok了

p.s. 但也遇過 有小綠標 但還是讀失敗的
 不過不記得當時的情況,遇到再說吧

星期二, 4月 27, 2010

組合exe,dll成單一執行檔 - ILMerge

寫好的程式常會include一些dll檔,每次copy給同事,就會發現漏掉dll沒給
查了一下 原來.net下有ILMerge 這好東西
下載:ILMerge

寫法
將aaa.exe跟bbb.dll及ccc.dll合併成Merged.exe
ILMerge.exe /out:Merged.exe aaa.exe bbb.dll ccc.dll
當然要先設環境變數囉
一般預設路徑C:\Program Files\Microsoft\ILMerge

另還有GUI
不過還是直接在建置事件那設定完最快了
每次compile完 就完成了...真是好東西
到Visul Studio的專案屬性裡的建置事件,如下圖












Error Code
  • 1: 發現是缺了要合併的檔案,補上就ok了
    • 不過有時也有其他問題,要log下來才知道 其他

Reference:
介紹好用工具:ILMerge (將多的 .NET 組件合併成單一組件)

星期四, 2月 25, 2010

委派時機

雖然知道delegate
但要說使用時機..還真不知什麼時候用

委派有用的時機:

* 當單一方法被呼叫。
* 當一個類別可能想要有該方法規格的多個實作。
* 當想要允許使用靜態方法來實作規格。
* 當想要事件形式的設計模式 (如需詳細資訊,請參閱事件教學課程)。
* 當呼叫者不需要知道或取得定義方法所在的物件。
* 當實作的提供者只想要將規格的實作「提供」給少數選取的元件。
* 當想要易於撰寫。

介面有用的時機:

* 當規格定義了一組會被呼叫的相關方法。
* 當類別通常只實作規格一次。
* 當介面的呼叫者想要轉換成或從介面型別上取得其他介面或類別。


Reference
委派教學課程

星期一, 2月 22, 2010

檢查網路連線

You can check for a network connection in .NET 2.0 using GetIsNetworkAvailable():

System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()

To monitor changes in IP address or changes in network availability use the events from the NetworkChange class:

System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged
System.Net.NetworkInformation.NetworkChange.NetworkAddressChanged


Reference
How do I check for a network connection

星期五, 10月 30, 2009

要先引用幾個COM元件
查了一下還真麻煩
後來發現直接引進Microsoft Excel 11 Object就會自動帶入其他的COM

[C# .Net] Microsoft.Office.Interop.Excel 讀 / 寫 Excel 語法概全

Reading and Writing Excel Spreadsheets Using ADO.NET C# DbProviderFactory

星期一, 10月 19, 2009

不規則 Form 透背及拖曳

簡單方法 (只限24bit color以下)
//將form的透明鍵值設為一特定值
//方法1.圖中的10,10為透明鍵值
this.TransparencyKey = Img.GetPixel(10,10);

//方法2.直接指定顏色為透明鍵值
this.TransparencyKey = System.Drawing.Color.Transparent;//指定透明色
this.TransparencyKey = Color.Red; //或指定特定色

如此一來 圖中有該指定色 即會透明

如果放在panel裡,那panel也要設透背
在panel要設背景色,才會透到form上的顏色(當然...form也是透背...)
xxPanel.BackColor = System.Drawing.Color.Transparent;
這樣裡面的東西才會透背

WebBrowser透背
只要在form的屬性設TransparencyKey 為Transparent即可
剩下的當然是網頁裡的圖要去背

另一種方法-以圖去畫透背 ( 24bit Color 以上適用 )
先引用using System.Drawing.Drawing2D;
看source吧



--

假設標題列(pnlTitle)為拖曳
//全域變數
int nOldWndLeft;
int nOldWndTop;
int nClickX;
int nClickY;
...

#region "GUI event"
//滑鼠按下的事件
private void pnlTitle_MouseDown(object sender, MouseEventArgs e)
{
nOldWndLeft = this.Left;
nOldWndTop = this.Top;
nClickX = e.X;
nClickY = e.Y;
}

//滑鼠拖曳事件
private void pnlTitle_MouseMove(object sender, MouseEventArgs e)
{
if (pnlTitle.Capture == true) //如果滑鼠按著拖曳
{
//'設定新的視窗位置
this.Top = e.Y + nOldWndTop - nClickY;
this.Left = e.X + nOldWndLeft - nClickX;
//更新紀錄的視窗位置
nOldWndLeft = this.Left;
nOldWndTop = this.Top;
}
}
#endregion



form在拖拉時會產生閃爍問題
//建構子裡
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
SetStyle(ControlStyles.DoubleBuffer, true); // 雙緩衝


source:
C#製作不規則窗口 ( 24bit Color 以上適用 )

星期二, 9月 15, 2009

帳號、密碼的管理

存放帳、密
利用windows的註冊表來儲放帳、密

//在註冊表的HKEY_CURRENT_USER下建立AccountInfo資料夾及kevyu的鍵值
using Microsoft.Win32;
...
RegistryKey key = Registry.CurrentUser; //放在CurrentUser下
RegistryKey newkey = key.CreateSubKey(@"AccountInfo"); //在CurrentUser下建立AccountInfo資料夾
newkey.SetValue("kevyu", "ok1234"); //建立kevyu的密碼值 ok1234

//讀取值
RegistryKey mykey = key.OpenSubKey(@"AccountInfo", true);
Console.WriteLine("kevyu's password is " + mykey.GetValue("kevyu"));

當然 這樣存明碼實在太high了...
看下一步來加密

加密
存儲密碼——要做對

星期二, 6月 23, 2009

透過C#寄發mail

1.直接寄發
透過System.Net.Mail,舊的System.Web.Mail不用了
reference
MailMessage 類別


2.呼叫outlook
需加入參考「 Microsoft Outlook 11.0 Object Library」
Outlook.ApplicationClass app = new Outlook.ApplicationClass();
Outlook.MailItemClass mi = (Outlook.MailItemClass)app.CreateItem(Outlook.OlItemType.olMailItem);
mi.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
mi.To = "yurenju@gmail.com";
mi.Display(new object());


references
C# 呼叫 Outlook

3.呼叫預設email程式
private void StartDefaultClient()
{
string filename = "mailto:jismenon@yahoo.com?subject=Hello&body=Hello&cc=meera@yahoo.com&bcc=jany@yahoo.com&Attach=@C:\\test.txt";
Process myProcess = new Process();
myProcess.StartInfo.FileName = filename;
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.RedirectStandardOutput = false;
myProcess.Start();
}

references
Opening default Email client from a C# Application


p.s 斷行問題
body裡有斷行時,要改用escape("\n") 或 %0A
否則會沒效果

星期三, 6月 03, 2009

將DataTable裡的Byte column存入access

string[] myPicArrayTitle = new string[] { "Pic1", "Pic2"};
foreach(string title in myPicArrayTitle )
{
string strSQL = string.Format("Update PicInfo Set {0}=@{0} Where PicSN={1}", title, PicSN);
accessAdapter.MdbAccessOLE(strSQL , title,(byte[])dt.Rows[0][title]);
}
public bool MdbAccessOLE(string strSQL,string ColName ,byte[] FileByteArray)
{
this.my_StrConnection = "Provider=Microsoft.JET.OLEDB.4.0;data source=" + this.my_TablePath;
OleDbConnection my_conn = new OleDbConnection(this.my_StrConnection);
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = my_conn;
cmd.CommandText = strSQL;
cmd.Parameters.Add("@"+ColName, System.Data.OleDb.OleDbType.Binary, FileByteArray.Length).Value = FileByteArray;

bool result = true;
try
{
cmd.Connection.Open();
cmd.ExecuteNonQuery();

}
catch (Exception ex)
{
result = false;
SharedAPI.Log_Error("MDB操作失敗, 錯誤訊息:" + ex.Message + " SQL:" + strSQL);
}
finally
{
cmd.Connection.Close();
}
return result;
}

星期一, 5月 04, 2009

開啟預設Browser

利用Process就可了

//直接執行,就是預設的browser
System.Diagnostics.Process.Start("http://www.google.com/");


要指定browser
//指定ie
System.Diagnostics.Process.Start("IExplore.exe", "http://www.google.com");

星期四, 4月 16, 2009

C# 列印 Word

列印文件
HOW TO:列印文件
若要列印整份文件
若要列印文件的目前頁面

這寫法還真特別
using Word = Microsoft.Office.Interop.Word;

合併列印

HOWTO:讓 Microsoft Word 由 Visual C# .NET 自動執行合併列印

星期日, 4月 12, 2009

改變DataGridView的值或cell顏色

在設定DataSource後,改
dataGridView1.DataSource = DataTable;
foreach (DataGridViewRow dgv in dataGridView1.Rows)
{
row.DefaultCellStyle.BackColor = Color.Red; //改row的顏色
row.Cells["Col_AddUpdate"].Value = "新增"; //改內容值
}


但這樣改是無用的
因為必需在Bind Data的event後
private void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
//在這裡改才有用
foreach (DataGridViewRow dgv in dataGridView1.Rows)
{
row.DefaultCellStyle.BackColor = Color.Red; //改row的顏色
row.Cells["Col_AddUpdate"].Value = "新增"; //改內容值
}
}

星期五, 3月 27, 2009

常用的正規表達示-統計

  • 統計字串中內某字元或字串出現次數
    /*
    * JavaScript 
    * 找出cloudchen有幾個c
    */
    var str =  "cloudchen"
    var find = "c";
    var reg = new RegExp(find,"g")
    var result = str.match(reg);
    var count = (result)?result.length:0;
    console.log('共:%d次',count);
    reference: JavaScript 統計字串中內某字元或字串出現次數
  • 統計字串中內某字元或字串出現次數
    去-,:,空白,由於"-"是保留字,所以在前面要加\
    //C#.Net
    System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(@"[:|\-| ]");
    string datetime = "2009-01-02 03:04:05";
    datetime = reg.Replace(datetime, "");
    Console.WriteLine(datetime); //輸出20090102030405
    .Net的Regex位於System.Text.RegularExpressions之下

References:
Regular Expression (RegExp) in JavaScript 還可以直接測試
regular language 說明表格

星期二, 2月 17, 2009

當系統程式掛時 給於使用者提示

就在系統掛時 還可以給個提示...
說是windows有問題....不是我寫的程式掛了 哈

1.先catch exception
系統會掛 通常發生在exception發生了,但沒有catch到
所以可以用ThreadException來抓到沒有handle到的excpetion
Application.ThreadException += new ThreadExceptionEventHandler(HandleException);

而Application.ThreadException只能handle到主執行緒上的Exception
當有thread或某些情況下,這event就不會被觸發
所以得另外用AppDomain.CurrentDomain.UnhandledException
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(UnhandledException);

細節查關鍵字就可以找到了

2.Report Error


*註
UnhandledExceptionEvent在執行編譯過release下的exe才會抓到
UnhandledExceptionEventdebug的抓不到,而ThreadExceptionEvent好像debug模式下可以

Reference
C# Tutorial - Dealing With Unhandled Exceptions
如何在程序中友好提示錯誤

星期六, 2月 14, 2009

.Net Process相關應用

.net的Process
除了可以自己new起來外
還加參數
myProc.StartInfo.Arguments = "xx";

偵測Process結束事件
myProc.Exited += new EventHandler(myProcExit);

星期四, 2月 12, 2009

利用WM_DEVICECHANGE抓Port Name

除了用監聽Usb event外
還可利用WM_DEVICECHANGE來攔截相關訊息
由於網路上多是C/C++的實作
真不容易找到C#的 但又沒有完整的用C#查Port Name
在Reference[2]有相關的教學,但沒有查Port Name
就看了MSDN的說明,依樣畫葫蘆做出來了
Reference[2]裡有做了 Win32的class
[StructLayout(LayoutKind.Sequential)] public class DEV_BROADCAST_PORT {
public int dbcp_size;
public int dbcp_devicetype;
public int dbcp_reserved;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
public char[] dbcp_name;
}

然後在DBT_DEVICEARRIVAL裡,再改成用剛寫的StructLayout DEV_BROADCAST_PORT
if (m.WParam.ToInt32() == DBT_DEVICEARRIVAL)
{
Marshal.PtrToStructure(m.LParam, typeof(Win32.DEV_BROADCAST_HDR));
int dbccSize = Marshal.ReadInt32(m.LParam, 0);
int devType = Marshal.ReadInt32(m.LParam, 4);

if (devType == Win32.DBT_DEVTYP_PORT)
{
Win32.DEV_BROADCAST_PORT dip = (Win32.DEV_BROADCAST_PORT)
Marshal.PtrToStructure(m.LParam, typeof(Win32.DEV_BROADCAST_PORT));
string csTemp = "COM" + dip.dbcp_name[6].ToString(); //dbcp_name是一串字,在第6個是COM的Number
//MessageBox.Show(csTemp + " arrived/removed");
listBox1.Items.Add(csTemp + " arrived/removed");
}
}


Reference
1.MSDN WM_DEVICECHANGE Message MSDN的說明
2.Retrieving dbcc_name string from a DEV_BROADCAST_DEVICEINTERFACE structure 有VB及C#的實作

星期三, 2月 04, 2009

C#查詢Windows已安裝的軟體

找某軟體是否已安裝

  1. 先取得軟體安裝路徑
    可利用regedit.exe,到LocalMachine下的Software查軟體安裝註冊表
    比如說要查Prolific Technology INC 公司的 PL-2303 USB-to-Serial
    得知路徑為
    string path = "Prolific Technology INC\PL-2303 USB-to-Serial";
  2. 程式寫法
    程式的話,就可以透過Microsoft.Win32.Registry 達成
    比如說要查Prolific Technology INC 公司的 PL-2303 USB-to-Serial
    在程式註冊表中會在SOFTWARE資料夾中Prolific Technology下找到PL-2303 USB-to-Serial
    如果可以找到代表有安裝,所以程式可寫成
    regkey = Registry.LocalMachine.OpenSubKey("SOFTWARE", true).OpenSubKey(@"SOFTWARE下的路徑", true); 

以下為完整範例
//先引用Microsoft.Win32
using Microsoft.Win32;

public bool findSoftwareInstalled()
{
  try
  {                   
    //找PL-2303 USB-to-Serial 是否安裝
    string path = "Prolific Technology INC\PL-2303 USB-to-Serial";
    RegistryKey regkey = Registry.LocalMachine.OpenSubKey("SOFTWARE", true).OpenSubKey(@path , true);
    if (regkey == null)
    {
       //"註冊表內無儲存安裝訊息";
       return false;
    }
    else
    {
      //已安裝,可利用regkey.GetValue("xxx").ToString(); 取得相關資訊
      return true;
    }
  }
  catch (Exception ex)
  {                
    Console.WriteLine(ex.Message.ToString());
    return false;
   }
}

*Clickonce安裝位置
利用clickonce安裝的軟體不會在LocalMachine下的Software
而會是在CurrentUser的Microsoft\Windows\CurrentVersion\Uninstall下

星期三, 1月 21, 2009

ClickOnce 必要條件 - 從相同位置下載必要條件

搞死人了
怎麼樣都無法設定好
在老板的淫威逼迫下 總算把這搞定了

狀況
為了讓使用者不必透過網路下載「必要條件」
所以在ClickOnce「必要條件」設定「從應用程式的相同位置下載必要條件」
但都會發生類似以下令人抓狂的錯誤:
1.錯誤 無法發行,因為無法建置專案錯誤。
2.錯誤 必要條件的安裝位置沒有設定為「元件廠商的網站」,且磁碟上找不到項目 '.NET Framework 2.0' 中的檔案 'DotNetFX\instmsia.exe'。如需詳細資訊,請參閱 [說明]。
3. 錯誤 必要條件的安裝位置沒有設定為「元件廠商的網站」,且磁碟上找不到項目 '.NET Framework 2.0' 中的檔案 'DotNetFX\WindowsInstaller-KB893803-v2-x86.exe'。如需詳細資訊,請參閱 [說明]。
4.錯誤 必要條件的安裝位置沒有設定為「元件廠商的網站」,且磁碟上找不到項目 '.NET Framework 2.0' 中的檔案 'DotNetFX\dotnetfx.exe'。如需詳細資訊,請參閱 [說明]。
5.錯誤 必要條件的安裝位置沒有設定為「元件廠商的網站」,且磁碟上找不到項目 '.NET Framework 2.0' 中的檔案 'DotNetFX\langpack.exe'。如需詳細資訊,請參閱 [說明]。


問題點:需下載相關的檔案,並放到對的位置,問題就在這位置不知要放哪,且依SDK不同放的位置也不同,而且3.5還需設定xml檔


針對不同版本的Framework會有不同的解決方法
A.必要條件.Net Framework 2.0版
Step1 環境確認
IDE:C# 2008 Express

Step2 下載必要檔案
需要4個檔案,click鏈結可以直接下載檔案,如果鍵結斷了,可以直接search關鍵字
1.instmsia.exe
2.WindowsInstaller-KB893803-v2-x86.exe
3.dotnetfx.exe
4.langpack.exe

Step 3 放至指定資料夾
將全部的檔案丟到
C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\DotNetFX
在錯誤訊息中指出,這個資料夾缺了這四個,但即使將這四個檔放進這資料夾,還是會出現潮少langpack.exe,也就是說錯誤訊息剩下2個
1.錯誤 無法發行,因為無法建置專案錯誤。
2.錯誤 必要條件的安裝位置沒有設定為「元件廠商的網站」,且磁碟上找不到項目 '.NET Framework 2.0' 中的檔案 'DotNetFX\langpack.exe'。如需詳細資訊,請參閱 [說明]。

明明都寫這位置了,卻還是不行,看了一下該資料夾下還有個「zh-CHT」
就順手把 langpack.exe 丟進去,結果就成功了
大家試試吧

References:
VB2005 Express 部署問題
VS bootstrapper packages for .NET Framework 2.0 SP2 and 3.0 SP2 available for download

B.必要條件.Net Framework 3.5 SP2
照著網誌的做法就可以成功了
ClickOnce 發佈時,一起發佈 Framework 套件
ClickOnce 暨 Framework 3.5 發佈失敗的問題

星期日, 1月 18, 2009

如何維持.net程式單一執行個體應用程式

VB專案可以很開心的依以下路徑設定 就完成這限制
「專案=>屬性=>應用程式=>建立單一執行個體應用程式 」

不過其他的如C#等語言 就得自己寫程式
C#裡
/*
Code Snippet
Just add that piece of code (here in C#) in your main method (you need to
include the System.Diagnostic namespace) :
*/
Process currentProcess = Process.GetCurrentProcess();

Process [] allProcesses =
Process.GetProcessesByName(currentProcess.ProcessN ame);

if (allProcesses.Length > 1)
{
MessageBox.Show(currentProcess.ProcessName + " is already running !",
currentProcess.ProcessName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
//do your stuff here
}

VB
/*
Code Snippet
In the VB.NET application:
*/
Dim m As Mutex = _
New Mutex(False, "{11C92606-65D9-4df2-9AEA-B6A4DA91BCE2}")
If m.WaitOne(10, False) Then
Application.Run(New Form1())
m.ReleaseMutex()
Else
MessageBox.Show("Application already running!")
End If


Reference:
[VB 2005]如何避免程式(.exe)連開兩個以上

後記
除了維持單一執行應用程式外
應該不只是關閉新開的程式,而且要喚起即有的程式視窗
據說一般是利用hook達成... 等研究出來再補上

ClickOnce加入桌面Shortcut

ClickOnce本身沒支援
不過還是有人硬寫出來了

/// <summary>
/// This will create a Application Reference file on the users desktop
/// if they do not already have one when the program is loaded.
// If not debugging in visual studio check for Application Reference
// #if (!debug)
// CheckForShortcut();
// #endif
/// </summary>
void CheckForShortcut()
{
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
if (ad.IsFirstRun)
{
Assembly code = Assembly.GetExecutingAssembly();
string company = string.Empty;
string description = string.Empty;
if (Attribute.IsDefined(code, typeof(AssemblyCompanyAttribute)))
{
AssemblyCompanyAttribute ascompany = (AssemblyCompanyAttribute)Attribute.GetCustomAttribute(code,typeof(AssemblyCompanyAttribute));
company = ascompany.Company;

}
if (Attribute.IsDefined(code, typeof(AssemblyDescriptionAttribute)))
{
AssemblyDescriptionAttribute asdescription = (AssemblyDescriptionAttribute)Attribute.GetCustomAttribute(code, typeof(AssemblyDescriptionAttribute));
description = asdescription.Description;
}
if (company != string.Empty && description != string.Empty)
{
string desktopPath = string.Empty;
desktopPath = string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "\\", description, ".appref-ms");
string shortcutName = string.Empty;
shortcutName = string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.Programs), "\\", company, "\\", description, ".appref-ms");
System.IO.File.Copy(shortcutName, desktopPath, true);
}
}
}


remark
1.clickonce利用company name在「開始/程式集」中建立路徑,而description為「捷徑檔的名稱」
所以記得在clicknoce中設置company及description,否則上面的程式會找不到
2.另外clickonce的「發行/選項」的「產品名稱」及「應用程式/組件資訊」的「描述」,兩者要一致,不然會找不到
說明:
「發行/選項」的「產品名稱」是clickonce部署後,在程式集命名捷徑的命稱
「應用程式/組件資訊」的「描述」是上述程式asdescription.Description所取得的,所以這一項要跟產品名稱相同,才找的到clickonce設的捷徑

References:
How to add Desktop Shortcut to ClickOnce Deployment Application