Auto-Disconnect feature / QNAP qpkg not up-to-date

Hi,

I have two questions. First one is simple: I have a QNAP NAS and downloaded VirtualHere from their store. The version there is 2.0.6. Would it be possible to publish a newer version, or did I get something wrong?

The second one is probably a feature request rather than a question. I'm trying to get a shared printer working. The "auto use" feature is getting a bit in the way. So I searched through the forum and found a post where you mention that a script could be written to check if the spooler has a document. That works great, except for the disconnection part. Depending on the document size it might take more than a constant amount of time for the script to disconnect the USB printer via API. So here's my feature request: Would it be possible to add a "auto-disconnect-after-n-seconds-idle" feature? If no communication to that device happens for n-seconds then the client (or server?) could automatically detach the device. That would allow me to better handle the disconnection part of the printer.

Other than that: great piece of software and really impressed!

Cheers
Loris

#2

Hi Loris,

1. Yes i should update qnap on their apps store, its a manual email process so i only do it if i found a big bug and there haven't been any lately.

2. Actually its i bit tricky because although your printer is not being printed to, there is actually messages continually being send/received. I think they are paper/ink status and so forth. So there is no such thing as "idle time" with the printer. The best way to detect it is when the print queue is empty or that document isnt in it anymore, send the "stop using,..." command to the client via the api. Probably powershell or something can do this i havent tried it, but im sure it can be done e.g http://learn-powershell.net/2010/11/21/viewing-print-queue-statistics-w…

In reply to by Michael

#3

That was a fast response! :)

I see your point about the "keep-alive" packets and I'd love to verify this. Is there a "communication dump" that can be triggered (something like vhui64.exe --verbose --really-verbose --debug-all ;))?

While looking through the other forum posts, I saw that other users were also "complaining" about the "auto-use" feature. Personally speaking, having a generic "auto-unuse" feature would make VirtualHere an really, really perfect product, although I have to admit, that I wouldn't know what the trigger(s) would be for the auto-disconnect (reg-ex of binary data, throughput/sec below threshold, ...). For the printer case, I could see that the window app could have an additional feature that would itself check the printer spooler (e.g. in config.ini having an List e.g. AutoConnectPrinter=LexmarkXYZ/USBIDToConnect,CannonABC/USBIDToConnect,...).

Just out of curiosity, the windows client in written in which language? My current guess in plain C. If I can provide you code that would do the spooler check, would you think of adding it to the windows client? :)

You can use something like usblyzer to see the messages. Start the virtualhere client, run usblyzer (free version) and then press record and then "Use" in virtualhere and you will see the message flow. USB has "Interrupt" message types which are periodic and these are the ones you will probably see.

I wrote a similar thing for osx that traces the usb device back up through the kernel to userspace to automatically trigger an eject on a usb disk before un-using in virtualhere. This was very difficult and i suspect even more so in windows as windows doesnt have good standard text based utilities to do the work and parse the output. Essentially the USB path of the printer has to be mapped back to the actual port of the USB Host controller, if that can be done easily then i think it should be possible. the client is c++

Thanks for the reference to usblyzer; didn't know that existed :).

I wouldn't go that far as to automatically map the USB port to the printer; I'd rather see it like this:
* User connects the USB printer (drivers get installed, etc...)
* User opens up the VirtualHere UI and right-clicks on the USB port and would select "Auto connect to Printer..." (instead of auto-use)
* A simple dialog with the printer enum would show the printers. User selects the printer he/she thinks it the right one

A background thread would get the printer handler [OpenPrinter("MyPrinterString", &hPrinter, NULL)] and fires up a FindFirstPrinterChangeNotification(hPrinter, PRINTER_CHANGE_JOB, PRINTER_NOTIFY_CATEGORY_ALL). Waiting for return value to be signaled with the WaitForSingleObject(...). As soon as a print job is added, set, deleted or written to then the connected to.

Would you consider adding this to VirtualHere if I wrote a simple C application that would do the print spooler checking (and call VirtualHere's API)?

Yeah you can write something, perhaps i can change the client to add an event to call your c program at the right time. Ill wait until i see how you end up writing your utility then i can figure out the event trigger into the client ...

Cool :). I'll try to get it done this or next week. You can then use the code as you wish (you'll get the sources, naturally). And just for the books: I don't want anything in return. It's your product and you decide what you want to put in it ;). But I would be happy if it was in ;)

Ok.... here it is.... it's a rather small C example that will call the VirtualHere UI whenever a print job event was received. The printer name and USB address are hard-coded - was a bit lazy ;)

--------------------
#include
#include
#include "windows.h"

#define PRINTER_NAME "Samsung CLX-216x Series"
#define USB_PRINTER_ADDRESS "268435467"

int main(int argc, char* argv[]) {
HANDLE hPrinter = INVALID_HANDLE_VALUE;
HANDLE hChangeNotificationObject = INVALID_HANDLE_VALUE;

printf("INFO: Starting...\n");

// initialize

if (OpenPrinter(PRINTER_NAME, &hPrinter, NULL) == 0) {
printf("ERR: Could not open printer\n");
exit(1);
} else {
printf("INFO: Printer handle is 0x%08X\n", hPrinter);
}

hChangeNotificationObject = FindFirstPrinterChangeNotification(hPrinter, PRINTER_CHANGE_JOB, 0, NULL);
if (hChangeNotificationObject == INVALID_HANDLE_VALUE) {
printf("ERR: Could not get a notification object\n");
} else {
printf("INFO: notification object handle is 0x%08X\n", hChangeNotificationObject);
}

printf("Waiting for change notification... Try to print something like the test page...\n");
WaitForSingleObject(hChangeNotificationObject, INFINITE);

// we've got an event... connect the USB port via API
system("vhui64.exe -t \"USE," USB_PRINTER_ADDRESS "\"");

// cleanup

if (hChangeNotificationObject != INVALID_HANDLE_VALUE) {
if (FindClosePrinterChangeNotification(hChangeNotificationObject) == 0) {
printf("ERR: Could not close notification object\n");
} else {
printf("INFO: Notification object closed\n");
}
}

if (hPrinter != INVALID_HANDLE_VALUE) {
if (ClosePrinter(hPrinter) == 0) {
printf("ERR: Could not close printer\n");
} else {
printf("INFO: Printer handle closed\n");
}
}

printf("INFO: done.\n");
}

#10

Thanks for the code. I see, you are more interested in auto connecting the printer , i thought you were more interested in auto DISconnecting it. Thats an easier problem to solve...i can work on this in a few weeks as its more complicated that it appears. As i actually the virtualhere client doesnt know if its connected to a printer, because most printers are complicated now days and have multiple devices appear from a single device (called a "composite usb device") in windows and actually certain functionality may appear to be a printer only after a complicated set of configuration settings. So there is no generic way for me to tell if im connected to a printer other than looking into the driver stack and seeing a generic print driver there at some level. This is quite complicated so i will have to allocate some time for this in a few weeks.... in the mean time your can compile your code and see if thats ok for you for the time being

I'm actually intested in both connecting and disconnecting... I just thought I could start with the auto-connect ;). I'll try to expand the code to do both of them.