Tips for making Sequence Diagrams with Visio from Reverse Engineered Models

Align the bottom of your first object to a grid line. This tends to make the connection points on the object's lifeline fall on grid boundaries.

For the most part, leave off Activation blocks; they just make it harder to make the message call arrows go straight. I'll only add them occasionally to call attention to a particular method call/message.

Turn off Snap To "connection points" - (Tools->Snap and Glue -> General tab) I thought this would make for straighter message arrows but found it easier to get straighter message arrows with it unchecked.

Anything on a diagram that appears Bold and Red when unselected indicates that something's wrong. Usually it just means a shape isn't connected to a connection point.

Both the top and bottom of an Activation Bar have to connect to Connection Points on a Lifeline. If the Activation Bar is red then they're not both connected to Connection Points.

SHIFT+MouseWheel pans horizontally.

CTRL+MouseWheel zooms.

CTRL+drag on page edges resizes the page.

Interop with a struct that contains an array of structs

To pass a struct that contains an array of structs from C# to C++ a managed version of both structs must be created. The easiest way to create the managed version of the structs is via the P/Invoke Interop Assistant.

For example, consider the following native structs:

typedef struct MYNAME_t
{
char* first;
char *last;
};

typedef struct MYGROUP_t
{
int count;
MYNAME_t groupMembers[5];
};




MYGROUP_t is a struct that contains 5 MYNAME_t structs. The managed version of these structs follows:


[StructLayout(LayoutKind.Sequential)]
public struct MYNAME_t
{
[MarshalAs(UnmanagedType.LPStr)] public string first;
[MarshalAs(UnmanagedType.LPStr)] public string last;
};

[StructLayout(LayoutKind.Sequential)]
public struct MYGROUP_t
{
public int count;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.Struct)]
public MYNAME_t[] groupMembers;
};




To handle the embedded array of structs the groupMembers field must be marshaled as a ByValArray with the size of the array and array sub type specified.





The following native function takes a MYGROUP_t as a parameter:


INTEROPTEST_API int testStructWithStructArray(MYGROUP group)
{
cout << "in testStructWithStructArray() group.count=" << group.count << endl;

for (int i=0; i < group.count; i++)
{
cout << "member[" << i << "]=" << group.groupMembers[i].first <<
" " << group.groupMembers[i].last << endl;
}
return 42;
}





The native function can be called from managed code as follows:




[DllImport("InteropTest.dll", EntryPoint = "testStructWithStructArray")]
public static extern int testStructWithStructArray(MYGROUP_t group);

...

MYNAME_t[] members = new MYNAME_t[5];

group.groupMembers = members;
group.count = 5;

testStructWithStructArray(group);






NOTE: The native code in this example must be surrounded by

 extern "C" {
...
}


to demangle the names in the exports.

Searching with Regular Expressions in Internet Explorer

Ever wish you could do a regular expression search on the text of a webpage? FindRegex adds the ability to do this to Internet Explorer. After installing it (click here to download), you can do a regular expression search by right clicking on any web page and choosing "Find Regex".

This has only been tested in Internet Explorer 7+.

NOTE: Ignore the "this can harm your computer" warning on the download page. SkyDrive does that for any file ending in .msi.

Managed type signatures for P/Invoke Interop

Ran across an incredibly useful tool for native Interop. The P/Invoke Interop Assistant automagically generates managed signatures for calls to DLLs.

It can even take C/C++ declarations as input and generate the corresponding managed signature. The closest thing to this that I've seen before was the VB6 API text viewer but it had no ability to parse native code declarations.

After downloading it I used a call to RasDialDlg() (declared in RasDlg.h, implemented in RasDlg.dll) to test it out. The C++ declarations had to be modified a little, mainly to remove usage of #define, for correct parsing. Given the following input:
struct RASDIALDLG{ IN DWORD
dwSize; IN HWND hwndOwner; DWORD
dwFlags; LONG xDlg; LONG
yDlg; DWORD dwSubEntry; DWORD
dwError; ULONG_PTR reserved; ULONG_PTR
reserved2;};
BOOL APIENTRY RasDialDlgW( LPWSTR
lpszPhonebook, LPWSTR lpszEntry, LPWSTR lpszPhoneNumber,
RASDIALDLG *lpInfo )

The P/Invoke Interop Assistant produced the following managed signatures (inside a neat little wrapper class no less!):

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public
struct RASDIALDLG {
/// DWORD->unsigned int
public uint dwSize;
///
HWND->HWND__*
public System.IntPtr hwndOwner;
/// DWORD->unsigned
int
public uint dwFlags;
/// LONG->int
public int xDlg;
///
LONG->int
public int yDlg;
/// DWORD->unsigned int
public uint
dwSubEntry;
/// DWORD->unsigned int
public uint dwError;
///
ULONG_PTR->unsigned int
public uint reserved;
///
ULONG_PTR->unsigned int
public uint
reserved2;
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public
struct HWND__ {
/// int
public int unused;
}
public partial class
NativeMethods {
/// Return Type: BOOL->int
///lpszPhonebook:
LPWSTR->WCHAR*
///lpszEntry: LPWSTR->WCHAR*
///lpszPhoneNumber:
LPWSTR->WCHAR*
///lpInfo:
RASDIALDLG*
[System.Runtime.InteropServices.DllImportAttribute("",
EntryPoint="RasDialDlgW")]
[return:
System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
public
static extern bool
RasDialDlgW([System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
System.Text.StringBuilder lpszPhonebook,
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
System.Text.StringBuilder lpszEntry,
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
System.Text.StringBuilder lpszPhoneNumber, ref RASDIALDLG lpInfo) ;
}

I really wish I had this tool a few months back when doing major interop. Ah well, better late than never.

Google Chrome vs Internet Explorer 7

I'm a few weeks into Chrome use after recently switching from Internet Explorer 7.  Chrome is still noticeably faster than IE particularly on javascript heavy pages.  I also get the feeling that a lot of thought was put into a minimalistic approach to the browser.  There's no Home button - something I occasionally trip up on, there's no permanent status bar, there's no menu bar, etc.  Definitely a less is more mileux going on with Chrome.

As far Chrome's shortcomings, I have only come across two.  The first is that the back button doesn't remember your position in the previous document.  So if I click on a link halfway through an article then click back Chrome displays the top of the page.

The second is the initial page, with snippets of recently browsed pages, isn't quite as Terminal Services friendly as about:blank (my homepage in Internet Explorer).

Despite these two shortcomings it's an excellent browser.  Uniquely positioned to take advantage of the coming multicore revolution since each tab gets rendered by a separate process that can run on a separate core.

A Pagefile allows pages to be recycled

I've been reading an excellent series on resource limits in Windows by Mark Russinovich and ran across some information that's prompting me to change a habit I started many years ago.

After a fresh install of Windows I've always gotten rid of the pagefile on the theory that, with so much RAM installed, I shouldn't have to worry about running out of physical memory. I figured, hard drives are so much slower than RAM that running without a pagefile would wring a little bit of extra performance out of the system.

"Pushing the Limits of Windows: Virtual Memory" makes it clear that there's a downside to not having a pagefile that I hadn't considered. Memory pages that haven't been used in a long time can't be paged out if there's no pagefile. If you reboot frequently then this is probably not an issue but over the past few years I've tended to be far less frequently than in prior years.

Without a pagefile, if I understand correctly, once a page has been allocated to a process that page will never be recycled. To paraphrase a line from The Matrix: Revolution, this represents an ever increasing probability of catastrophic system failure.

So it's back to using a pagefile. But only one that's fixed at 64MB :)

Belkin Wireless USB on Vista x64

I've had the darndest time finding drivers for the Belkin Wireless USB Adapter (F5D8053 ver 1) that work in Vista x64.

Their version 1 driver won't load but, to their credit, they don't claim that it works with 64 bit Vista.

Their version 3 and version 4 drivers load but only connect every 3 or 4 attempts.

Fortunately a bit of googling paid off in the form of the chipset: the Ralink rt 2870.  Downloaded their drivers and they work like a charm.  Even comes with an incredibly well written WLAN utility.  If I were Belkin I'd ship that instead of the one that Belkin ships...

Building Query Tool/Statistical Analysis software

A lot of custom software involves reinventing the wheel. Writing things that have been written before and solving problems that have been solved before. I'm a fan of not reinventing the wheel but, like with so many things in life, even this heuristic needs to be adhered to in moderation. There are times when reinventing the wheel is the lesser of evils; in some cases it's even instructive.

While working on software to do statistical analysis on some data extracted under a certain set of circumstances, I've run across some micropatterns that I hope will save me some work some day.

#1 - Take the time to extract the data points into a class/standard form. If it's time series data then every data point should be associated with its underlying series. In the object model there should always be a path from the data point back to the underlying data source (e.g., the file it was taken from).

In the beginning this might seem like overkill. Why bother with the overhead of wrapping a double in a class that has a reference to the underlying source of data? Eventually you're going to want to know more about the data point than can be represented by its value. You'll definitely want to know where it came from. But you may also want its ordinal position in the set of data points. What about any special circumstances that were in effect at the time? If they vary over time then you might have a set of data all from the same source but with different configurations in effect. When your users want to query based on those configurations it's a lot easier if this information is readily accessible from any given data point.

#2 - Take the time to abstract the source of the data points into a standard form. This is usually a class that stores, in the very least, the name of the file that contained the data.

This class might start out storing very little; perhaps just the name of the file and the date it was acquired. Believe me, it'll grow. Over time more data sources will come online; new hardware, new algorithms, new "meta" information about the data. If this class already exists it'll be the natural repository for this information.

#3 - Encapsulate common statistical methods into a class that references a collection of the underlying data points. By common I mean things like mean, standard deviation, variance, etc... Make sure this encapsulating class has a reference to its underlying data sources.

This really comes in handy as new sources of data become available. The code to visually represent aggregate statistics will already exist; new data sources can just be fed into existing encapsulating classes or, in rare cases, derivative classes.

#4 - Do as little calculation at the User Interface level as possible. Ideally the UI should be handed nothing but data containing classes that get rendered. I'm not a total purist though, I'll occasionally do unit conversion at the UI (though with C# properties this is less justifiable).

Initially it's often easier to do some final calculations at the User Interface than it is to do them earlier but not only does this complicate the UI it also hardwires the UI to a specific calculation from specific data points. When the users decide they want to visualize the data in a different way it'll be a lot harder to do if a lot of calculation was being done at the UI level.