IIS服务程序在Win7,Window Server 2008下与应用程序模块(如DLL)之间的调用注意事项
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++ DLL和delphi 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;
byte[] len = new byte;
int resultStrValue1 = intandstrFun(100, outstr, licenceinfo, len);
string xmlReusl = outstr.ToString();
int valueconst = 50;
if ((outstr == valueconst) && (outstr == valueconst) && (outstr == 49) && (outstr == 49))
{
int InfoLen = (len0))
{
Response.Write("alert('" + "测试调用delphi dll intandstr方法修改传入的参数和返回参数值OK" + "');");
}
else
{
Response.Write("alert('" + "测试调用delphi dll intandstr方法修改返回值不对" + "');");
}
}
}
else
{
Response.Write("alert('" + "测试调用delphi dll 方法加载失败!。" + "');");
}
}
catch
{
Response.Write("alert('" + "测试调用 delphi dll 失败" + "');");
//Page.Response.Redirect("../Common/RepeatLoginTip.htm");
}
//VS C++ DLL
try
{
string UnitName = "abc";
int hModule = DLLWrapper.LoadLibrary(MapPath("") + CalldllFilePath);
if (hModule == 0)
{
Response.Write("alert('" + "测试调用 VC C++ DLL Dll文件加载失败" + "');");
return;
}
ParseLicenseDataAFun = (_ParseLicenseDataA)DLLWrapper.GetAddress(hModule, "ParseLicenseDataA", typeof(_ParseLicenseDataA));
UnitName = "111111111111111111111111111111111111111111111111";
byte[] byteUnitName = Encoding.Default.GetBytes(UnitName);
byte[] bytelicenceinfo = new byte;
byte[] bytelen = new byte;
byte[] byteLicenseLen = Encoding.Default.GetBytes(StationName);
int ResultInt = ParseLicenseDataAFun(byteUnitName, 100, bytelicenceinfo, bytelen);
if ((ResultInt != 100) && (bytelen == 0) && (bytelen == 4))
{
if ((byteUnitName == 50) && (byteUnitName == 50) && (byteUnitName == 50) && (byteUnitName == 49))
{
if ((bytelicenceinfo == 49) && (bytelicenceinfo == 50) && (bytelicenceinfo == 97) && (bytelicenceinfo == 98))
{
Response.Write("alert('" + "测试调用 VS C++ DLL ParseLicenseDataA方法成功" + "');");
}
}
}
else
{
Response.Write("alert('" + "测试调用 VS C++ DLL ParseLicenseDataA方法失败" + "');");
}
}
catch
{
Response.Write("alert('" + "测试调用 VS C++ DLL 接口失败" + "');");
}
}
}
}
}
public class DLLWrapper
{
public DLLWrapper()
{
}
///
/// API LoadLibrary
///
public static extern int GetProcAddress(int handle, String funcname);
///
/// API GetProcAddress
///
public static extern int LoadLibrary(String funcname);
public static extern int FreeLibrary(int handle);
//
///通过非托管函数名转换为对应的委托
///
///通过LoadLibrary获得的DLL句柄
///非托管函数名
///对应的委托类型
///委托实例,可强制转换为适当的委托类型
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);
}
///
///将表示函数地址的IntPtr实例转换成对应的委托, by jingzhongrong
///
public static Delegate GetDelegateFromIntPtr(IntPtr address, Type t)
{
if (address == IntPtr.Zero)
return null;
else
return Marshal.GetDelegateForFunctionPointer(address, t);
}
///
///将表示函数地址的int转换成对应的委托,by jingzhongrong
///
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++Win32DLL工程如下所示:
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
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 = 50;//2
aUnitName = 50;
aUnitName = 50;
aLicenseInfo = 49; //1
aLicenseInfo = 50;
aLicenseInfo = 97;//a
aLicenseInfo = 98;
aLen = 0;
aLen = 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 of Byte;
begin
Result := 0;
if intvalue > 0 then
begin
//instr := str;//修改无效,需要使用move进行内存复制
Move(str, instr, Length(str)); //即使用move修改传入参数的内容
LicenceStr := PChar('112233445566778899中国abc~');
licenceLen := Length(LicenceStr);
Move(LicenceStr, licenceinfo, licenceLen);//使用move内存复制方式输出信息
//len := licenceLen shr 8; //直接修改无效,需要使用move进行内存复制
tempLen := licenceLen shr 8;
Move(tempLen,len,1);
tempLen := licenceLen and $00FF;
Move(tempLen,len,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 of Byte;
begin
Result := 0;
if intvalue > 0 then
begin
//instr := str;//修改无效,需要使用move进行内存复制
Move(str, instr, Length(str)); //即使用move修改传入参数的内容
LicenceStr := PChar('112233445566778899中国abc~');
licenceLen := Length(LicenceStr);
Move(LicenceStr, licenceinfo, licenceLen);//使用move内存复制方式输出信息
//len := licenceLen shr 8; //直接修改无效,需要使用move进行内存复制
tempLen := licenceLen shr 8;
Move(tempLen,len,1);
tempLen := licenceLen and $00FF;
Move(tempLen,len,1);
Move(LicenceStr, Result, licenceLen);
//ShowMessage(Result);//注意在WIN7下非开发环境下,即发布后,由于运行在不同的会话层,不能显示窗体,显示也看不到,看不到也就关闭不了窗体,
//关闭不了会引起网页程序请求超时,C/S程序直接当机
end;
end;
End.
4.以上步骤做完后,把VS C++的DLL和dlephi 的DLL文件拷贝到 VS 2008的网页工程bin目录(也可以直接设置VS C++和delphi工程的编译输出目录为VS 2008的网页工程bin目录)。
5.在WIN7下IIS管理器发布此网页程序(先要安装IIS),通过浏览布置好的网站即可查看到调用VS C++的DLL和Delphi DLL的效果。
页:
[1]