ScpInstaller/ScpForm.cs (353 lines of code) (raw):

using System; using System.Collections; using System.ComponentModel; using System.Configuration.Install; using System.IO; using System.Reflection; using System.ServiceProcess; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using log4net; using ScpControl.Driver; using ScpControl.Utilities; using ScpDriver.Properties; namespace ScpDriver { public partial class ScpForm : Form { private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private bool _bthDriverConfigured; private bool _busDeviceConfigured; private bool _busDriverConfigured; private bool _ds3DriverConfigured; private bool _ds4DriverConfigured; private Difx _installer; private bool _reboot; private Cursor _saved; private bool _scpServiceConfigured; private OsType _valid = OsType.Invalid; public ScpForm() { InitializeComponent(); AppDomain.CurrentDomain.UnhandledException += (sender, args) => { Log.FatalFormat("An unhandled exception occured: {0}", args.ExceptionObject); }; try { // get absolute path to XML file var cfgFile = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty, Assembly.GetExecutingAssembly().GetName().Name + ".xml"); // deserialize file content var cfg = ScpDriver.Deserialize(cfgFile); // set display options cbService.Checked = cbService.Visible = cfg.InstallService; cbBluetooth.Checked = cbBluetooth.Visible = cfg.InstallBluetooth; cbDS3.Checked = cbDS3.Visible = cfg.InstallDualShock3; cbBus.Checked = cbBus.Visible = cfg.InstallVirtualBus; // Don't install Service if Bus not Enabled if (!cfg.InstallVirtualBus) cbService.Checked = cbService.Visible = cfg.InstallVirtualBus; } catch (Exception ex) { Log.ErrorFormat("Couldn't load configuration: {0}", ex); } } private static void Logger(DifxLog Event, int error, string description) { switch (Event) { case DifxLog.DIFXAPI_ERROR: Log.Error(description); break; case DifxLog.DIFXAPI_INFO: case DifxLog.DIFXAPI_SUCCESS: Log.Info(description); break; case DifxLog.DIFXAPI_WARNING: Log.Warn(description); break; } } private static bool Start(string service) { try { var sc = new ServiceController(service); if (sc.Status == ServiceControllerStatus.Stopped) { sc.Start(); Thread.Sleep(1000); return true; } } catch (Exception ex) { Log.ErrorFormat("Couldn't start service: {0}", ex); } return false; } private static bool Stop(string service) { try { var sc = new ServiceController(service); if (sc.Status == ServiceControllerStatus.Running) { sc.Stop(); Thread.Sleep(1000); return true; } } catch (InvalidOperationException iopex) { if (!(iopex.InnerException is Win32Exception)) { Log.ErrorFormat("Win32-Exception occured: {0}", iopex); return false; } switch (((Win32Exception) iopex.InnerException).NativeErrorCode) { case 1060: // ERROR_SERVICE_DOES_NOT_EXIST Log.Warn("Service doesn't exist, maybe it was uninstalled before"); break; default: Log.ErrorFormat("Win32-Error: {0}", (Win32Exception) iopex.InnerException); break; } } catch (Exception ex) { Log.ErrorFormat("Couldn't stop service: {0}", ex); } return false; } private void ScpForm_Load(object sender, EventArgs e) { Log.InfoFormat("SCP Driver Installer {0} [{1}]", Application.ProductVersion, DateTime.Now); _installer = Difx.Instance; _installer.OnLogEvent += Logger; var info = OsInfoHelper.OsInfo; _valid = OsInfoHelper.OsParse(info); Log.InfoFormat("{0} detected", info); if (_valid == OsType.Invalid) { btnInstall.Enabled = false; btnUninstall.Enabled = false; Log.Error("Could not find a valid configuration"); } else { btnInstall.Enabled = true; btnUninstall.Enabled = true; Log.InfoFormat("Selected {0} configuration", _valid); } Icon = Resources.Scp_All; if (!OsInfoHelper.IsVc2013Installed) { MessageBox.Show(Resources.ScpForm_VcppMissingText, Resources.ScpForm_VcppMissingHead, MessageBoxButtons.OK, MessageBoxIcon.Error); Close(); } } private async void btnInstall_Click(object sender, EventArgs e) { #region Pre-Installation _saved = Cursor; Cursor = Cursors.WaitCursor; btnInstall.Enabled = false; btnUninstall.Enabled = false; btnExit.Enabled = false; _busDeviceConfigured = false; _busDriverConfigured = false; _ds3DriverConfigured = false; _bthDriverConfigured = false; _scpServiceConfigured = false; pbRunning.Style = ProgressBarStyle.Marquee; var forceInstall = cbForce.Checked; var installBus = cbBus.Checked; var installBth = cbBluetooth.Checked; var installDs3 = cbDS3.Checked; var installDs4 = cbDs4.Checked; var installService = cbService.Checked; #endregion #region Installation await Task.Run(() => { string devPath = string.Empty, instanceId = string.Empty; try { uint result = 0; var flags = DifxFlags.DRIVER_PACKAGE_ONLY_IF_DEVICE_PRESENT; if (forceInstall) flags |= DifxFlags.DRIVER_PACKAGE_FORCE; if (installBus) { if (!Devcon.Find(Settings.Default.Ds3BusClassGuid, ref devPath, ref instanceId)) { if (Devcon.Create("System", new Guid("{4D36E97D-E325-11CE-BFC1-08002BE10318}"), "root\\ScpVBus\0\0")) { Logger(DifxLog.DIFXAPI_SUCCESS, 0, "Virtual Bus Created"); _busDeviceConfigured = true; } } bool rebootRequired; result = _installer.Install(Path.Combine(Settings.Default.InfFilePath, @"ScpVBus.inf"), flags, out rebootRequired); _reboot |= rebootRequired; if (result == 0) _busDriverConfigured = true; } if (installBth) { Invoke( (MethodInvoker) delegate { result = DriverInstaller.InstallBluetoothDongles(Handle, forceInstall); }); if (result > 0) _bthDriverConfigured = true; } if (installDs3) { Invoke( (MethodInvoker) delegate { result = DriverInstaller.InstallDualShock3Controllers(Handle, forceInstall); }); if (result > 0) _ds3DriverConfigured = true; } if (installDs4) { Invoke( (MethodInvoker) delegate { result = DriverInstaller.InstallDualShock4Controllers(Handle, forceInstall); }); if (result > 0) _ds4DriverConfigured = true; } if (installService) { IDictionary state = new Hashtable(); var service = new AssemblyInstaller(Directory.GetCurrentDirectory() + @"\ScpService.exe", null); state.Clear(); service.UseNewContext = true; service.Install(state); service.Commit(state); if (Start(Settings.Default.ScpServiceName)) Logger(DifxLog.DIFXAPI_INFO, 0, Settings.Default.ScpServiceName + " Started."); else _reboot = true; _scpServiceConfigured = true; } } catch (Win32Exception w32Ex) { switch (w32Ex.NativeErrorCode) { case 1073: // ERROR_SERVICE_EXISTS Log.WarnFormat("Service already exists, skipping installation..."); break; default: Log.ErrorFormat("Win32-Error during installation: {0}", w32Ex); break; } } catch (Exception ex) { Log.ErrorFormat("Error during installation: {0}", ex); } }); #endregion #region Post-Installation pbRunning.Style = ProgressBarStyle.Continuous; btnInstall.Enabled = true; btnUninstall.Enabled = true; btnExit.Enabled = true; Cursor = _saved; Log.Info("Install Succeeded."); if (_reboot) Log.InfoFormat("[Reboot Required]"); Log.Info("-- Install Summary --"); if (_scpServiceConfigured) Log.Info("SCP DS3 Service installed"); if (_busDeviceConfigured) Log.Info("Bus Device installed"); if (_busDriverConfigured) Log.Info("Bus Driver installed"); if (_ds3DriverConfigured) Log.Info("DS3 USB Driver installed"); if (_bthDriverConfigured) Log.Info("Bluetooth Driver installed"); if (_ds4DriverConfigured) Log.Info("DS4 USB Driver installed"); #endregion } private async void btnUninstall_Click(object sender, EventArgs e) { #region Pre-Uninstallation _saved = Cursor; Cursor = Cursors.WaitCursor; btnInstall.Enabled = false; btnUninstall.Enabled = false; btnExit.Enabled = false; _busDeviceConfigured = false; _busDriverConfigured = false; _ds3DriverConfigured = false; _bthDriverConfigured = false; _scpServiceConfigured = false; pbRunning.Style = ProgressBarStyle.Marquee; #endregion #region Uninstallation await Task.Run(() => { string devPath = string.Empty, instanceId = string.Empty; try { var rebootRequired = false; if (cbService.Checked) { IDictionary state = new Hashtable(); var service = new AssemblyInstaller(Directory.GetCurrentDirectory() + @"\ScpService.exe", null); state.Clear(); service.UseNewContext = true; if (Stop(Settings.Default.ScpServiceName)) { Logger(DifxLog.DIFXAPI_INFO, 0, Settings.Default.ScpServiceName + " Stopped."); } service.Uninstall(state); _scpServiceConfigured = true; } if (cbBluetooth.Checked) { DriverInstaller.UninstallBluetoothDongles(ref rebootRequired); _reboot |= rebootRequired; } if (cbDS3.Checked) { DriverInstaller.UninstallDualShock3Controllers(ref rebootRequired); _reboot |= rebootRequired; } if (cbDs4.Checked) { DriverInstaller.UninstallDualShock4Controllers(ref rebootRequired); _reboot |= rebootRequired; } if (cbBus.Checked && Devcon.Find(Settings.Default.Ds3BusClassGuid, ref devPath, ref instanceId)) { if (Devcon.Remove(Settings.Default.Ds3BusClassGuid, devPath, instanceId)) { Logger(DifxLog.DIFXAPI_SUCCESS, 0, "Virtual Bus Removed"); _busDeviceConfigured = true; _installer.Uninstall(Path.Combine(Settings.Default.InfFilePath, @"ScpVBus.inf"), DifxFlags.DRIVER_PACKAGE_DELETE_FILES, out rebootRequired); _reboot |= rebootRequired; } else { Logger(DifxLog.DIFXAPI_ERROR, 0, "Virtual Bus Removal Failure"); } } } catch (InstallException instex) { if (!(instex.InnerException is Win32Exception)) { Log.ErrorFormat("Error during uninstallation: {0}", instex); return; } switch (((Win32Exception) instex.InnerException).NativeErrorCode) { case 1060: // ERROR_SERVICE_DOES_NOT_EXIST Log.Warn("Service doesn't exist, maybe it was uninstalled before"); break; default: Log.ErrorFormat("Win32-Error during uninstallation: {0}", (Win32Exception) instex.InnerException); break; } } catch (Exception ex) { Log.ErrorFormat("Error during uninstallation: {0}", ex); } }); #endregion #region Post-Uninstallation pbRunning.Style = ProgressBarStyle.Continuous; btnInstall.Enabled = true; btnUninstall.Enabled = true; btnExit.Enabled = true; Cursor = _saved; Log.Info("Uninstall Succeeded."); if (_reboot) Log.Info(" [Reboot Required]"); Log.Info("-- Uninstall Summary --"); if (_scpServiceConfigured) Log.Info("SCP DS3 Service uninstalled"); if (_busDeviceConfigured) Log.Info("Bus Device uninstalled"); if (_busDriverConfigured) Log.Info("Bus Driver uninstalled"); if (_ds3DriverConfigured) Log.Info("DS3 USB Driver uninstalled"); if (_bthDriverConfigured) Log.Info("Bluetooth Driver uninstalled"); #endregion } private void btnExit_Click(object sender, EventArgs e) { Close(); } } }