上次那个P/Invoke调用WinAPI的是用Borland Delphi和Cassini服务器,本来以为没问题的,结果最近换到了IIS上,FindWindow就找不到窗口了,经过研究,发现问题出在IIS是作为系统服务运行这上面。
Cassini是以administrator运行的一个程序,而IIS不是,所以找不到窗口。
解决的办法是把IIS的服务设成“允许与桌面交互”,但是这样对安全性不好。
CodeProject上的一个解决方法是自己写一个服务,把那个允许交互打开,而API调用他用了System.Runtime.Remoting,具体还没有完全理解,感觉M$挺神奇的。
[color=#0000D0]using[/color] System;
[color=#0000D0]using[/color] System.Collections;
[color=#0000D0]using[/color] System.ComponentModel;
[color=#0000D0]using[/color] System.Configuration;
[color=#0000D0]using[/color] System.Data;
[color=#0000D0]using[/color] System.Diagnostics;
[color=#0000D0]using[/color] System.ServiceProcess;
[color=#0000D0]using[/color] System.Runtime.Remoting;
[color=#0000D0]using[/color] System.Runtime.Remoting.Channels;
[color=#0000D0]using[/color] System.Runtime.Remoting.Channels.Tcp;
[color=#0000D0]using[/color] EJudge.BizClass;
[color=#0000D0]namespace[/color] BridgeService
{
[color=#0000D0]public[/color] [color=#0000D0]class[/color] Service : System.ServiceProcess.ServiceBase
{
[color=#008000]/// <summary> [/color]
[color=#008000]/// 远程调用桥接服务主程序[/color]
[color=#008000]/// 由于不想打开IIS服务的允许与桌面交互(据说比较危险)[/color]
[color=#008000]/// 所以写了这个桥接服务提供FindWindow、SendMessage等[/color]
[color=#008000]/// 以便与WinAPP通信[/color]
[color=#008000]/// </summary>[/color]
[color=#0000D0]private[/color] System.ComponentModel.Container components = null;
[color=#008000]// tcp通道[/color]
[color=#0000D0]private[/color] TcpChannel m_channel;
[color=#0000D0]public[/color] Service()
{
[color=#008000]// This call is required by the Windows.Forms Component Designer.[/color]
InitializeComponent();
[color=#008000]// TODO: Add any initialization after the InitComponent call[/color]
}
[color=#008000]// The main entry point for the process[/color]
[color=#0000D0]static[/color] [color=#0000D0]void[/color] Main()
{
System.ServiceProcess.ServiceBase[] ServicesToRun;
[color=#008000]// More than one user Service may run within the same process. To add[/color]
[color=#008000]// another service to this process, change the following line to[/color]
[color=#008000]// create a second service object. For example,[/color]
[color=#008000]//[/color]
[color=#008000]// ServicesToRun = new System.ServiceProcess.ServiceBase[] {new Service(), new MySecondUserService()};[/color]
[color=#008000]//[/color]
ServicesToRun = [color=#0000D0]new[/color] System.ServiceProcess.ServiceBase[] { [color=#0000D0]new[/color] Service() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}
[color=#008000]/// <summary> [/color]
[color=#008000]/// Required method for Designer support – do not modify [/color]
[color=#008000]/// the contents of this method with the code editor.[/color]
[color=#008000]/// </summary>[/color]
[color=#0000D0]private[/color] [color=#0000D0]void[/color] InitializeComponent()
{
components = [color=#0000D0]new[/color] System.ComponentModel.Container();
[color=#008000]// 服务名称[/color]
[color=#0000D0]this[/color].ServiceName = [color=#808080]”EJudgeBridgeService”[/color];
}
[color=#008000]/// <summary>[/color]
[color=#008000]/// Clean up any resources being used.[/color]
[color=#008000]/// </summary>[/color]
[color=#0000D0]protected[/color] override [color=#0000D0]void[/color] Dispose( bool disposing )
{
[color=#0000D0]if[/color]( disposing )
{
[color=#0000D0]if[/color] (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
[color=#008000]/// <summary>[/color]
[color=#008000]/// Set things in motion so your service can do its work.[/color]
[color=#008000]/// </summary>[/color]
[color=#0000D0]protected[/color] override [color=#0000D0]void[/color] OnStart([color=#0000D0]string[/color][] args)
{
[color=#008000]// TODO: Add code here to start your service.[/color]
[color=#008000]// 监听端口[/color]
[color=#0000D0]int[/color] iTcpChannelVal = 0;
[color=#0000D0]try[/color]
{
[color=#008000]// 尝试从配置文件中取得监听端口[/color]
iTcpChannelVal = [color=#0000D0]int[/color].Parse(ConfigurationSettings.AppSettings[[color=#808080]”ChannelNum”[/color]]);
}
[color=#0000D0]catch[/color](Exception)
{
[color=#008000]// 如果没有则使用1096默认端口[/color]
iTcpChannelVal = 1096;
}
[color=#008000]// 初始化[/color]
m_channel = [color=#0000D0]new[/color] TcpChannel(iTcpChannelVal);
[color=#008000]// 注册通道[/color]
ChannelServices.RegisterChannel(m_channel);
[color=#008000]// 应用程序名,提供Web程序通过URL取得对象实例与WinAPP通信[/color]
RemotingConfiguration.ApplicationName = [color=#808080]”EJudgeController”[/color];
[color=#008000]// 使用“著名”的singleton单身模式[/color]
RemotingConfiguration.RegisterWellKnownServiceType(typeof(CWinAPI),[color=#808080]”EJudgeController”[/color],WellKnownObjectMode.Singleton);
}
[color=#008000]/// <summary>[/color]
[color=#008000]/// Stop this service.[/color]
[color=#008000]/// </summary>[/color]
[color=#0000D0]protected[/color] override [color=#0000D0]void[/color] OnStop()
{
[color=#008000]// TODO: Add code here to perform any tear-down necessary to stop your service.[/color]
[color=#008000]// 取消注册的TCP通道[/color]
ChannelServices.UnregisterChannel(m_channel);
}
}
}
调用的时候这样
// 通过bridge服务取得对象实例
CWinAPI winapi = (CWinAPI)Activator.GetObject(typeof(CWinAPI),”tcp://localhost:1096/EJudgeController”);
// 提交消息发送请求
winapi.IncomingCode(100,20);
博主友情提示:
如您在评论中需要提及如QQ号、电子邮件地址或其他隐私敏感信息,欢迎使用>>博主专用加密工具v3<<处理后发布,原文只有博主可以看到。