Visual Basic Q&A

As a software engineer, I focus on .NET, especially asp.net, C#, WCF and so on, and I am also very interested in Search Engine Optimization.

Entries Tagged ‘click’

How to sum the fields in a Windows Forms DataGrid control and then display the calculated totals in a footer by using Visual Basic .NET

Symptoms
To sum the fields in a Microsoft Windows Forms DataGrid control and then to display the calculated totals in a footer, you must first create a user control that inherits from the System.Windows.Forms.DataGrid class. Then you must handle the events that are raised when a cell in this user control is changed.
You must disable the default sorting feature of the DataGrid control to prevent the footer row from being sorted. To implement custom sorting for your DataGrid control, you must handle the MouseDown event.
You must also disable the footer row of the DataGrid control to prevent users from editing the cells of the footer row. To provide data for the event that prevents users from editing the cells of the DataGrid control, you must define an event arguments class, and then you must define a class that contains methods to paint and to disable the footer row.
To sum the fields and to display the calculated totals in a footer, build the DataGrid control, add an instance of the DataGrid control to a Windows Application project, bind the DataGrid control to the related data, and then build and run the application.
Resolution
This step-by-step article describes how to sum the fields in a Windows Forms DataGrid control by using Microsoft Visual Basic .NET. This article also describes how to customize the Windows Forms DataGrid control to display the calculated totals in a footer.

RequirementsThis article assumes that you are familiar with the following topics: The Windows Forms DataGrid controlData binding by using Windows Forms and Microsoft ADO.NETHandling and raising events
The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:Microsoft Windows 2000, Microsoft Windows XP, or Microsoft Windows Server 2003Microsoft Visual Studio .NET
Create a Windows Control Library projectStart Visual Studio .NET.On the File menu, point to New, and then click Project. The New Project dialog box appears.Under Project Types, click Visual Basic Projects.Under Templates, click Windows Control Library.In the Name box, type DataGridControl, and then click OK. By default, a user control that is named UserControl1 is created.On the View menu, click Solution Explorer.In Solution Explorer, right-click UserControl1.vb, and then click Rename.Rename the UserControl1.vb file as DataGridControlVB.vb.
Inherit from the Windows Forms DataGrid control, and then add variables, properties, and methodsIn Solution Explorer, right-click DataGridControlVB.vb, and then click View Code.Import the required namespaces, and then declare a delegate for the event that disables the cells of the DataGrid control. To do this, add the following code at the top of the code window:

Imports SystemImports System.CollectionsImports System.ComponentModelImports System.DrawingImports System.DataImports System.Data.SqlClientImports System.Windows.FormsImports System.Text’ Declare a delegate for the event that disables the cells of the DataGrid control.Public Delegate Sub DataGridDisableCellEventHandler _(ByVal sender As System.Object, ByVal e As DataGridDisableCellEventArgs)Locate the following code:

Public Class UserControl1Inherits System.Windows.Forms.UserControlMake your Windows Forms DataGrid control inherit from the System.Windows.Forms.DataGrid class. To do this, replace the code that you located in step 3 with the following code:

Public Class DataGridControlVBInherits System.Windows.Forms.DataGridAdd the following variable declarations after the code that you added in step 4:

‘ Declare private variables for your DataGrid control.Private RowCount As IntegerPrivate ColCount As IntegerPrivate SortedColNum As IntegerPrivate Ascending As BooleanPrivate CellValueChanged As BooleanPrivate SourceTable As StringPrivate MyDataView As DataViewPrivate MyDataSet As DataSetPrivate MyDataRow As DataRowPrivate SummaryCols As ArrayListPrivate CurrentDataGridCellLocation As DataGridCellPrivate WithEvents MyDataTable As DataTablePrivate Shared FooterBackColor As BrushPrivate Shared FooterForeColor As BrushLocate the following code comment in the “Windows Form Designer generated code” area:

‘Add any initialization after the InitializeComponent() callPerform custom initialization in the constructor of your Windows Forms DataGrid control. To do this, replace the code comment that you located in step 6 with the following code:

RowCount = 0ColCount = 0CellValueChanged = FalseAscending = FalseMyDataRow = NothingMyDataTable = New DataTable(“NewTable”)CurrentDataGridCellLocation = New DataGridCellSummaryCols = New ArrayListLocate the following code:

#End RegionAdd the following property definitions after the code that you located in step 8:

Public WriteOnly Property GridDataSet() As DataSetSet(ByVal Value As DataSet)MyDataSet = ValueEnd SetEnd PropertyPublic Property SummaryColumns() As ArrayListGetReturn SummaryColsEnd GetSet(ByVal Value As ArrayList)SummaryCols = ValueEnd SetEnd PropertyPublic Property DataSourceTable() As StringGetReturn SourceTableEnd GetSet(ByVal Value As String)SourceTable = ValueEnd SetEnd PropertyPublic Shared Property FooterColor() As BrushGetReturn FooterBackColorEnd GetSet(ByVal Value As Brush)FooterBackColor = ValueEnd SetEnd PropertyPublic Shared Property FooterFontColor() As BrushGetReturn FooterForeColorEnd GetSet(ByVal Value As Brush)FooterForeColor = ValueEnd SetEnd PropertyDisable the default sorting feature of the DataGrid control to prevent the footer row from being sorted. To do this, and to bind the custom DataGrid control to the related data, add the following code after the code that you added in step 9:

Public Sub BindDataGrid()MyDataTable = MyDataSet.Tables(0)MyDataView = MyDataTable.DefaultViewMe.DataSource = MyDataViewDim TableStyle As DataGridTableStyle = New DataGridTableStyleTableStyle.MappingName = SourceTable’ Add a Boolean data type column to the DataTable object.’ You can use this column during your custom sorting.MyDataTable.Columns.Add(“ID”, System.Type.GetType(“System.Boolean”))MyDataTable.Columns(“ID”).DefaultValue = FalseMyDataTable.Columns(“ID”).ColumnMapping = MappingType.HiddenColCount = MyDataTable.Columns.Count’ Create a footer row for the DataTable object.MyDataRow = MyDataTable.NewRow()’ Set the footer value as an empty string for all columns that contains string values.Dim MyIterator As IntegerFor MyIterator = 0 To ColCount – 1If (MyDataTable.Columns(MyIterator).DataType.ToString() = “System.String”) ThenMyDataRow(MyIterator) = “”End IfNext’ Add the footer row to the DataTable object.MyDataTable.Rows.Add(MyDataRow)RowCount = MyDataTable.Rows.Count’ Add a MyDataGridTextBox control to each cell of the DataGrid control.Dim TempDataGridTextBox As MyDataGridTextBoxFor MyIterator = 0 To ColCount – 2TempDataGridTextBox = New MyDataGridTextBox(MyIterator)TempDataGridTextBox.HeaderText = MyDataTable.Columns(MyIterator).ColumnNameTempDataGridTextBox.MappingName = MyDataTable.Columns(MyIterator).ColumnNameAddHandler TempDataGridTextBox.DataGridDisableCell, _New DataGridDisableCellEventHandler(AddressOf SetEnableValues)’ Disable the default sorting feature of the DataGrid control.TableStyle.AllowSorting = FalseTableStyle.GridColumnStyles.Add(TempDataGridTextBox)NextMe.TableStyles.Add(TableStyle)Me.DataSource = MyDataViewMyDataView.ApplyDefaultSort = FalseMyDataView.AllowNew = False’ Set the value of the footer cell.Dim MyCell As DataGridCell = New DataGridCellMyCell.RowNumber = MyDataTable.Rows.Count – 1′ Calculate the value for each of the cells in the footer.Dim MyArray(2) As StringDim MyString As StringFor Each MyString In SummaryColsMyArray = MyString.Split(“,”c)MyCell.ColumnNumber = Convert.ToInt32(MyArray(0))Me(MyCell) = MyDataTable.Compute(MyArray(1), “ID is null”).ToString()NextEnd Sub
Handle the events that are raised when a cell in the DataGrid control is changedYou must handle the ColumnChanged event of the DataTable object, and then you must handle the CurrentCellChanged event of the DataGrid control to track when a cell value in the DataGrid control is changed. To do this, follow these steps: Handle the ColumnChanged event of the DataTable object. To do this, add the following code after the code that you added in step 10 of the “Inherit from the Windows Forms DataGrid control, and then add variables, properties, and methods” section:

‘ Handle the DataTable object’s ColumnChanged event’ to track whether the value in a cell has changed.Private Sub MyDataTable_ColumnChanged(ByVal sender As Object, _ByVal e As System.Data.DataColumnChangeEventArgs) Handles MyDataTable.ColumnChangedDim Row As Integer, Col As IntegerRow = 0Col = 0′ Determine the row that contains the changed cell.Dim TempDataRow As DataRowFor Each TempDataRow In MyDataTable.RowsIf (TempDataRow.Equals(e.Row)) ThenCurrentDataGridCellLocation.RowNumber = RowCellValueChanged = TrueExit ForRow = Row + 1End IfNext’ Determine the column that contains the changed cell.Dim TempDataColumn As DataColumnFor Each TempDataColumn In MyDataTable.ColumnsIf (TempDataColumn.Equals(e.Column)) ThenCurrentDataGridCellLocation.ColumnNumber = ColCellValueChanged = TrueExit ForCol = Col + 1End IfNextEnd SubHandle the CurrentCellChanged event of the DataGrid control. To do this, add the following code after the code that you added in step 1:

‘ Handle the CurrentCellChanged event of the DataGrid control.Private Sub DataGridControlVB_CurrentCellChanged(ByVal sender As Object, _ByVal e As System.EventArgs) Handles MyBase.CurrentCellChangedIf (CellValueChanged = True) ThenDim MyCell As DataGridCell = New DataGridCellMyCell.RowNumber = MyDataTable.Rows.Count – 1′ Calculate the value for each cell in the footer.Dim MyArray(2) As StringDim MyString As StringFor Each MyString In SummaryColsMyArray = MyString.Split(“,”)MyCell.ColumnNumber = Convert.ToInt32(MyArray(0))Me(MyCell) = MyDataTable.Compute(MyArray(1), “ID is null”).ToString()NextEnd IfCellValueChanged = FalseEnd Sub
Handle the MouseDown event of the DataGrid control to implement custom sortingBecause you have disabled the default sorting feature of the DataGrid control, you must perform custom sorting when a user clicks a column header. You must handle the MouseDown event of the DataGrid control to implement custom sorting.
To do this, add the following event handler after the code that you added in step 2 of the “Handle the events that are raised when a cell in the DataGrid control is changed” section:

‘ Handle the MouseDown event to perform custom sorting.Private Sub DataGridControlVB_MouseDown(ByVal sender As Object, _ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDownDim MyHitTestInfo As DataGrid.HitTestInfoMyHitTestInfo = Me.HitTest(e.X, e.Y)Dim ColName As StringIf (MyHitTestInfo.Type = DataGrid.HitTestType.ColumnHeader) ThenDim ColNum As Integer = MyHitTestInfo.ColumnIf (ColNum <> -1) ThenColName = MyDataTable.Columns(ColNum).ColumnName’ Perform custom sorting. To do this, always sort the Boolean data type column in’ ascending order so that the footer row stays at the end.Dim MyChar() As Char = {“↑”c, “↓”c}Dim NewString As String = _Me.TableStyles(0).GridColumnStyles(SortedColNum).HeaderText.TrimEnd(MyChar).Trim()Me.TableStyles(0).GridColumnStyles(SortedColNum).HeaderText = NewStringIf (Ascending = True) ThenMyDataView.Sort = “ID Asc,” + ColName + ” desc”Ascending = FalseMe.TableStyles(0).GridColumnStyles(ColNum).HeaderText = _Me.TableStyles(0).GridColumnStyles(ColNum).HeaderText + ” ↑”SortedColNum = ColNumElseMyDataView.Sort = “ID Asc,” + ColName + ” asc”Ascending = TrueMe.TableStyles(0).GridColumnStyles(ColNum).HeaderText = _Me.TableStyles(0).GridColumnStyles(ColNum).HeaderText + ” ↓”SortedColNum = ColNumEnd IfEnd IfEnd IfEnd Sub
Disable the footer row of the DataGrid controlTo disable the footer row of the DataGrid control, add the following code after the code that you added in the “Handle the MouseDown event of the DataGrid control to implement custom sorting” section:

‘ Disable the footer row of the DataGrid control.Public Sub SetEnableValues(ByVal sender As Object, ByVal e As DataGridDisableCellEventArgs)If (e.Row = RowCount – 1) Thene.EnableValue = FalseElsee.EnableValue = TrueEnd IfEnd Sub
Define an event arguments class that provides data for the DataGridDisableCell eventTo define an event arguments class that provides data for the DataGridDisableCell event, follow these steps: In the Form1.vb file, locate the following code:

End ClassAdd the following code after the code that you located in step 1:

‘ Define a custom event arguments class that inherits from the EventArgs class.Public Class DataGridDisableCellEventArgsInherits EventArgsPrivate MyCol As IntegerPrivate MyRow As IntegerPrivate MyEnableValue As BooleanPublic Sub New(ByVal Row As Integer, ByVal Col As Integer)MyRow = RowMyCol = ColMyEnableValue = TrueEnd SubPublic Property Column() As IntegerGetReturn MyColEnd GetSet(ByVal Value As Integer)MyCol = ValueEnd SetEnd PropertyPublic Property Row() As IntegerGetReturn MyRowEnd GetSet(ByVal Value As Integer)MyRow = ValueEnd SetEnd PropertyPublic Property EnableValue() As BooleanGetReturn MyEnableValueEnd GetSet(ByVal Value As Boolean)MyEnableValue = ValueEnd SetEnd PropertyEnd Class
Define a class that contains methods to paint and to disable the footer rowTo define a class that contains methods to paint and to disable the footer row, add the following code after the code that you added in step 2 of the “Define an event arguments class that provides data for the DataGridDisableCell event” section:

Public Class MyDataGridTextBoxInherits DataGridTextBoxColumn’ Declare an event for the DataGridDisableCellEventHandler delegate that you have defined.Public Event DataGridDisableCell As DataGridDisableCellEventHandlerPrivate MyCol As Integer’ Save the column number of the column to add the MyDataGridTextBox control to.Public Sub New(ByVal Column As Integer)MyCol = ColumnEnd Sub’ Override the Paint method to set colors for the footer row.Protected Overloads Overrides Sub Paint(ByVal g As System.Drawing.Graphics, _ByVal bounds As System.Drawing.Rectangle, ByVal source As System.Windows.Forms.CurrencyManager, _ByVal rowNum As Integer, ByVal backBrush As System.Drawing.Brush, _ByVal foreBrush As System.Drawing.Brush, ByVal alignToRight As Boolean)’ Initialize the event arguments by using the number’ of the current row and the current column.Dim e As New DataGridDisableCellEventArgs(rowNum, MyCol)’ Raise the DataGridDisableCell event.RaiseEvent DataGridDisableCell(Me, e)’ Set the foreground color and the background color for the footer row.If Not e.EnableValue ThenIf DataGridControlVB.FooterColor Is Nothing _Or DataGridControlVB.FooterFontColor Is Nothing ThenbackBrush = Brushes.WhiteforeBrush = Brushes.BlackElsebackBrush = DataGridControlVB.FooterColorforeBrush = DataGridControlVB.FooterFontColorEnd IfEnd If’ Call the Paint event of the DataGridTextBoxColumn class.MyBase.Paint(g, bounds, source, rowNum, backBrush, foreBrush, alignToRight)End Sub’ Override the Edit method to disable the footer row.Protected Overloads Overrides Sub Edit(ByVal source As System.Windows.Forms.CurrencyManager, _ByVal rowNum As Integer, ByVal bounds As System.Drawing.Rectangle, ByVal readOnlyFlag As Boolean, _ByVal instantText As String, ByVal cellIsVisible As Boolean)Dim e As DataGridDisableCellEventArgs = Nothing’ Initialize the event arguments by using the number’ of the current row and the current column.e = New DataGridDisableCellEventArgs(rowNum, MyCol)’ Raise the DataGridDisableCell event.RaiseEvent DataGridDisableCell(Me, e)’ Call the Edit event of the DataGridTextBoxColumn’ class for all rows other than the footer row.If e.EnableValue ThenMyBase.Edit(source, rowNum, bounds, readOnlyFlag, instantText, cellIsVisible)End IfEnd SubEnd Class
Save the DataGridControlVB.vb file, and then build the DataGrid controlOn the File menu, click Save DataGridControlVB.vb As. The Save File As dialog box appears.Click the arrow next to the Save button, and then click Save with Encoding. You receive a message to replace the existing DataGridControlVB.vb file.Click Yes. The Advanced Save Options dialog box appears.In the Encoding box, select Unicode (UTF-8 with signature) – Codepage 65001, and then click OK.On the Build menu, click Build DataGridControl to build the DataGridControl.dll assembly.
Create a Windows Application project that uses the DataGrid controlIn Solution Explorer, right-click the DataGridControl solution, point to Add, and then click New Project. The Add New Project dialog box appears.Under Project Types, click Visual Basic Projects.Under Templates, click Windows Application.In the Name box, type TestApplication, and then click OK. By default, a Windows Form that is named Form1 is created.In Solution Explorer, right-click TestApplication, and then click Set as StartUp Project.On the View menu, click Toolbox.Do one of the following, depending on the version of Visual Studio .NET that you have:If you are using Visual Studio .NET 2003, click Add/Remove Toolbox Items on the Tools menu. If you are using Visual Studio .NET 2002, click Customize Toolbox on the Tools menu.The Customize Toolbox dialog box appears.On the .NET Framework Components tab, click Browse. The Open dialog box appears.Locate and then click the DataGridControl.dll assembly that you created in step 5 of the “Save the DataGridControlVB.vb file, and then build the DataGrid control” section.Click Open, and then click OK. The DataGridControlVB control is added to the Toolbox.In the Toolbox, double-click the DataGridControlVB control to add the DataGridControlVB1 control to the Form1 form.Click Form1.On the View menu, click Properties Window to view the Properties window for the Form1 form.Set the Size property to 450, 200.In the Design view of the Form1 form, click the DataGridControlVB1 control.On the View menu, click Properties Window to view the Properties window for the DataGridControlVB1 control.Set the Size property to 420, 115.
Bind the custom DataGrid control to the related dataIn Solution Explorer, right-click Form1.vb, and then click View Code.Import the required namespaces. To do this, add the following code at the top of the code window:

Imports System.DataImports System.Data.SqlClientLocate the following code:

Public Class Form1Inherits System.Windows.Forms.FormAdd the following variable declarations after the code that you located in step 3:

Dim MyConnString As StringDim MyDataSet As DataSet = NothingDim MyDataAdapter As SqlDataAdapter = NothingDim MyConn As SqlConnectionBind the DataGrid control to the related data. To do this, add the following code after the “Windows Form Designer generated code” area.
Note In the following code, replace <ServerName> with the appropriate value for an instance of Microsoft SQL Server:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.LoadDim SqlString As String = “SELECT * FROM discounts”MyConnString = “server=<ServerName>;Integrated Security=SSPI;database=pubs”MyConn = New SqlConnection(MyConnString)MyDataAdapter = New SqlDataAdapter(SqlString, MyConn)MyDataSet = New DataSetTryMyDataAdapter.Fill(MyDataSet, “discounts”)’ Specify the dataset that you want your DataGrid control to use.DataGridControlVB1.GridDataSet = MyDataSet’ Specify the source table that you want your DataGrid control to use.DataGridControlVB1.DataSourceTable = “discounts”‘ Add the columns that you want to sum to an array list. Use the following format:’ “<ColumnNumber>,summing expression”Dim Summary As New ArrayListSummary.Add(“2,sum(lowqty)”)Summary.Add(“3,sum(highqty)”)’ Map the array list to the SummaryColumns property of your DataGrid control.DataGridControlVB1.SummaryColumns = Summary’ Set the foreground color and the background color for the footer row.DataGridControlVB1.FooterColor = Brushes.BlueVioletDataGridControlVB1.FooterFontColor = Brushes.White’ Bind the DataGrid control to the related data.DataGridControlVB1.BindDataGrid()’ Dispose the data adapter, and then close the connection.Catch DatabaseException As SqlExceptionMessageBox.Show(“Database exception: ” & DatabaseException.Message)Catch OtherException As ExceptionMessageBox.Show(OtherException.Message)FinallyMyDataAdapter.Dispose()MyConn.Dispose()End TryEnd Sub
Complete code listingDataGridControlVB.vb

Imports SystemImports System.CollectionsImports System.ComponentModelImports System.DrawingImports System.DataImports System.Data.SqlClientImports System.Windows.FormsImports System.Text’ Declare a delegate for the event that disables the cells of the DataGrid control.Public Delegate Sub DataGridDisableCellEventHandler _(ByVal sender As System.Object, ByVal e As DataGridDisableCellEventArgs)Public Class DataGridControlVBInherits System.Windows.Forms.DataGrid’ Declare private variables for your DataGrid control.Private RowCount As IntegerPrivate ColCount As IntegerPrivate SortedColNum As IntegerPrivate Ascending As BooleanPrivate CellValueChanged As BooleanPrivate SourceTable As StringPrivate MyDataView As DataViewPrivate MyDataSet As DataSetPrivate MyDataRow As DataRowPrivate SummaryCols As ArrayListPrivate CurrentDataGridCellLocation As DataGridCellPrivate WithEvents MyDataTable As DataTablePrivate Shared FooterBackColor As BrushPrivate Shared FooterForeColor As Brush#Region ” Windows Form Designer generated code “Public Sub New()MyBase.New()’This call is required by the Windows Form Designer.InitializeComponent()RowCount = 0ColCount = 0CellValueChanged = FalseAscending = FalseMyDataRow = NothingMyDataTable = New DataTable(“NewTable”)CurrentDataGridCellLocation = New DataGridCellSummaryCols = New ArrayListEnd Sub’UserControl1 overrides dispose to clean up the component list.Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)If disposing ThenIf Not (components Is Nothing) Thencomponents.Dispose()End IfEnd IfMyBase.Dispose(disposing)End Sub’Required by the Windows Form DesignerPrivate components As System.ComponentModel.IContainer’NOTE: The following procedure is required by the Windows Form Designer’It can be modified using the Windows Form Designer.’Do not modify it using the code editor.<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()components = New System.ComponentModel.ContainerEnd Sub#End RegionPublic WriteOnly Property GridDataSet() As DataSetSet(ByVal Value As DataSet)MyDataSet = ValueEnd SetEnd PropertyPublic Property SummaryColumns() As ArrayListGetReturn SummaryColsEnd GetSet(ByVal Value As ArrayList)SummaryCols = ValueEnd SetEnd PropertyPublic Property DataSourceTable() As StringGetReturn SourceTableEnd GetSet(ByVal Value As String)SourceTable = ValueEnd SetEnd PropertyPublic Shared Property FooterColor() As BrushGetReturn FooterBackColorEnd GetSet(ByVal Value As Brush)FooterBackColor = ValueEnd SetEnd PropertyPublic Shared Property FooterFontColor() As BrushGetReturn FooterForeColorEnd GetSet(ByVal Value As Brush)FooterForeColor = ValueEnd SetEnd PropertyPublic Sub BindDataGrid()MyDataTable = MyDataSet.Tables(0)MyDataView = MyDataTable.DefaultViewMe.DataSource = MyDataViewDim TableStyle As DataGridTableStyle = New DataGridTableStyleTableStyle.MappingName = SourceTable’ Add a Boolean data type column to the DataTable object.’ You can use this column during your custom sorting.MyDataTable.Columns.Add(“ID”, System.Type.GetType(“System.Boolean”))MyDataTable.Columns(“ID”).DefaultValue = FalseMyDataTable.Columns(“ID”).ColumnMapping = MappingType.HiddenColCount = MyDataTable.Columns.Count’ Create a footer row for the DataTable object.MyDataRow = MyDataTable.NewRow()’ Set the footer value as an empty string for all columns that contains string values.Dim MyIterator As IntegerFor MyIterator = 0 To ColCount – 1If (MyDataTable.Columns(MyIterator).DataType.ToString() = “System.String”) ThenMyDataRow(MyIterator) = “”End IfNext’ Add the footer row to the DataTable object.MyDataTable.Rows.Add(MyDataRow)RowCount = MyDataTable.Rows.Count’ Add a MyDataGridTextBox control to each cell of the DataGrid control.Dim TempDataGridTextBox As MyDataGridTextBoxFor MyIterator = 0 To ColCount – 2TempDataGridTextBox = New MyDataGridTextBox(MyIterator)TempDataGridTextBox.HeaderText = MyDataTable.Columns(MyIterator).ColumnNameTempDataGridTextBox.MappingName = MyDataTable.Columns(MyIterator).ColumnNameAddHandler TempDataGridTextBox.DataGridDisableCell, _New DataGridDisableCellEventHandler(AddressOf SetEnableValues)’ Disable the default sorting feature of the DataGrid control.TableStyle.AllowSorting = FalseTableStyle.GridColumnStyles.Add(TempDataGridTextBox)NextMe.TableStyles.Add(TableStyle)Me.DataSource = MyDataViewMyDataView.ApplyDefaultSort = FalseMyDataView.AllowNew = False’ Set the value of the footer cell.Dim MyCell As DataGridCell = New DataGridCellMyCell.RowNumber = MyDataTable.Rows.Count – 1′ Calculate the value for each of the cells in the footer.Dim MyArray(2) As StringDim MyString As StringFor Each MyString In SummaryColsMyArray = MyString.Split(“,”c)MyCell.ColumnNumber = Convert.ToInt32(MyArray(0))Me(MyCell) = MyDataTable.Compute(MyArray(1), “ID is null”).ToString()NextEnd Sub’ Handle the DataTable object’s ColumnChanged event’ to track if the value in a cell has changed.Private Sub MyDataTable_ColumnChanged(ByVal sender As Object, _ByVal e As System.Data.DataColumnChangeEventArgs) Handles MyDataTable.ColumnChangedDim Row As Integer, Col As IntegerRow = 0Col = 0′ Determine the row that contains the changed cell.Dim TempDataRow As DataRowFor Each TempDataRow In MyDataTable.RowsIf (TempDataRow.Equals(e.Row)) ThenCurrentDataGridCellLocation.RowNumber = RowCellValueChanged = TrueExit ForRow = Row + 1End IfNext’ Determine the column that contains the changed cell.Dim TempDataColumn As DataColumnFor Each TempDataColumn In MyDataTable.ColumnsIf (TempDataColumn.Equals(e.Column)) ThenCurrentDataGridCellLocation.ColumnNumber = ColCellValueChanged = TrueExit ForCol = Col + 1End IfNextEnd Sub’ Handle the CurrentCellChanged event of the DataGrid control.Private Sub DataGridControlVB_CurrentCellChanged(ByVal sender As Object, _ByVal e As System.EventArgs) Handles MyBase.CurrentCellChangedIf (CellValueChanged = True) ThenDim MyCell As DataGridCell = New DataGridCellMyCell.RowNumber = MyDataTable.Rows.Count – 1′ Calculate the value for each of the cells in the footer.Dim MyArray(2) As StringDim MyString As StringFor Each MyString In SummaryColsMyArray = MyString.Split(“,”)MyCell.ColumnNumber = Convert.ToInt32(MyArray(0))Me(MyCell) = MyDataTable.Compute(MyArray(1), “ID is null”).ToString()NextEnd IfCellValueChanged = FalseEnd Sub’ Handle the MouseDown event to perform custom sorting.Private Sub DataGridControlVB_MouseDown(ByVal sender As Object, _ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDownDim MyHitTestInfo As DataGrid.HitTestInfoMyHitTestInfo = Me.HitTest(e.X, e.Y)Dim ColName As StringIf (MyHitTestInfo.Type = DataGrid.HitTestType.ColumnHeader) ThenDim ColNum As Integer = MyHitTestInfo.ColumnIf (ColNum <> -1) ThenColName = MyDataTable.Columns(ColNum).ColumnName’ Perform custom sorting. To do this, always sort the Boolean data type column in’ ascending order so that the footer row stays at the end.Dim MyChar() As Char = {“↑”c, “↓”c}Dim NewString As String = _Me.TableStyles(0).GridColumnStyles(SortedColNum).HeaderText.TrimEnd(MyChar).Trim()Me.TableStyles(0).GridColumnStyles(SortedColNum).HeaderText = NewStringIf (Ascending = True) ThenMyDataView.Sort = “ID Asc,” + ColName + ” desc”Ascending = FalseMe.TableStyles(0).GridColumnStyles(ColNum).HeaderText = _Me.TableStyles(0).GridColumnStyles(ColNum).HeaderText + ” ↑”SortedColNum = ColNumElseMyDataView.Sort = “ID Asc,” + ColName + ” asc”Ascending = TrueMe.TableStyles(0).GridColumnStyles(ColNum).HeaderText = _Me.TableStyles(0).GridColumnStyles(ColNum).HeaderText + ” ↓”SortedColNum = ColNumEnd IfEnd IfEnd IfEnd Sub’ Disable the footer row of the DataGrid control.Public Sub SetEnableValues(ByVal sender As Object, ByVal e As DataGridDisableCellEventArgs)If (e.Row = RowCount – 1) Thene.EnableValue = FalseElsee.EnableValue = TrueEnd IfEnd SubEnd Class’ Define a custom event arguments class that inherits from the EventArgs class.Public Class DataGridDisableCellEventArgsInherits EventArgsPrivate MyCol As IntegerPrivate MyRow As IntegerPrivate MyEnableValue As BooleanPublic Sub New(ByVal Row As Integer, ByVal Col As Integer)MyRow = RowMyCol = ColMyEnableValue = TrueEnd SubPublic Property Column() As IntegerGetReturn MyColEnd GetSet(ByVal Value As Integer)MyCol = ValueEnd SetEnd PropertyPublic Property Row() As IntegerGetReturn MyRowEnd GetSet(ByVal Value As Integer)MyRow = ValueEnd SetEnd PropertyPublic Property EnableValue() As BooleanGetReturn MyEnableValueEnd GetSet(ByVal Value As Boolean)MyEnableValue = ValueEnd SetEnd PropertyEnd ClassPublic Class MyDataGridTextBoxInherits DataGridTextBoxColumn’ Declare an event for the DataGridDisableCellEventHandler delegate that you have defined.Public Event DataGridDisableCell As DataGridDisableCellEventHandlerPrivate MyCol As Integer’ Save the column number of the column to add the MyDataGridTextBox control to.Public Sub New(ByVal Column As Integer)MyCol = ColumnEnd Sub’ Override the Paint method to set colors for the footer row.Protected Overloads Overrides Sub Paint(ByVal g As System.Drawing.Graphics, _ByVal bounds As System.Drawing.Rectangle, ByVal source As System.Windows.Forms.CurrencyManager, _ByVal rowNum As Integer, ByVal backBrush As System.Drawing.Brush, _ByVal foreBrush As System.Drawing.Brush, ByVal alignToRight As Boolean)’ Initialize the event arguments with the number’ of the current row and the current column.Dim e As New DataGridDisableCellEventArgs(rowNum, MyCol)’ Raise the DataGridDisableCell event.RaiseEvent DataGridDisableCell(Me, e)’ Set the foreground color and the background color for the footer row.If Not e.EnableValue ThenIf DataGridControlVB.FooterColor Is Nothing _Or DataGridControlVB.FooterFontColor Is Nothing ThenbackBrush = Brushes.WhiteforeBrush = Brushes.BlackElsebackBrush = DataGridControlVB.FooterColorforeBrush = DataGridControlVB.FooterFontColorEnd IfEnd If’ Call the Paint event of the DataGridTextBoxColumn class.MyBase.Paint(g, bounds, source, rowNum, backBrush, foreBrush, alignToRight)End Sub’ Override the Edit method to disable the footer row.Protected Overloads Overrides Sub Edit(ByVal source As System.Windows.Forms.CurrencyManager, _ByVal rowNum As Integer, ByVal bounds As System.Drawing.Rectangle, ByVal readOnlyFlag As Boolean, _ByVal instantText As String, ByVal cellIsVisible As Boolean)Dim e As DataGridDisableCellEventArgs = Nothing’ Initialize the event arguments with the number’ of the current row and the current column.e = New DataGridDisableCellEventArgs(rowNum, MyCol)’ Raise the DataGridDisableCell event.RaiseEvent DataGridDisableCell(Me, e)’ Call the Edit event of the DataGridTextBoxColumn’ class for all rows other than the footer row.If e.EnableValue ThenMyBase.Edit(source, rowNum, bounds, readOnlyFlag, instantText, cellIsVisible)End IfEnd SubEnd ClassForm1.vbNote In the following code, replace <ServerName> with the appropriate value for an instance of Microsoft SQL Server.

Imports System.DataImports System.Data.SqlClientPublic Class Form1Inherits System.Windows.Forms.FormDim MyConnString As StringDim MyDataSet As DataSet = NothingDim MyDataAdapter As SqlDataAdapter = NothingDim MyConn As SqlConnection#Region ” Windows Form Designer generated code “Public Sub New()MyBase.New()’This call is required by the Windows Form Designer.InitializeComponent()’Add any initialization after the InitializeComponent() callEnd Sub’Form overrides dispose to clean up the component list.Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)If disposing ThenIf Not (components Is Nothing) Thencomponents.Dispose()End IfEnd IfMyBase.Dispose(disposing)End Sub’Required by the Windows Form DesignerPrivate components As System.ComponentModel.IContainer’NOTE: The following procedure is required by the Windows Form Designer’It can be modified using the Windows Form Designer.’Do not modify it using the code editor.Friend WithEvents DataGridControlVB1 As DataGridControl.DataGridControlVB<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()Me.DataGridControlVB1 = New DataGridControl.DataGridControlVBCType(Me.DataGridControlVB1, System.ComponentModel.ISupportInitialize).BeginInit()Me.SuspendLayout()”DataGridControlVB1′Me.DataGridControlVB1.DataMember = “”Me.DataGridControlVB1.DataSourceTable = NothingMe.DataGridControlVB1.HeaderForeColor = System.Drawing.SystemColors.ControlTextMe.DataGridControlVB1.Location = New System.Drawing.Point(0, 0)Me.DataGridControlVB1.Name = “DataGridControlVB1″Me.DataGridControlVB1.Size = New System.Drawing.Size(420, 115)Me.DataGridControlVB1.TabIndex = 0”Form1′Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)Me.ClientSize = New System.Drawing.Size(442, 173)Me.Controls.Add(Me.DataGridControlVB1)Me.Name = “Form1″Me.Text = “Form1″CType(Me.DataGridControlVB1, System.ComponentModel.ISupportInitialize).EndInit()Me.ResumeLayout(False)End Sub#End RegionPrivate Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.LoadDim SqlString As String = “SELECT * FROM discounts”MyConnString = “server=<ServerName>;Integrated Security=SSPI;database=pubs”MyConn = New SqlConnection(MyConnString)MyDataAdapter = New SqlDataAdapter(SqlString, MyConn)MyDataSet = New DataSetTryMyDataAdapter.Fill(MyDataSet, “discounts”)’ Specify the dataset that you want your DataGrid control to use.DataGridControlVB1.GridDataSet = MyDataSet’ Specify the source table that you want your DataGrid control to use.DataGridControlVB1.DataSourceTable = “discounts”‘ Add the columns that you want to sum to an array list in the following format:’ “<ColumnNumber>,summing expression”Dim Summary As New ArrayListSummary.Add(“2,sum(lowqty)”)Summary.Add(“3,sum(highqty)”)’ Map the array list to the SummaryColumns property of your DataGrid control.DataGridControlVB1.SummaryColumns = Summary’ Set the foreground color and the background color for the footer row.DataGridControlVB1.FooterColor = Brushes.BlueVioletDataGridControlVB1.FooterFontColor = Brushes.White’ Bind the DataGrid control to the related data.DataGridControlVB1.BindDataGrid()’ Dispose the data adapter, and then close the connection.Catch DatabaseException As SqlExceptionMessageBox.Show(“Database exception: ” & DatabaseException.Message)Catch OtherException As ExceptionMessageBox.Show(OtherException.Message)FinallyMyDataAdapter.Dispose()MyConn.Dispose()End TryEnd SubEnd Class
Build and then run your applicationOn the Build menu, click Build Solution.On the Debug menu, click Start.
The Form1 form appears. Your custom DataGrid control is present on the Form1 form. The footer row of the DataGrid control contains the sums of the values of the fields that you specified to sum. You cannot edit the footer row. However, when you change the value in any one of the cells, the corresponding footer cell is updated.

How To Log On to a Terminal Server Session Programmatically from Visual Basic

Symptoms
The Terminal Services ActiveX client control does not expose the ImsTscNonScriptable interface. However, this interface can be used to configure automatic log on for a Terminal Services Session programmatically, which enables the programmer to log a user on to a Terminal Services Session without receiving the Windows Logon prompt. This is demonstrated in the sample in the “More Information” section.
Resolution
To run this program, configure your Terminal Server computer as follows: Log on to the Terminal Server locally as an administrator.On the Start button, click Programs, click Administrative Tools, and then click Terminal Services Configuration.Click on Connections.In the right pane, right-click RDP-Tcp, and then choose Properties.Click on the Logon Settings tab.Deselect Always prompt for password, and then click OK.NOTE: For security reasons, Microsoft recommends that you do not implement this scenario without extreme care and a clear understanding of Microsoft Windows security.
Sample CodeStart a new Standard EXE project. Form1 is created by default.On the Project menu, click to select Components, select Microsoft Terminal Services Control(redist), and then click OK. If this control is not available, see the “References” section of this article for information on how to download and install it.Add one Terminal Services Control to Form1, making sure it is big enough to handle the display of the session.Add three Label controls, three TextBox controls, and one CommandButton control to Form1. Make sure that Lable1 and Text1 are on the same line, and that Label2, Text2, Label3, and Text3 are on the same line.Paste the following code into the General Declarations of Form1:

‘ This code only works when you set the configuration on the Server-side.’ Log on to the Terminal Server as an administrator’ Start\Programs\Administrative Tools\Terminal Services Configuration’ Click on Connections’ On the Right Pane, right-click on RDP-Tcp and choose Properties’ Click on the “Logon Settings” Tab’ Uncheck “Always prompt for password” and click OKOption ExplicitPrivate Obj As IMsTscNonScriptablePrivate Sub Form_Load()Text1.Text = “”Text2.Text = “”Text3.Text = “”Label1.Caption = “Server”Label2.Caption = “UserName”Label3.Caption = “Password”Command1.Caption = “Connect”Text3.PasswordChar = “*”End SubPrivate Sub Command1_Click()Set Obj = MsTscAx1.ObjectMsTscAx1.Server = Text1.TextMsTscAx1.UserName = Text2.TextObj.ClearTextPassword = Text3.TextMsTscAx1.ConnectEnd Sub Save the project, press the F5 key to run it, and note that after you supply your username, password, and server name, you are not prompted for a logon screen at the server. Microsoft recommends that you enlarge the Terminal Server .ocx file so that you are able to manipulate the Shut Down dialog box.

How to load an assembly at runtime that is located in a folder that is not the bin folder of the application

Symptoms
You do not have to put an assembly that an application must use at runtime in the bin folder of the application. You can put the assembly in any folder on the system, and then youcan refer to the assembly at runtime.
Resolution
This step-by-step article describes three methods that you can useto refer to the assemblies that are located in folders that are not the bin folder of the application.
RequirementsThis article assumes that you are familiar with the following topics: General familiarity with Microsoft Visual Basic .NET or Microsoft Visual Basic 2005 or with Microsoft Visual C# .NET or Microsoft Visual C# 2005General familiarity with assemblies in Visual Basic .NET or Visual Basic 2005and in Visual C# .NET or Microsoft Visual C# 2005General familiarity with .config files in Visual Basic .NET or Visual Basic 2005 and in Visual C# .NET or Microsoft Visual C# 2005The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:The Microsoft .NET FrameworkMicrosoft Visual Studio .NET or Microsoft Visual Studio 2005
Method 1: Install the assembly in the global assembly cache (GAC)The GAC is a computer-wide code cache where the common language runtime is installed. The GAC stores assemblies that you specifically designate to be shared by several applications.
Note You can only install strong-named assemblies in the GAC.
To install an assembly in the GAC, follow these steps: StartVisual Studio .NET or Visual Studio 2005. On the File menu, point to New, and then click Project.
The New Project dialog box appears.Under Project Types, click Visual Basic .NET, or click Visual C# .NET.
Note In Visual Studio 2005, click Visual Basic or click Visual C#.Under Templates, click Class Library. In the Name box, type MyAssembly1.In the Location box,type C:\Myassemblies.
By default, the Class1.vb file is created byVisual Basic .NET or Visual Basic 2005. By default, the Class1.cs file is created byVisual C# .NET or Visual C# 2005. Add the following code tothe Class1 class of the Class1.vb file or of the Class1.cs file.
Visual Basic .NET or Visual Basic 2005 code

Public Function HelloWorld() As StringReturn “From Class Library “End FunctionVisual C# .NET or Visual C# 2005 code

public string HelloWorld(){ return “From Class Library”;}On the File menu,click Save All to save the solution.Install the MyAssembly1 assembly in the GAC.
For more information about how to do this in Visual Basic .NET, click the following article number to view the article in the Microsoft Knowledge Base:
315682?(http://support.microsoft.com/kb/315682/) How to install an assembly in the global assembly cache in Visual Basic. NETFor more information bout how to do this in Visual C# .NET, click the following article number to view the article in the Microsoft Knowledge Base:
815808?(http://support.microsoft.com/kb/815808/) How to install an assembly into the global assembly cache in Visual C# .NETCreate a new client application. To do this,follow these steps:In Visual Studio .NET or Visual Studio 2005, create a new Visual Basic .NET or Visual Basic 2005 Windows application or a new Visual C# .NET or Visual C# 2005 Windows application that is named TestClient1.
By default, the Form1.vb file is created by Visual Basic .NET or Visual Basic 2005. By default,the Form1.cs file is created by Visual C# .NET or Visual C# 2005.In Solution Explorer, right-click Add Reference.
The Add Reference dialog box appears.Click Browse, locateC:\MyAssembly, click the MyAssembly1 assembly, and thenclick Open.
Note In this step, C:\MyAssembly is a placeholder for theactual location of the MyAssembly1 assembly.Add the following code to the Form1_Load event of the Form1.vb file or of the Form1.cs file as follows:
Visual Basic .NET or Visual Basic 2005 code

Dim obj1 As New MyAssembly1.Class1()MessageBox.Show(obj1.HelloWorld())Visual C# .NET or Visual C# 2005 code

MyAssembly1.Class1 obj1=new MyAssembly1.Class1();MessageBox.Show(obj1.HelloWorld());On the Debug menu, click Start to build and to run the application.
Method 2: Use an application configuration (.config) file with the <codeBase> tagsA .config file containsthe following settings:Settings that are specific to an applicationSettings that the common language runtime reads, such as the assembly binding policy settings and the remoting objects settingsSettings that the application readsThe <codeBase> tags specify where the common language runtime can find an assembly. The common language runtime applies the settings of the <codeBase> tags from the .config file.The settings of the <codeBase> tags determine the version and the location of the assembly.
To use a .config file with the <codeBase> tags to refer to the assemblies, follow these steps:Create a new Class Library project that isnamed MyAssembly2 by following steps 1 through6 of the “Method 1: Install the assembly in the global assembly cache (GAC)” section.Make the assembly strong-named.
For additional information about how to do this, click either of the article numbers that are mentioned in step 8 of the “Method 1: Install the assembly in the global assembly cache (GAC)” section.Create a new client application. To do this,follow these steps:In Visual Studio .NET or Visual Studio 2005, create a new Visual Basic .NET or Visual Basic 2005Windows application or a new Visual C# .NET or Visual C# 2005 Windows application that is named TestClient2.
By default,the Form1.vb file iscreated by Visual Basic .NET or Visual Basic 2005. By default,the Form1.cs file is created by Visual C# .NET or Visual C# 2005. In Solution Explorer, right-click Add reference.
The Add Reference dialog box appears.Click Browse, click theMyAssembly2 assembly, and then click Open.Under References, right-click MyAssembly2, and then click Properties.
The Properties window appears.In the Properties window, set the Copy Local property of the assembly to False. Add the following code to the Form1_Load event of the Form1.vb file or of the Form1.cs file as follows:
Visual Basic .NET or Visual Basic 2005 code

Dim obj2 As New MyAssembly2.Class1()MessageBox.Show(obj2.HelloWorld())Visual C# .NET or Visual C# 2005 code

MyAssembly2.Class1 obj2=new MyAssembly2.Class1();MessageBox.Show(obj2.HelloWorld());On the Build menu, click Build Solution.Find the publicKeyToken attribute number of the assembly that you created. To do this,follow these steps: At the Visual Studio .NET or Visual Studio 2005 command prompt, locate the following folder:
C:\MyAssemblies\MyAssembly2\bin\debug
Note To find the publicKeyToken attribute number, locatethe folder that containsyour compiled library assembly. Typically, this is the bin folder in your project folder that is mentioned previously in this step.Type the following command:
SN -T MyAssembly2.dll
Note You must use a capital letter “T” to obtain the correct public key.
The command returns a hexadecimal value that represents the publicKeyToken attributenumber of the assembly.To find the version number of the assembly, follow these steps: In Microsoft Windows Explorer, locate the following folder:
C:\Myassemblies\MyAssembly2\bin\debug Right-click the MyAssembly2.dll file, and then click Properties.
The Properties window appears.In the Properties window, click the Version tab.
Note The assembly version is specified in the Value section.Use the publicKeyToken attribute number and the version number to identify the correct assembly.
Note You must provide the publicKeyToken attribute number, the version number, and the path of the MyAssembly2.dll file that uses the <codeBase> tags to refer to theMyAssembly2.dll file at runtime.Adda .config file to the project. To do this,follow these steps:On the Project menu, click Add New Item.In the Add New Item dialog box, click Application configuration file under Templates. Make sure that the file name is App.config, and then click Open.Add the following code to the file:

<configuration><runtime><assemblyBinding xmlns=”urn:schemas-microsoft-com:asm.v1″><dependentAssembly><assemblyIdentity name=”MyAssembly2″culture=”neutral” publicKeyToken=”307041694a995978″/><codeBase version=”1.0.1524.23149″ href=”FILE://C:/Myassemblies/MyAssembly2.dll”/></dependentAssembly></assemblyBinding></runtime></configuration>Note The TestClient2.exe.config file is locatedin the Debug folder or in the Release folder. Both of these folders are locatedin the bin folder. The solution configuration mode that you select determines the location of the TestClient2.exe.config file.Make the following changes in the <assemblyIdentity> tags: Change the name attribute to the name of your library assembly.Change the publicKeyToken attribute to the public key that you determined in step 4 of this section.Make the following changes in the <codeBase> tags: Change the version attribute to the version number of the assembly that you determined in step 5 of this section.Change the href attribute to the path where the DLL is located.On the Debug menu, click Start to build the project,and thenrun the application.
Method 3: Use the AssemblyResolve eventThe AssemblyResolve event fires whenever the common language runtime tries to bind to an assembly and fails. You can use the AddHandler method to add an event handler to the application that returns the correct assembly whenever the AssemblyResolve event fires.
The AssemblyResolve event handler must return an [Assembly] object, and the common language runtime must bind to this object. Typically, you can use the Assembly.LoadFrom method to load the assembly and then to return the object. To do this, follow these steps: Create a new Class Library project that is named MyAssembly3 by following steps 1 through7 of the “Method 1: Install the assembly in the global assembly cache (GAC)” section.Create a new client application. To do this,follow these steps:In Visual Studio .NET or Visual Studio 2005, create a new Visual Basic .NET or Visual Basic 2005 Windows application or create a new Visual C# .NET or Visual C# 2005 Windows application that is named TestClient3.
By default, the Form1.vb file is created by Visual Basic .NET or Visual Basic 2005. By default, the Form1.cs fileis created by Visual C# .NET or Visual C# 2005.Add a Button control to the Form1.vb file or to the Form1.cs file.Double-click the Button1 control, and then add the following code to the Button1_Click event:
Visual Basic .NET or Visual Basic 2005 code

Dim obj3 As New MyAssembly3.Class1()MessageBox.Show(obj3.HelloWorld())Visual C# .NET or Visual C# 2005 code

MyAssembly3.Class1 obj3=new MyAssembly3.Class1();MessageBox.Show(obj3.HelloWorld()); In Solution Explorer, right-click Add reference.
The Add Reference dialog box appears.Click Browse, click the MyAssembly3 assembly, and then click Open.In the References folder, right-click the MyAssembly3 assembly, and then click Properties.
The Properties window appears.In the Properties window, set the Copy Local property of the assembly to False.Add an event handler to the AssemblyResolve event in the Form1_Load event as follows:
Visual Basic .NET or Visual Basic 2005 code

AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf MyResolveEventHandlerVisual C# .NET or Visual C# 2005 code

AppDomain currentDomain = AppDomain.CurrentDomain;currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);Define the MyResolveEventHandler function as follows:
Visual Basic .NET or Visual Basic 2005 code

Function MyResolveEventHandler(ByVal sender As Object, _ByVal args As ResolveEventArgs) As [Assembly]‘This handler is called only when the common language runtime tries to bind to the assembly and fails.’Retrieve the list of referenced assemblies in an array of AssemblyName.Dim objExecutingAssemblies As [Assembly]objExecutingAssemblies = [Assembly].GetExecutingAssembly()Dim arrReferencedAssmbNames() As AssemblyNamearrReferencedAssmbNames = objExecutingAssemblies.GetReferencedAssemblies()’Loop through the array of referenced assembly names.Dim strAssmbName As AssemblyNameFor Each strAssmbName In arrReferencedAssmbNames’Look for the assembly names that have raised the “AssemblyResolve” event.If (strAssmbName.FullName.Substring(0, strAssmbName.FullName.IndexOf(“,”)) = args.Name.Substring(0, args.Name.IndexOf(“,”))) Then’Build the path of the assembly from where it has to be loaded.Dim strTempAssmbPath As StringstrTempAssmbPath = “C:\assemblies\” & args.Name.Substring(0, args.Name.IndexOf(“,”)) & “.dll” Dim MyAssembly as [Assembly]‘Load the assembly from the specified path.MyAssembly = [Assembly].LoadFrom(strTempAssmbPath)’Return the loaded assembly.Return MyAssemblyEnd IfNextEnd FunctionVisual C# .NET or Visual C# 2005 code

private Assembly MyResolveEventHandler(object sender,ResolveEventArgs args){ //This handler is called only when the common language runtime tries to bind to the assembly and fails. //Retrieve the list of referenced assemblies in an array of AssemblyName. Assembly MyAssembly,objExecutingAssemblies; string strTempAssmbPath=”"; objExecutingAssemblies=Assembly.GetExecutingAssembly(); AssemblyName [] arrReferencedAssmbNames=objExecutingAssemblies.GetReferencedAssemblies(); //Loop through the array of referenced assembly names. foreach(AssemblyName strAssmbName in arrReferencedAssmbNames) { //Check for the assembly names that have raised the “AssemblyResolve” event. if(strAssmbName.FullName.Substring(0, strAssmbName.FullName.IndexOf(“,”))==args.Name.Substring(0, args.Name.IndexOf(“,”))) { //Build the path of the assembly from where it has to be loaded. strTempAssmbPath=”C:\\Myassemblies\\”+args.Name.Substring(0,args.Name.IndexOf(“,”))+”.dll”; break; } } //Load the assembly from the specified path. MyAssembly = Assembly.LoadFrom(strTempAssmbPath); //Return the loaded assembly. return MyAssembly; }On the Debug menu, click Start to run the application.
Note You must import the System.Reflection namespace to run this application.Click Button1 to call the HelloWorld() method of the MyAssembly3 assembly.

How to consume assemblies that are located in a folder that is different from the application base folder in Visual Basic .NET or in Visual Basic 2005

Symptoms
This article discusses how to consume assemblies that are located in a folder than is different from the application base folder in a Microsoft Visual Basic .NET or Microsoft Visual Basic 2005 solution.
Resolution
When you run a Visual Basic .NET or Visual Basic 2005 application, the common language runtime (CLR) expects to locate any assemblies that the application uses in either the global assembly cache or the application folder. When the CLR does not successfully bind to an assembly, you receive an error message that is similar to the following:

System.IO.FileNotFoundException. File or assembly name AssemblyName, or one of its dependencies, was not found. You can use many methods to locate an assembly that is located in a different folder. This article describes the following three methods.
Method 1: Install the assemblies in the global assembly cacheThis method requires that you sign an assembly with a strong name. To sign an assembly with a strong name and to then install the assembly in the global assembly cache, follow these steps: Name an assembly by using a strong name. To do this, follow these steps: Use the Strong Name tool (Sn.exe) that is included with the Microsoft .NET Framework software development kit (SDK) to generate a cryptographic key pair.
At the Microsoft Visual Studio .NET or Microsoft Visual Studio 2005 Command Prompt, type the following command:
sn -k AssemblyName.snk This command generates and stores a key pair in a file that is named AssemblyName.snk.Include the following assembly-level attribute in the source code (AssemblyInfo.vb):

<Assembly: AssemblyKeyFile(“AssemblyName.snk”)>Use the Global Assembly Cache Tool (Gacutil.exe) to register the .NET Framework assembly in the global assembly cache. To do this, type the following command at the Visual Studio .NET Command Prompt:
gacutil /i AssemblyName.dllFor more information about how to work with assemblies and with the global assembly cache, visit the following Microsoft Developer Network (MSDN) Web site:
http://msdn2.microsoft.com/en-us/library/6axd4fx6(vs.71).aspx(http://msdn2.microsoft.com/en-us/library/6axd4fx6(vs.71).aspx)For more information about how to sign an assembly with a strong name, visit the following MSDN Web site:
http://msdn2.microsoft.com/en-us/library/xc31ft41(vs.71).aspx(http://msdn2.microsoft.com/en-us/library/xc31ft41(vs.71).aspx)Note This method may be difficult and time-consuming if many assemblies exist and if the assemblies have dependencies on Microsoft Component Object Model (COM) objects. Any assembly dependencies must also be discoverable by the CLR. Therefore, if you plan to install your assembly to the global assembly cache, also install the dependencies of the assembly into the global assembly cache.
Method 2: Use an Application.Config file together with the CodeBase tagBy using an application configuration file, you can specify the location at which the CLR should look for dependent assemblies. Specifically, use the Codebase tag. By using this tag, you can put your assemblies in a separate folder. However, this method still requires that you name the library assembly by using a strong name. To use the application configuration file, follow these steps: Compile your library assembly.Sign the assembly by using a strong name.From your main application, add a reference to your library assembly, and then compile the main application.Obtain the public key token from your strongly named library assembly. To do this, follow these steps: Click Start, click All Programs, and then click Microsoft Visual Studio .NET 2003.
Note In Visual Studio 2005, click Start, click All Programs, and then click Microsoft Visual Studio 2005.Click Visual Studio .NET Tools, and then click Visual Studio .NET 2003 Command Prompt.
Note In Visual Studio 2005, click Visual Studio 2005 Tools, and then click Visual Studio .NET 2005 Command Prompt.Change the directory to the location of your library assembly. Typically, the location is the Bin folder of your library assembly project.Type the following command, and then press ENTER:
SN -T MyLibrary.dllNote Replace MyLibrary with the name of your library assembly. To make sure that the correct value is returned, make sure that you use an uppercase T in the -T switch.This command returns a hexadecimal value that represents the token for the public key of your library assembly. Make a copy of the hexadecimal value that will be used in the application configuration file.Obtain the assembly version from your strongly named library assembly. To obtain the assembly version, use one of the following methods:Method A: Windows Explorer file propertiesIn Windows Explorer, right-click your library assembly, and then click Properties.In the Properties dialog box, click the Version tab.Under Other version Information, click Assembly Version. Make a copy of this version value that will be used in the application configuration file.Method B: MSIL Disassembler (ILDASM)At the Visual Studio .NET 2003 Command Prompt, type ILDASM, and then press ENTER.On the File menu, click Open.Click your custom assembly, and then click Open.In the bottom pane, locate the assembly version (.ver). The following is an example of the assembly version:

.assembly yourAssemblyName{.ver 1:0:1969:29451}Note In this example, the assembly version is 1.0.1969.29541.Create an application configuration file. To do this, follow these steps: Paste the following XML code in Notepad:

<configuration><runtime><assemblyBinding xmlns=”urn:schemas-microsoft-com:asm.v1″><dependentAssembly><assemblyIdentity name=”MyLibrary”culture=”neutral”publicKeyToken=”fa4e781ae585ee8a”/><codeBase version=”1.0.1074.32347″ href=”FILE://C:/assemblies/myLibrary.dll”/></dependentAssembly></assemblyBinding></runtime></configuration>Change the following XML element attributes.
Collapse this tableExpand this table
Element attributeMake this changeassemblyIdentity nameChange MyLibrary to the name of your library assembly.assemblyIdentity publicKeyTokenChange the publicKeyToken attribute to the public key token value that you copied in step 4.codeBase versionChange the version attribute to the version value that you copied in step 5.codeBase hrefChange the href attribute to point to the full path name and the file name of your library assembly.Save the file as the main assembly .exe file name. Use .config as the file name extension. For example, if your main assembly is named “MyProject.exe,” the application configuration file name is “MyProject.exe.config.” You must save this file in the same folder in which your main application assembly is located.For more information, visit the following MSDN Web sites:
Specifying an assembly’s location
http://msdn2.microsoft.com/en-us/library/4191fzwb(vs.71).aspx(http://msdn2.microsoft.com/en-us/library/4191fzwb(vs.71).aspx)
<codeBase> element
http://msdn2.microsoft.com/en-us/library/efs781xb(vs.71).aspx(http://msdn2.microsoft.com/en-us/library/efs781xb(vs.71).aspx)
How the runtime locates assemblies
http://msdn2.microsoft.com/en-us/library/yx7xezcf(vs.71).aspx(http://msdn2.microsoft.com/en-us/library/yx7xezcf(vs.71).aspx)
Method 3: Use the System.Reflection.Assembly.LoadFrommethodThis method uses the Assembly.LoadFrom method to explicitly load an assembly from a fully qualified path name and from a fully qualified file name. To do this, follow these steps: Compile your library assembly.Use code that is similar to the following code example to load your assembly:

Dim yourAssembly As System.Reflection.Assembly = _System.Reflection.Assembly.LoadFrom(“c:\yourAssembly.dll”)Note If you have any dependent assemblies, you should locate them in the same path where the main assembly is located.
For more information about the Assembly.LoadFrom method, visit the following MSDN Web site:
http://msdn2.microsoft.com/en-us/library/system.reflection.assembly.loadfrom(vs.71).aspx(http://msdn2.microsoft.com/en-us/library/system.reflection.assembly.loadfrom(vs.71).aspx)
Method 4: Use the AssemblyResolve eventThe AssemblyResolve event occurs whenever the CLR unsuccessfully tries to bind to an assembly. Use the AddHandler method in the application to add an event handler that returns the correct assembly whenever the AssemblyResolve event occurs.
Note This method does not require that you name the assemblies by using strong names.
The AssemblyResolve event handler must return an [Assembly] object that represents the assembly to which the CLR must bind. Typically you can use the Assembly.LoadFrom method to load the assembly. Then, return the loaded assembly.
Note The event handler must be located in a procedure that does not contain any references to the relocated assemblies. Additionally, the event handler must be called before any code that depends on the relocated assemblies is called.
The following code is an example of an application that loads an assembly by using the AssemblyResolve event:

Module Module1Sub Main()Dim f As Form1′Set up event handler for AssemblyResolve eventAddHandler AppDomain.CurrentDomain.AssemblyResolve, _AddressOf MyResolveEventHandlerf = New Form1()Application.Run(f)End SubFunction MyResolveEventHandler(ByVal sender As Object, _ByVal args As ResolveEventArgs) As [Assembly]‘Load the assembly from the correct location and return the assembly’This handler is only called if we try to bind to the assembly and the attempt fails.Dim MyAssembly As [Assembly]MyAssembly = [Assembly].LoadFrom(“C:\assemblies\MyLibrary.dll”)Return MyAssemblyEnd FunctionEnd Module’Some sample code in Form1 which depends on the external assemblyPrivate Sub Button1_Click(ByVal sender As System.Object, _ByVal e As System.EventArgs) Handles Button1.ClickDim x As MyLibrary.Applicationx = New MyLibrary.Application()x.MyMethod()End SubEnd ClassFor more information about the AppDomain.AssemblyResolve event, visit the following MSDN Web site:
http://msdn2.microsoft.com/en-us/library/system.appdomain.assemblyresolve(vs.71).aspx(http://msdn2.microsoft.com/en-us/library/system.appdomain.assemblyresolve(vs.71).aspx)

How To Configure Posting Acceptor to Work with the Package and Deployment Wizard

Symptoms
The Visual Basic Package and Deployment Wizard (PDW) uses a technologynamed the Posting Acceptor to manage the transfer of your Visual Basicapplications to a Web server. Posting Acceptor is a component that is located on the Microsoft Internet Information Server (IIS) Web server. You can use Posting Acceptor to post the content to the server.Before you can successfully post your applications, you must installPosting Acceptor and configure the Web server correctly.
This article walks you through the basic configuration and presentstroubleshooting information for some of the more common problems that you may experience when you post Visual Basic applications to the Web.
Resolution
Steps in the Web Deployment ProcessWhen you post a Visual Basic application to a Web server by using the Package and Deployment Wizard, you first use the packaging portion of the wizard to package your applications into one or more .cab files. Then, you use the deployment portion of the wizard to transfer your files to the appropriate location.
IMPORTANT: Make sure that you have administrator-level rights to the Web server to which you are posting content.
The Web server goes through these steps during deployment:It extracts the .cab file into a temporary directory.It locates the .inf file for the .cab file.Based on the contents of the .inf file, it installs application files (based on the RInstallApplicationFiles section of the .inf file), system files (based on the RIinstallSystemFiles section), and shared files (based on the RInstallSharedFiles section). In the process, the server registers any necessary files.NOTE: The DefaultInstall section of the .inf file is not run because the instructions it contains often require user input. Additionally, the posting process does not create a virtual directory for your application if one is required; directories must be set up in advance.
Installing Posting AcceptorYou must install Posting Acceptor on any server to which you want to postapplications by using the Visual Basic Package and Deployment Wizard. There are multiple versions of Posting Acceptor. You must make sure you install the correct version based on your server’s configuration:Posting Acceptor 2.0 Windows NT 4.0 with Service Pack 3 (SP3)IIS 4.0 Posting Acceptor 2.0 supports both content posting and the unpacking of cabinet (.cab) files on the server.Posting Acceptor 1.1 Windows NT 4.0 with SP3 IIS 3.0 You cannot unpack .cab files with this version of Posting Acceptor. Use this version to post content only. You can move your files to the server and then manually register any necessary files that the .cab process would have registered.NOTE: Posting Acceptor does not work on any platforms that are usingPersonal Web Server or Peer Web Server. You must use IIS.
Posting Acceptor is no longer available as a separate download. To obtain Posting Acceptor, you can install the Microsoft Windows NT 4.0 Option Pack, which is available from the following Microsoft Web site:
Windows NT 4.0 Option Pack
http://technet.microsoft.com/en-us/library/cc767904.aspx(http://technet.microsoft.com/en-us/library/cc767904.aspx)Installing Posting Acceptor 2.0Start Microsoft Visual Studio or Visual Basic setup from your installation CDs.When you are prompted to choose options to install, click Install Server Applications and Tools, and then click Next.Click Launch the BackOffice Installation Wizard, and then click Install.Click Custom, and then click Next.You will see the options to install and their sizes. Click Next.Click Microsoft Posting Acceptor 2.0.NOTE: If you want to install Posting Acceptor 2.0 on a computer thatalready has the Windows NT Option Pack, you should first check to see ifversion 1.0 of the Posting Acceptor is already installed. If so, remove this version before you install version 2.0.Determine If Posting Acceptor 1.0 Is InstalledIn Control Panel, click Add/Remove Programs.In the Install\Uninstall pane, click NT Option Pack.Click Add/Remove, and then look for Posting Acceptor 1.0 in the component list. You may find Posting Acceptor 1.0 under Microsoft Site Server. If Posting Acceptor 1.0 is installed, remove it.
Configuring the ServerYou must perform the following steps on the Web server to which you want todeploy your packaged Visual Basic applications. To configure your IIS server, follow these steps:Install Microsoft Internet Information Server (IIS) from the NT Option Pack.Follow the steps in the previous procedure to install Posting Acceptor 2.0.Click Start, point to Programs, point to Windows NT 4.0 Options Pack, point to Microsoft Internet Information Server, and then click Internet Service Manager.In the left panel of the manager, make sure that the Console Root node is expanded, and then expand the Internet Information Server node. Your IIS server or servers are listed under this folder.Expand the IIS server that you want to configure. You will see a number of nodes, including a node named Default Web Site.Right-click the Default Web Site node, and then click Properties.In the Default Web Site Properties dialog box, click the Home Directory tab, and then make sure that the Write option is selected.Click Apply. The Inheritance Overrides dialog box may appear, which contains a list of folders to which the setting you just made should apply. Select only those folders to which you want users to be able to deploy packages, and then click OK until you return to the manager.NOTE: Granting write access to a virtual directory is a security RISK. Make sure that you only grant write access to virtual directories that you know are secure.In the left panel, right-click the SCRIPTS node that appears under the Default Web Site node, and then click Properties.Click the Virtual Directory tab, make sure that the Execute (including script) button is selected, and then click OK.
Configuring the Client ComputerVisual Studio installs and configures all the components that you need to deploy applications from your development computer. However, if you are running Visual Studio on a computer that is on an intranet and you connect through a proxy server, you must configure Microsoft Internet Explorer 4.0 to bypass the proxy server for local addresses.
To configure your development computer, follow these steps:On your Windows desktop, right-click the Internet Explorer icon, and then click Properties.In the Properties dialog box, click the Connection tab.In the Proxy Server area, make sure that the Bypass proxy server for local (Intranet) addresses check box is selected if the Access the Internet using a proxyserver check box is selected. Click OK.
Troubleshooting Web Deployment from Visual BasicThe following sections list some of the more common problems that you mayencounter when you try to post applications to the server by using the Package and Deployment Wizard.General TipsYou should have administrator-level rights to the Web server to which you are posting content.If you receive an error that files are busy during the posting process, you should reboot your server rather than just stopping and restarting the service. After you reboot, you can try to post again. In general, it is a good idea to reboot the server as part of your troubleshooting process.Problem: Your Server Does Not Have Visual Basic InstalledIf your Web server does not have a copy of the Visual Basic 6.0 runtimeDLL installed and other system files such as:Msvbvm60.dllOleaut32.dllOlepro32.dllAsycfilt.dllStdole2.tlbComcat.dllMswcrun.dll is needed for IIS Applications (WebClass Designer runtime)Mshtmpgr.dll is needed for DHTML Applications (DHTML Page Designer run-time)You may encounter problems when you try to post an application toit the first time. In this case, the server may not be able to correctly install the necessary system files.
There are several things that you can do about this:
Install a copy of Visual Basic on the server, and then use the wizard to post your application again.Create a standard setup package with the Package and Deployment Wizard instead of an Internet package. You can then move the Setup.exe file to the server and install the program on the server. This installs the necessary system files. After the installation process, reboot your server.You can download the .cab files for the above-needed system files from the Microsoft site. You must install and register these files on the server. You may need to reboot the server after this process.NOTE: This procedure only applies to the first installation of a Visual Basic application on such a server; all subsequent installations can be posted with the Web deployment feature of the wizard.Problem: Cab File Is Copied to Web Server But Is Not UnpackedIf the .cab file that you are deploying is copied to the server but is notunpacked, make sure that:You included the .cab file on the Items to Deploy page of the wizard.You used HTTP Post as the protocol on the Web Publishing Site page of the wizard.You selected the Unpack and Install Server-Side Cab check box on the Web Publishing Site page of the wizard. If you did not, try to redeploy your package with this option selected.NOTE: Only Posting Acceptor 2.0 running on IIS 4.0 supports .cab file unpacking. If you are running Posting Acceptor 1.0, you cannot unpack the file during deployment.Problem: Web Server Does Not Support the Selected Service ProviderThere are several things you can do to try to fix this problem:If you are using the HTTP Post protocol, make sure that Posting Acceptor is installed on your Web server.Make sure that your URL is correct. If you are using HTTP Post, make sure that your URL begins with http://. If you are using FTP, make sure that your URL begins with ftp://.If you are uploading to a server that has Posting Acceptor 1.0 installed, you cannot select the option to unpack and install your cabinet files when you use the wizard to deploy your package. In this case, deploy your .cab file again, and make sure that you click to clear the Unpack and Install Server-Side Cab check box.Problem: Need Write Access to the Web ServerIf you use the HTTP Post protocol and receive an error that you do not havewrite access for the Web server, you must change the access permissions foryour Web server.
To set Write access, follow these steps:On the server computer, click Start, point to Programs, point to Windows NT 4.0 Options Pack, point to Microsoft Internet Information Server, and then click Internet Service Manager.Expand the Console Root and the Internet Information Server nodes, and then expand the node for your Web server computer.Right-click the Default Web Site node, and then click Properties.Click the Home Directory tab, and then click to select the Write check box.NOTE: Granting write access to a virtual directory is a security risk. Make sure that you only grant write access to the virtual directories that you know are secure.Problem: Error c0042116, or Processing Has StoppedIf your files are read-only when you try to post, you receive an errorC0042116, which states that processing has stopped. Use File Explorer tochange your file attributes, and then continue with your posting process.Problem: FTP Protocol ProblemsWith the Package and Deployment Wizard, you can post content by using the HTTP or the FTP protocol. If you use FTP, you may encounter thefollowing issues:
If you receive an error that access is denied, follow these steps:On the server computer, click Start, point to Programs, point to Windows NT 4.0 Options Pack, point to Microsoft Internet Information Server, and then click Internet Service Manager.Expand the Console Root and the Internet Information Server nodes, and then expand the node for your Web server computer.Right-click the Default Web Site node, and then click Properties.Click the Home Directory tab, and then click to select the Write check box.NOTE: Granting write access to a virtual directory is a security risk. Make sure that you only grant write access to the virtual directories that you know are secure.
If you use the FTP protocol and receive additional errors besides the one that is described in the previous bullet, make sure that you have properly configured your FTP service on the Web server. To do so, start the Microsoft Management Console (MMC), and then follow these steps:Right-click Default FTP Site, and then click New Virtual Directory.Type an alias to be used to access the virtual directory, and then click Next.Type the physical path of the directory to which to map the virtual directory. For example, C:\Inetpub\Ftproot, and then click Next.Select the appropriate access permissions, making sure to grant writeaccess so that your deployments can proceed without errors, and thenclick Finish.Right-click Default FTP Site, and then click Stop.Right-click Default FTP Site and then click Start.When you deploy to the FTP server by using the Package and Deployment Wizard, use the site FTP://servername/alias format, where alias is the alias that you assigned in step 2. Use the username “anonymous” and the password “me@somewhere” for anonymous login.Problem: Incorrect ParameterIf you receive an error that states that a parameter is incorrect, you may need to take one of the following actions:Make sure that you have typed a valid URL to the Web server that you have chosen to use.On the Web server, search for files named Default.asp and Default.htm in the \Inetpub\wwwroot directory. Open both files, and make sure that they have the following code at the top of the file:

<META name=”postinfo” content=”/scripts/postinfo.asp”>

BUG: You receive a “Microsoft.VisualBasic.CompilerServices.LateBinding.InternalLateCall” error message when you make a late-bound call in Visual Basic .NET

Symptoms
When you make a late-bound call in Microsoft Visual Basic .NET, the late-binding support fails when the ByRef decimal is converted to ByRef currency. You receive the following error message:

Unhandled Exception: System.Runtime.InteropServices.COMException (0×80020005): Type mismatch. at Microsoft.VisualBasic.CompilerServices.LateBinding.InternalLateCall(Object o, Type objType, String name, Object[] args, String[] paramnames, Boolean[] CopyBack, Boolean IgnoreReturn) at Microsoft.VisualBasic.CompilerServices.LateBinding.LateCall(Object o, Type objType, String name, Object[] args, String[] paramnames, Boolean[] CopyBack) at ConsoleApplication2.Module1.main() in C:\ConsoleApplication\Module.vb:line number
Press any key to continueNote In this error message, C:\ConsoleApplication\Module.vb:line number is a placeholder for the actual path where the application is saved. In the application module, line number represents the line where the error occurs.
Resolution
To work around this bug, use either of the following options: Use the CurrencyWrapper type.Force the decimal value to be passed by using the ByVal keyword.
To do this, put parentheses around the variable that contains the decimal value.To implement either of these workaround options, create a DLL by using Visual Basic 6.0, create a console application, and reference the DLL in the console application, as follows:Create a DLL by using Visual Basic 6.0Start Visual Basic 6.0.On the File menu, click New Project.
The New Project dialog box appears.Click ActiveX DLL, and then click OK.
By default, the Class1 class is created.Add the following code to the Class1 class:

Public Function cedrbank(name As String, ACCNUM As String, ACCBAL As Currency) As LongMsgBox ACCBALACCBAL = 4.321End FunctionOn the File menu, click Save Class1.cls, and then click Save Project As.In the File name box, type the name of the project.On the File menu, click Make Project.dll.
The Make Project dialog box appears.
Note Project is a placeholder for the actual name of the project.Click OK.Create a console applicationStart Visual Studio .NET.On the File menu, point to New, and then click Project.
The New Project dialog box appears.Under Project Types, click Visual Basic Projects.Under Templates, click Console Application.Click OK.
By default, the Module1.vb module is created.Replace the existing code in the Module1.vb module with the following code:

Imports SystemImports System.Runtime.InteropServicesImports System.ReflectionImports Project1Public Module Module1Sub Main()Dim x As Objectx = New Class1Dim dc As Object = New CurrencyWrapper(5)Dim d As Decimal = 1.987Dim args(2) As Objectargs(0) = “name”args(1) = “num”args(2) = dcDim c(0) As Reflection.ParameterModifierc(0) = New Reflection.ParameterModifier(3)c(0).Item(0) = Truec(0).Item(1) = Truec(0).Item(2) = TrueCObj(x).GetType().InvokeMember(“cedrbank”, BindingFlags.InvokeMethod, Nothing, x, args, c, Nothing, Nothing)Console.WriteLine(args(2))dc = New CurrencyWrapper(6)’Use the CurrencyWrapper type.x.cedrbank(“name”, “num”, dc)Console.WriteLine(dc)’Force ‘d’ to be passed ByVal by using parentheses around ‘d.’x.cedrbank(“name”, “num”, (d))Console.WriteLine(d)End SubEnd ModuleAdd a reference to the DLL that you created in the “Create a DLL by using Visual Basic 6.0″ section of this article.On the Build menu, click Build Solution.On the Debug menu, click Start.
You do not receive the error message that is mentioned in the “Symptoms” section of this article.