Added SetTwainDirectTask method to session.

This commit is contained in:
Eugene Wang 2021-04-27 07:37:52 -04:00
parent d9e56794e5
commit 714caf4935
5 changed files with 117 additions and 17 deletions

View File

@ -4,6 +4,7 @@
<PackageId>NTwain</PackageId> <PackageId>NTwain</PackageId>
<Description>Library containing the TWAIN API for dotnet.</Description> <Description>Library containing the TWAIN API for dotnet.</Description>
<TargetFrameworks>net45;netstandard2.0;</TargetFrameworks> <TargetFrameworks>net45;netstandard2.0;</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -49,6 +49,19 @@ namespace TWAINWorkingGroup
public int Images; public int Images;
} }
public struct TwainDirectTaskResult
{
/// <summary>
/// Return code of task.
/// </summary>
public STS ReturnCode;
/// <summary>
/// The response of the task in JSON if successful.
/// </summary>
public string ResponseJson;
}
/// <summary> /// <summary>
/// A more dotnet-friendly representation of <see cref="TW_ENUMERATION"/>. /// A more dotnet-friendly representation of <see cref="TW_ENUMERATION"/>.
/// </summary> /// </summary>

View File

@ -131,16 +131,16 @@ namespace NTwain
get { return _twain.GetState(); } get { return _twain.GetState(); }
} }
/// <summary> ///// <summary>
/// Gets the manager status. Useful after getting a non-success return code. ///// Gets the manager status. Useful after getting a non-success return code.
/// </summary> ///// </summary>
/// <returns></returns> ///// <returns></returns>
public TW_STATUS GetStatus() //public TW_STATUS GetStatus()
{ //{
TW_STATUS stat = default; // TW_STATUS stat = default;
_ = _twain.DatStatus(DG.CONTROL, MSG.GET, ref stat); // _ = _twain.DatStatus(DG.CONTROL, MSG.GET, ref stat);
return stat; // return stat;
} //}
/// <summary> /// <summary>
/// Opens the TWAIN data source manager. /// Opens the TWAIN data source manager.
@ -352,12 +352,36 @@ namespace NTwain
return new Metrics { ReturnCode = sts }; return new Metrics { ReturnCode = sts };
} }
//public sts SetTwainDirectTask() /// <summary>
//{ /// Sends a TWAIN Direct task from the application to the driver.
// TW_TWAINDIRECT task = default; /// </summary>
// var sts = _twain.DatTwaindirect(DG.CONTROL, MSG.SETTASK, ref task); /// <param name="taskJson">The TWAIN Direct task in JSON.</param>
// return sts; /// <param name="communicationManager">The current system being used to connect the application to the scanner.</param>
//} /// <returns></returns>
public TwainDirectTaskResult SetTwainDirectTask(string taskJson, ushort communicationManager = 0)
{
var result = new TwainDirectTaskResult { ReturnCode = STS.FAILURE };
TW_TWAINDIRECT task = default;
try
{
task.SizeOf = (uint)Marshal.SizeOf(typeof(TW_TWAINDIRECT));
task.CommunicationManager = communicationManager;
task.Send = ValueWriter.StringToPtrUTF8(_twain, taskJson, out int length);
task.SendSize = (uint)length;
result.ReturnCode = _twain.DatTwaindirect(DG.CONTROL, MSG.SETTASK, ref task);
if (result.ReturnCode == STS.SUCCESS && task.ReceiveSize > 0 && task.Receive != IntPtr.Zero)
{
result.ResponseJson = ValueReader.PtrToStringUTF8(task.Receive, (int)task.ReceiveSize);
}
}
finally
{
if (task.Send != IntPtr.Zero) _twain.DsmMemFree(ref task.Send); // just in case
if (task.Receive != IntPtr.Zero) _twain.DsmMemFree(ref task.Receive);
}
return result;
}
#endregion #endregion
} }

View File

@ -14,6 +14,30 @@ namespace NTwain
/// </summary> /// </summary>
public static class ValueReader public static class ValueReader
{ {
/// <summary>
/// Reads pointer as UTF8 string.
/// </summary>
/// <param name="intPtr">Pointer to string.</param>
/// <param name="length">Number of bytes to read.</param>
/// <returns></returns>
public static unsafe string PtrToStringUTF8(IntPtr intPtr, int length)
{
if (intPtr == IntPtr.Zero) throw new ArgumentNullException(nameof(intPtr));
if (length == 0) throw new ArgumentOutOfRangeException(nameof(length), length, "Length must be greater than 0.");
//// safe method with 2 copies
//var bytes = new byte[length];
//Marshal.Copy(intPtr, bytes, 0, length);
//return Encoding.UTF8.GetString(bytes);
// unsafe method with 1 copy (does it work?)
sbyte* bytes = (sbyte*)intPtr;
var str = new string(bytes, 0, length, Encoding.UTF8);
return str;
}
// most of these are modified from the original TWAIN.CapabilityToCsv() // most of these are modified from the original TWAIN.CapabilityToCsv()
public static TValue ReadOneValueContainer<TValue>(TWAIN twain, ref TW_CAPABILITY cap, bool freeMemory = true) where TValue : struct public static TValue ReadOneValueContainer<TValue>(TWAIN twain, ref TW_CAPABILITY cap, bool freeMemory = true) where TValue : struct

View File

@ -13,6 +13,45 @@ namespace NTwain
/// </summary> /// </summary>
public static class ValueWriter public static class ValueWriter
{ {
/// <summary>
/// Allocates and copies the string value into a pointer in UTF8 that's null-terminated.
/// </summary>
/// <param name="twain"></param>
/// <param name="value"></param>
/// <param name="length">Actual number of bytes used to encode the string without the null.</param>
/// <returns></returns>
internal static unsafe IntPtr StringToPtrUTF8(TWAIN twain, string value, out int length)
{
var utf8 = Encoding.UTF8;
length = utf8.GetByteCount(value);
var ptr = twain.DsmMemAlloc((uint)length + 1); // +1 for null-terminated
// TODO: test if this works
int written;
byte* bytes = (byte*)ptr;
try
{
fixed (char* firstChar = value)
{
written = Encoding.UTF8.GetBytes(firstChar, value.Length, bytes, length);
}
bytes[written] = 0;
}
catch
{
// just in case
if (ptr != IntPtr.Zero) twain.DsmMemFree(ref ptr);
throw;
}
return ptr;
}
// most of these are modified from the original TWAIN.CsvToCapability() // most of these are modified from the original TWAIN.CsvToCapability()
public static void WriteOneValueContainer<TValue>(TWAIN twain, ref TW_CAPABILITY twCap, TValue value) where TValue : struct public static void WriteOneValueContainer<TValue>(TWAIN twain, ref TW_CAPABILITY twCap, TValue value) where TValue : struct
@ -470,7 +509,6 @@ namespace NTwain
} }
} }
static TWTY GetItemType<TValue>() where TValue : struct static TWTY GetItemType<TValue>() where TValue : struct
{ {
var type = typeof(TValue); var type = typeof(TValue);