wtsvirtualchannelRead文字列の最初の文字のみを読み取ります
-
01-10-2019 - |
質問
Windowsターミナルサービスクライアントで仮想チャネルを使用するためのHello World Typeプログラムを作成しようとしています。
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コントロールからデータを送信しています。
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 Assistantを呼び出します そして新しいシジアリを生成しました
[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);
テキスト文字列(ええ!)が受信されましたが、テスト文字列の最初の文字のみを取得します(boo!)。何が問題になっているのかについてのアイデアはありますか?
編集3 ---コールの後、それはHello Worldを読むべきです。
bytesRead = 24
buffer.length = 1; buffer.capacity = 16; buffer.m_stringvalue = "h";
解決
問題は、送信側に16ビットユニコード文字列を送信し、もう一方の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());
}
他の誰かが、1つのキャラクターを送信する唯一のキャラクターに対してより良い解決策を提供できる場合、私はこれではなくそれを喜んで受け入れます。