Wednesday, September 11, 2013

TFS 2012 authenticates trusted domain users, but not groups

I am configuring my first Team Foundation Server (TFS) 2012 in a domain we can call TFSdomain, that has a one-way trust to another domain where most users will access TFS from, let's call it the UserDomain. I tried to add UserDomain\Domain Admins to the Team Foundation Administrators group to let one of the group's users, UserDomain\Administrator have access to the TFS Web Administration. It did not allow access.

The UserDomain\Domain Admins is also a member of the local BUILTIN\Administrators which is a member of the Team Foundation Administrators group. This gives access to TFSdomain\Administrator, but not to UserDomain\Administrator.

I then added UserDomain\Administrator directly to the Team Foundation Administrators and tried again. Now I was allowed access as expected.

I then noticed the icon of the UserDomain\Administrator entry in the Team Foundation Administrators group. It shows the icon for a single user - not for a group. It is also not possible to see group members from the TFS Administration Console.


Have I discovered a bug in TFS 2012, or is there some other reason for this behavior?


Saturday, May 25, 2013

Language neutral Pin shortcut to Start Menu using C#

Problem: I needed a program that would automatically pin an existing shortcut on the desktop to the start menu, regardless what localization the Windows user was using. I was using Windows Server 2008 R2 with a couple of alternate languages to English installed for testing. The program was written in C#. I hit the wall a copule of times while trying to make c# code from an earlier implementation written in VB.NET - this is a summary of what I got to work in the end:
Type shellAppType = Type.GetTypeFromProgID("Shell.Application");
Object oShell = Activator.CreateInstance(shellAppType);
Shell32.Folder oFolder = (Shell32.Folder)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, oShell, new object[] { 0 }); //25 = common desktop, 0 is local desktop
 


if (System.IO.File.Exists(ShortcutTarget) & (oFolder != null))
{
   Shell32.FolderItem oFolderItem = oFolder.ParseName("somefile.lnk");
   Shell32.ShellLinkObject oShellLink = (Shell32.ShellLinkObject)oFolderItem.GetLink;
   if (oShellLink != null)
   {
      // Find localized shell32 verb used to pin shortcut to the start menu (so that it works in any language)
      StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
      IntPtr hShell32 = LoadLibrary("SHELL32");
      LoadString(hShell32, 5381, szPinToStartLocalized, MAX_PATH); // 5381 is the DLL index for "Pin to start menu", ref. http://www.win7dll.info/shell32_dll.html
      string localizedVerb = szPinToStartLocalized.ToString();

      foreach (Shell32.FolderItemVerb verb in oFolderItem.Verbs())
      {
         if (verb.Name == localizedVerb)
         {
            verb.DoIt();
            break;
         }
      }
   }
}


You need to reference Shell32 - i.e. Microsoft Shell Controls and Automation on the COM tab of your "Add reference" dialog in VS2010. Also make sure you copy the shell32.interop.dll along with your application when you move the application out of your bin folder.

The following problems were encountered and solved on the way:

BadImageFormatException when entering the method containing this code. The code worked well on a Windows Vista computer, but crashed when running on Server 2008 R2. I assume this happened because of the fact that Server 2008 R2 is a 64 bit OS, and this did not work well with using the unmanaged Shell32.
Solution: Change the target CPU of your application to x86. If you use VS2010 Express, this tip on StackOverflow may be helpful to you - Make sure to read all the answers if you are stuck.

InvokeVerb did not work. Before ending up using the line verb.DoIt(), I tried using oFolderItem.InvokeVerb(verb.Name), which used to work in an earlier VB.NET implementation of the same code. I have no explanation to why this did not work, but it did not. A conspiracy theory is that Nike paid them off to just do it...

By the way, this earlier post mentions a problem I encountered trying to do the same in VB.NET some time ago. It probably applies here too, which is why the top three lines of the code looks like they do.

Saturday, February 23, 2013

How MSBuild could make a file inparseable

Problem: A text file that was being parsed from an assembly being part of a developing system. In the developer environment, this worked great. After having deployed the text file and the necessary assemblies to a different location using MSBuild, where MSBuild also replaced a couple of strings inside the text file, parsing would no longer work.
  • Looking at the file in a text editor (i use Notepad++) confirmed that the edited version looked fine.
  • Editing the file in the developer environment manually (not running MSBuild on it) worked fine - the file was parseable afterwards.
Obviously, MSBuild made the file inparseable So how could MSBuild make the text file inparseable? The command touching the file was
<MSBuild.ExtensionPack.FileSystem.File 
     TaskAction="Replace" 
     RegExPattern="Something" Replacement="SomethingElse"
     Files="%(filename)"/>
Only when tracing the code parsing the file it became clear to me that the file now contained some extra characters at the beginning of the file. Then it occurred to me:

Solution: MSBuild changed the file encoding. To make sure MSBuild used the right encoding, I had to add one more key/value pair to the MSBuild tag mentioned above:
TextEncoding="Windows-1252"
I found this by inspecting the file encoding on the source and destination text files. My source file was reported as ANSI, whileas my destination file was reported as UTF-8. It was however not as simple as putting "ANSI" as the TextEncoding, as described in this excellent StackOverflow article, which also lead me on the right path to "Windows-1252".

In my opinion, MSBuild should have retained the original encoding on the files it touches instead of  defaulting it into something unwanted. But then again, that's wat keeps bread on my table... Thanks, MS...