我需要有关使用for PCSAPI.dll进行IBM仿真程序编程的帮助。
C中已经提供了文档。您可以参考以下URL:
PCSAPI Documentation IBM Emulator programming
有一个函数pcsQuerySessionList,用于获取有关当前活动的会话以及连接到模拟器的会话的信息。提供的函数是C语言的,但我需要用C语言实现。
这是文档中提供的功能:

ULONG PCSAPI_ENTRY pcsQuerySessionList(ULONG Count, SESSINFO *SessList);

typedef union _SESSNAME {   // Name field of SessInfo structure
  char ShortName;           // Short session ID (A-Z)
  ULONG Handle;             // Session handle
} SESSNAME;

typedef struct _SESSINFO {  // Description of a single session
  SESSNAME Name;            // Session name (ID or handle)
  ULONG    Status;          // Session status (PCS_SESSION_* bit flags)
} SESSINFO;

这是关于pcsQuerySessionList的细节:
Function Type
ULONG WINAPI pcsQuerySessionList(ULONG Count, SESSINFO *SessionList)

Parameter Type and Description
ULONG Count
- Number of elements in the SessionList array
SESSINFO *SessionList
- Pointer to an array of SESSINFO structures as defined in PCSAPI.H

这是一个使用函数的示例:
ULONG      NumSessions, i;  // Session counters
SESSINFO   *SessList;       // Array of session information structures
// Find out number of sessions that exist
NumSessions = pcsQuerySessionList (0,NULL);
if (NumSessions == 0) {
   printf("There are no sessions.");
   exit;
}

// Allocate array large enough for all sessions
SessList = (SESSINFO *)malloc(NumSessions * sizeof(SESSINFO));
memset(SessList, 0x00, NumSessions * sizeof(SESSINFO));

// Now read actual session info
pcsQuerySessionList(NumSessions, SessList);

for (i=0; i<NumSessions; i++) {
   if ((SessList[i].Status & PCS_SESSION_STARTED) &&
       (SessList[i].Status & PCS_SESSION_ONLINE))  {

      printf("Session %c is started and connected.",
        SessList[i].Name.ShortName);
   }
}

exit;

我已经试着把它实现到C#。您可以在下面的代码中看到它:
using System.Runtime.InteropServices;

public partial class Form1 : Form
{
    [DllImport("PCSAPI32.dll")]
    public static extern int pcsQuerySessionList(out int sessionCount, out SESSINFO sessionInfo);

    [StructLayout(LayoutKind.Sequential)]
    public struct SESSNAME
    {
        char ShortName;
        ulong Handle;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SESSINFO
    {
        [MarshalAs(UnmanagedType.Struct)]
        SESSNAME Name;
        ulong Status;
    }

    private void button3_Click(object sender, EventArgs e)
    {
        try
        {
            int sessCount = 0;
            SESSINFO structSESSINFO;
            sessCount = pcsQuerySessionList(out sessCount, out structSESSINFO);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

从上面的实现中,我成功地获得了返回值(sessionfo)。但是,当模拟器运行多个会话时,我需要获取所有活动会话信息,而我的代码只返回第一个活动会话。当我试图将sessionfo解析为一个数组时,出现了一个访问冲突错误。
PCSAPI.exe中出现“System.AccessViolationException”类型的未处理异常。
其他信息:试图读取或写入受保护的内存。这通常表示其他内存已损坏。
请帮我解决这个问题。任何帮助都将不胜感激。
--编辑--
谢谢你的建议。但是,我已经尝试了你的建议,仍然发生了同样的错误。
[DllImport("PCSAPI32.dll")]
public static extern int pcsQuerySessionList(out int sessionCount, ref SESSINFO[] sessionInfo);

private void button3_Click(object sender, EventArgs e)
{
    try
    {
        int sessCount = 0;
        SESSINFO[] structSESSINFO = new SESSINFO[sessCount];
        sessCount = pcsQuerySessionList(out sessCount, ref structSESSINFO);
        structSESSINFO = new SESSINFO[sessCount];
        pcsQuerySessionList(out sessCount, ref structSESSINFO);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

另外,我已经得到了sessCount值(不使用array),并且我也得到了structSESSINFO值,但是不能用array方法(multiple session)得到SESSINFO。总是有同样的错误。
--再次编辑--
这是代码:
using System.Runtime.InteropServices;

public partial class Form1 : Form
{
    [DllImport("PCSAPI32.dll")]
    public static extern int pcsQuerySessionList(int sessionCount, SESSINFO[] sessionInfo);

    [StructLayout(LayoutKind.Sequential)]
    public struct SESSNAME
    {
        char ShortName;
        ulong Handle;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SESSINFO
    {
        [MarshalAs(UnmanagedType.Struct)]
        SESSNAME Name;
        ulong Status;
    }

    private void button3_Click(object sender, EventArgs e)
    {
        try
        {
            int returnVal;
            SESSINFO[] structSESSINFO = null;
            returnVal = pcsQuerySessionList(0, structSESSINFO);
            structSESSINFO = new SESSINFO[returnVal];
            pcsQuerySessionList(returnVal, structSESSINFO);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

我已经试过rs232建议了。上面的代码运行正常。我得到了returnVal,但是structSESSINFO是空的。
再次感谢你的帮助。

最佳答案

方法签名

ULONG PCSAPI_ENTRY pcsQuerySessionList(ULONG Count, SESSINFO *SessList);

您提供的描述都表明函数希望您为它提供已分配的sessionfo结构数组:SessList参数应包含对该数组的引用,Count参数表示该数组中的元素数量。不能将函数的参数声明为“out”并期望由函数设置,您的责任是分配数组并在该数组中传递正确数量的项,只有这样,函数才会将值填充到数组中。

关于c# - C#上的PCSAPI IBM Emulator编程,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48222416/

10-11 21:20