Bert's profileBert's weblogBlogLists Tools Help

Bert

Occupation
Location

Bert's weblog

A collection of things lingering in my mind
January 31

Miguel de Icaza says that the EU Prosecutors are Wrong.

 

Miguel de Icaza wrote a an article about the war that's going on between Microsoft and the EU, especially about the new open XML formats used in Microsoft Office 2007. He states that's there's nothing wrong with these formats and fighting against them is pointless... According to him the only thing the open source community could do is making Open Office a better product than Microsoft Office 2007, and that to me sounds as a nearly impossible task to complete :-)

Link to Miguel de Icaza: The EU Prosecutors are Wrong.

Technorati tags: ,
    
del.icio.us tags: ,
October 30

Don’t Click It

Don’t Click It is an experiment in human interface design. It is a strange one.

You are allowed one click to start off the interface, and from then on as you use the mouse to grok the interface, you are warned not to click.

If you do so, you shock the monkey and you are asked why you clicked. If you haven’t clicked in awhile you will be surveyed on if you miss it: “Do you miss the click within this interface”.

It is highly strange to navigate for an extended period without clicking.

Don\'t click it 

 

Technorati tags: ,
 
del.icio.us tags: ,

October 29

Visual Studio 2005 IDE Enhancements

 

Microsoft has released a set of Visual Studio enhancements that are designed to make you more productive. These enhancements where previously part of the Visual Studio SDK, but are now available as a separate download. Features included are:

  • Source Code Outliner : The Source Outliner tool is a Visual Studio extension that provides a tree view of your source code's types and members and lets you quickly navigate to them inside the editor.
  • Visual C++ Code Snippets:The Visual C++ Code Snippets tool lets you insert snippets in your code by using a pop-up menu that contains programming keywords. VB.NET and C# languages have this functionality in Visual Studio 2005.
  • Indexed Find : The Indexed Find tool is a Visual Studio extension that uses the Microsoft Indexing Service to provide improved Search capabilities to the integrated development environment (IDE). It sends the results of a search to the Output Window.
  • Super Diff Utility: The Super Diff Find tool is a Visual Studio extension that compares text files. It uses color coding and graphics to show the difference between the files in deleted text (red), changed text (blue), inserted text (green).
  • Event Toaster Utility: The Event Toaster tool is a Visual Studio extension that notifies users about specific events within the Visual Studio IDE.

This is a free download which can be obtained here.

del.icio.us tags:
       
Technorati tags:

October 26

Fetching TCP/IP routing information using C#...and P/Invoke, part 2

Recently I wrote about TCP/IP routing and how to list the routing table using C#. In this article I'll continue this subject, but before digging into code I'll explain why I wrote this code:

I've architected a typical smart client application with as major requirement to be able to work online and offline and very important to work using expensive and sometimes slow communication technologies like GPRS and UMTS (3G). In this application it's crucial that we know which network adapter is used for communication with the back office because we do need to upload locally generated docs. If we would do this using a pay-per-bit type technology like GPRS or UMTS then this would be very costly... In essence knowing the used network adapter gives you the capability to gradually allow more application features depending on the type, speed and stability of the used network.

1. A slight update of the code mentioned in list the routing table using C#: instead of displaying the route information it will be stored in a list of IPRouteTable objects which are defined like this:

IPRouteTable class: - Copy Code
public class IPRouteTable { private int ifIndex = 0; private string ifIP = ""; private int ifMetric = 0; private string ifName = ""; private string ifDescription = ""; private NetworkInterfaceType ifType; private OperationalStatus ifStatus; private long ifSpeed = 0; public string IfName { get { return ifName; } set { ifName = value; } } public string IfDescription { get { return ifDescription; } set { ifDescription = value; } } public NetworkInterfaceType IfType { get { return ifType; } set { ifType = value; } } public OperationalStatus IfStatus { get { return ifStatus; } set { ifStatus = value; } } public long IfSpeed { get { return ifSpeed; } set { ifSpeed = value; } } public IPRouteTable(int ifIndex, int ifMetric) { this.ifIndex = ifIndex; this.ifMetric = ifMetric; } public int IfIndex { get { return ifIndex; } set { ifIndex = value; } } public string IfIP { get { return ifIP; } set { ifIP = value; } } public int IfMetric { get { return ifMetric; } set { ifMetric = value; } } }

The code below replaces the Console.WriteLine part from my previous code :

Copy Code
for (int i = 0; i < entries; i++) { ip = IPToString(IPAddress.NetworkToHostOrder(table[i].dwForwardDest)); if (ip == "0.0.0.0") { ipRoute = new IPRouteTable(table[i].dwForwardIfIndex, table[i].dwForwardMetric1); ipRouteList.Add(ipRoute); } }

All routes with forward destination of 0.0.0.0 are added because these all are default routes.

2. Complete the information in the IPRouteTable objects with the IP address of the used adapter for each default route:

We start with the necessary structs and DLL imports:

Copy Code
[StructLayout(LayoutKind.Sequential)] struct MIB_IPADDRROW { public int dwAddr; public int dwIndex; public int dwMask; public int dwBCastAddr; public int dwReasmSize; public short unused1; public short unused2; } [DllImport("IpHlpApi.dll")] static extern int GetIpAddrTable( IntPtr pIpAddrTable, ref int pdwSize, bool bOrder);

The method below will complete IPRouteTable with the IP address:

Copy Code
private void LinkWithInterfaceAddresses() { IntPtr pBuf = IntPtr.Zero; int nBufSize = 0; GetIpAddrTable(IntPtr.Zero, ref nBufSize, false); try { pBuf = Marshal.AllocHGlobal(nBufSize); int r = GetIpAddrTable(pBuf, ref nBufSize, false); if (r != 0) throw new System.ComponentModel.Win32Exception(r); Type tIPAddrRow = typeof(MIB_IPADDRROW); int nNumRows = Marshal.ReadInt32(pBuf); IntPtr pRow = unchecked((IntPtr)((int)pBuf + 4)); while (nNumRows-- > 0) { MIB_IPADDRROW row = (MIB_IPADDRROW)Marshal.PtrToStructure(pRow, tIPAddrRow); foreach (IPRouteTable tab in ipRouteList) { if (tab.IfIndex == row.dwIndex) { tab.IfIP = IPToString(IPAddress.NetworkToHostOrder(row.dwAddr)); } } pRow = unchecked((IntPtr)((int)pRow + Marshal.SizeOf(tIPAddrRow))); } } finally { if (pBuf != IntPtr.Zero) Marshal.FreeHGlobal(pBuf); } }

3. The last step is to process all the gathered information and return an object (ConnectionInformation) to the consumer that describes the currently used IP route:

ConnectionInformation - Copy Code
public class ConnectionInformation { private string connectionType; private long connectionSpeed; private bool fastNetwork; public ConnectionInformation() { } public ConnectionInformation(string connectionType, long connectionSpeed, bool fastNetwork) { this.connectionSpeed = connectionSpeed; this.connectionType = connectionType; this.fastNetwork = fastNetwork; } public string ConnectionType { get { return connectionType; } set { connectionType = value; } } public long ConnectionSpeed { get { return connectionSpeed; } set { connectionSpeed = value; } } public bool FastNetwork { get { return fastNetwork; } set { fastNetwork = value; } } }

This object is constructed in the code below:

Copy Code
ConnectionInformation con = new ConnectionInformation("",0,false); int currentMetric = int.MaxValue; foreach (IPRouteTable tab in ipRouteList) { if (tab.IfDescription.IndexOf("VPN") == -1) { if (tab.IfMetric < currentMetric) { if (tab.IfType == NetworkInterfaceType.Ppp) { if ((tab.IfSpeed / 1000) < 120) { con.ConnectionType = "GPRS"; con.ConnectionSpeed = tab.IfSpeed / 1000; } else { con.ConnectionType = "UMTS/GPRS"; con.ConnectionSpeed = tab.IfSpeed / 1000; } } else { if (tab.IfType == NetworkInterfaceType.Ethernet || tab.IfType == NetworkInterfaceType.GigabitEthernet) { if (tab.IfDescription.IndexOf("Wireless") == -1) { con.ConnectionType = "LAN"; con.ConnectionSpeed = tab.IfSpeed / 1000; } else { con.ConnectionType = "WIRELESS"; con.ConnectionSpeed = tab.IfSpeed / 1000; } } else if (tab.IfType == NetworkInterfaceType.Wireless80211) { con.ConnectionType = "WIRELESS"; con.ConnectionSpeed = tab.IfSpeed / 1000; } } currentMetric = tab.IfMetric; } } } //foreach (IPRouteTable tab in ipRouteList) con.FastNetwork = this.IsFastNetwork(con);

The code fragment above filters out possible VPN tunnels (when you open a VPN, then the VPN appears as a route with normally the lowest metric) by just checking on the string VPN in the adapter name: if someone knows a clean solution for this, please let me know.

If you want a complete working solution containing all the code of this and the previous post then please drop me a comment and I'll mail it to you.

Technorati tags: , ,

del.icio.us tags: , ,
October 24

An important step, take 2

In my last post I spoke about an important step I've taken. Well it's time to give you all some more details: I'll be joining the Microsoft Belgium as an Architect within the Microsoft Consultancy & Services team. smile_teeth I'm very delighted with this and I can't wait to get started, but first I have to finish my current Real Software assignments...

October 18

An important step

 

This week I've taken an important step regarding my future career. It's still to soon to reveal more details...but stay tuned and you'll get to know what's this all about...

October 13

Google Code search versus Krugle, Koders, and Codease

 

Google recently announced Google Code Search which allows one to quickly search the code of open-source projects. Completing it with a regex enabled search this results in a quite a powerful code search engine, but how does it compare against the existing code search engines like Krugle, Koders, and Codease ? I haven't used Koders are Codease yet, but if I compare Krugle against Google code search then I'm afraid that the investors behind Krugle are getting a bit nervous smile_regular 

On the web you can find several pages which list all kind issues in open-source code ranging from funny comments from the developers up to buffer-overflows and hidden passwords and backdoors. A nice selection of these can be found here.

October 11

ClickOnce for the enterprise

 

Recently a nice article about ClickOnce in enterprise environments has been published onto MSDN. The author (Brian Noyes) describes his paper as:

ClickOnce provides an easy-to-use and flexible deployment mechanism for smart client applications built for the .NET Framework 2.0. ClickOnce offers end-user deployment, ready-made installation dialogs, a built-in security model, and automatic or on-demand updates. But while it's great to have so many built-in features, one area that users often request more control is in tracking who uses which applications, controlling access to those applications, and knowing when something goes wrong. You may just need to keep track of who is using which versions of each application at the user level. You may want to restrict access to certain applications and updates based on a user's identity or their association with a role or group. You may want to know when launch errors have occurred for particular users so that you can troubleshoot deployment problems if they exist.

This whitepaper discusses all of these scenarios. It identifies the places you can insert your own code or tools into the process for control or monitoring purposes. Several alternative solutions will be discussed, allowing you to pick the approach that provides the best trade-off of complexity and control given your requirements. This whitepaper also identifies potential hazards of certain solutions that may seem like a good idea, but that can lead to fragility or unexpected results. Along the way, I give you insight into what artifacts are being placed where when you publish and deploy a ClickOnce application.

 

del.icio.us tags:
     
Technorati tags:
October 06

Fetching TCP/IP routing information using C#...and P/Invoke

 

This article is a follow-up on the article about finding the used TCP/IP route which you can read here. Using the GetIpForwardTable API it's possible to fetch almost the same information then outputted by the route print command.

The first step will be to declare the appropriate structs and DLL imports:

[StructLayout(LayoutKind.Sequential)] public struct MIB_IPFORWARDROW { [MarshalAs(UnmanagedType.U4)] public int dwForwardDest; // IP addr of destination [MarshalAs(UnmanagedType.U4)] public int dwForwardMask; // subnetwork mask of destination [MarshalAs(UnmanagedType.U4)] public int dwForwardPolicy; // conditions for multi-path route [MarshalAs(UnmanagedType.U4)] public int dwForwardNextHop; // IP address of next hop [MarshalAs(UnmanagedType.U4)] public int dwForwardIfIndex; // index of interface [MarshalAs(UnmanagedType.U4)] public int dwForwardType; // route type [MarshalAs(UnmanagedType.U4)] public int dwForwardProto; // protocol that generated route [MarshalAs(UnmanagedType.U4)] public int dwForwardAge; // age of route [MarshalAs(UnmanagedType.U4)] public int dwForwardNextHopAS; // autonomous system number [MarshalAs(UnmanagedType.U4)] public int dwForwardMetric1; // protocol-specific metric [MarshalAs(UnmanagedType.U4)] public int dwForwardMetric2; // protocol-specific metric [MarshalAs(UnmanagedType.U4)] public int dwForwardMetric3; // protocol-specific metric [MarshalAs(UnmanagedType.U4)] public int dwForwardMetric4; // protocol-specific metric [MarshalAs(UnmanagedType.U4)] public int dwForwardMetric5; // protocol-specific metric } [DllImport("IpHlpApi.dll")] [return: MarshalAs(UnmanagedType.U4)] static extern int GetIpForwardTable( IntPtr pIpForwardTable, [MarshalAs(UnmanagedType.U4)] ref int pdwSize, bool bOrder); const int ERROR_INSUFFICIENT_BUFFER = 122;

Once that's done we can start getting our hands dirty writing some nasty code to use the GetIpForwardTable API:

private static void PrintRouteList() { // The number of bytes needed. int bytesNeeded = 0; // The result from the API call. int result = GetIpForwardTable(IntPtr.Zero, ref bytesNeeded, false); // Call the function, expecting an insufficient buffer. if (result != ERROR_INSUFFICIENT_BUFFER) { // Throw an exception. throw new Win32Exception(result); } // Allocate the memory, do it in a try/finally block, to ensure // that it is released. IntPtr buffer = IntPtr.Zero; try { // Allocate the memory. buffer = Marshal.AllocCoTaskMem(bytesNeeded); // Make the call again. If it did not succeed, then // raise an error. result = GetIpForwardTable(buffer, ref bytesNeeded, false); // If the result is not 0 (no error), then throw an exception. if (result != 0) { // Throw an exception. throw new Win32Exception(result); } // Now we have the buffer, we have to marshal it. We can read // the first 4 bytes to get the length of the buffer. int entries = Marshal.ReadInt32(buffer); // Increment the memory pointer by the size of the int. IntPtr currentBuffer = new IntPtr(buffer.ToInt64() + Marshal.SizeOf(new int())); // Allocate an array of entries. MIB_IPFORWARDROW[] table = new MIB_IPFORWARDROW[entries]; // Cycle through the entries. for (int index = 0; index < entries; index++) { // Call PtrToStructure, getting the structure information. table[index] = (MIB_IPFORWARDROW)Marshal.PtrToStructure(new IntPtr(currentBuffer.ToInt64() + (index * Marshal.SizeOf(typeof(MIB_IPFORWARDROW)))), typeof(MIB_IPFORWARDROW)); } string ip = ""; for (int i = 0; i < entries; i++) { ip = IPToString(IPAddress.NetworkToHostOrder(table[i].dwForwardDest)); Console.WriteLine("Destination: {0} Interface index: {1} Metric: {2}", ip, table[i].dwForwardIfIndex, table[i].dwForwardMetric1); if (ip == "0.0.0.0") { Console.WriteLine("This is the default route!"); } } } finally { // Release the memory. Marshal.FreeCoTaskMem(buffer); } } private static string IPToString(int ipaddr) { return String.Format("{0}.{1}.{2}.{3}", (ipaddr >> 24) & 0xFF, (ipaddr >> 16) & 0xFF, (ipaddr >> 8) & 0xFF, ipaddr & 0xFF); }

When you use this method then following output is generated:

Destination: 0.0.0.0 Interface index: 65544 Metric: 30 This is the default route! Destination: 127.0.0.0 Interface index: 1 Metric: 1 Destination: 192.168.163.0 Interface index: 2 Metric: 20 Destination: 192.168.163.1 Interface index: 1 Metric: 20 Destination: 192.168.163.255 Interface index: 2 Metric: 20 Destination: 192.168.238.0 Interface index: 3 Metric: 20 Destination: 192.168.238.1 Interface index: 1 Metric: 20 Destination: 192.168.238.255 Interface index: 3 Metric: 20 Destination: 192.168.240.0 Interface index: 65544 Metric: 30 Destination: 192.168.240.100 Interface index: 1 Metric: 30 Destination: 192.168.240.255 Interface index: 65544 Metric: 30 Destination: 224.0.0.0 Interface index: 3 Metric: 20 Destination: 224.0.0.0 Interface index: 2 Metric: 20 Destination: 224.0.0.0 Interface index: 65544 Metric: 30 Destination: 255.255.255.255 Interface index: 5 Metric: 1 Destination: 255.255.255.255 Interface index: 6 Metric: 1 Destination: 255.255.255.255 Interface index: 65544 Metric: 1 Destination: 255.255.255.255 Interface index: 4 Metric: 1 Destination: 255.255.255.255 Interface index: 3 Metric: 1 Destination: 255.255.255.255 Interface index: 2 Metric: 1

That all for today, soon I'll tell you how to figure out which network adapter is linked to the specified interface index...

 

Technorati tags: , , ,
  
del.icio.us tags: , , ,
October 03

Finding the way home...

Ever wondered how to determine which of your network interfaces is being used to communicate? Suppose you are connected using your wireless adapter, which has received an IP-address from the DHCP server in your network. At this moment all communication to the outside world uses the wireless adapter.

But what would happen if you also plugging in your network cable? Will the system automatically use the faster Ethernet adapter or not?

One way to find this out is using the route command: open a command prompt and type in route print and you'll get something like this:

1 C:\Documents and Settings\jansenbe>route print 2 =========================================================================== 3 Interface List 4 0x1 ........................... MS TCP Loopback interface 5 0x2 ...00 50 56 c0 00 08 ...... VMware Virtual Ethernet Adapter for VMnet8 6 0x3 ...00 50 56 c0 00 01 ...... VMware Virtual Ethernet Adapter for VMnet1 7 0x4 ...00 0d 9d 90 31 f6 ...... Broadcom NetXtreme Gigabit Ethernet - Determinis 8 tic Network Enhancer Miniport 9 0x5 ...00 20 e0 26 5d 32 ...... Bluetooth LAN Access Server Driver #2 - Determin 10 istic Network Enhancer Miniport 11 0x6 ...00 20 e0 26 5d 32 ...... Bluetooth LAN Access Server Driver - Determinist 12 ic Network Enhancer Miniport 13 0x10008 ...00 0c f1 35 18 db ...... Intel(R) PRO/Wireless LAN 2100 3B Mini PCI A 14 dapter - Deterministic Network Enhancer Miniport 15 =========================================================================== 16 =========================================================================== 17 Active Routes: 18 Network Destination Netmask Gateway Interface Metric 19 0.0.0.0 0.0.0.0 192.168.240.244 192.168.240.100 30 20 127.0.0.0 255.0.0.0 127.0.0.1 127.0.0.1 1 21 192.168.163.0 255.255.255.0 192.168.163.1 192.168.163.1 20 22 192.168.163.1 255.255.255.255 127.0.0.1 127.0.0.1 20 23 192.168.163.255 255.255.255.255 192.168.163.1 192.168.163.1 20 24 192.168.238.0 255.255.255.0 192.168.238.1 192.168.238.1 20 25 192.168.238.1 255.255.255.255 127.0.0.1 127.0.0.1 20 26 192.168.238.255 255.255.255.255 192.168.238.1 192.168.238.1 20 27 192.168.240.0 255.255.255.0 192.168.240.100 192.168.240.100 30 28 192.168.240.100 255.255.255.255 127.0.0.1 127.0.0.1 30 29 192.168.240.255 255.255.255.255 192.168.240.100 192.168.240.100 30 30 224.0.0.0 240.0.0.0 192.168.163.1 192.168.163.1 20 31 224.0.0.0 240.0.0.0 192.168.238.1 192.168.238.1 20 32 224.0.0.0 240.0.0.0 192.168.240.100 192.168.240.100 30 33 255.255.255.255 255.255.255.255 192.168.163.1 192.168.163.1 1 34 255.255.255.255 255.255.255.255 192.168.238.1 192.168.238.1 1 35 255.255.255.255 255.255.255.255 192.168.240.100 4 1 36 255.255.255.255 255.255.255.255 192.168.240.100 192.168.240.100 1 37 255.255.255.255 255.255.255.255 192.168.240.100 6 1 38 255.255.255.255 255.255.255.255 192.168.240.100 5 1 39 Default Gateway: 192.168.240.244 40 =========================================================================== 41 Persistent Routes: 42 None
The output shows all active TCP/IP routes, both static and dynamic, available on your machine. The route we're interested in is the so called default route which all TCP/IP traffic uses when there's no specific route defined. The default route is the one line 19:

1 Network Destination Netmask Gateway Interface Metric 2 0.0.0.0 0.0.0.0 192.168.240.244 192.168.240.100 30 3

In the route table above only my wireless network adapter was connected. If I also plugged in my Ethernet cable on use the same route print command again then there are two default routes:

1 Network Destination Netmask Gateway Interface Metric 2 0.0.0.0 0.0.0.0 192.168.240.244 192.168.240.100 30 3 0.0.0.0 0.0.0.0 192.168.240.244 192.168.240.102 20 4

Which one of the two routes is my default route? That the question smile_nerd !

The answer is simple: Windows will take the route with the lowest metric as it's default route which means in my case that my local area network will be used instead of my wireless network. In most cases Windows will configure this correct, but if you would want to alter this, then take a look at following screenshots:

Open the properties dialog of one of your network connections:

Select the Internet Protocal and go to Properties:

Go to Advanced...And here you can define your own metric!

In the coming days I'll post more about this topic: How to retrieve this information using C# and how to use this all to detect the speed of the currently used adapter, which can be very handy in smart client applications that want to disallow heavy network operations on slow and more important expensive networks. Each bit transmitted using GPRS or UMTS still is very expensive (at least here in Belgium) smile_sad

Technorati tags: , ,
    
del.icio.us tags: , ,