有没有办法正确结束与 QuickBooks/QBW32.exe 的会话,这样它就不会在后台停留 运行?

Is there a way to properly end a session with QuickBooks/QBW32.exe so it does not stay running in the background?

我对许多使用 QuickBooks SDK 执行各种功能的程序执行技术支持和一些开发。最近我注意到当用户执行以下操作时:

先决条件: - QuickBooks 未在桌面上打开,目前未 运行ning。 - 我的桌面程序未在 QuickBooks 集成应用程序列表中设置为自动登录。

1) 打开我的程序之一。

2) 执行启动与 QuickBooks 的连接和会话的操作。

3) QuickBooks 界面 returns 一个错误,指出您必须打开 QuickBooks 并登录公司文件才能执行此操作。

4) 我的程序关闭会话和连接,然后向用户显示一些对话框,为他们提供故障排除提示。

结果:

QuickBooks 本身继续在后台 运行 作为 QBW32.exe,即使会话和连接都已关闭。

如果用户随后尝试打开 QuickBooks 桌面程序,他们会收到一条错误消息,告诉他们 QuickBooks 已经 运行ning。然后,他们必须在 windows 中打开任务管理器并关闭 运行ning QBW32.exe 才能成功打开 QuickBooks。

我使用下面编写的非常基本的 C# 程序重现了这个。

在测试应用程序中,我使用以下 steps/scenario:

先决条件:1) 测试应用程序未设置为自动登录到 QuickBooks。它被设置为仅当用户打开 QuickBooks 桌面程序并且他们有一个打开的公司文件时登录。

2) 确保在进行以下测试之前未打开 QuickBooks。

步骤:

1) 打开测试 C# 应用程序

2) 按下显示 "Open Connection." 的按钮,应通过 QBXML 互操作与 QuickBooks 的界面打开连接。

3) 按 "Start Session" 按钮。应使用 QuickBooks 开始会话。

4) 假设上面的测试先决条件已满足,您应该会收到 QuickBooks 返回的错误消息,告诉您应用程序未设置为自动登录,您需要先打开 QuickBooks尝试会话。

5) QBW32.exe 现在应该 运行 在后台运行。

6) 按表示结束会话的按钮。这应该使用 QuickBooks 界面结束会话。无论如何,会话应该已经通过步骤 3 按钮中的 try-catch 结束了。

7) 按 "Close Connection" 按钮。这应该会关闭与 QuickBooks 的所有连接。

8) 即使会话和连接都已结束并关闭,QBW32.exe 仍在后台 运行ning。

9) 使用退出按钮关闭测试应用程序。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using Interop.QBXMLRP2;

namespace Open_Connection
{

    public partial class Form1 : Form
    {

        bool sessionBegun = false;
        bool connectionOpen = false;
        RequestProcessor2 rp = null;
        string ticket;


        public Form1()
        {
            InitializeComponent();
        }

        private void End_Click(object sender, EventArgs e)
        {
            Environment.Exit(0);
        }

        private void OpenConn_Click(object sender, EventArgs e)
        {
            try
            {  //Start a new connection with QuickBooks
                rp = new RequestProcessor2();
                rp.OpenConnection2("", "Open Connection", QBXMLRPConnectionType.localQBD);
                connectionOpen = true;
            }

            catch (Exception connectionException)
                { //If the connection fails, close the connection to avoid the program from getting stuck in an interop error loop.
                        MessageBox.Show(connectionException.Message, "Error");
                        if (connectionOpen)
                        {
                            rp.CloseConnection();
                        }
                }
        }

        private void StartSess_Click(object sender, EventArgs e)
        {
            try
            {  //Start a new session with QuickBooks using the company file specified below.
                string ticket = rp.BeginSession(@"C:\Users\username\Documents\Quickbooks Company Files\example.QBW", QBFileMode.qbFileOpenDoNotCare);
                sessionBegun = true;
            }
            catch (Exception sessException)
            {
                //If the session fails (I.E. QuickBooks is not open with a user logged into the company file and the program is not given permission to
                //automatically log in, imeedietly end the session and close the connection.
                MessageBox.Show(sessException.Message, "Error");
                if (sessionBegun)
                {
                    rp.EndSession(ticket);
                }

                if (connectionOpen)
                {
                    rp.CloseConnection();
                }
            }
        }

        private void EndSess_Click(object sender, EventArgs e)
        {
            try
            { //End the session 
                rp.EndSession(ticket);
                sessionBegun = false;
            }

            catch (Exception ex)
            { //If a session was not started already, set the session begun flag to false to avoid getting stuck in a loop. 
                sessionBegun = false;
            }

        }

        private void CloseConn_Click(object sender, EventArgs e)
        {
            try
            { //Close the connection to QuickBooks 
                rp.CloseConnection();
                connectionOpen = false;
            }

            catch (Exception ex)
            { //If the connection was not open, set the connection open flag ot false to avoid getting stuck in a loop.
                connectionOpen = false;
            }

        }
    }
}

根据我上面的示例程序,我可以做些什么来让 QBW32.exe 自行关闭,这样它就不会在后台停留 运行ning我上面描述的场景?

更新:我自己和许多其他用户已经尝试关闭 QuickBooks 首选项部分中的设置 "Keep Quickbooks Running for faster startup"。这不会阻止 QBW32.exe 在会话和连接都结束后在后台保持打开状态。我看到这种行为在 2013 年至 2015 年的 QB 中出现。

如果您的 QuickBooks 运行正在后台运行,请执行以下步骤:

关闭 QuickBooks 2011 或更高版本中的“保持 QuickBooks 运行 快速启动”首选项。

  1. 打开 QuickBooks 并打开您的公司文件。
  2. 选择“编辑”>“首选项”。
  3. 选择左侧列表中的常规图标。
  4. 选择顶部的“我的首选项”选项卡。
  5. 单击以清除“为快速启动保留 QuickBooks 运行”复选框。
  6. 单击“确定”。

关闭 QuickBooks 或重新启动计算机后,QuickBooks 将不会 运行 在后台运行。

我试过以下方法: 打开 SQL Server Management Studio,运行 查询 QuickBooks 的集成包(QuickBooks 会在后台自动启动),然后完全关闭 SQL MS。我可以确认 QBW32.EXE 仍然是 运行ning,并且访问 QB 的服务不再是 运行ning。

调用应用程序必须始终关闭连接。终止调用应用程序会终止应用程序而不是连接。使用 MS SQL 服务器时,您需要 link 和 unlink QODBC。

例如:

EXEC sp_addlinkedserver @server = N'QODBC', @srvproduct=N'QODBC', @provider=N'MSDASQL', @datasrc=N'QuickBooks Data', @ provstr = 'ODBC;DSN=QuickBooks Data;DFQ=C:\Program Files\QODBC Driver for QuickBooks\sample04.qbw;SERVER=QODBC;UseDCOM=Y; OptimizerDBFolder=C:\Program Files\QODBC Driver for QuickBooks\Optimizer; OptimizerAllowDirtyReads=Y'

EXEC sp_dropserver @server = N'QODBC'

希望对您有所帮助。

在使用 Geetanjali 提供的场景进行进一步测试后,我得出了这个结论:

  • 如果您在 QB 中的集成应用程序列表中设置程序自动登录,QBW32.exe 只会自行关闭。

  • 如果您的程序未设置为自动登录,QBW32.exe 将在您开始会话时打开并输入公司文件名并保持打开状态即使您结束会话并结束连接。

  • 如果在启动会话时没有传入公司文件,QBW32.exe 将不会启动。

我已经在 Intuit 论坛上与 William 确认了这似乎按预期工作。

为了解决这个问题,我在我的测试应用程序中这样做了:

我在会话开始时添加了一个额外的 if 块,以首先通过未指定公司文件的打开会话调用发送连接测试。这迫使界面出现 return 错误,告诉我无法启动会话,因为未指定公司文件且 QuickBooks 未打开。这随后会强制我的测试应用程序显示一条消息,告诉我在重试之前打开公司文件。

我想我可以通过向 'use log in automatic mode' 和 'regular mode' 添加一个设置来进一步构建,这样如果我真的想使用自动登录,可以在需要时跳过测试连接。

无论如何,除了添加终止 QBW32.exe 进程的代码块之外,这似乎是解决这种情况的唯一方法。这不是完全可取的,但它也是一种选择。

无论如何,我希望这对在不久的将来 运行 进入这个障碍的任何人有所帮助。

截至 2017 年 9 月 12 日的更新:

似乎从 QuickBooks 2016 开始,这种行为不再是问题。无论您是否通过自动登录传递公司文件,当您开始会话时,当用户尝试直接或通过 运行 可执行文件时 QBW32.exe 将打开desktop/start 菜单快捷方式。有趣的是,QBW32.exe 进程可能已经 运行 在后台运行,因为您在没有自动登录的情况下传入了公司文件。尽管如此,用户仍然可以打开 QuickBooks,他们不会收到说明 QuickBooks 已经 运行ning.

的消息

我已经使用 QuickBooks Enterprise 2016 和 Enterprise 2017 对此进行了测试。我们所有至少拥有 QuickBooks 2016(各种版本、Pro、Premier 等)的用户也没有抱怨上述问题。我要在这里冒险,猜测 Intuit 决定有意或无意地解决这个问题。

因此,如果您或您的集成应用程序的用户仍在使用低于 QuickBooks 2016 的 QuickBooks 版本,我只推荐上述方法。

根据多年使用 C# 桌面 SDK 的经验,我可以告诉您,您并不孤单。 Intuit 知道它,它与 "keep running" 选项无关。我和 Intuit 的支持人员聊过;有些人认为这是一个错误,有些人认为这是设计使然。

我有一个 WinForms 应用程序,该应用程序自 QuickBooks 2006 年以来一直在生产中,并且从 2011 年左右(Enterprise 11)开始,这个进程问题就开始了。截至 2013 年,即使是 SDK 的测试应用程序 ("SDK Test Plus 3") 也会执行与您的测试应用程序相同的行为。

我的应用程序在我客户端的许多 PC 上 运行,但是与 QB 通信的部分会调用他们服务器上的 QB 实例(不是安装在他们 PC 上的 QB),我选择使用 "Kill QBW32 if it won't close" 的想法。 2014 年,我将其更改为在他们的桌面上与 QB 通信(因为他们的 PC 上有 QB)并且不使用 kill 技术(因为他们可能同时 运行ning QB)。由于此更改,我不必担心 QBW32 仍然 运行ning 并且我没有遇到任何问题(我的客户是让我知道的类型)。