<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>.NET(COM+元件)</title><link>http://blog.blueshop.com.tw/topcat/category/716.aspx</link><description>使用.NET開發COM+元件技術分享</description><managingEditor>topcat</managingEditor><dc:language>zh-TW</dc:language><generator>.Text Version 0.95.2004.101</generator><item><dc:creator>topcat</dc:creator><title>ObjectDataSouce結合物件設計方式</title><link>http://blog.blueshop.com.tw/topcat/archive/2008/06/21/55380.aspx</link><pubDate>Sat, 21 Jun 2008 00:30:00 GMT</pubDate><guid>http://blog.blueshop.com.tw/topcat/archive/2008/06/21/55380.aspx</guid><wfw:comment>http://blog.blueshop.com.tw/topcat/comments/55380.aspx</wfw:comment><comments>http://blog.blueshop.com.tw/topcat/archive/2008/06/21/55380.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blog.blueshop.com.tw/topcat/comments/commentRss/55380.aspx</wfw:commentRss><trackback:ping>http://blog.blueshop.com.tw/topcat/services/trackbacks/55380.aspx</trackback:ping><description>&lt;p&gt;小喵以前撰寫ObjectDataSouce都是透過DataSet,DataTable,DataReader的方式傳回值，而要進行維護的動作，也是一個一個的參數慢慢傳遞，後來小喵看到Jeff大大的這篇文章【&lt;a href="http://www.dotblogs.com.tw/jeff377/archive/2008/06/06/4245.aspx"&gt;ObjectDataSoruce 繫結 BusinessObject 控制項&lt;/a&gt;】，原來可以用物件的方式來傳遞，於是小喵今天開始著手看看是否能夠改用物件的方式處理。&lt;/p&gt;&lt;p&gt;首先小喵先設計一個測試的資料表，資料表(Employees)欄位如下圖&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=ODS001_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="120" alt="ODS001" width="476" border="0" src="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=ODS001_thumb.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;接著就針對這個資料表，建立一個Employee的類別，未來這個物件類別可以抽出來當作是商業邏輯層或者資料層的元件，並撰寫相關的新增、修改、刪除、查詢等功能，相關程式碼如下：&lt;/p&gt;&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:2dc9c5eb-a8ee-4ac6-9954-9964d5ff2b69" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre class="vb" name="code"&gt;
Imports System.Data
Imports System.Data.SqlClient
Imports Microsoft.VisualBasic

Public Class ObjEmployee
    
    ''' &amp;lt;summary&amp;gt;
    ''' 員工編號欄位
    ''' &amp;lt;/summary&amp;gt;
    Private m_EmployeeID As Integer
    ''' &amp;lt;summary&amp;gt;
    ''' 員工姓名欄位
    ''' &amp;lt;/summary&amp;gt;
    Private m_EmpName As String
    ''' &amp;lt;summary&amp;gt;
    ''' 員工電話欄位
    ''' &amp;lt;/summary&amp;gt;
    Private m_EmpTel As String

    Private oConns As New objConnS
    Private ConnStr As String = oConns.ConnStr

    ''' &amp;lt;summary&amp;gt;
    ''' 員工編號屬性
    ''' &amp;lt;/summary&amp;gt;
    Public Property EmployeeID() As Integer
        Get
            Return m_EmployeeID
        End Get
        Set(ByVal value As Integer)
            m_EmployeeID = value
        End Set
    End Property

    ''' &amp;lt;summary&amp;gt;
    ''' 員工姓名屬性
    ''' &amp;lt;/summary&amp;gt;
    Public Property EmpName() As String
        Get
            Return m_EmpName
        End Get
        Set(ByVal value As String)
            m_EmpName = value
        End Set
    End Property

    ''' &amp;lt;summary&amp;gt;
    ''' 員工電話屬性
    ''' &amp;lt;/summary&amp;gt;
    Public Property EmpTel() As String
        Get
            Return m_EmpTel
        End Get
        Set(ByVal value As String)
            m_EmpTel = value
        End Set
    End Property

    '建構函數
    Public Sub New()

    End Sub

    Public Sub New(ByVal myEmpID As Integer)
        GetEmp(myEmpID)
    End Sub

    Private Sub GetEmp(ByVal myEmpID As Integer)
        Try
            Using Conn As New SqlConnection(ConnStr)
                Conn.Open()
                Dim SqlTxt As String = &amp;quot;&amp;quot;
                SqlTxt += &amp;quot; SELECT * &amp;quot;
                SqlTxt += &amp;quot; FROM Employees &amp;quot;
                SqlTxt += &amp;quot; WHERE EmployeeID = @EmployeeID &amp;quot;
                Dim Cmmd As New SqlCommand(SqlTxt, Conn)
                Cmmd.Parameters.AddWithValue(&amp;quot;@EmployeeID&amp;quot;, myEmpID)
                Dim dr As SqlDataReader = Cmmd.ExecuteReader
                If dr.HasRows Then
                    While dr.Read
                        m_EmployeeID = myEmpID
                        m_EmpName = dr.Item(&amp;quot;EmpName&amp;quot;)
                        m_EmpTel = dr.Item(&amp;quot;EmpTel&amp;quot;)
                    End While
                End If
                dr.Close()
            End Using

        Catch ex As Exception
            Throw New Exception(ex.Message)
        End Try
    End Sub

    ''' &amp;lt;summary&amp;gt;
    ''' 新增一筆Employee
    ''' &amp;lt;/summary&amp;gt;
    Public Sub Add()
        Try
            Using Conn As New SqlConnection(ConnStr)
                Conn.Open()
                Dim SqlTxt As String = &amp;quot;&amp;quot;
                SqlTxt += &amp;quot; INSERT INTO Employees &amp;quot;
                SqlTxt += &amp;quot;     (EmpName, EmpTel) &amp;quot;
                SqlTxt += &amp;quot; VALUES (@EmpName, @EmpTel) &amp;quot;
                SqlTxt += &amp;quot;  &amp;quot;
                Dim Cmmd As New SqlCommand(SqlTxt, Conn)
                Cmmd.Parameters.AddWithValue(&amp;quot;@EmpName&amp;quot;, m_EmpName)
                Cmmd.Parameters.AddWithValue(&amp;quot;@EmpTel&amp;quot;, m_EmpTel)

                Cmmd.ExecuteNonQuery()
            End Using
        Catch ex As Exception
            Throw New Exception(ex.Message)

        End Try
    End Sub

    ''' &amp;lt;summary&amp;gt;
    ''' 刪除一筆Employee
    ''' &amp;lt;/summary&amp;gt;
    Public Sub Del()
        Try
            Using Conn As New SqlConnection(ConnStr)
                Conn.Open()
                Dim SqlTxt As String = &amp;quot;&amp;quot;
                SqlTxt += &amp;quot; Delete Employees &amp;quot;
                SqlTxt += &amp;quot; WHERE EmployeeID=@EmployeeID &amp;quot;
                SqlTxt += &amp;quot;  &amp;quot;
                Dim Cmmd As New SqlCommand(SqlTxt, Conn)
                Cmmd.Parameters.AddWithValue(&amp;quot;@EmployeeID&amp;quot;, m_EmployeeID)

                Cmmd.ExecuteNonQuery()
            End Using
        Catch ex As Exception
            Throw New Exception(ex.Message)

        End Try

    End Sub

    ''' &amp;lt;summary&amp;gt;
    ''' 修改單筆Employee
    ''' &amp;lt;/summary&amp;gt;
    Public Sub Update()
        Try
            Using Conn As New SqlConnection(ConnStr)
                Conn.Open()
                Dim SqlTxt As String = &amp;quot;&amp;quot;
                SqlTxt += &amp;quot; UPDATE Employees &amp;quot;
                SqlTxt += &amp;quot; SET EmpName=@EmpName) &amp;quot;
                SqlTxt += &amp;quot;     , EmpTel=@EmpTel  &amp;quot;
                SqlTxt += &amp;quot; WHERE EmployeeID=@EmployeeID &amp;quot;
                SqlTxt += &amp;quot;  &amp;quot;
                Dim Cmmd As New SqlCommand(SqlTxt, Conn)
                Cmmd.Parameters.AddWithValue(&amp;quot;@EmployeeID&amp;quot;, m_EmployeeID)
                Cmmd.Parameters.AddWithValue(&amp;quot;@EmpName&amp;quot;, m_EmpName)
                Cmmd.Parameters.AddWithValue(&amp;quot;@EmpTel&amp;quot;, m_EmpTel)

                Cmmd.ExecuteNonQuery()
            End Using
        Catch ex As Exception
            Throw New Exception(ex.Message)

        End Try

    End Sub
End Class
&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;另外為了方便處理Connection String，也寫了個小類別來存放&lt;/p&gt;&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:9bca419d-3c37-4c27-9f86-abef8b7d1adc" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre class="vb" name="code"&gt;
Imports Microsoft.VisualBasic

Public Class objConnS
    Private m_ConnStr As String = &amp;quot;Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\MyDB.mdf;Integrated Security=True;User Instance=True&amp;quot;

    Public ReadOnly Property ConnStr() As String
        Get
            Return m_ConnStr
        End Get
    End Property

End Class
&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再來設計一個配合ObjectDataSouce的物件，進行新增、修改、刪除、查詢的動作&lt;/p&gt;&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:a9bc3adb-ae9f-44df-97d5-c8a34dbde1a8" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre class="vb" name="code"&gt;
Imports System.Data
Imports System.Data.SqlClient
Imports Microsoft.VisualBasic

Public Class daoEmployee
    Private oConnS As New objConnS
    Private ConnStr As String = oConnS.ConnStr

    Public Function GetAllEmployee() As List(Of ObjEmployee)
        Try
            Dim tEmps As New List(Of ObjEmployee)
            tEmps.Clear()
            Using Conn As New SqlConnection(ConnStr)
                Conn.Open()
                Dim SqlTxt As String = &amp;quot;&amp;quot;
                SqlTxt += &amp;quot; SELECT * &amp;quot;
                SqlTxt += &amp;quot; FROM Employees &amp;quot;
                Dim Cmmd As New SqlCommand(SqlTxt, Conn)
                Dim Dr As SqlDataReader = Cmmd.ExecuteReader
                If Dr.HasRows Then
                    Dim tEmp As ObjEmployee
                    While Dr.Read
                        tEmp = New ObjEmployee(Dr.Item(&amp;quot;EmployeeID&amp;quot;))
                        tEmps.Add(tEmp)
                    End While
                End If
            End Using
            Return tEmps

        Catch ex As Exception
            Throw
        End Try
    End Function

    Public Sub EmpUpdate(ByVal oEmp As ObjEmployee)
        Try
            oEmp.Update()
        Catch ex As Exception
            Throw
        End Try
    End Sub

    Public Sub EmpDel(ByVal oEmp As ObjEmployee)
        Try
            oEmp.Del()
        Catch ex As Exception
            Throw
        End Try
    End Sub

    Public Sub EmpAddNew(ByVal oEmp As ObjEmployee)
        Try
            oEmp.Add()
        Catch ex As Exception
            Throw
        End Try
    End Sub

End Class
&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="color: #0000ff"&gt;有趣的地方有看到嗎，GetAllEmployee傳回的不再是DataSet,DataTable,DataRead，而是&lt;b&gt;&lt;span style="color: #ff0000"&gt;objEmployee的物件集合&lt;/span&gt;&lt;/b&gt;，另外，新增修改刪除的程式碼&lt;span style="color: #ff0000"&gt;精減&lt;/span&gt;到一個不行。傳遞的參數沒有其他的，就是物件，而運作的，就是物件提供的新增修改刪除。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;接著設計一下測試的畫面&lt;/p&gt;&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:48ab3e91-0cf7-43f9-9303-252ee09f817b" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre class="xml" name="code"&gt;
        &amp;lt;asp:GridView ID=&amp;quot;gvEmployees&amp;quot; runat=&amp;quot;server&amp;quot; AutoGenerateColumns=&amp;quot;False&amp;quot; 
            DataSourceID=&amp;quot;odsEmployees&amp;quot; DataKeyNames=&amp;quot;EmployeeID&amp;quot;&amp;gt;
            &amp;lt;Columns&amp;gt;
                &amp;lt;asp:CommandField ShowDeleteButton=&amp;quot;True&amp;quot; ShowEditButton=&amp;quot;True&amp;quot; /&amp;gt;
                &amp;lt;asp:BoundField DataField=&amp;quot;EmployeeID&amp;quot; HeaderText=&amp;quot;EmployeeID&amp;quot; 
                    SortExpression=&amp;quot;EmployeeID&amp;quot; /&amp;gt;
                &amp;lt;asp:BoundField DataField=&amp;quot;EmpName&amp;quot; HeaderText=&amp;quot;EmpName&amp;quot; 
                    SortExpression=&amp;quot;EmpName&amp;quot; /&amp;gt;
                &amp;lt;asp:BoundField DataField=&amp;quot;EmpTel&amp;quot; HeaderText=&amp;quot;EmpTel&amp;quot; 
                    SortExpression=&amp;quot;EmpTel&amp;quot; /&amp;gt;
            &amp;lt;/Columns&amp;gt;
        &amp;lt;/asp:GridView&amp;gt;
        &amp;lt;asp:ObjectDataSource ID=&amp;quot;odsEmployees&amp;quot; runat=&amp;quot;server&amp;quot; 
            DataObjectTypeName=&amp;quot;ObjEmployee&amp;quot; DeleteMethod=&amp;quot;EmpDel&amp;quot; 
            SelectMethod=&amp;quot;GetAllEmployee&amp;quot; TypeName=&amp;quot;daoEmployee&amp;quot; 
            UpdateMethod=&amp;quot;EmpUpdate&amp;quot; InsertMethod=&amp;quot;EmpAddNew&amp;quot;&amp;gt;
        &amp;lt;/asp:ObjectDataSource&amp;gt;
        &amp;lt;asp:DetailsView ID=&amp;quot;dvEmployee&amp;quot; runat=&amp;quot;server&amp;quot; AutoGenerateRows=&amp;quot;False&amp;quot; 
            DataSourceID=&amp;quot;odsEmployees&amp;quot; DefaultMode=&amp;quot;Insert&amp;quot; Height=&amp;quot;50px&amp;quot; 
            Width=&amp;quot;125px&amp;quot; DataKeyNames=&amp;quot;EmployeeID&amp;quot;&amp;gt;
            &amp;lt;Fields&amp;gt;
                &amp;lt;asp:BoundField DataField=&amp;quot;EmployeeID&amp;quot; HeaderText=&amp;quot;EmployeeID&amp;quot; 
                    InsertVisible=&amp;quot;False&amp;quot; SortExpression=&amp;quot;EmployeeID&amp;quot; /&amp;gt;
                &amp;lt;asp:BoundField DataField=&amp;quot;EmpName&amp;quot; HeaderText=&amp;quot;EmpName&amp;quot; 
                    SortExpression=&amp;quot;EmpName&amp;quot; /&amp;gt;
                &amp;lt;asp:BoundField DataField=&amp;quot;EmpTel&amp;quot; HeaderText=&amp;quot;EmpTel&amp;quot; 
                    SortExpression=&amp;quot;EmpTel&amp;quot; /&amp;gt;
                &amp;lt;asp:CommandField ShowInsertButton=&amp;quot;True&amp;quot; /&amp;gt;
            &amp;lt;/Fields&amp;gt;
        &amp;lt;/asp:DetailsView&amp;gt;
        &amp;lt;br /&amp;gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;唯一畫面要寫的程式是，在DetailView的資料新增之後，要讓GridView重新整理一次&lt;/p&gt;&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b0644830-086f-409e-8ff7-12dfba02ef7e" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre class="vb" name="code"&gt;
    Protected Sub dvEmployee_ItemInserted(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewInsertedEventArgs) Handles dvEmployee.ItemInserted
        Me.gvEmployees.DataBind()
    End Sub&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;這樣就能夠使用物件的方式來處理並且方便把物件抽離出去，並且不用寫ObjectDataSouce的搭配物件時，需要撰寫一堆傳遞的參數。&lt;/p&gt;&lt;img src ="http://blog.blueshop.com.tw/topcat/aggbug/55380.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>topcat</dc:creator><title>註冊ICSharpCode.SharpZipLib.dll到作業系統中讓ASP可以透過COM+可呼叫</title><link>http://blog.blueshop.com.tw/topcat/archive/2008/02/26/54401.aspx</link><pubDate>Tue, 26 Feb 2008 11:25:00 GMT</pubDate><guid>http://blog.blueshop.com.tw/topcat/archive/2008/02/26/54401.aspx</guid><wfw:comment>http://blog.blueshop.com.tw/topcat/comments/54401.aspx</wfw:comment><comments>http://blog.blueshop.com.tw/topcat/archive/2008/02/26/54401.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blog.blueshop.com.tw/topcat/comments/commentRss/54401.aspx</wfw:commentRss><trackback:ping>http://blog.blueshop.com.tw/topcat/services/trackbacks/54401.aspx</trackback:ping><description>&lt;P&gt;在之前的一篇&lt;A href="http://blog.blueshop.com.tw/topcat/archive/2008/02/04/54267.aspx" target=_blank&gt;使用自訂的類別透過SharpZip執行Zip壓縮、解壓縮(VB.NET)&lt;/A&gt; 小喵用一個類別把SharpZip做了一個包裝，讓使用上能夠更直觀。小喵心想如果能夠再把他寫成COM+元件的話，那麼就能夠讓ASP或者VB呼叫使用，可用範圍更擴大。&lt;/P&gt;
&lt;P&gt;轉成COM+的元件需要一些額外的設定，這與一般COM+元件的寫法是一樣的，有需要的請參考這篇：&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blog.blueshop.com.tw/topcat/archive/2006/08/09/35629.aspx" target=_blank&gt;N-Tiers開發方式(如何使用VB.NET撰寫COM+元件)&lt;/A&gt; &lt;BR&gt;&lt;A href="http://blog.blueshop.com.tw/topcat/archive/2006/08/09/35630.aspx" target=_blank&gt;N-Tiers開發方式(COM+元件的註冊、修改)&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;但是小喵遇到一個狀況，當小喵寫好的元件註冊後，要呼叫使用的時候卻出現以下的錯誤訊息&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;P&gt;無法載入檔案或組件 'ICSharpCode.SharpZipLib, Version=0.85.4.369, Culture=neutral, PublicKeyToken=1b03e6acf1164f73' 或其相依性的其中之一。 系統找不到指定的檔案。&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;原因在於ICSharpCode.SharpZipLib.dll沒有註冊到系統中，因此當小喵寫的COM+要呼叫該dll的時候，就找不到了。&lt;/P&gt;
&lt;P&gt;因此必須在OS中把這個dll註冊。由於該dll並非COM+的dll，所以要用以下的方式來註冊&lt;/P&gt;
&lt;P&gt;首先開啟Visual Studio 2005的命令提示字元(VS2005的命令視窗，需安裝SDK才有)，接著將ICSharpCode.SharpZipLib.dll複製到某個存放dll的資料夾，然後輸入以下的兩個指令：&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#0000ff&gt;RegAsm /tlb ICSharpCode.SharpZipLib.dll&lt;BR&gt;GACUTIL /i ICSharpCode.SharpZipLib.dll&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;這樣會將該dll產生tlb並且註冊到GAC中。COM+就能夠正確的呼叫該dll並執行壓縮/解壓縮了。&lt;/P&gt;
&lt;P&gt;小喵之後測試，在ASP中可以透過該COM+正確的壓縮/解壓縮檔案。這樣可以透過COM+讓ASP/ASP.NET/VB/VB.NET這些所開發的系統都能有壓縮/解壓縮的能力了。&lt;/P&gt;&lt;img src ="http://blog.blueshop.com.tw/topcat/aggbug/54401.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>topcat</dc:creator><title>解決ASP呼叫VB.NET撰寫的COM+元件沒有停止的問題</title><link>http://blog.blueshop.com.tw/topcat/archive/2008/01/22/54119.aspx</link><pubDate>Tue, 22 Jan 2008 14:18:00 GMT</pubDate><guid>http://blog.blueshop.com.tw/topcat/archive/2008/01/22/54119.aspx</guid><wfw:comment>http://blog.blueshop.com.tw/topcat/comments/54119.aspx</wfw:comment><comments>http://blog.blueshop.com.tw/topcat/archive/2008/01/22/54119.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blog.blueshop.com.tw/topcat/comments/commentRss/54119.aspx</wfw:commentRss><trackback:ping>http://blog.blueshop.com.tw/topcat/services/trackbacks/54119.aspx</trackback:ping><description>&lt;P&gt;在新舊系統交替的尷尬期，本來的系統是&lt;BR&gt;ASP-----COM+(VB6)-------DB&lt;BR&gt;會變成&lt;BR&gt;ASP/ASP.NET-----COM+(VB6/VB.NET)-----DB&lt;BR&gt;這樣新舊混用的階段(系統龐大，不太可能全部改寫成.NET再上線)&lt;/P&gt;
&lt;P&gt;在這樣的尷尬期裡，上次小喵提到在ASP.NET呼叫VB6/VB.NET所撰寫的元件，他的使用釋放方式是不同的。這次來聊聊用ASP呼叫新的VB.NET撰寫的元件的問題&lt;/P&gt;
&lt;P&gt;其實啟動新舊元件的寫法是一模一樣的，最大的問題在於，ASP呼叫VB6的元件，當元件執行完後，會自動的釋放掉，但是用ASP呼叫VB.NET開發的元件，卻會讓元件在執行完成時，沒有完全的回收釋放。如果元件是讀取資料那還沒關係，慘的是如果呼叫的元件是維護資料，由於元件並沒有運轉完成並回收。因此整個維護時的Transaction並沒有釋放掉。這會造成其他的程式讀取資料時，因為還被Lock而一直等待著。&lt;/P&gt;
&lt;P&gt;因此如果VB.NET所撰寫的元件必須要讓ASP或者VB6的元件呼叫的時候，就必須捨棄AutoComplete，並額外加入手動的SetComplete與SetAbort的動作，並停用AutoComplete。相關的程式碼請參考以下&lt;/P&gt;
&lt;P&gt;&lt;TEXTAREA class=vb style="WIDTH: 682px; HEIGHT: 100px" name=code rows=6 cols=80&gt; Public Function ChgData(Byval Fld1 as String,Byval Key1 as String) As String
    Dim ConnStr as String = "連接字串"
    Using Conn as New SqlConnection(ConnStr)
        Try
   
            Dim SqlTxt as String = "Update Table1 Set Fld1=@Fld1 Where Key1=@Key1 "
            Dim Cmmd as New SqlCommand(SqlTxt,Conn)
            Cmmd.Parameters.AddWithValue("@Fld1",Fld1)
            Cmmd.Parameters.AddWithValue("@Key1",Key1)
            Cmmd.ExecuteNonQuery()

            Return "Success"
            ContextUtil.SetComplete()  '增加這個手動的SetComplete

       Catch ex as Exception
            Return "False"
            ConTextUtil.SetAbort()    '增加這個手動的SetAbort
            Throw New Exception(ex.Message)

       End Try
    End Using
End Function&lt;/TEXTAREA&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src ="http://blog.blueshop.com.tw/topcat/aggbug/54119.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>topcat</dc:creator><title>ASP.NET呼叫.NET的COM+元件與VB6的COM+元件方式比較</title><link>http://blog.blueshop.com.tw/topcat/archive/2008/01/16/54069.aspx</link><pubDate>Wed, 16 Jan 2008 12:22:00 GMT</pubDate><guid>http://blog.blueshop.com.tw/topcat/archive/2008/01/16/54069.aspx</guid><wfw:comment>http://blog.blueshop.com.tw/topcat/comments/54069.aspx</wfw:comment><comments>http://blog.blueshop.com.tw/topcat/archive/2008/01/16/54069.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blog.blueshop.com.tw/topcat/comments/commentRss/54069.aspx</wfw:commentRss><trackback:ping>http://blog.blueshop.com.tw/topcat/services/trackbacks/54069.aspx</trackback:ping><description>&lt;P&gt;小喵的系統剛好處於新舊交替的階段，以往的方式是透過【ASP----COM+------DB】這樣的方式運作，由於系統龐大，不可能全部重新改寫為.NET的情況下，產生新舊交替的階段就會變成以下這樣&lt;/P&gt;
&lt;P&gt;ASP/ASP.NET共存--------COM+(VB6/VB.NET共存)-----------DB&lt;/P&gt;
&lt;P&gt;因此就會有呼叫新的COM+(VB.NET)與舊的COM+(VB6)的狀況&lt;/P&gt;
&lt;P&gt;有趣的是.NET裡面呼叫新舊的元件的寫法是不同的，以下與大家分享&lt;/P&gt;
&lt;P&gt;
&lt;HR&gt;

&lt;P&gt;&lt;/P&gt;
&lt;P&gt;假設我有新舊元件名稱如下：&lt;/P&gt;
&lt;P&gt;新元件(VB.NET撰寫)：PNEW0000.CNEW0000裡面Function Fnc1N&lt;BR&gt;舊元件(VB6撰寫)：POLD0000.COLD0000&amp;nbsp;裡面Function Fnc1O&lt;/P&gt;
&lt;P&gt;使用方式如下&lt;/P&gt;
&lt;P&gt;(呼叫VB.NET的COM+)&lt;/P&gt;
&lt;P&gt;&lt;TEXTAREA class=vb style="WIDTH: 662px; HEIGHT: 100px" name=code rows=6 cols=78&gt;Using obj as Object=CreateObject  '使用Using呼叫，用完自動釋放
    Try
        Dim rc as String = obj.Fnc1N()
    Catch ex as Exception
        Throw
    End Try
End Using&lt;/TEXTAREA&gt;&lt;/P&gt;
&lt;P&gt;(呼叫VB6的COM+)&lt;/P&gt;
&lt;P&gt;&lt;TEXTAREA class=vb style="WIDTH: 664px; HEIGHT: 100px" name=code rows=6 cols=78&gt;
Dim obj as Object=CreateObject("POLD0000.COLD0000")
Try
    Dim rc as String = obj.Fnc1O()

Catch ex as Exception
    Throw
Finally
    '釋放非.NET的元件不能用Using或者是Dispose來處理
    System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
    obj = Nothing
End Try&lt;/TEXTAREA&gt;&lt;/P&gt;
&lt;P&gt;說明：&lt;/P&gt;
&lt;P&gt;.NET程式呼叫.NET所撰寫的COM+元件，強烈建議使用Using的方式宣告，這樣會在End Using的時候自動的將資源給釋放掉。但是.NET呼叫VB6的元件，就必須使用特別的語法來釋放資源。&lt;/P&gt;
&lt;P&gt;以上分享大家&lt;/P&gt;&lt;img src ="http://blog.blueshop.com.tw/topcat/aggbug/54069.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>topcat</dc:creator><title>設定應用程式集區(AppPool)防止Server上的Web應用程式彼此干擾</title><link>http://blog.blueshop.com.tw/topcat/archive/2008/01/07/53968.aspx</link><pubDate>Mon, 07 Jan 2008 16:48:00 GMT</pubDate><guid>http://blog.blueshop.com.tw/topcat/archive/2008/01/07/53968.aspx</guid><wfw:comment>http://blog.blueshop.com.tw/topcat/comments/53968.aspx</wfw:comment><comments>http://blog.blueshop.com.tw/topcat/archive/2008/01/07/53968.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blog.blueshop.com.tw/topcat/comments/commentRss/53968.aspx</wfw:commentRss><trackback:ping>http://blog.blueshop.com.tw/topcat/services/trackbacks/53968.aspx</trackback:ping><description>&lt;P&gt;說明一下AppPool的概念&lt;BR&gt;IIS6.0之後，有AppPool的概念&lt;BR&gt;預設的Web應用程式，會使用DefaultAppPool&lt;BR&gt;&lt;BR&gt;每個不同的AppPool在Server上運作的時候&lt;BR&gt;會使用不同的記憶體區塊，產生各自的執行個體&lt;BR&gt;並且運作在不同的Session中&lt;BR&gt;&lt;BR&gt;預設都會在DefaultAppPool這個區塊裡面運作&lt;BR&gt;當AppPool停止，或者回收的時候&lt;BR&gt;使用這個AppPool的所有Web應用程式都會同時的被停止、或者回收(ASPX裡面的Session會被清空)&lt;BR&gt;而當相同的AppPool裡面，如果有某個Web應用程式有問題時(例如發生無窮迴圈)&lt;BR&gt;相同的AppPool裡面的也都會因為執行在同一個Session中&lt;BR&gt;造成其他在這個AppPool的程式也受到影響(例如瀏覽速度變慢，甚至同時當掉)&lt;BR&gt;&lt;BR&gt;在使用上，如果在同一台Server上要運作不同的.NET Framework&lt;BR&gt;那麼就一定需要讓不同的Framework運作在不同的AppPool裡面&lt;BR&gt;&lt;BR&gt;至於使用相同的.NET Framework版本的狀況下&lt;BR&gt;就可以依照Server的狀況來設定&lt;BR&gt;如果每個不同的Web應用程式都設定一個專屬的AppPool&lt;BR&gt;這樣做當然可以，不過相對的必須使用較多的Server資源&lt;BR&gt;但是這麼做卻可以讓不同的Web應用程式變得比較獨立&lt;BR&gt;不會受到其他Web應用程式的不良影響&lt;BR&gt;(&lt;BR&gt;例如要解決Web App1的問題，把DefaultAppPool停掉&lt;BR&gt;→結果造成所有DefaultAppPool的程式全部重新啟動&lt;BR&gt;但是如果是獨立的WebApp1Pool的話，停掉WebApp1Pool只會讓有問題的Web App1重新啟動&lt;BR&gt;其他的Web App不會有影響&lt;BR&gt;)&lt;BR&gt;&lt;BR&gt;所以...小喵的建議...&lt;BR&gt;如果您的Sever記憶體夠大的話...&lt;BR&gt;不妨讓每個WebApp有自己的AppPool&lt;BR&gt;&lt;BR&gt;^_^ &lt;/P&gt;
&lt;P&gt;
&lt;HR&gt;
&lt;/P&gt;
&lt;P&gt;&amp;nbsp;接著就來看一下怎麼設定應用程式集區AppPool&lt;BR&gt;(以Windows 2003 Server的IIS6為範例，2008、Vista使用精神差不多，但是設定的畫面不太一樣)&lt;/P&gt;
&lt;P&gt;開啟IIS，在應用程式集區右鍵→新增 →應用程式集區&lt;/P&gt;
&lt;P&gt;&lt;IMG src="/images/blog_blueshop_com_tw/topcat/590/o_AppPool01.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;小喵習慣用現存的來改，這樣原本現存的一些設定可以複製過來&lt;/P&gt;
&lt;P&gt;&lt;IMG src="/images/blog_blueshop_com_tw/topcat/590/o_AppPool02.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;建立好AppPool後，接著設定應用程式指定剛剛的AppPool&lt;/P&gt;
&lt;P&gt;&lt;IMG src="/images/blog_blueshop_com_tw/topcat/590/o_AppPool03.jpg"&gt;&lt;IMG src="/images/blog_blueshop_com_tw/topcat/590/o_AppPool04.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;當有WebApp當掉時，就可以用停止，當抓不到新的class時，就用回收&lt;/P&gt;
&lt;P&gt;&lt;IMG src="/images/blog_blueshop_com_tw/topcat/590/o_AppPool05.jpg"&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src ="http://blog.blueshop.com.tw/topcat/aggbug/53968.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>topcat</dc:creator><title>.NET呼叫VB6撰寫元件【釋放資源】的語法</title><link>http://blog.blueshop.com.tw/topcat/archive/2007/04/04/50403.aspx</link><pubDate>Wed, 04 Apr 2007 18:31:00 GMT</pubDate><guid>http://blog.blueshop.com.tw/topcat/archive/2007/04/04/50403.aspx</guid><wfw:comment>http://blog.blueshop.com.tw/topcat/comments/50403.aspx</wfw:comment><comments>http://blog.blueshop.com.tw/topcat/archive/2007/04/04/50403.aspx#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://blog.blueshop.com.tw/topcat/comments/commentRss/50403.aspx</wfw:commentRss><trackback:ping>http://blog.blueshop.com.tw/topcat/services/trackbacks/50403.aspx</trackback:ping><description>在撰寫.NET的時候，.NET並不會自動作資源回收，所以呼叫完元件後，需要自己下語法將資源回收&lt;br&gt;
&lt;br&gt;
如果呼叫的是.NET所撰寫的COM+元件，那麼資源回收的語法是&lt;br&gt;
&lt;br&gt;
Obj.Dispose()&lt;br&gt;
&lt;br&gt;
Obj = Nothing&lt;br&gt;
&lt;br&gt;
 &lt;br&gt;
&lt;br&gt;
但是如果呼叫的是VB6的元件，那麼不能呼叫Dispose將資源釋放&lt;br&gt;
&lt;br&gt;
所以需要用以下的指令將資源釋放(元件服務中的數字會停下來)&lt;br&gt;
&lt;br&gt;
 &lt;br&gt;
&lt;br&gt;
 &lt;br&gt;&lt;font color=red&gt;&lt;b&gt;System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
整體的語法如下&lt;br&gt;
Dim obj as Object = CreateObject(“PDemo.CDemo”)&lt;br&gt;
&lt;br&gt;
Try&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Catch ex As Exception&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Finally&lt;br&gt;
&lt;br&gt;
&lt;br&gt;&lt;font color=red&gt;&lt;b&gt;System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
    obj = Nothing&lt;br&gt;
&lt;br&gt;
End Try&lt;br&gt;

&lt;img src ="http://blog.blueshop.com.tw/topcat/aggbug/50403.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>topcat</dc:creator><title>N-Tiers開發方式(ASP/ASP.NET、VB6/VB.NET呼叫使用COM+元件)</title><link>http://blog.blueshop.com.tw/topcat/archive/2006/08/28/36695.aspx</link><pubDate>Mon, 28 Aug 2006 19:05:00 GMT</pubDate><guid>http://blog.blueshop.com.tw/topcat/archive/2006/08/28/36695.aspx</guid><wfw:comment>http://blog.blueshop.com.tw/topcat/comments/36695.aspx</wfw:comment><comments>http://blog.blueshop.com.tw/topcat/archive/2006/08/28/36695.aspx#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://blog.blueshop.com.tw/topcat/comments/commentRss/36695.aspx</wfw:commentRss><trackback:ping>http://blog.blueshop.com.tw/topcat/services/trackbacks/36695.aspx</trackback:ping><description>&lt;P&gt;續接：&lt;A id=_dd85df0e09b5c35a_HomePageDays_DaysList__ctl2_DayItem_DayList__ctl0_TitleUrl href="/topcat/archive/2006/08/09/35630.aspx"&gt;N-Tiers開發方式(COM+元件的註冊、修改)&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;在元件安裝完成後，接下來的工作就是要如何呼叫使用我們寫好的元件了。我們假設我們寫好的元件的名稱如下：&lt;/P&gt;
&lt;P&gt;&lt;TEXTAREA class=xml style="WIDTH: 681px; HEIGHT: 100px" name=code rows=6 cols=80&gt;Package:KDMO1000
Project：PDMOMenu
Class：
    CDMOMenu1(無Transaction)
    CDMOMenu2(有Transaction)
假設CDMOMenu1中有一個Function是GetNodeName，傳入參數NodeId(整數)，傳回NodeName(字串)

GetNodeName(Byval NodeId as Integer) As String&lt;/TEXTAREA&gt;&lt;/P&gt;
&lt;P&gt;Late Binding：&lt;/P&gt;
&lt;P&gt;我這邊所提的使用方式，是使用Late Binding的呼叫方式。也就是說，不會預先將元件註冊到您的ASP.NET的專案中，或者是您的VB.NET的專案中，當系統運作的時候，在動態的從Server把該物件Bind上來使用。這樣做的缺點是，您無法透過obj.就彈出元件內的屬性方法讓您選擇，使用屬性方法的時候都必須自己Keyin進去。但是優點則是，當您的元件有做了變更，您不必去一個一個的專案裡重新的Reference您的元件；另外就是不論您寫的是ASP、ASP.NET、VB、VB.NET，您呼叫元件的方式是一致的。&lt;/P&gt;
&lt;P&gt;呼叫元件：&lt;/P&gt;
&lt;P dir=ltr&gt;呼叫元件的方式如下：&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;P dir=ltr&gt;ASP:&lt;BR&gt;&lt;TEXTAREA class=vb style="WIDTH: 607px; HEIGHT: 100px" name=code rows=6 cols=71&gt;Set obj = CreateObject("PDMOMenu.CDMOMenu1")
NodeId = 2
NodeName = obj.GetNodeName(NodeId)&lt;/TEXTAREA&gt;&lt;/P&gt;
&lt;P dir=ltr&gt;VB:&lt;BR&gt;&lt;TEXTAREA class=vb style="WIDTH: 606px; HEIGHT: 100px" name=code rows=6 cols=71&gt;Dim obj as Object
Set obj = CreateObject("PDMOMenu.CDMOMenu1")
Dim NodeId as Integer
NodeId = 2
Dim NodeName as String
NodeName = obj.GetNodeName(NodeId)&lt;/TEXTAREA&gt;&lt;/P&gt;
&lt;P dir=ltr&gt;ASP.NET/VB.NET&lt;/P&gt;
&lt;P dir=ltr&gt;&lt;TEXTAREA class=vb style="WIDTH: 609px; HEIGHT: 179px" name=code rows=7 cols=72&gt;Dim NodeId As Integer = 2
Dim obj As Object = CreateObject("PDMOMenu.CDMOMenu1")
Try
    Dim NodeName As String = obj.GetNodeName(NodeId)
Catch ex As Exception
    Me.lblErrMsg.Text=ex.Message.toString()
Finally
    '資源回收
    obj.Dispose()
    obj = Nothing
End Try&lt;/TEXTAREA&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P dir=ltr&gt;&amp;nbsp;.NET呼叫元件需自行釋放元件：&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;P dir=ltr&gt;從以上的這些程式碼，可以發現，呼叫元件的過程幾乎相同，使用.NET撰寫時，呼叫的方式更可以簡潔。&lt;/P&gt;
&lt;P dir=ltr&gt;當元件被呼叫執行後，可以在【元件服務】中找到該Package中的元件被呼叫而轉起來。如果是用ASP,VB6呼叫元件，可以發現當元件呼叫完成後，元件的轉動會停下來，呼叫中的元件數字也會歸零。但次使用.NET呼叫元件，如果沒有撰寫【Try..Catch..Finally..End Try】並且把【&lt;STRONG&gt;&lt;FONT color=#0000ff&gt;obj.Dispose()&lt;/FONT&gt;&lt;/STRONG&gt;】、【&lt;STRONG&gt;&lt;FONT color=#0000ff&gt;obj = Nothing&lt;/FONT&gt;&lt;/STRONG&gt;】放在Finally裡，那麼【元件服務】中的元件將會轉不停。這是因為ASP,VB6再程式執行完畢時，會自動的做【&lt;STRONG&gt;&lt;FONT color=#0000ff&gt;資源回收&lt;/FONT&gt;&lt;/STRONG&gt;】的動作；但是在.NET中【&lt;STRONG&gt;&lt;FONT color=#0000ff&gt;資源回收&lt;/FONT&gt;&lt;/STRONG&gt;】必須經由程式設計者手動的執行，否則需當系統資源不足時啟動GC才能夠真正的回收。&lt;/P&gt;
&lt;P dir=ltr&gt;&amp;nbsp;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;img src ="http://blog.blueshop.com.tw/topcat/aggbug/36695.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>topcat</dc:creator><title>N-Tiers開發方式(COM+元件的註冊、修改)</title><link>http://blog.blueshop.com.tw/topcat/archive/2006/08/09/35630.aspx</link><pubDate>Wed, 09 Aug 2006 16:45:00 GMT</pubDate><guid>http://blog.blueshop.com.tw/topcat/archive/2006/08/09/35630.aspx</guid><wfw:comment>http://blog.blueshop.com.tw/topcat/comments/35630.aspx</wfw:comment><comments>http://blog.blueshop.com.tw/topcat/archive/2006/08/09/35630.aspx#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://blog.blueshop.com.tw/topcat/comments/commentRss/35630.aspx</wfw:commentRss><trackback:ping>http://blog.blueshop.com.tw/topcat/services/trackbacks/35630.aspx</trackback:ping><description>&lt;P&gt;當COM+的元件已經撰寫完成後，接著就是要如何將撰寫好的元件註冊的主機的【元件服務】上&lt;/P&gt;
&lt;P&gt;以往小喵用VB6撰寫元件，要註冊元件時，只需要在元件服務中建立空的Package，然後將寫好的元件托拉進去即可，要修改時，只要元件的機碼相容，也只需要將Package停止後，將元件覆蓋即可。請參考&lt;A href="http://www.blueshop.com.tw/download/show.asp?pgmcde=PGM20050624134625OTC"&gt;元件撰寫、註冊過程錄影檔&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;但是進入.NET開發元件，小喵發現無法使用原來的方式處理，必須透過【.NET Framework 2.0】的【SDK命令提示字元】，使用這樣的Command視窗透過下指令的方式來註冊，註冊後元件會依照原件撰寫時所指定的Package存放，而如果該Package不存在，也會自動產生&lt;/P&gt;
&lt;P&gt;首先Server除了要安裝.NET Framework 2.0以外，還得安裝SDK才能使用，相關鏈結如下：&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;.NET Framework 2.0&lt;BR&gt;&lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=0856eacb-4362-4b0d-8edd-aab15c5e04f5&amp;amp;DisplayLang=zh-tw"&gt;http://www.microsoft.com/downloads/details.aspx?FamilyID=0856eacb-4362-4b0d-8edd-aab15c5e04f5&amp;amp;DisplayLang=zh-tw&lt;/A&gt; 
&lt;LI&gt;.NET Framework 2.0 SDK&lt;BR&gt;&lt;A href="http://www.microsoft.com/downloads/details.aspx?familyid=FE6F2099-B7B4-4F47-A244-C96D69C35DEC&amp;amp;displaylang=zh-tw"&gt;http://www.microsoft.com/downloads/details.aspx?familyid=FE6F2099-B7B4-4F47-A244-C96D69C35DEC&amp;amp;displaylang=zh-tw&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;註冊與反註冊過程如下&lt;/P&gt;
&lt;P&gt;手先準備好兩個批次檔，分別用來註冊與反註冊元件&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;註冊元件(RegNetCom.bat)：&lt;BR&gt;&lt;TEXTAREA class=xml name=code rows=6 cols=50&gt;REGSVCS %1.dll
GACUTIL /i %1.dll&lt;/TEXTAREA&gt; 
&lt;LI&gt;反註冊元件(UnRegNetCom.bat)：&lt;BR&gt;&lt;TEXTAREA class=xml name=code rows=6 cols=50&gt;GACUTIL /u %1
REGSVCS /u %1.dll&lt;/TEXTAREA&gt;
&lt;LI&gt;有人反應原有方式GAC無法移除，所以小喵稍微改寫了一下，這樣註冊移除就可以都正常了。【&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;New&lt;/FONT&gt;&lt;/STRONG&gt;】&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;安裝完.NET Framework SDK後，會有【SDK命令提示字元】，首先將您要註冊的元件，複製到適當的目錄中，小喵通常是將相關的dll複製到【D:\Application\(專案名稱)\】中，其中專案名稱依不同需求會訂定不同的名稱，例如：D:\Application\PDMO&lt;/P&gt;
&lt;P&gt;接著將以上兩個批次檔(RegNetCom.bat、UnRegNetCom.bat)也複製到該資料夾中&lt;/P&gt;
&lt;P&gt;然後開啟【SDK命令提示字元】，假設元件產生後的dll名稱為PDMOMenu.dll那麼下以下指令：&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;註冊時：&lt;BR&gt;RegNetCom PDMOMenu 
&lt;LI&gt;反註冊(移除)時：&lt;BR&gt;UnRegNetCom PDMOMenu&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;反註冊時必須注意：元件是否有被呼叫起來→如果有→先停止Package&lt;/P&gt;
&lt;P&gt;當元件註冊完後，如果是該Package的第一個元件，還需針對元件設定【使用者識別】讓呼叫元件時可切換指定的帳號權限執行，方式如下：&lt;/P&gt;
&lt;UL&gt;
&lt;LI dir=ltr style="MARGIN-RIGHT: 0px"&gt;在Package上按右鍵→內容 
&lt;LI dir=ltr style="MARGIN-RIGHT: 0px"&gt;識別碼→使用下列使用者 
&lt;LI dir=ltr style="MARGIN-RIGHT: 0px"&gt;瀏覽→選取適當使用者→輸入該帳號密碼 
&lt;LI dir=ltr style="MARGIN-RIGHT: 0px"&gt;確認&lt;/LI&gt;&lt;/UL&gt;
&lt;P style="MARGIN-RIGHT: 0px"&gt;這樣就能夠依據需求，在呼叫該Package中的元件時，切換身分為指定的使用者，透過該使用者的權限來執行元件了&lt;/P&gt;&lt;img src ="http://blog.blueshop.com.tw/topcat/aggbug/35630.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>topcat</dc:creator><title>N-Tiers開發方式(如何使用VB.NET撰寫COM+元件)</title><link>http://blog.blueshop.com.tw/topcat/archive/2006/08/09/35629.aspx</link><pubDate>Wed, 09 Aug 2006 16:21:00 GMT</pubDate><guid>http://blog.blueshop.com.tw/topcat/archive/2006/08/09/35629.aspx</guid><wfw:comment>http://blog.blueshop.com.tw/topcat/comments/35629.aspx</wfw:comment><comments>http://blog.blueshop.com.tw/topcat/archive/2006/08/09/35629.aspx#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://blog.blueshop.com.tw/topcat/comments/commentRss/35629.aspx</wfw:commentRss><trackback:ping>http://blog.blueshop.com.tw/topcat/services/trackbacks/35629.aspx</trackback:ping><description>&lt;P&gt;小喵撰寫COM+元件開始於VB6的年代，撰寫與註冊的方式還算不是很複雜，不過隨著進入了.NET的世界，撰寫的過程也變得比較複雜了許多。&lt;/P&gt;
&lt;P&gt;以下是撰寫的步驟&lt;/P&gt;
&lt;P&gt;假設要撰寫的是一個資料庫DDMO中的資料表(TDMOMenu)的資料存取元件，要產生一個元件服務中的Package名稱為【KDMO1000】，裡面有個元件PDMOMenu.dll內有兩個COM+元件分別是&lt;BR&gt;Project.Class&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;PDMOMenu.CDMOMenu1(無Transaction)：用以讀取資料 
&lt;LI&gt;PDMOMenu.CDMOMenu2(有Transaction)：用以維護資料&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;撰寫步驟：&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;建專案：&lt;BR&gt;&lt;TEXTAREA class=xml style="WIDTH: 619px; HEIGHT: 100px" name=code rows=6 cols=73&gt; 1.請在適當的目錄下，建立您元件專案的目錄【PDMOMenu】 

 2.建立專案(Create Project),選擇【類別庫(Class Library)】，目錄請設定為您專案的目錄，Name設定為【PDMOMenu】 

 3.方案總管(Solution Explorer)中點選Class1.vb，變更屬性(Properties)中的檔名(File Name)為【CDMOMenu1.vb】(無TranSaction)，【CDMOMenu2.vb】(有Transaction) 

 4.參考(Reference)右鍵→加入參考，增加【System.EnterpriseServices】 

  

 →步驟二 &lt;/TEXTAREA&gt; 
&lt;LI&gt;專案內容：&lt;BR&gt;&lt;TEXTAREA class=xml style="WIDTH: 615px; HEIGHT: 100px" name=code rows=6 cols=72&gt; 1.點選專案(Project)右鍵→屬性(Properties) 

 2.點選【簽署(Signing)】，勾選【簽署組件】 

   在選擇強勢名稱金鑰檔(Choose a strong name key file): 
   選擇新增(New)→輸入【PDMOMenu】 

 3.點選【應用程式(Application)】 
   檢查【組件名稱(Assembly Name)】、【根命名空間(Root NameSpace)】是否是【PDMOMenu】 

 **4.按【組件資訊】，將【讓組件成為COM-Visiable(Make assembly COM-Visiable)】打勾 
  

 →步驟三 &lt;/TEXTAREA&gt; 
&lt;LI&gt;AssemblyInfo.vb：&lt;BR&gt;&lt;TEXTAREA class=xml style="WIDTH: 614px; HEIGHT: 100px" name=code rows=6 cols=72&gt;1.請在最上方Imports加入：
Imports System.EnterpriseServices

2.請在最下方加入以下指令：
&amp;lt;Assembly: ApplicationName("KDMO1000")&amp;gt; '*設定元件服務的專案名稱  
&amp;lt;Assembly: ApplicationAccessControl(False)&amp;gt;  
&amp;lt;Assembly: ApplicationActivation(ActivationOption.Server)&amp;gt;  
  &lt;/TEXTAREA&gt; 
&lt;LI&gt;Class&amp;nbsp;內容：&lt;BR&gt;無Transaction Class(CDMOMenu1.vb)：&lt;BR&gt;&lt;TEXTAREA class=vb style="WIDTH: 613px; HEIGHT: 100px" name=code rows=6 cols=72&gt;Imports System.EnterpriseServices
Imports System.Runtime.InteropServices
Imports System.Data.SqlClient
Imports System.Data
Imports System.IO

'Guid請在元件第一次建立時，產生新的，之後修改時不必變更
&amp;lt;Guid("838A5FE4-2DCC-43DF-8658-0697E8FB7C0F"), _
EventTrackingEnabled(True)&amp;gt; _
Public Class CDMOMenu1

    Inherits ServicedComponent
    Const DBName as String = "DDMO"   



    Public Function Test1(ByVal In1() As String, ByVal Out1() As String, ByRef P As String, ByRef R As String, ByVal User As String) As String
        '*************************************************************************
        '**     撰寫者：topcat             撰寫日期：2006/8/9
        '**     用途：  1.
        '**     做法：
        '**             1.
        '**     注意事項：
        '**             1.
        '**             2.
        '**     維護記錄：
        '**         維護者：姓名             維護日期：日期
        '**         維護項目：
        '**                 1.
        '**                 2.
        '**         做法：  1.
        '**                 2.
        '**         注意事項：
        '**                 1.
        '*************************************************************************

        Dim ConnStr As String = GetConnStr(DBName)

        Try

            Test1 = "Success"

        Catch ex As Exception
            Test1 = "False"
            Throw New Exception(ex.Message)

        Finally


        End Try
    End Function

    Public Function GetConnStr(ByVal DBName As String) As String
        '*************************************************************************
        '**     撰寫者：topcat     撰寫日期：2006/2/8
        '**     用途：  1.讀取Connection String的方式
        '**     做法：
        '**             1.傳入參數DataBase Name DBName
        '**             2.透過Stream將文字檔讀出
        '**             3.將取得的資料傳回
        '**             4.關閉相關物件
        '**     注意事項：
        '**             1.
        '**             2.
        '**     維護記錄：
        '**         維護者：姓名(員工代號)     維護日期：日期
        '**         維護項目：
        '**                 1.
        '**                 2.
        '**         做法：  1.
        '**                 2.
        '**         注意事項：
        '**                 1.
        '*************************************************************************

        Dim StrmRd As New StreamReader("C:\DataLink\" + DBName + ".ini")
        Dim Line As String = ""
        Dim ConnStr As String = ""
        Try
            Do
                Line = StrmRd.ReadLine()
                If Line &amp;lt;&amp;gt; "" Then
                    ConnStr += Line
                End If
            Loop Until Line Is Nothing
            GetConnStr = ConnStr

        Catch ex As Exception
            Throw New Exception(ex.Message.ToString)

        Finally
            StrmRd.Close()
            StrmRd.Dispose()
            StrmRd = Nothing

        End Try
    End Function
End Class&lt;/TEXTAREA&gt;&lt;BR&gt;有Transaction Class(CDMOMenu2.vb)：&lt;BR&gt;&lt;TEXTAREA class=vb style="WIDTH: 611px; HEIGHT: 100px" name=code rows=6 cols=72&gt;Imports System.EnterpriseServices
Imports System.Runtime.InteropServices
Imports System.Data.SqlClient
Imports System.Data
Imports System.IO


&amp;lt;Guid("28549732-9A0F-4731-9688-10CEE644500E") _
, Transaction(TransactionOption.Required) _
, Synchronization(SynchronizationOption.Required) _
, JustInTimeActivation(True) _
, EventTrackingEnabled(True)&amp;gt; _
Public Class CDMOMenu2
    Inherits ServicedComponent

    Const DBName as String = "DDMO"   


    &amp;lt;AutoComplete()&amp;gt; _
    Public Function Test2(ByVal In1() As String, ByVal Out1() As String, ByRef P As String, ByRef R As String, ByVal User As String) As String
        '*************************************************************************
        '**     撰寫者：topcat             撰寫日期：2006/8/9
        '**     用途：  1.
        '**     做法：
        '**             1.
        '**     注意事項：
        '**             1.
        '**             2.
        '**     維護記錄：
        '**         維護者：姓名(員工代號)     維護日期：日期
        '**         維護項目：
        '**                 1.
        '**                 2.
        '**         做法：  1.
        '**                 2.
        '**         注意事項：
        '**                 1.
        '*************************************************************************

        Dim ConnStr As String = GetConnStr(DBName)

        Try


            Test2 = "Success"
        Catch ex As Exception
            Test2 = "False"
            Throw New Exception(ex.Message)

        Finally

        End Try
    End Function

    Public Function GetConnStr(ByVal DBName As String) As String
        '*************************************************************************
        '**     撰寫者：topcat     撰寫日期：2006/2/8
        '**     用途：  1.讀取Connection String的方式
        '**     做法：
        '**             1.傳入參數DataBase Name DBName
        '**             2.透過Stream將文字檔讀出
        '**             3.將取得的資料傳回
        '**             4.關閉相關物件
        '**     注意事項：
        '**             1.
        '**             2.
        '**     維護記錄：
        '**         維護者：姓名(員工代號)     維護日期：日期
        '**         維護項目：
        '**                 1.
        '**                 2.
        '**         做法：  1.
        '**                 2.
        '**         注意事項：
        '**                 1.
        '*************************************************************************

        Dim StrmRd As New StreamReader("C:\DataLink\" + DBName + ".ini")
        Dim Line As String = ""
        Dim ConnStr As String = ""
        Try
            Do
                Line = StrmRd.ReadLine()
                If Line &amp;lt;&amp;gt; "" Then
                    ConnStr += Line
                End If
            Loop Until Line Is Nothing
            GetConnStr = ConnStr

        Catch ex As Exception
            Throw New Exception(ex.Message.ToString)

        Finally
            StrmRd.Close()
            StrmRd.Dispose()
            StrmRd = Nothing

        End Try
    End Function

End Class&lt;/TEXTAREA&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;撰寫完相關的程式後，接著就是Build專案，然後就會依照Project的Property設定的位置產生dll&lt;/P&gt;
&lt;P&gt;
&lt;HR&gt;
&lt;/P&gt;
&lt;P&gt;補充，感謝網友小魔告知內容有誤，把取得資料庫連線的Function補上&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;說明：&lt;/P&gt;
&lt;P&gt;存取資料會透過ConnString的設定來指定要存取的是哪台Server上的哪個資料庫，使用驗證方式是用什麼方式。如果ConnString寫在元件內，那麼當Server的位址改變、甚至資料庫名稱改變，那麼就必須把元件的程式一個個叫出來修改，然後再編譯註冊，這樣的過程太過繁複&lt;/P&gt;
&lt;P&gt;那麼怎麼把ConnString的設定抽離元件，小喵的做法是建立一個.ini的文字檔，放在C:\DataLink，裡面就放著ConnString的內容，然後在元件中透過System.IO讀取該文字檔的內容。&lt;/P&gt;
&lt;P&gt;如此一來，未來資料庫有異動(位置、名稱)，就可以不需要改寫元件，直接修改設定檔即可。&lt;/P&gt;&lt;img src ="http://blog.blueshop.com.tw/topcat/aggbug/35629.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>topcat</dc:creator><title>N-Tiers開發方式(為何使用COM+元件的撰寫商業邏輯層)</title><link>http://blog.blueshop.com.tw/topcat/archive/2006/08/09/35628.aspx</link><pubDate>Wed, 09 Aug 2006 16:00:00 GMT</pubDate><guid>http://blog.blueshop.com.tw/topcat/archive/2006/08/09/35628.aspx</guid><wfw:comment>http://blog.blueshop.com.tw/topcat/comments/35628.aspx</wfw:comment><comments>http://blog.blueshop.com.tw/topcat/archive/2006/08/09/35628.aspx#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://blog.blueshop.com.tw/topcat/comments/commentRss/35628.aspx</wfw:commentRss><trackback:ping>http://blog.blueshop.com.tw/topcat/services/trackbacks/35628.aspx</trackback:ping><description>&lt;P&gt;在上一篇&lt;A id=_ef60b7bc5af60fef_HomePageDays_DaysList__ctl0_DayItem_DayList__ctl0_TitleUrl href="/topcat/archive/2006/08/09/35627.aspx"&gt;N-Tier方式開發(系統分析)&lt;/A&gt; 提到了商業邏輯層的開發，為何會選用COM+來處理，主要有兩個原因：&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;確保交易的完整性：可交由COM+支援Transaction的機制處理 
&lt;LI&gt;Web App切換身分執行元件&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;一、確保交易的完整性：&lt;/P&gt;
&lt;P&gt;在確保交易的完整性，可以透過COM+對於Transaction的支援，讓拆解各功能的時候，不必特意的去考量Transation異動的部份，可交由COM+來處理&lt;/P&gt;
&lt;P&gt;當一個商業邏輯中有了資料的維護，在邏輯的過程中可能會維護了超過兩個以上的資料表在不同的功能上。&lt;/P&gt;
&lt;P&gt;舉個例子來說，例如：產生交易資料、扣除在庫資料，如果將這兩個動作處理在兩個元件上，我們分別稱作【COMA(產生交易資料)】與【COMB(扣除在庫資料)】，將此兩個動作分別放在不同的元件上，可以讓其他的功能來呼叫，而兩個動作，又必須完整的完成了，才能夠算是一個成功的交易過程，如果COMA或者COMB的程式運作過程中，有了什麼狀況(例如無在庫資料，無法扣除時)，那麼在這過程中維護的資料必須還原→此時這樣的還原動作可交給COM+自動完成&lt;/P&gt;
&lt;P&gt;假設COMA中需要維護4個資料表，而COMB需要維護3個資料表，程式流程是&lt;/P&gt;
&lt;P&gt;&lt;TEXTAREA class=xml style="WIDTH: 671px; HEIGHT: 100px" name=code rows=6 cols=79&gt;COMA                       COMB
TBLA1--TBLA2--TBLA3-----→TBLB1--TBLB2--TBLB3┐
              TBLB4←------------------------┘  &lt;/TEXTAREA&gt;&lt;/P&gt;
&lt;P&gt;在COMA執行的過程中，維護了3個資料表(A1、A2、A3)時，呼叫COMB又維護了兩個(B1、B2)&lt;BR&gt;此時要維護B3時出了問題，那嚜剛剛維護的(A1、A2、A3、B1、B2)資料通通要還原&lt;/P&gt;
&lt;P&gt;只需將COMA與COMB包在一個交易中，那麼當過程中有其中一個失敗了，就會還原回去&lt;/P&gt;
&lt;P&gt;如果又有另外一個元件COMC也會呼叫COMB的相同Function，那麼也只需將COMC與COMB包成一個交易，那麼就能夠當有問題的時候也自動還原回去&lt;/P&gt;
&lt;P&gt;二、Web App切換身分執行元件&lt;/P&gt;
&lt;P&gt;在Web App運作的過程中，透過IIS來使用應用程式，主要是透過【IUSER】這樣的使用者來運作，而IUSER這樣的使用者基本上在權限上是限制很多的，因此如果要存取非IIS的資料夾、存取資料庫，都不適合將權限開放給IUSER來使用，以免網路上的駭客透過IUSER竄進來做一些壞事。&lt;/P&gt;
&lt;P&gt;然而系統又有時候必須讓Web的使用者在Server上執行一些特別的功能(例如資料庫的存取)，此時就可以透過COM+的Package來設定特別的識別帳號，然後開放這樣的帳號相關資料表的權限。這樣就能夠更靈活的設計我們的程式&lt;/P&gt;
&lt;P&gt;三、介面與商業邏輯分離→資料庫轉換介面層可沿用&lt;/P&gt;
&lt;P&gt;當介面與商業邏輯分離時，在ASP.NET中所設計的與資料庫之間的溝通是透過商業邏輯的元件，只需要元件的名稱不變、呼叫的函數不變、傳遞的參數不變，那麼假使要轉換不同的資料庫(例如Access轉成SQL)，介面層的相關程式都不需要修改，只需要修改商業邏輯的元件即可。&lt;/P&gt;
&lt;P&gt;更進一步的，如果商業邏輯層中，把商業邏輯運算與資料庫存取也分開了，那麼要轉換資料庫的時候，也只需要把資料庫存取的相關元件修改後，就能夠快速的切換過去，不需要修改商業邏輯的運算部分。這讓整體系統在未來的擴充、轉換上有更大的彈性。&lt;/P&gt;
&lt;P&gt;因為有這樣的特性，所以小喵才會以COM+元件來當作商業邏輯的開發。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src ="http://blog.blueshop.com.tw/topcat/aggbug/35628.aspx" width = "1" height = "1" /&gt;</description></item></channel></rss>