2010-04-26 97 views
1

我正在嘗試編寫一個在Windows終端服務客戶端中使用虛擬通道的hello world類型程序。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); 

} 

我從MSTSC COM對象和ActiveX控件1發送數據。

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運行

任何幫助,將不勝感激時間得到一個execption。

編輯 - mHandle在函數運行時有一個非零值。更新代碼以添加該檢查。

EDIT2 - 我用P/Invoke Interop Assistant並生成新sigiture

​​

現在收到的文本字符串(是的!),但它只是得到我的測試字符串的第一個字母(噓!)。有什麼想法出錯?

編輯3 --- 在應該閱讀hello world的電話之後;

BytesRead = 24

Buffer.Length = 1; Buffer.Capacity = 16; Buffer.m_S​​tringValue =「H」;

回答

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 ""; 
    } 
} 
+0

將LPStr更改爲LPWStr讓我親近,返回'Hello World!豈怒' – 2010-04-26 21:52:41

+0

使用您的示例代碼修復了它。 – 2010-04-26 21:57:52

0

我覺得像洗澡寫這一點,但之後...

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

如果其他人可以提供更好的解決方案,只有一個字符傳輸問題,我會很樂意接受,而不是這個。

相關問題