Go to content Go to navigation Go to search

System.Timers.Timer still broken
· 16 days ago by Thijs Kroesbergen for Brokenwire.NET

About one year ago I wrote about System.Timer.Timer and it’s exception silencing capabilities. Now the .NET framework version 4 is almost done I thought it would be nice to do the same test again on the brand new framework. And guess what? It’s still broken!

Just to be clear what’s happening here: when an exception is thrown in the .Elapsed event of a System.Timers.Timer object then the exception gets silenced by an empty catch block within the framework code surrounding this event. You can see the sample code for reproducing this in my previous post.

Now there are many discussions about the usage of empty catch blocks but the general opinion seems to be that empty catch blocks are usually a bad idea. So why is this not fixed yet?

There is even a Microsoft Connect bug for this issue, in which we are promised that this will be fixed in “a next version of the framework”. That bug was opened in 2007…

So, if you want .Net framework 4 to suck a little bit less: go HERE and vote for this bug. And remember: You ARE the framework ;)

Comment - Permalink -

Fix: Virtualbox causes "Unidentified" network on Vista and Windows 7
· 24 days ago by Thijs Kroesbergen for Brokenwire.NET

The problem:

When you install Virtualbox on Windows Vista or Windows 7 it will install an additional virtual network adapter on the host system. This “Virtualbox Host-Only Adapter” causes the Windows network detection to show an additional “unidentified” network. And while this “unidentified” network is present the windows firewall settings will stay on “Public”. This behavior is undesirable because you want to be able to switch your firewall settings based on your location (home/work/public).


The solution (manually):

WARNING; DANGER: THE REGISTRY IS NO PLAYGROUND, IF YOU DON’T UNDERSTAND WHAT YOU’RE DOING THEN DON’T DO IT!
Now we have that out of the way, here is what you should do:

1. Open regedit and navigate to HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}

2. Browse through the subkeys (named 0000, 0001, etc) until you find the subkey containing the virtualbox network adapter, this is the one where the “DriverDesc” key has “VirtualBox Host-Only Ethernet Adapter” as value.

3. Add a new DWORD value with a name of “*NdisDeviceType” and a value of “1

4. Disable en re-enable the virtuabox host-only network adapter, or alternatively reboot your pc.

The solution (PowerShell)

I hacked together this PowerShell script to easily re-do this trick after a virtualbox upgrade. The script has only been tested on my pc (and it works), use at your own risk. You need to run an elevated PowerShell shell to modify the registry.

$devices = "HKLM:\SYSTEM\CurrentControlSet\Control\Class\*"
$adapters = Get-ItemProperty $devices | Where-Object  {$_.Class -eq "Net"} | Foreach-Object { $_.PSPath }
Get-ChildItem $adapters -erroraction silentlycontinue | Foreach-Object { get-itemproperty -path $_.PSPath } | Where-Object {$_.ComponentId -eq "sun_vboxnetadp"} | Foreach-Object { Set-ItemProperty -path $_.PSPath -name "*NdisDeviceType" -Type DWORD -Value 1}
Get-WmiObject -Class Win32_NetworkAdapter | Where-Object {$_.Name -like "*Virtualbox Host*"} | Foreach-Object {$_.Disable(); $_.Enable()}

Why this registry fix fixes that:

There is actually an MSDN article that describes the possible registry keys for network adapters:

*NdisDeviceType

The type of the device. The default value is zero, which indicates a standard networking device that connects to a network. Set *NdisDeviceType to NDIS_DEVICE_TYPE_ENDPOINT (1) if this device is an endpoint device and is not a true network interface that connects to a network. For example, you must specify NDIS_DEVICE_TYPE_ENDPOINT for devices such as smart phones that use a networking infrastructure to communicate to the local computer system but do not provide connectivity to an external network.

And

Note  Windows Vista automatically identifies and monitors the networks to which a computer connects. If the NDIS_DEVICE_TYPE_ENDPOINT flag is set, the device is an endpoint device and is not a connection to a true external network. Consequently, Windows ignores the endpoint device when Windows identifies networks. The Network Awareness APIs indicate that the device does not connect the computer to a network. For end users in this situation, the Network and Sharing Center and the network icon in the notification area do not show the NDIS endpoint device as connected. However, the connection is shown in the Network Connections Folder.

More

Similar problem and similar fix for vmware:

http://aspoc.net/archives/2008/10/30/unidentified-network-issue-with-vmwares-virtual-nics-in-vista/

With a much nicer powershell script:

http://www.nivot.org/2008/09/05/VMWareVMNETAdaptersTriggeringPublicProfileForWindowsFirewall.aspx

And the virtualbox forums thread that pointed me in the right direction:

http://forums.virtualbox.org/viewtopic.php?f=6&t=17153#p73167

Comment - Permalink -

Christmas Lights updated
· 90 days ago by Thijs Kroesbergen for Brokenwire.NET

I just published a new version of the popular Christmas Lights. You can grab your free copy from the publish page right now.

So what’s new in this years update?

- New light bulbs: The new bulbs are bitmap based instead of “dynamic” WPF shapes, this reduces the CPU usage. And I think these look nicer too.

- Better stability: I resolved several issues which caused crashes when you changed the display resolution when the lights where active. Now you can also add/remove monitors while the lights are running.

- Plasma “burn-in” prevention: When this option is switched on the lights move a bit every minute so they don’t burn in your nice big plasma TV. :)

- Fully tested on Windows 7 but the lights will run on any pc having .NET framework 3.5(sp1). (This includes Windows XP, Vista, Server 2003)

DOWNLOAD NOW

I’ve already got some nice ideas for a future version, but suggestions (or patches) are always welcome!

Possible features for a next version:

- Make the blinking speed dependant on the power level of your laptop battery: As the battery gets empty the lights should blink slower (or faster).

- Make the lights blink when sound is detected, so they can sync up with your favorite Christmas tunes.

- Create more blinking patterns and add a pattern to cycle through all other patterns.

So prepare your PC for the Christmas season and install the lights!
And if you are curious about the code that makes all that goodness happen, take a look at the “Wpf Christmas Lights” CodePlex project page. There you can also report bugs or post suggestions.

Happy Holidays!

Comment - Permalink -

Building .NET 1.1 projects with Team Foundation Server
· 101 days ago by Thijs Kroesbergen for Brokenwire.NET

Recently Olav Kwakman and I collaborated for the challenge to build .NET 1.1 code with a TFS 2008 build environment.

After configuring the build server we asked Captain Google what to do, and we implemented approach two described in the following blog post but the important thing is that we added one extra feature.

In approach #2 of Nagaraju's blog he modifies the output directory by adding an <ItemGroup> in the build script and writes the output to that directory in the After Compile Target Group. The problem with this solution is that the list of file in the ItemGroup is being initialized before the solution is being build. Therefore when your solution output changes the build will not pick this up the first time around. (This is a common "issue" with listing files in itemgroups, many have been tricked into this problem before)

By creating the ItemGroup at runtime (using an CreateItem task) this problem will not occur. Here's how you do just that:

<CreateItem Include ="$(SolutionRoot)\**\bin\$(VS2003_Configuration)\**\*.*">
<Output ItemName ="VS2003_OutputFiles" TaskParameter="Include"/>
</CreateItem>

The complete build script will look like this:

<PropertyGroup>
<VS2003_Devenv>$(ProgramFiles)\Microsoft Visual Studio .NET 2003\Common7\IDE\devenv.com</VS2003_Devenv>
<VS2003_Configuration>Debug</VS2003_Configuration>
</PropertyGroup>

<Target Name="AfterCompile">
<Exec Command="&quot;$(VS2003_Devenv)&quot; &quot;$(SolutionRoot)\Your .Net1.1 Solution.sln&quot; /build $(VS2003_Configuration)" />
<CreateItem Include ="$(SolutionRoot)\**\bin\$(VS2003_Configuration)\**\*.*">
<Output ItemName ="VS2003_OutputFiles" TaskParameter="Include"/>
</CreateItem>
<MakeDir
Directories="$(BinariesRoot)\$(VS2003_Configuration)"
Condition="!Exists('$(BinariesRoot)\$(VS2003_Configuration)')" />
<Copy SourceFiles="@(VS2003_OutputFiles)"
DestinationFiles="@(VS2003_OutputFiles->'$(BinariesRoot)\$(VS2003_Configuration)\%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>

Of course it would be better not to build .NET 1.1 code anymore and just upgrade your projects to a newer version of the .NET framework. From our .NET build jungle Olav and I wish you happy coding...

Comment - Permalink -

Run ClickOnce app on startup
· 197 days ago by Thijs Kroesbergen for Brokenwire.NET

While toying with a small ClickOnce application I found out that there wasn’t an easy way to launch the app automatically on Windows startup. Of course I wasn’t the first one to have this problem so I started reading Ben Griswold aka Johnny Coder’s blog post on this topic. He sums up the pros and cons of several solutions nicely. (So go read that now, I’ll wait here.)

After trying out some of his suggestions I came up with the following plan:

I’ll put a shortcut in the Startup folder of the start menu. This shortcut will point to the executable file of my application, but it will start it with an additional parameter (“-L”). When the application detects that it is being run with this parameter it doesn’t show any of its forms, but just starts the .appref-ms shortcut that is already in the start menu. This shortcut will then start the application just as if the user him/herself clicked it.

The good thing about this solution is that this also fools Vista in starting a ClickOnce app on startup (so it WORKS!).

Why is this the best solution?

One small drawback: if the application is uninstalled then the shortcut in the startup folder will be left behind…

Code, show me code! Okay, so here is the code:

To install the shortcut in the startup folder of the start menu I’ve written this Install method. The ShellLink class is a wrapper around the windows API to make a shortcut. The corresponding article about creating and modifying shortcuts using C# can be found on vbaccelerator.com.

public static void Install()
{
  ShellLink shortcut = new ShellLink();
  shortcut.Target = Application.ExecutablePath;
  shortcut.Arguments = "-l";
  shortcut.WorkingDirectory = Path.GetDirectoryName(Application.ExecutablePath);
  shortcut.Description = "Start TestApp";
  shortcut.DisplayMode = ShellLink.LinkDisplayMode.edmMinimized;
  shortcut.Save(shortcutFileName);
}

Then to have the application launch itself, I've modified the Main method in Program.cs:

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
  if (args.Contains("-L"))
  {
    AppLauncher.Launch();
  }
  else
  {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new TestForm());
  }
}

The “Launch” method that finds the shortcut for the ClickOnce application and starts it via Process.Start. The determination of the location of the .appref-ms file can be a bit tricky, this code works for me but your mileage may vary.

public static void Launch()
{
  string shortcutFileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), "Start TestApp.lnk");
  string publisherName = Application.CompanyName;
  string productName = Application.ProductName;
  string allProgramsPath = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
  string shortcutPath = Path.Combine(allProgramsPath, publisherName);
  shortcutPath = Path.Combine(shortcutPath, productName) + ".appref-ms";
  System.Diagnostics.Process.Start(shortcutPath);
}

You can try it out for yourself with this small sample:

ClickOnceStartupTestApp.zip which is also published here: http://www.brokenwire.net/~thijs/clickoncestartup/publish.htm

Have fun!

Comment [4] - Permalink -

The madness of “exclusive” row locks
· 260 days ago by Thijs Kroesbergen for Brokenwire.NET

Yesterday I discovered some really weird behavior of SQL Server. I had a case where I could read a record that was exclusively locked by someone else. Considering the word “exclusive” you would expect that when one transaction has an exclusive rowlock an other transaction would be unable to read that same row. But there is one specific case where this isn’t true. In that case it is possible to read a record that is locked exclusively by someone else.

It took me (together with a colleague) a lot of time to finally find out what was happening.

To reproduce this behavior you need a test-table with some random data in it.

CREATE TABLE [MyTable]
 ([Col1] bigint PRIMARY KEY CLUSTERED, [Col2] bigint)
INSERT INTO [MyTable] ([Col1], [Col2]) VALUES (1,10)
INSERT INTO [MyTable] ([Col1], [Col2]) VALUES (2,20)
INSERT INTO [MyTable] ([Col1], [Col2]) VALUES (3,30)
INSERT INTO [MyTable] ([Col1], [Col2]) VALUES (4,40)
INSERT INTO [MyTable] ([Col1], [Col2]) VALUES (5,50)

You can put this table in any database, as long as it doesn’t have snapshot isolation turned on. The recovery model for your database doesn’t matter.

Now let’s run some queries and see what happens. To be able to test this properly you should run two different session against this table. To be able to hold (and see) the locks that used you need to start a transaction and run some statements, but don’t complete the transaction (yet).

First in the first window of the Query Analyzer (which I’ll refer to as session 1) select one row from the table and request an exclusive rowlock on it with the XLOCK and ROWLOCK table hints.

session 1:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN TRAN
SELECT Col1 FROM [MyTable] WITH (XLOCK, ROWLOCK) WHERE [Col1] = 3

To verify the locks that where put into place you can run sp_locks to check the locks that are granted to the connection (spid) that you used to perform the actions for session 1.

spid   dbid   ObjId       IndId  Type Resource                         Mode     Status
------ ------ ----------- ------ ---- -------------------------------- -------- ------
56     21     69575286    1      PAG  1:41                             IX       GRANT
56     21     69575286    1      KEY  (030075275214)                   X        GRANT
56     21     69575286    0      TAB                                   IX       GRANT

As you can see there is an “X” (exclusive) lock on the first key of this table. (The other locks are “IX” (intentional)). Now let’s move to session 2 and see if we can we retrieve that record.

session 2:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN TRAN
SELECT Col1 FROM [MyTable] WHERE [Col1] = 3

I did expected this statement to just “hang” while waiting for the record to come available. But I was surprised to see that the record could be retrieved without a problem. Also, sp_locks doesn’t show any additional locks for this statement, not even a shared lock!

If you rollback session 2 (to clear everything that might have happened) and retry it with the HOLDLOCK table hint you do get the expected behavior, because the select in session 2 now will wait for the transaction in session 1 to complete.

To understand what is happening here you should remember one of the rules of read committed data access. This rule says that you can read any row as long as it’s in a committed state. The row we’re trying to read here is in a “clean” state (it’s not marked “dirty” by the system). In this case the optimizer decides that it doesn’t hurt to retrieve it via the index without checking for locks. So your table doesn’t even need a primary key, a long as you have an index containing the requested data the rowlocks may be skipped at will.

So if the locked record has not changed and the data for requested columns is stored in an index and you are working from an READ COMMITTED isolation level then the exclusive lock is possibly not honored.

One possible workaround is to add a “HOLDLOCK” table hint to the select in session 2. Alternatively you can actually update the record to have it exclusively locked (and marked “dirty”) in session 1. The last possibility is to lock an entire page instead of just one row by using the PAGLOCK hint. Exclusive page locks do prevent all other readers for the rows in that page.

There’s a thread on http://social.msdn.microsoft.com/ posted by someone who has observed the same weird locking behavior. A Microsoft employee responded with:

Using XLOCK in SELECT statements will not prevent reads from happening. This is because SQL Server has a special optimization under read committed isolation level that checks if the row is dirty or not and ignores the xlock if the row has not changed. Since this is acceptable under the read committed isolation level semantics it is by design.

Perhaps the worst thing about all this is that this behavior cannot be found easily in the Books Online. A small note somewhere in the section about table hints would have be nice. There are some hints in KB324417 (which applies to Sql Server 2000). Combine all that with the fact that the optimizer may choose to do this at will, you’ll have a very hard to find bug in your sql code.

Conclusion:

It took me a lot of time to find out what was going on here. So remember kids: a SELECT with XLOCK and ROWLOCK hints doesn’t mean that you are the only one who can read those rows!

Comment [2] - Permalink -

Previous