Certificate/wireless plugins; major refactoring
Migrate much of BI to Services. Added Wireless Profile Provider plugin feature. Added Certificate Authority Provider plugin feature. Modified Certificate Provider plugin feature. Database migration v17, for Device Profiles. Enrolment Client Updated to support CA Certificates, Wireless Profiles and Hardware Info. New Client Enrolment Protocol to support new features. Plugin Manifest Generator added to main solution. Improved AD search performance.
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
<AssemblyVersion>2.2.16272.1003</AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
@@ -65,6 +66,42 @@
|
||||
<Compile Include="..\Disco.Models\ClientServices\Enrol.cs">
|
||||
<Link>Models\ClientServices\Enrol.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\Certificate.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\Certificate.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\CertificateStore.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\CertificateStore.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\DeviceHardware.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\DeviceHardware.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\DiskDrive.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\DiskDrive.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\DiskDrivePartition.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\DiskDrivePartition.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\DiskLogical.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\DiskLogical.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\NetworkAdapter.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\NetworkAdapter.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\PhysicalMemory.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\PhysicalMemory.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\Processor.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\Processor.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\WirelessProfile.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\WirelessProfile.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\WirelessProfileStore.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\WirelessProfileStore.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolmentInformation\WirelessProfileTransformation.cs">
|
||||
<Link>Models\ClientServices\EnrolmentInformation\WirelessProfileTransformation.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Disco.Models\ClientServices\EnrolResponse.cs">
|
||||
<Link>Models\ClientServices\EnrolResponse.cs</Link>
|
||||
</Compile>
|
||||
@@ -92,10 +129,19 @@
|
||||
<Compile Include="Extensions\EnrolExtensions.cs" />
|
||||
<Compile Include="Extensions\WhoAmIExtensions.cs" />
|
||||
<Compile Include="Interop\Certificates.cs" />
|
||||
<Compile Include="Interop\Hardware.cs" />
|
||||
<Compile Include="Interop\LocalAuthentication.cs" />
|
||||
<Compile Include="Interop\Native\NetworkConnectionStatuses.cs" />
|
||||
<Compile Include="Interop\Native\ProfileInfoFlags.cs" />
|
||||
<Compile Include="Interop\Native\WlanApi.cs" />
|
||||
<Compile Include="Interop\Native\WLAN_INTERFACE_INFO.cs" />
|
||||
<Compile Include="Interop\Native\WLAN_INTERFACE_INFO_LIST.cs" />
|
||||
<Compile Include="Interop\Native\WLAN_INTERFACE_STATE.cs" />
|
||||
<Compile Include="Interop\Native\WLAN_PROFILE_INFO.cs" />
|
||||
<Compile Include="Interop\Native\WLAN_PROFILE_INFO_LIST.cs" />
|
||||
<Compile Include="Interop\Network.cs" />
|
||||
<Compile Include="Interop\WirelessNetwork.cs" />
|
||||
<Compile Include="Presentation.cs" />
|
||||
<Compile Include="Interop\SystemAudit.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace Disco.Client
|
||||
string reportResponse;
|
||||
|
||||
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(ServicePathTemplate);
|
||||
request.UserAgent = string.Format("Disco-Client/{0}", Assembly.GetExecutingAssembly().GetName().Version.ToString(3));
|
||||
request.UserAgent = $"Disco-Client/{Assembly.GetExecutingAssembly().GetName().Version.ToString(3)}";
|
||||
request.ContentType = "application/json";
|
||||
request.Method = WebRequestMethods.Http.Post;
|
||||
request.UseDefaultCredentials = true;
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.Client.Extensions
|
||||
{
|
||||
|
||||
@@ -1,55 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Disco.Models.ClientServices;
|
||||
using Newtonsoft.Json;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Disco.Models.ClientServices;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Disco.Client.Extensions
|
||||
{
|
||||
public static class ClientServicesExtensions
|
||||
{
|
||||
#if DEBUG
|
||||
public const string ServicePathAuthenticatedTemplate = "http://WS-GSHARP:57252/Services/Client/Authenticated/{0}";
|
||||
public const string ServicePathUnauthenticatedTemplate = "http://WS-GSHARP:57252/Services/Client/Unauthenticated/{0}";
|
||||
#else
|
||||
public const string ServicePathAuthenticatedTemplate = "http://DISCO:9292/Services/Client/Authenticated/{0}";
|
||||
public const string ServicePathUnauthenticatedTemplate = "http://DISCO:9292/Services/Client/Unauthenticated/{0}";
|
||||
#endif
|
||||
|
||||
public static ResponseType Post<ResponseType>(this ServiceBase<ResponseType> Service, bool Authenticated)
|
||||
{
|
||||
string jsonResponse;
|
||||
ResponseType serviceResponse;
|
||||
string serviceUrl;
|
||||
|
||||
if (Authenticated)
|
||||
serviceUrl = string.Format(ServicePathAuthenticatedTemplate, Service.Feature);
|
||||
else
|
||||
serviceUrl = string.Format(ServicePathUnauthenticatedTemplate, Service.Feature);
|
||||
|
||||
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceUrl);
|
||||
request.UserAgent = string.Format("Disco-Client/{0}", Assembly.GetExecutingAssembly().GetName().Version.ToString(3));
|
||||
request.UserAgent = $"Disco-Client/{Assembly.GetExecutingAssembly().GetName().Version.ToString(3)}";
|
||||
request.ContentType = "application/json";
|
||||
request.Method = WebRequestMethods.Http.Post;
|
||||
request.UseDefaultCredentials = true;
|
||||
request.Timeout = 300000; // 5 Minutes
|
||||
string jsonRequest = JsonConvert.SerializeObject(Service);
|
||||
|
||||
using (StreamWriter requestWriter = new StreamWriter(request.GetRequestStream()))
|
||||
var jsonSerializer = new JsonSerializer();
|
||||
|
||||
using (var requestWriter = new StreamWriter(request.GetRequestStream()))
|
||||
{
|
||||
requestWriter.Write(jsonRequest);
|
||||
using (var jsonWriter = new JsonTextWriter(requestWriter))
|
||||
{
|
||||
jsonSerializer.Serialize(jsonWriter, Service);
|
||||
}
|
||||
}
|
||||
|
||||
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
||||
{
|
||||
using (StreamReader responseReader = new StreamReader(response.GetResponseStream()))
|
||||
using (var responseReader = new StreamReader(response.GetResponseStream()))
|
||||
{
|
||||
jsonResponse = responseReader.ReadToEnd();
|
||||
using (var jsonReader = new JsonTextReader(responseReader))
|
||||
{
|
||||
serviceResponse = jsonSerializer.Deserialize<ResponseType>(jsonReader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(jsonResponse))
|
||||
return default(ResponseType);
|
||||
else
|
||||
return JsonConvert.DeserializeObject<ResponseType>(jsonResponse);
|
||||
return serviceResponse;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Client.Interop;
|
||||
using Disco.Models.ClientServices;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Win32;
|
||||
using System.Text.RegularExpressions;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace Disco.Client.Extensions
|
||||
{
|
||||
@@ -16,26 +12,23 @@ namespace Disco.Client.Extensions
|
||||
|
||||
public static void Build(this Enrol enrol)
|
||||
{
|
||||
enrol.DeviceUUID = Interop.SystemAudit.DeviceUUID;
|
||||
enrol.DeviceSerialNumber = Interop.SystemAudit.DeviceSerialNumber;
|
||||
enrol.ComputerName = Environment.MachineName;
|
||||
enrol.RunningUserDomain = Environment.UserDomainName;
|
||||
enrol.RunningUserName = Environment.UserName;
|
||||
enrol.RunningInteractively = Environment.UserInteractive;
|
||||
|
||||
enrol.DeviceComputerName = Interop.LocalAuthentication.ComputerName;
|
||||
// Hardware Audit
|
||||
enrol.Hardware = Hardware.Information;
|
||||
enrol.SerialNumber = enrol.Hardware.SerialNumber;
|
||||
|
||||
enrol.DeviceManufacturer = Interop.SystemAudit.DeviceManufacturer;
|
||||
enrol.DeviceModel = Interop.SystemAudit.DeviceModel;
|
||||
enrol.DeviceModelType = Interop.SystemAudit.DeviceType;
|
||||
|
||||
enrol.DeviceIsPartOfDomain = Interop.SystemAudit.DeviceIsPartOfDomain;
|
||||
enrol.DeviceDNSDomainName = Interop.SystemAudit.DeviceDNSDomainName;
|
||||
|
||||
// LAN
|
||||
enrol.DeviceLanMacAddress = Interop.Network.PrimaryLanMacAddress;
|
||||
|
||||
// WAN
|
||||
enrol.DeviceWlanMacAddress = Interop.Network.PrimaryWlanMacAddress;
|
||||
// Apply System Information
|
||||
enrol.ApplySystemInformation();
|
||||
|
||||
// Certificates
|
||||
enrol.DeviceCertificates = Interop.Certificates.GetCertificateSubjects(StoreName.My, StoreLocation.LocalMachine);
|
||||
enrol.Certificates = Certificates.GetAllCertificates();
|
||||
|
||||
// Wireless Profiles
|
||||
enrol.WirelessProfiles = WirelessNetwork.GetWirelessProfiles();
|
||||
}
|
||||
|
||||
public static void Process(this EnrolResponse enrolResponse)
|
||||
@@ -51,12 +44,14 @@ namespace Disco.Client.Extensions
|
||||
// Offline Domain Join
|
||||
bool requireReboot = enrolResponse.ApplyOfflineDomainJoin();
|
||||
|
||||
// Certificates
|
||||
enrolResponse.ApplyDeviceCertificates();
|
||||
|
||||
// Device Owner
|
||||
enrolResponse.ApplyDeviceAssignedUser();
|
||||
|
||||
// Certificates
|
||||
enrolResponse.ApplyDeviceCertificates();
|
||||
|
||||
// Wireless Profiles
|
||||
enrolResponse.ApplyWirelessProfiles();
|
||||
|
||||
Presentation.UpdateStatus("Enrolling Device", "Device Enrolment Successfully Completed", false, 0, 1500);
|
||||
|
||||
@@ -71,15 +66,15 @@ namespace Disco.Client.Extensions
|
||||
/// <returns>Boolean indicating whether a reboot is required.</returns>
|
||||
private static bool ApplyOfflineDomainJoin(this EnrolResponse enrolResponse)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(enrolResponse.OfflineDomainJoin))
|
||||
if (!string.IsNullOrWhiteSpace(enrolResponse.OfflineDomainJoinManifest))
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", string.Format("Performing Offline Domain Join:{0}Renaming Computer: {1} -> {2}", Environment.NewLine, Interop.LocalAuthentication.ComputerName, enrolResponse.DeviceComputerName), true, -1, 1500);
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Performing Offline Domain Join:\r\nRenaming Computer: {Environment.MachineName} -> {enrolResponse.ComputerName}", true, -1, 1500);
|
||||
|
||||
string odjFile = Path.GetTempFileName();
|
||||
File.WriteAllBytes(odjFile, Convert.FromBase64String(enrolResponse.OfflineDomainJoin));
|
||||
File.WriteAllBytes(odjFile, Convert.FromBase64String(enrolResponse.OfflineDomainJoinManifest));
|
||||
|
||||
string odjWindowsPath = Environment.GetEnvironmentVariable("SystemRoot");
|
||||
string odjProcessArguments = string.Format("/REQUESTODJ /LOADFILE \"{0}\" /WINDOWSPATH \"{1}\" /LOCALOS", odjFile, odjWindowsPath);
|
||||
string odjProcessArguments = $"/REQUESTODJ /LOADFILE \"{odjFile}\" /WINDOWSPATH \"{odjWindowsPath}\" /LOCALOS";
|
||||
|
||||
ProcessStartInfo odjProcessStartInfo = new ProcessStartInfo("DJOIN.EXE", odjProcessArguments)
|
||||
{
|
||||
@@ -95,17 +90,17 @@ namespace Disco.Client.Extensions
|
||||
odjResult = odjProcess.StandardOutput.ReadToEnd();
|
||||
odjProcess.WaitForExit(20000); // 20 Seconds
|
||||
}
|
||||
Presentation.UpdateStatus("Enrolling Device", string.Format("Offline Domain Join Result:{0}{1}", Environment.NewLine, odjResult), true, -1, 3000);
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Offline Domain Join Result:\r\n{odjResult}", true, -1, 3000);
|
||||
|
||||
if (File.Exists(odjFile))
|
||||
File.Delete(odjFile);
|
||||
|
||||
// Flush Logged-On History
|
||||
if (!string.IsNullOrEmpty(enrolResponse.DeviceDomainName))
|
||||
if (!string.IsNullOrEmpty(enrolResponse.DomainName))
|
||||
{
|
||||
using (RegistryKey regWinlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true))
|
||||
{
|
||||
regWinlogon.SetValue("DefaultDomainName", enrolResponse.DeviceDomainName, RegistryValueKind.String);
|
||||
regWinlogon.SetValue("DefaultDomainName", enrolResponse.DomainName, RegistryValueKind.String);
|
||||
regWinlogon.SetValue("DefaultUserName", String.Empty, RegistryValueKind.String);
|
||||
}
|
||||
using (RegistryKey regLogonUI = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI", true))
|
||||
@@ -130,62 +125,44 @@ namespace Disco.Client.Extensions
|
||||
private static void ApplyDeviceAssignedUser(this EnrolResponse enrolResponse)
|
||||
{
|
||||
// Only run task if Assigned User was specified
|
||||
if (!string.IsNullOrWhiteSpace(enrolResponse.DeviceAssignedUserSID))
|
||||
if (!string.IsNullOrWhiteSpace(enrolResponse.AssignedUserSID))
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", string.Format(@"Configuring the device owner:{0}{1} ({2}\{3})", Environment.NewLine, enrolResponse.DeviceAssignedUserName, enrolResponse.DeviceAssignedUserDomain, enrolResponse.DeviceAssignedUserUsername), true, -1, 3000);
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring the device owner:\r\n{enrolResponse.AssignedUserDescription} ({enrolResponse.AssignedUserDomain}\\{enrolResponse.AssignedUserUsername})", true, -1, 3000);
|
||||
|
||||
if (enrolResponse.DeviceAssignedUserIsLocalAdmin)
|
||||
Interop.LocalAuthentication.AddLocalGroupMembership("Administrators", enrolResponse.DeviceAssignedUserSID, enrolResponse.DeviceAssignedUserUsername, enrolResponse.DeviceAssignedUserDomain);
|
||||
if (enrolResponse.AssignedUserIsLocalAdmin)
|
||||
Interop.LocalAuthentication.AddLocalGroupMembership("Administrators", enrolResponse.AssignedUserSID, enrolResponse.AssignedUserUsername, enrolResponse.AssignedUserDomain);
|
||||
|
||||
// Make Windows think this user was the last to logon
|
||||
using (RegistryKey regWinlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true))
|
||||
{
|
||||
regWinlogon.SetValue("DefaultDomainName", enrolResponse.DeviceAssignedUserDomain, RegistryValueKind.String);
|
||||
regWinlogon.SetValue("DefaultUserName", enrolResponse.DeviceAssignedUserUsername, RegistryValueKind.String);
|
||||
regWinlogon.SetValue("DefaultDomainName", enrolResponse.AssignedUserDomain, RegistryValueKind.String);
|
||||
regWinlogon.SetValue("DefaultUserName", enrolResponse.AssignedUserUsername, RegistryValueKind.String);
|
||||
}
|
||||
using (RegistryKey regLogonUI = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI", true))
|
||||
{
|
||||
regLogonUI.SetValue("LastLoggedOnUser", string.Format(@"{0}\{1}", enrolResponse.DeviceAssignedUserDomain, enrolResponse.DeviceAssignedUserUsername), RegistryValueKind.String);
|
||||
regLogonUI.SetValue("LastLoggedOnUser", $@"{enrolResponse.AssignedUserDomain}\{enrolResponse.AssignedUserUsername}", RegistryValueKind.String);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes a Client Service Enrol Response for Device Certificate Actions
|
||||
/// </summary>
|
||||
/// <param name="enrolResponse"></param>
|
||||
private static void ApplyDeviceCertificates(this EnrolResponse enrolResponse)
|
||||
{
|
||||
// Only run if a Certificate was supplied
|
||||
if (!string.IsNullOrEmpty(enrolResponse.DeviceCertificate))
|
||||
if (enrolResponse.Certificates != null)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", "Configuring Wireless Certificates", true, -1, 1000);
|
||||
Presentation.UpdateStatus("Enrolling Device", "Configuring Certificates", true, -1, 1000);
|
||||
|
||||
var certPersonalBytes = Convert.FromBase64String(enrolResponse.DeviceCertificate);
|
||||
var certPersonal = new X509Certificate2(certPersonalBytes, "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
|
||||
if (certPersonal == null)
|
||||
throw new ClientServiceException("Enrolment > Device Certificate", "Unable to Import Device Certificate Provided, possibly check password.");
|
||||
|
||||
// Certificate Removal
|
||||
if (enrolResponse.DeviceCertificateRemoveExisting != null && enrolResponse.DeviceCertificateRemoveExisting.Count > 0)
|
||||
{
|
||||
List<Regex> regExMatchesSubject = new List<Regex>();
|
||||
foreach (var subjectRegEx in enrolResponse.DeviceCertificateRemoveExisting)
|
||||
regExMatchesSubject.Add(new Regex(subjectRegEx, RegexOptions.IgnoreCase));
|
||||
|
||||
// Remove from 'My' Store
|
||||
Interop.Certificates.RemoveCertificates(StoreName.My, StoreLocation.LocalMachine, regExMatchesSubject, certPersonal);
|
||||
// Remove from 'Root' Store
|
||||
Interop.Certificates.RemoveCertificates(StoreName.Root, StoreLocation.LocalMachine, regExMatchesSubject, certPersonal);
|
||||
// Remove from 'CertificateAuthority' Store
|
||||
Interop.Certificates.RemoveCertificates(StoreName.CertificateAuthority, StoreLocation.LocalMachine, regExMatchesSubject, certPersonal);
|
||||
}
|
||||
|
||||
// Add Certificate
|
||||
Presentation.UpdateStatus("Enrolling Device", string.Format("Configuring Wireless Certificates{0}Installing Certificate: {1}", Environment.NewLine, Interop.Certificates.GetCertificateFriendlyName(certPersonal)), true, -1);
|
||||
Interop.Certificates.AddCertificate(StoreName.My, StoreLocation.LocalMachine, certPersonal);
|
||||
enrolResponse.Certificates.Apply();
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyWirelessProfiles(this EnrolResponse enrolResponse)
|
||||
{
|
||||
if (enrolResponse.WirelessProfiles != null)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", "Configuring Wireless Profiles", true, -1, 1000);
|
||||
|
||||
enrolResponse.WirelessProfiles.Apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,103 +1,130 @@
|
||||
using System;
|
||||
using Disco.Models.ClientServices.EnrolmentInformation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Disco.Client.Interop
|
||||
{
|
||||
public static class Certificates
|
||||
{
|
||||
|
||||
public static string GetCertificateFriendlyName(X509Certificate2 Certificate)
|
||||
public static List<Certificate> GetAllCertificates()
|
||||
{
|
||||
string subject = Certificate.Subject;
|
||||
return subject.Substring(subject.IndexOf("=") + 1, subject.IndexOf(",") - subject.IndexOf("=") - 1);
|
||||
var certificates = new List<Certificate>();
|
||||
|
||||
// Trusted Root Certificates
|
||||
certificates.AddRange(GetCertificates(StoreName.Root, "TrustedRoot"));
|
||||
|
||||
// Intermediate Certificates
|
||||
certificates.AddRange(GetCertificates(StoreName.CertificateAuthority, "Intermediate"));
|
||||
|
||||
// Personal Certificates
|
||||
certificates.AddRange(GetCertificates(StoreName.My, "Personal"));
|
||||
|
||||
return certificates;
|
||||
}
|
||||
|
||||
public static List<string> GetCertificateSubjects(StoreName StoreName, StoreLocation StoreLocation)
|
||||
private static IEnumerable<Certificate> GetCertificates(StoreName StoreName, string StoreDescription)
|
||||
{
|
||||
X509Store certStore = new X509Store(StoreName, StoreLocation);
|
||||
certStore.Open(OpenFlags.ReadOnly);
|
||||
var certSubjects = certStore.Certificates.Cast<X509Certificate2>().Select(c => c.Subject).ToList();
|
||||
certStore.Close();
|
||||
return certSubjects;
|
||||
}
|
||||
|
||||
public static bool AddCertificate(StoreName StoreName, StoreLocation StoreLocation, X509Certificate2 Certificate)
|
||||
{
|
||||
X509Store certStore = new X509Store(StoreName, StoreLocation);
|
||||
bool certAlreadyAdded = false;
|
||||
|
||||
certStore.Open(OpenFlags.ReadWrite);
|
||||
|
||||
var store = new X509Store(StoreName, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.ReadOnly);
|
||||
try
|
||||
{
|
||||
foreach (X509Certificate2 cert in certStore.Certificates)
|
||||
foreach (var certificate in store.Certificates)
|
||||
{
|
||||
if (cert.SerialNumber.Equals(Certificate.SerialNumber))
|
||||
yield return new Certificate()
|
||||
{
|
||||
certAlreadyAdded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!certAlreadyAdded)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", string.Format("Configuring Wireless Certificates{0}Adding Certificate: '{1}' from {2}@{3}", Environment.NewLine, GetCertificateFriendlyName(Certificate), StoreName.ToString(), StoreLocation.ToString()), true, -1, 3000);
|
||||
certStore.Add(Certificate);
|
||||
Store = StoreDescription,
|
||||
SubjectName = certificate.SubjectName.Name,
|
||||
Thumbprint = certificate.Thumbprint,
|
||||
FriendlyName = certificate.FriendlyName,
|
||||
DnsName = certificate.GetNameInfo(X509NameType.DnsName, false),
|
||||
Version = certificate.Version,
|
||||
SignatureAlgorithm = certificate.SignatureAlgorithm.FriendlyName,
|
||||
Issuer = certificate.IssuerName.Name,
|
||||
NotAfter = certificate.NotAfter,
|
||||
NotBefore = certificate.NotBefore,
|
||||
HasPrivateKey = certificate.HasPrivateKey
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (Exception) { throw; }
|
||||
finally
|
||||
{
|
||||
certStore.Close();
|
||||
store.Close();
|
||||
}
|
||||
|
||||
return !certAlreadyAdded;
|
||||
}
|
||||
|
||||
public static List<string> RemoveCertificates(StoreName StoreName, StoreLocation StoreLocation, List<Regex> RegExMatchesSubject, X509Certificate2 CertificateException)
|
||||
public static void Apply(this CertificateStore EnrolStore)
|
||||
{
|
||||
X509Store certStore = new X509Store(StoreName, StoreLocation);
|
||||
List<string> results = new List<string>();
|
||||
List<X509Certificate2> certStoreRemove = new List<X509Certificate2>();
|
||||
|
||||
certStore.Open(OpenFlags.ReadWrite);
|
||||
|
||||
try
|
||||
if (EnrolStore != null)
|
||||
{
|
||||
foreach (X509Certificate2 cert in certStore.Certificates)
|
||||
// Apply Trusted Root
|
||||
ApplyToStore(StoreName.Root, EnrolStore.TrustedRootCertificates, EnrolStore.TrustedRootRemoveThumbprints);
|
||||
|
||||
// Apply Intermediate
|
||||
ApplyToStore(StoreName.CertificateAuthority, EnrolStore.IntermediateCertificates, EnrolStore.IntermediateRemoveThumbprints);
|
||||
|
||||
// Apply Personal
|
||||
ApplyToStore(StoreName.My, EnrolStore.PersonalCertificates, EnrolStore.PersonalRemoveThumbprints);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyToStore(StoreName StoreName, List<byte[]> Certificates, List<string> RemoveThumbprints)
|
||||
{
|
||||
|
||||
if ((Certificates != null && Certificates.Count > 0) ||
|
||||
(RemoveThumbprints != null && RemoveThumbprints.Count > 0))
|
||||
{
|
||||
var store = new X509Store(StoreName, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.ReadWrite);
|
||||
try
|
||||
{
|
||||
if (!cert.SerialNumber.Equals(CertificateException.SerialNumber))
|
||||
var addedThumbprints = new List<string>();
|
||||
var existingThumbprints = store.Certificates.Cast<X509Certificate2>().GroupBy(c => c.Thumbprint).ToDictionary(c => c.Key, c => c.ToList(), StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// Add
|
||||
if (Certificates != null && Certificates.Count > 0)
|
||||
{
|
||||
foreach (var subjectRegEx in RegExMatchesSubject)
|
||||
foreach (var certificateBytes in Certificates)
|
||||
{
|
||||
if (subjectRegEx.IsMatch(cert.Subject))
|
||||
var certificate = new X509Certificate2(certificateBytes, "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
|
||||
|
||||
// check if it already exists
|
||||
if (!existingThumbprints.ContainsKey(certificate.Thumbprint) && !addedThumbprints.Contains(certificate.Thumbprint))
|
||||
{
|
||||
certStoreRemove.Add(cert);
|
||||
break;
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Certificates\r\nAdding Certificate: '{certificate.GetNameInfo(X509NameType.DnsName, false)}' from {store.Name}@{store.Location}", true, -1, 1000);
|
||||
store.Add(certificate);
|
||||
addedThumbprints.Add(certificate.Thumbprint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove
|
||||
if (RemoveThumbprints != null && RemoveThumbprints.Count > 0)
|
||||
{
|
||||
foreach (var thumbprint in RemoveThumbprints)
|
||||
{
|
||||
List<X509Certificate2> certificates;
|
||||
if (existingThumbprints.TryGetValue(thumbprint, out certificates) && !addedThumbprints.Contains(thumbprint))
|
||||
{
|
||||
foreach (var certificate in certificates)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Certificates\r\nRemoving Certificate: '{certificate.GetNameInfo(X509NameType.DnsName, false)}' from {store.Name}@{store.Location}", true, -1, 1000);
|
||||
store.Remove(certificate);
|
||||
existingThumbprints.Remove(thumbprint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var cert in certStoreRemove)
|
||||
finally
|
||||
{
|
||||
results.Add(cert.Subject);
|
||||
|
||||
Presentation.UpdateStatus("Enrolling Device", string.Format("Configuring Wireless Certificates{0}Removing Certificate: '{1}' from {2}@{3}", Environment.NewLine, GetCertificateFriendlyName(cert), StoreName.ToString(), StoreLocation.ToString()), true, -1, 1500);
|
||||
certStore.Remove(cert);
|
||||
store.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception) { throw; }
|
||||
finally
|
||||
{
|
||||
certStore.Close();
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
using Disco.Models.ClientServices;
|
||||
using Disco.Models.ClientServices.EnrolmentInformation;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
|
||||
namespace Disco.Client.Interop
|
||||
{
|
||||
public static class Hardware
|
||||
{
|
||||
private static DeviceHardware information;
|
||||
|
||||
public static DeviceHardware Information
|
||||
{
|
||||
get
|
||||
{
|
||||
if (information == null)
|
||||
{
|
||||
information = GatherInformation();
|
||||
}
|
||||
return information;
|
||||
}
|
||||
}
|
||||
|
||||
private static DeviceHardware GatherInformation()
|
||||
{
|
||||
var audit = new DeviceHardware();
|
||||
|
||||
audit.ApplyBIOSInformation();
|
||||
audit.ApplySystemInformation();
|
||||
audit.ApplyBaseBoardInformation();
|
||||
audit.ApplySystemProductInformation();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(audit.SerialNumber))
|
||||
{
|
||||
throw new Exception("This device has no serial number stored in BIOS or BaseBoard");
|
||||
}
|
||||
if (audit.SerialNumber.Length > 60)
|
||||
{
|
||||
throw new Exception($"The serial number reported by this device is over 60 characters long:\r\n{audit.SerialNumber}");
|
||||
}
|
||||
|
||||
#warning TODO: Processors, PhysicalMemory, DiskDrives, etc
|
||||
|
||||
audit.NetworkAdapters = Network.GetNetworkAdapters();
|
||||
|
||||
return audit;
|
||||
}
|
||||
|
||||
private static void ApplyBIOSInformation(this DeviceHardware DeviceHardware)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT SerialNumber, SMBIOSBIOSVersion FROM Win32_BIOS WHERE PrimaryBios=true"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
var serialNumber = (string)mItem.GetPropertyValue("SerialNumber");
|
||||
if (!string.IsNullOrWhiteSpace(serialNumber))
|
||||
{
|
||||
DeviceHardware.SerialNumber = serialNumber.Trim();
|
||||
}
|
||||
|
||||
ErrorReporting.DeviceIdentifier = DeviceHardware.SerialNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_BIOS WHERE PrimaryBios=true was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco Client was unable to retrieve BIOS information from WMI", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplySystemInformation(this DeviceHardware DeviceHardware)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT Manufacturer, Model, PartOfDomain, PCSystemType, Domain FROM Win32_ComputerSystem"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
var manufacturer = (string)mItem.GetPropertyValue("Manufacturer");
|
||||
if (!string.IsNullOrWhiteSpace(manufacturer))
|
||||
{
|
||||
DeviceHardware.Manufacturer = manufacturer.Trim();
|
||||
}
|
||||
|
||||
var model = (string)mItem.GetPropertyValue("Model");
|
||||
if (!string.IsNullOrWhiteSpace(model))
|
||||
{
|
||||
DeviceHardware.Model = model.ToString();
|
||||
}
|
||||
|
||||
DeviceHardware.ModelType = ((PCSystemTypes)mItem.GetPropertyValue("PCSystemType")).Description();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_ComputerSystem was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco Client was unable to retrieve ComputerSystem information from WMI", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ApplySystemInformation(this Enrol Enrol)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT PartOfDomain, Domain FROM Win32_ComputerSystem"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
Enrol.IsPartOfDomain = (bool)mItem.GetPropertyValue("PartOfDomain");
|
||||
|
||||
if (Enrol.IsPartOfDomain)
|
||||
{
|
||||
Enrol.DNSDomainName = (string)mItem.GetPropertyValue("Domain");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_ComputerSystem was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco Client was unable to retrieve ComputerSystem information from WMI", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyBaseBoardInformation(this DeviceHardware DeviceHardware)
|
||||
{
|
||||
// Added 2012-11-22 G# - Lenovo IdeaPad Serial SHIM
|
||||
// http://www.discoict.com.au/forum/feature-requests/2012/11/serial-number-detection-on-ideapads.aspx
|
||||
if (string.IsNullOrWhiteSpace(DeviceHardware.SerialNumber) ||
|
||||
(DeviceHardware.Manufacturer.Equals("LENOVO", StringComparison.OrdinalIgnoreCase) &&
|
||||
(DeviceHardware.Model.Equals("S10-3", StringComparison.OrdinalIgnoreCase) // S10-3
|
||||
|| DeviceHardware.Model.Equals("2957", StringComparison.OrdinalIgnoreCase)))) // S10-2
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
var serialNumber = (string)mItem.GetPropertyValue("SerialNumber");
|
||||
if (!string.IsNullOrWhiteSpace(serialNumber))
|
||||
{
|
||||
DeviceHardware.SerialNumber = serialNumber.Trim();
|
||||
ErrorReporting.DeviceIdentifier = DeviceHardware.SerialNumber;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_BaseBoard was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco Client was unable to retrieve BaseBoard information from WMI", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplySystemProductInformation(this DeviceHardware DeviceHardware)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT IdentifyingNumber, UUID FROM Win32_ComputerSystemProduct"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
if (DeviceHardware.SerialNumber == null)
|
||||
{
|
||||
var serialNumber = mItem.GetPropertyValue("IdentifyingNumber") as string;
|
||||
if (!string.IsNullOrWhiteSpace(serialNumber))
|
||||
{
|
||||
DeviceHardware.SerialNumber = serialNumber.Trim();
|
||||
ErrorReporting.DeviceIdentifier = DeviceHardware.SerialNumber;
|
||||
}
|
||||
}
|
||||
|
||||
var uUID = (string)mItem.GetPropertyValue("UUID");
|
||||
if (!string.IsNullOrWhiteSpace(uUID))
|
||||
DeviceHardware.UUID = uUID.Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_ComputerSystemProduct was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco Client was unable to retrieve ComputerSystemProduct information from WMI", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static string Description(this PCSystemTypes type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case PCSystemTypes.Desktop:
|
||||
return "Desktop";
|
||||
case PCSystemTypes.Mobile:
|
||||
return "Mobile";
|
||||
case PCSystemTypes.Workstation:
|
||||
return "Workstation";
|
||||
case PCSystemTypes.EnterpriseServer:
|
||||
return "Enterprise Server";
|
||||
case PCSystemTypes.SmallOfficeAndHomeOfficeServer:
|
||||
return "Small Office And Home Office Server";
|
||||
case PCSystemTypes.AppliancePC:
|
||||
return "Appliance PC";
|
||||
case PCSystemTypes.PerformanceServer:
|
||||
return "Performance Server";
|
||||
case PCSystemTypes.Maximum:
|
||||
return "Maximum";
|
||||
case PCSystemTypes.Unknown:
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
private enum PCSystemTypes : ushort
|
||||
{
|
||||
Unknown = 0,
|
||||
Desktop,
|
||||
Mobile,
|
||||
Workstation,
|
||||
EnterpriseServer,
|
||||
SmallOfficeAndHomeOfficeServer,
|
||||
AppliancePC,
|
||||
PerformanceServer,
|
||||
Maximum
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.DirectoryServices;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.Client.Interop
|
||||
{
|
||||
@@ -14,7 +10,7 @@ namespace Disco.Client.Interop
|
||||
public static bool AddLocalGroupMembership(string GroupName, string UserSID, string Username, string UserDomain)
|
||||
{
|
||||
|
||||
using (DirectoryEntry group = new DirectoryEntry(string.Format("WinNT://./{0},group", GroupName)))
|
||||
using (DirectoryEntry group = new DirectoryEntry($"WinNT://./{GroupName},group"))
|
||||
{
|
||||
// Check to see if the User is already a member
|
||||
foreach (object memberRef in (IEnumerable)group.Invoke("Members"))
|
||||
@@ -22,38 +18,15 @@ namespace Disco.Client.Interop
|
||||
using (DirectoryEntry member = new DirectoryEntry(memberRef))
|
||||
{
|
||||
var memberPath = member.Path;
|
||||
if (memberPath.Equals(string.Format("WinNT://{0}/{1}", UserDomain, Username), StringComparison.OrdinalIgnoreCase) ||
|
||||
memberPath.Equals(string.Format("WinNT://{0}", UserSID), StringComparison.OrdinalIgnoreCase))
|
||||
if (memberPath.Equals($"WinNT://{UserDomain}/{Username}", StringComparison.OrdinalIgnoreCase) ||
|
||||
memberPath.Equals($"WinNT://{UserSID}", StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
group.Invoke("Add", string.Format("WinNT://{0}", UserSID));
|
||||
group.Invoke("Add", $"WinNT://{UserSID}");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static string CurrentUserDomain
|
||||
{
|
||||
get
|
||||
{
|
||||
return Environment.UserDomainName;
|
||||
}
|
||||
}
|
||||
public static string CurrentUserName
|
||||
{
|
||||
get
|
||||
{
|
||||
return Environment.UserName;
|
||||
}
|
||||
}
|
||||
|
||||
public static string ComputerName
|
||||
{
|
||||
get
|
||||
{
|
||||
return Environment.MachineName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
public enum NetworkConnectionStatuses : ushort
|
||||
{
|
||||
Disconnected = 0,
|
||||
Connecting,
|
||||
Connected,
|
||||
Disconnecting,
|
||||
HardwareNotPresent,
|
||||
HardwareDisabled,
|
||||
HardwareMalfunction,
|
||||
MediaDisconnected,
|
||||
Authenticating,
|
||||
AuthenticationSucceeded,
|
||||
AuthenticationFailed,
|
||||
InvalidAddress,
|
||||
CredentialsRequired
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
[Flags]
|
||||
public enum ProfileInfoFlags : uint
|
||||
{
|
||||
WLAN_PROFILE_GROUP_POLICY = 1,
|
||||
WLAN_PROFILE_USER = 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
/// <summary >
|
||||
/// The WLAN_INTERFACE_INFO structure contains information about a wireless LAN interface.
|
||||
/// </summary >
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct WLAN_INTERFACE_INFO
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the GUID of the interface.
|
||||
/// </summary>
|
||||
public Guid InterfaceGuid;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the description of the interface.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string strInterfaceDescription;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a WLAN_INTERFACE_STATE value that indicates the current state of the interface.
|
||||
/// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2: Only the wlan_interface_state_connected,
|
||||
/// wlan_interface_state_disconnected, and wlan_interface_state_authenticating values are supported.
|
||||
/// </summary>
|
||||
public WLAN_INTERFACE_STATE isState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
/// <summary>
|
||||
/// The WLAN_INTERFACE_INFO_LIST structure contains an array of NIC interface information.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct WLAN_INTERFACE_INFO_LIST
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the number of items in the InterfaceInfo member.
|
||||
/// </summary>
|
||||
public uint dwNumberOfItems;
|
||||
/// <summary>
|
||||
/// The index of the current item. The index of the first item is 0. dwIndex must be less than dwNumberOfItems.
|
||||
/// This member is not used by the wireless service. Applications can use this member when processing individual
|
||||
/// interfaces in the WLAN_INTERFACE_INFO_LIST structure. When an application passes this structure from one
|
||||
/// function to another, it can set the value of dwIndex to the index of the item currently being processed.
|
||||
/// This can help an application maintain state.
|
||||
/// dwIndex should always be initialized before use.
|
||||
/// </summary>
|
||||
public uint dwIndex;
|
||||
|
||||
private IntPtr InterfaceInfoPtr;
|
||||
|
||||
/// <summary>
|
||||
/// An array of WLAN_INTERFACE_INFO structures containing interface information.
|
||||
/// </summary>
|
||||
public IEnumerable<WLAN_INTERFACE_INFO> InterfaceInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
var size = Marshal.SizeOf(typeof(WLAN_INTERFACE_INFO));
|
||||
for (int i = 0; i < dwNumberOfItems; i++)
|
||||
{
|
||||
yield return (WLAN_INTERFACE_INFO)Marshal.PtrToStructure(InterfaceInfoPtr + (i * size), typeof(WLAN_INTERFACE_INFO));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WLAN_INTERFACE_INFO_LIST(IntPtr Pointer)
|
||||
{
|
||||
dwNumberOfItems = (uint)Marshal.ReadInt32(Pointer, 0);
|
||||
dwIndex = (uint)Marshal.ReadInt32(Pointer, 4);
|
||||
InterfaceInfoPtr = Pointer + 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
/// <summary>
|
||||
/// The WLAN_INTERFACE_STATE enumerated type indicates the state of an interface.
|
||||
/// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2: Only the wlan_interface_state_connected,
|
||||
/// wlan_interface_state_disconnected, and wlan_interface_state_authenticating values are supported.
|
||||
/// </summary>
|
||||
public enum WLAN_INTERFACE_STATE
|
||||
{
|
||||
/// <summary>
|
||||
/// The interface is not ready to operate.
|
||||
/// </summary>
|
||||
wlan_interface_state_not_ready = 0,
|
||||
/// <summary>
|
||||
/// The interface is connected to a network.
|
||||
/// </summary>
|
||||
wlan_interface_state_connected = 1,
|
||||
/// <summary>
|
||||
/// The interface is the first node in an ad hoc network. No peer has connected.
|
||||
/// </summary>
|
||||
wlan_interface_state_ad_hoc_network_formed = 2,
|
||||
/// <summary>
|
||||
/// The interface is disconnecting from the current network.
|
||||
/// </summary>
|
||||
wlan_interface_state_disconnecting = 3,
|
||||
/// <summary>
|
||||
/// The interface is not connected to any network.
|
||||
/// </summary>
|
||||
wlan_interface_state_disconnected = 4,
|
||||
/// <summary>
|
||||
/// The interface is attempting to associate with a network.
|
||||
/// </summary>
|
||||
wlan_interface_state_associating = 5,
|
||||
/// <summary>
|
||||
/// Auto configuration is discovering the settings for the network.
|
||||
/// </summary>
|
||||
wlan_interface_state_discovering = 6,
|
||||
/// <summary>
|
||||
/// The interface is in the process of authenticating.
|
||||
/// </summary>
|
||||
wlan_interface_state_authenticating = 7,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct WLAN_PROFILE_INFO
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the profile. This value may be the name of a domain if the profile is for provisioning. Profile names are case-sensitive.
|
||||
/// This string must be NULL-terminated.
|
||||
/// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2: The name of the profile is derived automatically from
|
||||
/// the SSID of the wireless network. For infrastructure network profiles, the name of the profile is the SSID of the network.
|
||||
/// For ad hoc network profiles, the name of the profile is the SSID of the ad hoc network followed by -adhoc.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string strInterfaceDescription;
|
||||
|
||||
/// <summary>
|
||||
/// A set of flags specifying settings for wireless profile. These values are defined in the Wlanapi.h header file.
|
||||
/// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2: dwFlags must be 0. Per-user profiles are not supported.
|
||||
/// </summary>
|
||||
public ProfileInfoFlags dwFlags;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
public struct WLAN_PROFILE_INFO_LIST
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of wireless profile entries in the ProfileInfo member.
|
||||
/// </summary>
|
||||
public uint dwNumberOfItems;
|
||||
|
||||
/// <summary>
|
||||
/// The index of the current item. The index of the first item is 0. The dwIndex member must be less than the dwNumberOfItems member.
|
||||
/// This member is not used by the wireless service. Applications can use this member when processing individual profiles in the
|
||||
/// WLAN_PROFILE_INFO_LIST structure. When an application passes this structure from one function to another, it can set the value
|
||||
/// of dwIndex to the index of the item currently being processed. This can help an application maintain state.
|
||||
/// dwIndex should always be initialized before use.
|
||||
/// </summary>
|
||||
public uint dwIndex;
|
||||
|
||||
private IntPtr ProfileInfoPointer;
|
||||
|
||||
/// <summary>
|
||||
/// An array of WLAN_PROFILE_INFO structures containing interface information. The number of items in the array is specified in the dwNumberOfItems member.
|
||||
/// </summary>
|
||||
public IEnumerable<WLAN_PROFILE_INFO> ProfileInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
var size = Marshal.SizeOf(typeof(WLAN_PROFILE_INFO));
|
||||
for (int i = 0; i < dwNumberOfItems; i++)
|
||||
{
|
||||
yield return (WLAN_PROFILE_INFO)Marshal.PtrToStructure(ProfileInfoPointer + (i * size), typeof(WLAN_PROFILE_INFO));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WLAN_PROFILE_INFO_LIST(IntPtr Pointer)
|
||||
{
|
||||
dwNumberOfItems = (uint)Marshal.ReadInt32(Pointer, 0);
|
||||
dwIndex = (uint)Marshal.ReadInt32(Pointer, 4);
|
||||
ProfileInfoPointer = Pointer + 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Disco.Client.Interop.Native
|
||||
{
|
||||
public static class WlanApi
|
||||
{
|
||||
|
||||
public const uint WLAN_API_VERSION_2_0 = 2; // Windows Vista WiFi API Version
|
||||
public const int ERROR_SUCCESS = 0;
|
||||
public const int ERROR_INVALID_PARAMETER = 87;
|
||||
public const int ERROR_NOT_ENOUGH_MEMORY = 8;
|
||||
|
||||
/// <summary>
|
||||
/// The WlanOpenHandle function opens a connection to the server.
|
||||
/// </summary>
|
||||
/// <param name="dwClientVersion">The highest version of the WLAN API that the client supports.
|
||||
/// 1 = Client version for Windows XP with SP3 and Wireless LAN API for Windows XP with SP2.
|
||||
/// 2 = Client version for Windows Vista and Windows Server 2008</param>
|
||||
/// <param name="pReserved">Reserved for future use. Must be set to NULL.</param>
|
||||
/// <param name="pdwNegotiatedVersion">The version of the WLAN API that will be used in this session. This value is usually the highest version supported by both the client and server.</param>
|
||||
/// <param name="phClientHandle">A handle for the client to use in this session. This handle is used by other functions throughout the session.</param>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is ERROR_SUCCESS.
|
||||
/// If the function fails, the return value may be one of the following return codes.
|
||||
/// ERROR_INVALID_PARAMETER: pdwNegotiatedVersion is NULL, phClientHandle is NULL, or pReserved is not NULL.
|
||||
/// ERROR_NOT_ENOUGH_MEMORY: Failed to allocate memory to create the client context.
|
||||
/// RPC_STATUS: Various error codes.
|
||||
/// ERROR_REMOTE_SESSION_LIMIT_EXCEEDED: Too many handles have been issued by the server.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The version number specified by dwClientVersion and pdwNegotiatedVersion is a composite version number
|
||||
/// made up of both major and minor versions. The major version is specified by the low-order word, and the
|
||||
/// minor version is specified by the high-order word. The macros WLAN_API_VERSION_MAJOR(_v) and
|
||||
/// WLAN_API_VERSION_MINOR(_v) return the major and minor version numbers respectively.
|
||||
/// You can construct a version number using the macro WLAN_API_MAKE_VERSION(_major, _minor).
|
||||
/// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2: WlanOpenHandle will return an
|
||||
/// error message if the Wireless Zero Configuration (WZC) service has not been started or if the WZC service is not responsive.
|
||||
/// </remarks>
|
||||
[DllImport("Wlanapi.dll")]
|
||||
public static extern uint WlanOpenHandle(uint dwClientVersion, IntPtr pReserved, out uint pdwNegotiatedVersion, out IntPtr phClientHandle);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanCloseHandle function closes a connection to the server.
|
||||
/// </summary>
|
||||
/// <param name="hClientHandle">The client's session handle, which identifies the connection to be closed. This handle was obtained by a previous call to the WlanOpenHandle function.</param>
|
||||
/// <param name="pReserved">Reserved for future use. Set this parameter to NULL.</param>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is ERROR_SUCCESS.
|
||||
/// If the function fails, the return value may be one of the following return codes.
|
||||
/// ERROR_INVALID_PARAMETER: hClientHandle is NULL or invalid, or pReserved is not NULL.
|
||||
/// ERROR_INVALID_HANDLE: The handle hClientHandle was not found in the handle table.
|
||||
/// RPC_STATUS: Various error codes.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// After a connection has been closed, any attempted use of the closed handle can cause unexpected errors.
|
||||
/// Upon closing, all outstanding notifications are discarded.
|
||||
/// Do not call WlanCloseHandle from a callback function. If the client is in the middle of a
|
||||
/// notification callback when WlanCloseHandle is called, the function waits for the callback to
|
||||
/// finish before returning a value. Calling this function inside a callback function will result in
|
||||
/// the call never completing. If both the callback function and the thread that closes the handle try
|
||||
/// to acquire the same lock, a deadlock may occur. In addition, do not call WlanCloseHandle from
|
||||
/// the DllMain function in an application DLL. This could also cause a deadlock.
|
||||
/// </remarks>
|
||||
[DllImport("Wlanapi")]
|
||||
public static extern uint WlanCloseHandle(IntPtr hClientHandle, IntPtr pReserved);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanEnumInterfaces function enumerates all of the wireless LAN interfaces currently enabled on the local computer.
|
||||
/// </summary>
|
||||
/// <param name="hClientHandle">The client's session handle, obtained by a previous call to the WlanOpenHandle function.</param>
|
||||
/// <param name="pReserved">Reserved for future use. This parameter must be set to NULL.</param>
|
||||
/// <param name="ppInterfaceList">
|
||||
/// A pointer to storage for a pointer to receive the returned list of wireless LAN interfaces in a WLAN_INTERFACE_INFO_LIST structure.
|
||||
/// The buffer for the WLAN_INTERFACE_INFO_LIST returned is allocated by the WlanEnumInterfaces function if the call succeeds.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is ERROR_SUCCESS.
|
||||
/// If the function fails, the return value may be one of the following return codes.
|
||||
/// ERROR_INVALID_PARAMETER: A parameter is incorrect. This error is returned if the hClientHandle or ppInterfaceList parameter is NULL. This error is returned if the pReserved is not NULL.
|
||||
/// This error is also returned if the hClientHandle parameter is not valid.
|
||||
/// ERROR_INVALID_HANDLE: The handle hClientHandle was not found in the handle table.
|
||||
/// RPC_STATUS: Various error codes.
|
||||
/// ERROR_NOT_ENOUGH_MEMORY: Not enough memory is available to process this request and allocate memory for the query results.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The WlanEnumInterfaces function allocates memory for the list of returned interfaces that is returned in the
|
||||
/// buffer pointed to by the ppInterfaceList parameter when the function succeeds. The memory used for the buffer
|
||||
/// pointed to by ppInterfaceList parameter should be released by calling the WlanFreeMemory function
|
||||
/// after the buffer is no longer needed.
|
||||
/// </remarks>
|
||||
[DllImport("Wlanapi")]
|
||||
public static extern uint WlanEnumInterfaces(IntPtr hClientHandle, IntPtr pReserved, out IntPtr ppInterfaceList);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanGetProfileList function retrieves the list of profiles in preference order.
|
||||
/// </summary>
|
||||
/// <param name="hClientHandle">The client's session handle, obtained by a previous call to the WlanOpenHandle function.</param>
|
||||
/// <param name="pInterfaceGuid">The GUID of the wireless interface.</param>
|
||||
/// <param name="pReserved">Reserved for future use. Must be set to NULL.</param>
|
||||
/// <param name="ppProfileList">A PWLAN_PROFILE_INFO_LIST structure that contains the list of profile information.</param>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is ERROR_SUCCESS.
|
||||
/// If the function fails, the return value may be one of the following return codes.
|
||||
/// ERROR_INVALID_HANDLE: The handle hClientHandle was not found in the handle table.
|
||||
/// ERROR_INVALID_PARAMETER: A parameter is incorrect.
|
||||
/// ERROR_NOT_ENOUGH_MEMORY: Not enough memory is available to process this request and allocate memory for the query results.
|
||||
/// RPC_STATUS: Various error codes.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The WlanGetProfileList function returns only the basic information on the wireless profiles on a wireless interface.
|
||||
/// The list of wireless profiles on a wireless interface are retrieved in the preference order. The WlanSetProfilePosition
|
||||
/// can be used to change the preference order for the wireless profiles on a wireless interface.
|
||||
/// More detailed information for a wireless profile on a wireless interface can be retrieved by using the WlanGetProfile
|
||||
/// function. The WlanGetProfileCustomUserData function can be used to retrieve custom user data for a wireless profile on
|
||||
/// a wireless interface. A list of the wireless interfaces and associated GUIDs on the local computer can be retrieved
|
||||
/// using the WlanEnumInterfaces function.
|
||||
/// The WlanGetProfileList function allocates memory for the list of profiles returned in the buffer pointed to by the
|
||||
/// ppProfileList parameter. The caller is responsible for freeing this memory using the WlanFreeMemory function when
|
||||
/// this buffer is no longer needed.
|
||||
/// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2: Guest profiles, profiles with Wireless Provisioning
|
||||
/// Service (WPS) authentication, and profiles with Wi-Fi Protected Access-None (WPA-None) authentication are not
|
||||
/// supported. These types of profiles are not returned by WlanGetProfileList, even if a profile of this type appears
|
||||
/// on the preferred profile list.
|
||||
/// </remarks>
|
||||
[DllImport("Wlanapi")]
|
||||
public static extern uint WlanGetProfileList(IntPtr hClientHandle, Guid pInterfaceGuid, IntPtr pReserved, out IntPtr ppProfileList);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanGetProfile function retrieves all information about a specified wireless profile.
|
||||
/// </summary>
|
||||
/// <param name="hClientHandle">The client's session handle, obtained by a previous call to the WlanOpenHandle function.</param>
|
||||
/// <param name="pInterfaceGuid">The GUID of the wireless interface. </param>
|
||||
/// <param name="strProfileName">The name of the profile. Profile names are case-sensitive. This string must be NULL-terminated. The maximum length of the profile name is 255 characters. This means that the maximum length of this string, including the NULL terminator, is 256 characters.</param>
|
||||
/// <param name="pReserved">Reserved for future use. Must be set to NULL.</param>
|
||||
/// <param name="pstrProfileXml">A string that is the XML representation of the queried profile. There is no predefined maximum string length.</param>
|
||||
/// <param name="pdwFlags">On input, a pointer to the address location used to provide additional information about the request. If this parameter is NULL on input, then no information on profile flags will be returned. On output, a pointer to the address location used to receive profile flags.</param>
|
||||
/// <param name="pdwGrantedAccess">The access mask of the all-user profile.</param>
|
||||
/// <returns>If the function succeeds, the return value is ERROR_SUCCESS.</returns>
|
||||
[DllImport("Wlanapi", CharSet = CharSet.Unicode)]
|
||||
public static extern uint WlanGetProfile(IntPtr hClientHandle, Guid pInterfaceGuid, [MarshalAs(UnmanagedType.LPWStr)] string strProfileName, IntPtr pReserved, out IntPtr pstrProfileXml, out uint pdwFlags, out IntPtr pdwGrantedAccess);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanSetProfile function sets the content of a specific profile.
|
||||
/// </summary>
|
||||
/// <param name="hClientHandle">The client's session handle, obtained by a previous call to the WlanOpenHandle function.</param>
|
||||
/// <param name="pInterfaceGuid">The GUID of the interface.</param>
|
||||
/// <param name="dwFlags">The flags to set on the profile.</param>
|
||||
/// <param name="strProfileXml">Contains the XML representation of the profile. The WLANProfile element is the root profile element. To view sample profiles, see Wireless Profile Samples. There is no predefined maximum string length.</param>
|
||||
/// <param name="strAllUserProfileSecurity">Sets the security descriptor string on the all-user profile. For more information about profile permissions, see the Remarks section.</param>
|
||||
/// <param name="bOverwrite">Specifies whether this profile is overwriting an existing profile. If this parameter is FALSE and the profile already exists, the existing profile will not be overwritten and an error will be returned.</param>
|
||||
/// <param name="pReserved">Reserved for future use. Must be set to NULL.</param>
|
||||
/// <param name="pdwReasonCode">A WLAN_REASON_CODE value that indicates why the profile is not valid.</param>
|
||||
/// <returns>If the function succeeds, the return value is ERROR_SUCCESS.</returns>
|
||||
[DllImport("Wlanapi", CharSet = CharSet.Unicode)]
|
||||
public static extern uint WlanSetProfile(IntPtr hClientHandle, Guid pInterfaceGuid, uint dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string strProfileXml, [MarshalAs(UnmanagedType.LPWStr)] string strAllUserProfileSecurity, bool bOverwrite, IntPtr pReserved, out uint pdwReasonCode);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanDeleteProfile function deletes a wireless profile for a wireless interface on the local computer.
|
||||
/// </summary>
|
||||
/// <param name="hClientHandle">The client's session handle, obtained by a previous call to the WlanOpenHandle function.</param>
|
||||
/// <param name="pInterfaceGuid">The GUID of the interface from which to delete the profile. </param>
|
||||
/// <param name="strProfileName">The name of the profile to be deleted. Profile names are case-sensitive. This string must be NULL-terminated.</param>
|
||||
/// <param name="pReserved">Reserved for future use. Must be set to NULL.</param>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is ERROR_SUCCESS.
|
||||
/// If the function fails, the return value may be one of the following return codes.
|
||||
/// ERROR_INVALID_PARAMETER: The hClientHandle parameter is NULL or not valid, the pInterfaceGuid parameter is NULL, the strProfileName parameter is NULL, or pReserved is not NULL.
|
||||
/// ERROR_INVALID_HANDLE: The handle specified in the hClientHandle parameter was not found in the handle table.
|
||||
/// ERROR_NOT_FOUND: The wireless profile specified by strProfileName was not found in the profile store.
|
||||
/// ERROR_ACCESS_DENIED: The caller does not have sufficient permissions to delete the profile.
|
||||
/// RPC_STATUS: Various error codes.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The WlanDeleteProfile function deletes a wireless profile for a wireless interface on the local computer.
|
||||
/// All wireless LAN functions require an interface GUID for the wireless interface when performing profile operations.
|
||||
/// When a wireless interface is removed, its state is cleared from Wireless LAN Service (WLANSVC) and no profile operations are possible.
|
||||
/// The WlanDeleteProfile function can fail with ERROR_INVALID_PARAMETER if the wireless interface specified in the pInterfaceGuid parameter
|
||||
/// for the wireless LAN profile has been removed from the system (a USB wireless adapter that has been removed, for example).
|
||||
/// </remarks>
|
||||
[DllImport("Wlanapi", CharSet = CharSet.Unicode)]
|
||||
public static extern uint WlanDeleteProfile(IntPtr hClientHandle, Guid pInterfaceGuid, [MarshalAs(UnmanagedType.LPWStr)] string strProfileName, IntPtr pReserved);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanReasonCodeToString function retrieves a string that describes a specified reason code.
|
||||
/// </summary>
|
||||
/// <param name="dwReasonCode">A WLAN_REASON_CODE value of which the string description is requested.</param>
|
||||
/// <param name="dwBufferSize">The size of the buffer used to store the string, in WCHAR. If the reason code string is longer than the buffer, it will be truncated and NULL-terminated. If dwBufferSize is larger than the actual amount of memory allocated to pStringBuffer, then an access violation will occur in the calling program.</param>
|
||||
/// <param name="pStringBuffer">Pointer to a buffer that will receive the string. The caller must allocate memory to pStringBuffer before calling WlanReasonCodeToString.</param>
|
||||
/// <param name="pReserved">Reserved for future use. Must be set to NULL.</param>
|
||||
/// <returns>If the function succeeds, the return value is a pointer to a constant string.</returns>
|
||||
[DllImport("Wlanapi", CharSet = CharSet.Unicode)]
|
||||
public static extern uint WlanReasonCodeToString(uint dwReasonCode, uint dwBufferSize, ref StringBuilder pStringBuffer, IntPtr pReserved);
|
||||
|
||||
/// <summary>
|
||||
/// The WlanFreeMemory function frees memory. Any memory returned from Native Wifi functions must be freed.
|
||||
/// </summary>
|
||||
/// <param name="pMemory">Pointer to the memory to be freed.</param>
|
||||
/// <remarks>
|
||||
/// If pMemory points to memory that has already been freed, an access violation or heap corruption may occur.
|
||||
/// </remarks>
|
||||
[DllImport("Wlanapi")]
|
||||
public static extern void WlanFreeMemory(IntPtr pMemory);
|
||||
|
||||
}
|
||||
}
|
||||
+76
-300
@@ -1,73 +1,68 @@
|
||||
using System;
|
||||
using Disco.Client.Interop.Native;
|
||||
using Disco.Models.ClientServices.EnrolmentInformation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Disco.Client.Interop
|
||||
{
|
||||
public static class Network
|
||||
{
|
||||
private static List<NetworkAdapterInfo> NetworkAdapters { get; set; }
|
||||
private static NetworkAdapterInfo PrimaryLanNetworkAdapter { get; set; }
|
||||
private static NetworkAdapterInfo PrimaryWlanNetworkAdapter { get; set; }
|
||||
|
||||
public static void Initialize()
|
||||
public static List<NetworkAdapter> GetNetworkAdapters()
|
||||
{
|
||||
// Get All Adapters
|
||||
RetrieveLanAdapters();
|
||||
var adapters = GetWmiNetworkAdapters();
|
||||
|
||||
if (NetworkAdapters.Count > 0)
|
||||
if (adapters != null && adapters.Count > 0)
|
||||
{
|
||||
// Only Retrieve Wlan Adapters if at least one adapter was found by WMI
|
||||
try
|
||||
{
|
||||
RetrieveWlanAdapters();
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
// Ignore DllNotFoundException
|
||||
// This which indicates 'Wlanapi.dll' isn't present (eg. Windows Servers)
|
||||
}
|
||||
|
||||
// Determine Primary Adapters
|
||||
|
||||
// Lan
|
||||
PrimaryLanNetworkAdapter = NetworkAdapters.Where(n => !n.IsWLanAdapter && n.NetConnectionId.StartsWith("Local Area Connection", StringComparison.OrdinalIgnoreCase)).OrderByDescending(n => n.Speed).FirstOrDefault();
|
||||
// Might be too restrictive - remove name restriction just in case.
|
||||
if (PrimaryLanNetworkAdapter == null)
|
||||
PrimaryLanNetworkAdapter = NetworkAdapters.Where(n => !n.IsWLanAdapter).OrderByDescending(n => n.Speed).FirstOrDefault();
|
||||
|
||||
// Wan
|
||||
PrimaryWlanNetworkAdapter = NetworkAdapters.Where(n => n.IsWLanAdapter).OrderByDescending(n => n.Speed).FirstOrDefault();
|
||||
// Apply Wlan Information
|
||||
adapters.ApplyWlanInformation();
|
||||
}
|
||||
}
|
||||
|
||||
private static void RetrieveLanAdapters()
|
||||
return adapters;
|
||||
}
|
||||
|
||||
private static List<NetworkAdapter> GetWmiNetworkAdapters()
|
||||
{
|
||||
// Get NetworkAdapter Information
|
||||
try
|
||||
{
|
||||
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT Index, GUID, MACAddress, Name, NetConnectionID, Speed FROM Win32_NetworkAdapter WHERE PhysicalAdapter=true AND MACAddress IS NOT NULL AND Name IS NOT NULL AND NetConnectionID IS NOT NULL AND Speed IS NOT NULL"))
|
||||
// Load Physical Adapters
|
||||
using (var wmiSearcher = new ManagementObjectSearcher("SELECT DeviceID, GUID, Manufacturer, ProductName, AdapterType, MACAddress, Speed, NetConnectionID, NetConnectionStatus, NetEnabled FROM Win32_NetworkAdapter WHERE PhysicalAdapter=true AND MACAddress IS NOT NULL AND NetConnectionID IS NOT NULL AND Speed IS NOT NULL"))
|
||||
{
|
||||
using (ManagementObjectCollection mResults = mSearcher.Get())
|
||||
using (var wmiResults = wmiSearcher.Get())
|
||||
{
|
||||
NetworkAdapters = new List<NetworkAdapterInfo>();
|
||||
foreach (var mResult in mResults.Cast<ManagementObject>())
|
||||
{
|
||||
NetworkAdapterInfo nic = new NetworkAdapterInfo()
|
||||
return wmiResults
|
||||
.Cast<ManagementObject>()
|
||||
.Select(wmiResult =>
|
||||
{
|
||||
Index = (UInt32)mResult.GetPropertyValue("Index"),
|
||||
Guid = Guid.Parse((string)mResult.GetPropertyValue("GUID")),
|
||||
MacAddress = mResult.GetPropertyValue("MACAddress").ToString(),
|
||||
Name = mResult.GetPropertyValue("Name").ToString(),
|
||||
NetConnectionId = mResult.GetPropertyValue("NetConnectionID").ToString(),
|
||||
Speed = Convert.ToUInt64(mResult.GetPropertyValue("Speed")),
|
||||
IsWLanAdapter = false
|
||||
};
|
||||
NetworkAdapters.Add(nic);
|
||||
}
|
||||
var adapter = new NetworkAdapter()
|
||||
{
|
||||
DeviceID = (string)wmiResult.GetPropertyValue("DeviceID"),
|
||||
ConnectionIdentifier = Guid.Parse((string)wmiResult.GetPropertyValue("GUID")),
|
||||
Manufacturer = (string)wmiResult.GetPropertyValue("Manufacturer"),
|
||||
ProductName = (string)wmiResult.GetPropertyValue("ProductName"),
|
||||
AdapterType = (string)wmiResult.GetPropertyValue("AdapterType"),
|
||||
MACAddress = (string)wmiResult.GetPropertyValue("MACAddress"),
|
||||
Speed = (ulong)wmiResult.GetPropertyValue("Speed"),
|
||||
NetConnectionID = (string)wmiResult.GetPropertyValue("NetConnectionID"),
|
||||
NetConnectionStatus = ((NetworkConnectionStatuses)wmiResult.GetPropertyValue("NetConnectionStatus")).Description(),
|
||||
NetEnabled = (bool)wmiResult.GetPropertyValue("NetEnabled")
|
||||
};
|
||||
|
||||
using (var wmiRelatedResults = wmiResult.GetRelated("Win32_NetworkAdapterConfiguration", "Win32_NetworkAdapterSetting", null, null, null, null, false, null))
|
||||
{
|
||||
var wmiConfiguration = wmiRelatedResults.Cast<ManagementObject>().First();
|
||||
|
||||
adapter.IPEnabled = (bool)wmiConfiguration.GetPropertyValue("IPEnabled");
|
||||
if (adapter.IPEnabled)
|
||||
{
|
||||
adapter.IPAddresses = ((string[])wmiConfiguration.GetPropertyValue("IPAddress")).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
return adapter;
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,259 +72,40 @@ namespace Disco.Client.Interop
|
||||
}
|
||||
}
|
||||
|
||||
private static void RetrieveWlanAdapters()
|
||||
public static string Description(this NetworkConnectionStatuses Status)
|
||||
{
|
||||
WLAN_INTERFACE_INFO_LIST wlanApiInterfaceList;
|
||||
|
||||
IntPtr wlanApiHandle = IntPtr.Zero;
|
||||
uint wlanApiServiceVersion = 0;
|
||||
|
||||
if (WlanOpenHandle(WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanApiServiceVersion, ref wlanApiHandle) == ERROR_SUCCESS)
|
||||
switch (Status)
|
||||
{
|
||||
IntPtr wlanApiInterfaceListPointer = IntPtr.Zero;
|
||||
|
||||
if (WlanEnumInterfaces(wlanApiHandle, IntPtr.Zero, ref wlanApiInterfaceListPointer) == ERROR_SUCCESS)
|
||||
{
|
||||
wlanApiInterfaceList = new WLAN_INTERFACE_INFO_LIST(wlanApiInterfaceListPointer);
|
||||
WlanFreeMemory(wlanApiInterfaceListPointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error - No Wlan Adapters Reported
|
||||
WlanCloseHandle(wlanApiHandle, IntPtr.Zero);
|
||||
return;
|
||||
}
|
||||
|
||||
WlanCloseHandle(wlanApiHandle, IntPtr.Zero);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error - No Wlan Adapters Reported
|
||||
return;
|
||||
}
|
||||
|
||||
if (wlanApiInterfaceList.InterfaceInfo != null)
|
||||
{
|
||||
foreach (var wlanApiAdapter in wlanApiInterfaceList.InterfaceInfo)
|
||||
{
|
||||
var wlanApiAdapterInfo = wlanApiAdapter;
|
||||
var wmiAdapterInfo = NetworkAdapters.FirstOrDefault(n => n.Guid == wlanApiAdapterInfo.InterfaceGuid);
|
||||
if (wmiAdapterInfo != null)
|
||||
{
|
||||
wmiAdapterInfo.IsWLanAdapter = true;
|
||||
wmiAdapterInfo.WlanState = wlanApiAdapterInfo.isState;
|
||||
}
|
||||
}
|
||||
case NetworkConnectionStatuses.Disconnected:
|
||||
return "Disconnected";
|
||||
case NetworkConnectionStatuses.Connecting:
|
||||
return "Connecting";
|
||||
case NetworkConnectionStatuses.Connected:
|
||||
return "Connected";
|
||||
case NetworkConnectionStatuses.Disconnecting:
|
||||
return "Disconnecting";
|
||||
case NetworkConnectionStatuses.HardwareNotPresent:
|
||||
return "Hardware Not Present";
|
||||
case NetworkConnectionStatuses.HardwareDisabled:
|
||||
return "Hardware Disabled";
|
||||
case NetworkConnectionStatuses.HardwareMalfunction:
|
||||
return "Hardware Malfunction";
|
||||
case NetworkConnectionStatuses.MediaDisconnected:
|
||||
return "Media Disconnected";
|
||||
case NetworkConnectionStatuses.Authenticating:
|
||||
return "Authenticating";
|
||||
case NetworkConnectionStatuses.AuthenticationSucceeded:
|
||||
return "Authentication Succeeded";
|
||||
case NetworkConnectionStatuses.AuthenticationFailed:
|
||||
return "Authentication Failed";
|
||||
case NetworkConnectionStatuses.InvalidAddress:
|
||||
return "Invalid Address";
|
||||
case NetworkConnectionStatuses.CredentialsRequired:
|
||||
return "Credentials Required";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
public static string PrimaryLanMacAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
// Return null if no Primary LAN Network Adapter found on this Device
|
||||
|
||||
return (PrimaryLanNetworkAdapter == null) ? null : PrimaryLanNetworkAdapter.MacAddress;
|
||||
}
|
||||
}
|
||||
public static string PrimaryWlanMacAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
// Return null if no Primary WLAN Network Adapter found on this Device
|
||||
|
||||
return (PrimaryWlanNetworkAdapter == null) ? null : PrimaryWlanNetworkAdapter.MacAddress;
|
||||
}
|
||||
}
|
||||
|
||||
private class NetworkAdapterInfo
|
||||
{
|
||||
public UInt32 Index { get; set; }
|
||||
public Guid Guid { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string NetConnectionId { get; set; }
|
||||
public string MacAddress { get; set; }
|
||||
public UInt64 Speed { get; set; }
|
||||
|
||||
public bool IsWLanAdapter { get; set; }
|
||||
public WLAN_INTERFACE_STATE WlanState { get; set; }
|
||||
|
||||
public string WlanStateDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (WlanState)
|
||||
{
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_not_ready:
|
||||
return "Not Ready";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_connected:
|
||||
return "Connected";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_ad_hoc_network_formed:
|
||||
return "Ad Hoc Network Formed";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_disconnecting:
|
||||
return "Disconnecting";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_disconnected:
|
||||
return "Disconnected";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_associating:
|
||||
return "Associating";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_discovering:
|
||||
return "Discovering";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_authenticating:
|
||||
return "Authenticating";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Wlan Win32 Interop
|
||||
|
||||
private const uint WLAN_API_VERSION_2_0 = 2; // Windows Vista WiFi API Version
|
||||
private const int ERROR_SUCCESS = 0;
|
||||
|
||||
/// <summary >
|
||||
/// Opens a connection to the server
|
||||
/// </summary >
|
||||
[DllImport("Wlanapi.dll")]
|
||||
private static extern int WlanOpenHandle(
|
||||
uint dwClientVersion,
|
||||
IntPtr pReserved, //not in MSDN but required
|
||||
[Out] out uint pdwNegotiatedVersion,
|
||||
ref IntPtr ClientHandle);
|
||||
|
||||
/// <summary >
|
||||
/// Closes a connection to the server
|
||||
/// </summary >
|
||||
[DllImport("Wlanapi", EntryPoint = "WlanCloseHandle")]
|
||||
private static extern uint WlanCloseHandle(
|
||||
[In] IntPtr hClientHandle,
|
||||
IntPtr pReserved);
|
||||
|
||||
/// <summary >
|
||||
/// Enumerates all wireless interfaces in the laptop
|
||||
/// </summary >
|
||||
[DllImport("Wlanapi", EntryPoint = "WlanEnumInterfaces")]
|
||||
private static extern uint WlanEnumInterfaces(
|
||||
[In] IntPtr hClientHandle,
|
||||
IntPtr pReserved,
|
||||
ref IntPtr ppInterfaceList);
|
||||
|
||||
/// <summary >
|
||||
/// Frees memory returned by native WiFi functions
|
||||
/// </summary >
|
||||
[DllImport("Wlanapi", EntryPoint = "WlanFreeMemory")]
|
||||
private static extern void WlanFreeMemory([In] IntPtr pMemory);
|
||||
|
||||
/// <summary>
|
||||
/// Defines the state of the interface. e.g. connected, disconnected.
|
||||
/// </summary>
|
||||
private enum WLAN_INTERFACE_STATE
|
||||
{
|
||||
/// <summary>
|
||||
/// wlan_interface_state_not_ready -> 0
|
||||
/// </summary>
|
||||
wlan_interface_state_not_ready = 0,
|
||||
/// <summary>
|
||||
/// wlan_interface_state_connected -> 1
|
||||
/// </summary>
|
||||
wlan_interface_state_connected = 1,
|
||||
/// <summary>
|
||||
/// wlan_interface_state_ad_hoc_network_formed -> 2
|
||||
/// </summary>
|
||||
wlan_interface_state_ad_hoc_network_formed = 2,
|
||||
/// <summary>
|
||||
/// wlan_interface_state_disconnecting -> 3
|
||||
/// </summary>
|
||||
wlan_interface_state_disconnecting = 3,
|
||||
/// <summary>
|
||||
/// wlan_interface_state_disconnected -> 4
|
||||
/// </summary>
|
||||
wlan_interface_state_disconnected = 4,
|
||||
/// <summary>
|
||||
/// wlan_interface_state_associating -> 5
|
||||
/// </summary>
|
||||
wlan_interface_state_associating = 5,
|
||||
/// <summary>
|
||||
/// wlan_interface_state_discovering -> 6
|
||||
/// </summary>
|
||||
wlan_interface_state_discovering = 6,
|
||||
/// <summary>
|
||||
/// wlan_interface_state_authenticating -> 7
|
||||
/// </summary>
|
||||
wlan_interface_state_authenticating = 7,
|
||||
}
|
||||
|
||||
|
||||
/// <summary >
|
||||
/// Stores interface info
|
||||
/// </summary >
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
private struct WLAN_INTERFACE_INFO
|
||||
{
|
||||
/// GUID->_GUID
|
||||
public Guid InterfaceGuid;
|
||||
|
||||
/// WCHAR[256]
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string strInterfaceDescription;
|
||||
|
||||
/// WLAN_INTERFACE_STATE->_WLAN_INTERFACE_STATE
|
||||
public WLAN_INTERFACE_STATE isState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains an array of NIC information
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct WLAN_INTERFACE_INFO_LIST
|
||||
{
|
||||
/// <summary>
|
||||
/// Length of <see cref="InterfaceInfo"/> array
|
||||
/// </summary>
|
||||
public Int32 dwNumberOfItems;
|
||||
/// <summary>
|
||||
/// This member is not used by the wireless service. Applications can use this member when processing individual interfaces.
|
||||
/// </summary>
|
||||
public Int32 dwIndex;
|
||||
/// <summary>
|
||||
/// Array of WLAN interfaces.
|
||||
/// </summary>
|
||||
public WLAN_INTERFACE_INFO[] InterfaceInfo;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for WLAN_INTERFACE_INFO_LIST.
|
||||
/// Constructor is needed because the InterfaceInfo member varies based on how many adapters are in the system.
|
||||
/// </summary>
|
||||
/// <param name="pList">the unmanaged pointer containing the list.</param>
|
||||
public WLAN_INTERFACE_INFO_LIST(IntPtr pList)
|
||||
{
|
||||
// The first 4 bytes are the number of WLAN_INTERFACE_INFO structures.
|
||||
dwNumberOfItems = Marshal.ReadInt32(pList, 0);
|
||||
|
||||
// The next 4 bytes are the index of the current item in the unmanaged API.
|
||||
dwIndex = Marshal.ReadInt32(pList, 4);
|
||||
|
||||
// Construct the array of WLAN_INTERFACE_INFO structures.
|
||||
InterfaceInfo = new WLAN_INTERFACE_INFO[dwNumberOfItems];
|
||||
|
||||
for (int i = 0; i <= dwNumberOfItems - 1; i++)
|
||||
{
|
||||
// The offset of the array of structures is 8 bytes past the beginning.
|
||||
// Then, take the index and multiply it by the number of bytes in the
|
||||
// structure.
|
||||
// The length of the WLAN_INTERFACE_INFO structure is 532 bytes - this
|
||||
// was determined by doing a Marshall.SizeOf(WLAN_INTERFACE_INFO)
|
||||
IntPtr pItemList = new IntPtr(pList.ToInt64() + (i * 532) + 8);
|
||||
|
||||
// Construct the WLAN_INTERFACE_INFO structure, marshal the unmanaged
|
||||
// structure into it, then copy it to the array of structures.
|
||||
InterfaceInfo[i] = (WLAN_INTERFACE_INFO)Marshal.PtrToStructure(pItemList, typeof(WLAN_INTERFACE_INFO));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.Client.Interop
|
||||
{
|
||||
public static class SystemAudit
|
||||
{
|
||||
|
||||
public static string DeviceSerialNumber { get; private set; }
|
||||
public static string DeviceSMBIOSVersion { get; private set; }
|
||||
public static string DeviceManufacturer { get; private set; }
|
||||
public static string DeviceModel { get; private set; }
|
||||
public static string DeviceType { get; private set; }
|
||||
public static string DeviceUUID { get; private set; }
|
||||
public static bool DeviceIsPartOfDomain { get; private set; }
|
||||
public static string DeviceDNSDomainName { get; private set; }
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
// Get BIOS Information
|
||||
try
|
||||
{
|
||||
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT SerialNumber, SMBIOSBIOSVersion FROM Win32_BIOS WHERE PrimaryBios=true"))
|
||||
{
|
||||
using (ManagementObjectCollection mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
DeviceSerialNumber = mItem.GetPropertyValue("SerialNumber") as string;
|
||||
if (!string.IsNullOrEmpty(DeviceSerialNumber))
|
||||
DeviceSerialNumber = DeviceSerialNumber.Trim();
|
||||
|
||||
ErrorReporting.DeviceIdentifier = DeviceSerialNumber;
|
||||
DeviceSMBIOSVersion = mItem.GetPropertyValue("SMBIOSBIOSVersion") as string;
|
||||
if (!string.IsNullOrEmpty(DeviceSMBIOSVersion))
|
||||
DeviceSMBIOSVersion = DeviceSMBIOSVersion.Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_BIOS WHERE PrimaryBios=true was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco Client was unable to retrieve BIOS information from WMI", ex);
|
||||
}
|
||||
|
||||
// Get System Information
|
||||
try
|
||||
{
|
||||
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT Manufacturer, Model, PartOfDomain, PCSystemType, Domain FROM Win32_ComputerSystem"))
|
||||
{
|
||||
using (ManagementObjectCollection mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
DeviceManufacturer = mItem.GetPropertyValue("Manufacturer") as string;
|
||||
if (!string.IsNullOrEmpty(DeviceManufacturer))
|
||||
DeviceManufacturer = DeviceManufacturer.Trim();
|
||||
|
||||
DeviceModel = mItem.GetPropertyValue("Model") as string;
|
||||
if (!string.IsNullOrEmpty(DeviceModel))
|
||||
DeviceModel = DeviceModel.Trim();
|
||||
|
||||
DeviceIsPartOfDomain = (bool)mItem.GetPropertyValue("PartOfDomain");
|
||||
DeviceType = PCSystemTypeToString((UInt16)mItem.GetPropertyValue("PCSystemType"));
|
||||
|
||||
DeviceDNSDomainName = DeviceIsPartOfDomain ? mItem.GetPropertyValue("Domain") as string : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_ComputerSystem was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco Client was unable to retrieve ComputerSystem information from WMI", ex);
|
||||
}
|
||||
|
||||
// Get System Product Information
|
||||
string ComputerSystemProductSerialNumber;
|
||||
try
|
||||
{
|
||||
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT IdentifyingNumber, UUID FROM Win32_ComputerSystemProduct"))
|
||||
{
|
||||
using (ManagementObjectCollection mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
ComputerSystemProductSerialNumber = mItem.GetPropertyValue("IdentifyingNumber") as string;
|
||||
if (!string.IsNullOrEmpty(ComputerSystemProductSerialNumber))
|
||||
ComputerSystemProductSerialNumber = ComputerSystemProductSerialNumber.Trim();
|
||||
|
||||
DeviceUUID = mItem.GetPropertyValue("UUID") as string;
|
||||
if (!string.IsNullOrEmpty(DeviceUUID))
|
||||
DeviceUUID = DeviceUUID.Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_ComputerSystemProduct was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco Client was unable to retrieve ComputerSystemProduct information from WMI", ex);
|
||||
}
|
||||
|
||||
// Added 2012-11-22 G# - Lenovo IdeaPad Serial SHIM
|
||||
// http://www.discoict.com.au/forum/feature-requests/2012/11/serial-number-detection-on-ideapads.aspx
|
||||
if (string.IsNullOrWhiteSpace(DeviceSerialNumber) ||
|
||||
(DeviceManufacturer.Equals("LENOVO", StringComparison.OrdinalIgnoreCase) &&
|
||||
(DeviceModel.Equals("S10-3", StringComparison.OrdinalIgnoreCase) // S10-3
|
||||
|| DeviceModel.Equals("2957", StringComparison.OrdinalIgnoreCase)))) // S10-2
|
||||
{
|
||||
try
|
||||
{
|
||||
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard"))
|
||||
{
|
||||
using (ManagementObjectCollection mResults = mSearcher.Get())
|
||||
{
|
||||
using (var mItem = mResults.Cast<ManagementObject>().FirstOrDefault())
|
||||
{
|
||||
if (mItem != null)
|
||||
{
|
||||
DeviceSerialNumber = mItem.GetPropertyValue("SerialNumber") as string;
|
||||
if (!string.IsNullOrEmpty(DeviceSerialNumber))
|
||||
DeviceSerialNumber = DeviceSerialNumber.Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("No Win32_BaseBoard was found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Disco Client was unable to retrieve BaseBoard information from WMI", ex);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(DeviceSerialNumber))
|
||||
DeviceSerialNumber = ComputerSystemProductSerialNumber;
|
||||
}
|
||||
// End Added 2012-11-22 G#
|
||||
|
||||
ErrorReporting.DeviceIdentifier = DeviceSerialNumber;
|
||||
|
||||
// Validate Device 'State'
|
||||
if (string.IsNullOrWhiteSpace(DeviceSerialNumber))
|
||||
throw new Exception("This device has no serial number stored in BIOS or BaseBoard");
|
||||
if (DeviceSerialNumber.Length > 60)
|
||||
throw new Exception(string.Format("The serial number reported by this device is over 60 characters long:{0}{1}", Environment.NewLine, DeviceSerialNumber));
|
||||
}
|
||||
|
||||
private static string PCSystemTypeToString(UInt16 PCSystemType)
|
||||
{
|
||||
switch (PCSystemType)
|
||||
{
|
||||
case 0:
|
||||
return "Unknown";
|
||||
case 1:
|
||||
return "Desktop";
|
||||
case 2:
|
||||
return "Mobile";
|
||||
case 3:
|
||||
return "Workstation";
|
||||
case 4:
|
||||
return "EnterpriseServer";
|
||||
case 5:
|
||||
return "SmallOfficeAndHomeOfficeServer";
|
||||
case 6:
|
||||
return "AppliancePC";
|
||||
case 7:
|
||||
return "PerformanceServer";
|
||||
case 8:
|
||||
return "Maximum";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
using Disco.Client.Interop.Native;
|
||||
using Disco.Models.ClientServices.EnrolmentInformation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Disco.Client.Interop
|
||||
{
|
||||
public static class WirelessNetwork
|
||||
{
|
||||
|
||||
public static void ApplyWlanInformation(this List<NetworkAdapter> Adapters)
|
||||
{
|
||||
try
|
||||
{
|
||||
IntPtr wlanHandle;
|
||||
uint wlanServiceVersion;
|
||||
|
||||
if (WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanServiceVersion, out wlanHandle) == WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
try
|
||||
{
|
||||
IntPtr wlanInterfacesPtr;
|
||||
|
||||
if (WlanApi.WlanEnumInterfaces(wlanHandle, IntPtr.Zero, out wlanInterfacesPtr) == WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
try
|
||||
{
|
||||
var wlanInterfaces = new WLAN_INTERFACE_INFO_LIST(wlanInterfacesPtr);
|
||||
|
||||
foreach (var wlanInterface in wlanInterfaces.InterfaceInfo)
|
||||
{
|
||||
var adapter = Adapters.FirstOrDefault(a => a.ConnectionIdentifier == wlanInterface.InterfaceGuid);
|
||||
if (adapter != null)
|
||||
{
|
||||
adapter.IsWlanAdapter = true;
|
||||
adapter.WlanStatus = wlanInterface.isState.Description();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
WlanApi.WlanFreeMemory(wlanInterfacesPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
WlanApi.WlanCloseHandle(wlanHandle, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
// Ignore
|
||||
// Indicates 'Wlanapi.dll' isn't present (ie. Servers)
|
||||
}
|
||||
}
|
||||
|
||||
public static List<WirelessProfile> GetWirelessProfiles()
|
||||
{
|
||||
try
|
||||
{
|
||||
IntPtr wlanHandle;
|
||||
uint wlanServiceVersion;
|
||||
uint interopResult;
|
||||
|
||||
// Connect to wireless service
|
||||
interopResult = WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanServiceVersion, out wlanHandle);
|
||||
if (interopResult != WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Exception($"Unable to connect to local wireless service. WlanOpenHandle returned: {interopResult}");
|
||||
}
|
||||
try
|
||||
{
|
||||
return GetWirelessProfiles(wlanHandle);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WlanApi.WlanCloseHandle(wlanHandle, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
// Indicates 'Wlanapi.dll' isn't present (ie. Servers)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<WirelessProfile> GetWirelessProfiles(IntPtr wlanHandle)
|
||||
{
|
||||
uint interopResult;
|
||||
IntPtr wlanInterfacesPtr;
|
||||
|
||||
// Enumerate wireless interfaces
|
||||
interopResult = WlanApi.WlanEnumInterfaces(wlanHandle, IntPtr.Zero, out wlanInterfacesPtr);
|
||||
if (interopResult != WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Exception($"Unable to list interfaces with the local wireless service. WlanEnumInterfaces returned: {interopResult}");
|
||||
}
|
||||
try
|
||||
{
|
||||
var wlanInterfaces = new WLAN_INTERFACE_INFO_LIST(wlanInterfacesPtr);
|
||||
var profiles = new List<WirelessProfile>();
|
||||
|
||||
foreach (var wlanInterface in wlanInterfaces.InterfaceInfo)
|
||||
{
|
||||
IntPtr wlanProfilesPtr;
|
||||
// Enumerate wireless profiles for interface
|
||||
interopResult = WlanApi.WlanGetProfileList(wlanHandle, wlanInterface.InterfaceGuid, IntPtr.Zero, out wlanProfilesPtr);
|
||||
if (interopResult != WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Exception($"Unable to list wireless profiles for the {wlanInterface.InterfaceGuid} interface with the local wireless service. WlanGetProfileList returned: {interopResult}");
|
||||
}
|
||||
try
|
||||
{
|
||||
var wlanProfiles = new WLAN_PROFILE_INFO_LIST(wlanProfilesPtr);
|
||||
|
||||
foreach (var wlanProfile in wlanProfiles.ProfileInfo)
|
||||
{
|
||||
profiles.Add(new WirelessProfile()
|
||||
{
|
||||
Name = wlanProfile.strInterfaceDescription,
|
||||
InterfaceGuid = wlanInterface.InterfaceGuid,
|
||||
IsGroupPolicy = wlanProfile.dwFlags.HasFlag(ProfileInfoFlags.WLAN_PROFILE_GROUP_POLICY)
|
||||
});
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
WlanApi.WlanFreeMemory(wlanProfilesPtr);
|
||||
}
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
finally
|
||||
{
|
||||
WlanApi.WlanFreeMemory(wlanInterfacesPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Apply(this WirelessProfileStore ProfileStore)
|
||||
{
|
||||
var adapters = Network.GetNetworkAdapters().Where(a => a.IsWlanAdapter).ToList();
|
||||
|
||||
try
|
||||
{
|
||||
IntPtr wlanHandle;
|
||||
uint wlanServiceVersion;
|
||||
uint interopResult;
|
||||
|
||||
// Connect to wireless service
|
||||
interopResult = WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanServiceVersion, out wlanHandle);
|
||||
if (interopResult != WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Exception($"Unable to connect to local wireless service. WlanOpenHandle returned: {interopResult}");
|
||||
}
|
||||
try
|
||||
{
|
||||
var existingProfiles = GetWirelessProfiles(wlanHandle);
|
||||
var addedProfiles = new List<string>();
|
||||
|
||||
// Remove Profiles
|
||||
if (ProfileStore.RemoveNames != null && ProfileStore.RemoveNames.Count > 0)
|
||||
{
|
||||
var profileRemoved = false;
|
||||
|
||||
foreach (var removeName in ProfileStore.RemoveNames)
|
||||
{
|
||||
var foundProfiles = existingProfiles.Where(p => p.Name == removeName);
|
||||
foreach (var profile in foundProfiles)
|
||||
{
|
||||
var adapter = adapters.FirstOrDefault(a => a.ConnectionIdentifier == profile.InterfaceGuid);
|
||||
|
||||
if (profile.IsGroupPolicy == true)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nUnable to remove Group Policy Wireless Profile '{removeName}' from '{adapter?.NetConnectionID ?? profile.InterfaceGuid.ToString()}'", true, -1, 3000);
|
||||
}
|
||||
else
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nRemoving Wireless Profile '{removeName}' from '{adapter?.NetConnectionID ?? profile.InterfaceGuid.ToString()}'", true, -1, 1000);
|
||||
|
||||
interopResult = WlanApi.WlanDeleteProfile(wlanHandle, profile.InterfaceGuid.Value, profile.Name, IntPtr.Zero);
|
||||
|
||||
if (interopResult != WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nFailed to remove Wireless Profile '{removeName}' from '{adapter?.NetConnectionID ?? profile.InterfaceGuid.ToString()}'; WlanDeleteProfile returned: {interopResult}", true, -1, 3000);
|
||||
}
|
||||
profileRemoved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (profileRemoved)
|
||||
{
|
||||
existingProfiles = GetWirelessProfiles(wlanHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// Add Profiles
|
||||
if (ProfileStore.Profiles != null && ProfileStore.Profiles.Count > 0)
|
||||
{
|
||||
foreach (var addProfile in ProfileStore.Profiles)
|
||||
{
|
||||
foreach (var adapter in adapters)
|
||||
{
|
||||
var existingProfile = existingProfiles.FirstOrDefault(p => p.Name == addProfile.Name && p.InterfaceGuid == adapter.ConnectionIdentifier);
|
||||
|
||||
if (addProfile.ForceDeployment.Value ||
|
||||
existingProfile == null)
|
||||
{
|
||||
if (existingProfile != null && existingProfile.IsGroupPolicy.Value)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nUnable to replace Group Policy Wireless Profile '{addProfile.Name}' on '{adapter.NetConnectionID}'", true, -1, 3000);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint pdwReasonCode;
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nAdding Wireless Profile '{addProfile.Name}' on '{adapter.NetConnectionID}'", true, -1, 1000);
|
||||
interopResult = WlanApi.WlanSetProfile(wlanHandle, adapter.ConnectionIdentifier, 0, addProfile.ProfileXml, null, true, IntPtr.Zero, out pdwReasonCode);
|
||||
|
||||
if (interopResult != WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
// Get Reason Code
|
||||
var reason = new StringBuilder(256);
|
||||
WlanApi.WlanReasonCodeToString(pdwReasonCode, (uint)reason.Capacity, ref reason, IntPtr.Zero);
|
||||
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nFailed to add Wireless Profile '{addProfile.Name}' on '{adapter.NetConnectionID}'; WlanSetProfile returned: {interopResult}; {reason.ToString()}", true, -1, 3000);
|
||||
}
|
||||
}
|
||||
addedProfiles.Add(addProfile.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Transform Profiles
|
||||
if (ProfileStore.Transformations != null && ProfileStore.Transformations.Count > 0)
|
||||
{
|
||||
foreach (var transformGroup in ProfileStore.Transformations.GroupBy(t => t.Name))
|
||||
{
|
||||
var profileName = transformGroup.Key;
|
||||
|
||||
// Don't transform if just added
|
||||
if (!addedProfiles.Contains(transformGroup.Key))
|
||||
{
|
||||
foreach (var adapter in adapters)
|
||||
{
|
||||
var existingProfile = existingProfiles.FirstOrDefault(p => p.Name == profileName && p.InterfaceGuid == adapter.ConnectionIdentifier);
|
||||
|
||||
if (existingProfile != null)
|
||||
{
|
||||
if (existingProfile.IsGroupPolicy.Value)
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nUnable to modify Group Policy Wireless Profile '{profileName}' on '{adapter.NetConnectionID}'", true, -1, 3000);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load profile
|
||||
IntPtr pstrProfileXml;
|
||||
uint pdwFlags;
|
||||
IntPtr pdwGrantAccess;
|
||||
|
||||
interopResult = WlanApi.WlanGetProfile(wlanHandle, adapter.ConnectionIdentifier, profileName, IntPtr.Zero, out pstrProfileXml, out pdwFlags, out pdwGrantAccess);
|
||||
|
||||
if (interopResult == WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
try
|
||||
{
|
||||
var profileXml = Marshal.PtrToStringUni(pstrProfileXml);
|
||||
var originalProfileXml = XElement.Parse(profileXml);
|
||||
var transformProfileXml = originalProfileXml.ToString(SaveOptions.DisableFormatting);
|
||||
|
||||
// Apply Transforms
|
||||
foreach (var transform in transformGroup)
|
||||
{
|
||||
var regex = new Regex(transform.RegularExpression, RegexOptions.Singleline);
|
||||
transformProfileXml = regex.Replace(transformProfileXml, transform.RegularExpressionReplacement);
|
||||
}
|
||||
|
||||
// Compare XML
|
||||
var transformedProfileXml = XElement.Parse(transformProfileXml);
|
||||
|
||||
if (!XNode.DeepEquals(originalProfileXml, transformedProfileXml))
|
||||
{
|
||||
// Set Profile
|
||||
uint pdwReasonCode;
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nModifying Wireless Profile '{profileName}' on '{adapter.NetConnectionID}'", true, -1, 1000);
|
||||
transformProfileXml = transformedProfileXml.ToString(SaveOptions.None);
|
||||
interopResult = WlanApi.WlanSetProfile(wlanHandle, adapter.ConnectionIdentifier, 0, transformProfileXml, null, true, IntPtr.Zero, out pdwReasonCode);
|
||||
|
||||
if (interopResult != WlanApi.ERROR_SUCCESS)
|
||||
{
|
||||
// Get Reason Code
|
||||
var reason = new StringBuilder(256);
|
||||
WlanApi.WlanReasonCodeToString(pdwReasonCode, (uint)reason.Capacity, ref reason, IntPtr.Zero);
|
||||
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nFailed to modify Wireless Profile '{profileName}' to '{adapter.NetConnectionID}'; WlanSetProfile returned: {interopResult}; {reason.ToString()}", true, -1, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
WlanApi.WlanFreeMemory(pstrProfileXml);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nFailed to transform Wireless Profile '{profileName}' on '{adapter.NetConnectionID}'; WlanGetProfile returned: {interopResult}", true, -1, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
WlanApi.WlanCloseHandle(wlanHandle, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
// Indicates 'Wlanapi.dll' isn't present (ie. Servers)
|
||||
// Ignore policies
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static string Description(this WLAN_INTERFACE_STATE State)
|
||||
{
|
||||
switch (State)
|
||||
{
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_not_ready:
|
||||
return "Not Ready";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_connected:
|
||||
return "Connected";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_ad_hoc_network_formed:
|
||||
return "Ad Hoc Network";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_disconnecting:
|
||||
return "Disconnecting";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_disconnected:
|
||||
return "Disconnected";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_associating:
|
||||
return "Associating";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_discovering:
|
||||
return "Discovering";
|
||||
case WLAN_INTERFACE_STATE.wlan_interface_state_authenticating:
|
||||
return "Authenticating";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Disco.Client.Extensions;
|
||||
using Disco.Client.Interop;
|
||||
|
||||
namespace Disco.Client
|
||||
{
|
||||
@@ -38,8 +39,8 @@ namespace Disco.Client
|
||||
public static void WriteBanner()
|
||||
{
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.Append("Version: ").AppendLine(Assembly.GetExecutingAssembly().GetName().Version.ToString(3));
|
||||
message.Append("Device: ").Append(Interop.SystemAudit.DeviceSerialNumber).Append(" (").Append(Interop.SystemAudit.DeviceManufacturer).Append(" ").Append(Interop.SystemAudit.DeviceModel).AppendLine(")");
|
||||
message.AppendLine($"Version: {Assembly.GetExecutingAssembly().GetName().Version.ToString(3)}");
|
||||
message.AppendLine($"Device: {Hardware.Information.SerialNumber} ({Hardware.Information.Manufacturer} {Hardware.Information.Model})");
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
UpdateStatus("Preparation Client Started", message.ToString(), false, 0);
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
@@ -52,8 +53,8 @@ namespace Disco.Client
|
||||
ClientServiceException clientServiceException = ex as ClientServiceException;
|
||||
if (clientServiceException != null)
|
||||
{
|
||||
UpdateStatus(string.Format("An error occurred during {0}", clientServiceException.ServiceFeature),
|
||||
clientServiceException.Message, false, 0);
|
||||
UpdateStatus($"An error occurred during {clientServiceException.ServiceFeature}",
|
||||
clientServiceException.Message, false, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+11
-4
@@ -20,6 +20,17 @@ namespace Disco.Client
|
||||
{
|
||||
bool keepProcessing;
|
||||
|
||||
#if DEBUG
|
||||
if (args != null && args.Any(a => a.Equals("debug", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
do
|
||||
{
|
||||
Console.WriteLine("Waiting for Debugger to Attach");
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
} while (!System.Diagnostics.Debugger.IsAttached);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Initialize Environment Settings
|
||||
SetupEnvironment();
|
||||
|
||||
@@ -59,10 +70,6 @@ namespace Disco.Client
|
||||
{
|
||||
Presentation.DelayUI = true; // Add Delays on Error
|
||||
}
|
||||
|
||||
// Initialize Interop
|
||||
Interop.SystemAudit.Initialize();
|
||||
Interop.Network.Initialize();
|
||||
}
|
||||
|
||||
public static bool WhoAmI()
|
||||
|
||||
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("2.1.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.1.0.0")]
|
||||
[assembly: AssemblyVersion("2.2.16272.1003")]
|
||||
[assembly: AssemblyFileVersion("2.2.16272.1003")]
|
||||
Reference in New Issue
Block a user