merged in from branch issue13

This commit is contained in:
S T Chan 2019-05-29 15:42:13 -04:00
parent 213db0409d
commit 5789ee5d86
7 changed files with 119 additions and 127 deletions

View File

@ -5,7 +5,7 @@
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyCompany("Black Telescope Workshop")] [assembly: AssemblyCompany("Black Telescope Workshop")]
[assembly: AssemblyProduct("PDF Scribe")] [assembly: AssemblyProduct("PDF Scribe")]
[assembly: AssemblyCopyright("Copyright © S T Chan 2013-2018")] [assembly: AssemblyCopyright("Copyright © S T Chan 2013-2019")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
@ -22,4 +22,4 @@
// Build Number // Build Number
// Revision // Revision
// //
[assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.7.*")]

View File

@ -1,43 +1,43 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<configuration> <configuration>
<configSections> <configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="PdfScribe.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> <section name="PdfScribe.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup> </sectionGroup>
</configSections> </configSections>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup> </startup>
<system.diagnostics> <system.diagnostics>
<trace autoflush="true" /> <trace autoflush="true" />
<sources> <sources>
<source name="PdfScribe" <source name="PdfScribe"
switchName="PdfScribeAll" > switchName="PdfScribeAll" >
<listeners> <listeners>
<add name="textwriterListener" <add name="textwriterListener"
type="System.Diagnostics.TextWriterTraceListener" type="System.Diagnostics.TextWriterTraceListener"
initializeData="PdfScribe_trace.log" initializeData="PdfScribe_trace.log"
traceOutputOptions="DateTime" /> traceOutputOptions="DateTime" />
<remove name="Default" /> <remove name="Default" />
<clear /> <!-- Remove the <clear /> element to turn on tracing output --> <clear /> <!-- Remove the <clear /> element to turn on tracing output -->
</listeners> </listeners>
</source> </source>
</sources> </sources>
<switches> <switches>
<add name="PdfScribeAll" value="Verbose"/> <add name="PdfScribeAll" value="Verbose"/>
</switches> </switches>
</system.diagnostics> </system.diagnostics>
<applicationSettings> <applicationSettings>
<PdfScribe.Properties.Settings> <PdfScribe.Properties.Settings>
<setting name="OutputFile" serializeAs="String"> <setting name="OutputFile" serializeAs="String">
<value>%UserProfile%\PDFSCRIBE.PDF</value> <value>%UserProfile%\PDFSCRIBE.PDF</value>
</setting> </setting>
<setting name="AskUserForOutputFilename" serializeAs="String"> <setting name="OpenAfterCreating" serializeAs="String">
<value>True</value> <value>False</value>
</setting> </setting>
<setting name="OpenAfterCreating" serializeAs="String"> <setting name="AskUserForOutputFilename" serializeAs="String">
<value>False</value> <value>True</value>
</setting> </setting>
</PdfScribe.Properties.Settings> </PdfScribe.Properties.Settings>
</applicationSettings> </applicationSettings>
</configuration> </configuration>

View File

@ -1,10 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Windows.Forms; using System.Windows.Forms;
@ -16,13 +13,16 @@ namespace PdfScribe
#region Message constants #region Message constants
const string errorDialogCaption = "PDF Scribe"; // Error taskdialog caption text const string errorDialogCaption = "PDF Scribe"; // Error taskdialog caption text
const string errorDialogInstructionPDFGeneration = "There was a PDF generation error."; const string errorDialogInstructionPDFGeneration = "There was a PDF generation error.";
const string errorDialogInstructionCouldNotWrite = "Could not create the output file."; const string errorDialogInstructionCouldNotWrite = "Could not create the output file.";
const string errorDialogInstructionUnexpectedError = "There was an internal error. Enable tracing for details."; const string errorDialogInstructionUnexpectedError = "There was an internal error. Enable tracing for details.";
const string errorDialogOutputFilenameInvalid = "Output file path is not valid. Check the \"OutputFile\" setting in the config file.";
const string errorDialogOutputFilenameTooLong = "Output file path too long. Check the \"OutputFile\" setting in the config file.";
const string errorDialogOutputFileAccessDenied = "Access denied - check permissions on output folder.";
const string errorDialogTextFileInUse = "{0} is being used by another process."; const string errorDialogTextFileInUse = "{0} is being used by another process.";
const string errorDialogTextGhostScriptConversion = "Ghostscript error code {0}."; const string errorDialogTextGhostScriptConversion = "Ghostscript error code {0}.";
@ -33,7 +33,7 @@ namespace PdfScribe
#region Other constants #region Other constants
const string traceSourceName = "PdfScribe"; const string traceSourceName = "PdfScribe";
const string defaultOutputFilename = "PDFSCRIBE.PDF"; //const string defaultOutputFilename = "PDFSCRIBE.PDF";
#endregion #endregion
@ -76,7 +76,7 @@ namespace PdfScribe
{ {
// We couldn't delete, or create a file // We couldn't delete, or create a file
// because it was in use // because it was in use
logEventSource.TraceEvent(TraceEventType.Error, logEventSource.TraceEvent(TraceEventType.Error,
(int)TraceEventType.Error, (int)TraceEventType.Error,
errorDialogInstructionCouldNotWrite + errorDialogInstructionCouldNotWrite +
Environment.NewLine + Environment.NewLine +
@ -91,8 +91,8 @@ namespace PdfScribe
// because it was set to readonly // because it was set to readonly
// or couldn't create a file // or couldn't create a file
// because of permissions issues // because of permissions issues
logEventSource.TraceEvent(TraceEventType.Error, logEventSource.TraceEvent(TraceEventType.Error,
(int)TraceEventType.Error, (int)TraceEventType.Error,
errorDialogInstructionCouldNotWrite + errorDialogInstructionCouldNotWrite +
Environment.NewLine + Environment.NewLine +
"Exception message: " + unauthorizedEx.Message); "Exception message: " + unauthorizedEx.Message);
@ -105,8 +105,8 @@ namespace PdfScribe
catch (ExternalException ghostscriptEx) catch (ExternalException ghostscriptEx)
{ {
// Ghostscript error // Ghostscript error
logEventSource.TraceEvent(TraceEventType.Error, logEventSource.TraceEvent(TraceEventType.Error,
(int)TraceEventType.Error, (int)TraceEventType.Error,
String.Format(errorDialogTextGhostScriptConversion, ghostscriptEx.ErrorCode.ToString()) + String.Format(errorDialogTextGhostScriptConversion, ghostscriptEx.ErrorCode.ToString()) +
Environment.NewLine + Environment.NewLine +
"Exception message: " + ghostscriptEx.Message); "Exception message: " + ghostscriptEx.Message);
@ -121,7 +121,7 @@ namespace PdfScribe
{ {
File.Delete(standardInputFilename); File.Delete(standardInputFilename);
} }
catch catch
{ {
logEventSource.TraceEvent(TraceEventType.Warning, logEventSource.TraceEvent(TraceEventType.Warning,
(int)TraceEventType.Warning, (int)TraceEventType.Warning,
@ -152,7 +152,7 @@ namespace PdfScribe
bool filenameRetrieved = false; bool filenameRetrieved = false;
switch (Properties.Settings.Default.AskUserForOutputFilename) switch (Properties.Settings.Default.AskUserForOutputFilename)
{ {
case (true) : case (true):
using (SetOutputFilename dialogOwner = new SetOutputFilename()) using (SetOutputFilename dialogOwner = new SetOutputFilename())
{ {
dialogOwner.TopMost = true; dialogOwner.TopMost = true;
@ -179,8 +179,47 @@ namespace PdfScribe
} }
break; break;
default: default:
outputFile = GetOutputFilename(); try
filenameRetrieved = true; {
outputFile = GetOutputFilename();
// Test if we can write to the destination
using (FileStream newOutputFile = File.Create(outputFile))
{ }
File.Delete(outputFile);
filenameRetrieved = true;
}
catch (Exception ex) when (ex is ArgumentException ||
ex is ArgumentNullException ||
ex is NotSupportedException ||
ex is DirectoryNotFoundException)
{
logEventSource.TraceEvent(TraceEventType.Error,
(int)TraceEventType.Error,
errorDialogOutputFilenameInvalid + Environment.NewLine +
"Exception message: " + ex.Message);
DisplayErrorMessage(errorDialogCaption,
errorDialogOutputFilenameInvalid);
}
catch (PathTooLongException ex)
{
// filename is greater than 260 characters
logEventSource.TraceEvent(TraceEventType.Error,
(int)TraceEventType.Error,
errorDialogOutputFilenameTooLong + Environment.NewLine +
"Exception message: " + ex.Message);
DisplayErrorMessage(errorDialogCaption,
errorDialogOutputFilenameTooLong);
}
catch (UnauthorizedAccessException ex)
{
logEventSource.TraceEvent(TraceEventType.Error,
(int)TraceEventType.Error,
errorDialogOutputFileAccessDenied + Environment.NewLine +
"Exception message: " + ex.Message);
// Can't write to target dir
DisplayErrorMessage(errorDialogCaption,
errorDialogOutputFileAccessDenied);
}
break; break;
} }
return filenameRetrieved; return filenameRetrieved;
@ -189,58 +228,15 @@ namespace PdfScribe
private static String GetOutputFilename() private static String GetOutputFilename()
{ {
String outputFilename = Path.GetFullPath(Environment.ExpandEnvironmentVariables(Properties.Settings.Default.OutputFile));
String outputFilename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), defaultOutputFilename); // Check if there are any % characters -
if (!String.IsNullOrEmpty(Properties.Settings.Default.OutputFile) && // even though it's a legal Windows filename character,
!String.IsNullOrWhiteSpace(Properties.Settings.Default.OutputFile)) // it is a special character to Ghostscript
{ if (outputFilename.Contains("%"))
if (IsFilePathValid(Properties.Settings.Default.OutputFile)) throw new ArgumentException("OutputFile setting contains % character.");
{
outputFilename = Properties.Settings.Default.OutputFile;
}
else
{
if (IsFilePathValid(Environment.ExpandEnvironmentVariables(Properties.Settings.Default.OutputFile)))
{
outputFilename = Environment.ExpandEnvironmentVariables(Properties.Settings.Default.OutputFile);
}
}
}
else
{
logEventSource.TraceEvent(TraceEventType.Warning,
(int)TraceEventType.Warning,
String.Format("Using default output filename {0}",
outputFilename));
}
return outputFilename; return outputFilename;
} }
static bool IsFilePathValid(String filePath)
{
bool pathIsValid = false;
if (!String.IsNullOrEmpty(filePath) && filePath.Length <= 260)
{
String directoryName = Path.GetDirectoryName(filePath);
String filename = Path.GetFileName(filePath);
if (Directory.Exists(directoryName))
{
// Check for invalid filename chars
Regex containsABadCharacter = new Regex("["
+ Regex.Escape(new String(System.IO.Path.GetInvalidPathChars())) + "]");
pathIsValid = !containsABadCharacter.IsMatch(filename);
}
}
else
{
logEventSource.TraceEvent(TraceEventType.Warning,
(int)TraceEventType.Warning,
"Output filename is longer than 260 characters, or blank.");
}
return pathIsValid;
}
/// <summary> /// <summary>
/// Opens the PDF in the default viewer /// Opens the PDF in the default viewer
@ -273,7 +269,7 @@ namespace PdfScribe
MessageBoxIcon.Error, MessageBoxIcon.Error,
MessageBoxDefaultButton.Button1, MessageBoxDefaultButton.Button1,
MessageBoxOptions.DefaultDesktopOnly); MessageBoxOptions.DefaultDesktopOnly);
} }
} }
} }

View File

@ -12,7 +12,7 @@ namespace PdfScribe.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@ -32,15 +32,6 @@ namespace PdfScribe.Properties {
} }
} }
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool AskUserForOutputFilename {
get {
return ((bool)(this["AskUserForOutputFilename"]));
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()] [global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")] [global::System.Configuration.DefaultSettingValueAttribute("False")]
@ -49,5 +40,14 @@ namespace PdfScribe.Properties {
return ((bool)(this["OpenAfterCreating"])); return ((bool)(this["OpenAfterCreating"]));
} }
} }
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool AskUserForOutputFilename {
get {
return ((bool)(this["AskUserForOutputFilename"]));
}
}
} }
} }

View File

@ -5,11 +5,11 @@
<Setting Name="OutputFile" Type="System.String" Scope="Application"> <Setting Name="OutputFile" Type="System.String" Scope="Application">
<Value Profile="(Default)">%UserProfile%\PDFSCRIBE.PDF</Value> <Value Profile="(Default)">%UserProfile%\PDFSCRIBE.PDF</Value>
</Setting> </Setting>
<Setting Name="AskUserForOutputFilename" Type="System.Boolean" Scope="Application">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="OpenAfterCreating" Type="System.Boolean" Scope="Application"> <Setting Name="OpenAfterCreating" Type="System.Boolean" Scope="Application">
<Value Profile="(Default)">False</Value> <Value Profile="(Default)">False</Value>
</Setting> </Setting>
<Setting Name="AskUserForOutputFilename" Type="System.Boolean" Scope="Application">
<Value Profile="(Default)">True</Value>
</Setting>
</Settings> </Settings>
</SettingsFile> </SettingsFile>

View File

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:netfx ="http://schemas.microsoft.com/wix/NetFxExtension"> <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:netfx ="http://schemas.microsoft.com/wix/NetFxExtension">
<Product Id="{AF5F6415-3DB9-4B88-B1AE-37D4A736AD3A}" Name="PDF Scribe" Language="1033" Version="1.0.6" Manufacturer="Black Telescope Workshop" UpgradeCode="409ff0d1-1c3a-4f8d-8a5a-350705977809"> <Product Id="{DE27E86D-0514-45DF-B0CC-CFF2C1DF7038}" Name="PDF Scribe" Language="1033" Version="1.0.7" Manufacturer="Black Telescope Workshop" UpgradeCode="409ff0d1-1c3a-4f8d-8a5a-350705977809">
<Package InstallerVersion="500" Compressed="yes" InstallScope="perMachine" <Package InstallerVersion="500" Compressed="yes" InstallScope="perMachine"
Platform="x64" Platform="x64"
InstallPrivileges="elevated" InstallPrivileges="elevated"
Description="PDF Scribe Virtual Printer" Description="PDF Scribe Virtual Printer"
Comments="PDF Scribe Virtual Printer 1.0.6 installation package" Comments="PDF Scribe Virtual Printer 1.0.7 installation package"
Id="*" /> Id="*" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed."

View File

@ -1,4 +1,4 @@
# PdfScribe v1.0.6 # PdfScribe v1.0.7
PdfScribe is a PDF virtual printer. Check the [releases](https://github.com/stchan/PdfScribe/releases) page for this project to download a prebuilt MSI package. PdfScribe is a PDF virtual printer. Check the [releases](https://github.com/stchan/PdfScribe/releases) page for this project to download a prebuilt MSI package.
@ -19,8 +19,7 @@ PdfScribe links to, and distributes the following third party components:
## License ## License
Ghostscript is AGPL (more restrictive than GPLv3), so PdfScribe is bound by that license. PdfScribe is AGPL.
## Configuration ## Configuration
@ -28,7 +27,7 @@ Ghostscript is AGPL (more restrictive than GPLv3), so PdfScribe is bound by that
In the application config file (PdfScribe.exe.config), there are the following settings in the "applicationSettings" element: In the application config file (PdfScribe.exe.config), there are the following settings in the "applicationSettings" element:
* ****AskUserForOutputFilename**** - set value to *true* if you want PdfScribe to ask the user where to save the PDF. * ****AskUserForOutputFilename**** - set value to *true* if you want PdfScribe to ask the user where to save the PDF.
* ****OutputFile**** - if there is a constant filename you want the PDF to be saved to, set its value here. Environment variables can be used. PdfScribe will overwrite each time. This setting is ignored if **AskUserForOutputFilename** is set to *true*. * ****OutputFile**** - if there is a constant filename you want the PDF to be saved to, set its value here. Environment variables can be used. PdfScribe will overwrite each time. This setting is ignored if **AskUserForOutputFilename** is set to *true*. Note that a literal % character cannot be used even though it is legal in a Windows filename.
* ****OpenAfterCreating**** - set value to *true* if you want the PDF automatically opened with the default viewer. This setting is ignored if the file extension is not .PDF * ****OpenAfterCreating**** - set value to *true* if you want the PDF automatically opened with the default viewer. This setting is ignored if the file extension is not .PDF
## To do ## To do
@ -39,6 +38,3 @@ In the application config file (PdfScribe.exe.config), there are the following s
* Allow selection of page sizes other than default * Allow selection of page sizes other than default
* Watermarking output * Watermarking output