سؤال

أحاول كتابة برنامج Hello World Type لاستخدام القنوات الافتراضية في عميل Windows Terminal Services.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

    }
    IntPtr mHandle = IntPtr.Zero;
    private void Form1_Load(object sender, EventArgs e)
    {
        mHandle = NativeMethods.WTSVirtualChannelOpen(IntPtr.Zero, -1, "TSCRED");
        if (mHandle == IntPtr.Zero)
        {
            throw new Win32Exception(Marshal.GetLastWin32Error());
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        uint bufferSize = 1024;
        StringBuilder buffer = new StringBuilder();
        uint bytesRead;
        NativeMethods.WTSVirtualChannelRead(mHandle, 0, buffer, bufferSize, out bytesRead);
        if (bytesRead == 0)
        {
            MessageBox.Show("Got no Data");
        }
        else
        {
            MessageBox.Show("Got data: " + buffer.ToString());
        }
    }

    protected override void Dispose(bool disposing)
    {
        if (mHandle != System.IntPtr.Zero)
        {
            NativeMethods.WTSVirtualChannelClose(mHandle);
        }
        base.Dispose(disposing);

    }
}

internal static class NativeMethods
{
    [DllImport("Wtsapi32.dll")]
    public static extern IntPtr WTSVirtualChannelOpen(IntPtr server,
        int sessionId, [MarshalAs(UnmanagedType.LPStr)] string virtualName);

    //[DllImport("Wtsapi32.dll", SetLastError = true)]
    //public static extern bool WTSVirtualChannelRead(IntPtr channelHandle, long timeout,
    //        byte[] buffer, int length, ref int bytesReaded);

    [DllImport("Wtsapi32.dll")]
    public static extern bool WTSVirtualChannelClose(IntPtr channelHandle);


    [DllImport("Wtsapi32.dll", EntryPoint = "WTSVirtualChannelRead")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool WTSVirtualChannelRead(
        [In()] System.IntPtr hChannelHandle
        , uint TimeOut
        , [Out()] [MarshalAs(UnmanagedType.LPStr)] 
          System.Text.StringBuilder Buffer
        , uint BufferSize
        , [Out()] out uint pBytesRead);

}

أقوم بإرسال البيانات من كائن MSTSC COM و ActiveX Control.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

    }

    private void Form1_Load(object sender, EventArgs e)
    {
        rdp.Server = "schamberlainvm";
        rdp.UserName = "TestAcct";
        IMsTscNonScriptable secured = (IMsTscNonScriptable)rdp.GetOcx();
        secured.ClearTextPassword = "asdf";
        rdp.CreateVirtualChannels("TSCRED");
        rdp.Connect();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        rdp.SendOnVirtualChannel("TSCRED", "Hello World!");
    }
}
//Designer code
// 
// rdp
// 
this.rdp.Enabled = true;
this.rdp.Location = new System.Drawing.Point(12, 12);
this.rdp.Name = "rdp";
this.rdp.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("rdp.OcxState")));
this.rdp.Size = new System.Drawing.Size(1092, 580);
this.rdp.TabIndex = 0;

أحصل على تنفيذ في كل مرة NativeMethods.WTSVirtualChannelRead أشواط

اي مساهمه في هذا ستكون خدمة عظيمة.

تحرير-لدى Mhandle قيمة غير صفرية عند تشغيل الوظيفة. رمز محدث لإضافة هذا الشيك.

edit2 - لقد استخدمت P/استدعاء مساعد interop وتوليد sigiture جديد

    [DllImport("Wtsapi32.dll", EntryPoint = "WTSVirtualChannelRead")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool WTSVirtualChannelRead(
        [In()] System.IntPtr hChannelHandle
        , uint TimeOut
        , [Out()] [MarshalAs(UnmanagedType.LPStr)] 
          StringBuilder Buffer
        , uint BufferSize
        , [Out()] out uint pBytesRead);

يستقبل الآن سلسلة النص (نعم!) ولكن يحصل فقط على الحرف الأول من سلسلة الاختبار الخاصة بي (بوو!). أي أفكار حول ما هو الخطأ؟

تحرير 3 --- بعد المكالمة التي ينبغي قراءة عالم مرحبا ؛

Bytesread = 24

buffer.length = 1 ؛ buffer.capacity = 16 ؛ buffer.m_stringValue = "H" ؛

هل كانت مفيدة؟

المحلول

حسنًا ، المشكلة هي أنك ترسل سلسلة Unicode 16bit في الجانب الإرسال وقراءة سلسلة ANSI على الجانب الآخر بحيث تقوم الطبقة الماردة بإنهاء المخزن المؤقت للسلسلة في حرف NUL الأول. يمكنك إما تغيير UnmanagedType.LPStr إلى UnmanagedType.LPWStr أو حميضها كصفيف بايت ثم قم بتحويلها إلى سلسلة باستخدام فئة ترميز Unicode.

قد ينجح شيء من هذا القبيل (ملاحظة: رمز غير مختبر حيث ليس لدي خادم لاختباره):

public static extern int WTSVirtualChannelRead(IntPtr hChannel, 
        uint Timeout, 
        [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] byte[] Buffer, 
        uint BufferSize, 
        out uint BytesRead);

string DoRead(IntPtr hChannel)
{ 
    byte[] buf = new byte[1024];
    uint bytesRead;
    if (WTSVirtualChannelRead(hChannel, 0, buf, (uint)buf.Length, out bytesRead) != 0)
    {
        return Encoding.Unicode.GetString(buf, 0, (int)bytesRead);
    }
    else
    {
        return "";
    }
}

نصائح أخرى

أشعر بالرغبة في الاستحمام بعد كتابة هذا ولكن ...

private void button1_Click(object sender, EventArgs e)
{
    uint bufferSize = 2;
    StringBuilder buffer = new StringBuilder();
    StringBuilder final = new StringBuilder();
    uint bytesRead;
    NativeMethods.WTSVirtualChannelRead(mHandle, 0, buffer, bufferSize, out bytesRead);
    while (bytesRead != 0)
    {
        final.Append(buffer);
        NativeMethods.WTSVirtualChannelRead(mHandle, 0, buffer, bufferSize, out bytesRead);
    }
        MessageBox.Show("Got data: " + final.ToString());
}

إذا كان بإمكان أي شخص آخر توفير حل أفضل لمشكلة الشخصية الوحيدة التي تنقل ، فسوف أقبل ذلك بكل سرور بدلاً من ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top