cyanfish / naps2

Scan documents to PDF and more, as simply as possible.
https://www.naps2.com
Other
2.71k stars 320 forks source link

naps2.sdk - problem with scanner in citrix environment #412

Open tobiasoehler opened 1 month ago

tobiasoehler commented 1 month ago

Describe the bug

I have tried to access a scanner via redirected Twain in Citrix using the NAPS2.Sdk and the examples. However, the process hangs and the scanner is then blocked via Twain.

Logging in first Scan:

Scanning with ScanDevice { Driver = Twain, ID = PaperStream IP SP-1125, Name = PaperStream IP SP-1125 } Scan source: Duplex; bit depth: Color; dpi: 150; page size: 8.5x11 in Using TWAIN DSM: C:\WINDOWS\twain_32.dll NAPS2.TW - Opening session NAPS2.TW - StateChanged (to 3) NAPS2.TW - Finding source NAPS2.TW - Opening source NAPS2.TW - Name: PaperStream IP SP-1125; Manu: FUJITSU; Family: PaperStr; Version: 3.32 3.32.0.1361 Apr 23 2024; Protocol: 2.4 NAPS2.TW - StateChanged (to 4) NAPS2.TW - Configuring source NAPS2.TW - Enabling source NAPS2.TW - StateChanged (to 5)

-> from here it does not go any further - it hangs

Logging in second Scan:

Scanning with ScanDevice { Driver = Twain, ID = PaperStream IP SP-1125, Name = PaperStream IP SP-1125 } Scan source: Duplex; bit depth: Color; dpi: 150; page size: 8.5x11 in Using TWAIN DSM: C:\WINDOWS\twain_32.dll NAPS2.TW - Opening session NAPS2.TW - StateChanged (to 3) NAPS2.TW - Finding source NAPS2.TW - Opening source NAPS2.TW - Name: PaperStream IP SP-1125; Manu: FUJITSU; Family: PaperStr; Version: 3.32 3.32.0.1361 Apr 23 2024; Protocol: 2.4 NAPS2.TW - Finishing with error Error: NAPS2.Scan.Exceptions.DeviceException: TWAIN error: MaxConnections

Additional context

When using the Naps2 console application and the Naps2 exe, the scanner works without any problems.

cyanfish commented 1 month ago

Can you attach the debuglog from the NAPS2 exe for comparison?

Are you scanning using the worker (NAPS2.Sdk.Worker.Win32) or by running your main process as 32-bit? (You can also try the other to see if it makes a difference.)

tobiasoehler commented 1 month ago

The debug log is attached. debuglog.txt

We have tried both. Both reacted in the same way.

rothtobi commented 1 month ago

Tobias is a colleague of mine, we can do a remote session together under a Citrix session to analyze/fix the bug. Feel free to contact Tobias Oehler or me directly.

cyanfish commented 1 month ago

A couple more things you could try to narrow down the difference between the SDK and the NAPS2 application:

  1. In the NAPS2 application, in your profile settings, under Advanced, under Twain Implementation, select "Old DSM". See if that causes any problems.
  2. In your SDK project, try setting ScanOptions.DialogParent to a valid window handle (e.g. if you can run it as a WinForms application, then set it to form.Handle). See if that helps.
tobiasoehler commented 1 month ago

I apologize for my late response. “Old DSM” works without problems in NAPS2. If I start a Windows Forms application and call controller.Scan(options) with the option DialogParent = form.Handle I get the error message “This can only be created on the Windows Forms UI thread”.

cyanfish commented 1 month ago

Yes, you'll need to call form.Handle somewhere on the UI thread (e.g. in your form's Load or Shown event).

tobiasoehler commented 1 month ago

Sorry for my stupid questions. But unfortunately I'm not very familiar with Windows Forms. When starting the application, I registered the load event to get the handle.

form.Load += (object sender, System.EventArgs e) => {
    formHandle = form.Handle;
};

Then I click on a button to load the scanner and scan as in the example. I have tried both, using an async method and also invoking it.

Example async button click:

private async void button1_Click(object sender, EventArgs e)
{
    using var scanningContext = new ScanningContext(new GdiImageContext());
    var controller = new ScanController(scanningContext);

    ScanDevice device = (await controller.GetDeviceList(Driver.Twain)).First();

    var options = new ScanOptions
    {
        Device = device,
        DialogParent = Program.formHandle
    };

    await foreach (var image in controller.Scan(options))
    {
        MessageBox.Show("Scanned a page!");
    }
}

Example Invoke:

private void button1_Click(object sender, EventArgs e)
{
    this.Invoke(async () =>
    {
        using var scanningContext = new ScanningContext(new GdiImageContext());
        var controller = new ScanController(scanningContext);

        ScanDevice device = (await controller.GetDeviceList(Driver.Twain)).First();

        var options = new ScanOptions
        {
            Device = device,
            DialogParent = Program.formHandle
        };

        await foreach (var image in controller.Scan(options))
        {
            MessageBox.Show("Scanned a page!");
        }
    });
}

But in both cases I get the error message “This can only be created on the Windows Forms UI thread”.