Best vb.net questions in October 2010

.Net Rounding Issue

8 votes

I have a rounding issue inside of .Net.

I am rounding a 3 digit number down to two digits and it is causing some problems with one number.

If I try to round 34.425 to two decimal places it should round it to 34.43. I am using the roundawayfromzero option and it has worked for every number in the program except for this one so far.

The code Math.Round(34.425, 2, MidpointRounding.AwayFromZero) should equal 34.43 however, it equals 34.42.

If I try this with any other number it works fine.

Math.Round(34.435, 2, MidpointRounding.AwayFromZero) = 34.44

Math.Round(34.225, 2, MidpointRounding.AwayFromZero) = 34.23

Math.Round(34.465, 2, MidpointRounding.AwayFromZero) = 34.47

I just wanted to check to see if anyone has run into this problem before?

For right now I have fixed this problem by converting the number to a decimal. I have changed the code to this and it works fine now:

Math.Round(CDec(34.425), 2, MidpointRounding.AwayFromZero) = 34.43

I am just looking for a reason on why my old code did not work.

Thank you!

Updated the code to the correct AwayFromZero

Floating point is never exact, 34.425 may have an internal represantation 34.4249999999999.. which will be rounded up to 34.42.

If you need exact representation for numbers use the decimal type.

Is there any console "graphics" library for .Net?

8 votes

My basic goal here is writing a .NET remake of Kingdom of Kroz. For those not familiar with the game:

http://www.indiefaqs.com/index.php/Kingdom_of_Kroz

http://www.youtube.com/watch?v=cHwlNAFXpIw

Originally it was supposed to be a quick distraction project to give me a break from all the generic enterprise WCF/WF/LINQ2SQL/etc work projects occupying most of my time lately. While the result of my effort is playable, it looks like absolute arse (even for a console-based game) because of the way I'm redrawing everything in each frame.

I'm aware of some alternate approaches but in the brief tests I've done they still don't offer significant performance or aesthetic benefits. I almost can't believe I'm asking this, but... does anyone know of a fast and efficient "console graphics" library for VB.Net / C#?


Edit: failing the availability of a "library" as such, perhaps there's a reference for fast console drawing/update techniques?

http://msdn.microsoft.com/en-us/library/ms682073(v=VS.85).aspx

Some/many of these functions you might need to use P/Invoke for, but they should do what you need. You can write at arbitrary locations in the buffer and get key-based, non-buffered input. Usually you start with GetStdHandle() to get handles to the console input and output "streams" and then you call one of the appropriate functions from the above list to do something, like WriteConsoleOutputCharacter(), or PeekConsoleInput().

I once wrote a library to create an in-process windowing system using the Windows console and plain Win32 on C. Fun project, but I don't know where it is now.

Why we use flush parameter with Encoder.GetBytes method

6 votes

This link explains the Encoder.GetBytes Method and there is a bool parameter called flush explained too . The explanation of flush is :

true if this encoder can flush its state at the end of the conversion; otherwise, false. To ensure correct termination of a sequence of blocks of encoded bytes, the last call to GetBytes can specify a value of true for flush.

but I didn't understand what flush does , maybe I am drunk or somthing :). can you explain it in more details please.

Suppose you receive data over a socket connection. You will receive a long text as several byte[] blocks.

It is possible that 1 Unicode character occupies 2+ bytes in a UTF-8 stream and that it is split over 2 byte blocks. Encoding the 2 byte blocks separately (and concatenating the strings) would produce an error.

So you can only specify flush=true on the last block. And of course, if you only have 1 block then that is also the last.

Tip: Use a TextReader and let it handle this problem(s) for you.

Edit

The mirror problem (that was actually asked: GetBytes) is slightly harder to explain.

Using flush=true is the same as using Encoder.Reset() after GetBytes(...). It clears the 'state' of the encoder,

including trailing characters at the end of the previous data block, such as an unmatched high surrogate

The basic idea is the same: when converting from string to blocks of bytes, or vice versa, the blocks are not independent.

Why are C# and VB.NET so similar?

6 votes

Also, if they are so similar then why do they exist separately ?

Some people prefer a c like curly brace syntax, others a more English like syntax like in VB.net And since MS wants VB programmers to upgrade to .net they need to offer a VB.net, and since they want to attract Java and C/C++ programmers they need to offer C#.

C#
Do what I say

  • Syntax similar to Java C/C++
  • Case sensitive
  • Fewer implicit conversions (=> more casts)
  • Allows unsafe code(pointers)

VB
Do what I mean

  • English like syntax
  • Case insensitive
  • Weaker Typing (more implicit conversions)

What does := mean in vb.net?

6 votes

We have this method call:

SendAck(AppData:=AppData, Status:=Status, StatusMessage:=StatusMessage, IsApplication:=IsApplication)

And here is the definition:

Private Sub SendAck(ByVal AppData As XDocument, ByVal Status As Boolean, ByVal StatusMessage As String, ByVal IsApplication As Boolean)

Why does the call have the parameters with the ":=". I'm just curious.

The ":=" in VB.Net is used to pass a function argument by name. The default is by position. It allows for parameters to be called in any order and determines the positioning based on name matches.

For example

Sub Example(ByVal param1 as Integer, ByVal param2 As Integer) 
  Console.WriteLine("{0} - {1}", param1, param2)
End Sub

Example(param2:=42, param1:=1) ' Prints "1 - 42"
Example(42, 1)                 ' Prints "42 - 1"

basic question about "using" construct

5 votes

If I use "using" construct, I know that the object gets automatically disposed. What happens if a statement inside an "using" construct raises an exception. Is the "using" object still disposed? If so, when?

A using block is converted - by the compiler - to this:

DisposableType yourObj = new DisposableType();
try
{
    //contents of using block
}
finally
{
    ((IDisposable)yourObj).Dispose();
}

By putting the Dispose() call in the finally block, it ensures Dispose is always called - unless of course the exception occurs at the instantiation site, since that happens outside the try.

It is important to remember that using is not a special kind of operator or construct - it's just something the compiler replaces with something else that's slightly more obtuse.

Getting Folder Name(s) from Path

5 votes

If I have a file path like "C:\My Documents\Images\Image1.png", how can I get the parent folder name of the "Image1.png" file? In this case, "Images", but that's just a sample. I've looked through System.IO.Path and there doesn't seem to be anything there. Maybe I'm overlooking it, but I have no idea where it would be.

Like this:

Path.GetFileName(Path.GetDirectoryName(something))

Is String a primitive type?

5 votes

I am curious about the string and primitive types. Article like this says string is primitive type. However second article on MSDN does not list string as primitive type.

However when I ran the code provided in second article, it displays String is not Primitive type.

Can any one guide me on this?

Thanks, Ram

Both articles says that string is NOT a primitive type. Which it is not.

If you compile and run the example code from the second article it would print:

string is not a primitive type.

I think the confusion about this is, that the syntax of of creating a new string is similar to creating valye types.

When defining a value type all of these are equal (on a 32 bit system anyway)

System.Int32 a = new System.Int32(5);
System.Int32 a = 5;
int a = 5;

Just like these when creating a reference type string:

System.String s = new System.String(new char[]{'h', 'e', 'l', 'l', 'o'});
System.String s = "hello";
string s = "hello";

Also we can compare strings by value even though they are reference types:

s == "hello";//true

This still does not make string a primitive type..

The accepted answer to this question should give you details on that.

Changing the forecolor and backcolor of text in a textbox

5 votes

I'm making a C++ code editor application using VB.NET. I'd like to change the color of the keywords as the user types it. Also I'm looking for a way to highlight some lines of the code.

Is there a way to change the forecolor and backcolour of a piece of text inside a textbox or a rich textbox?

I do not really know what you want to do so here are some options.

If you want a step by step tutorial on how to write a syntax highlighting control, you can read these articles:

  1. Syntax Highlighting in RichTextBox Part 1 and Part 2.
  2. Syntax Highlighting in RichTextBox using C#


For a basic syntax highlighting control written in VB.NET, see this article: Color Syntax Control (VB.NET).


There are two very good options if you want a fully-fledged syntax highlighting control. These are:

  1. ScintillaNET for WinForms and;
  2. AvalonEdit for WPF.
    • There is a tutorial on Using AvalonEdit on CodeProject so be sure to check that out as well.

Preventing SQL Injection in ASP.Net VB.Net

5 votes

I have this code

UPDATE OPENQUERY (db,'SELECT * FROM table WHERE ref = ''"+ Ref +"'' AND bookno = ''"+ Session("number") +"'' ') 

How would I prevent SQL Injections on this?

Thanks

Jamie

UPDATE

Here's what i'm trying

SqlCommand cmd = new SqlCommand("Select * from Table where ref=@ref", con); 
cmd.Parameters.AddWithValue("@ref", 34);

For some reason everything I try and add it doesn't seem to work I keep getting SQL Command mentioned below.

The error is this

'SqlCommand' is a type and cannot be used as an expression

I'm taking over someone else's work so this is all new to me and I would like do things the right way so if anyone can provide any more help on how to make my query above safe from SQL injections then please do.

Thanks

Jamie

UPDATE NO 2

I added in the code as VasilP said like this

Dim dbQuery As [String] = "SELECT * FROM table WHERE ref = '" & Tools.SQLSafeString(Ref) & "' AND bookno = '" & Tools.SQLSafeString(Session("number")) & "'"

But I get an error Tools is not declared do I need to specify a certain namespace for it to work?

Thanks

Jamie

UPDATE

Has anyone got any ideas on the best of getting my query safe from SQL injection without the errors that i'm experiencing?

Thanks

Jamie

UPDATE

I now have it so it work without the parameters bit here's my updated souce code any idea why it won't add the parameter value?

Dim conn As SqlConnection = New SqlConnection("server='server1'; user id='w'; password='w'; database='w'; pooling='false'")
   conn.Open()


Dim query As New SqlCommand("Select * from openquery (db, 'Select * from table where investor = @investor ') ", conn)
query.Parameters.AddWithValue("@investor", 69836)

dgBookings.DataSource = query.ExecuteReader
dgBookings.DataBind()

It works like this

Dim conn As SqlConnection = New SqlConnection("server='server1'; user id='w'; password='w'; database='w'; pooling='false'")
   conn.Open()


Dim query As New SqlCommand("Select * from openquery (db, 'Select * from table where investor = 69836') ", conn)

dgBookings.DataSource = query.ExecuteReader
dgBookings.DataBind()

The error i'm getting is this

An error occurred while preparing a query for execution against OLE DB provider 'MSDASQL'. 

And it's because it isn't replacing the @investor with the 69836

Any ideas?

SOLUTION

Here is how I solved my problem

Dim conn As SqlConnection = New SqlConnection("server='h'; user id='w'; password='w'; database='w'; pooling='false'")

conn.Open()

Dim query As New SqlCommand("DECLARE @investor varchar(10), @sql varchar(1000) Select @investor = 69836 select @sql = 'SELECT * FROM OPENQUERY(db,''SELECT * FROM table WHERE investor = ''''' + @investor + ''''''')' EXEC(@sql)", conn)

dgBookings.DataSource = query.ExecuteReader
dgBookings.DataBind()

Now I can write queries without the worry of SQL injection

Thanks everyone

Try using a parameterized query here is a link http://www.aspnet101.com/2007/03/parameterized-queries-in-asp-net/

Also, do not use OpenQuery... use the this to run the select

SELECT * FROM db...table WHERE ref = @ref AND bookno = @bookno

More articles describing some of your options:

http://support.microsoft.com/kb/314520

http://stackoverflow.com/questions/125457/what-is-the-t-sql-syntax-to-connect-to-another-sql-server


Edited

Note your original question was asking about distributed queries and Linked servers. This new statement does not reference a distributed query. I can only assume you are directly connecting to the database now. Here is an example that should work. Here is another reference site for using SqlCommand.Parameters

SqlCommand cmd = new SqlCommand("Select * from Table where ref=@ref", con); 
cmd.Parameters.Add("@ref", SqlDbType.Int);
cmd.Parameters["@ref"] = 34;

Edited:

Ok Jamie taylor I will try to answer your question again.

You are using OpenQuery becuase you are probably using a linked DB

Basically the problem is the OpenQuery Method takes a string you cannot pass a variable as part of the string you sent to OpenQuery.

You can format your query like this instead. The notation follows servername.databasename.schemaname.tablename. If you are using a linked server via odbc then omit databasename and schemaname, as illustrated below

    Dim conn As SqlConnection = New SqlConnection("your SQL Connection String")
    Dim cmd As SqlCommand = conn.CreateCommand()
    cmd.CommandText = "Select * db...table where investor = @investor"
    Dim parameter As SqlParameter = cmd.CreateParameter()
    parameter.DbType = SqlDbType.Int
    parameter.ParameterName = "@investor"
    parameter.Direction = ParameterDirection.Input
    parameter.Value = 34

Kill process started with System.Diagnostic.Process.Start("FileName")

4 votes

I am trying to create an app that will perform actions on specific times (much like the Windows Task Scheduler). I am currently using Process.Start() to lunch the file (or exe) required by the task.

I am initiating a process by calling a file (an .mp3) and the process starts WMP (since it is the default application), so far so good. Now I wan't to kill that process. I know that it is normal behavior for the Process.Start(string, string) to return nothing (null in C#) in this case.

So I am asking how can i close WMP when I called it through Process.Start(string, string)??

Edit:

Please note that I am not opening WMP directly with Process.Start() and this is the line with which I run the process:

VB: Me._procs.Add(Process.Start(Me._procInfo))

C#: this._procs.Add(Process.Start(this._procInfo))

_procInfo is a ProcessStartInfo instance. _procInfo.FileName is "C:\route\myFile.mp3". That is why WMP opens. In any case, all of the Start() methods, except for the instance-one which returns a boolean, return nothing (null in C#), because WMP is not the process that was directly created (please note that WMP is run and the song does play).

Don't do it this way.

It's not clear whether the intent of your program is 'Always launch with Windows Media Player' or 'Launch with the registered MP3 player', which might be, say, iTunes.

If you need WMP, use Process.Start with the full path to windows media player.

If you need the registed MP3 player, you can find out the correct exe using the code shown here. Again, start the process with this exe path, passing the MP3 as a parameter.

[VB.net] What's the best approach to logging?

4 votes

My (local, windows/mono) app logs important events to a text file. In case of a sudden crash/failure/forced exit, no data should remain unwritten (as far as it's possible). Thus I currently use a simple append-to-text-file approach:

Public Shared Sub LogAppEvent(ByVal EventData As String)
    Dim Config As ConfigHandler = ConfigHandler.GetSingleton()
    Dim AppLog As New IO.StreamWriter(Config.GetUserFilesRootDir() & ConfigOptions.AppLogName, True)
    AppLog.WriteLine(String.Format("[{0}] {1}", Date.Now.ToString(), EventData))
    AppLog.Close()
End Sub

This is highly sub-optimal, but log events are pretty rare. Would you recommand moving to the System.Diagnostics logging class?

Or maybe would you suggest another solution?

Thanks,
CFP.

If a super basic approach like this is functionally sufficient for your needs, you can stick with it. But, you might ask yourself a few questions to make sure:

  • Is it possible for events to be logged concurrently by multiple threads? This function is not threadsafe

  • Is error notification needed?

  • Is there a risk of the log files growing without bounds with no automated pruning?

  • Would you benefit from more extensive logging so that you had more info about events leading up to an error?

  • Would you benefit from more detail about errors (stack trace, exception details, etc)

  • Does your program run on multiple computers? If so, how do logs get to you?

  • Is there any need/value in tools to help analyze log files (either singularly or finding patterns such as common errors across many log files)?

If you decide that you have other requirements, there are a number of free logging frameworks such as NLog or log4net that can help record more detailed logs, and there are several commercial products such as GIBRALTAR and SmartInspect available that can help with log management and analysis.

how was Array.Sort implemented in .NET?

4 votes

I am using structures in my programming and I sort the structure according to a value in the structure using IComparer.

How did Microsoft implement the Array.Sort() method? Is there any documentation (references) for this? Is it the same for all types of Sort() in Visual Basic?

This is a simple example for what I want.

Dim MyArray(6) As Integer
    MyArray(0) = 1
    MyArray(1) = 45
    MyArray(2) = 45
   ' Some Code.....
    '.........
    '..........
    MyArray(3) = 1
    MyArray(4) = 10
    ' Some Code.....
    '.........
    '..........
    MyArray(5) = 1
    MyArray(6) = 57

    Array.Sort(MyArray)

Array.Sort() will sort this array as: (1 1 1 10 45 45 57)

How does number 1 get sorted? Is it bringing to the end the first one or keeps the old one in the same index?

In my original example (before sorting), MyArray(0) = 1 and after sorting MyArray(0) = 1.

Is this the same original 1 or this another 1 (the newest one added to the array) moved to that position?

In case the MyArray(0) = 1 after sorting should be MyArray(5) = 1 before sorting.

Array.Sort is an unstable sort, so the order of elements which are the same is undefined and not conserved. The article on Array.Sort in MSDN states:

This method uses the QuickSort algorithm. This implementation performs an unstable sort; that is, if two elements are equal, their order might not be preserved. In contrast, a stable sort preserves the order of elements that are equal.

LINQ's OrderBy methods on the other hand are stable. The article on OrderBy in the MSDN states:

This method performs a stable sort; that is, if the keys of two elements are equal, the order of the elements is preserved. In contrast, an unstable sort does not preserve the order of elements that have the same key.

Can a Visual Basic (.NET / 2010) file be split up for readability?

4 votes

I'm writing a program in Visual Basic 2010. It's a HMI (Human-Machine Interface) and therefore has a whole whack of buttons that just send commands to other devices. As a result, there are a huge pile of event handlers for clicking buttons that can't really be broken down into modules (unless my understanding of modules is wrong).

Essentially, I'd like to be able to move all the event handlers, for, say, button presses to a different file. Can this be done or is it important that they stay in "MainWindow.xaml.vb"? (All my buttons reside in one fullscreen window, some are hidden by tabs).

Thanks,

--Erik T

You can use Partial Classes to break up your class definition into multiple files which might help organize your code.

The link above will help explain exactly how to use Partial Classes. The following link will show you the VB.NET Syntax (and how to use Class Designer to split things up):

How to: Split a Class into Partial Classes

VB.Net - "With" and Closures don't mix

4 votes

Just thought I'd share this in case anyone else has run into this.
I did something similar today and it took me a while to figure out why this was causing a problem at runtime.

This code:

Public Class foo
  Public bar As String = "blah"
End Class

Public Sub DoInline()
  Dim o As New foo
  Dim f As Func(Of String)
  With o
    f = Function() .bar
  End With
  Try
    Console.WriteLine(f.DynamicInvoke())
  Catch ex As Reflection.TargetInvocationException
    Console.WriteLine(ex.InnerException.ToString)
  End Try
End Sub

Throws a NullReferenceException. It seems as though the With is using the closure as its temp storage, and at the "End With", it sets the closure's variable to Nothing.

Here is that code in RedGate Reflector:

Public Shared Sub DoInline()
    Dim o As New foo
    Dim $VB$Closure_ClosureVariable_7A_6 As New _Closure$__1
    $VB$Closure_ClosureVariable_7A_6.$VB$Local_VB$t_ref$L0 = o
    Dim f As Func(Of String) = New Func(Of String)(AddressOf $VB$Closure_ClosureVariable_7A_6._Lambda$__1)
    $VB$Closure_ClosureVariable_7A_6.$VB$Local_VB$t_ref$L0 = Nothing 
    Try 
        Console.WriteLine(RuntimeHelpers.GetObjectValue(f.DynamicInvoke(New Object(0  - 1) {})))
    Catch exception1 As TargetInvocationException
        ProjectData.SetProjectError(exception1)
        Console.WriteLine(exception1.InnerException.ToString)
        ProjectData.ClearProjectError
    End Try
End Sub

Notice the

$VB$Closure_ClosureVariable_7A_6.$VB$Local_VB$t_ref$L0 = Nothing 

Only "question" I can really ask is; is this a bug or a strange design decision that for some reason I'm not seeing. I'm pretty much just going to avoid using "With" from now on.

This behavior is "By Design" and results from an often misunderstood detail of the With statement.

The With statement actually takes an expression as an argument and not a direct reference (even though it's one of the most common use cases). Section 10.3 of the language spec guarantees that the expression passed into a With block is evaluated only once and is available for the execution of the With statement.

This is implemented by using a temporary. So when executing a .Member expressio inside a With statement you are not accessing the original value but a temporary which points to the original value. It allows for other fun scenarios such as the following.

Dim o as New Foo
o.bar = "some value"
With o   
  o = Nothing
  Console.WriteLine(.bar) ' Prints "some value"
End With

This works because inside the With statement you are not operating on o but rather a temporary pointing to the original expression. This temporary is only guaranteed to be alive for the lifetime of the With statement and is hence Nothingd out at the end.

In your sample the closure correctly captures the temporary value. Hence when it's executed after the With statement completes the temporary is Nothing and the code fails appropriately.

Iterators in VB.NET vNext, and limitations of iterators in C#

4 votes

I just saw on the Async CTP website that the next version of VB.NET will have iterators. I guess they included iterators because the rewriting process is similar to the one used for the new async/await feature.

But reading the document that explains the feature, I realized that VB.NET iterators will actually have features that are not available in C# today, namely:

  • iterator blocks in a try/catch block
  • anonymous iterator blocks

These were known limitations in C#. Is there any chance that these limitations will be removed in C# 5 ? If not, is there any reason why it can be done in VB.NET and not in C# ?

Is there any chance that these limitations will be removed in C# 5 ?

There is a slim chance. I certainly wouldn't count on it. Those are "nice to have" features, not "must have" features, and when you have an enormous amount of work to do, the "nice to have" features sometimes fall off the schedule, as nice as they are.

If not, is there any reason why it can be done in VB.NET and not in C# ?

Any technical reason? No. There are engineering reasons of course.

Often it is the case that being the second team to implement a particular feature is beneficial. The implementors of a second implementation get to take advantage of the knowledge gained from the first attempt without taking on so large a research and development cost, while not incurring any maintenance or backwards compatibility taxes.

VB has the benefit of not having had this feature already and therefore has no existing body of millions of lines of user code that they need to be 100% backwards compatible with. That is a considerable cost burden removed. And they have a large database of bug reports, design notes, and so on, from eight years of having this feature in C#.