还是那个P/Invoke,发现了一个小问题

上次那个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号、微信号、电子邮件地址或其他隐私敏感信息,欢迎通过>>博主专用加密工具v2<<加密后发布,原文只有博主可以看到。