【问题标题】:Access Violation Exception, when i call dll method访问冲突异常,当我调用 dll 方法时
【发布时间】:2016-09-17 11:53:33
【问题描述】:

如何从 dll 调用函数?我有AccessViolationExeception

我在 C: 上有签名

int WINAPI LogonNowait(Context* comm, 
              char*   host, 
              char*   username,
              char*   password,
              char*   shell_cmd,
              char*   logon_error_msg,
              int     buflen,
              SOCKET* sIO,
              SOCKET* sErr
              )

[DllImport(@"C:\\MyDLL.dll")]
        public static extern int WaitForLogon(ref Context ctx, ref string errmsg, int bLen, ref int sIO, ref int sErr);

 [StructLayout(LayoutKind.Sequential)]
    public struct CommContext
    {
        public uint inited;

        public uint rbufsize;
        public uint rbuf;
        public uint r_in_container;
        public uint left_in_container;
        public uint next_in_container;


        public uint wbufsize;
        public uint wbuf;
        public uint w_in_container;
        public uint first_free;
        public uint empty_container;

        public uint socket;
        public uint hdrtype;
        public uint last_error;
        public uint socket2;
        public string RX_context;
        public int port;
        public uint async_header;
        public string my_host_addr;

        public override string ToString()
        {
            return port.ToString();
        }
    }

附加信息:试图读取或写入受保护的内存。这通常表明其他内存已损坏。 我如何正确地从 C# 调用此方法?

【问题讨论】:

    标签: c#


    【解决方案1】:

    我会做这样的事情。不确定它是否完全正确,但很接近。我更新了原始帖子以消除设置套接字时发生的错误。您必须在运行代码之前初始化 CommContext。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime;
    using System.Runtime.InteropServices;
    
    namespace ConsoleApplication1
    {
        class Program
        {
                //int WINAPI LogonNowait(Context* comm, 
                //  char*   host, 
                //  char*   username,
                //  char*   password,
                //  char*   shell_cmd,
                //  char*   logon_error_msg,
                //  int     buflen,
                //  SOCKET* sIO,
                //  SOCKET* sErr
                //  )
            [DllImport(@"C:\\MyDLL.dll",CallingConvention = CallingConvention.Cdecl)]
            public static extern int WaitForLogon(IntPtr ctx, IntPtr host, IntPtr username, IntPtr password, IntPtr shell_cmd,  IntPtr errmsg, int bLen, IntPtr sIO, IntPtr sErr);
    
            [DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            static extern Int32 WSAStartup(Int16 wVersionRequested, out WSAData wsaData);
    
            [DllImport("ws2_32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern IntPtr socket(ADDRESS_FAMILIES_INT af, SOCKET_TYPE_INT socket_type, PROTOCOL_INT protocol);
    
            internal enum ADDRESS_FAMILIES_INT : int
            {
                /// <summary>
                /// Unspecified [value = 0].
                /// </summary>
                AF_UNSPEC = 0,
                /// <summary>
                /// Local to host (pipes, portals) [value = 1].
                /// </summary>
                AF_UNIX = 1,
                /// <summary>
                /// Internetwork: UDP, TCP, etc [value = 2].
                /// </summary>
                AF_INET = 2,
                /// <summary>
                /// Arpanet imp addresses [value = 3].
                /// </summary>
                AF_IMPLINK = 3,
                /// <summary>
                /// Pup protocols: e.g. BSP [value = 4].
                /// </summary>
                AF_PUP = 4,
                /// <summary>
                /// Mit CHAOS protocols [value = 5].
                /// </summary>
                AF_CHAOS = 5,
                /// <summary>
                /// XEROX NS protocols [value = 6].
                /// </summary>
                AF_NS = 6,
                /// <summary>
                /// IPX protocols: IPX, SPX, etc [value = 6].
                /// </summary>
                AF_IPX = 6,
                /// <summary>
                /// ISO protocols [value = 7].
                /// </summary>
                AF_ISO = 7,
                /// <summary>
                /// OSI is ISO [value = 7].
                /// </summary>
                AF_OSI = 7,
                /// <summary>
                /// european computer manufacturers [value = 8].
                /// </summary>
                AF_ECMA = 8,
                /// <summary>
                /// datakit protocols [value = 9].
                /// </summary>
                AF_DATAKIT = 9,
                /// <summary>
                /// CCITT protocols, X.25 etc [value = 10].
                /// </summary>
                AF_CCITT = 10,
                /// <summary>
                /// IBM SNA [value = 11].
                /// </summary>
                AF_SNA = 11,
                /// <summary>
                /// DECnet [value = 12].
                /// </summary>
                AF_DECnet = 12,
                /// <summary>
                /// Direct data link interface [value = 13].
                /// </summary>
                AF_DLI = 13,
                /// <summary>
                /// LAT [value = 14].
                /// </summary>
                AF_LAT = 14,
                /// <summary>
                /// NSC Hyperchannel [value = 15].
                /// </summary>
                AF_HYLINK = 15,
                /// <summary>
                /// AppleTalk [value = 16].
                /// </summary>
                AF_APPLETALK = 16,
                /// <summary>
                /// NetBios-style addresses [value = 17].
                /// </summary>
                AF_NETBIOS = 17,
                /// <summary>
                /// VoiceView [value = 18].
                /// </summary>
                AF_VOICEVIEW = 18,
                /// <summary>
                /// Protocols from Firefox [value = 19].
                /// </summary>
                AF_FIREFOX = 19,
                /// <summary>
                /// Somebody is using this! [value = 20].
                /// </summary>
                AF_UNKNOWN1 = 20,
                /// <summary>
                /// Banyan [value = 21].
                /// </summary>
                AF_BAN = 21,
                /// <summary>
                /// Native ATM Services [value = 22].
                /// </summary>
                AF_ATM = 22,
                /// <summary>
                /// Internetwork Version 6 [value = 23].
                /// </summary>
                AF_INET6 = 23,
                /// <summary>
                /// Microsoft Wolfpack [value = 24].
                /// </summary>
                AF_CLUSTER = 24,
                /// <summary>
                /// IEEE 1284.4 WG AF [value = 25].
                /// </summary>
                AF_12844 = 25,
                /// <summary>
                /// IrDA [value = 26].
                /// </summary>
                AF_IRDA = 26,
                /// <summary>
                /// Network Designers OSI &amp; gateway enabled protocols [value = 28].
                /// </summary>
                AF_NETDES = 28,
                /// <summary>
                /// [value = 29].
                /// </summary>
                AF_TCNPROCESS = 29,
                /// <summary>
                /// [value = 30].
                /// </summary>
                AF_TCNMESSAGE = 30,
                /// <summary>
                /// [value = 31].
                /// </summary>
                AF_ICLFXBM = 31
            }
    
            internal enum SOCKET_TYPE_INT : int
            {
                /// <summary>
                /// stream socket 
                /// </summary>
                SOCK_STREAM = 1,
    
                /// <summary>
                /// datagram socket 
                /// </summary>
                SOCK_DGRAM = 2,
    
                /// <summary>
                /// raw-protocol interface 
                /// </summary>
                SOCK_RAW = 3,
    
                /// <summary>
                /// reliably-delivered message 
                /// </summary>
                SOCK_RDM = 4,
    
                /// <summary>
                /// sequenced packet stream 
                /// </summary>
                SOCK_SEQPACKET = 5
            }
            internal enum PROTOCOL_INT : int
            {
                //dummy for IP  
                IPPROTO_IP = 0,
                //control message protocol  
                IPPROTO_ICMP = 1,
                //internet group management protocol  
                IPPROTO_IGMP = 2,
                //gateway^2 (deprecated)  
                IPPROTO_GGP = 3,
                //tcp  
                IPPROTO_TCP = 6,
                //pup  
                IPPROTO_PUP = 12,
                //user datagram protocol  
                IPPROTO_UDP = 17,
                //xns idp  
                IPPROTO_IDP = 22,
                //IPv6  
                IPPROTO_IPV6 = 41,
                //UNOFFICIAL net disk proto  
                IPPROTO_ND = 77,
    
                IPPROTO_ICLFXBM = 78,
                //raw IP packet  
                IPPROTO_RAW = 255,
    
                IPPROTO_MAX = 256
            }
    
            // For 32-bit execution
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            public struct WSAData
            {
                public Int16 version;
                public Int16 highVersion;
    
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257)]
                public String description;
    
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 129)]
                public String systemStatus;
    
                public Int16 maxSockets;
                public Int16 maxUdpDg;
                public IntPtr vendorInfo;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct CommContext
            {
                public uint inited;
    
                public uint rbufsize;
                public uint rbuf;
                public uint r_in_container;
                public uint left_in_container;
                public uint next_in_container;
    
    
                public uint wbufsize;
                public uint wbuf;
                public uint w_in_container;
                public uint first_free;
                public uint empty_container;
    
                public uint socket;
                public uint hdrtype;
                public uint last_error;
                public uint socket2;
                public string RX_context;
                public int port;
                public uint async_header;
                public string my_host_addr;
    
                public override string ToString()
                {
                    return port.ToString();
                }
            }
    
            static void Main(string[] args)
            {
                CommContext cmt = new CommContext();
                IntPtr cmtPtr = Marshal.AllocHGlobal(Marshal.SizeOf(cmt));
                Marshal.StructureToPtr(cmt, cmtPtr, true);
    
                string host = "LocalHost";
                byte[] hostBytes = Encoding.UTF8.GetBytes(host + "\0");
                IntPtr hostPtr = Marshal.AllocHGlobal(hostBytes.Length);
                Marshal.Copy(hostBytes, 0, hostPtr, hostBytes.Length);
    
                string username = "username";
                byte[] usernameBytes = Encoding.UTF8.GetBytes(username + "\0");
                IntPtr usernamePtr = Marshal.AllocHGlobal(usernameBytes.Length);
                Marshal.Copy(usernameBytes, 0, usernamePtr, usernameBytes.Length);
    
                string password = "password";
                byte[] passwordBytes = Encoding.UTF8.GetBytes(password + "\0");
                IntPtr passwordPtr = Marshal.AllocHGlobal(passwordBytes.Length);
                Marshal.Copy(passwordBytes, 0, passwordPtr, passwordBytes.Length);
    
                string shell_cmd = "shell_cmd";
                byte[] shell_cmdBytes = Encoding.UTF8.GetBytes(shell_cmd + "\0");
                IntPtr shell_cmdPtr = Marshal.AllocHGlobal(shell_cmdBytes.Length);
                Marshal.Copy(shell_cmdBytes, 0, shell_cmdPtr, shell_cmdBytes.Length);
    
                const int BUF_LEN = 256;
                IntPtr errmsgPtr = new IntPtr(BUF_LEN);
                int bLen = BUF_LEN;
    
                WSAData data = new WSAData();
                WSAStartup(0x201, out data);
    
                IntPtr sio = socket(ADDRESS_FAMILIES_INT.AF_INET, SOCKET_TYPE_INT.SOCK_STREAM, PROTOCOL_INT.IPPROTO_TCP);
    
                IntPtr sErr = socket(ADDRESS_FAMILIES_INT.AF_INET, SOCKET_TYPE_INT.SOCK_STREAM, PROTOCOL_INT.IPPROTO_TCP);
    
                int results = WaitForLogon(cmtPtr, hostPtr, usernamePtr, passwordPtr, shell_cmdPtr, errmsgPtr, bLen, sio, sErr);
    
                string error = Marshal.PtrToStringAuto(errmsgPtr);
            }
        }
    }
    

    【讨论】:

    • 您能否通过解释您在 OP 的代码中观察到的问题、您认为什么方法、为什么它对 OP 的选择有效以及您是如何实现的来改进您的答案?因为现在它看起来像“复制粘贴这个,它会解决你的问题”。不过,这不是我的反对意见。
    • 我使用在 pinvoke.net 上找到的一些结构自己开发了这段代码,但该代码不在 pinvoke.net 上。我使用了 40 年的经验,多次阅读 K&R “C 语言”,并在午餐期间多次阅读 unix 手册。原始代码的主要问题没有使用指针来传递参数,而是将参数编组到托管内存。用户没有指定要使用的套接字类型,所以我使用了 ws2_32 套接字并使用 pinvoke.net 来指导我找到正确的解决方案。 Pinvoke 在一些对 msdn 的链接引用,我也将其用作参考。
    • 我真的不知道你想通过那个评论告诉我什么。我所要求的只是让你改进你的答案。
    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 2010-11-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多