【问题标题】:Run Powershell Command from Oracle Procedure从 Oracle 过程运行 Powershell 命令
【发布时间】:2019-10-17 00:54:45
【问题描述】:

我需要将 pdf 文档从我的 android studio 应用程序打印到我的网络打印机。我想按原样打印所有图像和格式的 pdf,但是,我找到的解决方案只允许从 pdf 中提取和打印文本。

我还看到了提到 Ghostscript 等工具的解决方案,这些工具应该将 pdf 转换为 postscript 文件,但这些工具不适用于 Android Studio,或者至少我还没有弄清楚如何将它们集成到我的应用。我无法为 jPDFPrint 之类的工具付费,而这些工具正是我所需要的。

我开始考虑一种变通方法,并产生了将我的 pdf 作为 blob 发送到我的 oracle 数据库并从过程调用 power shell 命令以将其打印到特定打印机的想法。

我已经创建并测试了以下命令以从我的 PC 打印到我的网络打印机,效果很好。

    Start-Process -FilePath “c:\test.pdf” –Verb PrintTo '\\PrintServer\PrinterName' -PassThru | %{sleep 10;$_} | kill

现在我需要有关 oracle 部分的帮助。是否可以从 oracle 12c 中调用或运行 powershell 命令并将 pdf blob 以及打印机名称传递给它?

【问题讨论】:

  • 他的数据库在什么操作系统上? Poweshell 暗示您希望它在 Windows 上运行。
  • @TenG 抱歉没有指定。我有一个windows环境。确切地说是 Windows Server 2016。
  • 澄清一下,您需要将 BLOB 本身传递给 Oracle,还是将路径传递给 PDF?
  • @TenG 我设想将 blob 和打印机名称从我的 android 应用程序传递到我的 oracle 程序,然后在程序中运行脚本进行打印。理想情况下,我不想在数据库服务器的数据库或文件系统中存储任何内容。
  • 在尝试提供帮助之前,请先说明清楚。 android 应用程序将使用打印机名称将 blob 保存到 Oracle 数据库。然后,一项工作将把这个 blob 提取到一个 PDF 文件,并在 Win 2016 的 Oracle 数据库服务器上发出一个 powershell 命令。对吗?

标签: android oracle powershell oracle12c


【解决方案1】:

将 BLOB 提取为 PDF。

创建您的系统文件夹,例如c:\printthis

然后创建映射到这个文件夹的Oracle目录对象:

CREATE OR REPLACE DIRECTORY print_dir AS 'C:\print_this';

GRANT READ WRITE ON DIRECTORY print_dir TO PUBLIC;

此过程将 BLOB 提取到文件中。

CREATE OR REPLACE PROCEDURE extract_pdf ( p_id IN VARCHAR2 ) AS
   CURSOR c1 IS 
      SELECT doc_blob, doc_name
      FROM doc_table
      WHERE doc_id = p_id;
   r1         c1%ROWTYPE;
   v_size     NUMBER( 5,0) := 32000;
   v_len      NUMBER(38,0);
   v_buffer   RAW(32000);
   v_file     UTL_FILE.FILE_TYPE;
BEGIN
   OPEN c1;
   FETCH c1 INTO r1;
   v_file  := UTL_FILE.FOPEN('PRINT_DIR', r1.doc_name, 'wb', 32760 );
   v_start := 1;
   v_len   := DBMS_LOB.GETLENGTH( r.bbl_fic );
   WHILE v_start <= v_len LOOP
      DBMS_LOB.READ(
             r.bbl_fic,
             LEAST( v_len - v_start + 1, v_size ),
             v_start,
             v_buffer
           );
      UTL_FILE.PUT_RAW( v_file, v_buffer );
      UTL_FILE.FFLUSH( v_file ); 
      v_start := v_start + v_size;
    END LOOP;
    UTL_FILE.FCLOSE( v_file );
--  Write the CMD file
    v_file := UTL_FILE.FOPEN('PRINT_DIR', r1.doc_name || '.bat', 'w' );
    UTL_FILE.PUT_LINE(     'Start-Process -FilePath “c:\print_this\' || r1.doc_name || '” –Verb PrintTo '\\PrintServer\PrinterName' -PassThru | %{sleep 10;$_} | kill' );
    UTL_FILE.CLOSE(v_file);
END;
/

运行的 Windows At 作业,轮询 c:\print_this 文件夹中的文件并运行 .bat 命令,然后将其删除。

@ECHO OFF
setlocal enabledelayedexpansion
for %%f in (c:\print_this\*.bat) do (
  echo "Name: %%f"
  powershell %%f
  del %%f
)

问题仍然是如何将它们缝合在一起。您的 Android 应用程序调用您的过程以将 PDF 存储为 BLOB。它还必须能够调用上面建议的过程来将保存的 BLOB 提取到数据库服务器文件中,因此在保存 BLOB 之后调用这个提取 ODF 并创建打印 bat 脚本的过程。

Task Scheduler 作业轮询 bat 脚本的目录,运行它们会删除它们。

您不能从 Oracle 中直接向服务器主机发出命令。您可以使用 DBMS_SCHEDULER。在上面的示例中,作业将 doc_id 作为参数,并通过 DBMS_SCHEDULER.RUN_JOB 执行此操作。我不记得如何准确地做到这一点,但我希望我对 Windows 中的任务计划程序的其他建议对您有所帮助。

【讨论】:

  • 非常感谢@TenG。感谢您的帮助和示例代码。我将尝试实现这一点,并让你知道它是如何进行的。
【解决方案2】:

您可以使用 PL/SQL 包 DBMS_SCHEDULER 过程 create_program,使用 program_type=>'EXECUTABLE' 来执行您想要的操作。然后,您将让将数据发送到 oracle 的进程创建一个作业来调用该程序。 DBMS_SCHEDULER 包非常复杂,因此您可能需要四处寻找教程/提示;你可能想搜索https://asktom.oracle.com 寻找初学者。

【讨论】:

  • Mark 的回答对于调用 powershell 是正确的。但是,无论如何,通过 Oracle 推送 PDF 会给您带来什么,我有点困惑。您不能直接从应用程序调用类似的命令吗?
  • @MArk Stewart 我尝试了 DBMS_SCHEDULER,但无法让它工作。每当我运行它而没有给我错误时,该作业都会失败。
  • @Carlovski 对我来说,一等奖将是执行您的建议,但我似乎无法找到解决方法,这就是我想到解决方法的原因。如果有办法从我的应用程序中做到这一点,请与我分享。
  • 正如我所暗示的,DBMS_SCHEDULER 的设置非常复杂;您可能没有为作业设置凭据,这基本上是告诉 Oracle 使用什么 Windows 用户和密码来调用 Powershell 程序,并且您还需要允许 Oracle 访问 Powershell 程序所在的目录,并且.. . 创建一个oracle目录等等
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-16
  • 1970-01-01
  • 2016-05-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多