首页 > 编程语言 > C# > C#调用返回值为字符串的dll api,调试模式下崩溃的问题
2013
09-01

C#调用返回值为字符串的dll api,调试模式下崩溃的问题

有人反映QQ超人打码在vs2012 C#环境中调试模式下崩溃,而vs2010中没有出现这样的问题.
插件的api返回值都是字符串类型,考虑vs2012中C#的托管指针调试可能有改动.所以将返回值类型修改为IntPtr,在调用api后,将返回值用Marshal.PtrToStringAnsi转为字符串,解决方法繁琐了点,不知有无更好的方案了.

C#代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.IO;
using System.Collections;

namespace QQ超人打码范例
{

    class Program
    {
         
        [DllImport("dc.dll")]
        private static extern IntPtr GetUserInfo(string user, string pass);
        [DllImport("dc.dll")]
        private static extern IntPtr RecByte_A(byte[] img, int imgLen, string user, string pass, string softId);
        [DllImport("dc.dll")]
        private static extern IntPtr RecYZM_A(string imgPath, string user, string pass, string softId);
        [DllImport("dc.dll")]
        private static extern void ReportError(string user, string worker);
        static void Main(string[] args)
        {
            //账号配置
            string user = "user";
            string pass = "pass";
            string softId = "0";

            //查询剩余点数
            IntPtr info = GetUserInfo(user, pass);
            Console.WriteLine("剩余点数{0}",Marshal.PtrToStringAnsi(info));   
        
            //按图片数据识别验证码
            FileStream fs = new FileStream("code.jpg", FileMode.Open,FileAccess.Read);
            byte[] bFile = new byte[fs.Length];
            BinaryReader r = new BinaryReader(fs);
            bFile=r.ReadBytes((int)fs.Length);
            r.Close();
            r=null;
            fs.Close();

            Console.WriteLine("RecByte_A验证码远程识别中");
            IntPtr result = RecByte_A(bFile, bFile.Length, user, pass, softId);
            Console.WriteLine("返回的验证码识别结果:{0}", Marshal.PtrToStringAnsi(result));
            
            //按图片路径识别验证码
            Console.WriteLine("RecYZM_A验证码远程识别中");
            IntPtr result2 = RecYZM_A("code.jpg", user, pass, softId);
            Console.WriteLine("返回的验证码识别结果:{0}", Marshal.PtrToStringAnsi(result2));

            /*
            //报告错误 只有在确定验证码错误的情况下才调用该函数
            string worker = "F36B1D3A30474A75B497D82FC6342CFC";
            ReportError(user,worker);
            */
            Console.Read();
        }
    }
}

有个类似的例子就是python下的调用,python调用的时候,也是返回托管的字符串指针,需要用ctypes.string_at将指针转换为字符串

# -*- coding:utf-8 -*-
import ctypes
import sys
from os.path import join, dirname, abspath, exists

dll = ctypes.windll.LoadLibrary(join(dirname(__file__),'dc.dll'))

class dcVerCode:
    #user QQ超人打码账号
    #pwd QQ超人打码密码
    #softId 软件ID 缺省为0,作者务必提交softId,已保证分成
    def __init__(self,user,pwd,softId="0"):
        self.user = user
        self.pwd = pwd
        self.softId = softId

    #获取账号剩余点数
    def getUserInfo(self):
        p = dll.GetUserInfo(self.user,self.pwd)
        if p:
            return ctypes.string_at(p,-1)
        return ''

    def parseResult(self,result):
        list = result.split('|')
        if len(list)==3:
            return (list[0],list[2])
        return (NULL,NULL)

    #recByte 根据图片二进制数据识别验证码,返回验证码,打码工人编号
    #buffer 图片二进制数据
    def recByte(self,buffer):
        p = dll.RecByte_A(buffer,len(buffer),self.user,self.pwd,self.softId)
        if p:
            str = ctypes.string_at(p,-1)
            return self.parseResult(str)
        return ''

    #recYZM 根据验证码路径识别,返回验证码,打码工人编号
    #path 图片路径
    def recYZM(self,path):
        p = dll.RecYZM_A(path,self.user,self.pwd,self.softId)
        if p:
            str = ctypes.string_at(p,-1)
            return self.parseResult(str)
        return ''

    #reportErr 提交识别错误验证码
    #worker 打码工人编号
    def reportErr(self,worker):
        dll.ReportError(self.user,worker)

if __name__ == '__main__':
    client = dcVerCode("user","pass","0");
    img = open('c:\\123.jpg','rb')
    buffer = img.read()
    img.close()
    print (client.getUserInfo())
    yzm,worker = client.recByte(buffer)
    print(yzm,worker)
    yzm,worker = client.recYZM("c:\\123.jpg")
    print ( yzm,worker )
    #client.reportErr(worker) 只有在验证码识别错误时才运行这个方法,恶意提交将会受到惩罚
最后编辑:
作者:NINE
这个作者貌似有点懒,什么都没有留下。

留下一个回复

你的email不会被公开。