IsInRole While Disconnected; No Longer IsInHole

In an application I am continuing to write, during startup, the user’s security is determined by the user’s security groups and permissions are granted within the program based on the group membership.  This has worked fine.  Then one day in an airport I wanted to work on some documentation and I quickly discovered that I could not run the program.  I could not run the program because I was not on the VPN and the Active Directory (AD) groups could not be enumerated to check my permissions.  At the time, I was kind of grateful I couldn’t do any work and didn’t give it much more thought. Our application is not designed to be run in a disconnected fashion.  You have to be on the VPN to get to the database server and use it.  Lately, I revisited the problem and decided to resolve it.

In my particular instance, I had a database running locally, but I was missing an Active Directory server to read from.  I had my cached credentials, shouldn’t that be enough?  Well, it is, if you do it the hard way.

Everyone should know that a user or a group is just a name.  There is an ID behind that group or user, which allows you to rename the group/user without breaking anything.  Behind the scenes, Windows always uses the ID.  The name is just for your benefit.

Using the excellent tool WhoAmI, I saw the following (don’t chide me for running as Administrator):

C:\>whoami /groups /sid

[Group  1] = "700CB\Domain Users"  S-1-5-21-2454202000-1896829455-2950045386-513
[Group  2] = "Everyone"  S-1-1-0
[Group  3] = "DA3\Debugger Users"  S-1-5-21-854245398-1547161642-725345543-1007
[Group  4] = "DA3\Offer Remote Assistance Helpers"  S-1-5-21-854245398-1547161642-725345543-1004
[Group  5] = "BUILTIN\Users"  S-1-5-32-545
[Group  6] = "BUILTIN\Administrators"  S-1-5-32-544
[Group  7] = "NT AUTHORITY\INTERACTIVE"  S-1-5-4
[Group  8] = "NT AUTHORITY\Authenticated Users"  S-1-5-11
[Group  9] = "LOCAL"  S-1-2-0
[Group 10] = "700CB\Domain Admins"  S-1-5-21-2454202000-1896829455-2950045386-512

When disconnected form the LAN (you might need to reboot while disconnected to clear the cache), it looks like:

C:\>whoami /groups /sid

[Group  1] = ""  S-1-5-21-2454202000-1896829455-2950045386-513
[Group  2] = "Everyone"  S-1-1-0
[Group  3] = "DA3\Debugger Users"  S-1-5-21-854245398-1547161642-725345543-1007
[Group  4] = "DA3\Offer Remote Assistance Helpers"  S-1-5-21-854245398-1547161642-725345543-1004
[Group  5] = "BUILTIN\Users"  S-1-5-32-545
[Group  6] = "BUILTIN\Administrators"  S-1-5-32-544
[Group  7] = "NT AUTHORITY\INTERACTIVE"  S-1-5-4
[Group  8] = "NT AUTHORITY\Authenticated Users"  S-1-5-11
[Group  9] = "LOCAL"  S-1-2-0
[Group 10] = ""  S-1-5-21-2454202000-1896829455-2950045386-512

My local group names were resolved to their names, but my domain group names couldn’t resolve because AD was unreachable.  My cached profile still had the SIDs though.

So, if I could do an IsInRole check using the SID instead of the domain group name, I’d be golden.  And this is just what I did.

Imports System.Security.Principal
Imports System.Threading

Dim sid As New SecurityIdentifier("S-1-5-21-1859785585-1835888107-1082013118-1025")
Dim p As WindowsPrincipal = CType(Thread.CurrentPrincipal, WindowsPrincipal)

MsgBox(p.IsInRole(sid))

So I took the SID for the groups I was testing for and tested for them instead.  Obviously, if an admin deleted and recreated the group thinking nobody would notice, it would be hell to troubleshoot, so if you’re not fully in control of your environment, you might want to steer clear.  Maybe do the SID after checking IsNetworkAvailable to reduce the exposure to failure?

But for me, it works like a champ, and now I can work in airports.  Hmmm.  Why did I figure this out again?

Columns Autosize: Listview in List View

Here’s another little snip of code I couldn’t find online when I needed it.  Geez, when I became a programmer, I wasn’t thinking I’d have to actually figure things out on my own.  That’s a lot of work.

Anyway, the problem I faced was when I had a Listview control on a form and I changed views from anything to List view, the columns of the items were really small, so I’d get ellipses’ after all the entries.  Sure, I could just set the column with to some obnoxious amount like 500, but that’s a waste of space.  So after searching and seeing a bunch of postings about using a Win32 API call to autoresize the column, then getting disappointed because it was for VB 4/5/6, I just hacked through it.

The Details view has an autosize feature, but apparently they didn’t extend it to the List view.  But we can still make use of it.  Why not switch to detail, set the autosize of column 0 to true, then measure how wide it makes the column, then use that as the column width in List view?  That’s a dumb idea.  Who would do something like that.  Oh, what do you know, it works.

Dim maxSize As Integer

lstItems.View = View.Details
lstItems.Columns(0).AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent)
maxSize = lstItems.Columns(0).Width

lstItems.View = View.List
lstItems.Columns(0).Width = maxSize
lstItems.Refresh()

Yay.