SyntaxHighlighter

Friday, 27 October 2017

Open & Close a VPN Connection with C#

I've thrown together this simple class to check if a windows VPN connection is open and with it you can also connect and disconnect. It's not massively robust but does the trick. It's makes use of the rasdial command and is inspired by this post on SO.

Here's how to use it:
//Get a VPN connector ready
VPNConnector vpn = new VPNConnector("VPN_NAME", "USER_NAME", "USER_PASSWORD");

//Connect
Tuple<bool, IList<string>> response = vpn.Connect();

if (response.Item1)
{
    //Successfully connected
    Console.WriteLine("Connected!");
}
else
{
    //Failed to connect
    Console.WriteLine("Failed to connect :(");
    foreach (string s in response.Item2)
    {
        Console.WriteLine(s);
    }
}

//Disconnect
vpn.Disconnect();

You can optionally check if the connection is already open by using vpn.IsOpen.

The code:
/// <summary>
/// Gives access to Windows VPN connections
/// </summary>
public class VPNConnector
{

	#region Properties

	#region VPNName
	/// <summary>
	/// The name of the VPN connection
	/// </summary>
	public string VPNName { get; set; }
	#endregion

	#region Username
	/// <summary>
	/// The username to use for the connection
	/// </summary>
	public string Username { get; set; }
	#endregion

	#region Password
	/// <summary>
	/// The password to use for the connection
	/// </summary>
	public string Password { get; set; }
	#endregion

	#region IsOpen
	/// <summary>
	/// Whether the connection is currently open or not
	/// </summary>
	public bool IsOpen
	{
		get
		{
			if (String.IsNullOrWhiteSpace(this.VPNName))
				throw new ArgumentException("No VPN name (VPNName) has been set");
			
			Process p = this.getNewProcess;
			p.Start();

			bool bOpen = false;
			while (!p.StandardOutput.EndOfStream)
			{
				string sOutput = p.StandardOutput.ReadLine();
				if (sOutput.ToLower() != "no connections")
				{
					if (sOutput == this.VPNName)
					{
						bOpen = true;
						break;
					}
				}
				else
					break;
			}
			p.WaitForExit();

			return bOpen;
		}
	}
	#endregion

	#region parametersAreASet
	/// <summary>
	/// Determines if all the necessary parameters are set to make a VPN connection
	/// </summary>
	private bool parametersAreASet { get { return (!String.IsNullOrWhiteSpace(this.VPNName) && !String.IsNullOrWhiteSpace(this.Username) && !String.IsNullOrWhiteSpace(this.Password)); } }
	#endregion

	#region getNewProcess
	/// <summary>
	/// Get a new process ready to start a rasdial call
	/// </summary>
	private Process getNewProcess
	{
		get
		{
			return new Process
			{
				StartInfo = new ProcessStartInfo
				{
					FileName = "rasdial.exe",
					UseShellExecute = false,
					RedirectStandardOutput = true,
					CreateNoWindow = true
				}
			};
		}
	} 
	#endregion

	#endregion

	#region Cosntructor
	public VPNConnector() { }

	public VPNConnector(string name, string username, string password)
	{
		this.VPNName = name;
		this.Username = username;
		this.Password = password;

		if (!this.parametersAreASet)
			throw new ArgumentException("All arguments must have a value");
	}
	#endregion

	#region Public Methods

	#region Instance

	#region Connect
	/// <summary>
	/// Make a connection to the VPN. Item1 of Tuple indicates success or failure. Item2 of Tuple is the output of the dial call
	/// </summary>
	public Tuple<bool, IList<string>> Connect()
	{
		if (!this.IsOpen)
		{
			if (!this.parametersAreASet)
				throw new ArgumentException("All arguments must have a value");

			Process p = this.getNewProcess;
			p.StartInfo.Arguments = $"\"{this.VPNName}\" \"{this.Username}\" \"{ this.Password}\"";
			p.Start();

			bool bSuccess = false;
			IList<string> outputs = new List<string&gt();
			while (!p.StandardOutput.EndOfStream)
			{
				string sOutput = p.StandardOutput.ReadLine();
				outputs.Add(sOutput);

				if (sOutput.ToLower().StartsWith("success"))
					bSuccess = true;
			}
			p.WaitForExit();

			return new Tuple<bool, IList<string>>(bSuccess, outputs);
		}
		else
			return new Tuple<bool, IList<string>>(false, new List<string>() { "Connection already open" } );
	}
	#endregion

	#region Disconnect
	/// <summary>
	/// Disconnect from the VPN. Item1 of Tuple indicates success or failure. Item2 of Tuple is the output of the dial call
	/// </summary>
	public Tuple<bool, IList<string>> Disconnect()
	{
		if (this.IsOpen)
		{
			Process p = this.getNewProcess;
			p.StartInfo.Arguments = $"\"{this.VPNName}\" /d";
			p.Start();

			bool bSuccess = false;
			IList<string> outputs = new List<string>();
			while (!p.StandardOutput.EndOfStream)
			{
				string sOutput = p.StandardOutput.ReadLine();
				outputs.Add(sOutput);

				if (sOutput.ToLower().Contains("success"))
					bSuccess = true;
			}
			p.WaitForExit();

			return new Tuple<bool, IList<string>>(bSuccess, outputs);
		}
		else
			return new Tuple<bool, IList<string>>(false, new List<string&gt() { "Connection already closed" });
	}
	#endregion

	#endregion

	#endregion

}

Friday, 13 January 2017

signalR - Error during WebSocket handshake: Unexpected response code: 500

Having recently started playing with signalR, I got the following error:

WebSocket connection to 'ws://localhost/../signalr/connect?transport=webSockets&clientProtocol=1.4&connectionToken=DJquvX4%2B7kH0EzXZcCYSRPL66R3ytyc204DflljN1%2BgkHqi6Y5llDAAeUZTDKkDFFBQm6rdJooh8ck7LcejXVFZvhxE0iUJVD%2BZadN%2Ff5s13rc%2FMZD4WxsMSlToyvYid&connectionData=%5B%7B%22name%22%3A%22myapp%22%7D%5D&tid=4' failed: Error during WebSocket handshake: Unexpected response code: 500

This was odd as it was working fine on another development machine I was using. After serious amounts of hunting around and mucking about, I got it working by adding the following to the web.config:

<system.web>
    <httpRuntime targetFramework="4.5"/>
</system.web>

Interestingly, I found the answer in the Application Event Logs :)

It's also worth checking that the application target framework is also set to 4.5 in case there is a conflict there too.

Labels

.net (7) ajax (1) android (7) apache (1) asp.net (3) asus (2) blogger (2) blogspot (3) c# (16) compact framework (2) cron (1) css (1) data (1) data recovery (2) dns (1) eclipse (1) encryption (1) excel (1) font (1) ftp (1) gmail (5) google (4) gopro (1) html (1) iis (3) internet explorer IE (1) iphone (1) javascript (3) kinect (1) linux (1) macro (1) mail (9) mercurial (1) microsoft (3) microsoft office (3) monitoring (1) mootools (1) ms access (1) mssql (13) mysql (2) open source (1) openvpn (1) pear (2) permissions (1) php (12) plesk (4) proxy (1) qr codes (1) rant (4) reflection (3) regex (1) replication (1) reporting services (5) security (2) signalr (1) sql (11) sqlce (1) sqlexpress (1) ssis (1) ssl (1) stuff (1) svn (2) syntax (1) tablet (2) telnet (3) tools (1) twitter (1) unix (3) vb script (3) vb.net (9) vba (1) visual studio (2) vpc (2) vpn (1) windows (4) woff (1) xbox 360 (1)