/// <summary> /// Adds a new print driver in the system /// </summary> /// <param name="configFile"> The config file. </param> /// <param name="dataFile"> The data file. </param> /// <param name="dependentFiles"> The dependent files. </param> /// <param name="driverPath"> The driver path. </param> /// <param name="driverName"> The driver name. </param> /// <param name="environment"> The environment. </param> /// <param name="helpFile"> The help file. </param> /// <param name="monitorName"> The monitor name. </param> /// <param name="defaultDataType"> The default data type. </param> /// <exception cref="Win32Exception">Raised when the operation errored for whatever reason</exception> public void AddPrintDriver( string configFile, string dataFile, string[] dependentFiles, string driverPath, string driverName, string environment, string helpFile = null, string monitorName = null, string defaultDataType = "RAW") { // DRIVER_INFO_6 structure type const int DriverInfoVersion6 = 6; // Create the full path to the print directory where these files *should* be installed to (we will find out // if that is the case when attempting to add the driver as the call will fail string printDirectory = GetPrinterDriverDirectory(environment); Logger.Info("Print directory is " + printDirectory); Func <string, string> installedPath = fileName => Path.Combine(printDirectory, fileName); var di6 = new SafeNativeMethods.DRIVER_INFO_6(); di6.cVersion = 3; di6.pName = driverName; di6.pConfigFile = installedPath(configFile); di6.pDataFile = installedPath(dataFile); di6.pDependentFiles = dependentFiles.Length == 1 ? installedPath(dependentFiles[0]) : null; di6.pDriverPath = installedPath(driverPath); di6.pEnvironment = environment; di6.pHelpFile = installedPath(helpFile); di6.pMonitorName = monitorName; di6.pDefaultDataType = defaultDataType; int tryCount = 1; while (true) { try { IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SafeNativeMethods.DRIVER_INFO_6))); try { Marshal.StructureToPtr(di6, intPtr, false); if (!SafeNativeMethods.AddPrinterDriverExW( null, DriverInfoVersion6, intPtr, SafeNativeMethods.APD_COPY_NEW_FILES)) { int w32Error = Marshal.GetLastWin32Error(); throw new Win32Exception(w32Error); } Logger.Info("Print driver installed successfully with name of " + driverName + " after " + tryCount + " attempts"); break; } finally { if (IntPtr.Zero != intPtr) { Marshal.FreeHGlobal(intPtr); } } } catch (Win32Exception win32Ex) { // YUCK - on some machines, driver registration will fail the first time it is called (when run as an administrator). // This retry loop is added to try and force the issue to see if it is a timing problem (simulates several attempts by the // user to register the driver). Logger.Warn("Error caught trying to create print driver : " + win32Ex); Thread.Sleep(AddPrintDriverRetryInterval); if (tryCount > AddPrintDriverRetryLimit) { Logger.Fatal("Retry count exceeded, unable to create print driver"); throw; } tryCount++; } } }