Trouble with transfer function in WIA C# - c#

I have a problem with the below code. I want to scan a document by clicking a button in a WinForms C# application.
I use WIA, Visual studio and the scanner Fujitsu N7100A working with Windows 8. I am following a tutorial online for using WIA.
But the program doesn't run as expected. It seems to break down at the Transfer method.
// Create a DeviceManager instance
var deviceManager = new DeviceManager();
// Create an empty variable to store the scanner instance
DeviceInfo firstScannerAvailable = null;
// Loop through the list of devices to choose the first available
AddLogs(deviceManager.DeviceInfos.Count.ToString(), filename);
foreach (DeviceInfo d in deviceManager.DeviceInfos)
{
if (d.Type == WiaDeviceType.ScannerDeviceType)
{
firstScannerAvailable = d;
}
}
// Connect to the first available scanner
var device = firstScannerAvailable.Connect();
// Select the scanner
var scannerItem = device.Items[0];
// Retrieve a image in JPEG format and store it into a variable
var imageFile = (ImageFile)scannerItem.Transfer(FormatID.wiaFormatPNG);
//Save the image in some path with filename
var path = #"C:\Documents\scan.png";
if (File.Exists(path))
{
File.Delete(path);
}
// Save image !
imageFile.SaveFile(path);
I just have to remove the addition of lines in the file of log.

This is much more of a workaround since i have no idea about your scanner.
I would assume that all scanners has a drive where they store their scanned documents, like mine, So i would suggest that you read all available drives loop through them check for DriveType and VolumeLabel and then read it's files and copy the document where you want
Something like this :
foreach (var item in DriveInfo.GetDrives())
{
//VolumeLabel differs from a scanner to another
if (item.VolumeLabel == "Photo scan" && item.DriveType == DriveType.Removable)
{
foreach (var obj in Directory.GetFiles(item.Name))
{
File.Copy(obj, "[YOUR NEW PATH]");
break;
}
break;
}
}

Finaly a TWAIN application work with this scanner. I will work with that. I don't said why do that work with TWAIN and not with WIA but that the reality. Sorry for this waste of time. Thank you for the answers. Have a nice day.

I am currently solving this very problem. It seems the N7100A driver sets the Pages property of the device to 0, which should mean continous scanning, but the transfer method is unable to handle this value. You must set that property to 1:
var pages = 1;
// Not all devices have this property, but Fujitsu N7100A has.
device.Properties["Pages"]?.set_Value(ref pages);

I think the problem is here
var scannerItem = device.Items[0];
as WIA indexes are NOT zero based so it should be 1 instead
var scannerItem = device.Items[1];

Related

C# PrintQueue AddJob printingHandle throws null exception

I'm trying to print a file with C#. I have made some headway in listing off all the printers and then wrote some simple logic to select the correct printer:
var server = new PrintServer();
var queues = server.GetPrintQueues(new[] { EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections }).ToList();
int count = 0;
foreach (var q in queues)
{
Console.WriteLine(count++ + " " + q.Name);
}
int iSelection = 0;
while (true)
{
Console.Write("Select printer: ");
string selection = Console.ReadLine();
if (int.TryParse(selection, out iSelection) && iSelection >= 0 && iSelection < queues.Count())
{
break;
}
else
{
Console.WriteLine("Bad selection, try again.");
}
}
The next step, as for the posts I've seen on this site, is that you need to select the specific queue, and then add a job, grab the job stream, and write to the stream (at least that's how I want to try to do it, unless it's wrong?)
var queue = queues[iSelection];
var job = queue.AddJob(#".\Test.txt");
var stream = job.JobStream;
var file = File.ReadBytes(#".\Test.txt");
stream.Write(file, 0, file.Length);
When I do this, the program crashes at the line with AddJob. Specifically,
System.ArgumentNullException: 'Value cannot be null, Parameter name: printingHandler'
Now, I think I understand what the issue is. I had been playing with System.Drawing.Printing.PrintDocument yesterday, but I am trying to find a solution that allows me to print files, rather than manually draw them out and them print them. Ultimately, the goal in the future is to be able to print out text and PDF files (I was hoping that this solution would allow me to open a PDF file and dump the bytes into this stream, but I don't know if that's the correct way to this?)
Anyway, the exception I got I think is something similar to PrintDocument's PrintPageEventHandler, I need to add a callback to the PrintQueue somehow that tells it the font, color, font size, etc. Problem is that I see nothing for PrintQueue that allows me to add a handle for it to fix this issue.
What can I do to fix this exception?
I was having this issue as well. Eventually I found out that we need to call into Refresh() of the selected PrintQueue instance and before calling AddJob().

Windows IoT Raspberry Pi 3 C# GetDiskFreeSpace

I have a USB thumb-drive connected to my raspberry pi 3. I'd need to find out how to check for the available disk space to be printed on a textblock. I couldn't find any example for UWP application.
What I found was GetDiskFreeSpaceEx function and Is there a method available for UWP apps to get available disk space
Is there any example I could refer to?
Thanks.
Updated:
I have tried [Get available disk free space for a given path on Windows [duplicate]] .. Couldn't get it to work too..
You can use StorageFolder.Properties.RetrievePropertiesAsync() API to get the free space size of USB storage.I tested with the following pieces of code:
var removableDevices = KnownFolders.RemovableDevices;
var externalDevices = await removableDevices.GetFoldersAsync();
var usbDriver = externalDevices.FirstOrDefault();
var allProperties = usbDriver.Properties;
IEnumerable<string> propertiesToRetrieve = new List<string> { "System.FreeSpace" };
var storageIdProperties = await allProperties.RetrievePropertiesAsync(propertiesToRetrieve);
var freeSpaceSize = storageIdProperties["System.FreeSpace"].ToString();

List of all physical drives

How to get list of all physical drives in UWP (Windows 10) App? I'm try to use Windows.Storage.KnownFolders, but this way I can get only folders from Library.
In UWP you cannot list all the files/drives just like that (with official API) - this is by design, probably for security reasons. Windows Store apps work are isolated and the access is only granted to limited resources/locations. In this case you are freely able to access virtual locations like MusicLibray, PicturesLibrary and so on. The list of access permisions you will find at MSDN.
If you want to access a file/folder from out of above scope, the user will have to grand the access to it for your app. For this purpose you can use pickers.
I know you asked this question a long time ago, but I created a question (Get Internal Drives Using Windows.Storage Namespace in UWP) to provide my method for getting internal drives and encourage feedback/discussion on a better alternative.
I had exactly the same problem to solve and everything else I can find online doesn't fit with what I'm trying to do. So, with the broadFileSystemAccess attribute added to the manifest file and File System access switched on for the app in Privacy Settings, it is possible to call StorageFolder.GetFolderFromPathAsync for a drive letter and it will return an instance of StorageFolder if the drive exists.
Sadly there isn't a method to list the drives, so I wrote something to cycle through all the letters of the alphabet and call GetFolderFromPathAsync to see if a drive handle is returned.
The method I created to obtain the list of drives is as follows:
public List<StorageFolder> GetInternalDrives()
{
string driveLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int driveLettersLen = driveLetters.Length;
string removableDriveLetters = "";
string driveLetter;
List<StorageFolder> drives = new List<StorageFolder>();
StorageFolder removableDevices = KnownFolders.RemovableDevices;
IReadOnlyList<StorageFolder> folders = Task.Run<IReadOnlyList<StorageFolder>>(async () => await removableDevices.GetFoldersAsync()).Result;
foreach (StorageFolder removableDevice in folders)
{
if (string.IsNullOrEmpty(removableDevice.Path)) continue;
driveLetter = removableDevice.Path.Substring(0, 1).ToUpper();
if (driveLetters.IndexOf(driveLetter) > -1) removableDriveLetters += driveLetter;
}
for (int curDrive = 0; curDrive < driveLettersLen; curDrive++)
{
driveLetter = driveLetters.Substring(curDrive, 1);
if (removableDriveLetters.IndexOf(driveLetter) > -1) continue;
try
{
StorageFolder drive = Task.Run<StorageFolder>(async () => await StorageFolder.GetFolderFromPathAsync(driveLetter + ":")).Result;
drives.Add(drive);
}
catch (System.AggregateException) { }
}
return drives;
}
And here is the calling code:
List<StorageFolder> drives = GetInternalDrives();
panScanParams.Children.Clear();
foreach (StorageFolder drive in drives)
{
CheckBox cb = new CheckBox();
cb.Content = drive.DisplayName;
cb.IsChecked = true;
panScanParams.Children.Add(cb);
}
Whilst the code works, it's not good practice to call methods with bad parameters and handle the exception. But with a lack of suitable alternative, I don't know what other choice there is.

Windows phone 8: where and how to access files?

I have built a quizz app in C#/xaml that works fine on my computer and would like to port it on windows phone 8.
Here is how it works : I have a two columns .txt file : first column is a country, 2nd is the capital city. The program randomly selects a country and proposes 4 possible answer the user has to choose from.
I managed to port the game on my phone but I can't find how to use my .txt file.
To read the file I've written this method :
static List<Countries> openFile(string fileName)
{
string line = null;
List<string> liste = new List<string>();
List<Countries> countries = new List<Countries>();
using (StreamReader reader = new StreamReader(fileName)) //fileName = "capitals.txt")
{
line = reader.ReadLine();
while (line != null)
{
liste.Add(line);
line = reader.ReadLine();
}
}
foreach (string ttt in countries)
{
string[] test = ttt.Split('\t');
countries.Add(new Countries() { nomPays = test[0], Capitale = test[1] });
}
return countries;
}
My problem is very dumb. I don't know where to put the file on my computer to debug the program, visual studio keeps indicating it can't locate the file.
In the IDE, I tries to find where he is looking the file for. I found it was supposed to be located in a folder somewhere in "appdata\packages\" but when I look for that folder, it does not exist (I have checked that hidden files and folders are displayed).
One thing I tried, was to add the file manually in the assets, but I still can't open it. Maybe am I using the wrong method to open the file ? I've tried different options to open the file, such as :
//get local folder
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
var dataFolder = await local.GetFolderAsync("dataFolder");
var file = await local.OpenStreamForReadAsync("Capitals.txt");
Or :
var uri = new System.Uri("ms-appx:///Assets/Capitals.txt");
var file = Windows.Storage.StorageFile.GetFileFromApplicationUriAsync
But neither work, I keep having a file not found error.
My question is simple : 1/ Where should I put my file on my hard drive while working on the software and 2/ How should I access this file ?
Thank you very much for your help

Enumerate available WiFi Printers in my Windows Phone app

I know similar questions have been asked a lot, ie "can I print from my wp8?". Most folks seem content with the simple "no" response. I am looking to add this functionality into my app and I know it can be accomplished at some level - even if I can only support a very minimum printer set for now.
I've looked at the app PrintHand, and it appears to have the capabilities I need: print to wireless and Bluetooth printers.
I've been looking through the Bluetooth scenarios document a bit and I think this might help discover a Bluetooth printer. That's a start. Perhaps it will help in identifying wireless printers also.
I realize I need to start very small with this project and I want to first try to enumerate any wireless printers (I don't have a Bluetooth one yet) available on the current network. Would anybody happen to have a pointer in the right direction on how to get started or better yet, some related sample code?
Thanks so much!
Best I can give is my Github Repo which isn't related to Wifi printers, but Google cloud printing.
There isn't really a .net reference for using Google Cloud Print in their documentation, but the code works in Mono, and should be easy to move over to .NET and hence, Windows Phone.
MonoGCP
I was able to detect a nearby wireless printer using Simple Service Discovery Protocol.
Here is my sample function:
private const string SSDP_IP = "239.255.255.250";
private const string SSDP_PORT = "1900";
public async static void DiscoverAsync2()
{
var multicastIP = new HostName(SSDP_IP);
var found = false;
using (var socket = new DatagramSocket())
{
socket.MessageReceived += (sender, e) =>
{
var reader = e.GetDataReader();
var bytesRemaining = reader.UnconsumedBufferLength;
var receivedString = reader.ReadString(bytesRemaining);
// TODO: something useful with this new info
found = true;
};
await socket.BindEndpointAsync(null, string.Empty);
socket.JoinMulticastGroup(multicastIP);
while (true)
{
found = false;
using (var stream = await socket.GetOutputStreamAsync(multicastIP, SSDP_PORT))
{
var request = new StringBuilder();
request.AppendLine("M-SEARCH * HTTP/1.1");
request.AppendLine("HOST: " + SSDP_IP + ":" + SSDP_PORT);
request.AppendLine("MAN: \"ssdp:discover\"");
request.AppendLine("MX: 3");
request.AppendLine("ST: urn:schemas-upnp-org:device:Printer:1"); // use ssdp:all to get everything
request.AppendLine(); // without this extra blank line, query won't run properly
var buff = Encoding.UTF8.GetBytes(request.ToString());
await stream.WriteAsync(buff.AsBuffer());
await Task.Delay(5000);
if (!found)
break;
}
}
}

Categories