IIS服务程序在Win7,Window Server 2008下与应用程序模块(如DLL的调用注意事项

    微软Window XP后的操作系统把服务程序(如IIS服务)和应用程序分隔在不同的session(服务程序运行在0),所以应用程序与服务程序之前进行信息交互时与在XP上存在区别,遇到的情况主要有:

a)按同一会话层的方式发送消息,双方相互会收不到。

b)按同一会话层的方式进行参数传递,遇到寻址方式不一样的情况会寻址出错。

    针对以上a)b)两的点解决方法:

a)的解决方法:修改双方的消息发送方式,如可以通过创建 命名管道(named pipes)或者是进程通信(如内存文件映射实现内存共享)来解决。

b)的解决方法

1)双方使用相同的寻址方式,并由发起者创建好内存区域; 

2)进程通信(如内存文件映射实现内存共享)来解决;

3)直接通过访问指定文件的方式来实现信息交互。

 

以下为使用相同的寻址方式,并由发起者创建好内存区域的示例:

1.首先使用VS2008创建一个WEB工程,并在主页面调用VSC++ DLLdelphi DLL如下所示(主页面代码):

using System;

using System.Collections;

using System.Configuration;

using System.Data;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

 

using System.Reflection;

using System.Runtime.InteropServices;

using System.IO;

using System.Text;

 

namespace WebApplication1 //把此处的命令空间名称改为自己工程的命令空间即可 创建网页工作在此不说//

{

    public partial class _Default : System.Web.UI.Page

    {

        //delphi DLl

        private delegate int _intandstr(int intvalue, byte[] outstr, byte[] licenceinfo, byte[] len);

        private _intandstr intandstrFun;

        private delegate void _intandstrA(int intvalue, byte[] outstr, byte[] licenceinfo, byte[] len, byte[] ResultValue);

        private _intandstrA intandstrAFun;  

        private const string testdllFilePath = "\\bin\\testdll.dll";

 

        //VS C++     

        private delegate int _ParseLicenseDataA(byte[] aUnitName, int aUnitNameLen, byte[] aLicenseInfo, byte[] aLen);

        private _ParseLicenseDataA ParseLicenseDataAFun; 

        private const string CalldllFilePath = "\\bin\\licenseWin.dll";

 

        protected void Page_Load(object sender, EventArgs e)

        {

            if (!Page.IsPostBack)

            {

 

                //delphi DLL

                try

                {

                    int hModule = DLLWrapper.LoadLibrary(MapPath("") + testdllFilePath);

                    if (hModule == 0)

                    {

                        return;

                    }

 

                    intandstrFun = (_intandstr)DLLWrapper.GetAddress(hModule, "intandstr"typeof(_intandstr));

                    if (intandstrFun != null)

                    {                       

                        byte[] outstr = Encoding.Default.GetBytes("1111111111111111111111111111111111111111111111111111111111111111111111111111111111");

                        byte[] licenceinfo = new byte[1000];

                        byte[] len = new byte[2];

 

 

                        int resultStrValue1 = intandstrFun(100, outstr, licenceinfo, len);

                        string xmlReusl = outstr.ToString();

                        int valueconst = 50;

                        if ((outstr[1] == valueconst) && (outstr[10] == valueconst) && (outstr[0] == 49) && (outstr[11] == 49))

                        {

                            int InfoLen = (len[0] << 8) + len[1]; 

 

                            if ((InfoLen == resultStrValue1) && (licenceinfo.Length > 0))

                            {

                                Response.Write("<script type='text/javascript'>alert('" + "测试调用delphi dll intandstr方法修改传入的参数和返回参数值OK" + "');</script>");

                            }

                            else

                            {

                                Response.Write("<script type='text/javascript'>alert('" + "测试调用delphi dll intandstr方法修改返回值不对" + "');</script>");

                            }

                        }

                    }

                    else

                    {

                        Response.Write("<script type='text/javascript'>alert('" + "测试调用delphi dll 方法加载失败!" + "');</script>");

                    }                  

                 }

                catch

                {

                    Response.Write("<script type='text/javascript'>alert('" + "测试调用 delphi dll 失败" + "');</script>");

                    //Page.Response.Redirect("../Common/RepeatLoginTip.htm");

                }

 

 

                //VS C++ DLL

                try

                {

                    string UnitName = "abc";

 

                    int hModule = DLLWrapper.LoadLibrary(MapPath("") + CalldllFilePath);

                    if (hModule == 0)

                    {

                        Response.Write("<script type='text/javascript'>alert('" + "测试调用 VC C++ DLL Dll文件加载失败" + "');</script>");

                        return;

                    }

 

                    ParseLicenseDataAFun = (_ParseLicenseDataA)DLLWrapper.GetAddress(hModule, "ParseLicenseDataA"typeof(_ParseLicenseDataA));

                    UnitName = "111111111111111111111111111111111111111111111111";

                    byte[] byteUnitName = Encoding.Default.GetBytes(UnitName);

                    byte[] bytelicenceinfo = new byte[5000];

                    byte[] bytelen = new byte[2];

                    byte[] byteLicenseLen = Encoding.Default.GetBytes(StationName);

 

 

                    int ResultInt = ParseLicenseDataAFun(byteUnitName, 100, bytelicenceinfo, bytelen);

                    if ((ResultInt != 100) && (bytelen[0] == 0) && (bytelen[1] == 4))

                    {

                        if ((byteUnitName[0] == 50) && (byteUnitName[1] == 50) && (byteUnitName[2] == 50) && (byteUnitName[3] == 49))

                        {

                            if ((bytelicenceinfo[0] == 49) && (bytelicenceinfo[1] == 50) && (bytelicenceinfo[2] == 97) && (bytelicenceinfo[3] == 98))

                            {

                                Response.Write("<script type='text/javascript'>alert('" + "测试调用 VS C++ DLL ParseLicenseDataA方法成功" + "');</script>");

                            }

                        }

                    }

                    else

                    {

                        Response.Write("<script type='text/javascript'>alert('" + "测试调用 VS C++ DLL ParseLicenseDataA方法失败" + "');</script>");

                    }

                }

                catch

                {

                    Response.Write("<script type='text/javascript'>alert('" + "测试调用 VS C++ DLL 接口失败" + "');</script>");

                }

            }

 

        }

    }

}

 

 

public class DLLWrapper

{

    public DLLWrapper()

    {

    }

 

    ///<summary>

    /// API LoadLibrary

    ///</summary>

    [DllImport("Kernel32")]

    public static extern int GetProcAddress(int handle, String funcname);

 

    ///<summary>

    /// API GetProcAddress

    ///</summary>

    [DllImport("Kernel32")]

    public static extern int LoadLibrary(String funcname);

 

    [DllImport("Kernel32")]

    public static extern int FreeLibrary(int handle);

 

    //<summary>

    ///通过非托管函数名转换为对应的委托

    ///</summary>

    ///<param name="dllModule">通过LoadLibrary获得的DLL句柄</param>

    ///<param name="functionName">非托管函数名</param>

    ///<param name="t">对应的委托类型</param>

    ///<returns>委托实例,可强制转换为适当的委托类型</returns>

    public static Delegate GetAddress(int dllModule, string functionname, Type t)

    {

        int addr = GetProcAddress(dllModule, functionname);

        if (addr == 0)

            return null;

        else

            return Marshal.GetDelegateForFunctionPointer(new IntPtr(addr), t);

 

    }

 

    ///<summary>

    ///将表示函数地址的IntPtr实例转换成对应的委托, by jingzhongrong

    ///</summary>

    public static Delegate GetDelegateFromIntPtr(IntPtr address, Type t)

    {

        if (address == IntPtr.Zero)

            return null;

        else

            return Marshal.GetDelegateForFunctionPointer(address, t);

    }

 

    ///<summary>

    ///将表示函数地址的int转换成对应的委托,by jingzhongrong

    ///</summary>

    public static Delegate GetDelegateFromIntPtr(int address, Type t)

    {

        if (address == 0)

            return null;

        else

            return Marshal.GetDelegateForFunctionPointer(new IntPtr(address), t);

    }

 

 

}

 

2.使用VS 2008创建 VC++Win32  DLL工程如下所示:

VS C++ DLL接口声明头文件:

#ifndef TestDll_H_

#define TestDll_H_

#ifdef MYLIBDLL

#define MYLIBDLL extern "C" _declspec(dllimport)

#else

#define MYLIBDLL extern "C" _declspec(dllexport)

#endif

MYLIBDLL int Add(int plus1, int plus2);

MYLIBDLL int test(int value1);

MYLIBDLL int ParseLicenseDataA(char* aUnitName, int aUnitNameLen, char* aLicenseInfo, char * aLen);

 

#endif

 

VS C++ DLL 接口方法实现:

 

#include "stdafx.h"

#include "licenseWin.h"

#include <iostream>

using namespace std;

 

int test(int value1)

{

   int ResultValue = value1 * value1;

   return ResultValue;

}

 

int Add(int plus1, int plus2)

{

 int add_result = plus1 + plus2;

 return add_result;

}

 

int ParseLicenseDataA(char* aUnitName, int aUnitNameLen, char* aLicenseInfo, char * aLen)

{

if (aUnitNameLen == 100)

{

aUnitName[0] = 50;//2

aUnitName[1] = 50;

aUnitName[2] = 50;

aLicenseInfo[0] = 49; //1

aLicenseInfo[1] = 50;

aLicenseInfo[2] = 97;//a

aLicenseInfo[3] = 98;

aLen[0] = 0;

aLen[1] = 4;

return 4;

}

else

{

return aUnitNameLen;

 

}

}

 

VS C++ 接口导出:

LIBRARY licenseWin

EXPORTS

 ; 此处可以是显式导出

 Add 

 test

 ParseLicenseDataA

 

 

3.使用delphi创建DLL工程如下所示:

Delphi DLL工程文件:

library testdll;

 

{ Important note about DLL memory management: ShareMem must be the

  first unit in your library's USES clause AND your project's (select

  Project-View Source) USES clause if your DLL exports any procedures or

  functions that pass strings as parameters or function results. This

  applies to all strings passed to and from your DLL--even those that

  are nested in records and classes. ShareMem is the interface unit to

  the BORLNDMM.DLL shared memory manager, which must be deployed along

  with your DLL. To avoid using BORLNDMM.DLL, pass string information

  using PChar or ShortString parameters. }

 

uses

  SysUtils,

  Classes,

  dllFunUnit in 'dllFunUnit.pas';

 

{$R *.res}

 

exports

  intandstr,

  intandstrA;

 

begin

End.

 

Delphi DLL接口代码实现:

unit dllFunUnit;

 

interface

 

function intandstr(intvalue: Integer; instr: PChar; licenceinfo: PChar; len: PChar): Integer; stdcall ;

function intandstrA(intvalue: Integer; instr: PChar; licenceinfo: PChar; len: PChar): PChar; stdcall ;

 

implementation

 

uses

  Dialogs, SysUtils;

 

function intandstr(intvalue: Integer; instr: PChar; licenceinfo: PChar; len: PChar): Integer; stdcall ;

const

  str = '2222222222';

var

  LicenceStr: PChar;

  licenceLen: Integer ;

  tempLen: array[0..1] of Byte;

begin

  Result := 0;

  if intvalue > 0 then

  begin

    //instr[1] := str[1];//修改无效,需要使用move进行内存复制

    Move(str[1], instr[1], Length(str)); //即使用move修改传入参数的内容

    LicenceStr := PChar('112233445566778899中国abc~<>');

    licenceLen := Length(LicenceStr);

    Move(LicenceStr[0], licenceinfo[0], licenceLen);  //使用move内存复制方式输出信息

    //len[0] := licenceLen shr 8; //直接修改无效,需要使用move进行内存复制

    tempLen[0] := licenceLen shr 8;

    Move(tempLen[0],len[0],1);

    tempLen[1] := licenceLen and $00FF;

    Move(tempLen[1],len[1],1);

    Result := licenceLen;

  end;

end;

 

function intandstrA(intvalue: Integer; instr: PChar; licenceinfo: PChar; len: PChar): PChar; stdcall ;

const

  str = '2222222222';

var

  LicenceStr: PChar;

  licenceLen: Integer ;

  tempLen: array[0..1] of Byte;

begin

  Result := 0;

  if intvalue > 0 then

  begin

    //instr[1] := str[1];//修改无效,需要使用move进行内存复制

    Move(str[1], instr[1], Length(str)); //即使用move修改传入参数的内容

    LicenceStr := PChar('112233445566778899中国abc~<>');

    licenceLen := Length(LicenceStr);

    Move(LicenceStr[0], licenceinfo[0], licenceLen);  //使用move内存复制方式输出信息

    //len[0] := licenceLen shr 8; //直接修改无效,需要使用move进行内存复制

    tempLen[0] := licenceLen shr 8;

    Move(tempLen[0],len[0],1);

    tempLen[1] := licenceLen and $00FF;

    Move(tempLen[1],len[1],1);

    Move(LicenceStr[0], Result[0], licenceLen);

    //ShowMessage(Result);//注意在WIN7下非开发环境下,即发布后,由于运行在不同的会话层,不能显示窗体,显示也看不到,看不到也就关闭不了窗体,

//关闭不了会引起网页程序请求超时,C/S程序直接当机

  end;

end;

 

End.

 

4.以上步骤做完后,把VS C++DLLdlephi DLL文件拷贝到 VS 2008的网页工程bin目录(也可以直接设置VS C++delphi工程的编译输出目录为VS 2008的网页工程bin目录)。

5.WIN7IIS管理器发布此网页程序(先要安装IIS),通过浏览布置好的网站即可查看到调用VS C++的DLLDelphi DLL的效果。

 

posted on 2012-12-10 21:33  about88  阅读(1368)  评论(0编辑  收藏  举报