0

我正在尝试使用 C# 中WtsEnumerateSessionsExA定义的函数枚举所有远程桌面会话WtsApi32.dll

该函数写入一个WTS_SESSION_INFO_1A结构数组,其指针作为参数传递。您可以在此处找到文档:

我已经像这样在 C#中实现了WTS_SESSION_INFO_1A结构和:WTS_CONNECT_STATE_CLASS

struct WtsSessionInfoClass
{
    uint ExecEnvId;
    WtsConnectStateClass state;
    uint sessionId;
    string pSessionName;
    string pHostName;
    string pUserName;
    string pDomainName;
    string pFarmName;
}
enum WtsConnectStateClass
{
    WTSActive,
    WTSConnected,
    WTSConnectQuery,
    WTSShadow,
    WTSDisconnected,
    WTSIdle,
    WTSListen,
    WTSReset,
    WTSDown,
    WTSInit
}

我在一个名为的类中导入了所需的函数Native32

[DllImport("WtsApi32.dll")]
internal static extern IntPtr WTSOpenServerEx(string name);

[DllImport("WtsApi32.dll")]
internal static extern bool WTSEnumerateSessionsExA(
    IntPtr hServer,
    UIntPtr pLevel,
    uint Filter,
    out WtsSessionInfoClass[] ppSessionInfo,
    UIntPtr pCount
);

最后我的实现如下:

UIntPtr len = new UIntPtr();
WtsSessionInfoClass[] sessions;
IntPtr handle = Native32.WTSOpenServerEx("MyMachineName"); // This function gets the server handle and works fine
Native32.WTSEnumerateSessionsExA(handle, new UIntPtr(1), 0, out sessions, len); // This function will produce AccessViolationException
...

执行代码时,Native32.WTSEnumerateSessionsExA由于AccessViolationException.

我在这里做错了什么?任何帮助表示赞赏。

4

1 回答 1

2

我最好的猜测是您没有pLevel以正确的方式传递第二个参数。您试图传递一个指向值为 1 的 DWORD 的指针,但您实际上传递的是地址 1。相反,声明一个初始化为 1 的局部变量并传递它的地址。

更多细节:

您链接的 WTSEnumerateSessionsExA 的文档页面是这样说的:

pLevel

该参数是保留的。始终将此参数设置为 1。在输出时,WTSEnumerateSessionsEx不会更改此参数的值。

这里的措辞不是最好的,但我的解释是您需要为 传递一个有效的指针pLevel,并且该指针需要指向一个正确对齐的 DWORD,其值为 1。

对我来说,另一种解读是您需要将文字内存地址 1 作为指针传递给pLevel. 我本能地觉得这很荒谬。

但是,您的代码:

Native32.WTSEnumerateSessionsExA(
  handle, new UIntPtr(1), 0, out sessions, len);

为. new UIntPtr(1)_ pLevel根据我对UIntPtr doc pages的阅读,该表达式将创建一个字面值为 1 的指针,即地址 1。

如果您调试到 WTSEnumerateSessionsEx 实现的汇编代码,我猜您会看到它尝试取消引用pLevel,然后当它尝试从地址 1 加载 DWORD 时出现访问冲突而崩溃。

要解决此问题,您可以声明一个uint包含值 1 的变量,并将地址传递给该变量:

uint enumerateSessionsLevel = 1;
Native32.WTSEnumerateSessionsExA(
  handle, &enumerateSessionsLevel, 0, out sessions, len);
于 2020-08-30T09:26:10.110 回答