Things that were once hard

I needed a quick utility to generate a script for setting the permissions on a massive (wide and deep) directory structure.  The analysis for this was not going well – I asked someone else to try it and they did not get the scope of the issue.  I needed to just get something running quickly so I wrote a quick .NET app to generate what I needed.  I was pleasantly surprised when went to actually grab the permissions for a given folder.

The last time I did something where I was scraping permissions off a folder I was in C++ and the Win32 API.  Yikes!  High impedence for something that I was just going to throw away.

The following is a snippet of code that wrote doing in .NET 4 (I don’t think this code would be any different in .NET 2).

 class FolderPermissions  
 {  
   public string Name { get; set; }  
   public IEnumerable<Acl> Acls { get; set; }  
 }  
 class Acl  
 {  
   public string Name { get; set; }  
   public FileSystemRights Permission { get; set; }  
 }  
 private static FolderPermissions GetFolderPermissions(string pFolderName)  
 {  
   AuthorizationRuleCollection perms;  
   perms = SafeCallToGetAccessRules(pFolderName);  
   var retAcls = new FolderPermissions { Name = pFolderName };  
   var acls = new List<Acl>();  
   foreach (FileSystemAccessRule perm in perms)  
   {  
     if ( perm.AccessControlType == AccessControlType.Deny)  
       continue;  
     var acl = new Acl() {Permission = perm.FileSystemRights, Name = perm.IdentityReference.ToString()};  
     acls.Add(acl);  
   }  
   retAcls.Acls = acls.ToArray();  
   return retAcls;  
 }  

This snippet is where I am copying the permissions for a given folder into my own lightweight structure, so that I could do queries on the structure to help me create the script.

One thing in particular I remember about doing this in Win32 was once I got the SID for a particular identity, it was a pain to resolve that to a name.  Now it is just the IdentityReference.Value.

This is the type of value I like.  Now if I just had a scripting language to do this in so I did not have to compile it would be all set.  Of course there are bunch out there – just I am not as proficient in them as I am in C#.  Hmmm.

Recursive Yield Return

Was writing a recursive routine the other day and wondering what an implementation of this would look like should I convert it to use yield return.

Much to my consternation this was not as easy as I thought it would be.  It took me almost a week to get it working.  Not of constant time, of course, but elapsed time.  In my initial implementation I could not get my head wrapped around whether each yield return was going to bypass all the calls on the stack and return a result to the caller OR whether it was going to just pop one call context.  Turns out it is the latter, which greatly complicates the implementation.  Given that the implementation of this particular implementation was escaping me.

I was downstairs meditating last week, not thinking about anything in particular and it hit me.  Like a flash…I could see the implementation.  I ran upstairs and quickly wrote down the rough implementation.  I felt kind of like a musician when a riff for a song hits them in their sleep and they need to quickly write it down before they forget it.

I came back to the code after dinner and put the finishing touches on it.

The first method is the seed method implemented as an extension method on IEnumerable.  It in turn calls the the recursive method.

The implementation below is function that given a collection it will return you a collection of all the permutations (a collection of collections). 

For instance if you pass
[
    [ 1, 2, 3],
    [4, 5,  6],
    [7, 8,  9]
]

This routine will return you 3x3x3 (27) collections, each of which will contain 3 items.  Using the data above here are the first few collections returned…
[
   [1, 4, 7],
   [1, 4, 8],
   [1, 4, 9],
   [1, 5, 7],

]

  
public static IEnumerable> GetPerm(this IEnumerable> domain)
{
return GetPermRecur(domain);
}
public static IEnumerable> GetPermRecur(IEnumerable> domain)
{
var c = domain.Count();
var firstFromDomain = domain.First();
if (c == 1)
{
foreach (var item in firstFromDomain)
{
yield return new[] {item};
}
}
else
{
var domainWithoutFirst = domain.Skip(1);
var permSoFar = GetPermRecur(domainWithoutFirst);
foreach (var item in firstFromDomain)
{
foreach (var curCol in permSoFar)
{
var curPerm = new List() { item };
curPerm.AddRange(curCol);
yield return curPerm;
}
}
}
}
Posted in c#

Google Contacts Importer

Could not get a bunch of contacts to import into Google Contacts the way I wanted.  I had a CSV that I exported from Outlook but no matter what I did to the CSV header names, I did not get the phone numbers spiked out for the contact correctly.  Instead the phone numbers would all be put as text into the Notes of the contact.  Useless.

So I rolled up my sleeves and wrote the following code to import the CSV file.  I made some assumptions (because I could) about the order fields appear in the file and their format.  For instance, the name I have is in the “Last, First M.” format; so the code breaks this up.  Also, all the phone numbers are formatted correctly so no fixing required.

Another assumption is that all the contacts are added to the same group (see the constant at the top) which does not have to be the same as the company name in the CSV file.  Probably could have cleaned this up a bit, but it worked for what I needed.  

Hope this helps someone…

CSV Format
 UserName,Company,Department,Cell Phone,Home Phone,Work Phone,Mobile Phone 2  
"Adams, Gomez",My Co,Accounting,,(212) 555-4805,(212) 555-6748,

C# Code

 using System;  
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Diagnostics;
using Google.Contacts;
using Google.GData.Contacts;
using Google.GData.Client;
using Google.GData.Extensions;
using LumenWorks.Framework.IO.Csv; // http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader
namespace UploadContacts
{
class MyContact
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Company{ get; set; }
public string Department{ get; set; }
public string CellPhone{ get; set; }
public string HomePhone{ get; set; }
public string WorkPhone{ get; set; }
public string CellPhone2{ get; set; }
}
internal static class Program
{
private const string CompanyNameForGroup = "My Co";
private const string AppName = "Test";
private const string Username = "Me";
private const string Password = "blah";
private static ContactsService _cs;
private static void Main()
{
var himcoGroupId = LookupGroup(CompanyNameForGroup).Id;
var data = ReadCsv();
foreach (var contact in data)
{
var newEntry = CopyData(contact, himcoGroupId);
AddContact(newEntry);
}
}
private static void AddContact(ContactEntry newEntry)
{
if (_cs == null)
{
_cs = new ContactsService(AppName);
_cs.setUserCredentials(Username, Password);
}
var displayName = string.Format("{0} {1}", newEntry.Name.GivenName, newEntry.Name.FamilyName);
var feedUri = new Uri(ContactsQuery.CreateContactsUri("default"));
try
{
_cs.Insert(feedUri, newEntry);
Console.WriteLine("Added {0}", displayName);
}
catch (Exception ex)
{
Console.WriteLine("Error {0} while adding {1}", ex.Message, displayName);
}
}
private static ContactEntry CopyData(MyContact contact, string himcoGroupId)
{
var fullName = string.Format("{0} {1}", contact.FirstName, contact.LastName);
var newEntry = new ContactEntry
{
Title = {Text = fullName},
Name = new Name {GivenName = contact.FirstName, FamilyName = contact.LastName}
};
newEntry.Categories.Add(new AtomCategory(CompanyName));
newEntry.Organizations.Add(new Organization
{
Department = contact.Department,
Name = contact.Company,
Primary = true,
Rel = ContactsRelationships.IsWork
});
if (!string.IsNullOrEmpty(contact.CellPhone))
newEntry.Phonenumbers.Add(new PhoneNumber(contact.CellPhone)
{
Primary = true,
Rel = ContactsRelationships.IsMobile
});
if (!string.IsNullOrEmpty(contact.CellPhone2))
newEntry.Phonenumbers.Add(new PhoneNumber(contact.CellPhone2)
{
Primary = false,
Rel = ContactsRelationships.IsOther
});
if (!string.IsNullOrEmpty(contact.HomePhone))
newEntry.Phonenumbers.Add(new PhoneNumber(contact.HomePhone)
{
Primary = false,
Rel = ContactsRelationships.IsHome
});
if (!string.IsNullOrEmpty(contact.WorkPhone))
newEntry.Phonenumbers.Add(new PhoneNumber(contact.WorkPhone)
{
Primary = false,
Rel = ContactsRelationships.IsWork
});
newEntry.GroupMembership.Add(new GroupMembership {HRef = himcoGroupId});
return newEntry;
}
public static Group LookupGroup(string name)
{
var rs = new RequestSettings(AppName, Username, Password);
var cr = new ContactsRequest(rs);
var feed = cr.GetGroups();
var retVal = feed.Entries.Where(i => i.Title == name);
return retVal.First();
}
public static IEnumerable ReadCsv()
{
var retList = new List();
using (var csv = new CsvReader(new StreamReader(@"C:\Users\Curtis1\Dropbox\Code\UploadContacts\UploadContacts\PhoneNumbers.csv"), true))
{
while (csv.ReadNextRecord())
{
string fname;
string lname;
var wholeName = csv[0];
var nameParts = wholeName.Split(new [] { ',' });
if (nameParts.Length >= 2)
{
fname = nameParts[1];
lname = nameParts[0];
}
else
{
nameParts = wholeName.Split(new [] {' '});
fname = nameParts[0];
lname = nameParts[1];
}
if (fname.Length == 0 || lname.Length == 0)
Debug.Assert(false);
var newContact = new MyContact
{
FirstName = fname,
LastName = lname,
Company = csv[1],
Department = csv[2],
CellPhone = csv[3],
HomePhone = csv[4],
WorkPhone = csv[5],
CellPhone2 = csv[6]
};
retList.Add(newContact);
}
}
return retList;
}
}
}

New OLEDB Provider for Reading Excel 2007

I work for a financial company that uses alot of Excel. Many of the the business users here practically live in it. So we are constantly trying to figure out how to leverage Excel in our applications.

Do we just export data to Excel? If so, then is it a snapshot/copy of the data or do we build a connection to the backend data? What about importing data? Where is the boundry between using VBA and VSTO? Then if we pile SharePoint and Excel Services on this heap it starts to get really interesting.

One of our technical frustrations has been the OLEDB driver for reading Excel on the server was fairly lame. It made alot of assumptions about the data that made it nearly unusable except in the simpliest cases. Last week I found this updated Provider for Excel 2007 and I am looking forward to giving it a deeper look. What I can say is, that it did read in all my data rather easily. I just have not had time to play around the fringes much.

Download details: 2007 Office System Driver: Data Connectivity Components
href=”http://www.microsoft.com/downloads/details.aspx?FamilyID=7554F536-8C28-4598-9B72-EF94E038C891&displaylang=en

Old Problem – New Context

[Here is an old post I found that I had never published. I think it's because I could not get the formatting of the code to look "right". This time I published from Word and the formatting was still not preserved - rats! Also, the article is not as complete as I would like it but I wanted to get the code into the blogosphere.]

[There are a few technical things wrong with this post. The first is that using Thread Local Storage is risk (at best) in an ASP.NET application. See http://www.hanselman.com/blog/CommentView.aspx?guid=320. The second is that I would prefer to use a different pattern than the one below; something a little more elegant. Lastly, after using LINQ much more I don't know that this code is even a best practice; I need to noodle on this more.]

I keep thinking that there are like a dozen or so abstract problems that I solve and everything else is just another derivation from those. This is one of those dozen problems – what is context and why do we need it so often?

We have been using a lot of LINQ lately. While using LINQ to SQL I ran into a problem a few weeks ago and created a little hack to work around it. Well we are starting to roll LINQ out to the rest of the developers we need more than a hack for this issue. What is the issue, well it’s the same we have had in the last 4 ADO stacks – how do I reuse a connection when I have a transaction open. The only time I have not had to work around this issue was in MTS/MTX and when we used the Microsoft Enterprise Library (EntLib)

The way MTX and EntLib get around this is that they are a “layer” in between me (you) and the underlying infrastructure. I remember Bernie’s old saying – “Interesting things can happen when you can get in between things”. Another way of saying that layers or interception are something that are a key part of any design.


So here is what I want the client/consuming code to look like.


const
string CN = “Server=localhost;Database=AdventureWorks2008;Trusted_Connection=true”;

using (var aTrx = new TransactionScope())

{

var aCtx = new AdventureWorksDataContext(CN);

var x = from p in aCtx.Persons

where p.FirstName.StartsWith(“A”)

select p;

var y = x.First();

var aCtx2 = new AdventureWorksDataContext(CN);

var x2 = from p in aCtx2.Persons

where p.FirstName.StartsWith(“A”)

select p;

var y2 = x2.First();

}

So I wrote a little class that caches the connections so that they can be reused across LINQ statements. If we don’t do it this way then we are invoking the Distributed Transaction Coordinator (DTC). We only want to do this when the statements need to be in the same transaction.


public
static
class
TransactionalDataContext

{

[ThreadStatic]


private
static Hashtable mConnections;


public
static IDbConnection DataContext(string pCnStr)

{


var aTrx = Transaction.Current;


if (aTrx == null)

{


return CreateConnection(pCnStr);

}


if (mConnections == null)

{

mConnections = new Hashtable();

}


if (mConnections.ContainsKey(pCnStr))

{


return (IDbConnection)mConnections[pCnStr];

}


var aCn = CreateConnection(pCnStr);

mConnections[pCnStr] = aCn;

aTrx.TransactionCompleted += TransactionCompleted;


return aCn;

}


private
static IDbConnection CreateConnection(string pCnStr)

{


// cn str is name value pairs with ‘=’ and ‘;’ separating each pair


// get each of the pairs


var aCnStrPairs = pCnStr.Split(new[] { ‘;’ });


// find the pair with ‘Provider’


var aProvPairEnum = aCnStrPairs.Where(i => string.Compare(i, “Provider”, true) == 0);

IDbConnection aCn;


if (aProvPairEnum.Count() == 0)

{


// no provider specified so assume MS SQL Server

aCn = new SqlConnection(pCnStr);

}


else

{


// get the provider name


var aProvPair = aProvPairEnum.First();


var aProvNvp = aProvPair.Split(new[] { ‘=’ });


// create a connection


var aFactory = System.Data.Common.DbProviderFactories.GetFactory(aProvNvp[1]);

aCn = aFactory.CreateConnection();

aCn.ConnectionString = pCnStr;

}


// we open the cn so that LINQ does not – this will also signal to LINQ not to close the cn

aCn.Open();


return aCn;

}


// handler for when the trx is complete


private
static
void TransactionCompleted(object sender, TransactionEventArgs e)

{


try

{


// dispose of each connection


foreach (DictionaryEntry aEntry in mConnections)

{


try

{

((IDbConnection)aEntry.Value).Dispose();

}


catch { }

}

}


finally

{


// reset the collection, in case doing another on this thread

mConnections.Clear;

}

}

}


C# – Keep me from hurting myself

I just fixed a funny bug where it was behaving very odd and it was because I had a return statement where I intended to have a continue. I musta looked at that line a dozen times and did not think anything of it. Just went back to the basics of debugging and ran through the code line by line, iteration by iteration. What an embarassing relief!

[Upon further reflection]
What if there was new language feature that made this less likely to happen. Does it help readability and/or intent? Take the following loop.

foreach (var i in theCollection)
{
if (i.Visible == false)
continue;

// other code goes here
}

What if I could change the syntax to something like this…

foreach (var i in theCollection)
except i.Visible == false
{
// other code goes here
}

Upon futher thought what if I just used LINQ instead?

var iVisible = theCollection.FindAll( i => i.Visible)

foreach( var i in iVisible)
{
// other code goes here
}

Not to bad from a syntax point of view. I don’t like that I am making a shallow copy of the original list for the purposes of only iterating through it. The language extension above works on the original list.