diff --git a/Common/Adobe_CreatePDF_icon.png b/Common/Adobe_CreatePDF_icon.png new file mode 100644 index 0000000..65fd3e5 Binary files /dev/null and b/Common/Adobe_CreatePDF_icon.png differ diff --git a/Lib/gsdll64.dll b/Lib/gsdll64.dll new file mode 100644 index 0000000..a9e4c13 Binary files /dev/null and b/Lib/gsdll64.dll differ diff --git a/PdfScribe.sln b/PdfScribe.sln index 2034de9..53f78a6 100644 --- a/PdfScribe.sln +++ b/PdfScribe.sln @@ -5,6 +5,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PdfScribeUnitTests", "PdfSc EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PdfScribeCore", "PdfScribeCore\PdfScribeCore.csproj", "{1EAD8E9A-A123-4C37-B31E-AEE1354DF003}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PdfScribe", "PdfScribe\PdfScribe.csproj", "{09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -36,6 +38,15 @@ Global {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Release|x64.Build.0 = Release|x64 {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Release|x86.ActiveCfg = Release|x86 {1EAD8E9A-A123-4C37-B31E-AEE1354DF003}.Release|x86.Build.0 = Release|x86 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Debug|Any CPU.ActiveCfg = Debug|x86 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Debug|x64.ActiveCfg = Debug|x64 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Debug|x64.Build.0 = Debug|x64 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Debug|x86.ActiveCfg = Debug|x86 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Debug|x86.Build.0 = Debug|x86 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Release|Any CPU.ActiveCfg = Release|x86 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Release|x64.ActiveCfg = Release|x86 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Release|x86.ActiveCfg = Release|x86 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PdfScribe/ActivityNotification.xaml b/PdfScribe/ActivityNotification.xaml new file mode 100644 index 0000000..7494478 --- /dev/null +++ b/PdfScribe/ActivityNotification.xaml @@ -0,0 +1,13 @@ + + + + + diff --git a/PdfScribe/ActivityNotification.xaml.cs b/PdfScribe/ActivityNotification.xaml.cs new file mode 100644 index 0000000..aac97f6 --- /dev/null +++ b/PdfScribe/ActivityNotification.xaml.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace PdfScribe +{ + /// + /// Interaction logic for ActivityNotification.xaml + /// + public partial class ActivityNotification : Window + { + public ActivityNotification() + { + InitializeComponent(); + } + } +} diff --git a/PdfScribe/App.config b/PdfScribe/App.config new file mode 100644 index 0000000..49cc43e --- /dev/null +++ b/PdfScribe/App.config @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/PdfScribe/GhostScript64.cs b/PdfScribe/GhostScript64.cs new file mode 100644 index 0000000..535fcae --- /dev/null +++ b/PdfScribe/GhostScript64.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace PdfScribe +{ + internal class GhostScript64 + { + /* + This code was adapted from Matthew Ephraim's Ghostscript.Net project + https://github.com/mephraim/ghostscriptsharp + */ + + /// + /// Calls the Ghostscript API with a collection of arguments to be passed to it + /// + public static void CallAPI(string[] args) + { + // Get a pointer to an instance of the Ghostscript API and run the API with the current arguments + IntPtr gsInstancePtr; + lock (resourceLock) + { + NativeMethods.CreateAPIInstance(out gsInstancePtr, IntPtr.Zero); + try + { + int result = NativeMethods.InitAPI(gsInstancePtr, args.Length, args); + + if (result < 0) + { + throw new ExternalException("Ghostscript conversion error", result); + } + } + finally + { + Cleanup(gsInstancePtr); + } + } + } + + /// + /// Frees up the memory used for the API arguments and clears the Ghostscript API instance + /// + private static void Cleanup(IntPtr gsInstancePtr) + { + NativeMethods.ExitAPI(gsInstancePtr); + NativeMethods.DeleteAPIInstance(gsInstancePtr); + } + + + /// + /// GS can only support a single instance, so we need to bottleneck any multi-threaded systems. + /// + private static object resourceLock = new object(); + } +} diff --git a/PdfScribe/NativeMethods.cs b/PdfScribe/NativeMethods.cs new file mode 100644 index 0000000..db8cdb1 --- /dev/null +++ b/PdfScribe/NativeMethods.cs @@ -0,0 +1,27 @@ +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace PdfScribe +{ + internal static class NativeMethods + { + + #region Hooks into Ghostscript DLL + [DllImport("gsdll64.dll", EntryPoint = "gsapi_new_instance")] + internal static extern int CreateAPIInstance(out IntPtr pinstance, IntPtr caller_handle); + + [DllImport("gsdll64.dll", EntryPoint = "gsapi_init_with_args")] + internal static extern int InitAPI(IntPtr instance, int argc, string[] argv); + + [DllImport("gsdll64.dll", EntryPoint = "gsapi_exit")] + internal static extern int ExitAPI(IntPtr instance); + + [DllImport("gsdll64.dll", EntryPoint = "gsapi_delete_instance")] + internal static extern void DeleteAPIInstance(IntPtr instance); + #endregion + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + internal static extern bool SetDllDirectory(string lpPathName); + } +} diff --git a/PdfScribe/PdfScribe.csproj b/PdfScribe/PdfScribe.csproj new file mode 100644 index 0000000..4ad85f5 --- /dev/null +++ b/PdfScribe/PdfScribe.csproj @@ -0,0 +1,126 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {09BB3AA3-96D3-4BA1-BCB3-4E17067F42B2} + WinExe + Properties + PdfScribe + PdfScribe + v4.0 + Client + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + PdfScribe.Program + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + + + + + + + + + + + 4.0 + + + + + + + + ActivityNotification.xaml + + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + Adobe_CreatePDF_icon.png + + + gsdll64.dll + PreserveNewest + + + + + Designer + MSBuild:Compile + + + + + \ No newline at end of file diff --git a/PdfScribe/Program.cs b/PdfScribe/Program.cs new file mode 100644 index 0000000..5802a1f --- /dev/null +++ b/PdfScribe/Program.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Windows; + +namespace PdfScribe +{ + class Program + { + + static Application activityWindow; + + [STAThread] + static void Main(string[] args) + { + + var activityWindowThread = new Thread(new ThreadStart(() => + { + activityWindow = new Application(); + activityWindow.ShutdownMode = ShutdownMode.OnExplicitShutdown; + activityWindow.Run(new ActivityNotification()); + } + )); + activityWindowThread.SetApartmentState(ApartmentState.STA); + activityWindowThread.Start(); + + Thread.Sleep(3000); + + String standardInputFilename = Path.GetTempFileName(); + String outputFilename = Path.Combine(Path.GetTempPath(), "OAISISSOFTSCAN.PDF"); + + String[] ghostScriptArguments = { "-dBATCH", "-dNOPAUSE", "-dSAFER", "-dCompatibilityLevel=1.4", "-dPDFSETTINGS=/prepress", "-sDEVICE=pdfwrite", + String.Format("-sOutputFile={0}", outputFilename), standardInputFilename }; + + + try + { + // Remove the existing OAISISSOFTSCAN.PDF file if present + File.Delete(outputFilename); + + using (BinaryReader standardInputReader = new BinaryReader(Console.OpenStandardInput())) + { + using (FileStream standardInputFile = new FileStream(standardInputFilename, FileMode.Create, FileAccess.ReadWrite)) + { + standardInputReader.BaseStream.CopyTo(standardInputFile); + } + } + GhostScript64.CallAPI(ghostScriptArguments); + } + catch (IOException) + { + // We couldn't delete, or create a file + // because it was in use + } + catch (UnauthorizedAccessException) + { + // Couldn't delete a file + // because it was set to readonly + // or couldn't create a file + // because of permissions issues + } + catch (ExternalException) + { + // Ghostscript error + + } + finally + { + File.Delete(standardInputFilename); + activityWindow.Dispatcher.InvokeShutdown(); + } + } + } +} diff --git a/PdfScribe/Properties/AssemblyInfo.cs b/PdfScribe/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..28e35b9 --- /dev/null +++ b/PdfScribe/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("PdfScribe")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PdfScribe")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// 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("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/PdfScribe/Properties/Resources.Designer.cs b/PdfScribe/Properties/Resources.Designer.cs new file mode 100644 index 0000000..2d262fa --- /dev/null +++ b/PdfScribe/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.1008 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace PdfScribe.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PdfScribe.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/PdfScribe/Properties/Resources.resx b/PdfScribe/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/PdfScribe/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/PdfScribe/Properties/Settings.Designer.cs b/PdfScribe/Properties/Settings.Designer.cs new file mode 100644 index 0000000..520420a --- /dev/null +++ b/PdfScribe/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.1008 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace PdfScribe.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/PdfScribe/Properties/Settings.settings b/PdfScribe/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/PdfScribe/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/PdfScribeCore/PdfScribeCore.csproj b/PdfScribeCore/PdfScribeCore.csproj index 26edd5f..3d3ed57 100644 --- a/PdfScribeCore/PdfScribeCore.csproj +++ b/PdfScribeCore/PdfScribeCore.csproj @@ -94,11 +94,6 @@ - - - Designer - -