Getting started with VB.Net

Introduction

C# and VB.Net are the main languages used to write applications with the .Net framework.

Most assemblies, ie. .Net libraries, live in a directory called the Global assembly cache (GAC), eg. C:\WINDOWS\assembly. The Intermediate Language Disassembler utility (ildasm.exe) and Reflector provide information about any assembly.

Setup

.Net = big library

SDK = compiler (vbc.exe)

Visual Studio, Visual Basic Express, or SharpDevelop = IDE

The SDK, which includes the .Net framework, is installed when you install Visual Studio. If you decide to use the SharpDevelop IDE instead, you'll have to install the SDK manually.

How to reduce cold startup time

Applications written in managed code will always take longer to start since they require loading big libraries and compiling the opcode with the JIT at runtime. To improve performance, after it's been compiled by the JIT on the fly, the machine code version is kept in Windows' disk cache. This explains why the application starts much faster if it's restarted shortly.

To view which DLLs an application uses and whether the .Net DLL's are currently loaded, use Process Explorer.

Machine code generated manually by Ngen.exe is named following the pattern <app name>.ni.exe, is not directly executable, and is saved in subdirectories C:\Windows\Assembly\NativeImages_X. Note that Windows Explorer hides those sub-directories, so you'll have to use another file manager or open a DOS box to see them. Ngen lives in C:\WINDOWS\Microsoft.NET\Framework\<version number>\.

Here are ways to reduce the time it takes to load an application:

  1. Don't use an antivirus. Alternatively, either only use it to check a file manually, or mark the application + the .Net framework as safe applications so that they are ignored by the AV application
  2. Make sure the host has enough RAM so that Windows can keep as many files as possible in its file system cache
  3. If the application is on the bigger side, try and use Ngen to compile the opcode into machine code, so that the JIT is no longer needed. If you notice that this doesn't improve startup time, this means that the main issue is the time required to load the .Net assemblies. It might be possible to keep Ngen-compiled applications in Windows' file system cache
  4. Load only the minimum number of modules in the main application, and differ loading other modules when they are really needed
  5. POSSIBLE? Place the DLLs ("assemblies") in the file system cache
  6. CHECK Preload the CLR when the computer starts (sneaky, but...)
  7. Replace hard-disks with SSDs

Improving Managed Code Performance (Ngen.exe)

Native Image Generator (NGen)

How I Improved Execution Speed By 100 Times in 5 Minutes

.NET Framework Client Profile

VMWare ThinApp (ex-ThinInstall?)

CacheSet v1.0

Gacutil.exe Global Assembly Cache Tool

Improving Application Startup Performance

AnalogX CacheBooster

Increase Or Decrease Your Hard Drive Cache Memory With CacheBooster

How to increase the cache on your hard disk?

Pre-compile (pre-JIT) your assembly on the fly, or trigger JIT compilation ahead-of-time

How to distribute without the .Net framework

Remotesoft Salamander .NET Linker, Native Compiler and Mini-Deployment Tool ("Deploy .NET w/o Framework")

Not a good idea, but YMMV.

Coding

Starting with no form

Here's how to do it in Visual Basic Express:

  1. Project > MyApp Properties > Application, uncheck "Enable application framework"
  2. Next, in Startup object, choose "Sub Main"
  3. Finally, copy/paste this code:

    Public Shared Sub Main()
        MessageBox.Show("Main")
    End Sub

Here's how to do it in SharpDevelop:

(Build a Notification project instead, and figure out where to put your code).

Copying a string to the clipboard

Clipboard.SetText("Some text")

Pasting a string from the clipboard

Clipboard.GetText

Starting a second application

Based on this article.

If you just want to start an application, use this:

System.Diagnostics.Process.Start ("c:\windows\notepad.exe")

If you want to have access to a bit of information, use this:

Dim myProcess As Process = System.Diagnostics.Process.Start("c:\windows\notepad.exe")
MessageBox.Show(myProcess.ProcessName)

Yet more control with...

Dim psInfo As New System.Diagnostics.ProcessStartInfo("c:\windows\notepad.exe")
 
psInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal
 
Dim myProcess As Process = System.Diagnostics.Process.Start(psInfo)

... or this:

Dim myProcess As System.Diagnostics.Process = new System.Diagnostics.Process()
 
myProcess.StartInfo.FileName = "c:\windows\notepad.exe"
myProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal
 
myProcess.Start

Alternatively, you can add a Process component to your project and configure its settings at design-time.

Here's how to launch a process with no window showing:

Dim myProcess As Process = New Process()
Dim s As String
Dim outfile As String = Application.StartupPath & _
  "\dirOutput.txt"
 
' get the System path
Dim sysFolder As String = System.Environment.GetFolderPath(Environment.SpecialFolder.System)
 
' set the file name and the command line args
myProcess.StartInfo.FileName = "cmd.exe"
myProcess.StartInfo.Arguments = "/C cd " & _
  sysFolder & " && dir *.com >> " & Chr(34) & _
  outfile & Chr(34) & " && exit"
 
' start the process in a hidden window
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
myProcess.StartInfo.CreateNoWindow = True
myProcess.Start()
 
' if the process doesn't complete within 1 second, kill it
myProcess.WaitForExit(1000)
If Not myProcess.HasExited Then
  myProcess.Kill()
End If
 
' display exit time and exit code
MessageBox.Show("The 'dir' command window was " & _]
  "closed at: " & myProcess.ExitTime & "." & _
  System.Environment.NewLine & "Exit Code: " & _
  myProcess.ExitCode)
myProcess.Close()

Here's how to wait until the process has ended:

'One potential problem with both of these methods is that if the launched process hangs or never exits, your application is stuck. One solution is to add a timer that fires periodically, and checks to see if the launched application is still responding.
 
' allow the process to raise events
myProcess.EnableRaisingEvents = True
 
' add an Exited event handler
AddHandler myProcess.Exited, AddressOf Me.ProcessExited
 
' event handler
Friend Sub ProcessExited(ByVal sender As Object, ByVal e As System.EventArgs)
 
        Dim myProcess As Process = DirectCast(sender, Process)
        
        MessageBox.Show("The process exited, raising " & _
        "the Exited event at: " & myProcess.ExitTime & _
        "." & System.Environment.NewLine & _
        "Exit Code: " & myProcess.ExitCode)
        
        myProcess.Close()
End Sub

Formating strings

MessageBox.Show(String.Format("Some {0} {1}", "Dummy", "data"))

Using the Registry

Const Key="HKEY_CURRENT_USER"
Const Value="Ez Voice Mail"
Const KeyValue = Key & "\" & Value
Const SubKey="MySubKey"
 
If My.Computer.Registry.GetValue(KeyValue, SubKey, Nothing) Is Nothing Then
    My.Computer.Registry.CurrentUser.CreateSubKey(Value)
    My.Computer.Registry.SetValue(KeyValue, SubKey, "Dummy data")
Else
    Dim readValue As String
    readValue = My.Computer.Registry.GetValue(KeyValue, SubKey, Nothing)
    MsgBox("The value is " & readValue)
End If
 
My.Computer.Registry.CurrentUser.DeleteSubKey(Value)

Reading for a text file line by line

Here's a first way:

If System.IO.File.Exists(FILE_NAME) = True Then
    Dim srFileReader As System.IO.StreamReader
    Dim sInputLine As String
 
    srFileReader = System.IO.File.OpenText("myfile.txt)
    sInputLine = srFileReader.ReadLine()
    Do Until sInputLine Is Nothing
        'Do something
      sInputLine = srFileReader.ReadLine()
    Loop
End If

Alternatively:

Dim objReader As New System.IO.StreamReader("myfile.txt")
Dim Line As String
 
Do While objReader.Peek() <> -1
    Line = objReader.ReadLine
    'Do something
Loop

Writing to a text file

Dim objWriter As New System.IO.StreamWriter("myfile.txt")
objWriter.Write(RichTextBox1.Text)
objWriter.Close()

Running lengthy process without freezing UI

Here's an example downloading a web page. On a form, add a Button and a BackgroundWorker object:

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        BackgroundWorker1.WorkerReportsProgress = True

        BackgroundWorker1.RunWorkerAsync()

    End Sub

    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork

        Try

            Dim webClient As New System.Net.WebClient

            e.Result = webClient.DownloadString("http://192.168.0.10/")

        Catch ex As Exception

            'Note: WebClient has no TimeOut property. HttpWebRequest is more solid

        End Try

    End Sub

 

    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted

        Me.RichTextBox1.AppendText(e.Result)

    End Sub

End Class

Tell Express to save files at the root of a project directory

BAD File > Save All: MyTest (default: WindowsApplication1)

BAD Project > Properties > Application: Empty "Root namespace"

Run a lenghty process

While (True)

        Try

            'perform some lenghty process here

            Exit While

        Catch ex As Exception

            'BackgroundWorker1.ReportProgress(100, ex.Message)

            MessageBox.Show(ex.Message)

        End Try

        System.Threading.Thread.Sleep(2000)

End While

Use regex to read part of a block of text

Imports System.Text.RegularExpressions
 
Public Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      Dim data as String = "dummy <title>my title</title> dummy"
      Dim title As Regex = New Regex("<title>(.+?)</title>")
      Dim m As Match
 
      m = title.Match(data)
      If m.Success Then
        MsgBox(m.Groups(1).Value)
      End If
    End Sub
End Class

Note: Options such as SingleLine are available:

Dim title As Regex = New Regex("<title>(.+?)</title>", RegexOptions.Singleline)

More information: www.regular-expressions.info/dotnet.html

Recurse through directory

Here's how to start from a directory and get all the files and sub-directories it contains:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim filelist As Collections.ObjectModel.ReadOnlyCollection(Of String) = My.Computer.FileSystem.GetFiles("C:\MyFiles\", FileIO.SearchOption.SearchAllSubDirectories)
 
    For Each path As String In filelist
        ListBox1.Items.Add(path)
    Next
End Sub

Actually, FileSystem.GetFiles() is not a good solution if you might try to enter a protected sub-directory, as it stops searching if it tries to enter an off-limit directory.

A dirty solution is to just ignore the error:

For Each fileitem In dir.GetFiles("C:\", "MyFiles.*")
        Try
          Dim fileDetail As IO.FileInfo
          fileDetail = My.Computer.FileSystem.GetFileInfo(fileitem.FullName)
          Dim str As String = fileDetail.FullName
          BackgroundWorker1.ReportProgress(0, str)
        Catch err As UnauthorizedAccessException
          'Just ignore and resume search
        End Try
Next                    

Here is a recursive solution, but as it uses GetFiles(), it doesn't display files as it finds them so it's no possible to update the UI so the user knows how far the search is :-/

Having ListBox scroll to end automatically

ListBox1.SelectedIndex = ListBox1.Items.Count - 1

Get Current Time

ListBox1.Items.Add("Before GetResponse @ " + DateTime.Now)
ListBox1.Refresh()

Get double-clicked item in ListBox

MsgBox(ListBox1.SelectedItem.ToString)

Timer

After adding a Timer component to a form, here's how to enable the timer and execute code with every tick:

Imports System.IO
Imports System.Text
Imports System.Text.RegularExpressions
Imports System.Threading.Thread
Imports System.Windows.Forms
 
Public Class Form1
  Dim TimerBusy As Boolean = False
 
  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      ListBox1.Items.Clear()
 
      'Check every minute
      'Force timer to tick right away instead of waiting for event trigger
      Timer1.Interval = 60000
      Timer1.Enabled = True
      Timer1_Tick(Nothing, Nothing)
      Timer1.Start()
  End Sub
 
  Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
      'Check if routine still running previous tick
      If TimerBusy Then
          Exit Sub
      Else
          TimerBusy = True
      End If
      
      'Do stuff
        End Sub
End Class       

SQLite

There are a few solutions to connect VB.Net applications to an SQLite database file. One of them is the open-source System.Data.SQLite.

Besides choosing the right CPU architecture (32- or 64-bits) and .Net framework version (2.0 SP2, 3.5 SP1, 4.0, or 4.5), you must choose between...

... and different packages:

When using the non-static versions, make sure the VC++ runtime is installed, or ou might get the following errors: "Unable to load DLL 'SQLite.Interop.dll" or "Could not load file or assembly 'System.Data.SQLite.dll' or one of its dependencies. The specified module could not be found." This is due to the fact that the (no-)bundle versions rely on MSVCR110.DLL, which is part of the Visual C++ Redistributable for Visual Studio 2012 Update 1. Once the runtime is installed, the error should go away.

Since the SQLite DLL is available in a statically version ("Precompiled Statically-Linked Binaries"), I fail to see the added value of the other two versions. Maybe it's so the dynamic-linked libraries take advantage of upgrades to the VC++ runtime.

Once you know which package to download...

  1. Download the latest and greatest package. If using Precompiled, just unzip the file anywhere
  2. Create and save a new Windows Form VB.Net project
  3. Add a reference to this DLL: Project > Add Reference > System.Data.SQLite.dll
  4. In the code, add "Imports System.Data.SQLite"

Note:

Questions:

More Infos:

Test on brand new W7 host:

  1. Installed Visual Studio Express 2012 for Windows Desktop
  2. Installed Setups for 32-bit Windows (.Net Framework 4.5) bundle 1.0.84.0 :

    Two options can be checked:
    (default: Checked) "Generate native images for the assemblies and install the images in the native image cache"

    "Install the assemblied into the global assembly cache" + "Install the designer components for Visual Studio 2012"

    Note: The design-time component is no longer supported for Express editions
     
  3. Created new Forms project, tried to add reference to SQLite:

    Project > Add Reference: No trace of SQLite in Assemblies > Framework/Extension

    Ran Installer.exe: "Cannot continue, the "confirm" option is not enabled"

    In Project > Add Reference, hit "Browse", and pointed to "System.Data.SQLite.DLL": Seems OK
     
  4. Next, tried this:

    Imports System.Data.SQLite

    Dim SQLconnect As New SQLite.SQLiteConnection()
    Dim SQLcommand As SQLiteCommand

    'Note: Non-admin app cannot write to c:\
    SQLconnect.ConnectionString = "Data Source=c:\users\fred\test.sqlite;"
    SQLconnect.Open()

    SQLcommand = SQLconnect.CreateCommand

    SQLcommand.CommandText = "CREATE TABLE IF NOT EXISTS Item (type)"
    SQLcommand.ExecuteNonQuery()

    SQLcommand.CommandText = "INSERT INTO Item (type) VALUES ('something')"
    SQLcommand.ExecuteNonQuery()

    SQLcommand.Dispose()
    SQLconnect.Close()
  5. Next, uninstalled SQLite: Application still runs, since VS copied System.Data.SQLite.dll into the project's \Debug sub-directory
  6. Next, installed fresh Windows7 setup, installed Visual Studio Express 2012 for Windows Desktop
  7. Unzipped Precompiled Binaries no bundle ZIP, without installing required VC++ 2012 RTM runtime, and without running Installer.exe, added reference: "SQLite.Interop.dll : The specified module could not be found". Installed VC++ 2012 RTM runtime: no change. Copied SQLite.Interop.dll into \debug: OK! 
  8. Heres' how to read the data:
    SQLcommand.CommandText = "SELECT * FROM Item"

    Dim SQLreader As SQLiteDataReader = SQLcommand.ExecuteReader()
    lst_records.Items.Clear()

    While SQLreader.Read()
        lst_records.Items.Add(String.Format("ID = {0}, type = {1}", SQLreader(0), SQLreader(1)))

        'Alternative
        'lst_records.Items.Add(String.Format("ID = {0}, Title = {1}", SQLreader("id"), SQLreader("type")))
    End While

Test: Copy SQLite.Interop.dll in .\x86 where System.Data.SQLite.DLL is located in .\. The native library pre-loading feature in System.Data.SQLite.dll will check .\x86 or .\x64.

DataGridView

This is an unbound grid object. Here's how to create some columns, and add a couple of rows:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    With DataGridView1
        'Hide ugly, left-most column
        .RowHeadersVisible = False
 
        .ReadOnly = False
 
        'Prevents adding rows when editing cell
        .AllowUserToAddRows = False
 
        'Name + Label
        .Columns.Add("Key", "Key")
        .Columns.Add("Value", "Value")
 
        .Rows.Add(2)
 
        '.Item(0, 0).Value = "Key1"
        '.Item(0, 1).Value = "Value1"
        .Rows(0).Cells("Key").Value = "key1"
        .Rows(0).Cells("Value").Value = "value1"
 
        .BackgroundColor = SystemColors.Control
        .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill 
    End With
End Sub

Apparently, it's not possible to add rows and contents to an unbound control at design time.

Any way to use names for rows instead of index number? .Rows("myrow").Cells("mykey").Value = "myvalue"

Alternative, open-source grids:

More information:

Downloading a web page with WebClient

WebClient doesn't have a lot of features, but it's good enough to download a web page, synchronously or asynchronously, the latter being a better option since it prevents the UI from freezing while we're waiting for the web page to be downloaded:

'Add Button + RichTextBox to form
 
Imports System.Net
Imports System.IO
 
Public Class Form1
    Private Sub AlertStringDownloaded(ByVal sender As Object, ByVal e As DownloadStringCompletedEventArgs)
        If e.Cancelled = False AndAlso e.Error Is Nothing Then
            RichTextBox1.Text = CStr(e.Result)
            RichTextBox1.Refresh()
            Button1.Enabled = True
        End If
    End Sub
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Button1.Enabled = False
 
        Dim URL As String = "http://www.google.com"
        
        Dim theaters As New Dictionary(Of String, String)         theaters.Add("Theater #1", "http://www.theaters.com/1.html")         theaters.Add("Theater #2", "http://www.theaters.com/2.html")
 
        For Each kvp As KeyValuePair(Of String, String) In theaters
            'Synchronous DownloadString freezes UI while waiting for web page
 
            Dim webClient As New WebClient
            AddHandler webClient.DownloadStringCompleted, AddressOf AlertStringDownloaded
 
            ListBox1.Items.Add(kvp.Key)
 
          webClient.DownloadStringAsync(New Uri(kvp.Value))
      Next
 
    End Sub
End Class

Note: When downloading multiple web pages as above, you can't tell WebClient to download them in order. You could save each page into a database, and sort them later.

POSTing variables to a web server and receiving data with WebClient

Here's how to connect to a web server, send variables with the POST method, and receive data:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim client As New WebClient()
 
    Dim collect As New Specialized.NameValueCollection
    collect.Add("param1", "john")
    collect.Add("param2", "doe")
 
    client.Headers.Add("Content-Type", "application/x-www-form-urlencoded")
 
    'Turn bytes into a string
    RichTextBox1.Text = Encoding.ASCII.GetString(client.UploadValues("localhost", "POST", collect))
End Sub

Downloading a web page with HttpWebResponse

Although System.Net.WebClient is easier to use, System.Net.HttpWebRequest (and HttpWebResponse) offers more features.

Imports System.Net
Imports System.IO
 
Public Class Form1
    Const URL = "http://www.google.com"
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim Request As HttpWebRequest
        Dim Response As HttpWebResponse
        Dim ResponseStream As StreamReader
        Dim Result As String
 
        Try
            Request = HttpWebRequest.Create(URL)
 
            Response = Request.GetResponse()
 
            ResponseStream = New StreamReader(Response.GetResponseStream())
            Result = ResponseStream.ReadToEnd()
            Response.Close()
 
            RichTextBox1.Text = Result
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub
End Class

Enhanced use of HttpWebRequest + HttpWebResponse

Here's how to enable cookies, connect out through a web proxy, and POST a login + password to log on to a web server:

 

Uploading a file to an FTP server

Using System.Net.WebClient

WebClient can upload (and download) as Data/File/String/Values ("Values" is to send metadata in the HTTP header), synchronously or asynchronously, in HTTP or FTP.

Imports System.Net

Try

    Const File as String = "dummy.txt"

    Dim filename As String = "ftp://www.acme.com/" & File

    Dim client As New WebClient

    client.Credentials = New NetworkCredential("myself", "mypasswd")

    client.Proxy = Nothing

    client.UploadFile(filename, "C:\" & File)

    MsgBox("File uploaded!")

Catch ex As Exception

    MsgBox(ex.ToString)

End Try

Using System.Net.WebRequest/WebResponse

Those are abstract classes that derive into HttpWebRequest and FileWebRequest/FTPWebRequest.

Extracting filename from fully-qualified path

Dim dirName As String = IO.Path.GetFileName(fullPath)

or

System.IO.Path.GetFileNameWithoutExtension(FullPath)

Dictionary

                Dim keys As New List(Of String)()

                Dim storedValues As New Dictionary(Of String, String)()

                keys.Add("server")

                keys.Add("login")

                keys.Add("password")

                keys.Add("url")

                For Each mykey In keys

                    storedValues.Add(mykey, CStr(My.Computer.Registry.GetValue(KeyValue, mykey, String.Empty)))

                Next

 

 

        Dim dict As New Dictionary(Of String, String)

 

        dict.Add("server", Nothing)

        dict.Add("login", Nothing)

        dict.Add("password", Nothing)

        dict.Add("url", Nothing)

 

        'For Each kvp As KeyValuePair(Of String, String) In dict

        '    'Property "Value" is read-only

        '    kvp.Value = My.Computer.Registry.GetValue(KeyValue, kvp.Key, Nothing)

        '    MessageBox.Show("Key: " + kvp.Key + " Value: " + kvp.Value)

        'Next

 

        For Each MyKey In dict.Keys

            dict(MyKey) = My.Computer.Registry.GetValue(KeyValue, MyKey, Nothing)

            MessageBox.Show("Key: " + MyKey + " Value: " + dict(MyKey))

 

            'Collection was modified; enumeration operation may not execute.

        Next

 

Two-column, unbound grid?

When you need to enter a bunch of key/value tuples:

datagridview

propertygrid

http://www.vbnettutorial.net/?Id=125&Desc=VB.Net-DataGridView

http://vb.net-informations.com/datagridview/vb.net_datagridview_tutorial.htm

http://www.dotnetperls.com/datagridview-vbnet

Generate a unique filename

System.IO.Path.GetTempFileName()

Dim sTempFileName As String = System.IO.Path.GetTempFileName()

Guid.NewGuid()

Dim FileName As String

FileName = Guid.NewGuid().ToString().GetHashCode().ToString("x")

FileName = String.Format("c:\{0}.txt", FileName)

Storing key,value in a Dictionary

DataGridView

propertygrid

Checking that a node exists in the Registry

Dim regKey As RegistryKey

Try

    regKey = Registry.CurrentUser.OpenSubKey("My node", False)

    If regKey Is Nothing Then

        MessageBox.Show("Node doesn't exist")

    End If

Catch ex As Exception

    MessageBox.Show(ex.Message, "Error: Reading Registry Value", MessageBoxButtons.OK, MessageBoxIcon.Error)

End Try

Checking that a file exists

Imports System.IO

...

Const MYAPP = "myapp.exe"

If File.Exists(MYAPP) = False Then

    MessageBox.Show(MYAPP & " not found. Exiting.")

    End

End If

Enhancements

Charts

Grid

All Windows Forms > DataGridView

Deployment

ClickOnce

Language/IDE Peeves

In a Release version of a program, does it end with Catch?

... or must I add an End?

[Express 2008] No support for bookmarking/navigating with F2/CTRL-F2

[Express 2008] No support for in-place scrolling through CTRL+up/down

[Express 2008] No support for code block (un)folding

Only available for whole routine, not if/endif, select/endselect, etc.

Can't disable automatic indenting for the following case

In VB.Net Express 2008 at least, it's an either/or, ie. you can't disable auto-indenting only in certain cases such as this one:

'Comment about what following block does
If A Then
 
    'This comment not lined up with Else block that follows
Else
    'Stuff happens

No support for in-place scrolling with CTRL-up/down arrow

No support for whole-block out-commenting

Must still prepend each line with an apostrophe, instead of C's /*...*/

Q&A

In Visual Studio Express, how to hide debugging windows?

Ie. "Memory", "Watch", "Locals", etc.

Tools > Options > Debugging > General: Uncheck "Enable address-level debugging".

What files must be checked in the source control manager?

IOW, ignore \bin and \obj.

Why should I install the .Net SDK in addition to the SharpDevelop IDE?

http://community.sharpdevelop.net/forums/p/14362/38239.aspx#38239

Ngen: I can't find where it saved the machine code of an application

It seems to sometime name the file under a different name than the opcode version.

ngen display > display.txt

Why does this code report success although the file isn't actually uploaded?

    Sub WebClientUploadFileCompleted(ByVal sender As Object, ByVal e As UploadFileCompletedEventArgs)

        MessageBox.Show("Done!")

    End Sub

 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim client As New WebClient()

        AddHandler client.UploadFileCompleted, AddressOf WebClientUploadFileCompleted

        Try

            With client

                .Credentials = New NetworkCredential("jdoe", "mypasswd")

                .UploadFileAsync(New Uri("ftp://ftp.acme.com"), "c:\test.txt")

            End With

        Catch ex As Exception

            MessageBox.Show(ex.Message)

        End Try

    End Sub

How to check that the user has the right .Net framework?

How to check code that requires the app to run as Administrator?

How to investigate why an app doesn't start?

In case an application refuses to start on a test host while it works fine on your develop host, add the following code to the form:

Edit: In case another newbie stumbles on this issue: It was due to a missing dependency. To catch this type of error, add the following to Form1:

Public Sub New()
        AddHandler Application.ThreadException, AddressOf OnThreadException
        AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf UnhandledExceptionEventRaised
 
        InitializeComponent()
    End Sub
 
Private Sub UnhandledExceptionEventRaised(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs)
        If e.IsTerminating Then
            Dim o As Object = e.ExceptionObject
            MessageBox.Show(o.ToString) ' use EventLog instead
        End If
End Sub
 
Private Sub OnThreadException(ByVal sender As Object, _
                       ByVal e As ThreadExceptionEventArgs)
        ' This is where you handle the exception
        MessageBox.Show(e.Exception.Message)
End Sub

How to check which .Net framework a program needs to run?

[DataGridView] Any way to name a row?

... so that we can refer to rows with names just like we do for columns?

.Rows(0).Cells("Key").Value = "key1"

Why does BeginGetResponse() wait for a couple of seconds?

To resolve the hostname. Just use an IP address instead, and BeginGetResponse() won't block.

How to create an installer with InnoSetup?

How to easily comment a whole block of code?

Don't want to prepend each line with '

Which IDE should I use?

MS'VisualStudio? SharpDevelop? Other?

How to check if the user has the right version of the .Net framework and any needed ServicePack?

Manually: Through the "Add or remove Programs" applet in Control Panel (look for "Microsoft .Net Framework").

Programmatically:

Is .Net downward-compatible?

ie. can an application compiled for 2.0 run on 3.5?

What happens if the user isn't logged with enough admin rights to install .Net and/or any needed ServicePack?

What makes Mono better than .Net for Windows apps?

VisualStudio vs. VisualStudio Express?

http://en.wikipedia.org/wiki/Microsoft_Visual_Studio_Express

Why import System and System.Drawing?

Imports System
Imports System.Drawing

.Net for Macintosh?

Is there a difference between the code created by SharpDevelop and Visual Studio?

Resources

Books

Sites

Forums