Showing posts with label visual studio. Show all posts
Showing posts with label visual studio. Show all posts

Monday, December 7, 2009

NDepend

I've started using NDepend Pro on my open-source project. I will try to outline some important features and explain some ideas that differenciate this tool from others like FXCop or ReSharper rules.

What is NDepend?

For me NDepend is a tool for monitoring and improving code quality. It uses software metrics and .NET IL characteristics to help us understand, analyze, visualize and compare different code bases and builds. We learnt code coverage, cohesion, coupling and other code metrics at university, but we hardly had the chance to employ this knowledge (or even understand deeper them). Who wants to calculate them for hundreds of code lines? Well, NDepend just does it instead of us. We can see the internals of code structure and dependencies with just one click!

Costs

NDepend is a free tool for academic and open-source projects. Unfortunately it comes with a cost: you will be restricted with CQL (creating custom code metrics queries) usage, won’t be able to compare builds, won’t be able to integrate test metrics into the dataset and (almost) won’t have Visual Studio integration. I think it’s OK for an open-source project.

Where to start?

NDepend is not an easy tool. Easy to use, but it takes time to learn and understand the metrics and find the proper threshold limits for your project. NDepend team knows it, so they set up a lot of preset thresholds and built-in CQL queries. There are useful demo videos and there is a metrics library. So it’s easy to start using it.

How do I use it?

I use NDepend as a guard. I use other tools (like Resharper, Team System Tools or FXCop) in Visual Studio to check against naming conventions and some other rules. Visual NDepend helps me to understand the structure of my application and recheck some rules, mainly with built-in CQL queries.

I found a circular call in one of my assemblies. It was not trivial to me, I couldn’t have found that without NDepend.

Link: NDepend
Link: software metrics
Link: Inheritance Depth in CQL

Friday, October 30, 2009

Logging proxy

I learnt today that I can create a proxy that intercepts calls to an object, do anything with the call and forward the call to the appropriate object. The same is true for the results. The whole thing is implemented by using a RealProxy implementation. I will demonstrate the functionality with .NET Remoting.

The common interface

namespace Common
{
public interface IServer
{
int Add(int a, int b);
}
}

The server implementation

using Common;

namespace Server
{
class ServerImpl: MarshalByRefObject, IServer
{
#region IServer Members

public int Add(int a, int b)
{
return a + b;
}

#endregion

public override object InitializeLifetimeService()
{
return null;
}
}
}

The server loop

static void Main()
{
// Windows Forms settings
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

// Remoting loop
RemotingServices.Marshal(new SzerverImplementacio(), "Server");
ChannelServices.RegisterChannel(new TcpChannel(8080), false);

// Windows Froms Window
Application.Run(new Form1());
}

The logging proxy

using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Channels;
using System.Collections;
 
namespace Kliens
{
    public class LogProxy : RealProxy
    {
        String uri;
        MarshalByRefObject obj;
        IMessageSink _sinkChain;
 
        public LogProxy(Type type, string uri) : base(type)
        {
            this.uri = uri;
 
            IChannel[] registeredChannels = ChannelServices.RegisteredChannels;
            foreach (IChannel chnl in registeredChannels)
            {
                if (chnl is IChannelSender)
                {
                    IChannelSender chnlSender = (IChannelSender)chnl;
                    _sinkChain = chnlSender.CreateMessageSink(uri, null, out uri);
                    if (_sinkChain != null)
                        break;
                }
            } 
 
            if (_sinkChain == null)
            {
                throw new Exception("No channel has been found for " + uri);
            }
 
        }
 
        public override IMessage Invoke(IMessage msg)
        {
            Console.WriteLine("LogProxy.Invoke Start");
            Console.WriteLine("");
 
            // Set message URI
            msg.Properties["__Uri"] = uri;
 
            // List call properties
            Console.WriteLine("Call properties:");
            foreach (var key in msg.Properties.Keys)
            {
                Console.WriteLine("{0}: {1}", key, msg.Properties[key]);
                if (key.ToString() == "__Args")
                {
                    Console.WriteLine("Arguments:");
 
                    object[] args = (object[])msg.Properties[key];
                    foreach (var arg in args)
                    {
                        Console.WriteLine("arg: {0}", arg);
                    }
                }
            }
 
            // Process the request mesage
            IMessage retMsg = _sinkChain.SyncProcessMessage(msg);
 
            // List return properties
            Console.WriteLine("Return properties:");
            foreach (var key in retMsg.Properties.Keys)
            {
                Console.WriteLine("{0}: {1}", key, retMsg.Properties[key]);
            }
 
            // Process the return message
            return retMsg;
 
        }
    }
}

Call the server from the client

// Without logging proxy:
// IServer server = (IServer)Activator.GetObject(typeof(IServer), "tcp://localhost:8080/Server");
 
TcpChannel chnl = new TcpChannel();
ChannelServices.RegisterChannel(chnl, false);
 
LogProxy prx = new LogProxy(typeof(IServer), "Tcp://localhost:8080/Server");
IServer server = (IServer)prx.GetTransparentProxy();
MessageBox.Show(server.Add(2, 3).ToString());

Result

All the call end response properties will be listed in the Output window (or in the Console). The call will happen as there were no proxy class taking part in the call.

Apart Remoting this is a good solution for generating any kind of proxies:

  • Virtual proxies
  • Security proxies

RealProxy is a good extension point for an application.

Thursday, October 29, 2009

Hiding XAML designer by default

I hate Visual Studio 2008 XAML Designer. It’s slow and can be easily killed (I mean XAML Designer can’t be displayed, just an error message instead). I prefer Expression Blend 3 for GUI design.

So here are the steps to hide the designer and go straight to the text editor:

  1. Open Tools/Options
  2. Select Text Editor/XAML/Miscellaneous
  3. Under ‘Default View’ select ‘Always open documents in full XAML view’

After setting this option, you will still be able to change to designer using a tab, but the editor will be the default view for XAML files. Faster loading an (hopefully) less crashes.

Thursday, October 15, 2009

Autofill TFS password on Codeplex

TFS login  I hate filling in TFS credentials every time I connect to TFS server on Codeplex. I’ve just found an easy way to automate it.

Microsoft Windows Vista and Windows 7 have a new component called Credential Manager. You can store Windows, Certificate-based and Generic credentials. It means these credentials can be automatically provided by Windows on request. So you just simply don’t have to type them in every time you log on somewhere.

Codeplex

These are the steps to automate the Codeplex login process:

  1. Open Credential Manager
  2. Choose Add a Windows credential
  3. Specify the Codeplex server name at Internet or network address, fill in the rest
  4. Click OK
  5. Open your TFS project

You won’t be prompted for credentials anymore.

Credential Manager

Monday, August 31, 2009

NCover – Empty Coverage.xml

I spent a half day investigating an empty coverage.xml file generated by NCover console. Finally I had no idea at all.

Accidentally I recognized that the .pdb was not in the directory. After generating the .pdb file into the directory, the expected results appeared.

Friday, March 6, 2009

Visual Studio Help Blocks

I was using Visual Studio 2008 in Virtual PC when I accidentally pressed a Help button. It was a virtual machine so no one used the Document Explorer before. Visual Studio user interface became unresponsive, Help system started processing help files. I got tired of it after a few minutes.

Workaround for the problem:

  1. Kill Visual Studio 2008 (from Task Manager)
  2. Set Document Explorer thread priority to Below Normal
  3. Restart Visual Studio 2008

So help system will be initialized next time and you can continue working on your project.

Wednesday, February 4, 2009

F# – Visual Studio Integration

The newer versions of F# support Visual Studio better and better, but don’t wait such feature rich designer support as C# and other mainstream languages have. In fact F# doesn’t have any designer support (yet?).

F# integrates with Visual Studio, so first of all you can create an F# project from File/New/Project… Select Visual F# node. There are three project types:

Project Description
F# Application It creates a project that compiles to .NET .exe. It can be run from command prompt.
F# Library It creates a project that compiles to .NET .dll. It can be referenced from other .NET applications.
F# Tutorial It creates a project containing examples of F# language constructs.

So application template compiles to a standalone application, library templates compiles to a .NET DLL, and tutorial template contains several examples. Library template contains a Script.sfx file. This file can be directly accessed from F# Interactive and loads the DLL so it can be tested in an interactive manner.

F# Interactive is the interactive environment of F#. It’s reminds me to qBasic: expressions are evaluated as you type and close them. It’s basically an interpreter. F# Interactive can be accessed either from command prompt (called fsi.exe) or from Visual Studio. You can display it clicking on View/Other Windows/F# Interactive (CTRL+ALT+F). I prefer it full (editor) screen, so I usually drag it up to the editor area (e.g. over the editor window).
Expressions must be closed with ;; operator in F# Interactive.

Tuesday, December 16, 2008

Visual Studio 2010

.NET Logo Microsoft has announced Visual Studio 2010 (VS). The list of changes that sounds interesting to me:

  • The user interface will be implemented in Windows Presentation Foundation (WPF)
  • Managed addins will be supported
  • Multiple new windows
  • Built-in Test Driven Development (TDD) support
  • Built-in ASP.NET Model-View-Control (MVC) support
  • JQuery will be part of VS
  • Built-in Silverlight 2 support
  • Native Windows 7 support (means C++, MFC)
  • Multiple new UML-like diagrams (Team System (VSTS): use case, activity, sequence)
  • New Architecture Explorer (VSTS)
  • New Architecture Layer Diagram (VSTS)
  • Built-in support for Windows Azure cloud computing environment
  • Built-in support for Parallel development (Parallel Extensions, native, managed)

I can see two main possible problems with VS 2010. The first is WPF UI, the second are managed addons. Both means significant performance degradation. One of the main goals of Windows 7 is significantly improved performance. All the performance we can save on Windows 7 will be lost on WPF. VS 2008 is one of the fastest IDEs on the market, but it's becoming more and more slower. I doubt its performance will be as good as current VS 2008 performance.

On the other hand, I can hardly wait for built-in Silverlight 2, JQuery, Parallel Extension and MVC support. These will be great changes.

Link: Visual Studio 2010 Overview
Link: Visual Studio 2010 Product Overview (PDF)
Link: Visual Studio 2010 CTP Download

Tuesday, November 18, 2008

Silverlight 2 Designer crash

Visual Studio 2008 crashed every time I opened a XAML file. No crash dump, no messages, VS just disappeared. I used Silverlight designer before and worked fine. One day it just started crashing.

I've removed everyting from my computer containing Silverlight in it's name. I ran Microsoft Silverlight Tools Beta 2 for Visual Studio 2008 after that. Silverlight 2 content appeared in my browser, but Visual Studio 2008 keeped crashing. I reran Visual Studio 2008 SP1 setup. It didn't help.

Finally I tried Microsoft® Silverlight™ Tools for Visual Studio 2008 SP1. It works. XAML designer works, Visual Studio 2008 doesn't crash!!! It seems Silverlight chainer doesn't contain SP1 tools. So don't forget to install it manually if you have similar problems.

Friday, May 23, 2008

IIS debugging macro

Usually developers use a single remote server while developing custom SharePoint solution. It means the developer tools and the server are not on the same machine. You can connect to the server after starting the Visual Studio Remote Debugger. Now you can attach debugger to the remote w3wp.exe processes. This process can be very annoying after a while.
It is a macro that will automate this process:
   1:  Imports System
   2:  Imports EnvDTE80
   3:  Imports System.Diagnostics
   4:   
   5:  Public Module AttachToWebServer
   6:   
   7:      Public Sub AttachToWebServer()
   8:   
   9:          Dim AspNetWp As String = "aspnet_wp.exe"
  10:          Dim W3WP As String = "w3wp.exe"
  11:   
  12:          If Not (AttachToProcess(AspNetWp)) Then
  13:              If Not AttachToProcess(W3WP) Then
  14:                  System.Windows.Forms.MessageBox.Show(String.Format("Process {0} or {1} Cannot Be Found", AspNetWp, W3WP), "Attach To Web Server Macro")
  15:              End If
  16:          End If
  17:   
  18:      End Sub
  19:   
  20:      Public Function AttachToProcess(ByVal ProcessName As String) As Boolean
  21:   
  22:          Dim dbg2 As EnvDTE80.Debugger2 = DTE.Debugger
  23:          Dim trans As EnvDTE80.Transport = dbg2.Transports.Item("Default")
  24:   
  25:          Dim Processes As EnvDTE.Processes = dbg2.GetProcesses(trans, "DOMAIN\USER@MACHINE")
  26:          Dim Process As EnvDTE.Process
  27:          Dim ProcessFound As Boolean = False
  28:   
  29:          For Each Process In Processes
  30:              If (Process.Name.Substring(Process.Name.LastIndexOf("\") + 1) = ProcessName) Then
  31:                  Process.Attach()
  32:                  ProcessFound = True
  33:              End If
  34:          Next
  35:   
  36:          AttachToProcess = ProcessFound
  37:   
  38:      End Function
  39:   
  40:  End Module

Change the "DOMAIN\USER@MACHINE" to your own ID. The DOMAIN\USER is the debugger user, the MACHINE is the debugging target machine. You can get this ID from Visual Studio Remote Debugger first log line or from a previous connection log line.

This macro is based on Howard van Rooijen macro implementation.


Localhost debugging: change DOMAIN\USER@MACHINE to empty string ("").

Developer (Visual Studio-integrated) server debugging: add WebDev.WebServer.EXE before If Not (AttachToProcess(AspNetWp)) Then like If Not (AttachToProcess("WebDev.WebServer.EXE")) Then

Link: View and download the script on Google Code [.vb]
Link: Attach to Web Server Macro for Visual Studio