C#能写COM组件吗? 新手问一下,C#能写COM组件吗,我看了一下没找到。用VC++写COM太麻烦,而且他自动生成的代码有的还有错误,很不好用。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 可以,以下是转贴:用C#寫COM組件步驟一:建立“windows控制項程式庫”工程,如圖: jiangligongcheng.bmp 步驟二:在我們這個例子中用不到帶界面的com控件所以我們將界面的size屬性設置為 0, 0我們要用C#寫COM組件必須要實現 public interface IObjectSafety接口因為這是。IObjectSafety接口,把ActiveX控件标记为安全的ActiveX控件。每個接口需要一個GUID特性。要生成變個唯一的Guid,需要運行guidgen.exe工具軟體,要選擇第四項“Registry Format” 如圖:guidgen.bmp我們還有定義一個接口如下[Guid("1B1DFAE7-FC2E-4f05-BC5A-5267408EF2A9")] public interface IOLpt1 { [DispId(1)] bool WriteCommand(string com,string flag); [DispId(2)] void WhenLoad(); }功能是提供一個其他語言利用我們所寫的方法的接口。如果不用接口的話其他語言將無法使用我們在程序裡面定義的方法(我在其他的地方也看到過不用接口的例子,不知道為什麼,在我的電腦上如果不用接口編譯隻後將看不到我定義的方法)。這個接口定義了兩個方法分別是 bool WriteCommand(string com,string flag); 和 void WhenLoad();第一個方法是將命令寫入到並口,第二個方法是當控件啟動的時候讀取Access的命令的內碼並存如到數組中。這裡我們隻介紹如何寫COM組件,其他的將不涉及。定義類 UserControl1 繼承 System.Windows.Forms.UserControl 實現接口IOLpt1於IObjectSafety [Guid("AC8C1E64-B501-4f8b-A026-B4F1D8EF7DF2")] [ ClassInterfaceAttribute(ClassInterfaceType.AutoDual) ] public class UserControl1 : System.Windows.Forms.UserControl,IOLpt1,IObjectSafety步驟三我們還要給我們的控件一個強名。強名需要用sn.exe來得到 命令格式sn -k myKey.snk 將得到的強名文件myKey.snk復制到你的工程的目錄下,並在我們的工程文件 AssemblyInfo.cs裡面的[assembly: AssemblyKeyFile("")]項中加入你的強名的絕對路徑F:\webpriteCon\PrintExe\mykey.snk例如:[assembly: AssemblyKeyFile("F:\\webpriteCon\\PrintExe\\mykey.snk")]步驟四如圖:shuxing 將建置項裡面的「注冊COM組件Interop」項設置為true然後編譯隻後就可以注冊到其他的機器讓別的語言進行引用了。下面是詳細代碼。我將陸續寫出如何將COM組件發布成ActiveX控件。using System;using System.Collections;using System.ComponentModel;using System.Drawing;using System.Data;using System.Windows.Forms;using System.Runtime.InteropServices;using System.Data.OleDb;namespace PrintExe{ /*必須要實現IObjectSafety接口, * 把ActiveX控件標記為安全的ActiveX控件。 * IObjectSafety 的實現方式如下 */ [Guid("10615515-3979-4f87-A0C9-F786F050AE8B"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IObjectSafety { // methods [DispId(1)] void GetInterfacceSafyOptions( System.Int32 riid, out System.Int32 pdwSupportedOptions, out System.Int32 pdwEnabledOptions); [DispId(2)] void SetInterfaceSafetyOptions( System.Int32 riid, System.Int32 dwOptionsSetMask, System.Int32 dwEnabledOptions); } [Guid("1B1DFAE7-FC2E-4f05-BC5A-5267408EF2A9")] public interface IOLpt1 { [DispId(1)] bool WriteCommand(string com,string flag); [DispId(2)] void WhenLoad(); } [Guid("AC8C1E64-B501-4f8b-A026-B4F1D8EF7DF2")] [ ClassInterfaceAttribute(ClassInterfaceType.AutoDual) ] public class UserControl1 : System.Windows.Forms.UserControl,IOLpt1,IObjectSafety { string sqlStr; static string connStr = @"Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Registry Path=;Jet OLEDB:Database Locking Mode=1;Data Source='C:\\printTypeDB.mdb';Mode=Share Deny None;Jet OLEDB:Engine Type=5;Provider='Microsoft.Jet.OLEDB.4.0';Jet OLEDB:System database=;Jet OLEDB:SFP=False;persist security info=False;Extended Properties=;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Create System Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;User ID=Admin;Jet OLEDB:Global Bulk Transactions=1"; OleDbConnection myConn = new OleDbConnection(connStr); OleDbCommand myComm; OleDbDataReader myDr; public string comlist=""; string[,] myArray; private System.ComponentModel.Container components = null; public UserControl1() { InitializeComponent(); } protected override void Dispose( bool disposing ) { if( disposing ) { if( components != null ) components.Dispose(); } base.Dispose( disposing ); } #region 元件設計工具產生的程式碼 /// <summary> /// 此為設計工具支援所必須的方法 - 請勿使用程式碼編輯器修改 /// 這個方法的內容。 /// </summary> private void InitializeComponent() { // // UserControl1 // this.Name = "UserControl1"; this.Size = new System.Drawing.Size(0, 0); } #endregion #region IOLpt1 成員 public bool WriteCommand(string com,string flag) { //MessageBox.Show("WriteCommand方法已經運行","Error"); //com為指令碼 str為要列印字符串 ExeFunction ef = new ExeFunction(); string[] str = com.Split(new Char[]{'~'}); //開始將textBox中的外碼取出找到數組中對應的指令碼組成完整的指令 string Instruction = ""; string outI = str[0].Trim(); if(outI!="SET") { for(int i = 0;i<myArray.Length/5;i++) { if(myArray[i,0].Trim() == outI) { char temp1 = Convert.ToChar(Convert.ToInt32(myArray[i,1].Trim())); char temp2='1'; Instruction = temp1.ToString(); if(myArray[i,2].Trim() != "") { temp2 = Convert.ToChar(Convert.ToInt32(myArray[i,2].Trim())); Instruction += temp1.ToString(); } if(myArray[i,3].Trim() != "") Instruction += myArray[i,3].Trim(); Instruction += str[1] + Convert.ToChar(Convert.ToInt32(myArray[i,4].Trim())); comlist += Instruction + "~"; if(flag == "0") //則將指令預存起來 return true; //MessageBox.Show("方法已經運行完畢","Error"); } } if(comlist!="") { string[] str1 = comlist.Split(new Char[]{'~'}); comlist=""; for(int j=0;j<str1.Length-1;j++) { byte[] buffer = System.Text.Encoding.Default.GetBytes(str1[j]); ef.StartP(buffer); } } }else if(outI == "SET") //如果為SET則為設置本機收銀機 { sqlStr = "update printTypeSet set Flag = false"; myComm = new OleDbCommand(sqlStr,myConn); myConn.Open(); myDr = myComm.ExecuteReader(); myDr.Close(); sqlStr = "update printTypeSet set Flag = true where PrintType='" + str[1].Trim() + "'"; myComm = new OleDbCommand(sqlStr,myConn); int i = myComm.ExecuteNonQuery(); myDr.Close(); myConn.Close(); if(i>0) MessageBox.Show("設定成功!","OK"); else MessageBox.Show("沒有合適的型號!","OK"); } return true; } public void WhenLoad() { //MessageBox.Show("WhenLoad方法已經運行","Error"); int i = 0; //先取得資料的行數 //將資料取出放入到數組裡面 try { sqlStr = "SELECT count(*) FROM printTypeSet WHERE Flag = true"; myComm = new OleDbCommand(sqlStr,myConn); myConn.Open(); myDr = myComm.ExecuteReader(); if(myDr.HasRows) { while(myDr.Read()) { i = (int)myDr[0]; } } myDr.Close(); myArray = new string[i,5]; sqlStr = "SELECT Instruction,FirstI,SecondI,Parameter,EndI FROM printTypeSet WHERE Flag = true"; myComm = new OleDbCommand(sqlStr,myConn); myDr = myComm.ExecuteReader(); i = 0; if(myDr.HasRows) { while(myDr.Read()) { myArray[i,0] = myDr[0].ToString(); myArray[i,1] = myDr[1].ToString(); myArray[i,2] = myDr[2].ToString(); myArray[i,3] = myDr[3].ToString(); myArray[i,4] = myDr[4].ToString(); i++; } } myDr.Close(); } catch(Exception ex) { MessageBox.Show("WhenLoad方法運行錯誤" + ex.ToString(),"Error"); } finally { myConn.Close(); //MessageBox.Show("方法已經運行完畢","Error"); } } #endregion #region IObjectSafety 成員 public void GetInterfacceSafyOptions(Int32 riid, out Int32 pdwSupportedOptions, out Int32 pdwEnabledOptions) { // TODO: 加入 UserControl1.GetInterfacceSafyOptions 實作 pdwSupportedOptions = new Int32 (); pdwEnabledOptions = new Int32 (); } public void SetInterfaceSafetyOptions(Int32 riid, Int32 dwOptionsSetMask, Int32 dwEnabledOptions) { // TODO: 加入 UserControl1.SetInterfaceSafetyOptions 實作 } #endregion }} 简单的做法就是:按照上面说的建个DLL工程,写个接口和具体实现类,给他们一个GUID,并签名DLL就如--从COM组件调用.NET组件编程实战 上所说的.然后1.生成类型库;2.注册类型库;3.安装到GAC;就如--如何创建COM组件能够调用的.NET装配件上所说的. http://www.csdn.net/develop/Read_Article.asp?id=23438 求助编程创建ODBC数据源问题 如何在Page_Load里用JS实现页面跳转 请教一个问题,判断最相似数字 一个连接数据库时的问题 跪求!!! C#和别的C有什么区别? 请问asp中的response.end在asp.net中怎么用 各位大侠,快帮忙!!!急!!! 寻找高手 修改记录的问题,急! C#怎样从文本中读取中文并显示在文本框中 有什么方法,可以用程序把数据库备份到本地,网上的资料好象都是备份到服务器的路径的??? winfrom下水晶报表的问题,帮帮忙呀!!!!!!!!!
建立“windows控制項程式庫”工程,如圖: jiangligongcheng.bmp
步驟二:
在我們這個例子中用不到帶界面的com控件所以我們將界面的size屬性設置為 0, 0
我們要用C#寫COM組件必須要實現 public interface IObjectSafety接口因為這是。IObjectSafety接口,把ActiveX控件标记为安全的ActiveX控件。每個接口需要一個GUID特性。要生成變個唯一的Guid,需要運行guidgen.exe工具軟體,要選擇第四項“Registry Format” 如圖:guidgen.bmp
我們還有定義一個接口如下
[Guid("1B1DFAE7-FC2E-4f05-BC5A-5267408EF2A9")]
public interface IOLpt1
{
[DispId(1)] bool WriteCommand(string com,string flag);
[DispId(2)] void WhenLoad();
}
功能是提供一個其他語言利用我們所寫的方法的接口。如果不用接口的話其他語言將無法使用我們在程序裡面定義的方法(我在其他的地方也看到過不用接口的例子,不知道為什麼,在我的電腦上如果不用接口編譯隻後將看不到我定義的方法)。這個接口定義了兩個方法分別是 bool WriteCommand(string com,string flag); 和 void WhenLoad();
第一個方法是將命令寫入到並口,第二個方法是當控件啟動的時候讀取Access的命令的內碼並存如到數組中。這裡我們隻介紹如何寫COM組件,其他的將不涉及。
定義類 UserControl1 繼承 System.Windows.Forms.UserControl 實現接口IOLpt1於IObjectSafety [Guid("AC8C1E64-B501-4f8b-A026-B4F1D8EF7DF2")]
[ ClassInterfaceAttribute(ClassInterfaceType.AutoDual) ]
public class UserControl1 : System.Windows.Forms.UserControl,IOLpt1,IObjectSafety
步驟三
我們還要給我們的控件一個強名。強名需要用sn.exe來得到 命令格式
sn -k myKey.snk 將得到的強名文件myKey.snk復制到你的工程的目錄下,並在我們的工程文件 AssemblyInfo.cs裡面的[assembly: AssemblyKeyFile("")]項中加入你的強名的絕對路徑F:\webpriteCon\PrintExe\mykey.snk
例如:[assembly: AssemblyKeyFile("F:\\webpriteCon\\PrintExe\\mykey.snk")]
步驟四
如圖:shuxing
將建置項裡面的「注冊COM組件Interop」項設置為true然後編譯隻後就可以注冊到其他的機器讓別的語言進行引用了。
下面是詳細代碼。
我將陸續寫出如何將COM組件發布成ActiveX控件。using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Data.OleDb;namespace PrintExe
{
/*必須要實現IObjectSafety接口,
* 把ActiveX控件標記為安全的ActiveX控件。
* IObjectSafety 的實現方式如下
*/
[Guid("10615515-3979-4f87-A0C9-F786F050AE8B"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
// methods
[DispId(1)] void GetInterfacceSafyOptions(
System.Int32 riid,
out System.Int32 pdwSupportedOptions,
out System.Int32 pdwEnabledOptions);
[DispId(2)] void SetInterfaceSafetyOptions(
System.Int32 riid,
System.Int32 dwOptionsSetMask,
System.Int32 dwEnabledOptions);
}
[Guid("1B1DFAE7-FC2E-4f05-BC5A-5267408EF2A9")]
public interface IOLpt1
{ [DispId(1)] bool WriteCommand(string com,string flag);
[DispId(2)] void WhenLoad();
} [Guid("AC8C1E64-B501-4f8b-A026-B4F1D8EF7DF2")]
[ ClassInterfaceAttribute(ClassInterfaceType.AutoDual) ]
public class UserControl1 : System.Windows.Forms.UserControl,IOLpt1,IObjectSafety
{
string sqlStr;
static string connStr = @"Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Registry Path=;Jet OLEDB:Database Locking Mode=1;Data Source='C:\\printTypeDB.mdb';Mode=Share Deny None;Jet OLEDB:Engine Type=5;Provider='Microsoft.Jet.OLEDB.4.0';Jet OLEDB:System database=;Jet OLEDB:SFP=False;persist security info=False;Extended Properties=;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Create System Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;User ID=Admin;Jet OLEDB:Global Bulk Transactions=1"; OleDbConnection myConn = new OleDbConnection(connStr);
OleDbCommand myComm;
OleDbDataReader myDr;
public string comlist="";
string[,] myArray; private System.ComponentModel.Container components = null; public UserControl1()
{
InitializeComponent();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if( components != null )
components.Dispose();
}
base.Dispose( disposing );
} #region 元件設計工具產生的程式碼
/// <summary>
/// 此為設計工具支援所必須的方法 - 請勿使用程式碼編輯器修改
/// 這個方法的內容。
/// </summary>
private void InitializeComponent()
{
//
// UserControl1
//
this.Name = "UserControl1";
this.Size = new System.Drawing.Size(0, 0); }
#endregion
{
//MessageBox.Show("WriteCommand方法已經運行","Error");
//com為指令碼 str為要列印字符串
ExeFunction ef = new ExeFunction();
string[] str = com.Split(new Char[]{'~'});
//開始將textBox中的外碼取出找到數組中對應的指令碼組成完整的指令
string Instruction = "";
string outI = str[0].Trim();
if(outI!="SET")
{
for(int i = 0;i<myArray.Length/5;i++)
{
if(myArray[i,0].Trim() == outI)
{
char temp1 = Convert.ToChar(Convert.ToInt32(myArray[i,1].Trim()));
char temp2='1'; Instruction = temp1.ToString(); if(myArray[i,2].Trim() != "")
{
temp2 = Convert.ToChar(Convert.ToInt32(myArray[i,2].Trim()));
Instruction += temp1.ToString();
} if(myArray[i,3].Trim() != "")
Instruction += myArray[i,3].Trim();
Instruction += str[1] + Convert.ToChar(Convert.ToInt32(myArray[i,4].Trim()));
comlist += Instruction + "~";
if(flag == "0") //則將指令預存起來
return true;
//MessageBox.Show("方法已經運行完畢","Error");
}
}
if(comlist!="")
{
string[] str1 = comlist.Split(new Char[]{'~'});
comlist="";
for(int j=0;j<str1.Length-1;j++)
{
byte[] buffer = System.Text.Encoding.Default.GetBytes(str1[j]);
ef.StartP(buffer);
}
}
}else if(outI == "SET") //如果為SET則為設置本機收銀機
{
sqlStr = "update printTypeSet set Flag = false";
myComm = new OleDbCommand(sqlStr,myConn);
myConn.Open();
myDr = myComm.ExecuteReader();
myDr.Close();
sqlStr = "update printTypeSet set Flag = true where PrintType='" + str[1].Trim() + "'";
myComm = new OleDbCommand(sqlStr,myConn);
int i = myComm.ExecuteNonQuery();
myDr.Close();
myConn.Close();
if(i>0)
MessageBox.Show("設定成功!","OK");
else
MessageBox.Show("沒有合適的型號!","OK");
}
return true;
} public void WhenLoad()
{
//MessageBox.Show("WhenLoad方法已經運行","Error");
int i = 0;
//先取得資料的行數
//將資料取出放入到數組裡面
try
{
sqlStr = "SELECT count(*) FROM printTypeSet WHERE Flag = true";
myComm = new OleDbCommand(sqlStr,myConn);
myConn.Open();
myDr = myComm.ExecuteReader();
if(myDr.HasRows)
{
while(myDr.Read())
{
i = (int)myDr[0];
}
}
myDr.Close();
myArray = new string[i,5];
sqlStr = "SELECT Instruction,FirstI,SecondI,Parameter,EndI FROM printTypeSet WHERE Flag = true";
myComm = new OleDbCommand(sqlStr,myConn);
myDr = myComm.ExecuteReader();
i = 0;
if(myDr.HasRows)
{
while(myDr.Read())
{
myArray[i,0] = myDr[0].ToString();
myArray[i,1] = myDr[1].ToString();
myArray[i,2] = myDr[2].ToString();
myArray[i,3] = myDr[3].ToString();
myArray[i,4] = myDr[4].ToString();
i++;
}
}
myDr.Close();
}
catch(Exception ex)
{
MessageBox.Show("WhenLoad方法運行錯誤" + ex.ToString(),"Error");
}
finally
{
myConn.Close();
//MessageBox.Show("方法已經運行完畢","Error");
}
} #endregion #region IObjectSafety 成員 public void GetInterfacceSafyOptions(Int32 riid, out Int32 pdwSupportedOptions, out Int32 pdwEnabledOptions)
{
// TODO: 加入 UserControl1.GetInterfacceSafyOptions 實作
pdwSupportedOptions = new Int32 ();
pdwEnabledOptions = new Int32 ();
} public void SetInterfaceSafetyOptions(Int32 riid, Int32 dwOptionsSetMask, Int32 dwEnabledOptions)
{
// TODO: 加入 UserControl1.SetInterfaceSafetyOptions 實作
} #endregion
}
}
就如--从COM组件调用.NET组件编程实战 上所说的.然后1.生成类型库;2.注册类型库;3.安装到GAC;就如--如何创建COM组件能够调用的.NET装配件上所说的.