Tuesday, October 23, 2007

How easy it is to destroy the internet experience for everybody else

At some point we have all been exposed to ads when we search the Internet. Some may have installed ad-removal software to get rid of the ads and some haven't. But the fact is that even if you have ad-blocking software installed you cannot completely avoid the ads on the Internet.
Ads serves two purposes for the visitors point of view (laugh now, but at least I tried to come up with an excuse for the existence of ads):

1) Keeps websites running for free or sometimes for a small fee
2) Makes it possible for websites to have better content or bandwidth

So even though we hate ads more than anything else, they do serve some kind of purpose.

Whats worse is ads that tries to trick you into buying crap. Personally I've been seeing an ad for the same company for quite a while now. It tries to trick you into buying the company's anti-virus software and now also their anti-malware software.
The ad is very annoying because it redirects away from the page you were visiting to their fake warning site, where they want you to download their software (I don't even know if it's actually a real piece of software or if it is just another malware).

The first thing you will see is their message box:

you can't do anything else than clicking the OK button and when you do that you will get redirected to their fake warning site:

On this page every link you try to click links to their installer which they want you to download. It doesn't take much of a programmer to see in the binary that the installer will download a load of crap from their site and tweak your Windows settings to make it look like there really is something wrong with you machine (actually when first you have run this installer they are probably right about that you have a problem with you Windows, but they are to blame).

So the lesson here is:

DO NOT ACCEPT OR DOWNLOAD ANYTHING FROM THEM!

By the way, if you know the people behind these ads please do me a favor and tie their shoelaces together at least once a month for wasting my time.
Read more!

Saturday, October 20, 2007

Invoking a method that takes a pointer as an argument

I'm currently playing around with a cloned StringBuilder. This builder needs to call some methods on the String class which is internal, so reflection is the only way to call them. Usually that's no problem, but this time some of the methods accepted Char* as arguments and I haven't dealt with that before in reflection matters.

Getting the method info
The method I'm interested in is:

internal unsafe void AppendInPlace(char* value, int count, int currentLength)

If there were no overloads this would be pretty easy since then I wouldn't have to supply the Type.GetMethod method with an array of argument types for the method. But this method has 5 overloads, so I need to be specific to the GetMethod method. The problem is that I have not tried to get a type of a pointer before so I didn't know what to write.

By calling the Type.GetMethods method I get a list of all the methods that the String class has. In that list I find the specific overload of AppendInPlace and by examining the MethodInfo that is returned I can see what the type is called. It was actually pretty simple: System.Char*

Knowing that I can now create the array of types and get the correct MethodInfo instance:

   Type type = typeof( String );

   BindingFlags internalInstance = BindingFlags.NonPublic | BindingFlags.Instance;

   Type[] types = GetTypeArray( Type.GetType( "System.Char*" ), count.GetType(), currentLength.GetType() );

   MethodInfo info = type.GetMethod( "AppendInPlace", internalInstance, null, types, null );


Invoking the method
Now everything is good to go, we have the MethodInfo, the arguments and the object to invoke the method on, what can possibly go wrong? Oh yeah, you cannot pass a Char* to a method that takes an array of objects as MethodInfo.Invoke does. But luckily the solution was quite easy. You just have to create an instance of IntPtr using the Char* in the constructor, like this:

   Object[] objects = GetObjectArray( new IntPtr( value ), count, currentLength );

   info.Invoke( str, objects );


That's all there is to it.
Read more!

Thursday, October 18, 2007

A nice SVN (Subversion) feature

Generally I like to use SVN as my source repository. I have several reasons for this, but the main reason is that you're not only getting a tool that works, you're also getting small surprises once i while. I got this one today:


What happened here was that I was renaming NewDefault.aspx to Default.aspx and then TortoiseSVN detected that maybe I would like to rename the C# file as well.

If you are a .NET programmer you're probably sitting right now saying to yourself that Visual Studio does this for you, but I'm not renaming from within Visual Studio, I'm actually renaming the files in the Windows Explorer, thanks to TortoiseSVN.

Don't miss out on the SVN fun:
SVN (client)
TortoiseSVN (Windows Shell extension)
AnkhSVN (Visual Studio addin)
SVNRepository.com (Hosted SVN - Great service!!)
Read more!

Sunday, October 7, 2007

The balcony with no access


Often when you put in a balcony you also put in some kind of way to access the balcony. This picture was taken not far from where I live.
Read more!

Wednesday, October 3, 2007

Multi row delete in DataGridView

A couple of weeks ago a colleague of mine asked me about how to have a delete confirmation dialog to show only once even if there is multiple rows to be deleted from a System.Windows.Forms.DataGridView.
There are three events on the DataGridView which is directly related to row deletion: "RowsRemoved", "UserDeletedRow" and "UserDeletingRow". Entertaining enough all of them are called once for each row that is to be deleted.

Sadly I did not have a solution at hand and I kept wondering how to solve that problem. Today I sat down and tried to solve the problem.

I quickly found that adding a KeyDown event handler and then monitor the Delete key could do the trick. All I had to do was to ask the user and set "e.Handled" to true if I did not want to delete the rows.

  private void fruitsDataGridView_KeyDown( object sender, KeyEventArgs e )

  {

   Int32 count = this.fruitsDataGridView.SelectedRows.Count;

   if( count.Equals( 0 ) )

   {

    return;

   }

 

   e.Handled = !this.ConfirmDeletion( count );

  }


However, simple as it was I did not like the solution. So I started looking at the Call Stack to see which methods would help raising the three events that is raised once per row. A couple of lines down the Call Stack I found a method named "ProcessDeleteKey", nice! This method was for once not marked private or internal, but someone "forgot" to add the virtual keyword to the method's signature, so I were not able to override it. So I looked at the method that called the "ProcessDeleteKey". It is named "ProcessDataGridViewKey" and is both protected and virtual. So I quickly made a new class inheriting from DataGridView and made an overridden "ProcessDataGridViewKey" method where I could check for the Delete key and take action if needed. Additionally I added a new event to the class named UserDeletingRows that would be called once per deletion batch.

  protected virtual Boolean ProcessDeleteKey( KeyEventArgs e )

  {

   if( !this.AllowUserToDeleteRows )

   {

    return false;

   }

 

   if( this.EditingControl != null )

   {

    return false;

   }

 

   CancelEventArgs args = new CancelEventArgs( false );

   this.OnUserDeletingRows( args );

   if( args.Cancel )

   {

    return true;

   }

 

   return base.ProcessDeleteKey( e.KeyData );

  }


The Solution
Although the first solution is simpler, I find that the second solution is much better, because having the implementation within the grid class should make it be used more often. If only I can find a better name for the new event.

Both solutions are included in the downloadable project.

Download
To download the full project click here.


Solution: Visual Studio 2005
Language: C#
Framework: 2.0


Read more!

Monday, October 1, 2007

String References Part 2

In a previous post I wrote that two identical strings would always have the same reference. Now let's go the whole way in true MythBusters style and try to break the rule!

So how do we break the rule? Well I'll start by defining the scenarios I believe could be able to force .NET into creating two different references. When I have done that I'll test them one by one.

Overview of the Tests


  • The System.String.Clone() method.

  • Creating one of the String objects by concatenating two other String objects.

  • Creating one of the String objects through System.Text.StringBuilder.

  • Parsing through a String to a method using "ref" keyword.

  • Creating the two objects in two different assemblies.

  • Loading in 50MB texts into the two String objects.

  • The System.String( Char* ) constructor.

  • Binary Deserialization.

  • The System.Runtime.InteropServices.Marshal.PtrToStringUni( IntPtr ) method.


The System.String.Clone() method
This test is very simple. Just call the Clone() method and then compare the results. I'm pretty sure this will work, after all a Clone() implementation shouldn't return it's own instance.

Creating one of the String objects by concatenating two other String objects
This test is just as simple as the previous. I don't think this will actually change the reference.

Creating one of the String objects through System.Text.StringBuilder
Again we're dealing with a simple test. I'm not sure what I expect from this test, but if I have to choose I say 49.9% for different references and 51.1% for the opposite.

Parsing through a String to a method using "ref" keyword
Yet another simple test. The references should be the same, but you can always hope.

Creating the two objects in two different assemblies
This was a suggestion I got from a colleague. I can see the idea, but I have my doubts because as soon as I reference them, they will exist in the same AppDomain.

Loading in 50MB texts into the two String objects
The idea behind this test is that if .NET uses GetHashCode() to index the strings it might not be that quick when working with larger strings and therefore should have an upper limit of how long strings may be for the string indexing engine. Besides if it is using the GetHashCode() two nonidentical strings could actually end up returning the same hash code. Personally I think the references will still be the same in this test.

The System.String( Char* ) constructor
This is my personal favorite. I believe that this test will result in two different references. Because the characters is placed in the memory in the same way as the String object wants it to be, the String object can just use the pointer as reference.

Binary Deserialization
I admit it, I was searching for a couple more tests at this point. None the less it might actually work.

The System.Runtime.InteropServices.Marshal.PtrToStringUni( IntPtr ) method
Well this is the first time I'm actually using this method but from the name I guess that it will return the same reference.

This was a short description of all the tests. Before I'll let you see the results I think that you should have the chance of downloading the project to try it out for yourself. As usual it's a Visual Studio 2005 C# project targeted the Windows platform.


Download
To download the full project click here.


And now....








for the results!!


I have to admit that I'm very surprised to see that the String.Clone() method did not change the reference. By looking at the code for the method you will quickly see why:

  public object Clone()

  {

   return this;

  }


Microsoft probably implemented it like this with the "identical strings share the same reference" rule in mind. When looking at it in that way the implementation is valid.

The Conclusion
From this test I can safely state that it is possible to have two identical strings with different references.


Read more!