private void CleanupTwain() { if (_twain.State == 4) { _twain.CurrentSource.Close(); } if (_twain.State == 3) { _twain.Close(); } if (_twain.State > 2) { // normal close down didn't work, do hard kill _twain.ForceStepDown(2); } }
private void InternalScan(TwainImpl twainImpl, IWin32Window dialogParent, ScanDevice scanDevice, ScanProfile scanProfile, ScanParams scanParams, CancellationToken cancelToken, ScannedImageSource.Concrete source, Action <ScannedImage, ScanParams, string> runBackgroundOcr) { if (dialogParent == null) { dialogParent = new BackgroundForm(); } if (twainImpl == TwainImpl.Legacy) { Legacy.TwainApi.Scan(scanProfile, scanDevice, dialogParent, formFactory, source); return; } PlatformInfo.Current.PreferNewDSM = twainImpl != TwainImpl.OldDsm; var session = new TwainSession(TwainAppId); var twainForm = Invoker.Current.InvokeGet(() => scanParams.NoUI ? null : formFactory.Create <FTwainGui>()); Exception error = null; bool cancel = false; DataSource ds = null; var waitHandle = new AutoResetEvent(false); int pageNumber = 0; session.TransferReady += (sender, eventArgs) => { Debug.WriteLine("NAPS2.TW - TransferReady"); if (cancel) { eventArgs.CancelAll = true; } }; session.DataTransferred += (sender, eventArgs) => { try { Debug.WriteLine("NAPS2.TW - DataTransferred"); pageNumber++; using (var output = twainImpl == TwainImpl.MemXfer ? GetBitmapFromMemXFer(eventArgs.MemoryData, eventArgs.ImageInfo) : Image.FromStream(eventArgs.GetNativeImageStream())) { using (var result = scannedImageHelper.PostProcessStep1(output, scanProfile)) { if (blankDetector.ExcludePage(result, scanProfile)) { return; } var bitDepth = output.PixelFormat == PixelFormat.Format1bppIndexed ? ScanBitDepth.BlackWhite : ScanBitDepth.C24Bit; var image = new ScannedImage(result, bitDepth, scanProfile.MaxQuality, scanProfile.Quality); if (scanParams.DetectPatchCodes) { foreach (var patchCodeInfo in eventArgs.GetExtImageInfo(ExtendedImageInfo.PatchCode)) { if (patchCodeInfo.ReturnCode == ReturnCode.Success) { image.PatchCode = GetPatchCode(patchCodeInfo); } } } scannedImageHelper.PostProcessStep2(image, result, scanProfile, scanParams, pageNumber); string tempPath = scannedImageHelper.SaveForBackgroundOcr(result, scanParams); runBackgroundOcr(image, scanParams, tempPath); source.Put(image); } } } catch (Exception ex) { Debug.WriteLine("NAPS2.TW - DataTransferred - Error"); error = ex; cancel = true; StopTwain(); } }; session.TransferError += (sender, eventArgs) => { Debug.WriteLine("NAPS2.TW - TransferError"); if (eventArgs.Exception != null) { error = eventArgs.Exception; } else if (eventArgs.SourceStatus != null) { Log.Error("TWAIN Transfer Error. Return code = {0}; condition code = {1}; data = {2}.", eventArgs.ReturnCode, eventArgs.SourceStatus.ConditionCode, eventArgs.SourceStatus.Data); } else { Log.Error("TWAIN Transfer Error. Return code = {0}.", eventArgs.ReturnCode); } cancel = true; StopTwain(); }; session.SourceDisabled += (sender, eventArgs) => { Debug.WriteLine("NAPS2.TW - SourceDisabled"); StopTwain(); }; void StopTwain() { waitHandle.Set(); if (!scanParams.NoUI) { Invoker.Current.Invoke(() => twainForm.Close()); } } void InitTwain() { try { var windowHandle = (Invoker.Current as Form)?.Handle; ReturnCode rc = windowHandle != null?session.Open(new WindowsFormsMessageLoopHook(windowHandle.Value)) : session.Open(); if (rc != ReturnCode.Success) { Debug.WriteLine("NAPS2.TW - Could not open session - {0}", rc); StopTwain(); return; } ds = session.FirstOrDefault(x => x.Name == scanDevice.ID); if (ds == null) { Debug.WriteLine("NAPS2.TW - Could not find DS - DS count = {0}", session.Count()); throw new DeviceNotFoundException(); } rc = ds.Open(); if (rc != ReturnCode.Success) { Debug.WriteLine("NAPS2.TW - Could not open DS - {0}", rc); StopTwain(); return; } ConfigureDS(ds, scanProfile, scanParams); var ui = scanProfile.UseNativeUI ? SourceEnableMode.ShowUI : SourceEnableMode.NoUI; Debug.WriteLine("NAPS2.TW - Enabling DS"); rc = scanParams.NoUI ? ds.Enable(ui, true, windowHandle ?? IntPtr.Zero) : ds.Enable(ui, true, twainForm.Handle); Debug.WriteLine("NAPS2.TW - Enable finished"); if (rc != ReturnCode.Success) { Debug.WriteLine("NAPS2.TW - Enable failed - {0}, rc"); StopTwain(); } else { cancelToken.Register(() => { Debug.WriteLine("NAPS2.TW - User Cancel"); cancel = true; session.ForceStepDown(5); }); } } catch (Exception ex) { Debug.WriteLine("NAPS2.TW - Error"); error = ex; StopTwain(); } } if (!scanParams.NoUI) { twainForm.Shown += (sender, eventArgs) => { InitTwain(); }; twainForm.Closed += (sender, args) => waitHandle.Set(); } if (scanParams.NoUI) { Debug.WriteLine("NAPS2.TW - Init with no form"); Invoker.Current.Invoke(InitTwain); } else if (!scanParams.Modal) { Debug.WriteLine("NAPS2.TW - Init with non-modal form"); Invoker.Current.Invoke(() => twainForm.Show(dialogParent)); } else { Debug.WriteLine("NAPS2.TW - Init with modal form"); Invoker.Current.Invoke(() => twainForm.ShowDialog(dialogParent)); } waitHandle.WaitOne(); Debug.WriteLine("NAPS2.TW - Operation complete"); if (ds != null && session.IsSourceOpen) { Debug.WriteLine("NAPS2.TW - Closing DS"); ds.Close(); } if (session.IsDsmOpen) { Debug.WriteLine("NAPS2.TW - Closing session"); session.Close(); } if (error != null) { Debug.WriteLine("NAPS2.TW - Throwing error - {0}", error); if (error is ScanDriverException) { throw error; } throw new ScanDriverUnknownException(error); } }