1

这里是编程环境。

  • 框架:ASP.NET 框架 4
  • 语言:Visual C# 2010,PowerBuilder 12.5.2 Build 5609 于 2014 年 1 月 2 日 01:29:51 构建

这是场景。

我正在创建一个 PowerBuilder 应用程序,它会启动一个带有多行编辑文本框的简单窗口,您可以在其中键入一些内容并单击一个按钮以加载一个 C# COM 类,该类检查拼写错误并将值返回给 PowerBuilder应用程序的文本框。

C# 类库.cs

using System;
using System.Runtime.InteropServices;

namespace InteropServices
{
    [Guid("Let's just assume that I have a correct Guid string here.")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface ISpellChecker
    {
        [(DispId(1)]
        string CheckText(string inputMsg);

        [(DispId(2)]
        void Dispose();
    }

    [ClassInterface(ClassInterfaceType.None)]
    [Guid("Let's just assume that I have a correct Guid string here.")]
    [ProgId("InteropServices.SpellChecker")]
    public class SpellChecker: ISpellChecker
    {
        private string newInputMsg

        public string inputMsg
        {
            get
            {
                return newInputMsg;
            }
            set
            {
                newInputMsg = value;
            }
        }

        private App spellCheckerApp;
        private MainWindow spellCheckerMainWindow;

        public SpellChecker() { }

        public string CheckText(string inputMsgBase)
        {
            inputMsg = inputMsgBase;
            spellCheckerApp = new App();
            spellCheckerMainWindow = new MainWindow(inputMsg);
            spellCheckerApp.Run(spellCheckerMainWindow);
            txtCorrected = MainWindow.TextReturned;

            return txtCorrected;
        }

        public string txtCorrected { get; set; }

        // This function was my futile attempt to resolve this issue, but it seemingly has no effect whatsoever.
        public void Dispose()
        {
            spellCheckerMainWindow.Close();
            spellCheckerApp.Shutdown();
            spellCheckerMainWindow = null;
            spellCheckerApp = null;
        }
    }
}

C# MainWindow.xaml

<Window x:Class="InteropServices.MainWindow"
        xmlns="http://schemas.microsft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsft.com/winfx/2006/xaml"
        Title="Spell Checker .NET" Height="350" Width="525" Loaded="Window_Loaded">
    <Grid>
        <TextBox Name="TextBoxSpellCheck" SpellCheck.IsEnabled="True" AcceptsReturn="True" TextWrapping="Wrap" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True" Margin="50" />
        <Button Name="ButtonAccept" Margin="229,267,146,12" Width="128" Height="32" Content="Accept" IsDefault="True" Click="ButtonAccept_Click" />
        <Button Name="ButtonCancel" Margin="364,267,12,12" Width="128" Height="32" Content="Cancel" IsDefault="True" Click="ButtonAccept_Click" />
    </Grid>
</Window>

C# MainWindow.xaml.cs

using System;
// Omitting the rest of the default Usings

namespace InteropServices
{
    public partial class MainWindow : Window
    {
        private string txtChecked;
        private int caretIdx;
        private SpellingError spellingErr;
        private string p;

        public MainWindow(string p)
        {
            this.p = p;
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            txtChecked = p;
            TextBoxSpellCheck.Text = txtChecked;
            caretIdx = TextBoxSpellCheck.CaretIndex;
            spellingErr = TextBoxSpellCheck.GetSpellingError(caretIdx);

            if (spellingErr == null)
            {
                MessageBox.Show("No spelling error was found. Click OK to continue.", "Congratulations!");
                txtReturned = p;
                Application.Current.Shutdown();
            }
        }

        private void ButtonAccept_Click(object sender, RoutedEventArg e)
        {
            txtReturned = TextBoxSpellCheck.Text;
            Application.Current.Shutdown();
        }

        private void ButtonCancel_Click(object sender, RoutedEventArg e)
        {
            txtReturned = p;
            Application.Current.Shutdown();
        }

        public static string txtReturned
    }
}

从 main 中的命令按钮单击类型 cb_1 的 PowerBuilder 事件

mle_1.Text = "Teh quik brownn fox junps ober teh lazy dgo!" // Too lazy to copy and paste this into the app's textbox, so here it is...
txtChecked = mle_1.Text
myOLEObject = CREATE OLEObject
result = myOLEObject.ConnectToNewObject("InteropServices.SpellChecker")

IF result < 0 THEN
    DESTROY myOLEObject
    MessageBox("Connecting to COM Object Failed", "Error: " + String(result))
    RETURN
ELSE
    txtCorrected = myOLEObject.CheckText(txtChecked) // This is the line that causes an error.
    mle_1.Text = txtCorrected
END IF

myOLEObject.Dispose() // This function was my futile attempt to resolve this issue, but it seemingly has no effect whatsoever.
myOLEObject.DisconnectObject()
DESTROY myOLEObject

用于 main 的 PowerBuilder 实例变量

String txtChecked
String txtCorrected
Int result
OLEObject myOLEObject

到目前为止,我想出的解决方案一直表现得很奇怪。从 PowerBuilder 应用程序中单击该按钮仅在启动 PowerBuilder 或部署的可执行文件后起作用一次,并且在再次尝试再次单击该按钮时将给出以下消息:

PowerBuilder 应用程序执行错误 (R0035)

应用程序终止。

错误:在 main 的对象 cb_1 的单击事件中,在第 11 行调用外部对象函数 checktext 时出错。

我应该从这些代码中更改什么以使其每次都能正常工作?

4

1 回答 1

2

您从 PowerBuilder 获得的诊断完全不够,无法调试问题。最好的办法是使用 Visual Studio 调试器:

  • 项目 + 属性,调试选项卡。选择“启动外部程序”单选按钮并选择您的 PowerBuilder 测试程序。
  • Debug + Exceptions,勾选 CLR Exceptions 的 Throw 复选框。当您的程序抛出异常时,这会使调试器停止。
  • 在 CheckText() 的开头和 Run() 调用之后的语句上设置断点。Loaded 事件处理程序中的一个应该很有用。
  • 按 F5 开始调试。

当您单击 PowerBuilder 按钮时,您的第一个断点应该命中。检查是否喜欢inputMsgBase值,按 F5 继续。再次按下按钮,调试器现在很可能停止并告诉您出了什么问题。我有一些猜测,如果不知道你看到了什么,我现在不会冒险。

于 2014-10-27T15:06:14.653 回答