从PowerBuilder调用.NET程序集(将.NET Framework组件公开给COM)

时间:2014-10-24 11:56:02

标签: c# .net com powerbuilder interopservices

这是编程环境。

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

以下是该方案。

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

C#ClassLibrary.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
    }
}

从主要

中的命令按钮点击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

主要

的PowerBuilder实例变量
String txtChecked
String txtCorrected
Int result
OLEObject myOLEObject

到目前为止我提出的解决方案一直表现得非常奇怪。单击PowerBuilder应用程序中的按钮仅在启动PowerBuilder或部署的可执行文件后才能工作一次,并且在再次单击该按钮时会发出以下消息:

  

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

     

申请已终止。

     

错误:在第11行调用外部对象函数checktext时出错   点击了主要对象cb_1的事件。

我应该从这些代码中更改哪些内容以使其每次都有效?

1 个答案:

答案 0 :(得分:2)

您从PowerBuilder获得的诊断完全不足以避免调试问题。这里最好的办法是使用Visual Studio调试器:

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

当您单击PowerBuilder按钮时,您的第一个断点应该会点击。检查您是否喜欢 inputMsgBase 值,按F5继续。再次按下按钮,调试器现在停止的好几率并告诉你出了什么问题。我有一些猜测,在没有知道你所看到的情况下,我现在没有任何风险。