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 for January, 2010

How to enumerate the running processes of an application by using Visual Basic .NET or Visual Basic 2005

Symptoms
A process is the running instance of an application. A thread is the basicunit of a process. To retrieve information that corresponds to processes that are running on a local computer or on a remote computer, use the following methods:The GetProcesses() method retrieves information aboutthe processes that are running on a local computer. This method creates an array of process components and then associates the processesthat are running with these process components. The GetProcesses() method never returns an empty array.The GetProcesses(String) method retrieves information about the processes that are running on a local computer or on a remote computer. You must pass the computer name or the computer Internet Protocol(IP) address to the GetProcesses(String) method to retrieve the processes that are running on a remote computer. Also, you must have administrative rights on theremote computer to retrieve the processes that are running on that computer.
Resolution
This step-by-step article describes how to enumerate running instances of applications by using Microsoft Visual Basic .NET.

RequirementsThis article assumes that you are familiar with the following topics: Microsoft Visual Basic .NET or Microsoft Visual Basic 2005 programming
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 2003. Microsoft Visual Studio .NET 2002, Microsoft Visual Studio .NET 2003, or Microsoft Visual Studio 2005.
Process definitionA process is the running instance of an application. A thread is the basic unit of a process. The operating system allocates processor time to a thread so that thethread can run any part of the process code. A process can create one or more threads to run any part of the code that is associated with the process.
You can use a process component to start, to stop, to control, and to monitor a process. You can use aprocess component to obtain the list of processes that are running on a computer. After you initialize a process component, you can obtain informationabout the set of threads, about the loaded modules, and about the performance forall the running processes. You can also obtain information about processes that are running on a remote computer.

The GetProcesses methodYou can use the GetProcesses method to obtain information about the processes that are running on local computers and on remote computers. This method creates an array of new process components and then associates these components with the existing process resources. The two overloaded versions of this method are as follows:The GetProcesses() method
The GetProcesses() method creates an array of new process components and associates the components with all the process resources that are on the local computer. The process resources must already exist on the local computer. This method does not create process resources. Instead, this method associates existing resources with application-generated process components. Because the operating system itself is constantly running background processes, this array is never empty.The GetProcesses(String) method
The GetProcesses(String) method accepts a string as a parameter. Typically, the string is the computer name or the IP address of a remote computer. However, you can pass a period (.) to this method to retrieve the list of processes that are running on your local computer. To retrieve information about the processes that are running on a remote computer, you must have administrative rights to map a network drive to a folder on the remote computer.
Step-by-step sampleNote You must have administrative rights on the remote computer to follow these steps.Start Visual 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 Projects.
Note In Visual Studio 2005, clickVisual Basic under Project Types. Under Templates, click Windows Application.In the Name box,type ProcessInfo, and then click OK.
By default, the Form1.vb file is created.Replace the existing code in the Form1.vb file with the following code:

Option Strict OnPublic Class Form1Inherits System.Windows.Forms.Form#Region ” Windows Form Designer generated code “Public Sub New()MyBase.New()’The Windows Form Designer requires this call.InitializeComponent()’Add any initialization after the InitializeComponent() call.End 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 Designer.Private components As System.ComponentModel.IContainer’NOTE: The Windows Form Designer requires the following procedure.’It can be modified by using the Windows Form Designer.’Do not modify the procedure by using the Code editor.Friend WithEvents Button1 As System.Windows.Forms.ButtonFriend WithEvents TextBox1 As System.Windows.Forms.TextBoxFriend WithEvents Label1 As System.Windows.Forms.LabelFriend WithEvents ListView1 As System.Windows.Forms.ListViewFriend WithEvents Button2 As System.Windows.Forms.ButtonFriend WithEvents process1 As System.Windows.Forms.ColumnHeaderFriend WithEvents Process2 As System.Windows.Forms.ColumnHeaderFriend WithEvents PageMemorySize As System.Windows.Forms.ColumnHeader<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()Me.Button1 = New System.Windows.Forms.Button()Me.TextBox1 = New System.Windows.Forms.TextBox()Me.Label1 = New System.Windows.Forms.Label()Me.ListView1 = New System.Windows.Forms.ListView()Me.Button2 = New System.Windows.Forms.Button()Me.SuspendLayout()”Button1′Me.Button1.Location = New System.Drawing.Point(8, 368)Me.Button1.Name = “Button1″Me.Button1.Size = New System.Drawing.Size(72, 32)Me.Button1.TabIndex = 1Me.Button1.Text = “Get Processes””TextBox1′Me.TextBox1.Location = New System.Drawing.Point(272, 368)Me.TextBox1.Name = “TextBox1″Me.TextBox1.Size = New System.Drawing.Size(160, 20)Me.TextBox1.TabIndex = 5Me.TextBox1.Text = “””Label1′Me.Label1.Location = New System.Drawing.Point(160, 376)Me.Label1.Name = “Label1″Me.Label1.Size = New System.Drawing.Size(112, 23)Me.Label1.TabIndex = 7Me.Label1.Text = “Remote Computer IP””ListView1′Me.ListView1.ImeMode = System.Windows.Forms.ImeMode.OnMe.ListView1.Location = New System.Drawing.Point(32, 32)Me.ListView1.Name = “ListView1″Me.ListView1.Size = New System.Drawing.Size(360, 288)Me.ListView1.TabIndex = 8Me.ListView1.View = System.Windows.Forms.View.DetailsMe.ListView1.Columns.Add(“Process”, 100, HorizontalAlignment.Left)Me.ListView1.Columns.Add(“ProcessID”, 150, HorizontalAlignment.Left)Me.ListView1.Columns.Add(“Page Memory Size”, 110, HorizontalAlignment.Left)”Button2′Me.Button2.Location = New System.Drawing.Point(88, 368)Me.Button2.Name = “Button2″Me.Button2.Size = New System.Drawing.Size(64, 32)Me.Button2.TabIndex = 9Me.Button2.Text = “Clear””Form1′Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)Me.ClientSize = New System.Drawing.Size(440, 422)Me.Controls.Add(Me.Button2)Me.Controls.Add(Me.ListView1)Me.Controls.Add(Me.Label1)Me.Controls.Add(Me.TextBox1)Me.Controls.Add(Me.Button1)Me.Name = “Form1″Me.Text = “Form1″Me.ResumeLayout(False)End Sub#End RegionDim Processes As Process()Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.ClickTryDim myprocess As ProcessDim compName As String = TextBox1.TextIf compName = “.” ThenProcesses = process.GetProcesses()ElseProcesses = process.GetProcesses(compName)End IfDim proclength As IntegerFor proclength = 0 To Processes.Length – 1myprocess = Processes(proclength)Dim process(2) As Stringprocess(0) = myprocess.ProcessNameprocess(1) = myprocess.Id.ToString()process(2) = myprocess.PagedMemorySize.ToString()Dim process_Listview As ListViewItem = New ListViewItem(process)ListView1.Items.Add(process_Listview)NextCatch ex As ExceptionMessageBox.Show(ex.Message())End TryEnd SubPrivate Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.ClickListView1.Items.Clear()End SubEnd ClassNote You must change the code in Visual Basic 2005. By default, Visual Basic creates two files for the project when you create a Windows Forms project. If the form is named Form1, the two files that represent the form are named Form1.vb and Form1.Designer.vb. You write the code in the Form1.vb file. The Windows Forms Designer writes the code in the Form1.Designer.vb file. The Windows Forms Designer uses the partial keyword to divide the implementation of Form1 into two separate files. This behavior prevents the designer-generated code from being interspersed with your code.
For more information about the new Visual Basic 2005 language enhancements, visit the following Microsoft Developer Network (MSDN) Web site:
http://msdn2.microsoft.com/en-us/library/ms379584(vs.80).aspx(http://msdn2.microsoft.com/en-us/library/ms379584(vs.80).aspx)For more information about partial classes and the Windows Forms Designer, visit the following MSDN Web site:
http://msdn2.microsoft.com/en-us/library/ms171843.aspx(http://msdn2.microsoft.com/en-us/library/ms171843.aspx)On the Build menu, click Build Solution.Switch to Visual Studio .NET or Visual Studio 2005, and then press F5 to run your application.
The Form1 Windows form appears.Click Get Processes.
Notice the list of processes that are running on your local computer.Click Clear.In the Remote Computer IP box, type the IP address of the remote computer, and then click Get Processes. You will get the processes that are running on the remote computer.

How To Enumerate Connected Sites & Servers in Exchange with ADSI

Symptoms
The following sample code in Visual Basic illustrates using ADSI LDAP provider objects to enumerate all the connected sites and servers in an Exchange organization. In order to use this code, you must have at least one Exchange 5.5 server in your connected sites.You should also have the latest ADSI client runtime (version 2.0 or better) installed on your system.
Resolution
Steps to Reproduce BehaviorOpen a new Standard EXE Visual Basic Project.Add a Module.Make a reference to the Active DS Type Library.Set the Startup Object to Sub Main.Copy and paste the following sample code into the Module:

‘ Sample to enumerate sites and servers in an Exchange Organization’ using ADSi objectsOption ExplicitSub Main()Dim objOrg As IADsContainerDim objOU As IADsContainerDim objConfig As IADsContainerDim objServers As IADsContainerDim obj As IADs’ Replace “Server” with the name of any Exchange 5.5 server in one of’ the connected sites you want to enumerate.Set objOrg = GetObject(“LDAP://Server”)Debug.Print objOrg.Name’ filter passes organizationalUnit and any classes derived from it’ such as View-RootobjOrg.Filter = Array(“organizationalUnit”)For Each objOU In objOrgWith objOU’ Test that the most derived class is organizationalUnitIf objOU.Class = “organizationalUnit” ThenDebug.Print “Site: ” + .NameobjOU.Filter = Array(“Container”)For Each objConfig In objOUWith objConfig’ Test for cn=Configuration (root container)If .Name = “cn=Configuration” Then’ In case configuration might have non-containers.Filter = Array(“Container”)For Each objServers In objConfigWith objServers’ Test for cn=Servers inside of Configuration containerIf .Name = “cn=Servers” Then.Filter = Array(“Computer”)For Each obj In objServersWith objDebug.Print Chr(9) & “Server: ” & .NameDebug.Print Chr(9) & “ADsPath: “; .ADsPathEnd WithNext objEnd IfEnd WithNext objServersEnd IfEnd WithNext objConfigEnd IfEnd WithNext objOUDebug.Print “End Enumeration“End Sub

How To DAO: Attach to and Create QueryDefs on ODBC Tables

Symptoms
This article describes how to attach and create Querydefs on external ODBCtables. The method for opening external ODBC tables is to attach the tablesto an .mdb file.
Jet does not support named QueryDefs on a non-attached ODBC database. A non-attached ODBC database is one that is opened directly with the OpenDatabasemethod of the WorkSpace object without the use of an .mdb file.
If it is not appropriate for the application to attach the ODBC tables, itis possible to create Querydefs with no name to accomplish the procedure.
For additional information, please see the following article in theMicrosoft Knowledge Base:
149055?(http://support.microsoft.com/kb/149055/EN-US/): Jet Doesn’t Support QueryDefs on a Non-Attached ODBC Table
Resolution
The following is information from “Guide To Data Access Objects,” Chapter7, Data Access Choices, that explains this procedure:
In many cases, attaching a table to access external data is faster thanopening a table directly, especially if the data is located in an ODBCdatabase. In Visual Basic version 4.0, SQL Passthrough is used to queryattached ODBC databases directly. Consider attaching external tables ratherthan opening them directly. Using external data in an ODBC databaserequires opening the external tables directly so performance issignificantly slower when using the data.
Sample ProgramThe following example describes how to attach to and create a Querydef onan ODBC table using a “DSN-less” ODBC connection. With this procedure, itis not necessary to set up a DSN with the ODBC Admin utility.
Start a new project in Visual Basic. Form1 is created by default.Add three Command buttons to Form1: Command1, Command2, Command3 bydefault.Paste the following code in the General Declarations section of Form1:

Dim db As DatabaseDim cn As StringPrivate Sub Form_Load()cn = “odbc;driver={SQL Server};server=myserver;” & _”database=pubs;uid=myuid;pwd=mypwd”If Dir(“mydb.mdb”) <> “” Then’ database exists, so just open it.Set db = OpenDatabase(Name:=”mydb”, Exclusive:=False, _ReadOnly:=False, Connect:=”")Else’database does not exist, create it and attach authors table.Set db = CreateDatabase(Name:=”mydb”, Connect:=dbLangGeneral, _Option:=dbVersion30)Dim td As TableDefSet td = db.CreateTableDef()td.Name = “Authors”td.SourceTableName = “Authors”td.Connect = cnEnd IfEnd SubPrivate Sub Command1_Click()Dim qd As QueryDefOn Error Resume NextSet qd = db.QueryDefs(“abc”)’ test for existence of querydef.If Error > 0 ThenSet qd = db.CreateQueryDef(Name:=”abc”)qd.Connect = cnqd.SQL = “Select @@Version” ‘native SQL ServerEnd IfSet qd = db.QueryDefs(“xyz”)’ test for existence of querydef.If Error > 0 ThenSet qd = db.CreateQueryDef(Name:=”xyz”)qd.Connect = cnqd.SQL = “Select * from titles” ‘ generic SQL.End IfOn Error GoTo 0End SubPrivate Sub Command2_Click()Dim rs As RecordsetDim qd As QueryDefSet qd = db.QueryDefs(“abc”)Set rs = qd.OpenRecordset()Call displayResults(rs)End SubPrivate Sub Command3_Click()Dim rs As RecordsetDim qd As QueryDefSet qd = db.QueryDefs(“xyz”)Set rs = qd.OpenRecordset()Call displayResults(rs)End SubSub displayResults(rs As Recordset)Dim f As Field, s As String, i As IntegerFor Each f In rs.Fieldss = s & f.NameNext fDebug.Print s’ print column headers.While Not rs.EOF And i < 5s = “”For Each f In rs.Fieldss = s & f.ValueNext fDebug.Print s’ print first 5 rows.rs.MoveNexti = i + 1WendEnd Sub NOTE: You need to change the DRIVER, SERVER, DATABASE, UID, and PWDparameters in the OpenConnection method. Also you must modify the SQLstatements contained in the Command1_Click event to match your SQL datasource.
Press the F5 key to start the program.Click the Command1 button to create the Querydefs. Click the Command2and Command3 buttons to execute the Querydefs. Note that the first fiverows of data appear in the Debug window.

How to enable the “Option Strict” and “Option Explicit” statements in Visual Basic applications

Symptoms
This article describes how to enable the Option Strict and Option Explicit statements in Microsoft Visual Basic applications for code-behind files and files that are contained in the App_Code folder.
Resolution
To enable the Option Strict and Option Explicit statements in the code-behind files and files that are contained in the App_Code folder of a Visual Basic application, override the compiler configuration in the system.codedom section of the Web.config file for the application. To do this, add the following code to the Web.config file:

<system.codedom> <compilers> <compiler language=”c#;cs;csharp” extension=”.cs” type=”Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089″ warningLevel=”0″/> <compiler language=”vb;vbs;visualbasic;vbscript” extension=”.vb” type=”Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089″ warningLevel=”0″ /> </compilers> </system.codedom>

How to call the EnumJobs function from a Visual Basic .NET application

Symptoms
The EnumJobs function is available in the Winspool.drv print spool interface. You can use the EnumJobs function to retrieve the status of the jobs that are queued in a local print queue. The EnumJobs function enumerates the number of jobs, the job identification, the job status, and other parameters based on your requirements.
When you try to print any document, the print job is queued in the local print queue until the printer performs that job. The port monitor communicates with the printer to obtain information about a print job and then communicates the information to the local print queue. Therefore, you can monitor the local print queue to retrieve the status of your print job.
The local print queue accepts any number of jobs, even if the printer hardware is in an error state. Therefore, the Ready state of the print queue does not determine whether the job will print.Many statuses are available to report. However, many of them are not supported. The printer hardware and the port monitor determine the status that appears.
Resolution
This step-by-step article describes how to use Microsoft Windows API functions in Microsoft Visual Basic .NET to determine the printer status or the print job status programmatically. Although an application does not typically have to examine the status of a printer before the printer prints, it may be useful to determine the status of a printer or a print job programmatically.

Technical descriptionThe following information will help you use the sample application to obtain information about your printer status: The term printer refers to a hardware device, a queue, a driver, or a port. Here, the term printer status refers to the status of a local print queue.The sample code in the “Step-by-step sample” section returns the status that the operating system reports. This is the same status that the spooler reports. You can verify this status by monitoring the local print queue. The application continuously monitors the printer status.
To view the local print queue on a computer that is running the Microsoft Windows XP operating system, follow these steps: Click Start, point to Settings, and then click Printers and Faxes.In the Printers and Faxes window, double-click the icon for the printer whose queue you want to view. You cannot communicate directly with the physical printer. We recommend that you do not do this because the operating system controls access to the hardware. The “Step-by-step sample” section examines the local print queue that obtains the information from the port monitor.The port monitor communicates with the physical device. The sample code in the “Step-by-step sample” section reports the printer status and the job statuses.The queue is considered to be in a Ready state because it can accept jobs, even if the hardware is in an error state. For example, if the last job that printed used the last sheet of paper, the operating system cannot determine that the printer is out of paper until the system tries to print again.Although many statuses can be reported, many statuses are not supported in practice. The printer hardware and the port monitor determine the status to report. For example, if the printer is out of paper and is offline, the status may be reported as Printing because that is what the job is trying to do. Therefore, regardless of whether a local print queue displays the Ready status, the print job may not be completed successfully.The sample code in the “Step-by-step sample” section examines only the local print queue. This information may be sufficient for most applications. However, when you connect to remote printers, the process to obtain sufficient information may become complex. You may have a chain of print queues, and the port for the local print queue may be another queue. You may also use printer pooling. In printer pooling, multiple printers work from a common super queue. When the architecture becomes more complex, the code to retrieve a meaningful status also becomes more complex, and the usefulness of the status is reduced.
Step-by-step sampleStart Microsoft 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 Application.In the Name box, type PrinterStatus, and then click OK. By default, a form that is named Form1 is created.On the Project menu, click Add Module. The Add New Item – PrinterStatus dialog box appears. Under Templates, click Module, and then click Open. By default, a file that is named Module1.vb is created.In the Module1.vb file, replace the existing code with the following sample code.

Option Explicit On Imports System.Drawing.Printing.PrinterSettingsImports System.Runtime.InteropServicesModule Module1Public Class WINAPIDeclare Auto Function GetPrinter Lib “winspool.drv” (ByVal hPrinter As _IntPtr, ByVal Level As Integer, ByRef pPrinter As Byte, ByVal cbBuf _As Integer, ByRef pcbNeeded As Integer) As BooleanDeclare Auto Function lstrcpy Lib “Kernel32.Lib” Alias “lstrcpyA” _(<OutAttribute(), MarshalAs(UnmanagedType.LPStr)> ByVal lpString1 As String, _<MarshalAs(UnmanagedType.LPStr)> ByVal lpString2 As String) As LongDeclare Auto Function ClosePrinter Lib “winspool.drv” Alias “ClosePrinter” (ByVal hPrinter As IntPtr) As LongPublic Declare Function EnumJobs Lib “winspool.drv” Alias “EnumJobsA” _(ByVal hPrinter As IntPtr, _ByVal FirstJob As Int32, _ByVal NoJobs As Int32, _ByVal Level As Int32, _ByVal pJob As Byte(), _ByVal cdBuf As Int32, _ByRef pcbNeeded As Int32, _ByRef pcReturned As Int32) _As LongDeclare Function OpenPrinter Lib “winspool.drv” Alias “OpenPrinterA” (ByVal pPrinterName As String, _ByRef phPrinter As IntPtr, ByVal pDefault As PRINTER_DEFAULTS) As LongEnd Class’Constants for the PRINTER_DEFAULTS structurePublic Const PRINTER_ACCESS_USE = &H8Public Const PRINTER_ACCESS_ADMINISTER = &H4′Constants for the DEVMODE structurePublic Const CCHDEVICENAME = 32Public Const CCHFORMNAME = 32Public API As New WINAPI<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> Structure SYSTEMTIMEPublic wYear As ShortPublic wMonth As ShortPublic wDayOfWeek As ShortPublic wDay As ShortPublic wHour As ShortPublic wMinute As ShortPublic wSecond As ShortPublic wMilliseconds As ShortEnd Structure<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> Structure JOB_INFO_2Public PrinterJobId As IntegerPublic pPrinterName As IntegerPublic PrinterName As IntegerPublic PrinterUserName As IntegerPublic PrinterDocument As IntegerPublic PrinterNotifyName As IntegerPublic PrinterDatatype As IntegerPublic PrintProcessor As IntegerPublic PrinterParameters As IntegerPublic PrinterDriverName As IntegerPublic PrinterDevMode As IntegerPublic PrinterStatus As IntegerPublic PrinterSecurityDescriptor As IntegerPublic pStatus As IntegerPublic PrinterPriority As IntegerPublic Position As IntegerPublic StartTime As IntegerPublic UntilTime As IntegerPublic TotalPages As IntegerPublic Size As IntegerPublic Submitted As SYSTEMTIMEPublic time As IntegerPublic PagesPrinted As IntegerEnd Structure<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> Structure PRINTER_INFO_2Public pServerName As IntegerPublic pPrinterName As IntegerPublic pShareName As IntegerPublic pPortName As IntegerPublic pDriverName As IntegerPublic pComment As IntegerPublic pLocation As IntegerPublic pDevMode As IntegerPublic pSepFile As IntegerPublic pPrintProcessor As IntegerPublic pDatatype As IntegerPublic pParameters As IntegerPublic pSecurityDescriptor As IntegerPublic Attributes As IntegerPublic Priority As IntegerPublic DefaultPriority As IntegerPublic StartTime As IntegerPublic UntilTime As IntegerPublic Status As IntegerPublic cJobs As IntegerPublic AveragePPM As IntegerEnd StructurePublic Function Pointer_to_String(ByVal Add As Long) As StringDim Temp_var As StringTemp_var = New String(CChar(“”), 512)Dim x As Longx = API.lstrcpy(Temp_var, Add)If (InStr(1, Temp_var, Chr(0)) = 0) ThenPointer_to_String = “”ElsePointer_to_String = Left(Temp_var, InStr(1, Temp_var, Chr(0)) – 1)End IfEnd FunctionPublic Function DatatoDeserial(ByVal datas() As Byte, ByVal type_to_change As Type, _ByVal NumJub As Long) As Object’Returns the size of the JOB_INFO_2 structureDim Data_to_Size As Long = Marshal.SizeOf(type_to_change)If Data_to_Size > datas.Length ThenReturn NothingEnd IfDim buffer As IntPtr = Marshal.AllocHGlobal(Data_to_Size)Dim startindex As LongDim i As IntegerFor i = 0 To NumJub – 1If i = 0 Thenstartindex = 0Elsestartindex = startindex + Data_to_SizeEnd IfNext’Copy data from the datas array to the unmanaged memory pointer.Marshal.Copy(datas, startindex, buffer, Data_to_Size)’Marshal data from the buffer pointer to a managed object.Dim result_obj As Object = Marshal.PtrToStructure(buffer, type_to_change)’Free the memory that is allocated from the unmanaged memory.Marshal.FreeHGlobal(buffer)Return result_objEnd Function<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _Structure PRINTER_DEFAULTSPublic pDatatype As StringPublic pDevMode As LongPublic DesiredAccess As LongEnd Structure’Define the printer status constants.Public Const ERROR_INSUFFICIENT_BUFFER = 122Public Const PRINTER_STATUS_BUSY = &H200Public Const PRINTER_STATUS_DOOR_OPEN = &H400000Public Const PRINTER_STATUS_ERROR = &H2Public Const PRINTER_STATUS_INITIALIZING = &H8000Public Const PRINTER_STATUS_IO_ACTIVE = &H100Public Const PRINTER_STATUS_MANUAL_FEED = &H20Public Const PRINTER_STATUS_NO_TONER = &H40000Public Const PRINTER_STATUS_NOT_AVAILABLE = &H1000Public Const PRINTER_STATUS_OFFLINE = &H80Public Const PRINTER_STATUS_OUT_OF_MEMORY = &H200000Public Const PRINTER_STATUS_OUTPUT_BIN_FULL = &H800Public Const PRINTER_STATUS_PAGE_PUNT = &H80000Public Const PRINTER_STATUS_PAPER_JAM = &H8Public Const PRINTER_STATUS_PAPER_OUT = &H10Public Const PRINTER_STATUS_PAPER_PROBLEM = &H40Public Const PRINTER_STATUS_PAUSED = &H1Public Const PRINTER_STATUS_PENDING_DELETION = &H4Public Const PRINTER_STATUS_PRINTING = &H400Public Const PRINTER_STATUS_PROCESSING = &H4000Public Const PRINTER_STATUS_TONER_LOW = &H20000Public Const PRINTER_STATUS_USER_INTERVENTION = &H100000Public Const PRINTER_STATUS_WAITING = &H2000Public Const PRINTER_STATUS_WARMING_UP = &H10000′Define the job status constants.Public Const JOB_STATUS_PAUSED = &H1Public Const JOB_STATUS_ERROR = &H2Public Const JOB_STATUS_DELETING = &H4Public Const JOB_STATUS_SPOOLING = &H8Public Const JOB_STATUS_PRINTING = &H10Public Const JOB_STATUS_OFFLINE = &H20Public Const JOB_STATUS_PAPEROUT = &H40Public Const JOB_STATUS_PRINTED = &H80Public Const JOB_STATUS_DELETED = &H100Public Const JOB_STATUS_BLOCKED_DEVQ = &H200Public Const JOB_STATUS_USER_INTERVENTION = &H400Public Const JOB_STATUS_RESTART = &H800Public Function GetString(ByVal PtrStr As Long) As StringDim StrBuff As StringStrBuff = New String(CChar(“”), 256)’Determine if a zero address is used.If PtrStr = 0 ThenGetString = ” “Exit FunctionEnd If’Copy data from PtrStr to the buffer.Dim PtrInt As IntPtr = New IntPtr(PtrStr)StrBuff = Marshal.PtrToStringAuto(PtrInt)’Remove any trailing nulls from the string.GetString = StripNulls(StrBuff)End FunctionPublic Function StripNulls(ByVal OriginalStr As String) As String’Remove any trailing nulls from the input string.If (InStr(OriginalStr, Chr(0)) > 0) ThenOriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) – 1)End If’Return the modified string.StripNulls = OriginalStrEnd FunctionPublic Function CheckPrinterStatus(ByVal PI2Status As Long) As StringDim tempStr As StringIf PI2Status = 0 Then’ Return the “Ready” status.CheckPrinterStatus = “Printer Status = Ready” & vbCrLfElsetempStr = “”‘Determine the printer state.If (PI2Status And PRINTER_STATUS_BUSY) ThentempStr = tempStr & “Busy”End IfIf (PI2Status And PRINTER_STATUS_DOOR_OPEN) ThentempStr = tempStr & “Printer Door Open”End IfIf (PI2Status And PRINTER_STATUS_ERROR) ThentempStr = tempStr & “Printer Error”End IfIf (PI2Status And PRINTER_STATUS_INITIALIZING) ThentempStr = tempStr & “Initializing”End IfIf (PI2Status And PRINTER_STATUS_IO_ACTIVE) ThentempStr = tempStr & “I/O Active”End IfIf (PI2Status And PRINTER_STATUS_MANUAL_FEED) ThentempStr = tempStr & “Manual Feed”End IfIf (PI2Status And PRINTER_STATUS_NO_TONER) ThentempStr = tempStr & “No Toner”End IfIf (PI2Status And PRINTER_STATUS_NOT_AVAILABLE) ThentempStr = tempStr & “Not Available”End IfIf (PI2Status And PRINTER_STATUS_OFFLINE) ThentempStr = tempStr & “Off Line”End IfIf (PI2Status And PRINTER_STATUS_OUT_OF_MEMORY) ThentempStr = tempStr & “Out of Memory”End IfIf (PI2Status And PRINTER_STATUS_OUTPUT_BIN_FULL) ThentempStr = tempStr & “Output Bin Full”End IfIf (PI2Status And PRINTER_STATUS_PAGE_PUNT) ThentempStr = tempStr & “Page Punt”End IfIf (PI2Status And PRINTER_STATUS_PAPER_JAM) ThentempStr = tempStr & “Paper Jam”End IfIf (PI2Status And PRINTER_STATUS_PAPER_OUT) ThentempStr = tempStr & “Paper Out”End IfIf (PI2Status And PRINTER_STATUS_OUTPUT_BIN_FULL) ThentempStr = tempStr & “Output Bin Full”End IfIf (PI2Status And PRINTER_STATUS_PAPER_PROBLEM) ThentempStr = tempStr & “Page Problem”End IfIf (PI2Status And PRINTER_STATUS_PAUSED) ThentempStr = tempStr & “Paused”End IfIf (PI2Status And PRINTER_STATUS_PENDING_DELETION) ThentempStr = tempStr & “Pending Deletion”End IfIf (PI2Status And PRINTER_STATUS_PRINTING) ThentempStr = tempStr & “Printing”End IfIf (PI2Status And PRINTER_STATUS_PROCESSING) ThentempStr = tempStr & “Processing”End IfIf (PI2Status And PRINTER_STATUS_TONER_LOW) ThentempStr = tempStr & “Toner Low”End IfIf (PI2Status And PRINTER_STATUS_USER_INTERVENTION) ThentempStr = tempStr & “User Intervention”End IfIf (PI2Status And PRINTER_STATUS_WAITING) ThentempStr = tempStr & “Waiting”End IfIf (PI2Status And PRINTER_STATUS_WARMING_UP) ThentempStr = tempStr & “Warming Up”End IfIf Len(tempStr) = 0 ThentempStr = “Unknown Status of ” & PI2StatusEnd If’Return the status.CheckPrinterStatus = “Printer Status = ” & tempStr & vbCrLfEnd IfEnd FunctionEnd ModuleIn Solution Explorer, right-click the Form1.vb file, and then click View Code.In the Form1.vb file, replace the existing code with the following sample code.

Imports System.Diagnostics.DebugImports System.Drawing.PrintingImports System.Runtime.InteropServicesPublic Class Form1Inherits System.Windows.Forms.Form#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 TextBox1 As System.Windows.Forms.TextBoxFriend WithEvents TextBox2 As System.Windows.Forms.TextBoxFriend WithEvents Command1 As System.Windows.Forms.ButtonFriend WithEvents Command2 As System.Windows.Forms.ButtonFriend WithEvents Command3 As System.Windows.Forms.ButtonFriend WithEvents Timer1 As System.Windows.Forms.TimerFriend WithEvents TextBox3 As System.Windows.Forms.TextBox<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()Me.components = New System.ComponentModel.ContainerMe.Command1 = New System.Windows.Forms.ButtonMe.Command2 = New System.Windows.Forms.ButtonMe.Command3 = New System.Windows.Forms.ButtonMe.TextBox1 = New System.Windows.Forms.TextBoxMe.TextBox2 = New System.Windows.Forms.TextBoxMe.Timer1 = New System.Windows.Forms.Timer(Me.components)Me.TextBox3 = New System.Windows.Forms.TextBoxMe.SuspendLayout()”Command1′Me.Command1.Location = New System.Drawing.Point(352, 24)Me.Command1.Name = “Command1″Me.Command1.Size = New System.Drawing.Size(136, 23)Me.Command1.TabIndex = 0Me.Command1.Text = “Button1″”Command2′Me.Command2.Location = New System.Drawing.Point(360, 112)Me.Command2.Name = “Command2″Me.Command2.Size = New System.Drawing.Size(128, 23)Me.Command2.TabIndex = 1Me.Command2.Text = “Button2″”Command3′Me.Command3.Location = New System.Drawing.Point(360, 224)Me.Command3.Name = “Command3″Me.Command3.Size = New System.Drawing.Size(128, 23)Me.Command3.TabIndex = 2Me.Command3.Text = “Button3″”TextBox1′Me.TextBox1.Location = New System.Drawing.Point(8, 24)Me.TextBox1.Multiline = TrueMe.TextBox1.Name = “TextBox1″Me.TextBox1.Size = New System.Drawing.Size(320, 80)Me.TextBox1.TabIndex = 3Me.TextBox1.Text = “TextBox1″”TextBox2′Me.TextBox2.Location = New System.Drawing.Point(8, 120)Me.TextBox2.Multiline = TrueMe.TextBox2.Name = “TextBox2″Me.TextBox2.Size = New System.Drawing.Size(320, 80)Me.TextBox2.TabIndex = 4Me.TextBox2.Text = “TextBox2″”Timer1′Me.Timer1.Enabled = True”TextBox3′Me.TextBox3.Location = New System.Drawing.Point(8, 216)Me.TextBox3.Multiline = TrueMe.TextBox3.Name = “TextBox3″Me.TextBox3.ScrollBars = System.Windows.Forms.ScrollBars.VerticalMe.TextBox3.Size = New System.Drawing.Size(320, 80)Me.TextBox3.TabIndex = 5Me.TextBox3.Text = “TextBox3″”Form1′Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)Me.ClientSize = New System.Drawing.Size(504, 317)Me.Controls.Add(Me.TextBox3)Me.Controls.Add(Me.TextBox2)Me.Controls.Add(Me.TextBox1)Me.Controls.Add(Me.Command3)Me.Controls.Add(Me.Command2)Me.Controls.Add(Me.Command1)Me.Name = “Form1″Me.Text = “Form1″Me.ResumeLayout(False)End Sub#End RegionPublic Shared Sub main()Dim PrntInfo As New Form1PrntInfo.ShowDialog()End SubPrivate Sub Command1_Click(ByVal sender As System.Object, _ByVal e As System.EventArgs) Handles Command1.Click’Enable the timer to start printer status checks.Timer1.Enabled = TrueTimer1.Start()’Enable and disable the start and stop buttons.Command1.Enabled = FalseCommand2.Enabled = TrueCommand3.Enabled = TrueEnd SubPrivate Sub Command2_Click(ByVal sender As System.Object, _ByVal e As System.EventArgs) Handles Command2.Click’Disable the timer to stop additional printer checks.Timer1.Enabled = False’Enable and disable the start and stop buttons.Command1.Enabled = TrueCommand2.Enabled = FalseCommand3.Enabled = TrueAPI = NothingEnd SubPrivate Sub Command3_Click(ByVal sender As System.Object, _ByVal e As System.EventArgs) Handles Command3.Click’Clear the text boxes to display the printer status.TextBox1.Text = “”TextBox2.Text = “”TextBox3.Text = “”End SubPrivate Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) _Handles MyBase.Load’Initialize captions for the buttons.Command1.Text = “Start”Command2.Text = “Stop”Command3.Text = “Clear”‘Clear the text boxes to display the printer status.TextBox1.Text = “”TextBox2.Text = “”TextBox3.Text = “”Command1.Enabled = True’Disable the stop and clear buttons.Command2.Enabled = FalseCommand3.Enabled = False’Set the timer interval to 500 milliseconds to examine the printer status.Timer1.Enabled = FalseTimer1.Interval = 500End SubPrivate Sub Timer1_Tick(ByVal sender As System.Object, _ByVal e As System.EventArgs) Handles Timer1.TickDim PrinterStatus As StringDim JobStatus As StringDim ErrorInfo As String’Clear the text boxes to display the status.TextBox1.Text = “”TextBox2.Text = “”TextBox3.Text = “”‘Call the CheckPrinter function.TextBox1.Text = CheckPrinter(PrinterStatus, JobStatus)TextBox2.Text = PrinterStatusTextBox3.Text = JobStatusEnd SubPublic Function CheckPrinter(ByRef PrinterStr As String, _ByRef JobStr As String) As StringDim hPrinter As IntPtrDim ByteBuf As LongDim BytesNeeded As Int32Dim PI2 As New PRINTER_INFO_2Dim intCount As LongDim JI2(intCount) As JOB_INFO_2Dim PrinterInfo() As ByteDim JobInfo() As ByteDim result As LongDim LastError As LongDim PrinterName As StringDim tempStr As StringDim NumJI2 As Int32Dim pDefaults As PRINTER_DEFAULTS’Set a default return value if no errors occur.CheckPrinter = “Printer info retrieved!”Dim PD As New PrintDocumentPrinterName = PD.PrinterSettings.PrinterName’Set the access security setting that you want.pDefaults.DesiredAccess = PRINTER_ACCESS_USE’Call the API to obtain a handle to the printer.’If an error occurs, display the error.result = API.OpenPrinter(PrinterName, hPrinter, pDefaults)If result = 0 ThenCheckPrinter = “Cannot open printer ” & PrinterName & _”, Error: ” & Marshal.GetLastWin32Error()Exit FunctionEnd If’Initialize the BytesNeeded variable.BytesNeeded = 0′Clear the error object.Err.Clear()’Determine the buffer size that is required to obtain the printer information.result = API.GetPrinter(hPrinter, 2, 0&, 0, BytesNeeded)’Display the error message that you receive when you call the GetPrinter function,’and then close the printer handle.If Marshal.GetLastWin32Error() <> ERROR_INSUFFICIENT_BUFFER ThenCheckPrinter = ” > GetPrinter Failed on initial call! <”API.ClosePrinter(hPrinter)Exit FunctionEnd IfReDim PrinterInfo(BytesNeeded)ByteBuf = BytesNeeded’Call the GetPrinter function to obtain the status.result = API.GetPrinter(hPrinter, 2, PrinterInfo(0), ByteBuf, _BytesNeeded)’Check for any errors.If result = 0 Then’Get the error.LastError = Marshal.GetLastWin32Error()’Display the error message, and then close the printer handle.CheckPrinter = “Could not get Printer Status!Error = ” _& LastErrorAPI.ClosePrinter(hPrinter)Exit FunctionEnd If’Copy the contents of the printer status byte array into a’PRINTER_INFO_2 structure.PI2 = CType(DatatoDeserial(PrinterInfo, GetType(PRINTER_INFO_2), 1), PRINTER_INFO_2)PrinterStr = CheckPrinterStatus(PI2.Status)’Add the printer name, the driver, and the port to the text box.PrinterStr = PrinterStr & “Printer Name = ” & _GetString(PI2.pPrinterName) & vbCrLfPrinterStr = PrinterStr & “Printer Driver Name = ” & _GetString(PI2.pDriverName) & vbCrLfPrinterStr = PrinterStr & “Printer Port Name = ” & _GetString(PI2.pPortName) & vbCrLf’Call the API to obtain the buffer size that is required.result = API.EnumJobs(hPrinter, 0, &HFFFFFFFF, 2, JobInfo, 0, BytesNeeded, NumJI2)If result = 0 Then’Display the error, and then close the printer handle.LastError = Marshal.GetLastWin32Error()CheckPrinter = ” > EnumJobs Failed on initial call! <Error = ” _& LastErrorAPI.ClosePrinter(hPrinter)Exit FunctionEnd If’If no current jobs exist, display the message.If BytesNeeded = 0 ThenJobStr = “No Print Jobs!”Else’Resize the byte array to hold information about the print jobs.ReDim JobInfo(BytesNeeded – 1)’Call the API to obtain the print job information.result = API.EnumJobs(hPrinter, 0, &HFFFFFFFF, 2, JobInfo, _BytesNeeded, BytesNeeded, NumJI2)’Check for errors.If result = 0 Then’Display the error, and then close the printer handle.LastError = Marshal.GetLastWin32Error()CheckPrinter = ” > EnumJobs Failed on second call! <Error = ” _& LastErrorAPI.ClosePrinter(hPrinter)Exit FunctionEnd IfReDim JI2(NumJI2)’Copy the contents of print job info byte array into a’JOB_INFO_2 structure.TryFor intCount = 0 To NumJI2 – 1 ‘ Loop through jobs and obtain the job information.Dim test As ObjectJI2(intCount) = CType(DatatoDeserial(JobInfo, _GetType(JOB_INFO_2), intCount + 1), JOB_INFO_2)JobStr = JobStr & “Job ID = ” & JI2(intCount).PrinterJobId & _vbCrLf & “Total Pages = ” & JI2(intCount).TotalPages & vbCrLftempStr = “”‘Check for a ready state.If JI2(intCount).pStatus = 0& Then’ If pStatus is Null, check Status.If JI2(intCount).pStatus = 0 ThentempStr = tempStr & “Ready!” & vbCrLfElse’Check for the various print job states.If (JI2(intCount).pStatus And JOB_STATUS_SPOOLING) ThentempStr = tempStr & “Spooling”End IfIf (JI2(intCount).pStatus And JOB_STATUS_OFFLINE) ThentempStr = tempStr & “Off line”End IfIf (JI2(intCount).pStatus And JOB_STATUS_PAUSED) ThentempStr = tempStr & “Paused”End IfIf (JI2(intCount).pStatus And JOB_STATUS_ERROR) ThentempStr = tempStr & “Error”End IfIf (JI2(intCount).pStatus And JOB_STATUS_PAPEROUT) ThentempStr = tempStr & “Paper Out”End IfIf (JI2(intCount).pStatus And JOB_STATUS_PRINTING) ThentempStr = tempStr & “Printing”End IfIf (JI2(intCount).pStatus And JOB_STATUS_USER_INTERVENTION) ThentempStr = tempStr & “User Intervention Needed”End IfIf Len(tempStr) = 0 ThentempStr = “Unknown Status of ” & JI2(intCount).PrinterStatusEnd IfEnd IfElsetempStr = Pointer_to_String(JI2(intCount).pStatus)End If’Report the job status.JobStr = JobStr & tempStr & vbCrLfNext intCountCatch ex As ExceptionMessageBox.Show(ex.Message)End TryEnd If’Close the printer handle.API.ClosePrinter(hPrinter)End FunctionEnd ClassOn the Build menu, click Build Solution.Click Start, and then click Printers and Faxes.
Note On a computer that is running Microsoft Windows 2000, click Start, point to Settings, and then click Printers.In the Printers and Faxes window, double-click the icon for the printer whose queue you want to view.
Note In the Printers window on a computer that is running Windows 2000, double-click the icon for the printer whose queue you want to view.On the Printer menu in the PrinterName dialog box, click Pause Printing.
Note You may not be able to pause the print queue on a network printer.On the Debug menu in Visual Studio .NET, click Start to run the application.In the Form1 form, click Start to obtain the printer information and the list of jobs in the queue.
TroubleshootingOnly a specific device driver can obtain accurate printer status information. This sample code obtains the same status that the Windows spooler reports.
The exact status that is reported may vary for different printers and for different drivers.

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)