Get directory of an executing assembly in C# and Visual Basic


Continuing my series of short but useful tips and tricks, one usually needs to find the directory of an executing assembly. The simple console application below shows how to do this. The Visual Basic example is after the C# one.

C#

using System;
using System.IO;
using System.Reflection;
 
namespace ConsoleApplication2
{
internal class Program
{
private static void Main(string[] args)
{
Console.WriteLine("Directory: " + AssemblyDirectory());
Console.WriteLine("Location: " + Assembly.GetExecutingAssembly().Location);
Console.ReadKey();
}
 
public static string AssemblyDirectory()
{
var uri = new UriBuilder(Assembly.GetExecutingAssembly().CodeBase);
return Path.GetDirectoryName(Uri.UnescapeDataString(uri.Path));
}
 
}
}
 

Visual Basic

 

Imports System.Reflection
Imports System.IO
 
Module Module1
 
Sub Main()
Console.WriteLine("Directory: " + AssemblyDirectory())
Console.WriteLine("Location: " + Assembly.GetExecutingAssembly().Location)
Console.ReadKey()
End Sub
 
Public Function AssemblyDirectory() As String
Dim uri = New UriBuilder(Assembly.GetExecutingAssembly().CodeBase)
Return Path.GetDirectoryName(System.Uri.UnescapeDataString(uri.Path))
End Function
 
End Module

The calling thread must be STA, because many UI components require this


Whilst working on my current WPF application, I was at Sixes & Sevens trying to correct the following error;

Message: The calling thread must be STA, because many UI components require this

I ended up hacking my way out of this problem a week or so ago, hacks however, make me feel extremely dirty, and subscribing to the “leave code as you would like to find it” mantra meant one had to subsequently revisit it to “tidy-up”.  I have a strictly MVVM application that is complex and multithreaded, needing to update UI components from web service calls that typically are asynchronous. The issue here was that I was using code like this in my view model thinking I had access to the dispatcher.

Dispatcher.CurrentDispatcher.BeginInvoke((Action) (() =>
 

The mistake I made was in not getting a reference to the correct dispatcher.

To correct this issue, ensure you have a variable that gets a reference to the correct dispatcher when the view model is instantiated, you can then use this dispatcher in your view model, without having to pollute your code behind files.

private readonly Dispatcher dispatcher;
 
public DemoViewModel()
{
this.dispatcher = Dispatcher.CurrentDispatcher;
}

Single instance WPF application in C#


Update: 12/03/2012

I ran into some issues with the approach that I linked to below, and would not recommend it. It turns out that the best way to deal with this issue, is to use the Visual Basic instance detection classes (yes you can use these from C#). The sample code is available here

Note that is is more than likely that you will be retrofitting this to an existing project. If that is the case, make sure you double click the properties pane in visual studio and set your custom start-up file/class as shown below

startup

 

Original Post

Keeping in the same vein as my previous post, I frequently find that I have to solve the same problems at times. After a year or several months I usually move onto another project, consequently no longer have the source code, so I am posting this as a bit of a sticky as I am sure someone will find it useful.

Visual Basic has single instance classes one can use, one can import these into any C# application and consume them (that, after all,  is the real beauty of .NET), but I found that there was too much code, and too many classes, and it was taking me too long a little while back. I solve this problem using the Process class. Create a WPF application and use as follows;

using System.Diagnostics;
using System.Linq;
using System.Windows;
 
namespace SingleInstanceApp
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
IsAppAlreadyRunning();
}
 
private static void IsAppAlreadyRunning()
{
Process currentProcess = Process.GetCurrentProcess();
 
if (Process.GetProcessesByName(currentProcess.ProcessName).Any(p => p.Id != currentProcess.Id))
{
MessageBox.Show("Another instance is already running.", "Application already running",
MessageBoxButton.OK, MessageBoxImage.Exclamation);
Current.Shutdown();
return;
}
}
}
}

Copying an object in C# and Visual Basic


Sometimes there are classes you find you use in every project. I remember once (shudder) I, rather inelegantly instantiated a class, and performed a manual copy of all the properties in the object (when the pressure was on, and I just needed to make the thing work).

I have also found myself spending hours chasing subtle and hard to debug issues where ICloneable has been used -  which, incidentally, is widely accepted as an interface one ought never use – or Object.MemberwiseClone. It turns out the only way to do this correctly, is to serialise the object, and then use the deserialised object, implemented here using an extension method.

Even though this is quite straightforward, I still am posting this however , because I find I need to use this functionality frequently, and often I no longer have access to the source, or it takes ages to find the class. The Visual Basic code sample is after the C# one.

C#

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
 
namespace ObjectCopierApp.Extensions
{
/// <summary>
/// Provides a method for performing deep copying of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>
internal static class ObjectCopier
{
/// <summary>
/// Perform a deep copy of an object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
internal static T Clone<T>(this T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
 
// Don’t serialize a null object, simply return the default for that object
if (ReferenceEquals(source, null))
{
return default(T);
}
 
IFormatter formatter = new BinaryFormatter();
 
using (var stream = new MemoryStream())
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
}
 
 

Visual Basic

Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
 
Namespace ObjectCopierApp.Extensions
”’ <summary>
”’ Provides a method for performing deep copying of an object.
”’ Binary Serialization is used to perform the copy.
”’ </summary>
Friend NotInheritable Class ObjectCopier
Private Sub New()
End Sub
”’ <summary>
”’ Perform a deep copy of an object.
”’ </summary>
”’ <typeparam name="T">The type of object being copied.</typeparam>
”’ <param name="source">The object instance to copy.</param>
”’ <returns>The copied object.</returns>
<System.Runtime.CompilerServices.Extension()> _
Friend Shared Function Clone(Of T)(source As T) As T
If Not GetType(T).IsSerializable Then
Throw New ArgumentException("The type must be serializable.", "source")
End If
 
‘ Don’t serialize a null object, simply return the default for that object
If ReferenceEquals(source, Nothing) Then
Return Nothing
End If
 
Dim formatter As IFormatter = New BinaryFormatter()
 
Using stream = New MemoryStream()
formatter.Serialize(stream, source)
stream.Seek(0, SeekOrigin.Begin)
Return DirectCast(formatter.Deserialize(stream), T)
End Using
End Function
End Class
End Namespace