diff --git a/NTwain.sln b/NTwain.sln
index 538b616..f111ee3 100644
--- a/NTwain.sln
+++ b/NTwain.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
-VisualStudioVersion = 12.0.30110.0
+VisualStudioVersion = 12.0.30324.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NTwain", "NTwain\NTwain.csproj", "{0C5A6FB1-0282-4D61-8354-68DEB1515001}"
EndProject
@@ -19,6 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Others", "Others", "{4CE0B9
README.markdown = README.markdown
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tester.Console", "Tests\Tester.Console\Tester.Console.csproj", "{12D761EF-68DF-41CE-92EF-0C7AE81857A3}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -68,6 +70,16 @@ Global
{1715C2B7-5C35-4F8B-9D9B-8D68A3D5284D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{1715C2B7-5C35-4F8B-9D9B-8D68A3D5284D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{1715C2B7-5C35-4F8B-9D9B-8D68A3D5284D}.Release|x86.ActiveCfg = Release|Any CPU
+ {12D761EF-68DF-41CE-92EF-0C7AE81857A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {12D761EF-68DF-41CE-92EF-0C7AE81857A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {12D761EF-68DF-41CE-92EF-0C7AE81857A3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {12D761EF-68DF-41CE-92EF-0C7AE81857A3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {12D761EF-68DF-41CE-92EF-0C7AE81857A3}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {12D761EF-68DF-41CE-92EF-0C7AE81857A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {12D761EF-68DF-41CE-92EF-0C7AE81857A3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {12D761EF-68DF-41CE-92EF-0C7AE81857A3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {12D761EF-68DF-41CE-92EF-0C7AE81857A3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {12D761EF-68DF-41CE-92EF-0C7AE81857A3}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -76,6 +88,7 @@ Global
{6B034C50-A397-435F-8DDF-677B403FEBAA} = {2F906640-1664-4960-93D2-A054AC6E66A3}
{4FC243F1-318E-4FA9-9EBD-2CA3A8F35425} = {2F906640-1664-4960-93D2-A054AC6E66A3}
{1715C2B7-5C35-4F8B-9D9B-8D68A3D5284D} = {2F906640-1664-4960-93D2-A054AC6E66A3}
+ {12D761EF-68DF-41CE-92EF-0C7AE81857A3} = {2F906640-1664-4960-93D2-A054AC6E66A3}
EndGlobalSection
GlobalSection(TestCaseManagementSettings) = postSolution
CategoryFile = NTwain.vsmdi
diff --git a/NTwain/AsyncPump.cs b/NTwain/AsyncPump.cs
new file mode 100644
index 0000000..5800cc7
--- /dev/null
+++ b/NTwain/AsyncPump.cs
@@ -0,0 +1,50 @@
+//using System;
+//using System.Collections.Generic;
+//using System.Linq;
+//using System.Text;
+//using System.Threading;
+//using System.Windows.Threading;
+
+//namespace NTwain
+//{
+// // from http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx
+
+// ///
+// /// Provides a pump that supports running asynchronous methods on the current thread.
+// ///
+// public static class AsyncPump
+// {
+// ///
+// /// Runs the specified asynchronous function.
+// ///
+// /// The asynchronous function to execute.
+// /// func
+// /// No task provided.
+// public static void Run(Func func)
+// {
+// if (func == null) throw new ArgumentNullException("func");
+
+// var prevCtx = SynchronizationContext.Current;
+// try
+// {
+// var syncCtx = new DispatcherSynchronizationContext();
+// SynchronizationContext.SetSynchronizationContext(syncCtx);
+
+// var t = func();
+// if (t == null) throw new InvalidOperationException();
+
+// var frame = new DispatcherFrame();
+// t.ContinueWith(_ => { frame.Continue = false; },
+// TaskScheduler.Default);
+// Dispatcher.PushFrame(frame);
+
+// t.GetAwaiter().GetResult();
+// }
+// finally
+// {
+// SynchronizationContext.SetSynchronizationContext(prevCtx);
+// }
+
+// }
+// }
+//}
diff --git a/NTwain/NTwain.csproj b/NTwain/NTwain.csproj
index 725ab57..8e2ccce 100644
--- a/NTwain/NTwain.csproj
+++ b/NTwain/NTwain.csproj
@@ -53,6 +53,7 @@
+
diff --git a/NTwain/TwainSession.cs b/NTwain/TwainSession.cs
index 3b71a3a..c36643a 100644
--- a/NTwain/TwainSession.cs
+++ b/NTwain/TwainSession.cs
@@ -309,10 +309,7 @@ namespace NTwain
/// context
public ReturnCode EnableSource(SourceEnableMode mode, bool modal, HandleRef windowHandle, SynchronizationContext context)
{
- if (Environment.OSVersion.Platform == PlatformID.Win32NT)
- {
- if (context == null) { throw new ArgumentNullException("context"); }
- }
+ if (context == null) { throw new ArgumentNullException("context"); }
Debug.WriteLine(string.Format("Thread {0}: EnableSource.", Thread.CurrentThread.ManagedThreadId));
@@ -378,6 +375,8 @@ namespace NTwain
///
/// Forces the stepping down of an opened source when things gets out of control.
/// Used when session state and source state become out of sync.
+ /// This should be called on the Thread that originally called the
+ /// method, if applicable.
///
/// State of the target.
public void ForceStepDown(int targetState)
diff --git a/Tests/Tester.Console/Program.cs b/Tests/Tester.Console/Program.cs
new file mode 100644
index 0000000..6b09e65
--- /dev/null
+++ b/Tests/Tester.Console/Program.cs
@@ -0,0 +1,106 @@
+using NTwain;
+using NTwain.Data;
+using NTwain.Values;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Windows.Threading;
+
+namespace Tester
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ // just an amusing example to do twain in console without UI, but may not work in real life
+
+ Console.WriteLine("Running Main on thread {0}", Thread.CurrentThread.ManagedThreadId);
+ new Thread(new ParameterizedThreadStart(DoTwainWork)).Start(Dispatcher.CurrentDispatcher);
+
+ // basically just needs a msg loop to act as the UI thread
+ Dispatcher.Run();
+ Console.WriteLine("Test completed.");
+ Console.ReadLine();
+ }
+
+
+
+ static readonly TwainSession twain = InitTwain();
+ private static TwainSession InitTwain()
+ {
+ var twain = new TwainSession(TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetExecutingAssembly()));
+ twain.DataTransferred += twain_DataTransferred;
+ twain.TransferReady += twain_TransferReady;
+ twain.SourceDisabled += twain_SourceDisabled;
+ return twain;
+ }
+
+
+ static void DoTwainWork(object obj)
+ {
+ Console.WriteLine("Getting ready to do twain stuff on thread {0}", Thread.CurrentThread.ManagedThreadId);
+ Thread.Sleep(1000);
+
+ var mySyncer = SynchronizationContext.Current;
+
+ if (mySyncer == null)
+ {
+ mySyncer = new DispatcherSynchronizationContext(obj as Dispatcher);
+ }
+
+ var rc = twain.OpenManager(default(HandleRef));
+
+ if (rc == ReturnCode.Success)
+ {
+ rc = twain.OpenSource("TWAIN2 FreeImage Software Scanner");
+
+ if (rc == ReturnCode.Success)
+ {
+ // enablesource must be on the thread the sync context works on
+ mySyncer.Post(blah =>
+ {
+ rc = twain.EnableSource(SourceEnableMode.NoUI, false, default(HandleRef), blah as SynchronizationContext);
+ }, mySyncer);
+ return;
+ }
+ else
+ {
+ twain.CloseManager();
+ }
+ }
+
+ Dispatcher.ExitAllFrames();
+ }
+
+ static void twain_SourceDisabled(object sender, EventArgs e)
+ {
+ Console.WriteLine("Source disabled on thread {0}", Thread.CurrentThread.ManagedThreadId);
+ var rc = twain.CloseSource();
+ rc = twain.CloseManager();
+
+ Dispatcher.ExitAllFrames();
+ }
+
+ static void twain_TransferReady(object sender, TransferReadyEventArgs e)
+ {
+ Console.WriteLine("Got xfer ready on thread {0}", Thread.CurrentThread.ManagedThreadId);
+ }
+
+ static void twain_DataTransferred(object sender, DataTransferredEventArgs e)
+ {
+ if (e.Data != IntPtr.Zero)
+ {
+ Console.WriteLine("Got twain data on thread {0}", Thread.CurrentThread.ManagedThreadId);
+ }
+ else
+ {
+ Console.WriteLine("No twain data on thread {0}", Thread.CurrentThread.ManagedThreadId);
+ }
+ }
+ }
+}
diff --git a/Tests/Tester.Console/Properties/AssemblyInfo.cs b/Tests/Tester.Console/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..d8afa67
--- /dev/null
+++ b/Tests/Tester.Console/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 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("Tester.Console")]
+[assembly: AssemblyDescription("Console app for quick testing implementations in the TWAIN lib.")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Yin-Chun Wang")]
+[assembly: AssemblyProduct("Tester.Console")]
+[assembly: AssemblyCopyright("Copyright © Yin-Chun Wang 2014")]
+[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)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c27df82d-5be9-4396-8905-0af6ea6e63cd")]
+
+// 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/Tests/Tester.Console/Tester.Console.csproj b/Tests/Tester.Console/Tester.Console.csproj
new file mode 100644
index 0000000..6ba359f
--- /dev/null
+++ b/Tests/Tester.Console/Tester.Console.csproj
@@ -0,0 +1,62 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {12D761EF-68DF-41CE-92EF-0C7AE81857A3}
+ Exe
+ Properties
+ Tester
+ Tester.Console
+ v4.0
+ 512
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ x86
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {0c5a6fb1-0282-4d61-8354-68deb1515001}
+ NTwain
+
+
+
+
+
\ No newline at end of file