Friday, September 17, 2010

PowerShell Yammer

What I had learned in my last post I built a small PowerShell snap-in to integrate with the Yammer API which is better suited for companies. I have started a second CodePlex project specifically for the snap-in.

Friday, September 3, 2010

PowerShell OpenAuthentication and Twitter

Twitter recently depreciated support of Basic Authentication which has made it a little more tricky to post updates via the API. I decided a Cmdlet seemed like the best route to take since the new method required storage of state for the oAuth token. I started a CodePlex site for those of you who might also need the functionality or would like to contribute.

Friday, August 20, 2010

Where Am I.cmd

After re-installing I have yet again found my static DHCP lease is no longer holding my IP address. I am at home and can't think of another way to find the IP, pinging my machine name continues to resolve to the static lease. If you find your self in the same boat and want to scan the network for IP to name resolution the following script should do the trick:

@ECHO OFF
FOR /L %%i IN (1,1,254) DO (
ECHO 10.1.1.%%i
nbtstat -A 10.1.1.%%i
)

Tuesday, August 17, 2010

VSTS 2010 MsBuild Extension Pack TfsSource and Win32Exception: The system cannot find the file specified

I came across this error while trying to check out a file using MsBuild under TFS2010. The error message is misleading because your first inclination is to check the ItemPath or WorkingDirectory in the task. Had I not come across this forum post I may have been stuck for a bit http://msbuildextensionpack.codeplex.com/Thread/View.aspx?ThreadId=74209. The current version of the Extension Pack has some hard coded paths in the task that tell it where to find the tf.exe file. After taking a look at the source code I found if you just add the following path to your Path environment variable the task will function properly.

C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\

Where's the Build Number, using MSBuild with VSTS 2010

I wanted to key the our assembly versions using the VSTS build number I quickly found the solution is not as simple as it seems. At first I thought this property would be a first class member of the IBuildDetail class making it easily accessible in the VSTS workflow but, it's not. After popping open the UpdateBuildNumberActivity I found the build number is actually extracted from the IBuildDetail.Uri. Use the format below in your MsBuild task to gain access to the BuildID and the SourceGetVersion. While the SourceGetVersion may return a sequential change set number (C123) it is not guaranteed to be numeric so it's probably not a good fit for the revision part of your version number. You may consider adding it to your AssemblyConfiguration attribute or AssemblyInformationalVersion attribute. Connecting the change set or source version to the assemblies generated may prove to be useful in troubleshooting version related issues later on.

String.Format("/p:SkipInvalidConfigurations=true /p:BuildID=""{1}"" /p:SourceGetVersion=""{2}"" {0}", MSBuildArguments, LinkingUtilities.DecodeUri(BuildDetail.Uri.ToString()).ToolSpecificId, BuildDetail.SourceGetVersion)

Wednesday, August 11, 2010

More Time Saving Macros Who's Under Source Control

I am in the process of switching from Subversion to Teams Server source control. Unfortunately when merging project files the source control in teams is not applied causing build errors. Using my last macro as an example I now scan every file in the solution to see if it is in source control and correct if not. One could probably add the extra code to add the item to source control.


Public Module SourceControlScanner
Private Sub Write(ByVal name As String, ByVal message As String)
Dim output As Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
Dim window As OutputWindow = output.Object
Dim pane As OutputWindowPane = window.OutputWindowPanes.Item(name)
pane.Activate()
pane.OutputString(message)
pane.OutputString(Environment.NewLine)
End Sub
Private Sub Scan(ByVal project As Project)
If Not project.ProjectItems Is Nothing Then
If TypeOf (project.Object) Is VSProject Then
Dim visualStudioProject As VSProject = DirectCast(project.Object, VSProject)
For Each item As ProjectItem In project.ProjectItems
For index As Integer = 0 To item.FileCount
Dim file As String = item.FileNames(index)
If Not visualStudioProject.DTE.SourceControl.IsItemUnderSCC(file) Then
Write("Debug", String.Concat(project.Name, " ", item.Name))
End If
Next
Next
End If
For Each childProjectItem As ProjectItem In project.ProjectItems
If Not childProjectItem.SubProject Is Nothing Then Scan(childProjectItem.SubProject)
Next
End If
End Sub
Public Sub CheckSourceControl()
For Each project As Project In DTE.Solution.Projects
Scan(project)
Next
End Sub
End Module

Thursday, July 29, 2010

Hint Paths and The System.Reflection.CustomAttributeFormatException

With in my organization we use multiple branches and a centralized bin directory within each branch. All of our references are file based and not version specific. There are arguments for why this works or why it should not be done but this implementation has worked for our current architecture.
Now lets say one day you come to work and start in a new branch and find the System.Reflection.CustomAttributeFormatException after comping a new. And you begin asking your self how did I get here and what have I done this is not my beautiful house this is not my large automobile. After answering those questions and more colleague and I found someone added a rouge reference to a DLL in another branch. Initially this involved some meticulous evaluation of each project and its references.

I offer you a magnet for your needle in the hay stack the code below can be pasted in to a visual studio macro to scan each project and make sure it is referencing the correct path. (Your paths may vary)
Imports System
Imports System.Diagnostics
Imports EnvDTE
Imports VSLangProj
Imports System.Collections

Public Module ReferenceScanner
    Private Path As String
    Private ExcludedPaths As ArrayList
    Private Sub Scan(ByVal project As Project)
        If Not project.ProjectItems Is Nothing Then
            If TypeOf (project.Object) Is VSProject Then
                Dim visualStudioProject As VSProject = DirectCast(project.Object, VSProject)
                For Each reference As Reference In visualStudioProject.References
                    Dim referencePath As String = reference.Path
                    Dim exclude As Boolean = False
                    For Each excludePath As String In ExcludedPaths
                        exclude = referencePath.StartsWith(excludePath)
                        If exclude Then Exit For
                    Next
                    If Not exclude And Not String.IsNullOrEmpty(reference.Path) Then
                        If Not reference.Path.StartsWith(Path) Then
                            Debug.Write(project.Name)
                            Debug.Write(" ")
                            Debug.WriteLine(reference.Path)
                        End If

                    End If
                Next
            End If
            For Each childProjectItem As ProjectItem In project.ProjectItems
                If Not childProjectItem.SubProject Is Nothing Then Scan(childProjectItem.SubProject)
            Next
        End If
    End Sub
    Public Sub CheckSolutionHintPaths()
        If ExcludedPaths Is Nothing Then
            ExcludedPaths = New ArrayList()
            ExcludedPaths.Add("C:\Windows\Microsoft.NET\Framework\")
            ExcludedPaths.Add("C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\")
            ExcludedPaths.Add("D:\Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies\")
        End If

        Path = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(DTE.Solution.FullName), "bin")
        For Each project As Project In DTE.Solution.Projects
            Scan(project)
        Next
    End Sub
End Module

*Dont forget to replace the referenced dll after you have corrected your references

Saturday, May 1, 2010

Going Going Gone.. catch(T exception)

While writing some diagnostic code I got clever and tried to use a generic in a catch statement. After spending some time head scratching I came across this stackoverflow article http://stackoverflow.com/questions/1577760/why-cant-i-catch-a-generic-exception-in-c
apparently while this code compiles without error it results in an uncaught exception. The article refers to a defect in the compiler which indicates it is version specific. A good work around is to use the following code block instead:
catch(Exception exception) { if(exception is T) {//Your specialized code here;} }

Sunday, April 18, 2010

RDP Spanning and Multi-Monitor Support

In older versions of windows that support RDP I have found it is almost impossible to use multi-monitor support across RDP as it was designed (/span). The inability to maximize to monitor boundaries on the local machine is a frustrating limitation. I have tested several configurations and thought I would share my hacktastic findings:

SplitView
I installed the demo personal edition and could not get the boundaries to work properly. To be honest I felt 39$ was a little steep for what you would be getting.

Sizer
A good old tool from the 90's is a hidden gem unfortunately it is only 32-bit but this thing is an excellent and cheap alternative. Simply fire it up on your RDP host set your window sizes and positions and your off and running.

For Extra Credit-
If you hate browsing on your RDP host because it bogs down your RDP performance (flash ads mostly). Find a tool that allows you to set your client windows as "Always On Top" so you can use local applications over your spanned and maximized RDP session.

UPDATE: This solution is primarily geared to those of us still using Vista or XP as either a client or host. Those of you lucky enough to have both windows 7 at both ends can use the multimon feature: http://blogs.msdn.com/rds/archive/2009/07/01/using-multiple-monitors-in-remote-desktop-session.aspx


Thursday, January 28, 2010

All Your .base

I encountered some issues with a .NET service installer embedded into an .MSI package today. If you have classes dependent upon service startup in your installer and the service fails to start you will often get some unexpected and often cryptic messages. It gets even worse if your messages are relating to event log messages that wont write because of permissions or other similar issues. One gotcha I am guilty of was using EventLog instead of base.EventLog. I also failed to set the event log location when calling the static version of the method calls. By using base.EventLog the ServiceBase class creates an event log source and applies all messages to the Application log. Do this and all event log messages are not belong to us.

Tuesday, January 26, 2010

Console XML/XSD Validation Application

Could not find a decent console application to validate an XML file against multiple XSD Schema Documents so I decided to write one and share for any who may need it.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Schema;

namespace XmlValidator
{
class Program
{
static void Main(string[] args)
{
int result = 0;
string documentPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, args[0]);
if (!File.Exists(documentPath)) throw new Exception(String.Format("The document '{0}' does not exist", documentPath));
List schemaPaths = new List();
foreach (string path in args.Skip(1))
{
string schemaPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, path);
if (!File.Exists(schemaPath)) throw new Exception(String.Format("The schema document '{0}' does not exist", schemaPath));
schemaPaths.Add(schemaPath);
}
using (Stream stream = File.Open(documentPath,FileMode.Open,FileAccess.Read,FileShare.ReadWrite))
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = false;
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += new ValidationEventHandler(
delegate(object sender, ValidationEventArgs e)
{
result = -1;
Console.Write("Line:");
Console.Write(e.Exception.LineNumber);
Console.Write(" Position:");
Console.Write(e.Exception.LinePosition);
Console.Write(" ");
Console.Write(e.Severity.ToString("G"));
Console.Write(" ");
Console.WriteLine(e.Message);

}
);
foreach (string path in schemaPaths) settings.Schemas.Add(XmlSchema.Read(XmlReader.Create(path), null));
stream.Position = 0;
XmlReader validator = XmlReader.Create(stream, settings);
while (validator.Read()) ;
validator.Close();
}
if (result == 0) Console.WriteLine("Document is valid");
#if DEBUG
Console.ReadLine();
#endif
Environment.Exit(result);
}
}
}