Printing EMF from a Windows service - c#

I have some code that prints a document using the System.Drawing.Printing namespace. This now needs to be moved into a windows service. The documentation states that this is not possible, which would support my findings so far (in that it doesn't work). I'm working under the assumption that I can get this to work by using the System.Printing namespace instead.
Here is the code that I have so far:
private Metafile myDoc;
myDoc = GetEmfDoc();
PrintServer ps = new PrintServer("\\server1\printer1");
EnumeratedPrintQueueTypes[] flags = { EnumeratedPrintQueueTypes.Local };
PrintQueueCollection queues = ps.GetPrintQueues(flags);
PrintQueue pq = queues.First<PrintQueue>();
pq.AddJob("JobName", ?);
So I want to pass myDoc to pq.AddJob(), but this doesn't seem to be possible. Using System.Drawing.Printing it was possible to simply render this on a page by page basis in the PrintDocument.PrintPage event.
Is what I'm trying to do possible, and if so, could someone point me in the right direction?

Classes within the System.Drawing.Printing namespace are not supported for use within a Windows service or ASP.NET application or service. Attempting to use these classes from within one of these application types may produce unexpected problems, such as diminished service performance and run-time exceptions.
It is important to understand what "not supported" means in this context. It literally means what it says, it you try to print from a service and discover a problem then you cannot call Microsoft Support and ask for help.
This is not a problem that's induced by System.Drawing, it is a generic problem with printer drivers. Chunks of code that are supplied by the printer manufacturer, not Microsoft. A significant problem with them is that they are invariably designed to be used from a desktop program. Word, Acrobat, etcetera. They readily take advantage of that, they often pop up a window to let you know that they are Working On It. Not in the least to spam the manufacturer name and reminding you that the toner cartridge is half empty. These drivers are likely to misbehave in a service. The "runtime exceptions" phrase mentioned in the note.
The worst problem with them is that they use a popup window to let you know that there's a problem. These windows are not visible when you use the printer driver from a service. So you'll have to deal with print jobs that for no discernible reason refuse to print. The "diminished service performance" phrase in the note. That's very difficult to deal with, IT staff is just powerless to have a shot at fixing the problem when they can't see any diagnostic.
Your approach doesn't solve that fundamental problem. If you really want to pursue this then contact the printer manufacturer and ask for specific advise. Don't get your hopes up, getting good answers out of hardware companies is pretty difficult.

This is a combination of permission issues and Session 0 isolation...
The following might solve the problem you face although I do NOT recommend it:
IF you really want/need to make this work you will need to make a logon (beforehand!) to the remote server (in your example server1) from inside Session 0 (NOT from the "normal" user session) - either interactively (you can switch to the session 0 desktop via rundll32 winsta.dll,WinStationSwitchToServicesSession) OR via some calls (for example using WNetAddConnection2 with the proper credentials to the remote machine, unfortunately this is usable from .NET only via p/invoke or COM using WScript.Network). The credentials used for this logon need to have full permissions regarding printing on the remote machine.

Are you running your service in an account that has the necessary rights to use the printer? More details in the Windows Services FAQ.

Related

IInternetSecurityManager URLACTION_CROSS_DOMAIN_DATA and Asynchronous Pluggable Protocol for cross domain XMLHTTP requests in webbrowser control

I've implemented async pluggable protocol in a .net 2.0 application using C# which loads html files stored on the local machine into a MemoryStream.
when I load the html files normally in the webbrowser control using their local file paths, xmlhttprequest works fine but loading the files through the protocol and an attempt to use xmlhttprequest returns an access denied error.
I presume that this behavior is due to the webbrowser control no longer knowing that the html files are stored on the local machine, and is loading them in an untrusted internet zone.
Even though I'm returning S_OK for URLACTION_CROSS_DOMAIN_DATA inside IInternetSecurityManager's ProcessUrlAction which I checked with a break point to make sure it was fired, my IInternetSecurityManager's return value for this action is being ignored.
I've tried setting pdwZone to tagURLZONE.URLZONE_LOCAL_MACHINE in IInternetSecurityManager's MapUrlToZone for my protocol URLs and played around a little with GetSecurityId although I'm not sure exactly what I'm doing with and broke other things like allowing scripts to load etc... Nothing seems to work to allow cross-domain xmlhttprequest.
Anyone any idea how I can get this to work.
Not really an answer, but it may help to isolate the problem. I'd first implement this APP handler in C++ and test it with some robust unmanaged WebBrowser ActiveX host sample, like Lician Wishick's Webform:
http://www.wischik.com/lu/programmer/webform.html
If I could get it working reliably with the unmanaged host, I'd proceed with C# implementation.
I'd also try setting FEATURE_BROWSER_EMULATION to 8000 or less, to impose emulation of legacy IE behavior, just to check if it works that way.
That said, I wouldn't hold my hopes high. I've done my share of WebBrowser/MSHTML integration in the past, and I have a feeling that the APP support hasn't been regression-tested since IE9, in favor for new IE stuff aimed to embrace open web standards.
Updated, MSDN vaguely mentions this:
Upon successful completion, pbSecurityId contains the scheme, domain,
and zone information, as well as whether the specified pwszUrl was
derived from a Mark of the Web.
Here's the format which worked for me long ago (perhaps, way before "Mark of the Web" was introduced):
static const char security[] = "https:www.mysite.com\2\0\0"; // C++ puts the termination \0 for us
I believe, 2 stands here for the "Trusted Sites" zone. Other zones can be found here:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Lockdown_Zones
Hope this helps.
Maybe I'm wrong but, have you tried to send in your protocol headers Access-Control-Allow-Origin: *?

how to secure flash file from being downloaded or extracted in c#

I'm asked to develop a secured flash viewer in C# (WinForm) where flash files will be viewable through the viewer however being securely captured within the viewer - i.e. make it not extractable nor downloadable by any sniffer tools.
I haven't got a good solution for this yet, any one help?
I will make this in a form of an answer to stop bombarding the comment section.
The task you have at hand will be extremely difficult if you don't want to make your application very user unfriendly.
The reason for that is because if your program can decrypt the information locally then play the video file then a skilled user in reversed engineering can access the method of decryption and use it to dump the video as a file.
Now in case you want to make a licence method and have the users log in before they can use the program you will have two issues.
1) It will still be possible for a person that wants to crack the program to do so, the only thing he/she will need is a valid licence in this case, which in most cases they are stolen from other users. Something that is hard to notice server side except if you have someone constantly looking at the logs banning licences and handling the calls of the users that will be calling because their (stolen) licence is no longer working.
2) Put some kind of limitations server wide as to how many people can login with the credentials which will create more issues, people won't be able to use the software on two pcs at the same time for example. Even the problem above will still be an issue but users will complain why they can't login this time (since someone else will be using their licence.
Moral of the story ? There is always a way around things. Depends how much user experience you are willing to throw away in order to make your software just a bit more safer from being cracked.

Including Javascript on all websites on machine

I noticed that when using a 3G dongle to access the web. A javacript script is included at the end of any page that I visit. but just for (html, htm, php, asp, aspx). The script adds the functionality to download reduced quality images instead of full size, to save on bandwidth. However, it's function is irrelevant to my question.
I need to be able to do the same thing. For any request that comes into my machine, I would like a javascript include. But not a BHO or browser extention.
Does anyone know how this is done?
You would probably need to write a Web proxy engine to achieve this. Then you would configure it as either a transparent proxy (perhaps you would need to implement a network card driver for this), or configure all browsers on the machine to direct traffic through the proxy.
A 3G dongle may achieve this through various means, e.g. a filter inserted somewhere in the driver software, or may be even some processing occurs right in the hardware (less likely in my opinion).
I think I am going to use FiddlerCore as a service to do this. It seems to be a nice clean way of doing this.
http://www.fiddler2.com/Fiddler/Core/

How to capture visited URLs and their html by any browsers

I want to find a decent solution to track URLs and html content that users are visiting and provide more information to user. The solution should bring minimum impacts to end users.
I don't want to write plugins for different browsers. It's hard to maintain.
I don't accept proxy method, since I don't want to change any of user's proxy settings.
My application is writen in C# and targeting to Windows. It's best if the solution can support other OS as well.
Based on my research, I found following methods that looks working for me, but all of them have their drawbacks, I can't determine which one is the best.
Use WinPcap
WinPcap sniffers all TCP packets without changing any of user settings but only requires to install the WinPcap setup, which is acceptable to me. But I have two questions:
a. how to convert TCP packet into URL and HTML
b. Does it really impact the performance? I don't know if sniffer all TCP traffic is overhead for this requirment.
Find history files for different browsers
This way looks like the easist one, but I wonder if the solution is stable. I am not sure if the browser will stably write the history and when it writes to. My application will popup information before the user leave the current page. The solution won't work for me if browser writes to history file when user close the browser.
Use FindWindow or accessiblity object or COM interface to find the UI element which contains the URL
I find this way is not complete, for example, Chrome will only show the active tab's URL but not all of them.
Another drawback is that I have to request the URL another time to get its HTML content.
Any comment or suggestion is welcome.
BTW, I am not doing any spyware. The application is trying to find all RSS feeds from web page and show them to end users. I can easily do that in a browser plugin but I really want to support multiple broswers with single UI. Thanks.
Though this is very old post, I thought to just give an input.
Approach 1 of WinPcap is the best one. This will work for any browser, even builtin browser of any other installed application. The approach will be less resource consuming too.
There is a library Pcap.Net that has HTTP parser. You can construct http stream and use its httpresponsedatagram to parse the body that can be consumed by your application.
This link helped giving more insight to me -
Tcp Session Reconstruction with Winpcap

Printing from a .NET Service [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I am working on a project right now that involves receiving a message from another application, formatting the contents of that message, and sending it to a printer. The technology of choice is C# windows service. The output could be called a report, I suppose, but a reporting engine is not necessary. A simple templating engine, like StringTemplate, or even XSLT outputting HTML would be fine. The problem I'm having is finding a free way to print this kind of output from a service. Since it seems that it will work, I'm working on a prototype using Microsoft's RDLC, populating a local report and then rendering it as an image to a memory stream, which I will then print. Issues with that are:
Multi-page printing will be a big headache.
Still have to use PrintDocument to print the memory stream, which is unsupported in a Windows Service (though it may work - haven't gotten that far with the prototype yet)
If the data coming across changes, I have to change the dataset and the class that the data is being deserialized into. bad bad bad.
Has anyone had to do anything remotely like this? Any advice? I already posted a question about printing HTML without user input, and after wasting about 3 days on that, I have come to the conclusion that it cannot be done, at least not with any freely available tool.
All help is appreciated.
EDIT: We are on version 2.0 of the .NET framework.
Trust me, you will spend more money trying to search/develop a solution for this as compared to buying a third party component. Do not reinvent the wheel and go for the paid solution.
Printing is a complex problem and I would love to see the day when better framework support is added for this.
Printing from a Windows service is really painful. It seems to work... sometimes... but finally it craches or throws an exception from time to time, without any clear reason. It's really hopeless. Officially, it's even not supported, without any explanation, nor any proposal for an alternate solution.
Recently, I have been confronted to the problem and after several unsuccessful trials and experimentations, I came finally with two viable solutions:
Write your own printing DLL using the Win32 API (in C/C++ for instance), then use it from your service with P/Invoke (works fine)
Write your own printing COM+ component, then uses it from your service. I have chosen this solution with success recently (but it was third party COM+ component, not own written) It works absolutely fine too.
I've done it. It's a pain in the A*s. The problem is that printing requires that GDI engine to be in place, which normally means that you have to have the desktop, which only loads when you're logged in. If you're attempting to do this from a Service on a Server, then you normally aren't logged in.
So first you can't run as the normal service user, but instead as a real user that has interactive login rights. Then you have to tweak the service registry entries (I forget how at the moment, would have to find the code which I can do tonight if you're really interested). Finally, you have to pray.
Your biggest long term headache will be with print drivers. If you are running as a service without a logged in user, some print drivers like to pop up dialogs from time to time. What happens when your printer is out of toner? Or out of paper? The driver may pop up a dialog that will never be seen, and hold up the printer queue because nobody is logged in!
To answer your first question, this can be fairly straight forward depending on the data. We have a variety of Service-based applications that do exactly what you are asking. Typically, we parse the incoming file and wrap our own Postscript or PCL around it. If you layout is fairly simple, then there are some very basic PCL codes you can wrap it with to provide the font/print layup you want (I'd be more then happy to give you some guidance here offline).
One you have a print ready file you can send it to a UNC printer that is shared, directly to a locally installed printer, or even to the IP of the device (RAW or LPR type data).
If, however, you are going down the PDF path, the simplest method is to send the PDF output to a printer that supports direct PDF printing (many do now). In this case you just send the PDF to the device and away it prints.
The other option is to launch Ghostscript which should be free for your needs (check the licensing as they have a few different version, some GNU, some GPL etc.) and either use it's built in print function or simply convert to Postscript and send to the device. I've used Ghostscript many times in Service apps but not a huge fan as you will basically be shelling out and executing a command line app to do the conversion. That being said, it's a stable app that does tend to fail gracefully
Printing from a service is a bad idea. Network printers are connected "per-user". You can mark the service to be run as a particular user, but I'd consider that a bad security practice. You might be able to connect to a local printer, but I'd still hesitate before going this route.
The best option is to have the service store the data and have a user-launched application do the printing by asking the service for the data. Or a common location that the data is stored, like a database.
If you need to have the data printed as regular intervals, setup a Task event thru the Task Scheduler. Launching a process from a service will require knowing the user name and password, which again is bad security practice.
As for the printing itself, use a third-party tool to generate the report will be the easiest.
This may not be what you're looking for, but if I needed to do this quick&dirty, I would:
Create a separate WPF application (so I could use the built-in document handling)
Give the service the ability to interact with the desktop (note that you don't actually have to show anything on the desktop, or be logged in for this to work)
Have the service run the application, and give it the data to print.
You could probably also jigger this to print from a web browser that you run from the service (though I'd recommend building your own shell IE, rather than using a full browser).
For a more detailed (also free) solution, your best bet is probably to manually format the document yourself (using GDI+ to do the layout for you). This is tedious, error prone, time consuming, and wastes a lot of paper during development, but also gives you the most control over what's going to the printer.
If you can output to post script some printers will print anything that gets FTPed to a certain directory on them.
We used this to get past the print credits that our university exposed on us, but if your service outputs to a ps then you can just ftp the ps file to the printer.
We are using DevExpress' XtraReports to print from a service without any problems. Their report model is similar to that of Windows Forms, so you could dynamically insert text elements and then issue the print command.
I think we are going to go the third party route. I like the XSL -> HTML -> PDF -> Printer flow... Winnovative's HTML to PDF looks good for the first part, but I'm running into a block finding a good PDF printing solution... any suggestions? Ideally the license would be on a developer basis, not on a deployed runtime basis.
In answer to your question about PDF printing, I have not found an elegant solution. I was "shell" ing out to Adobe which was unreliable and required a user to be logged in at all times. To fix this specific problem, I requested that the files we process (invoices) be formatted as multi-page Tiff files instead which can be split apart and printed using native .NET printing functions. Adobe's position seems to be "get the user to view the file in Adobe Reader and they can click print". Useless.
I am still keen to find a good way of producing quality reports which can be output from the web server...
Printing using System.Drawing.Printing is not supported by MS, as per Yann Trevin's response. However, you might be able to use the new, WPF-based, System.Printing (I think)

Categories