2013-12-12 09:52:42 +08:00
using System ;
using System.Collections.Generic ;
using System.ComponentModel ;
2013-12-19 12:11:39 +08:00
using System.Diagnostics ;
2013-12-12 09:52:42 +08:00
using System.IO ;
using System.Runtime.InteropServices ;
using System.Linq ;
using System.Text ;
2013-12-14 09:31:31 +08:00
using System.Security ;
2013-12-12 09:52:42 +08:00
2013-12-14 09:31:31 +08:00
using Microsoft.Win32 ;
namespace PdfScribeCore
2013-12-12 09:52:42 +08:00
{
2013-12-19 12:11:39 +08:00
2013-12-12 09:52:42 +08:00
public class PdfScribeInstaller
{
2013-12-13 08:29:31 +08:00
#region Printer Driver Win32 API Constants
const uint DRIVER_KERNELMODE = 0x00000001 ;
const uint DRIVER_USERMODE = 0x00000002 ;
const uint APD_STRICT_UPGRADE = 0x00000001 ;
const uint APD_STRICT_DOWNGRADE = 0x00000002 ;
const uint APD_COPY_ALL_FILES = 0x00000004 ;
const uint APD_COPY_NEW_FILES = 0x00000008 ;
const uint APD_COPY_FROM_DIRECTORY = 0x00000010 ;
const uint DPD_DELETE_UNUSED_FILES = 0x00000001 ;
const uint DPD_DELETE_SPECIFIC_VERSION = 0x00000002 ;
const uint DPD_DELETE_ALL_FILES = 0x00000004 ;
2013-12-24 07:35:10 +08:00
const int WIN32_FILE_ALREADY_EXISTS = 183 ; // Returned by XcvData "AddPort" if the port already exists
2013-12-13 08:29:31 +08:00
#endregion
2013-12-20 09:04:08 +08:00
//private static readonly TraceSource logEventSource = new TraceSource("PdfScribeCore");
private readonly TraceSource logEventSource ;
private readonly String logEventSourceNameDefault = "PdfScribeCore" ;
2013-12-12 09:52:42 +08:00
const string ENVIRONMENT_64 = "Windows x64" ;
const string PRINTERNAME = "PDF Scribe" ;
const string DRIVERNAME = "PDF Scribe Virtual Printer" ;
const string HARDWAREID = "PDFScribe_Driver0101" ;
const string PORTMONITOR = "PDFSCRIBE" ;
2013-12-19 12:11:39 +08:00
const string MONITORDLL = "redmon64pdfscribe.dll" ;
2013-12-12 09:52:42 +08:00
const string PORTNAME = "PSCRIBE:" ;
const string PRINTPROCESOR = "winprint" ;
const string DRIVERMANUFACTURER = "S T Chan" ;
const string DRIVERFILE = "PSCRIPT5.DLL" ;
const string DRIVERUIFILE = "PS5UI.DLL" ;
const string DRIVERHELPFILE = "PSCRIPT.HLP" ;
const string DRIVERDATAFILE = "SCPDFPRN.PPD" ;
2013-12-19 12:11:39 +08:00
enum DriverFileIndex
{
Min = 0 ,
DriverFile = Min ,
UIFile ,
HelpFile ,
DataFile ,
Max = DataFile
} ;
readonly String [ ] printerDriverFiles = new String [ ] { DRIVERFILE , DRIVERUIFILE , DRIVERHELPFILE , DRIVERDATAFILE } ;
readonly String [ ] printerDriverDependentFiles = new String [ ] { "PSCRIPT.NTF" } ;
#region Error messages for Trace / Debug
2013-12-12 09:52:42 +08:00
2013-12-19 12:11:39 +08:00
const string FILENOTDELETED_INUSE = "{0} is being used by another process. File was not deleted." ;
const string FILENOTDELETED_UNAUTHORIZED = "{0} is read-only, or its file permissions do not allow for deletion." ;
2013-12-20 10:40:17 +08:00
const string FILENOTCOPIED_PRINTERDRIVER = "Printer driver file was not copied. Exception message: {0}" ;
2013-12-31 10:49:37 +08:00
const string FILENOTCOPIED_ALREADYEXISTS = "Destination file {0} was not copied/created - it already exists." ;
2013-12-20 10:40:17 +08:00
2013-12-19 12:11:39 +08:00
const string WIN32ERROR = "Win32 error code {0}." ;
const string NATIVE_COULDNOTENABLE64REDIRECTION = "Could not enable 64-bit file system redirection." ;
const string NATIVE_COULDNOTREVERT64REDIRECTION = "Could not revert 64-bit file system redirection." ;
2013-12-23 14:47:53 +08:00
const string INSTALL_ROLLBACK_FAILURE_AT_FUNCTION = "Partial uninstallation failure. Function {0} returned false." ;
2013-12-24 07:35:10 +08:00
const string REGISTRYCONFIG_NOT_ADDED = "Could not add port configuration to registry. Exception message: {0}" ;
const string REGISTRYCONFIG_NOT_DELETED = "Could not delete port configuration from registry. Exception message: {0}" ;
2013-12-31 10:49:37 +08:00
const String INFO_INSTALLPORTMONITOR_FAILED = "Port monitor installation failed." ;
const String INFO_INSTALLCOPYDRIVER_FAILED = "Could not copy printer driver files." ;
const String INFO_INSTALLPORT_FAILED = "Could not add redirected port." ;
const String INFO_INSTALLPRINTERDRIVER_FAILED = "Printer driver installation failed." ;
const String INFO_INSTALLPRINTER_FAILED = "Could not add printer." ;
const String INFO_INSTALLCONFIGPORT_FAILED = "Port configuration failed." ;
2013-12-19 12:11:39 +08:00
#endregion
2013-12-12 09:52:42 +08:00
2014-01-04 09:39:09 +08:00
public void AddTraceListener ( TraceListener additionalListener )
{
this . logEventSource . Listeners . Add ( additionalListener ) ;
}
2013-12-20 09:04:08 +08:00
2014-01-07 00:14:19 +08:00
2013-12-20 09:04:08 +08:00
#region Constructors
public PdfScribeInstaller ( )
{
this . logEventSource = new TraceSource ( logEventSourceNameDefault ) ;
2014-01-07 00:14:19 +08:00
this . logEventSource . Switch = new SourceSwitch ( "PdfScribeCoreAll" ) ;
2014-01-04 09:39:09 +08:00
this . logEventSource . Switch . Level = SourceLevels . All ;
2013-12-20 09:04:08 +08:00
}
2014-01-07 00:14:19 +08:00
/ *
2013-12-20 10:40:17 +08:00
/// <summary>
/// This override sets the
/// trace source to a specific name
/// </summary>
/// <param name="eventSourceName">Trace source name</param>
2013-12-20 09:04:08 +08:00
public PdfScribeInstaller ( String eventSourceName )
{
if ( ! String . IsNullOrEmpty ( eventSourceName ) )
{
this . logEventSource = new TraceSource ( eventSourceName ) ;
}
else
{
throw new ArgumentNullException ( "eventSourceName" ) ;
}
2014-01-04 09:39:09 +08:00
this . logEventSource . Switch = new SourceSwitch ( "PdfScribeCoreSwitch" ) ;
this . logEventSource . Switch . Level = SourceLevels . All ;
2013-12-20 09:04:08 +08:00
}
2014-01-07 00:14:19 +08:00
* /
2013-12-20 09:04:08 +08:00
#endregion
2013-12-12 09:52:42 +08:00
#region Port operations
2013-12-13 00:48:50 +08:00
2013-12-13 08:29:31 +08:00
#if DEBUG
2013-12-23 14:47:53 +08:00
public bool AddPdfScribePort_Test ( )
2013-12-13 08:29:31 +08:00
{
2013-12-19 12:11:39 +08:00
return AddPdfScribePort ( ) ;
2013-12-13 08:29:31 +08:00
}
#endif
2013-12-23 14:47:53 +08:00
private bool AddPdfScribePort ( )
2013-12-12 09:52:42 +08:00
{
2013-12-23 14:47:53 +08:00
bool portAdded = false ;
int portAddResult = DoXcvDataPortOperation ( PORTNAME , PORTMONITOR , "AddPort" ) ;
switch ( portAddResult )
{
case 0 :
2013-12-24 07:35:10 +08:00
case WIN32_FILE_ALREADY_EXISTS : // Port already exists - this is OK, we'll just keep using it
2013-12-23 14:47:53 +08:00
portAdded = true ;
break ;
}
return portAdded ;
2013-12-12 09:52:42 +08:00
}
2013-12-23 14:47:53 +08:00
public bool DeletePdfScribePort ( )
2013-12-12 09:52:42 +08:00
{
2013-12-23 14:47:53 +08:00
bool portDeleted = false ;
int portDeleteResult = DoXcvDataPortOperation ( PORTNAME , PORTMONITOR , "DeletePort" ) ;
switch ( portDeleteResult )
{
case 0 :
portDeleted = true ;
break ;
}
return portDeleted ;
2013-12-12 09:52:42 +08:00
}
2013-12-19 12:58:43 +08:00
/// <summary>
///
/// </summary>
/// <param name="portName"></param>
/// <param name="xcvDataOperation"></param>
/// <returns></returns>
2013-12-23 14:47:53 +08:00
/// <remarks>I can't remember the name/link of the developer who wrote this code originally,
2013-12-20 10:40:17 +08:00
/// so I can't provide a link or credit.</remarks>
2013-12-19 12:58:43 +08:00
private int DoXcvDataPortOperation ( string portName , string portMonitor , string xcvDataOperation )
2013-12-12 09:52:42 +08:00
{
int win32ErrorCode ;
PRINTER_DEFAULTS def = new PRINTER_DEFAULTS ( ) ;
def . pDatatype = null ;
def . pDevMode = IntPtr . Zero ;
def . DesiredAccess = 1 ; //Server Access Administer
IntPtr hPrinter = IntPtr . Zero ;
2013-12-19 12:58:43 +08:00
if ( NativeMethods . OpenPrinter ( ",XcvMonitor " + portMonitor , ref hPrinter , def ) ! = 0 )
2013-12-12 09:52:42 +08:00
{
if ( ! portName . EndsWith ( "\0" ) )
portName + = "\0" ; // Must be a null terminated string
// Must get the size in bytes. Rememeber .NET strings are formed by 2-byte characters
uint size = ( uint ) ( portName . Length * 2 ) ;
// Alloc memory in HGlobal to set the portName
IntPtr portPtr = Marshal . AllocHGlobal ( ( int ) size ) ;
Marshal . Copy ( portName . ToCharArray ( ) , 0 , portPtr , portName . Length ) ;
uint needed ; // Not that needed in fact...
uint xcvResult ; // Will receive de result here
NativeMethods . XcvData ( hPrinter , xcvDataOperation , portPtr , size , IntPtr . Zero , 0 , out needed , out xcvResult ) ;
NativeMethods . ClosePrinter ( hPrinter ) ;
Marshal . FreeHGlobal ( portPtr ) ;
win32ErrorCode = ( int ) xcvResult ;
}
else
{
win32ErrorCode = Marshal . GetLastWin32Error ( ) ;
}
return win32ErrorCode ;
}
#endregion
#region Port Monitor
2013-12-13 00:48:50 +08:00
/// <summary>
/// Adds the PDF Scribe port monitor
/// </summary>
/// <param name="monitorFilePath">Directory where the uninstalled monitor dll is located</param>
/// <returns>true if the monitor is installed, false if install failed</returns>
public bool AddPdfScribePortMonitor ( String monitorFilePath )
2013-12-12 09:52:42 +08:00
{
bool monitorAdded = false ;
IntPtr oldRedirectValue = IntPtr . Zero ;
try
{
2013-12-13 00:48:50 +08:00
oldRedirectValue = DisableWow64Redirection ( ) ;
if ( ! DoesMonitorExist ( PORTMONITOR ) )
2013-12-12 09:52:42 +08:00
{
// Copy the monitor DLL to
// the system directory
2013-12-13 00:48:50 +08:00
String fileSourcePath = Path . Combine ( monitorFilePath , MONITORDLL ) ;
String fileDestinationPath = Path . Combine ( Environment . SystemDirectory , MONITORDLL ) ;
2013-12-13 08:29:31 +08:00
try
{
File . Copy ( fileSourcePath , fileDestinationPath , true ) ;
}
catch ( IOException )
{
// File in use, log -
// this is OK because it means the file is already there
}
2013-12-12 09:52:42 +08:00
MONITOR_INFO_2 newMonitor = new MONITOR_INFO_2 ( ) ;
2013-12-13 00:48:50 +08:00
newMonitor . pName = PORTMONITOR ;
2013-12-12 09:52:42 +08:00
newMonitor . pEnvironment = ENVIRONMENT_64 ;
2013-12-13 00:48:50 +08:00
newMonitor . pDLLName = MONITORDLL ;
2013-12-12 09:52:42 +08:00
if ( ! AddPortMonitor ( newMonitor ) )
2013-12-20 10:40:17 +08:00
logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
String . Format ( "Could not add port monitor {0}" , PORTMONITOR ) + Environment . NewLine +
String . Format ( WIN32ERROR , Marshal . GetLastWin32Error ( ) . ToString ( ) ) ) ;
2013-12-12 09:52:42 +08:00
else
monitorAdded = true ;
}
2013-12-20 10:40:17 +08:00
else
{
// Monitor already installed -
// log it, and keep going
logEventSource . TraceEvent ( TraceEventType . Warning ,
( int ) TraceEventType . Warning ,
String . Format ( "Port monitor {0} already installed." , PORTMONITOR ) ) ;
monitorAdded = true ;
}
2013-12-12 09:52:42 +08:00
}
finally
{
2013-12-13 00:48:50 +08:00
if ( oldRedirectValue ! = IntPtr . Zero ) RevertWow64Redirection ( oldRedirectValue ) ;
2013-12-12 09:52:42 +08:00
}
return monitorAdded ;
}
2013-12-13 00:48:50 +08:00
/// <summary>
/// Disables WOW64 system directory file redirection
/// if the current process is both
2013-12-22 07:03:25 +08:00
/// 32-bit, and running on a 64-bit OS -
/// Compiling for 64-bit OS, and setting the install dir to "ProgramFiles64"
/// should ensure this code never runs in production
2013-12-13 00:48:50 +08:00
/// </summary>
/// <returns>A Handle, which should be retained to reenable redirection</returns>
private IntPtr DisableWow64Redirection ( )
{
IntPtr oldValue = IntPtr . Zero ;
if ( Environment . Is64BitOperatingSystem & & ! Environment . Is64BitProcess )
if ( ! NativeMethods . Wow64DisableWow64FsRedirection ( ref oldValue ) )
throw new Win32Exception ( Marshal . GetLastWin32Error ( ) , "Could not disable Wow64 file system redirection." ) ;
return oldValue ;
}
/// <summary>
/// Reenables WOW64 system directory file redirection
/// if the current process is both
2013-12-22 07:03:25 +08:00
/// 32-bit, and running on a 64-bit OS -
/// Compiling for 64-bit OS, and setting the install dir to "ProgramFiles64"
/// should ensure this code never runs in production
2013-12-13 00:48:50 +08:00
/// </summary>
/// <param name="oldValue">A Handle value - should be retained from call to <see cref="DisableWow64Redirection"/></param>
private void RevertWow64Redirection ( IntPtr oldValue )
{
if ( Environment . Is64BitOperatingSystem & & ! Environment . Is64BitProcess )
{
if ( ! NativeMethods . Wow64RevertWow64FsRedirection ( oldValue ) )
{
throw new Win32Exception ( Marshal . GetLastWin32Error ( ) , "Could not reenable Wow64 file system redirection." ) ;
}
}
}
/// <summary>
/// Removes the PDF Scribe port monitor
/// </summary>
/// <returns>true if monitor successfully removed, false if removal failed</returns>
public bool RemovePdfScribePortMonitor ( )
2013-12-12 09:52:42 +08:00
{
bool monitorRemoved = false ;
2013-12-13 00:48:50 +08:00
if ( ( NativeMethods . DeleteMonitor ( null , ENVIRONMENT_64 , PORTMONITOR ) ) ! = 0 )
2013-12-23 14:47:53 +08:00
{
2013-12-12 09:52:42 +08:00
monitorRemoved = true ;
2013-12-23 14:47:53 +08:00
// Try to remove the monitor DLL now
if ( ! DeletePdfScribePortMonitorDll ( ) )
{
logEventSource . TraceEvent ( TraceEventType . Warning ,
( int ) TraceEventType . Warning ,
"Could not remove port monitor dll." ) ;
}
}
2013-12-12 09:52:42 +08:00
return monitorRemoved ;
}
2013-12-19 12:11:39 +08:00
private bool DeletePdfScribePortMonitorDll ( )
{
return DeletePortMonitorDll ( MONITORDLL ) ;
}
private bool DeletePortMonitorDll ( String monitorDll )
{
bool monitorDllRemoved = false ;
String monitorDllFullPathname = String . Empty ;
IntPtr oldRedirectValue = IntPtr . Zero ;
try
{
oldRedirectValue = DisableWow64Redirection ( ) ;
monitorDllFullPathname = Path . Combine ( Environment . SystemDirectory , monitorDll ) ;
File . Delete ( monitorDllFullPathname ) ;
monitorDllRemoved = true ;
}
catch ( Win32Exception windows32Ex )
{
// This one is likely very bad -
// log and rethrow so we don't continue
// to try to uninstall
logEventSource . TraceEvent ( TraceEventType . Critical ,
( int ) TraceEventType . Critical ,
NATIVE_COULDNOTENABLE64REDIRECTION + String . Format ( WIN32ERROR , windows32Ex . NativeErrorCode . ToString ( ) ) ) ;
throw ;
}
catch ( IOException )
{
// File still in use
logEventSource . TraceEvent ( TraceEventType . Error , ( int ) TraceEventType . Error , String . Format ( FILENOTDELETED_INUSE , monitorDllFullPathname ) ) ;
}
catch ( UnauthorizedAccessException )
{
// File is readonly, or file permissions do not allow delete
logEventSource . TraceEvent ( TraceEventType . Error , ( int ) TraceEventType . Error , String . Format ( FILENOTDELETED_INUSE , monitorDllFullPathname ) ) ;
}
finally
{
try
{
if ( oldRedirectValue ! = IntPtr . Zero ) RevertWow64Redirection ( oldRedirectValue ) ;
}
catch ( Win32Exception windows32Ex )
{
// Couldn't turn file redirection back on -
// this is not good
logEventSource . TraceEvent ( TraceEventType . Critical ,
( int ) TraceEventType . Critical ,
NATIVE_COULDNOTREVERT64REDIRECTION + String . Format ( WIN32ERROR , windows32Ex . NativeErrorCode . ToString ( ) ) ) ;
throw ;
}
}
return monitorDllRemoved ;
}
2013-12-12 09:52:42 +08:00
private bool AddPortMonitor ( MONITOR_INFO_2 newMonitor )
{
bool monitorAdded = false ;
if ( ( NativeMethods . AddMonitor ( null , 2 , ref newMonitor ) ! = 0 ) )
{
monitorAdded = true ;
}
return monitorAdded ;
}
private bool DeletePortMonitor ( String monitorName )
{
bool monitorDeleted = false ;
if ( ( NativeMethods . DeleteMonitor ( null , ENVIRONMENT_64 , monitorName ) ) ! = 0 )
{
monitorDeleted = true ;
}
return monitorDeleted ;
}
private bool DoesMonitorExist ( String monitorName )
{
bool monitorExists = false ;
List < MONITOR_INFO_2 > portMonitors = EnumerateMonitors ( ) ;
foreach ( MONITOR_INFO_2 portMonitor in portMonitors )
{
if ( portMonitor . pName = = monitorName )
{
monitorExists = true ;
break ;
}
}
return monitorExists ;
}
2013-12-24 07:35:10 +08:00
2013-12-12 09:52:42 +08:00
public List < MONITOR_INFO_2 > EnumerateMonitors ( )
{
List < MONITOR_INFO_2 > portMonitors = new List < MONITOR_INFO_2 > ( ) ;
uint pcbNeeded = 0 ;
uint pcReturned = 0 ;
if ( ! NativeMethods . EnumMonitors ( null , 2 , IntPtr . Zero , 0 , ref pcbNeeded , ref pcReturned ) )
{
IntPtr pMonitors = Marshal . AllocHGlobal ( ( int ) pcbNeeded ) ;
if ( NativeMethods . EnumMonitors ( null , 2 , pMonitors , pcbNeeded , ref pcbNeeded , ref pcReturned ) )
{
IntPtr currentMonitor = pMonitors ;
for ( int i = 0 ; i < pcReturned ; i + + )
{
portMonitors . Add ( ( MONITOR_INFO_2 ) Marshal . PtrToStructure ( currentMonitor , typeof ( MONITOR_INFO_2 ) ) ) ;
2017-11-03 11:05:35 +08:00
currentMonitor = IntPtr . Add ( currentMonitor , Marshal . SizeOf ( typeof ( MONITOR_INFO_2 ) ) ) ;
2013-12-12 09:52:42 +08:00
}
Marshal . FreeHGlobal ( pMonitors ) ;
}
else
{
2013-12-24 07:35:10 +08:00
// Failed to retrieve enumerated monitors
throw new Win32Exception ( Marshal . GetLastWin32Error ( ) , "Could not enumerate port monitors." ) ;
2013-12-12 09:52:42 +08:00
}
}
else
{
2013-12-24 07:35:10 +08:00
throw new Win32Exception ( Marshal . GetLastWin32Error ( ) , "Call to EnumMonitors in winspool.drv succeeded with a zero size buffer - unexpected error." ) ;
2013-12-12 09:52:42 +08:00
}
return portMonitors ;
}
#endregion
#region Printer Install
public String RetrievePrinterDriverDirectory ( )
{
StringBuilder driverDirectory = new StringBuilder ( 1024 ) ;
int dirSizeInBytes = 0 ;
if ( ! NativeMethods . GetPrinterDriverDirectory ( null ,
null ,
1 ,
driverDirectory ,
1024 ,
ref dirSizeInBytes ) )
2013-12-23 14:47:53 +08:00
throw new DirectoryNotFoundException ( "Could not retrieve printer driver directory." ) ;
2013-12-12 09:52:42 +08:00
return driverDirectory . ToString ( ) ;
}
2013-12-23 14:47:53 +08:00
delegate bool undoInstall ( ) ;
2013-12-13 00:48:50 +08:00
/// <summary>
/// Installs the port monitor, port,
/// printer drivers, and PDF Scribe virtual printer
/// </summary>
/// <param name="driverSourceDirectory">Directory where the uninstalled printer driver files are located</param>
/// <param name="driverFilesToCopy">An array containing the printer driver's filenames</param>
/// <param name="dependentFilesToCopy">An array containing dependent filenames</param>
2013-12-24 07:35:10 +08:00
/// <returns>true if installation suceeds, false if failed</returns>
2014-01-01 07:17:02 +08:00
public bool InstallPdfScribePrinter ( String driverSourceDirectory ,
String outputHandlerCommand ,
String outputHandlerArguments )
2013-12-12 09:52:42 +08:00
{
2013-12-19 12:11:39 +08:00
2013-12-12 09:52:42 +08:00
bool printerInstalled = false ;
2013-12-31 10:49:37 +08:00
2013-12-23 14:47:53 +08:00
Stack < undoInstall > undoInstallActions = new Stack < undoInstall > ( ) ;
2013-12-19 12:11:39 +08:00
2013-12-12 09:52:42 +08:00
String driverDirectory = RetrievePrinterDriverDirectory ( ) ;
2013-12-24 07:35:10 +08:00
undoInstallActions . Push ( this . DeletePdfScribePortMonitorDll ) ;
2013-12-13 08:29:31 +08:00
if ( AddPdfScribePortMonitor ( driverSourceDirectory ) )
2013-12-12 09:52:42 +08:00
{
2014-01-04 09:39:09 +08:00
this . logEventSource . TraceEvent ( TraceEventType . Verbose ,
( int ) TraceEventType . Verbose ,
"Port monitor successfully installed." ) ;
2013-12-24 07:35:10 +08:00
undoInstallActions . Push ( this . RemovePdfScribePortMonitor ) ;
2013-12-19 12:11:39 +08:00
if ( CopyPrinterDriverFiles ( driverSourceDirectory , printerDriverFiles . Concat ( printerDriverDependentFiles ) . ToArray ( ) ) )
2013-12-12 09:52:42 +08:00
{
2014-01-04 09:39:09 +08:00
this . logEventSource . TraceEvent ( TraceEventType . Verbose ,
( int ) TraceEventType . Verbose ,
"Printer drivers copied or already exist." ) ;
2013-12-23 14:47:53 +08:00
undoInstallActions . Push ( this . RemovePdfScribePortMonitor ) ;
if ( AddPdfScribePort ( ) )
2013-12-12 09:52:42 +08:00
{
2014-01-04 09:39:09 +08:00
this . logEventSource . TraceEvent ( TraceEventType . Verbose ,
( int ) TraceEventType . Verbose ,
"Redirection port added." ) ;
2013-12-23 14:47:53 +08:00
undoInstallActions . Push ( this . RemovePDFScribePrinterDriver ) ;
2013-12-19 12:11:39 +08:00
if ( InstallPdfScribePrinterDriver ( ) )
2013-12-12 09:52:42 +08:00
{
2014-01-04 09:39:09 +08:00
this . logEventSource . TraceEvent ( TraceEventType . Verbose ,
( int ) TraceEventType . Verbose ,
"Printer driver installed." ) ;
2013-12-23 14:47:53 +08:00
undoInstallActions . Push ( this . DeletePdfScribePrinter ) ;
2013-12-14 09:31:31 +08:00
if ( AddPdfScribePrinter ( ) )
2013-12-19 12:11:39 +08:00
{
2014-01-04 09:39:09 +08:00
this . logEventSource . TraceEvent ( TraceEventType . Verbose ,
( int ) TraceEventType . Verbose ,
"Virtual printer installed." ) ;
2013-12-23 14:47:53 +08:00
undoInstallActions . Push ( this . RemovePdfScribePortConfig ) ;
2014-01-01 07:17:02 +08:00
if ( ConfigurePdfScribePort ( outputHandlerCommand , outputHandlerArguments ) )
2014-01-04 09:39:09 +08:00
{
this . logEventSource . TraceEvent ( TraceEventType . Verbose ,
( int ) TraceEventType . Verbose ,
"Printer configured." ) ;
2013-12-19 12:11:39 +08:00
printerInstalled = true ;
2014-01-04 09:39:09 +08:00
}
2013-12-19 12:11:39 +08:00
else
// Failed to configure port
2013-12-31 10:49:37 +08:00
this . logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
INFO_INSTALLCONFIGPORT_FAILED ) ;
2013-12-19 12:11:39 +08:00
}
else
// Failed to install printer
2013-12-31 10:49:37 +08:00
this . logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
INFO_INSTALLPRINTER_FAILED ) ;
2013-12-12 09:52:42 +08:00
}
2013-12-19 12:11:39 +08:00
else
// Failed to install printer driver
2013-12-31 10:49:37 +08:00
this . logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
INFO_INSTALLPRINTERDRIVER_FAILED ) ;
2013-12-19 12:11:39 +08:00
}
else
// Failed to add printer port
2013-12-31 10:49:37 +08:00
this . logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
INFO_INSTALLPORT_FAILED ) ;
2013-12-12 09:52:42 +08:00
}
2013-12-19 12:11:39 +08:00
else
//Failed to copy printer driver files
2013-12-31 10:49:37 +08:00
this . logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
INFO_INSTALLCOPYDRIVER_FAILED ) ;
2013-12-19 12:11:39 +08:00
}
else
//Failed to add port monitor
2013-12-31 10:49:37 +08:00
this . logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
INFO_INSTALLPORTMONITOR_FAILED ) ;
2013-12-23 14:47:53 +08:00
if ( printerInstalled = = false )
{
// Printer installation failed -
// undo all the install steps
while ( undoInstallActions . Count > 0 )
{
undoInstall undoAction = undoInstallActions . Pop ( ) ;
try
{
if ( ! undoAction ( ) )
{
this . logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
String . Format ( INSTALL_ROLLBACK_FAILURE_AT_FUNCTION , undoAction . Method . Name ) ) ;
}
}
catch ( Win32Exception win32Ex )
{
this . logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
String . Format ( INSTALL_ROLLBACK_FAILURE_AT_FUNCTION , undoAction . Method . Name ) +
String . Format ( WIN32ERROR , win32Ex . ErrorCode . ToString ( ) ) ) ;
}
}
}
2014-01-04 09:39:09 +08:00
this . logEventSource . Flush ( ) ;
2013-12-12 09:52:42 +08:00
return printerInstalled ;
}
2013-12-13 08:29:31 +08:00
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool UninstallPdfScribePrinter ( )
{
2013-12-31 10:49:37 +08:00
bool printerUninstalledCleanly = true ;
2013-12-23 14:47:53 +08:00
if ( ! DeletePdfScribePrinter ( ) )
2013-12-31 10:49:37 +08:00
printerUninstalledCleanly = false ;
2013-12-23 14:47:53 +08:00
if ( ! RemovePDFScribePrinterDriver ( ) )
2013-12-31 10:49:37 +08:00
printerUninstalledCleanly = false ;
2013-12-23 14:47:53 +08:00
if ( ! DeletePdfScribePort ( ) )
2013-12-31 10:49:37 +08:00
printerUninstalledCleanly = false ;
2013-12-23 14:47:53 +08:00
if ( ! RemovePdfScribePortMonitor ( ) )
2013-12-31 10:49:37 +08:00
printerUninstalledCleanly = false ;
2013-12-23 14:47:53 +08:00
if ( ! RemovePdfScribePortConfig ( ) )
2013-12-31 10:49:37 +08:00
printerUninstalledCleanly = false ;
2013-12-24 07:35:10 +08:00
DeletePdfScribePortMonitorDll ( ) ;
2013-12-31 10:49:37 +08:00
return printerUninstalledCleanly ;
2013-12-13 08:29:31 +08:00
}
2013-12-12 09:52:42 +08:00
private bool CopyPrinterDriverFiles ( String driverSourceDirectory ,
String [ ] filesToCopy )
{
bool filesCopied = false ;
String driverDestinationDirectory = RetrievePrinterDriverDirectory ( ) ;
try
{
for ( int loop = 0 ; loop < filesToCopy . Length ; loop + + )
{
String fileSourcePath = Path . Combine ( driverSourceDirectory , filesToCopy [ loop ] ) ;
String fileDestinationPath = Path . Combine ( driverDestinationDirectory , filesToCopy [ loop ] ) ;
try
{
File . Copy ( fileSourcePath , fileDestinationPath ) ;
}
2013-12-20 10:40:17 +08:00
catch ( PathTooLongException )
{
// Will be caught by outer
// IOException catch block
throw ;
}
catch ( DirectoryNotFoundException )
{
// Will be caught by outer
// IOException catch block
throw ;
}
catch ( FileNotFoundException )
{
// Will be caught by outer
// IOException catch block
throw ;
}
2013-12-12 09:52:42 +08:00
catch ( IOException )
{
2013-12-20 10:40:17 +08:00
// Just keep going - file was already there
// Not really a problem
2013-12-31 10:49:37 +08:00
logEventSource . TraceEvent ( TraceEventType . Verbose ,
( int ) TraceEventType . Verbose ,
String . Format ( FILENOTCOPIED_ALREADYEXISTS , fileDestinationPath ) ) ;
2013-12-12 09:52:42 +08:00
continue ;
}
}
filesCopied = true ;
}
2013-12-20 10:40:17 +08:00
catch ( IOException ioEx )
{
logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
String . Format ( FILENOTCOPIED_PRINTERDRIVER , ioEx . Message ) ) ;
}
catch ( UnauthorizedAccessException unauthorizedEx )
{
logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
String . Format ( FILENOTCOPIED_PRINTERDRIVER , unauthorizedEx . Message ) ) ;
}
catch ( NotSupportedException notSupportedEx )
{
logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
String . Format ( FILENOTCOPIED_PRINTERDRIVER , notSupportedEx . Message ) ) ;
}
2013-12-12 09:52:42 +08:00
return filesCopied ;
}
private bool DeletePrinterDriverFiles ( String driverSourceDirectory ,
String [ ] filesToDelete )
{
bool allFilesDeleted = true ;
for ( int loop = 0 ; loop < filesToDelete . Length ; loop + + )
{
try
{
File . Delete ( Path . Combine ( driverSourceDirectory , filesToDelete [ loop ] ) ) ;
}
catch
{
allFilesDeleted = false ;
}
}
return allFilesDeleted ;
}
2013-12-19 12:11:39 +08:00
2013-12-24 07:35:10 +08:00
#if DEBUG
public bool IsPrinterDriverInstalled_Test ( String driverName )
{
return IsPrinterDriverInstalled ( driverName ) ;
}
#endif
private bool IsPrinterDriverInstalled ( String driverName )
{
bool driverInstalled = false ;
List < DRIVER_INFO_6 > installedDrivers = EnumeratePrinterDrivers ( ) ;
foreach ( DRIVER_INFO_6 printerDriver in installedDrivers )
{
if ( printerDriver . pName = = driverName )
{
driverInstalled = true ;
break ;
}
}
return driverInstalled ;
}
public List < DRIVER_INFO_6 > EnumeratePrinterDrivers ( )
2013-12-12 09:52:42 +08:00
{
2013-12-24 07:35:10 +08:00
List < DRIVER_INFO_6 > installedPrinterDrivers = new List < DRIVER_INFO_6 > ( ) ;
2013-12-12 09:52:42 +08:00
2013-12-24 07:35:10 +08:00
uint pcbNeeded = 0 ;
uint pcReturned = 0 ;
2013-12-12 09:52:42 +08:00
2013-12-24 07:35:10 +08:00
if ( ! NativeMethods . EnumPrinterDrivers ( null , ENVIRONMENT_64 , 6 , IntPtr . Zero , 0 , ref pcbNeeded , ref pcReturned ) )
2013-12-12 09:52:42 +08:00
{
2013-12-24 07:35:10 +08:00
IntPtr pDrivers = Marshal . AllocHGlobal ( ( int ) pcbNeeded ) ;
if ( NativeMethods . EnumPrinterDrivers ( null , ENVIRONMENT_64 , 6 , pDrivers , pcbNeeded , ref pcbNeeded , ref pcReturned ) )
2013-12-12 09:52:42 +08:00
{
2013-12-24 07:35:10 +08:00
IntPtr currentDriver = pDrivers ;
for ( int loop = 0 ; loop < pcReturned ; loop + + )
{
installedPrinterDrivers . Add ( ( DRIVER_INFO_6 ) Marshal . PtrToStructure ( currentDriver , typeof ( DRIVER_INFO_6 ) ) ) ;
2017-11-03 11:05:35 +08:00
//currentDriver = (IntPtr)(currentDriver.ToInt32() + Marshal.SizeOf(typeof(DRIVER_INFO_6)));
currentDriver = IntPtr . Add ( currentDriver , Marshal . SizeOf ( typeof ( DRIVER_INFO_6 ) ) ) ;
2013-12-24 07:35:10 +08:00
}
Marshal . FreeHGlobal ( pDrivers ) ;
}
else
{
// Failed to enumerate printer drivers
throw new Win32Exception ( Marshal . GetLastWin32Error ( ) , "Could not enumerate printer drivers." ) ;
2013-12-12 09:52:42 +08:00
}
}
else
{
2013-12-24 07:35:10 +08:00
throw new Win32Exception ( Marshal . GetLastWin32Error ( ) , "Call to EnumPrinterDrivers in winspool.drv succeeded with a zero size buffer - unexpected error." ) ;
2013-12-12 09:52:42 +08:00
}
2013-12-19 12:11:39 +08:00
2013-12-24 07:35:10 +08:00
return installedPrinterDrivers ;
}
2013-12-19 12:11:39 +08:00
2013-12-24 07:35:10 +08:00
private bool InstallPdfScribePrinterDriver ( )
{
bool pdfScribePrinterDriverInstalled = false ;
2013-12-12 09:52:42 +08:00
2014-01-04 09:39:09 +08:00
if ( ! IsPrinterDriverInstalled ( DRIVERNAME ) )
2013-12-24 07:35:10 +08:00
{
String driverSourceDirectory = RetrievePrinterDriverDirectory ( ) ;
2013-12-12 09:52:42 +08:00
2013-12-24 07:35:10 +08:00
StringBuilder nullTerminatedDependentFiles = new StringBuilder ( ) ;
if ( printerDriverDependentFiles . Length > 0 )
{
for ( int loop = 0 ; loop < = printerDriverDependentFiles . GetUpperBound ( 0 ) ; loop + + )
{
nullTerminatedDependentFiles . Append ( printerDriverDependentFiles [ loop ] ) ;
nullTerminatedDependentFiles . Append ( "\0" ) ;
}
nullTerminatedDependentFiles . Append ( "\0" ) ;
}
else
{
nullTerminatedDependentFiles . Append ( "\0\0" ) ;
}
DRIVER_INFO_6 printerDriverInfo = new DRIVER_INFO_6 ( ) ;
2013-12-19 12:11:39 +08:00
2013-12-24 07:35:10 +08:00
printerDriverInfo . cVersion = 3 ;
printerDriverInfo . pName = DRIVERNAME ;
printerDriverInfo . pEnvironment = ENVIRONMENT_64 ;
printerDriverInfo . pDriverPath = Path . Combine ( driverSourceDirectory , DRIVERFILE ) ;
printerDriverInfo . pConfigFile = Path . Combine ( driverSourceDirectory , DRIVERUIFILE ) ;
printerDriverInfo . pHelpFile = Path . Combine ( driverSourceDirectory , DRIVERHELPFILE ) ;
printerDriverInfo . pDataFile = Path . Combine ( driverSourceDirectory , DRIVERDATAFILE ) ;
printerDriverInfo . pDependentFiles = nullTerminatedDependentFiles . ToString ( ) ;
printerDriverInfo . pMonitorName = PORTMONITOR ;
printerDriverInfo . pDefaultDataType = String . Empty ;
printerDriverInfo . dwlDriverVersion = 0x0000000200000000 U ;
printerDriverInfo . pszMfgName = DRIVERMANUFACTURER ;
printerDriverInfo . pszHardwareID = HARDWAREID ;
printerDriverInfo . pszProvider = DRIVERMANUFACTURER ;
pdfScribePrinterDriverInstalled = InstallPrinterDriver ( ref printerDriverInfo ) ;
}
else
{
pdfScribePrinterDriverInstalled = true ; // Driver is already installed, we'll just use the installed driver
}
return pdfScribePrinterDriverInstalled ;
2013-12-19 12:11:39 +08:00
}
private bool InstallPrinterDriver ( ref DRIVER_INFO_6 printerDriverInfo )
{
bool printerDriverInstalled = false ;
2013-12-12 09:52:42 +08:00
printerDriverInstalled = NativeMethods . AddPrinterDriver ( null , 6 , ref printerDriverInfo ) ;
if ( printerDriverInstalled = = false )
{
2013-12-23 14:47:53 +08:00
//int lastWinError = Marshal.GetLastWin32Error();
//throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not add printer PDF Scribe printer driver.");
logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
2014-01-28 12:33:27 +08:00
"Could not add PDF Scribe printer driver. " +
2013-12-23 14:47:53 +08:00
String . Format ( WIN32ERROR , Marshal . GetLastWin32Error ( ) . ToString ( ) ) ) ;
2013-12-12 09:52:42 +08:00
}
return printerDriverInstalled ;
}
2013-12-23 14:47:53 +08:00
/// <summary>
///
/// </summary>
/// <returns></returns>
2013-12-13 08:29:31 +08:00
public bool RemovePDFScribePrinterDriver ( )
{
2013-12-14 09:31:31 +08:00
bool driverRemoved = NativeMethods . DeletePrinterDriverEx ( null , ENVIRONMENT_64 , DRIVERNAME , DPD_DELETE_UNUSED_FILES , 3 ) ;
if ( ! driverRemoved )
2013-12-13 08:29:31 +08:00
{
2013-12-23 14:47:53 +08:00
logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
2014-01-28 12:33:27 +08:00
"Could not remove PDF Scribe printer driver. " +
2013-12-23 14:47:53 +08:00
String . Format ( WIN32ERROR , Marshal . GetLastWin32Error ( ) . ToString ( ) ) ) ;
2013-12-13 08:29:31 +08:00
}
2013-12-14 09:31:31 +08:00
return driverRemoved ;
2013-12-13 08:29:31 +08:00
}
2013-12-12 09:52:42 +08:00
private bool AddPdfScribePrinter ( )
{
bool printerAdded = false ;
PRINTER_INFO_2 pdfScribePrinter = new PRINTER_INFO_2 ( ) ;
pdfScribePrinter . pServerName = null ;
pdfScribePrinter . pPrinterName = PRINTERNAME ;
pdfScribePrinter . pPortName = PORTNAME ;
pdfScribePrinter . pDriverName = DRIVERNAME ;
pdfScribePrinter . pPrintProcessor = PRINTPROCESOR ;
pdfScribePrinter . pDatatype = "RAW" ;
2019-05-31 14:26:31 +08:00
pdfScribePrinter . Attributes = 0x00000040 ;
2013-12-12 09:52:42 +08:00
2013-12-23 14:47:53 +08:00
int pdfScribePrinterHandle = NativeMethods . AddPrinter ( null , 2 , ref pdfScribePrinter ) ;
if ( pdfScribePrinterHandle ! = 0 )
2013-12-12 09:52:42 +08:00
{
// Added ok
2013-12-23 14:47:53 +08:00
int closeCode = NativeMethods . ClosePrinter ( ( IntPtr ) pdfScribePrinterHandle ) ;
2013-12-12 09:52:42 +08:00
printerAdded = true ;
}
else
{
2013-12-23 14:47:53 +08:00
logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
2014-01-28 12:33:27 +08:00
"Could not add PDF Scribe virtual printer. " +
2013-12-23 14:47:53 +08:00
String . Format ( WIN32ERROR , Marshal . GetLastWin32Error ( ) . ToString ( ) ) ) ;
2013-12-12 09:52:42 +08:00
}
return printerAdded ;
}
2013-12-13 08:29:31 +08:00
private bool DeletePdfScribePrinter ( )
{
bool printerDeleted = false ;
PRINTER_DEFAULTS scribeDefaults = new PRINTER_DEFAULTS ( ) ;
scribeDefaults . DesiredAccess = 0x000F000C ; // All access
scribeDefaults . pDatatype = null ;
scribeDefaults . pDevMode = IntPtr . Zero ;
IntPtr scribeHandle = IntPtr . Zero ;
try
{
if ( NativeMethods . OpenPrinter ( PRINTERNAME , ref scribeHandle , scribeDefaults ) ! = 0 )
{
if ( NativeMethods . DeletePrinter ( scribeHandle ) )
printerDeleted = true ;
}
else
{
2013-12-23 14:47:53 +08:00
logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
2014-01-28 12:33:27 +08:00
"Could not delete PDF Scribe virtual printer. " +
2013-12-23 14:47:53 +08:00
String . Format ( WIN32ERROR , Marshal . GetLastWin32Error ( ) . ToString ( ) ) ) ;
2013-12-13 08:29:31 +08:00
}
}
finally
{
if ( scribeHandle ! = IntPtr . Zero ) NativeMethods . ClosePrinter ( scribeHandle ) ;
}
return printerDeleted ;
}
2013-12-24 07:35:10 +08:00
public bool IsPdfScribePrinterInstalled ( )
{
bool pdfScribeInstalled = false ;
PRINTER_DEFAULTS scribeDefaults = new PRINTER_DEFAULTS ( ) ;
scribeDefaults . DesiredAccess = 0x00008 ; // Use access
scribeDefaults . pDatatype = null ;
scribeDefaults . pDevMode = IntPtr . Zero ;
IntPtr scribeHandle = IntPtr . Zero ;
if ( NativeMethods . OpenPrinter ( PRINTERNAME , ref scribeHandle , scribeDefaults ) ! = 0 )
{
pdfScribeInstalled = true ;
}
else
{
int errorCode = Marshal . GetLastWin32Error ( ) ;
if ( errorCode = = 0x5 ) pdfScribeInstalled = true ; // Printer is installed, but user
// has no privileges to use it
}
return pdfScribeInstalled ;
}
2013-12-12 09:52:42 +08:00
#endregion
2013-12-24 07:35:10 +08:00
2013-12-14 09:31:31 +08:00
#region Configuration and Registry changes
#if DEBUG
public bool ConfigurePdfScribePort_Test ( )
{
return ConfigurePdfScribePort ( ) ;
}
#endif
private bool ConfigurePdfScribePort ( )
2013-12-24 07:35:10 +08:00
{
return ConfigurePdfScribePort ( String . Empty , String . Empty ) ;
}
2014-01-01 07:17:02 +08:00
2013-12-24 07:35:10 +08:00
private bool ConfigurePdfScribePort ( String commandValue ,
String argumentsValue )
2013-12-14 09:31:31 +08:00
{
bool registryChangesMade = false ;
// Add all the registry info
// for the port and monitor
2013-12-19 12:58:43 +08:00
RegistryKey portConfiguration ;
2013-12-14 09:31:31 +08:00
try
{
2013-12-19 12:58:43 +08:00
portConfiguration = Registry . LocalMachine . CreateSubKey ( "SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors\\" +
PORTMONITOR +
"\\Ports\\" + PORTNAME ) ;
2013-12-14 09:31:31 +08:00
portConfiguration . SetValue ( "Description" , "PDF Scribe" , RegistryValueKind . String ) ;
2013-12-24 07:35:10 +08:00
portConfiguration . SetValue ( "Command" , commandValue , RegistryValueKind . String ) ;
portConfiguration . SetValue ( "Arguments" , argumentsValue , RegistryValueKind . String ) ;
2013-12-23 14:47:53 +08:00
portConfiguration . SetValue ( "Printer" , PRINTERNAME , RegistryValueKind . String ) ;
2013-12-14 09:31:31 +08:00
portConfiguration . SetValue ( "Output" , 0 , RegistryValueKind . DWord ) ;
2013-12-23 14:47:53 +08:00
portConfiguration . SetValue ( "ShowWindow" , 2 , RegistryValueKind . DWord ) ;
2013-12-14 09:31:31 +08:00
portConfiguration . SetValue ( "RunUser" , 1 , RegistryValueKind . DWord ) ;
portConfiguration . SetValue ( "Delay" , 300 , RegistryValueKind . DWord ) ;
portConfiguration . SetValue ( "LogFileUse" , 0 , RegistryValueKind . DWord ) ;
portConfiguration . SetValue ( "LogFileName" , "" , RegistryValueKind . String ) ;
portConfiguration . SetValue ( "LogFileDebug" , 0 , RegistryValueKind . DWord ) ;
portConfiguration . SetValue ( "PrintError" , 0 , RegistryValueKind . DWord ) ;
registryChangesMade = true ;
}
2013-12-24 07:35:10 +08:00
catch ( UnauthorizedAccessException unauthorizedEx )
{
logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
String . Format ( REGISTRYCONFIG_NOT_ADDED , unauthorizedEx . Message ) ) ;
}
catch ( SecurityException securityEx )
{
logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
String . Format ( REGISTRYCONFIG_NOT_ADDED , securityEx . Message ) ) ;
}
2013-12-14 09:31:31 +08:00
return registryChangesMade ;
}
2013-12-18 09:36:21 +08:00
private bool RemovePdfScribePortConfig ( )
{
bool registryEntriesRemoved = false ;
try
{
Registry . LocalMachine . DeleteSubKey ( "SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors\\" +
PORTMONITOR + "\\Ports\\" + PORTNAME , false ) ;
registryEntriesRemoved = true ;
}
2013-12-24 07:35:10 +08:00
catch ( UnauthorizedAccessException unauthorizedEx )
{
logEventSource . TraceEvent ( TraceEventType . Error ,
( int ) TraceEventType . Error ,
String . Format ( REGISTRYCONFIG_NOT_DELETED , unauthorizedEx . Message ) ) ;
}
2013-12-18 09:36:21 +08:00
return registryEntriesRemoved ;
}
2013-12-14 09:31:31 +08:00
#endregion
2013-12-12 09:52:42 +08:00
}
}