I've created a service which accepts PDF files from other computers using a socket, and then prints it to a connected printer. The code for this is written in Python.
I've tested this application by running the Python script manually, and everything works as expected. The script creates a socket, accepts a PDF file, pushes it to its queue and then prints the file.
I've created a Windows Service for this script using NSSM - the Non-Sucking Service Manager.
The service runs my Python script fine as well, only, when it is trying to print to a printer, I get an error that there is no application associated for the PDF file. Which is weird, because I do have a standard program assigned to PDF (Adobe Acrobat Reader), and it does work when running the script manually.
The Python script executes PowerShell commands to set the default printer and then print the file using Adobe (which prints to the default printer).
Here is the snippet from my script that is responsible for this printing:
cmd_set_default_printer = "powershell.exe (New-Object -ComObject WScript.Network).SetDefaultPrinter('{0}')".format(printer_data['name'])
cmd_print_file = "powershell.exe Start-Process -FilePath '{0}' -Verb Print".format(item['file'])
cmd_close_acrobat = "powershell.exe Stop-Process -Name Acrobat -Force"
cmd_delete_file = "powershell.exe Remove-Item -Path '{0}'".format(item['file'])
self.logger.info('[+] Printing file {0}'.format(item['file']))
p = subprocess.Popen(cmd_set_default_printer, stdout=subprocess.PIPE)
p_out = p.communicate()
if p.returncode != 0: # non-zero return code means a failure
self.logger.error('[!] An error occured: {0}'.format(p_out))
self.db.set_item_status(item['id'], self.db.STATUS_FAILED)
continue
time.sleep(2)
p = subprocess.Popen(cmd_print_file, stdout=subprocess.PIPE)
p_out = p.communicate()
if p.returncode != 0:
self.logger.error('[!] An error occured: {0}'.format(p_out))
self.db.set_item_status(item['id'], self.db.STATUS_FAILED)
continue
time.sleep(5)
self.logger.info('[+] OK. Deleting file {0}'.format(item['file']))
p = subprocess.Popen(cmd_close_acrobat, stdout=subprocess.PIPE)
p_out = p.communicate()
p = subprocess.Popen(cmd_delete_file, stdout=subprocess.PIPE)
p_out = p.communicate()
When running the service and pushing a file to it, I get an error. These are my logs:
2023-01-16 15:13:20,589 - server_logger - INFO - [*] Listening as 0.0.0.0:50001
2023-01-16 15:13:20,620 - server_logger - INFO - [*] Connected to database
2023-01-16 15:20:40,916 - server_logger - INFO - [+] ('192.168.1.252', 44920) is connected.
2023-01-16 15:20:40,916 - server_logger - INFO - [+] Receiving new file... saving as wbcfaolzropovcui.pdf
2023-01-16 15:20:40,916 - server_logger - INFO - [+] Queue file for printing...
2023-01-16 15:20:40,942 - server_logger - INFO - [+] Queued.
2023-01-16 15:20:40,942 - server_logger - INFO - [+] Done receiving, closing socket.
2023-01-16 15:20:40,942 - server_logger - INFO - [+] Socket closed.
2023-01-16 15:20:41,309 - server_logger - INFO - [+] Printing file C:\.cloudspot\ecosyerp-printing\python_backend\print_queue\wbcfaolzropovcui.pdf
2023-01-16 15:20:44,012 - server_logger - ERROR - [!] An error occured: (b"Start-Process : This command cannot be run due to the error: Er is geen toepassing gekoppeld aan het opgegeven bestand \nvoor deze bewerking.\nAt line:1 char:1\n+ Start-Process -FilePath 'C:\\.cloudspot\\ecosyerp-printing\\python_backe ...\n+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n + CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException\n + FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand\n \n", None)
The error is in Dutch but translates to:
No application is associated with the specified file for this operation
Which leaves me scratching my head because when I do not run the script as a service, but directly from the CMD, then it works without a problem.
Is there any reason why inside a service it would not work and outside it does?
Thanks to Mathias R. Jessen who pointed me to the fact that the service does not run under the local account, but a system account. This system account did not have a default application for PDF files.
I was able to resolve the issue by letting the service run under an account that does have the default application set for PDF files.
Printing from the service did not work, but that was an issue with Adobe Acrobat Reader. I switched to FoxIt PDF Reader and was able to print using the service without an issue.