更接近绕过 Flex 打印对话?

发布于 2024-11-16 17:08:28 字数 2998 浏览 6 评论 0原文

我知道这是一个相当沉重的话题,并且一直看到对此的请求(我相信阻止它的立场与安全相关)。

当我尝试在 AIR 中进行 ZPL 打印时,我遇到了一些有趣的事情。

查看其他编程语言及其打印到 ZPL 的尝试,大多数语言都通过文件流处理它,并将打印机视为文件(请参阅此处的 .NET 示例 将 ZPL 发送到 Zebra 打印机的 .NET 代码)。

我在 Flex 中采用了这种方法,并得到了一些有趣的结果。

我测试了直接与我自己的 PC 上的网络共享打印机通信。这是一段简单的代码:

var file:File = new File('\\\\PC-Name\\Printer-Name');
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);

显然,您需要填写自己的 PC 名称(网络名称)和打印机名称(打印机的共享名称)信息。

如果您观察打印机,您会注意到它确实根据此请求启动假脱机。

不幸的是,这就是我所能做到的。启动任何形式的实际写入该流似乎不起作用(尽管我远非这方面的专家,但我可能会遗漏一些东西)。

逐步执行类似的操作:

var file:File = new File('\\\\PC-Name\\Printer-Name');
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);
stream.close();

您可以看到它在打开时撞击假脱机程序,然后成功关闭,没有任何不良影响。

一旦你添加了一个实际的写入,例如:

var byteArray:ByteArray = new ByteArray();
byteArray.writeUTFBytes("Hello World");
byteArray.position = 0;

var file:File = new File('\\\\PC-Name\\Printer-Name');
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);
stream.writeBytes(byteArray, 0, byteArray.length);
stream.close();

不幸的是,一切都会陷入困境。

关于变量和发生的情况需要注意的一些事项:

声明文件后 (var file:File = new File('\\PC-Name\Printer-Name');),当您检查 file 变量时,您会注意到很少有问题。 creationDate、modificationDate 和 size 都有“getter 引发的异常”错误。更具体地说,“错误:错误#3003:文件或目录不存在。”。我不太关心这些,因为它不是文件,而是打印机。

打开流 (stream.open(file, FileMode.WRITE);) 并检查流变量后,“bytesAvailable”出现“getter 引发的异常”(错误:错误 #2029:此 URLStream 对象没有打开流)。再说一遍,它不是一个文件,因此像这样的 bytesAvailable 可能没问题(或者这可能是此后所有内容似乎失败的原因)。此时,您的打印队列中还将有一个状态为“假脱机”的打印文档。

调用stream.writeBytes(byteArray, 0, byteArray.length);导致流变量位置从 0 移动到 167(我的 byteArray 的长度)。所以它似乎认为它试图写。这里似乎没有发生任何“坏”事情......

调用stream.close();然而,导致整个事情崩溃并出现“Error #2038: File I/O Error.at flash.filesystem::FileStream/close()

在这里发布此内容以查看是否有人有任何想法(我错过了什么吗?是吗?)完全不可能?关闭但没有雪茄?)

******** 更新************

我确实找到了一种使用网络打印机来完成此操作的方法(不幸的是不是使用 Windows 共享打印机)。我可以使用套接字而不是文件流。几乎可以保证,这会在实际发布时引发一些沙箱违规,因此需要进行处理(我假设是套接字策略文件),

public var socket:Socket = new Socket();
socket.addEventListener( Event.CONNECT, onConnect);
socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData);
socket.connect(ip_address, 9100);

private function onConnect(event : Event) : void {
  var byteArray:ByteArray = new ByteArray();
  byteArray.writeUTFBytes("Hello World");
  byteArray.position = 0;

  socket.writeBytes(byteArray, 0, byteArray.length);
  socket.removeEventListener(Event.CONNECT, onConnect);
  socket.removeEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
  socket.flush();
  socket.close();
}

public function onSocketData(event:Event):void {
  trace("onSocketData Fired");
}

不确定是否可以通过套接字连接到 Windows 共享打印机(即连接到的打印机 )。某人的电脑和共享)到目前为止,我还没有任何运气,但是,如果您严格处理网络打印机,这可能适合您跳过/绕过柔性打印对话。

I know this is a pretty heavy topic and see requests for it all the time (I believe the stance for blocking it is security related).

While messing around trying to get ZPL printing working in AIR, I ran into something interesting.

Looking at other programming languages and their attempts to print to ZPL, most of them handle it through a File Stream and treat the printer as a file (see here for a .NET example .NET code to send ZPL to Zebra printers).

I took this approach with Flex and got some interesting results.

I tested this talking directly to a network shared printer on my own PC. It's a simple piece of code:

var file:File = new File('\\\\PC-Name\\Printer-Name');
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);

Obviously you will need to fill in your own info for PC-Name (network name) and Printer-Name (printer's shared name).

If you watch your printer, you'll notice that it does initiate spooling with this request.

Unfortunately, this is about as far as I'm able to get with it. Initiating any sort of actually writing over that stream doesn't seem to work (although I'm far from an expert on the matter, I could be missing something).

Stepping through something like:

var file:File = new File('\\\\PC-Name\\Printer-Name');
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);
stream.close();

You can watch it hit the spooler with the open and then successfully close without any ill effects.

Once you add an actual write though such as:

var byteArray:ByteArray = new ByteArray();
byteArray.writeUTFBytes("Hello World");
byteArray.position = 0;

var file:File = new File('\\\\PC-Name\\Printer-Name');
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);
stream.writeBytes(byteArray, 0, byteArray.length);
stream.close();

It all goes to hell unfortunately.

Some things to note about the variables and what happens:

After declaring your file (var file:File = new File('\\PC-Name\Printer-Name');), when you inspect the file variable you'll notice a few issues. creationDate, modificationDate, and size all have "exception thrown by getter" errors. More specifically "Error: Error #3003: File or directory does not exist.". I'm not overly concerned with these as it isn't a file, it's a printer.

After opening the stream (stream.open(file, FileMode.WRITE);) and inspecting the stream variable the "bytesAvailable" has an "exception thrown by getter" (Error: Error #2029: This URLStream object does not have a stream opened). Once again, it isn't a file so the bytesAvailable like this might be okay (or it may be the reason everything after this seems to fail). At this point, you will also have a print document with a status of "Spooling" in your print queue.

Calling stream.writeBytes(byteArray, 0, byteArray.length); causes the stream variable position to move from 0 to 167 (the length of my byteArray). So it seems to think it attempts to write. Nothing "bad" seems to happen here.....

Calling stream.close(); however, brings the whole thing crashing down with a "Error #2038: File I/O Error. at flash.filesystem::FileStream/close()

Posting this here to see if anyone has any ideas (am I missing something? Is it completely not possible? Close but no cigar?)

******** UPDATE *********

I did find a way to accomplish this with a network printer (unfortunately not with a windows shared printer). It is using sockets instead of filestreams. I can almost guarantee you this will throw some sandbox violations upon an actual release so that will need to be handled (socket policy files I would assume).

public var socket:Socket = new Socket();
socket.addEventListener( Event.CONNECT, onConnect);
socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData);
socket.connect(ip_address, 9100);

private function onConnect(event : Event) : void {
  var byteArray:ByteArray = new ByteArray();
  byteArray.writeUTFBytes("Hello World");
  byteArray.position = 0;

  socket.writeBytes(byteArray, 0, byteArray.length);
  socket.removeEventListener(Event.CONNECT, onConnect);
  socket.removeEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
  socket.flush();
  socket.close();
}

public function onSocketData(event:Event):void {
  trace("onSocketData Fired");
}

Not sure if one can even connect over a socket to a windows shared printer (ie a printer connected to someone's PC and shared). So far I haven't had any luck. But, if you are strictly dealing with networked printers this might work for you to skip/bypass the flex print dialogue.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一绘本一梦想 2024-11-23 17:08:28

我做了一些假设:如果您使用 AIR 并且有一个有效的 .Net 解决方案,并且您仅针对 Windows...为什么不直接使用 .Net 解决方案并使用 NativeProcess 类?

基本上,您将 ZPL .NET 打印机编译为 EXE,并使用 NativeProcess 调用它,并传入打印机字符串。

这样您仍然可以拥有漂亮的 Flexy 界面,同时获得本机打印控件。

I'm making a few assumptions: If you're using AIR and you have a working .Net solution and you are targeting Windows only... why not just use the .Net solution and call it using NativeProcess class?

Basically you compile the ZPL .NET printer as an EXE and call it using NativeProcess, passing in the printer string.

That way you can still have a nice Flexy interface but get native printing controls.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文