说明:本来想使用ActaionX来实现B/S调起exe程序并传入参数,但是AcationX只能IE内核的浏览器使用,谷歌或火狐浏览器也是可以使用,但是得要安装插件,大家都知道谷歌需要翻墙才能访问插件中心,我们公司推荐使用谷歌浏览,所以就只能自己开发一个监听插件来实现此功能。
准备工作:环境介绍 vs2019 和 setup打包exe插件
1、自启并添加到注册表代码
using Microsoft.Win32;
using System;
using System.Windows.Forms;
namespace IDP_Agent_Geo
{
public class AutoRunHelper
{
#region 添加当前程序到注册表自启动项中
/// <summary>
/// 将程序添加到注册表自启动中
/// </summary>
/// <returns></returns>
public static bool AddAutoRun()
{
bool isSuccess = false;
//获取当前应用程序的路径
string localPath = Application.ExecutablePath;
//判断指定文件是否存在
if (!System.IO.File.Exists(localPath))
{
throw new Exception("找不到文件:" + localPath);
}
RegistryKey reg = Registry.CurrentUser;
RegistryKey run = reg.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
//判断注册表中是否存在当前名称和值
//string productName = System.IO.Path.GetFileName(localPath);
string productName = Application.ProductName;
if (run.GetValue(productName) == null)
{
run.SetValue(productName, localPath);
reg.Close();
}
isSuccess = true;
return isSuccess;
}
/// <summary>
/// 从注册表自启动中删除当前程序
/// </summary>
/// <returns></returns>
public static bool RemoveAutoRun()
{
string productName = Application.ProductName;
return RemoveAutoRun(productName);
}
#endregion
#region 添加指定程序到注册表自启动项中
/// <summary>
/// 将程序添加到注册表自启动中
/// </summary>
/// <returns></returns>
public static bool AddAutoRun(string filePath)
{
bool isSuccess = false;
//判断指定文件是否存在
if (!System.IO.File.Exists(filePath))
{
throw new Exception("找不到文件:" + filePath);
}
RegistryKey reg = Registry.LocalMachine;
RegistryKey run = reg.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
//判断注册表中是否存在当前名称和值
string productName = System.IO.Path.GetFileName(filePath);
if (run.GetValue(productName) == null)
{
run.SetValue(productName, filePath);
reg.Close();
}
isSuccess = true;
return isSuccess;
}
/// <summary>
/// 从注册表自启动中删除指定程序
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static bool RemoveAutoRun(string key)
{
bool isSuccess = false;
RegistryKey reg = Registry.LocalMachine;
RegistryKey run = reg.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
run.DeleteValue(key);
reg.Close();
isSuccess = true;
return isSuccess;
}
#endregion
}
}
2、监听插件代码
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Web;
using System.Windows.Forms;
namespace IDP_Agent_Geo
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form1());
#region 开机自启处理
try
{
bool autoRun = Convert.ToBoolean(System.Configuration.ConfigurationManager.AppSettings["AutoRun"]);
if (autoRun)
{
bool isSuccess = AutoRunHelper.AddAutoRun();
if (!isSuccess)
{
Console.WriteLine("开机自启处理失败!");
}
}
}
catch (Exception ex)
{
Console.WriteLine("开机自启处理失败!提示:" + ex.Message);
}
#endregion
//调用监听器方法
AppListerner();
}
//根据ip和端口来监听,并接收参数启动应用程序
private static void AppListerner()
{
HttpListener listerner = new HttpListener();
while (true)
{
try
{
listerner.AuthenticationSchemes = AuthenticationSchemes.Anonymous;//指定身份验证 Anonymous匿名访问
listerner.Prefixes.Add("http://127.0.0.1:18080/");
listerner.Start();
}
catch (Exception ex)
{
Console.WriteLine("服务启动失败...");
break;
}
Console.WriteLine("服务器启动成功.......");
//线程池
int minThreadNum;
int portThreadNum;
int maxThreadNum;
ThreadPool.GetMaxThreads(out maxThreadNum, out portThreadNum);
ThreadPool.GetMinThreads(out minThreadNum, out portThreadNum);
Console.WriteLine("最大线程数:{0}", maxThreadNum);
Console.WriteLine("最小空闲线程数:{0}", minThreadNum);
//ThreadPool.QueueUserWorkItem(new WaitCallback(TaskProc1), x);
Console.WriteLine("\n\n等待客户连接中。。。。");
while (true)
{
//等待请求连接
//没有请求则GetContext处于阻塞状态
HttpListenerContext ctx = listerner.GetContext();
ThreadPool.QueueUserWorkItem(new WaitCallback(TaskProc), ctx);
}
listerner.Stop();
}
Console.ReadKey();
}
//执行任务
private static void TaskProc(object o)
{
HttpListenerContext ctx = (HttpListenerContext)o;
try {
HttpListenerRequest request = ctx.Request;
//请求类型
String _method = request.HttpMethod;
ctx.Response.StatusCode = 200;//设置返回给客服端http状态代码
string executPath = "";
string idToken = "";
if ("POST".Equals(_method))
{
//接收POST参数
Stream stream = ctx.Request.InputStream;
System.IO.StreamReader reader = new System.IO.StreamReader(stream, Encoding.UTF8);
String body = reader.ReadToEnd();
JObject jo = (JObject)JsonConvert.DeserializeObject(body);
Console.WriteLine("收到POST数据:" + HttpUtility.UrlDecode(body));
Console.WriteLine("解析:" + jo["executPath"].ToString());
executPath = jo["executPath"].ToString();
idToken = jo["idToken"].ToString();
}
else
{
//接收Get参数
executPath = ctx.Request.QueryString["executPath"];
idToken = ctx.Request.QueryString["idToken"];
/*string filename = Path.GetFileName(ctx.Request.RawUrl);
string userName = HttpUtility.ParseQueryString(filename).Get("userName");//避免中文乱码*/
//进行处理
Console.WriteLine("收到数据:" + executPath);
}
// 创建进程
Process process = new Process();
//调用的exe的名称
process.StartInfo.FileName = executPath;
//传递进exe的参数
process.StartInfo.Arguments = idToken;
process.StartInfo.UseShellExecute = false;
//不显示exe的界面
process.StartInfo.CreateNoWindow = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardInput = true;
process.Start();
process.StandardInput.AutoFlush = true;
//阻塞等待调用结束
process.WaitForExit();
//使用Writer输出http响应代码,UTF8格式
using (StreamWriter writer = new StreamWriter(ctx.Response.OutputStream, Encoding.UTF8))
{
writer.Write("处理结果,数据是userId={0},executPath={1}", idToken, executPath);
writer.Close();
ctx.Response.Close();
}
}
catch (Exception ex) {
//使用Writer输出http响应代码,UTF8格式
using (StreamWriter writer = new StreamWriter(ctx.Response.OutputStream, Encoding.UTF8))
{
writer.Write("异常信息:{0}", ex.Message);
writer.Close();
ctx.Response.Close();
}
}
}
}
}
3、利用setup插件打包exe就不在介绍了,很简单
4、测试
启动winform主程序,并使用postman进行测试,WebToWinForm.exe是我自己写的demo例子。