WTSVirtualChannelRead Только читает первую букву строки

Я пытаюсь записать привет мировую программу типа для использования виртуальных каналов в клиенте служб удаленных рабочих столов окон.

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);

}

Я отправляю данные из COM-объекта MSTSC и управления ActiveX.

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;

Я получаю execption каждый раз NativeMethods.WTSVirtualChannelRead выполнения

Любая справка на этом значительно ценилась бы.

РЕДАКТИРОВАНИЕ - mHandle имеет ненулевое значение, когда функция работает. обновленный код для добавления той проверки.

EDIT2 - Я использовал Помощник P/Invoke 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

Буфер. Длина = 1; буфер. Способность = 16; буфер m_StringValue = "H";

1
задан Scott Chamberlain 26 April 2010 в 21:32
поделиться

2 ответа

Проблема в том, что вы отправляете 16-битную строку Unicode на передающей стороне и считываете строку 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 "";
    }
}
2
ответ дан 3 September 2019 в 01:00
поделиться

Я чувствую, что хочу принять душ после того, как написал это, но ...

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());
}

Если кто-то еще может предложить лучшее решение единственной проблемы с передачей символов, я с радостью приму это вместо этого.

0
ответ дан 3 September 2019 в 01:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: