using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.Serialization; using System.Security.Principal; using Vanara.Security; using static Vanara.PInvoke.NetApi32; namespace Vanara { /// Represents a single connected (authenticated) computer. /// /// /// [Serializable, DefaultProperty(nameof(Target))] public class Computer : Component, ISupportInitialize, ISerializable { /// The local computer connected by the current account. public static readonly Computer Local = new Computer(); private SharedDevices devices; private bool initializing; private NetworkDeviceConnectionCollection networkConnections; private string targetServer; private bool targetServerSet; private string userName; private bool userNameSet; private string userPassword; private bool userPasswordSet; /// Initializes a new instance of the class connecting to the local machine as the current user. public Computer() => Connect(); /// Initializes a new instance of the class. /// /// The name of the computer that you want to connect to. If the this parameter is , then this will connect to /// the local computer. /// /// /// The user name that is used during the connection to the computer. If the user is not specified, then the current user is used. /// /// /// The password that is used to connect to the computer. If the user name and password are not specified, then the current token is used. /// public Computer(string target, string userName = null, string password = null) { BeginInit(); Target = target; UserName = userName; UserPassword = password; EndInit(); } private Computer(SerializationInfo info, StreamingContext context) { BeginInit(); Target = (string)info.GetValue(nameof(Target), typeof(string)); UserName = (string)info.GetValue(nameof(UserName), typeof(string)); UserPassword = (string)info.GetValue(nameof(UserPassword), typeof(string)); EndInit(); } //public IEnumerable LocalUsers => LocalUser.GetEnum(Target, UserName, UserPassword); //public IEnumerable LocalGroups => LocalGroup.GetEnum(Target, UserName, UserPassword); /// Gets the remote resource collection for this computer. /// The remote resources. [Browsable(false)] public NetworkDeviceConnectionCollection NetworkDeviceConnections => targetServer is null ? networkConnections ??= new NetworkDeviceConnectionCollection(Identity, null) : throw new InvalidOperationException("Network connection information is only available for the local computer."); /// Gets the open files associated with this device. /// Returns a value. [Browsable(false)] public IEnumerable OpenFiles => Identity.Run(() => NetFileEnum(Target).Select(i => new OpenFile(i))); /// Gets the shared devices defined for this computer. /// Returns a value. [Browsable(false)] public SharedDevices SharedDevices => devices ??= new SharedDevices(this); /// Gets or sets the name of the computer that the user is connected to. [Category("Data"), DefaultValue(null), Description("The name of the computer to connect to.")] public string Target { get => ShouldSerializeTargetServer() ? targetServer : null; set { if (value == null || value.Trim() == string.Empty) value = null; if (string.Compare(value, targetServer, StringComparison.OrdinalIgnoreCase) != 0) { targetServerSet = true; targetServer = value; Connect(); } } } /// Gets or sets the user name to be used when connecting to the . /// The user name. [Category("Data"), DefaultValue(null), Description("The user name to be used when connecting.")] public string UserName { get => ShouldSerializeUserName() ? userName : null; set { if (value == null || value.Trim() == string.Empty) value = null; if (string.Compare(value, userName, StringComparison.OrdinalIgnoreCase) != 0) { userNameSet = true; userName = value; Connect(); } } } /// Gets or sets the user password to be used when connecting to the . /// The user password. [Category("Data"), DefaultValue(null), Description("The user password to be used when connecting.")] public string UserPassword { get => userPassword; set { if (value == null || value.Trim() == string.Empty) value = null; if (string.CompareOrdinal(value, userPassword) != 0) { userPasswordSet = true; userPassword = value; Connect(); } } } internal WindowsIdentity Identity { get { if (UserName is null) return null; var nonUpnIdx = UserName.IndexOf('\\'); var un = UserName; string dn = null; if (nonUpnIdx >= 0) { dn = UserName.Substring(0, nonUpnIdx); un = UserName.Substring(nonUpnIdx + 1); } return new Security.Principal.WindowsLoggedInIdentity(un, dn, UserPassword).AuthenticatedIdentity; } } /// Signals the object that initialization is starting. public void BeginInit() => initializing = true; /// Signals the object that initialization is complete. public void EndInit() { initializing = false; Connect(); } void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue(nameof(Target), Target, typeof(string)); info.AddValue(nameof(UserName), UserName, typeof(string)); info.AddValue(nameof(UserPassword), UserPassword, typeof(string)); } private void Connect() { ResetUnsetProperties(); if (!initializing && !DesignMode) { // Clear stuff if already connected Dispose(true); if (!string.IsNullOrEmpty(targetServer)) { // Check to ensure character only server name. (Suggested by bigsan) if (targetServer.StartsWith(@"\")) targetServer = targetServer.TrimStart('\\'); // Make sure null is provided for local machine to compensate for a native library oddity (Found by ctrollen) if (targetServer.Equals(Environment.MachineName, StringComparison.CurrentCultureIgnoreCase)) targetServer = null; } else targetServer = null; } } private void ResetUnsetProperties() { if (!targetServerSet) targetServer = null; if (!userNameSet) userName = null; if (!userPasswordSet) userPassword = null; } private bool ShouldSerializeTargetServer() => targetServer != null && !targetServer.Trim('\\').Equals(Environment.MachineName.Trim('\\'), StringComparison.InvariantCultureIgnoreCase); private bool ShouldSerializeUserName() => userName != null && !userName.Equals(Environment.UserName, StringComparison.InvariantCultureIgnoreCase); } }