Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Allow the App to Print without showing the Confirmation Dialog to user #124

Open
TonyHenrique opened this issue Mar 18, 2020 · 45 comments

Comments

@TonyHenrique
Copy link

Proposal: Allow the App to Print without showing the Confirmation Dialog to user

Summary

We should be able to programatically list printers, select the printer, configure paper size, orientation, settings... and PRINT without user interaction.

Rationale

I was trying to make a Touch Screen Kiosk Receipt Print application on UWP, but the samples show

await Windows.Graphics.Printing.PrintManager.ShowPrintUIAsync();
This brings the UWP Print Dialog.

I need to print directly without this dialog. How to do this?

I need something like

await Windows.Graphics.Printing.PrintManager.PrintAsync();
We should be able to programatically list printers, select the printer, configure paper size, orientation, settings...

This will enable:

  • Enable easy printing from Voice / Touch applications
  • Make the printing API more complete, like the WPF Printing API was.
  • This Permission will be very useful for ATM Applications, Touch Screen Kiosk Apps, Barcode Printing Software, Point of Sale applications, Line-of-Business Applications, etc;

Scope

Capability Priority
This proposal will allow developers Print without user interaction. Must
This proposal will allow the App to Configure Paper Size Must
This proposal will allow the App to Set Page Orientation Must
This proposal will allow the App to List printers Must
This proposal will allow end users to give the Printing without interaction permission on app install (AllowPrintingWithoutUserIteraction) Should
This proposal will allow the App to Change the Default Printer Could
This proposal will allow the App to set Printing Settings like Color, Grayscale, Draft Could

Important Notes

This may require the creation of a new permission/capability for UWP AppModel:
AllowPrintingWithoutUserIteraction

Open Questions

@mrlacey
Copy link

mrlacey commented Mar 18, 2020

A separate capability for this would be good because it makes it clear that this is a special scenario, should be treated differently, and is probably not for everybody.

Even with this setting/capability I still think there's value in the user having to opt-in to silent printing through the UI once. This will avoid any app from surprising users by printing without ever showing any UI indicating that it wants to print. This would be comparable with requesting location or other potentially sensitive information that the user may not want.

This should also be an app level setting that can be revoked in future if the user desires.

For scenarios like kiosks that need to print and not desktop style apps that are more likely to be used by a single person for longer, such devices/apps still need initial configuration which would include testing the printer configuration and therefore enabling this setting.

@mdtauk
Copy link

mdtauk commented Mar 18, 2020

It could be a permission that only presents it's permission dialog on the first programmatic print - rather than just at install, or first run of the app.

@TonyHenrique
Copy link
Author

I suppose that this will be useful to enable to use Windows10X with UWP instead of Win32, for those scenarios.

I also sent a message about this to Stefan Wick, he said:
... Not a WinUI limitation, but a limitation of the appmodel you chose. When you build a WinUI app with Win32 appmodel it will work, but not with UWP appmodel.
https://twitter.com/StefanWickDev/status/1240099309204287488

But anyways, I believe that the WinUI team can redirect this request, as this is required to increase the success of the WinUI, allowing it to be used in more scenarios, like the ones that I described.

@Felix-Dev
Copy link

@TonyHenrique IMO you are correct in posting this issue here even if it's not directly WinUI related. There is just no other platform out there right now to discuss UWP app model/WinRT improvements and where we can be confident at least someone from MS will take a look at it and redirect it internally if required (yes, MS keeps repeating they listen to feedback even in the feedback hub but the perception of the feedback hub among the community is really bad). The WinUI team recognizes this feedback platform issue and thus tolerates community input discussing (fundamental) UWP issues.

@mdtauk
Copy link

mdtauk commented Mar 18, 2020

I know this is further out of scope, but it may be worth looking at a possible opt in permission system for WinUI Desktop. Giving the user peace of mind, without the Win32 free for all, and less restrictive than UWP.

Either creating new sets of permissable actions, or a way to detect if an action could be abused, and display a general "Are you sure you want to do XXXX" permission. With Just Once Always and Never options.

@ranjeshj
Copy link

@takashi-moriyama as FYI

@jesbis jesbis transferred this issue from microsoft/microsoft-ui-xaml Jul 21, 2020
@ghost ghost added the needs-triage label Jul 21, 2020
@jonwis
Copy link
Member

jonwis commented Jul 21, 2020

This is very similar to existing issue #52, but has more detail. @AwsomeCode would you mind if we made this the primary since it has the "proposal" format with details? What else would you want to add to the proposal?

@AwsomeCode
Copy link

@jonwis Ya, this one will cover my requirement as well. You can make this primary.

@jonwis jonwis added area-UWP Support for UWP apps and removed needs-triage labels Jul 21, 2020
@ptorr-msft
Copy link
Contributor

@TonyHenrique FYI we do not show consent prompts on install[1]; we show them on first-use (more correctly: the first time the app requests the permission, which might be before it actually "uses" it, depending on how the app is written and the specific API in question). Otherwise, agreed that this feature would need a permission that the user could consents to and can later change their mind in Settings.

[1] We do perform a UAC prompt for anything that impacts the machine / other users during install.

@stevewri
Copy link
Contributor

Moving to backlog for future potential feature work.

@AwsomeCode
Copy link

@stevewri This wont be available on WinUI3 ?

@ptorr-msft
Copy link
Contributor

This wont be available on WinUI3 ?

Printing without confirmation requires work at the security / isolation level, not just the UI level.

@AwsomeCode
Copy link

This is so much import for retail softwares. Without this we can't convert WPF apps to UWP/WinUI3

@Felix-Dev
Copy link

Felix-Dev commented Oct 16, 2020

@AwsomeCode You should be able to print without a UI confirmation dialog if you will port your WPF apps to WinUI 3 desktop apps. @ptorr-msft's comment is about (WinUI 3) UWP apps (since the requested change will require changes in the UWP app model implementation and that's not something WinUI is responsible for).

@elielson-anjos
Copy link

I'm trying to build a POS application with UWP, can't get the POS to recognize the cheaper thermal printers out there, I'm waiting on this to be realeased so I can properly deal with the printers that are not supported by the POS namespace.

@ptorr-msft
Copy link
Contributor

@Rothanan can you share the details of the printers that don't work? Are they specifically sold as POS devices that adhere to the POS standards?

@AwsomeCode
Copy link

AwsomeCode commented Oct 21, 2020

@ysc3839
Copy link

ysc3839 commented Oct 21, 2020

I wonder how macOS deal with such issue. Is there a "print permission", or apps are allowed to print without confirm?

@elielson-anjos
Copy link

@ptorr-msft they are very basic printers, they only work through ESC/POS. I can get them working on android, but not in UWP:

Here's a model:
https://www.amazon.com/Wireless-Bluetooth-MUNBYN-Portable-Compatible/dp/B07N86DR4J

They are sold mainly as mobile bluetooth thermal printers(they also come with an usb conection) and because they are cheaper most customers wanna buy and use them.

@mdtauk
Copy link

mdtauk commented Oct 21, 2020

POS printers, sounds like an IOT device situation, and that supports device drivers right? Which would allow direct talking to the printer device right?

@elielson-anjos
Copy link

elielson-anjos commented Oct 21, 2020

Yeah, you're right, in android devices, all I do is send ESC/POS commands directly to the printer.

I'm looking for a way to do the same in UWP, in a Desktop environment.

@ptorr-msft
Copy link
Contributor

@Rothanan thanks for the info; I will send to the POS team internally to see if they know of any issues with these devices.

@AwsomeCode
Copy link

@ptorr-msft any update from pos team?

@ptorr-msft
Copy link
Contributor

Sorry @AwsomeCode , some rather urgent personal stuff came up and I've been distracted. Tracking them down now and will pass along. Thanks for the reminder.

@elielson-anjos
Copy link

Sorry to bother, but, any news on this?

@ptorr-msft
Copy link
Contributor

Can you confirm if you are using the POS APIs or the regular printing APIs?

@AwsomeCode
Copy link

In UWP
Its not POS APIs or Regular Printing API.
I have tried RawPrint
Which sends RAW ESC/POS data commands to printer and it print silently on printer. It works in debug mode. But on published app its not allowed.
For published app we have to use Desktop Extension for UWP. Which is not best experience in development. (Our UWP app never get approved in store. They say its crashing and In our machines its working fine.)

In Android
Sending RAW ESC/POS data commands via Bluetooth and its gets print silently.

In iOS
Printer is not getting connected via Bluetooth.

Below are the printers I am referring to.
https://www.atpos.in/product/atpos-usb-bluetooth-e-200-portable-thermal-receipt-printer/
https://www.atpos.in/product/atpos-hop-h58-58mm-thermal-receipt-printer/

@ptorr-msft
Copy link
Contributor

I have tried RawPrint
Which sends RAW ESC/POS data commands to printer and it print silently on printer. It works in debug mode. But on published app its not allowed.

That project says it relies on .NET 4, which isn't supported for UWP apps (only .NET Native is supported). Can you pair the printers first and then use the POS API?

@AwsomeCode
Copy link

I have tried this sample project it did not worked.
https://docs.microsoft.com/en-us/samples/microsoft/windows-universal-samples/posprinter/

@elielson-anjos
Copy link

Can you confirm if you are using the POS APIs or the regular printing APIs?

I tried using the POS API, it doesn't recognize the ESC/POS printer, the POS API support very few printers which renders it unusable.

We are just looking for a away to send ESC/POS commands to ANY printer that understands it.

@elielson-anjos
Copy link

I did get it working in UWP using the code bellow, but it doesn't go trhough to the app store, it says I can't use these APIs.

public class RawPrintingService
  {
      // Structure and API declarions:
      [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
      public class DOCINFOA
      {
          [MarshalAs(UnmanagedType.LPStr)]
          public string pDocName;
          [MarshalAs(UnmanagedType.LPStr)]
          public string pOutputFile;
          [MarshalAs(UnmanagedType.LPStr)]
          public string pDataType;
      }

      [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
      public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);

      [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
      public static extern bool ClosePrinter(IntPtr hPrinter);

      [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
      public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);

      [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
      public static extern bool EndDocPrinter(IntPtr hPrinter);

      [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
      public static extern bool StartPagePrinter(IntPtr hPrinter);

      [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
      public static extern bool EndPagePrinter(IntPtr hPrinter);

      [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
      public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);

      // SendBytesToPrinter()
      // When the function is given a printer name and an unmanaged array
      // of bytes, the function sends those bytes to the print queue.
      // Returns true on success, false on failure.
      public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
      {
          Int32 dwError = 0, dwWritten = 0;
          IntPtr hPrinter = new IntPtr(0);
          DOCINFOA di = new DOCINFOA();
          bool bSuccess = false; // Assume failure unless you specifically succeed.

          di.pDocName = "RAW Document";
          // Win7
          di.pDataType = "RAW";

          // Win8+
          // di.pDataType = "XPS_PASS";

          // Open the printer.
          if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
          {
              // Start a document.
              if (StartDocPrinter(hPrinter, 1, di))
              {
                  // Start a page.
                  if (StartPagePrinter(hPrinter))
                  {
                      // Write your bytes.
                      bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                      EndPagePrinter(hPrinter);
                  }
                  EndDocPrinter(hPrinter);
              }
              ClosePrinter(hPrinter);
          }
          // If you did not succeed, GetLastError may give more information
          // about why not.
          if (bSuccess == false)
          {
              dwError = Marshal.GetLastWin32Error();
          }
          return bSuccess;
      }

      public static bool SendFileToPrinter(string szPrinterName, string szFileName)
      {
          // Open the file.
          FileStream fs = new FileStream(szFileName, FileMode.Open);
          // Create a BinaryReader on the file.
          BinaryReader br = new BinaryReader(fs);
          // Dim an array of bytes big enough to hold the file's contents.
          Byte[] bytes = new Byte[fs.Length];
          bool bSuccess = false;
          // Your unmanaged pointer.
          IntPtr pUnmanagedBytes = new IntPtr(0);
          int nLength;

          nLength = Convert.ToInt32(fs.Length);
          // Read the contents of the file into the array.
          bytes = br.ReadBytes(nLength);
          // Allocate some unmanaged memory for those bytes.
          pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
          // Copy the managed byte array into the unmanaged array.
          Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
          // Send the unmanaged bytes to the printer.
          bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
          // Free the unmanaged memory that you allocated earlier.
          Marshal.FreeCoTaskMem(pUnmanagedBytes);
          fs.Close();
          fs.Dispose();
          fs = null;
          return bSuccess;
      }
      public static bool SendStringToPrinter(string szPrinterName, string szString)
      {
          IntPtr pBytes;
          Int32 dwCount;
          // How many characters are in the string?
          dwCount = szString.Length;
          // Assume that the printer is expecting ANSI text, and then convert
          // the string to ANSI text.
          pBytes = Marshal.StringToCoTaskMemAnsi(szString);
          // Send the converted ANSI string to the printer.
          SendBytesToPrinter(szPrinterName, pBytes, dwCount);
          Marshal.FreeCoTaskMem(pBytes);
          return true;
      }
  }

@elielson-anjos
Copy link

I had to create a WPF app just to receive a URI with a path to a text file and them print it.

@AwsomeCode
Copy link

@ptorr-msft any update from the pos team?

@ptorr-msft
Copy link
Contributor

@AwsomeCode
Copy link

Can pos team provided any sample for
MUNBYN Android Bluetooth Mobile Thermal Receipt Printer, MUNBYN 2 Inches 58MM Impresora térmica Printer with Leather Belt for Business ESC/POS, Does NOT Support iOS Devices,Square https://www.amazon.com/dp/B0753B5KYG/ref=cm_sw_r_cp_api_fabt1_IN-TFbH0SH19A

@elielson-anjos
Copy link

Sorry, I've been out of the office. I got this link:

https://docs.microsoft.com/en-us/windows/uwp/devices-sensors/pos-device-support#receipt-printer-posprinter

Thanks for the link, but, we've all stumbled upon this link and it does nothing for what we are trying to achieve.

We just wanna be able to silently print stuff, if for that we need to request permission for the user, so be it.

It would be awesome to also be able to send esc/pos commands directly to the printer, just like in the code I posted above. It works on debug mode but it doesn't pass to the Microsoft Store because it says I'm using APIs that are not always available.

@AwsomeCode
Copy link

@ptorr-msft I also have same situation as Rothanan

@AwsomeCode
Copy link

@ptorr-msft can someone from the POS team can post on this issue?

@ptorr-msft
Copy link
Contributor

Since this is now about POS printing, and not general consumer printing without prompts, can you start a new issue?

@TonyHenrique
Copy link
Author

In my case, I was planning to use general consumer printers from UWP without the user prompts for each printing job, using something like a PrintAsync instead of ShowPrintUIAsync . It would be OK if this may require the creation of a new permission/capability for UWP AppModel like: AllowPrintingWithoutUserIteraction

@elielson-anjos
Copy link

I'm with @TonyHenrique, I need that too.

@DoubleDBE
Copy link

DoubleDBE commented Feb 4, 2021

Hi everyone,

We develop POS software and we heavily rely on the printing options in WPF.

For example we create our layouts in XAML for receipt tickets / invoices / labels etc, even almost everything if I think about it.

We primarily use the PrintVisual method that we can use in WPF to print our XAML layouts to all kinds of printers.

Due to the nature of our clients (restaurants etc) they need to be able to quickly print a receipt without being bothered with dialogs before they can actually print something.

Is this something that wil be implemented in / ported to WinUI 3 Desktop?

@mirzodalerm
Copy link

We need this too.

@wolfgang-ironsoftware
Copy link

I wonder how macOS deal with such issue. Is there a "print permission", or apps are allowed to print without confirm?

I don't believe macOS APIs for printing require permission. Actually Apple's printing API has a boolean that indicates whether to show or hide the dialog. So just setting the boolean to false will print without showing the dialog.

@MoStAfAmAhMoUdAbDo
Copy link

i am new in flutter develop and i want to make direct print for pdf file without showing the preview of printing for the user and make this for printer device that in the same network and i have its ip address .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests