将B/S程序打包成exe,C#对外提供http接口,CefSharp 修改浏览器默认白色背景

简介

公司有个项目,需要将我们https的B/S程序集成到的http的B/S程序中,还要保持本身功能完整,由于https程序中需要调用电脑的麦克风和摄像头,这就难受了。最后商量决定将https程序制作成exe,之后http程序打开exe程序。讨论用一下几种方式:
1、chrome制作一个快捷方式
2、electron
3、C#

chrome

修改chrome的属性(如下图),在目标后添加如下内容

 --window-workspace=1000 --window-size=500,500 --window-position=200,200 --ignore-certificate-errors --draw-view-bounds-rects

在这里插入图片描述
按照如上设置后,会有如下问题不满足项目需求,舍弃
a、如果谷歌浏览器的窗口已经打开,则在打开新的链接时,会加入到原来的浏览器窗口中
b、未找到可以去除浏览器的外边框的参数配置

electron

查看官方文档,其中说到有三种方式( 和, 和 BrowserViews)可以集成web内容。根据文档写了和一个demo,结果未打包成功,本人是一个后端开发,也不想深入研究,最后也就舍弃了。

C#

同事之前在其他项目中有使用过C#中嵌入浏览器的插件,通过其打开对应的网址,直接漂过来使用使用使用。
由于https是不安全,还有需要调用电脑的摄像头和麦克风需要添加如下内容

setting.CefCommandLineArgs.Add("enable-media-stream", "1");  //开启摄像头
setting.CefCommandLineArgs.Add("enable-speech-input", "1");  //语音输入
setting.CefCommandLineArgs.Add("--ignore-certificate-errors", "0");
setting.CefCommandLineArgs.Add("--disable-infobars", "0");
setting.CefCommandLineArgs.Add("--unsafely-treat-insecure-origin-as-secure", "https://192.168.1.2:8086,https://192.168.1.2:9443");

经以上修改后,测试网站功能正常。

WCF

后又提出需要在http程序中控制程序的显示、隐藏、关闭,又使用到了WCF,这个可以使C#程序对外提供http请求。
网上有一大堆的关于如果打开exe程序的文档,这里不做描述

引入WCF

打开Visual Studio Installer,点击修改–>选择单个组件,搜索WCF选中,之后重新打开VS
在这里插入图片描述在这里插入图片描述
项目中添加WCF服务,项目上添加–>新加项–>搜索WCF,点击添加,之后就会发现项目中出现了两个文件IService1.cs和Service1.cs,其中就可开发对外提供的接口
在这里插入图片描述IService1.cs内容

[ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [WebInvoke(UriTemplate = "/closeDb/{param}", Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json)]
        string closeDb(String param);

        [OperationContract]
        [WebInvoke(UriTemplate = "/wcfTest/{param}", Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json)]
        string wcfTest(String param);

        [OperationContract]
        [WebInvoke(UriTemplate = "/showOrHide/{param}", Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json)]
        string showOrHide(String param);
    }

Service.cs内容

class MyWcfService : IService1
    {
        public string closeDb(String param)
        {
            LogUtil.WriteLog("准备关闭窗口:"+param);
            if ("1".Equals(param)) {
                //Program.mainForm.Dispose(); //这种方式会报错
                System.Environment.Exit(0);
            }
            return "OK";
        }


        public string wcfTest(string param)
        {
            LogUtil.WriteLog("wcf Test:" + param);
            return param;
        }


        public string showOrHide(string param)
        {
            LogUtil.WriteLog("showOrHide:" + param);
            if (Program.mainForm!=null) {
                if ("SHOW".Equals(param))
                {
                    Program.mainForm.Show();
                    Program.mainForm.TopMost = true;
                    return "OK";
                }
                else if ("HIDE".Equals(param))
                {
                    Program.mainForm.Hide();
                    return "OK";
                }
                else {
                    return "参数不对";
                }
            }
            
            return "系统异常,请联系管理员";
        }
    }

需要在main函数添加如下内容,这是后提供出的接口为"http://localhost:9000/XXX

WebServiceHost host = new WebServiceHost(typeof(MyWcfService), new Uri("http://localhost:9000/"));
               
               try
               {
                   ServiceEndpoint ep = host.AddServiceEndpoint(typeof(IService1), new WebHttpBinding(), "");
                   ServiceDebugBehavior sdb = host.Description.Behaviors.Find<ServiceDebugBehavior>();
                   sdb.HttpHelpPageEnabled = false;
				//该内容为了解决跨域问题,会创建一个拦截器
                foreach (ServiceEndpoint EP in host.Description.Endpoints) {
                    EP.Behaviors.Add(new BehaviorAttribute());
                }

                host.Open();
                   //host.Close();
                   LogUtil.WriteLog("启动WCF成功");
               }
               catch (CommunicationException cex)
               {
                   LogUtil.WriteLog("启动WCF失败",cex.Message);
                   Console.WriteLine("An exception occurred: {0}", cex.Message);
                   host.Abort();
               }

拦截器内容

public class MessageInspector : IDispatchMessageInspector
    {
        private ServiceEndpoint _serviceEndpoint;
        public MessageInspector(ServiceEndpoint serviceEndpoint)
        {
            _serviceEndpoint = serviceEndpoint;
        }
        /// <summary>
        /// Called when an inbound message been received
        /// </summary>
        /// <param name="request">The request message.</param>
        /// <param name="channel">The incoming channel.</param>
        /// <param name="instanceContext">The current service instance.</param>
        /// <returns>
        /// The object used to correlate stateMsg. 
        /// This object is passed back in the method.
        /// </returns>
        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            StateMessage stateMsg = null;
            HttpRequestMessageProperty requestProperty = null;
            if (request.Properties.ContainsKey(HttpRequestMessageProperty.Name))
            {
                requestProperty = request.Properties[HttpRequestMessageProperty.Name]
                                  as HttpRequestMessageProperty;
            }
            if (requestProperty != null)
            {
                var origin = requestProperty.Headers["Origin"];
                if (!string.IsNullOrEmpty(origin))
                {
                    stateMsg = new StateMessage();
                    // if a cors options request (preflight) is detected, 
                    // we create our own reply message and don't invoke any 
                    // operation at all.
                    if (requestProperty.Method == "OPTIONS")
                    {
                        stateMsg.Message = Message.CreateMessage(request.Version, null);
                    }
                    request.Properties.Add("CrossOriginResourceSharingState", stateMsg);
                }
            }
            return stateMsg;
        }
        /// <summary>
        /// Called after the operation has returned but before the reply message
        /// is sent.
        /// </summary>
        /// <param name="reply">The reply message. This value is null if the 
        /// operation is one way.</param>
        /// <param name="correlationState">The correlation object returned from
        ///  the method.</param>
        public void BeforeSendReply(ref Message reply, object correlationState)
        {
            var stateMsg = correlationState as StateMessage;
            if (stateMsg != null)
            {
                if (stateMsg.Message != null)
                {
                    reply = stateMsg.Message;
                }
                HttpResponseMessageProperty responseProperty = null;
                if (reply.Properties.ContainsKey(HttpResponseMessageProperty.Name))
                {
                    responseProperty = reply.Properties[HttpResponseMessageProperty.Name]
                                       as HttpResponseMessageProperty;
                }
                if (responseProperty == null)
                {
                    responseProperty = new HttpResponseMessageProperty();
                    reply.Properties.Add(HttpResponseMessageProperty.Name,
                                         responseProperty);
                }
                // Access-Control-Allow-Origin should be added for all cors responses
                responseProperty.Headers.Set("Access-Control-Allow-Origin", "*");
                if (stateMsg.Message != null)
                {
                    // the following headers should only be added for OPTIONS requests
                    responseProperty.Headers.Set("Access-Control-Allow-Methods",
                                                 "POST, OPTIONS, GET");
                    responseProperty.Headers.Set("Content-Type", "application/json");
                    responseProperty.Headers.Set("Access-Control-Allow-Headers",
                              "Content-Type, Accept, Authorization, x-requested-with");
                }
            }
        }
    }
    class StateMessage
    {
        public Message Message;
    }
    public class BehaviorAttribute : Attribute, IEndpointBehavior, IOperationBehavior
    {
        public void Validate(ServiceEndpoint endpoint) { }
        public void AddBindingParameters(ServiceEndpoint endpoint,
                                 BindingParameterCollection bindingParameters)
        { }
        /// <summary>
        /// This service modify or extend the service across an endpoint.
        /// </summary>
        /// <param name="endpoint">The endpoint that exposes the contract.</param>
        /// <param name="endpointDispatcher">The endpoint dispatcher to be
        /// modified or extended.</param>
        public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
                                          EndpointDispatcher endpointDispatcher)
        {
            // add inspector which detects cross origin requests
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(
                                                   new MessageInspector(endpoint));
        }
        public void ApplyClientBehavior(ServiceEndpoint endpoint,
                                        ClientRuntime clientRuntime)
        { }
        public void Validate(OperationDescription operationDescription) { }
        public void ApplyDispatchBehavior(OperationDescription operationDescription,
                                          DispatchOperation dispatchOperation)
        { }
        public void ApplyClientBehavior(OperationDescription operationDescription,
                                        ClientOperation clientOperation)
        { }
        public void AddBindingParameters(OperationDescription operationDescription,
                                  BindingParameterCollection bindingParameters)
        { }
    }

做完以上内容,只需要启动程序即可。

使用WCF注意事项

服务必须要以管理员去启动,不然无法启动WCF

C#打包

参考文章:C#程序打包
按照文章中配置.net框架时,做了如下尝试,都没有成功,欢迎大家有更好的方法
1、配置程序包中的文件
2、配置一个网络地址(内网的一个nginx地址)

C# CefSharp 修改浏览器默认白色背景

CefSettings setting = new CefSettings();
// 配置背景颜色
setting.BackgroundColor = ColorToUInt(System.Drawing.Color.FromArgb(255, 15, 23, 59));

public static uint ColorToUInt(Color color){
    return (uint)((color.A << 24) | (color.R << 16) | (color.G << 8) | (color.B << 0));
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值