833 lines
31 KiB
C#
833 lines
31 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Net;
|
|
using System.Net.NetworkInformation;
|
|
using System.Net.Sockets;
|
|
using Yaulw.Win32;
|
|
using System.Management;
|
|
using System.IO;
|
|
|
|
namespace Yaulw.Net
|
|
{
|
|
/// <summary>
|
|
/// Helper for common IP / Host Machine
|
|
/// </summary>
|
|
public static class IPHostHelper
|
|
{
|
|
#region Public consts
|
|
|
|
/// <summary>
|
|
/// This automation URL used to work, now it no longer works :(
|
|
/// Caller must set this before calling ExternalIP() Functions
|
|
/// </summary>
|
|
public static string WHAT_IS_MY_IP_AUTOMATION_URL = "http://automation.whatismyip.com/n09230945.asp";
|
|
|
|
#endregion
|
|
|
|
#region IPv4 Checkers
|
|
|
|
/// <summary>
|
|
/// Checks to see that the passed in ip is a valid Local IP
|
|
/// address that is of version 4 and not a broadcast/loopback/None
|
|
/// </summary>
|
|
/// <param name="ip"></param>
|
|
/// <param name="bAllowLoopback">true to allow Loopback address as valid Local IP</param>
|
|
/// <returns></returns>
|
|
/// <remarks>
|
|
/// IPAddress.IPv6Any = "::";
|
|
/// IPAddress.Any = "0.0.0.0"
|
|
/// IPAddress.Broadcast = "255.255.255.255"
|
|
/// IPAddress.None = "255.255.255.255"
|
|
/// IPAddress.Loopback = "127.0.0.1"
|
|
/// </remarks>
|
|
public static bool IsValidIPv4Address(IPAddress ip, bool bAllowLoopback)
|
|
{
|
|
if (ip != null)
|
|
{
|
|
if (ip.AddressFamily != AddressFamily.InterNetwork)
|
|
return false;
|
|
if (ip.AddressFamily.ToString().Contains(IPAddress.IPv6Any.ToString()))
|
|
return false;
|
|
if (ip == IPAddress.Any)
|
|
return false;
|
|
if (ip == IPAddress.Broadcast)
|
|
return false;
|
|
if (ip == IPAddress.None)
|
|
return false;
|
|
|
|
// Loopback technically is a valid Local IP that can be used to communicate
|
|
// to ourselves (on the same machine)
|
|
if (ip == IPAddress.Loopback)
|
|
return bAllowLoopback;
|
|
|
|
// This must be a valid local IPv4
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks to see if the passed in ip is in a valid Private subnet (i.e. not public)
|
|
/// </summary>
|
|
/// <param name="ip"></param>
|
|
/// <returns></returns>
|
|
/// <remarks>
|
|
/// Private subnets as defined in <seealso cref="http://tools.ietf.org/html/rfc1918"/>
|
|
/// Loopback address 127.0.0.1/8 <seealso cref="http://tools.ietf.org/html/rfc3330"/>
|
|
/// Zeroconf/bonjour self assigned addresses 169.254.0.0/16 <seealso cref="http://tools.ietf.org/html/rfc3927"/>
|
|
/// </remarks>
|
|
public static bool IsIPv4AddressInPrivateSubnet(IPAddress ip)
|
|
{
|
|
if (!IsValidIPv4Address(ip, true))
|
|
return false;
|
|
|
|
String[] netAddrs = { "192.168.0.0", "10.0.0.0", "172.16.0.0", "127.0.0.1", "169.254.0.0" };
|
|
String[] netMasks = { "255.255.0.0", "255.0.0.0", "255.240.0.0", "255.0.0.0", "255.255.0.0" };
|
|
|
|
UInt32 myIP = BitConverter.ToUInt32(ip.GetAddressBytes(), 0);
|
|
for (int i = 0; i < netMasks.Length; i++)
|
|
{
|
|
IPAddress netAddr = IPAddress.Parse(netAddrs[i]);
|
|
UInt32 netIP = BitConverter.ToUInt32(netAddr.GetAddressBytes(), 0);
|
|
|
|
IPAddress maskAddr = IPAddress.Parse(netMasks[i]);
|
|
UInt32 maskIP = BitConverter.ToUInt32(maskAddr.GetAddressBytes(), 0);
|
|
|
|
if ((myIP & maskIP) == (netIP & maskIP))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compares two IP Addresses, if the Left One is different from the right one, assigns
|
|
/// the right one to the LeftOrRight (simple) and returns true. Otherwise assigns left to it and returns false.
|
|
/// </summary>
|
|
public static bool AreIPAddressesDifferent(IPAddress left, IPAddress right, out IPAddress LeftOrRight)
|
|
{
|
|
LeftOrRight = left;
|
|
if (left != null && right != null)
|
|
{
|
|
if (String.Compare(left.ToString(), right.ToString(), true) != 0)
|
|
{
|
|
LeftOrRight = right;
|
|
return true;
|
|
}
|
|
}
|
|
else if (left == null && right != null)
|
|
{
|
|
LeftOrRight = right;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Connectivity
|
|
|
|
/// <summary>
|
|
/// Method to check if the Local Computer has a valid Network Connection
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static bool HasConnection()
|
|
{
|
|
//instance of our ConnectionStatusEnum
|
|
Definitions.ConnectionStatusEnum state = 0;
|
|
|
|
//call the API
|
|
bool bIsConnected = Wininet.InternetGetConnectedState(ref state, 0);
|
|
if (!bIsConnected)
|
|
return false;
|
|
|
|
//check the status, if in offline mode then return false
|
|
if (((int)Definitions.ConnectionStatusEnum.INTERNET_CONNECTION_OFFLINE & (int)state) != 0)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Method to check to see if local Computer has a valid Network connection
|
|
/// and can open the specified ip and port
|
|
/// </summary>
|
|
/// <param name="ip"></param>
|
|
/// <param name="port"></param>
|
|
/// <returns></returns>
|
|
public static bool HasConnectivity(IPAddress ip, uint port)
|
|
{
|
|
if(HasConnection() && IsValidIPv4Address(ip, true) && port > 0)
|
|
return IsPortOpen(ip, (int) port);
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Method to check to see if local Computer has a valid Network connection
|
|
/// and can open the specified host and port
|
|
/// </summary>
|
|
/// <param name="host"></param>
|
|
/// <param name="port"></param>
|
|
/// <param name="nTimeout"></param>
|
|
/// <returns></returns>
|
|
public static bool HasConnectivity(string host, uint port, int nTimeout)
|
|
{
|
|
if (HasConnection() && port > 0)
|
|
{
|
|
IPAddress ip = GetIpForHost(host);
|
|
if(ip != IPAddress.None && IsValidIPv4Address(ip, false))
|
|
return IsPortOpen(ip, (int) port, nTimeout);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the Servername from a DataBaseConnectionString, if possible,
|
|
/// then gets the ip for the server name and tries to open up the port specified
|
|
/// </summary>
|
|
/// <param name="DataBaseConnectionString">pass in either a DataSource or ConnectionString</param>
|
|
/// <param name="port"></param>
|
|
/// <returns></returns>
|
|
public static bool HasConnectivity(string DataBaseConnectionString, uint port)
|
|
{
|
|
if (HasConnection() && !String.IsNullOrEmpty(DataBaseConnectionString))
|
|
{
|
|
// Allow the SharedConnectionDataSource to be a ConnectionString also via calling GetDataSource()
|
|
DataBaseConnectionString = GetDataSource(DataBaseConnectionString);
|
|
|
|
// Retrieve the IP for the Data Source and test the ip and set it in the API
|
|
string host = GetServerNameFromADataSource(DataBaseConnectionString);
|
|
IPAddress ip = GetIpForHost(host);
|
|
if (ip != IPAddress.None)
|
|
{
|
|
if (IsPortOpen(ip, (int) port))
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Core IPHostHelper Functionallity
|
|
|
|
/// <summary>
|
|
/// Converts all incl. Loopback, if contained, valid IP addresses into a String array of IPs
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static string[] ConvertIPArrayToStringArray(IPAddress[] IPs)
|
|
{
|
|
List<string> ips = new List<string>();
|
|
if (IPs != null && IPs.Length > 0)
|
|
{
|
|
foreach (IPAddress ip in IPs)
|
|
{
|
|
if (IsValidIPv4Address(ip, true))
|
|
ips.Add(ip.ToString());
|
|
}
|
|
}
|
|
return ips.ToArray();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get all valid IPv4 Local IP addresses besides the loopback address
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static IPAddress[] GetAllLocalIPAddresses()
|
|
{
|
|
// Get host name
|
|
String HostName = Dns.GetHostName();
|
|
IPHostEntry iphostentry = Dns.GetHostEntry(HostName);
|
|
|
|
// Enumerate IP addresses
|
|
List<IPAddress> IPs = new List<IPAddress>();
|
|
foreach (IPAddress ipaddress in iphostentry.AddressList)
|
|
{
|
|
if (IsValidIPv4Address(ipaddress, false))
|
|
IPs.Add(ipaddress);
|
|
}
|
|
|
|
// Return them as a string[] of IPs
|
|
return IPs.ToArray();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get First Found Local IP Address (or IPAddress.None, if none found)
|
|
/// </summary>
|
|
/// <returns>get the first Local IP Address found</returns>
|
|
public static IPAddress GetFirstLocalIPAddress()
|
|
{
|
|
IPAddress[] IPs = GetAllLocalIPAddresses();
|
|
if (IPs.Length > 0)
|
|
return IPs[0];
|
|
else
|
|
return IPAddress.None;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get Nth Found Local IP Address (or first one found, if n > IPs Found)
|
|
/// (or IPAddress.None, if none found)
|
|
/// </summary>
|
|
/// <returns>get the Nth Local IP Address found</returns>
|
|
public static IPAddress GetNthLocalIPAddress(int n)
|
|
{
|
|
IPAddress[] IPs = GetAllLocalIPAddresses();
|
|
if (n >= 0 && IPs.Length < n)
|
|
return IPs[n];
|
|
else if (IPs.Length > 0)
|
|
return IPs[0];
|
|
else
|
|
return IPAddress.None;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check to see if the host passed in is Local
|
|
/// </summary>
|
|
/// <param name="host">can be ip or host name</param>
|
|
/// <returns>true, if host or ip is local, false otherwise</returns>
|
|
/// <exception cref="ArgumentException">When host is empty</exception>
|
|
public static bool IsHostOrIPLocal(string host)
|
|
{
|
|
if (!String.IsNullOrEmpty(host))
|
|
{
|
|
IPAddress ip = null;
|
|
if (IPAddress.TryParse(host, out ip))
|
|
{
|
|
IPAddress[] localIPs = GetAllLocalIPAddresses();
|
|
foreach(IPAddress localip in localIPs)
|
|
{
|
|
if (localip == ip)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return (String.Compare(host.Trim(), Dns.GetHostName(), true) == 0);
|
|
}
|
|
}
|
|
throw new ArgumentException("Invalid host");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Method for resolving a Host (DNS Resolve)
|
|
/// </summary>
|
|
/// <param name="host">the host</param>
|
|
/// <param name="bMustBeInPrivateIPRange">Set to true, if the host must be in the Private IP Range</param>
|
|
/// <returns>true, if host can be resolved to an IP Address, false otherwise</returns>
|
|
public static bool CanResolveHost(string host, bool bMustBeInPrivateIPRange)
|
|
{
|
|
if(!String.IsNullOrEmpty(host))
|
|
{
|
|
IPAddress ip = GetIpForHost(host);
|
|
if (bMustBeInPrivateIPRange)
|
|
return IsIPv4AddressInPrivateSubnet(ip);
|
|
return (ip != IPAddress.None);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Method for retrieving the IP address for a Host (DNS Resolve)
|
|
/// </summary>
|
|
/// <param name="host">the host we need the ip address for</param>
|
|
/// <returns>an IPAddress if found, otherwise IPAddress.None</returns>
|
|
public static IPAddress GetIpForHost(string host)
|
|
{
|
|
//variable to hold our error message (if something fails)
|
|
string errMessage = string.Empty;
|
|
|
|
//IPAddress instance for holding the returned host
|
|
IPAddress address = IPAddress.None;
|
|
|
|
//wrap the attempt in a try..catch to capture
|
|
//any exceptions that may occur
|
|
try
|
|
{
|
|
// if it's already an ip address being passed in,
|
|
// we are done
|
|
if (!IPAddress.TryParse(host, out address))
|
|
{
|
|
//get the host IP from the name provided
|
|
address = Dns.GetHostEntry(host).AddressList[0];
|
|
|
|
// We must be called for the local host, that
|
|
// could explain why it is not a valid IP
|
|
if (!IsValidIPv4Address(address, false))
|
|
address = GetFirstLocalIPAddress();
|
|
}
|
|
else
|
|
{
|
|
address = IPAddress.Parse(host);
|
|
}
|
|
}
|
|
catch (Exception) { /* ignore */ }
|
|
if (address == null)
|
|
return IPAddress.None;
|
|
else
|
|
return address;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ping a host
|
|
/// </summary>
|
|
/// <param name="host">url/host/ip</param>
|
|
/// <param name="nTimeout">timeout value in miliseconds</param>
|
|
/// <param name="nTrys">number of times to ping</param>
|
|
/// <returns>the number of successful pings</returns>
|
|
public static int PingHost(string host, int nTimeout, int nTrys)
|
|
{
|
|
//string to hold our return messge
|
|
//string returnMessage = string.Empty;
|
|
|
|
// Check to see if the host passed in is an IP Address
|
|
// otherwise, just resolve the host
|
|
IPAddress address = null;
|
|
if(!IPAddress.TryParse(host, out address))
|
|
address = GetIpForHost(host);
|
|
|
|
// Error occured resolving host
|
|
if (!IsValidIPv4Address(address, false))
|
|
return 0;
|
|
|
|
//set the ping options, TTL 128
|
|
PingOptions pingOptions = new PingOptions(128, true);
|
|
|
|
//create a new ping instance
|
|
Ping ping = new Ping();
|
|
|
|
//32 byte buffer (create empty)
|
|
byte[] buffer = new byte[32];
|
|
|
|
//first make sure we actually have an internet connection
|
|
int nPingSuccess = 0;
|
|
if (HasConnection())
|
|
{
|
|
//here we will ping the host nTrys times
|
|
for (int i = 0; i < nTrys; i++)
|
|
{
|
|
try
|
|
{
|
|
PingReply pingReply = ping.Send(address, nTimeout, buffer, pingOptions);
|
|
if (!(pingReply == null))
|
|
{
|
|
switch (pingReply.Status)
|
|
{
|
|
case IPStatus.Success:
|
|
nPingSuccess++;
|
|
break;
|
|
case IPStatus.TimedOut:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception) { /* ignore and continue iterating */ }
|
|
}
|
|
}
|
|
return nPingSuccess;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Port Open
|
|
|
|
/// <summary>
|
|
/// Check to see if a port is open for the specified ip
|
|
/// </summary>
|
|
/// <param name="host"></param>
|
|
/// <param name="port"></param>
|
|
/// <returns></returns>
|
|
public static bool IsPortOpen(IPAddress ip, int port)
|
|
{
|
|
bool bCanConnect = false;
|
|
if (IsValidIPv4Address(ip, true) && port > 0)
|
|
{
|
|
try
|
|
{
|
|
TcpClient tcP = new System.Net.Sockets.TcpClient();
|
|
tcP.Connect(ip, port);
|
|
bCanConnect = true;
|
|
tcP.Close();
|
|
}
|
|
catch (Exception) { /* ignore */ }
|
|
}
|
|
return bCanConnect;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check to see if a port is open for the specified ip
|
|
/// </summary>
|
|
/// <param name="host"></param>
|
|
/// <param name="port"></param>
|
|
/// <returns></returns>
|
|
public static bool IsPortOpen(IPAddress ip, int port, int nTimeout)
|
|
{
|
|
bool bCanConnect = false;
|
|
if (IsValidIPv4Address(ip, true) && port > 0)
|
|
{
|
|
try
|
|
{
|
|
TcpClient tcP = new System.Net.Sockets.TcpClient();
|
|
if (nTimeout > 0)
|
|
tcP.ReceiveTimeout = nTimeout;
|
|
tcP.Connect(ip, port);
|
|
bCanConnect = true;
|
|
tcP.Close();
|
|
}
|
|
catch (Exception) { /* ignore */ }
|
|
}
|
|
return bCanConnect;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Get External IP
|
|
|
|
/// <summary>
|
|
/// Get the External IP
|
|
/// </summary>
|
|
/// <param name="pTimeOutMiliSeconds">Timeout in MiliSeconds</param>
|
|
/// <returns>a valid external IPAddress or IPAddress.None, if error occured</returns>
|
|
public static IPAddress GetExternalIP(int pTimeOutMiliSeconds)
|
|
{
|
|
IPAddress extIP = IPAddress.None;
|
|
try
|
|
{
|
|
using (WebClient wc = new WebClient())
|
|
{
|
|
wc.Headers.Add("user-agent", WCHelper.USER_AGENT_GENERIC);
|
|
UTF8Encoding utf8 = new UTF8Encoding();
|
|
string ipaddr = null;
|
|
bool done = false;
|
|
|
|
wc.DownloadDataCompleted += new
|
|
DownloadDataCompletedEventHandler((object sender,
|
|
DownloadDataCompletedEventArgs e) =>
|
|
{
|
|
ipaddr = utf8.GetString(e.Result);
|
|
done = true;
|
|
});
|
|
|
|
wc.DownloadDataAsync(new Uri(WHAT_IS_MY_IP_AUTOMATION_URL));
|
|
System.DateTime startTime = System.DateTime.Now;
|
|
while (!done)
|
|
{
|
|
System.TimeSpan sp = System.DateTime.Now - startTime;
|
|
|
|
// We should get a response in less than timeout.
|
|
// If not, we cancel all and return the internal IP Address
|
|
if (sp.TotalMilliseconds > pTimeOutMiliSeconds)
|
|
{
|
|
done = true;
|
|
wc.CancelAsync();
|
|
}
|
|
}
|
|
|
|
if (IPAddress.TryParse(ipaddr, out extIP))
|
|
return extIP;
|
|
}
|
|
}
|
|
catch { /* ignore */ }
|
|
return IPAddress.None;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the External IP
|
|
/// </summary>
|
|
/// <returns>a valid external IPAddress or IPAddress.None, if error occured</returns>
|
|
public static IPAddress GetExternalIP()
|
|
{
|
|
string ipaddr = WCHelper.ScreenScrapeFromURL(WHAT_IS_MY_IP_AUTOMATION_URL);
|
|
IPAddress extIP = IPAddress.None;
|
|
if (IPAddress.TryParse(ipaddr, out extIP))
|
|
return extIP;
|
|
return IPAddress.None;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Call this to retrieve the external IP Address (also makes sure we can connect
|
|
/// to WhatIsMyIp site)
|
|
/// </summary>
|
|
/// <param name="bForceMultipleChecks">
|
|
/// Forces 4 checks at 2.5/5.0/7.5/10 seconds timeout values
|
|
/// otherwise makes one request defaulting to 5.0
|
|
/// </param>
|
|
/// <returns>valid external IP Address or null if not found</returns>
|
|
public static IPAddress GetExternalIP(bool bForceMultipleChecks)
|
|
{
|
|
if (HasConnection())
|
|
{
|
|
IPAddress ipExtIP = null;
|
|
if (bForceMultipleChecks)
|
|
{
|
|
// Check with an timout of 2.5/5.0/7.5/10 seconds
|
|
for (int n = 2500; n <= 10000; n = n + 2500)
|
|
{
|
|
ipExtIP = GetExternalIP(n);
|
|
if(ipExtIP != IPAddress.None)
|
|
return ipExtIP;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Check with whatever is the default timeout
|
|
ipExtIP = Yaulw.Net.IPHostHelper.GetExternalIP(5000);
|
|
return ipExtIP;
|
|
}
|
|
}
|
|
return IPAddress.None;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region UNC and Path Related Windows Network Helpers
|
|
|
|
/// <summary>
|
|
/// Allows us to use either pass in a ConnectionString or a DataSource * Added flexibility *
|
|
/// will return the DataSource part of the connection string, if exists, otherwise the connection string
|
|
/// </summary>
|
|
/// <param name="DataBaseConnectionString">pass in either a DataSource or ConnectionString</param>
|
|
/// <returns></returns>
|
|
public static string GetDataSource(string DataBaseConnectionString)
|
|
{
|
|
if (IsDataBaseConnectionString(DataBaseConnectionString))
|
|
{
|
|
String[] tokens = DataBaseConnectionString.Split(';');
|
|
foreach (string Pair in tokens)
|
|
{
|
|
string[] KeyValuePair = Pair.Split('=');
|
|
try
|
|
{
|
|
string left = KeyValuePair[0];
|
|
string right = KeyValuePair[1];
|
|
string FoundValue = "";
|
|
if (String.Compare(KeyValuePair[0].ToUpper().Trim(), "DATA SOURCE", true) == 0)
|
|
{
|
|
if (!String.IsNullOrEmpty(right))
|
|
{
|
|
FoundValue = right.Trim();
|
|
return FoundValue;
|
|
}
|
|
}
|
|
|
|
}
|
|
catch (Exception) { /* ignore and continue iteration */ }
|
|
}
|
|
}
|
|
|
|
// Migth still be a data source just not from a Connection string
|
|
// so just return the value trimmed
|
|
if (!String.IsNullOrEmpty(DataBaseConnectionString))
|
|
return DataBaseConnectionString.Trim();
|
|
else
|
|
return String.Empty;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Quick Check to see if a connection string is valid * must have DataSource Key and
|
|
/// a Value * in order to be considered a valid Connection String
|
|
/// </summary>
|
|
/// <param name="ConnectionString"></param>
|
|
/// <returns></returns>
|
|
public static bool IsDataBaseConnectionString(string ConnectionString)
|
|
{
|
|
if (!String.IsNullOrEmpty(ConnectionString) &&
|
|
ConnectionString.ToUpper().Contains("DATA SOURCE") &&
|
|
ConnectionString.Contains("="))
|
|
{
|
|
String[] tokens = ConnectionString.Split(';');
|
|
foreach (string Pair in tokens)
|
|
{
|
|
string[] KeyValuePair = Pair.Split('=');
|
|
try
|
|
{
|
|
string left = KeyValuePair[0];
|
|
string right = KeyValuePair[1];
|
|
if (String.Compare(KeyValuePair[0].ToUpper().Trim(), "DATA SOURCE", true) == 0)
|
|
return !String.IsNullOrEmpty(right);
|
|
}
|
|
catch (Exception) { /* ignore and continue iteration */ }
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the Server Name from a Database DataSource Connection String
|
|
/// </summary>
|
|
/// <param name="DataSource">
|
|
/// [DriveLetter]:\{SomeFileNameNPath}
|
|
/// \\{Server]\{SomeFileNameNPath}
|
|
/// \\{Server]:[Port]\{SomeFileNameNPath}
|
|
/// [Server]\Instance
|
|
/// [Server]
|
|
/// </param>
|
|
/// <remarks>Server string returned can be a name or an IP address</remarks>
|
|
/// <returns>Server Host Name or IP</returns>
|
|
public static string GetServerNameFromADataSource(string DataSource)
|
|
{
|
|
if (!String.IsNullOrEmpty(DataSource))
|
|
{
|
|
|
|
// Always strip out port in the DataSource *before doing anything*
|
|
// only do this for non-local paths
|
|
if (DataSource.Contains(":") && DataSource[1] != ':')
|
|
{
|
|
int nLoc = DataSource.IndexOf(":");
|
|
if (nLoc != -1)
|
|
DataSource = DataSource.Substring(0, nLoc);
|
|
}
|
|
|
|
// Let's begin ...
|
|
string Server = String.Empty;
|
|
|
|
// Local Medisoft
|
|
bool bIsLocalFilePath = DataSource.Contains(@":\");
|
|
if (bIsLocalFilePath)
|
|
{
|
|
string PathInCaseMapped = ResolveToUNCIfNeeded(DataSource);
|
|
|
|
// It's a local or a UNC path
|
|
if (!PathInCaseMapped.StartsWith(@"\\"))
|
|
{
|
|
// If Local file that the host is this computer
|
|
return Dns.GetHostName();
|
|
}
|
|
else
|
|
{
|
|
// else it's the other host * so follow UNC logic *
|
|
// Stripe out first 2 chars
|
|
Server = PathInCaseMapped.Substring(2);
|
|
|
|
// Stripe out the rest
|
|
int nLoc = Server.IndexOf(@"\");
|
|
if (nLoc != -1)
|
|
Server = Server.Substring(0, nLoc);
|
|
}
|
|
}
|
|
|
|
// Remote Medisoft
|
|
bool bIsNetworkFilePath = DataSource.StartsWith(@"\\");
|
|
if (bIsNetworkFilePath)
|
|
{
|
|
// Stripe out first 2 chars
|
|
Server = DataSource.Substring(2);
|
|
|
|
// Stripe out the rest
|
|
int nLoc = Server.IndexOf(@"\");
|
|
if (nLoc != -1)
|
|
Server = Server.Substring(0, nLoc);
|
|
}
|
|
|
|
// It's Lytec! :)
|
|
bool bIsSQLServerInstance = !bIsLocalFilePath && !bIsNetworkFilePath;
|
|
if (bIsSQLServerInstance)
|
|
{
|
|
// Stripe out Instance, if it exists
|
|
int nLoc = DataSource.IndexOf(@"\");
|
|
if (nLoc != -1)
|
|
Server = DataSource.Substring(0, nLoc);
|
|
else
|
|
Server = DataSource;
|
|
}
|
|
|
|
return Server;
|
|
}
|
|
return String.Empty;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines if the passed in string is a connection string or a data Source
|
|
/// and tries to make the best of things to retrieve the host/server name
|
|
/// </summary>
|
|
/// <param name="ConnectionString"></param>
|
|
/// <returns></returns>
|
|
public static string GetServerNameFromAConnectionString(string ConnectionString)
|
|
{
|
|
if (IsDataBaseConnectionString(ConnectionString))
|
|
{
|
|
string DataSource = GetDataSource(ConnectionString);
|
|
return GetServerNameFromADataSource(DataSource);
|
|
}
|
|
else
|
|
{
|
|
// Pretentd that it is just a DataSource
|
|
return GetServerNameFromADataSource(ConnectionString);
|
|
}
|
|
}
|
|
|
|
/// <summary>Resolves the given path to a UNC path, or local drive path.</summary>
|
|
/// <param name="pPath"></param>
|
|
/// <returns>\\server\share\[path] OR [driveletter]:\[path]</returns>
|
|
public static string ResolveToUNCIfNeeded(string pPath)
|
|
{
|
|
if (String.IsNullOrEmpty(pPath))
|
|
return String.Empty;
|
|
|
|
ManagementObject mo = new ManagementObject();
|
|
|
|
// Already UNC, we are done here
|
|
if (pPath.StartsWith(@"\\")) { return pPath; }
|
|
|
|
// Get just the drive letter for WMI call
|
|
string driveletter = GetDriveLetter(pPath);
|
|
|
|
mo.Path = new ManagementPath(string.Format("Win32_LogicalDisk='{0}'", driveletter));
|
|
|
|
// Get the data we need
|
|
uint DriveType = System.Convert.ToUInt32(mo["DriveType"]);
|
|
string NetworkRoot = System.Convert.ToString(mo["ProviderName"]);
|
|
mo = null;
|
|
|
|
// Return the root UNC path if network drive, otherwise return the root path to the local drive
|
|
if (DriveType == 4)
|
|
{
|
|
return NetworkRoot + pPath.Substring(2);
|
|
}
|
|
else
|
|
{
|
|
return driveletter + pPath.Substring(2);
|
|
}
|
|
}
|
|
|
|
/// <summary>Checks if the given path is on a network drive.</summary>
|
|
/// <param name="pPath"></param>
|
|
/// <returns></returns>
|
|
public static bool isNetworkDrive(string pPath)
|
|
{
|
|
ManagementObject mo = new ManagementObject();
|
|
|
|
if (pPath.StartsWith(@"\\")) { return true; }
|
|
|
|
// Get just the drive letter for WMI call
|
|
string driveletter = GetDriveLetter(pPath);
|
|
|
|
mo.Path = new ManagementPath(string.Format("Win32_LogicalDisk='{0}'", driveletter));
|
|
|
|
// Get the data we need
|
|
uint DriveType = System.Convert.ToUInt32(mo["DriveType"]);
|
|
mo = null;
|
|
|
|
return DriveType == 4;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private Helpers
|
|
|
|
/// <summary>Given a path will extract just the drive letter with volume separator.</summary>
|
|
/// <param name="pPath"></param>
|
|
/// <returns>C:</returns>
|
|
private static string GetDriveLetter(string pPath)
|
|
{
|
|
if (pPath.StartsWith(@"\\")) { throw new ArgumentException("A UNC path was passed to GetDriveLetter"); }
|
|
return Directory.GetDirectoryRoot(pPath).Replace(Path.DirectorySeparatorChar.ToString(), "");
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|