3

我正在尝试使用以下代码将盲 printf 从 dll 捕获/重定向到 WPF 文本框。

dll:

#include <stdlib.h>
#include <string.h>
#include "stdafx.h"
#define EXTERN_DLL_EXPORT __declspec(dllexport)


extern "C" EXTERN_DLL_EXPORT int startPipe()
{
    setvbuf(stdout, NULL, _IONBF, 0);
    printf("hey");
    return 20;
}

//Morepipe2, etc just return different test words.

C#代码:

using System;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;

namespace PipeTest {


public partial class MainWindow : Window {
    private NamedPipeServerStream serverPipe;
    private NamedPipeClientStream clientPipe;
    private int id;
    private StreamReader stm;
    private HandleRef hr11;
    private String txt;

    private delegate void updateCallback(string pipetext);

    [DllImport("kernel32.dll", SetLastError = true)]
    protected static extern bool SetStdHandle(int nStdHandle, IntPtr hConsoleOutput);

    public MainWindow() {
        InitializeComponent();

        id = Process.GetCurrentProcess().Id; // make this instance unique
        serverPipe = new NamedPipeServerStream("consoleRedirect" + id, PipeDirection.In, 1);
        clientPipe = new NamedPipeClientStream(".", "consoleRedirect" + id, PipeDirection.Out, PipeOptions.WriteThrough);
        ThreadPool.QueueUserWorkItem(state => {
            serverPipe.WaitForConnection();
            using (stm = new StreamReader(serverPipe)) {
                while (serverPipe.IsConnected) {
                    try {
                        txt = stm.ReadLine();
                        if (!string.IsNullOrEmpty(txt))

                            UpdateElement(txt + "\n");
                    } catch (IOException) {
                        break; // normal disconnect
                    }
                }
            }
        }, null);
        clientPipe.Connect();
        hr11 = new HandleRef(clientPipe,
         clientPipe.SafePipeHandle.DangerousGetHandle());
        SetStdHandle(-11, hr11.Handle); // redirect stdout to my pipe

        PipeServer.morePipe1();
        PipeServer.morePipe2();

        PipeServer.startPipe();
        PipeServer.morePipe1();
        PipeServer.morePipe2();
        Thread.Sleep(10000);
        PipeServer.startPipe();
        PipeServer.startPipe();
    }

    private void ender() {
        //clientPipe.Dispose();
        //serverPipe.Dispose();
    }

    private void button1_Click(object sender, RoutedEventArgs e) {
        PipeServer.startPipe();
    }

    private void button2_Click(object sender, RoutedEventArgs e) {
        PipeServer.morePipe1();
    }

    private void button3_Click(object sender, RoutedEventArgs e) {
        PipeServer.morePipe2();
    }

    private void UpdateElement(string pipetext) {
        if (textBox1.Dispatcher.CheckAccess() == false) {
            updateCallback uCallBack = new updateCallback(UpdateElement);
            this.Dispatcher.Invoke(uCallBack, pipetext);
        } else {
            textBox1.Text += pipetext;
        }
    }
}

public static class PipeServer {

     private const CallingConvention conv = CallingConvention.StdCall;

    [DllImport(@"PipeServer2.dll", CallingConvention = conv)]
    public static extern int startPipe();

    [DllImport(@"PipeServer2.dll", CallingConvention = conv)]
    public static extern int morePipe1();


}
}

这段代码不能像现在这样工作。但是这些是我的问题:

  1. 如果模块级别的私有变量被移动到 mainwindow(),它将工作并显示文本框的所有内容。只要它们在 mainwindow() 中,我就可以在 dll 中调用多个方法并显示输出。
  2. 即使它确实有效,一旦 mainwindow() 完成,当我单击调用 dll 的按钮时,它不再记录任何输出。我的期望是按钮应该调用 dll,并且应该有数据写入标准输出/管道,并且线程仍然应该拾取它(我错了吗?)。我认为制作变量模块级别会有所帮助,但如果我这样做,我不会得到任何结果。
4

0 回答 0