说明:在同一窗口打开链接,只要稍加改造就可以实现,这里实现的是在新Tab页打开链接,并且支持带type="POST" target="_blank"的链接

github和bitbucket上相关问题:

1、WPF empty POST data when using custom popup    https://github.com/cefsharp/CefSharp/issues/1267

2、CefLifeSpanHandler, customized OnBeforePopup problem    https://bitbucket.org/chromiumembedded/cef/issues/1949/

解决(CefSharp版本75.1.143.0):

一、实现IRequestHandler接口

using CefSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography.X509Certificates; namespace CefSharpDemo
{
public class RequestHandler : IRequestHandler
{
private ExtChromiumBrowser _browser; public RequestHandler(ExtChromiumBrowser browser)
{
_browser = browser;
} public bool GetAuthCredentials(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
{
return false;
} public IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
{
if (request.Method.ToUpper() == "POST" && request.PostData != null)
{
if (request.PostData.Elements.Count > )
{
_browser.PostData = new byte[request.PostData.Elements[].Bytes.Length];
request.PostData.Elements[].Bytes.CopyTo(_browser.PostData, );
}
}
return null;
} public bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect)
{
return false;
} public bool OnCertificateError(IWebBrowser chromiumWebBrowser, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback)
{
return false;
} public bool OnOpenUrlFromTab(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture)
{
return false;
} public void OnPluginCrashed(IWebBrowser chromiumWebBrowser, IBrowser browser, string pluginPath)
{ } public bool OnQuotaRequest(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, long newSize, IRequestCallback callback)
{
return false;
} public void OnRenderProcessTerminated(IWebBrowser chromiumWebBrowser, IBrowser browser, CefTerminationStatus status)
{ } public void OnRenderViewReady(IWebBrowser chromiumWebBrowser, IBrowser browser)
{ } public bool OnSelectClientCertificate(IWebBrowser chromiumWebBrowser, IBrowser browser, bool isProxy, string host, int port, X509Certificate2Collection certificates, ISelectClientCertificateCallback callback)
{
return false;
}
}
}

二、实现ILifeSpanHandler接口

using CefSharp;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;
using Utils; namespace CefSharpDemo
{
public class CefLifeSpanHandler : CefSharp.ILifeSpanHandler
{
private static LimitedTaskScheduler _scheduler = new LimitedTaskScheduler(); public CefLifeSpanHandler()
{ } public bool DoClose(IWebBrowser browserControl, CefSharp.IBrowser browser)
{
if (browser.IsDisposed || browser.IsPopup)
{
return false;
} return true;
} public void OnAfterCreated(IWebBrowser browserControl, IBrowser browser)
{ } public void OnBeforeClose(IWebBrowser browserControl, IBrowser browser)
{
} public bool OnBeforePopup(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser)
{
var chromiumWebBrowser = (ExtChromiumBrowser)browserControl; chromiumWebBrowser.Dispatcher.Invoke(new Action(() =>
{
BrowserPopupWin win = new BrowserPopupWin();
win.ShowInTaskbar = false;
win.Height = ;
win.Width = ;
win.Show(); IntPtr handle = new WindowInteropHelper(win).Handle;
windowInfo.SetAsChild(handle); _scheduler.Run(() =>
{
WaitUtil.Wait(() => chromiumWebBrowser.PostData); IRequest request = null;
if (chromiumWebBrowser.PostData != null)
{
request = frame.CreateRequest();
request.Url = targetUrl;
request.Method = "POST"; request.InitializePostData();
var element = request.PostData.CreatePostDataElement();
element.Bytes = chromiumWebBrowser.PostData;
request.PostData.AddElement(element);
chromiumWebBrowser.PostData = null;
} chromiumWebBrowser.Dispatcher.Invoke(new Action(() =>
{
NewWindowEventArgs e = new NewWindowEventArgs(targetUrl, request);
chromiumWebBrowser.OnNewWindow(e);
})); chromiumWebBrowser.Dispatcher.Invoke(new Action(() =>
{
win.Close();
}));
});
})); newBrowser = null;
return false;
} }
}

三、扩展ChromiumWebBrowser

using CefSharp.Wpf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace CefSharpDemo
{
public class ExtChromiumBrowser : ChromiumWebBrowser
{
public byte[] PostData { get; set; } public ExtChromiumBrowser()
: base()
{
this.LifeSpanHandler = new CefLifeSpanHandler();
this.DownloadHandler = new DownloadHandler(this);
this.MenuHandler = new MenuHandler();
this.KeyboardHandler = new KeyboardHandler();
this.RequestHandler = new RequestHandler(this);
} public event EventHandler<NewWindowEventArgs> StartNewWindow; public void OnNewWindow(NewWindowEventArgs e)
{
if (StartNewWindow != null)
{
StartNewWindow(this, e);
}
} public void ClearHandlers()
{
//如果不清理Handler,会导致子进程CefSharp.BrowserSubprocess.exe无法释放
this.LifeSpanHandler = null;
this.DownloadHandler = null;
this.MenuHandler = null;
this.KeyboardHandler = null;
}
}
}

四、封装ExtChromiumBrowser(BrowserCtrl控件)

using CefSharp;
using CefSharp.Wpf;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Utils; namespace CefSharpDemo
{
/// <summary>
/// 浏览器用户控件
/// </summary>
public partial class BrowserCtrl : UserControl, IDisposable
{
#region 外部方法
/*
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
[DllImport("user32.dll", SetLastError = true)]
public static extern int MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool BRePaint);
[DllImport("user32.dll", SetLastError = true)]
public static extern int CloseWindow(IntPtr hWnd);
[DllImport("User32.dll", EntryPoint = "GetWindowText")]
private static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int nMaxCount);
*/
#endregion #region 变量属性事件
private static bool _isCefInited = false; private static object _lockObject = new object(); private JSObject _jsObject; private bool _firstLoad = true; /// <summary>
/// 在此事件中设置URL(此事件已在线程中执行,此事件已对错误情况进行处理)
/// </summary>
public event EventHandler SetUrlEvent; /// <summary>
/// URL
/// </summary>
public string Url { get; set; } public IRequest Request { get; set; } /// <summary>
/// 浏览器FrameLoadEnd事件
/// </summary>
public event EventHandler FrameLoadEnd; private ExtChromiumBrowser _browser; public ExtChromiumBrowser Browser
{
get
{
WaitUtil.Wait(() => this._browser != null && this._browser.IsInitialized && _isCefInited); return this._browser;
}
} private static LimitedTaskScheduler _scheduler = new LimitedTaskScheduler();
#endregion #region 构造函数
public BrowserCtrl()
{
InitializeComponent();
if (DesignerProperties.GetIsInDesignMode(this)) return; this.Loaded += BrowserCtrl_Loaded; lock (_lockObject)
{
if (!_isCefInited)
{
_isCefInited = true;
InitCef();//初始化CefSharp
}
} _browser = new ExtChromiumBrowser();
BindBrowser(_browser);
grid.Children.Add(_browser);
}
#endregion #region BrowserCtrl_Loaded
private void BrowserCtrl_Loaded(object sender, RoutedEventArgs e)
{ }
#endregion #region SetMapCtrl
/// <summary>
/// 设置Map控件接口,用于C#和JS互操作
/// </summary>
public void SetMapCtrl(IMapCtrl mapCtrl)
{
_jsObject.MapCtrl = mapCtrl;
}
#endregion #region Dispose 释放资源
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
//如果有弹出窗口则先释放它
//foreach (UIElement item in grid.Children)
//{
// if (item is BrowserContainer)
// {
// (item as BrowserContainer).ClearResource();
// }
//} _browser.ClearHandlers();
if (_browser != null && !_browser.IsDisposed)
{
_browser.Dispose();
}
}
#endregion #region Load
public void Load(string url)
{
if (!string.IsNullOrWhiteSpace(url))
{
loadingWait.Visibility = Visibility.Visible;
Url = url;
_scheduler.Run(() =>
{
#region Wait
WaitUtil.Wait(() =>
{
if (this._browser == null) return false;
if (!this._browser.IsInitialized) return false;
if (!_isCefInited) return false;
bool isBrowserInitialized = false;
this.Dispatcher.Invoke(() =>
{
isBrowserInitialized = this._browser.IsBrowserInitialized;
});
if (!isBrowserInitialized) return false;
return true;
});
#endregion _browser.Load(Url);
});
}
}
#endregion #region LoadUrl
private void LoadUrl()
{
if (_firstLoad)
{
_firstLoad = false; _scheduler.Run(() =>
{
#region Wait
WaitUtil.Wait(() =>
{
if (this._browser == null) return false;
if (!this._browser.IsInitialized) return false;
if (!_isCefInited) return false;
bool isBrowserInitialized = false;
this.Dispatcher.Invoke(() =>
{
isBrowserInitialized = this._browser.IsBrowserInitialized;
});
if (!isBrowserInitialized) return false;
return true;
});
#endregion if (Url == null && SetUrlEvent != null)
{
try
{
SetUrlEvent(this, null);
}
catch (Exception ex)
{
LogUtil.Error(ex, "BrowserCtrl LoadUrl error 获取URL失败");
}
}
else
{
this.Dispatcher.Invoke(new Action(() =>
{
loadingWait.Visibility = Visibility.Collapsed;
}));
} if (Url != null)
{
try
{
if (Request == null)
{
_browser.Load(Url);
}
else
{
_browser.Load(Url);
_browser.GetMainFrame().LoadRequest(Request);
Request = null;
}
}
catch (Exception ex)
{
LogUtil.Error(ex, "BrowserCtrl LoadUrl error Load URL失败");
}
}
else
{
this.Dispatcher.Invoke(new Action(() =>
{
loadingWait.Visibility = Visibility.Collapsed;
}));
}
});
}
}
#endregion #region BindBrowser
private void BindBrowser(ExtChromiumBrowser browser)
{
_jsObject = new JSObject();
browser.RegisterJsObject("jsObj", _jsObject, new CefSharp.BindingOptions { CamelCaseJavascriptNames = false }); browser.IsBrowserInitializedChanged += (ss, ee) =>
{
LoadUrl();
};
browser.FrameLoadStart += (ss, ee) =>
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
(ss as ExtChromiumBrowser).Focus();
}));
};
browser.FrameLoadEnd += (ss, ee) =>
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
loadingWait.Visibility = Visibility.Collapsed;
}));
if (FrameLoadEnd != null)
{
FrameLoadEnd(null, null);
}
};
browser.KeyDown += (ss, ee) =>
{
if (ee.Key == Key.F5)
{
try
{
browser.Reload();
}
catch (Exception ex)
{
LogUtil.Error(ex, "ExtChromiumBrowser Reload error");
}
}
};
browser.PreviewTextInput += (o, e) =>
{
foreach (var character in e.Text)
{
// 把每个字符向浏览器组件发送一遍
browser.GetBrowser().GetHost().SendKeyEvent((int)WM.CHAR, (int)character, );
} // 不让cef自己处理
e.Handled = true;
};
browser.LoadError += (s, e) =>
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
loadingWait.Visibility = Visibility.Collapsed;
}));
};
}
#endregion #region RegisterJsObject
public void RegisterJsObject(string name, object objectToBind, BindingOptions options = null)
{
try
{
if (_browser != null)
{
_browser.RegisterJsObject(name, objectToBind, options);
}
}
catch (Exception ex)
{
LogUtil.Error(ex, "BrowserCtrl RegisterJsObject 错误");
}
}
#endregion #region 初始化CefSharp
public static void InitCef()
{
string cefsharpFolder = "CefSharp"; var settings = new CefSettings();
//The location where cache data will be stored on disk. If empty an in-memory cache will be used for some features and a temporary disk cache for others.
//HTML5 databases such as localStorage will only persist across sessions if a cache path is specified.
settings.CachePath = cefsharpFolder + "/cache"; //设置cache目录 settings.MultiThreadedMessageLoop = true;
CefSharpSettings.FocusedNodeChangedEnabled = true;
CefSharpSettings.LegacyJavascriptBindingEnabled = true;
CefSharpSettings.ShutdownOnExit = true;
CefSharpSettings.SubprocessExitIfParentProcessClosed = true; string logDir = AppDomain.CurrentDomain.BaseDirectory + cefsharpFolder + "/log/";
if (!Directory.Exists(logDir))
{
Directory.CreateDirectory(logDir);
} settings.BrowserSubprocessPath = AppDomain.CurrentDomain.BaseDirectory + cefsharpFolder + "/CefSharp.BrowserSubprocess.exe";
settings.LogFile = logDir + DateTime.Now.ToString("yyyyMMdd") + ".log";
settings.LocalesDirPath = AppDomain.CurrentDomain.BaseDirectory + cefsharpFolder + "/locales";
settings.CefCommandLineArgs.Add("disable-gpu", "");
settings.CefCommandLineArgs.Add("enable-media-stream", ""); if (!Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: new BrowserProcessHandler()))
{
throw new Exception("Unable to Initialize Cef");
}
}
#endregion }
}

五、MainWindow测试代码

using CefSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Utils; namespace CefSharpDemo
{
/// <summary>
/// CefSharp Demo 窗体
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); tabControl.AddTabItemEvent += tabControl_AddTabItemEvent;
Application.Current.MainWindow = this;
} private void tabControl_AddTabItemEvent(object sender, EventArgs e)
{
//CreateTabItem("https://www.cnblogs.com/");
CreateTabItem("file:///D:/_程序/CefSharpDemo/post.html");
} /// <summary>
/// 新增Tab页
/// </summary>
private void CreateTabItem(string url = null, IRequest request = null)
{
TabItem tabItem = new TabItem();
tabItem.Header = "新标签页";
BrowserDemoCtrl ctrl = new BrowserDemoCtrl();
ctrl.browserCtrl.Browser.StartNewWindow += (s, e) =>
{
CreateTabItem(e.TargetUrl, e.Request);
};
ctrl.browserCtrl.SetUrlEvent += (s, e) =>
{
ctrl.browserCtrl.Url = url;
ctrl.browserCtrl.Request = request;
};
tabItem.Content = ctrl;
tabControl.Items.Add(tabItem);
tabControl.SelectedItem = tabItem;
ScrollViewer scrollViewer = tabControl.Template.FindName("scrollViewer", tabControl) as ScrollViewer;
scrollViewer.ScrollToRightEnd();
} private void Window_Closed(object sender, EventArgs e)
{
tabControl.CloseAllTabItem(); //关闭窗体清理资源 //程序退出时删除cache
CefSharp.Cef.Shutdown();
string cachePath = AppDomain.CurrentDomain.BaseDirectory + "CefSharp\\cache";
if (Directory.Exists(cachePath))
{
foreach (string path in Directory.GetDirectories(cachePath))
{
Directory.Delete(path, true);
}
foreach (string file in Directory.GetFiles(cachePath))
{
if (!file.ToLower().Contains("cookies"))
{
File.Delete(file);
}
}
}
}
}
}

 六、测试html代码post.html

<!DOCTYPE html>
<html>
<head>
<title>CefSharpDemo</title> <meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <style type="text/css">
</style> <script type="text/javascript">
</script>
</head>
<body>
<!--enctype="multipart/form-data"-->
<form method="post" action="http://localhost:1209/netcms/" target="_blank">
<span>name:</span><input type="text" name="name" value="测试名称" />
<span>code:</span><input type="text" name="code" value="测试编码" /> <button type="submit">Post提交</button>
</form>
</body>
</html>

七、测试后台代码

public ActionResult index()
{
string name = Request.Params["name"];
string code = Request.Params["code"]; ViewBag.name = name;
ViewBag.code = code; return View();
}

八、测试前台cshtml代码

@using Models;
@{
Layout = "~/Views/Shared/_SiteLayout.cshtml";
} <div style="font-size:50px; height:1200px;">
<span>name:</span><span>@ViewBag.name</span><br /><span>code:</span><span>@ViewBag.code</span>
</div>

九:关键代码段:

1、RequestHandler类中获取并保存PostData

public IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
{
if (request.Method.ToUpper() == "POST" && request.PostData != null)
{
if (request.PostData.Elements.Count > )
{
_browser.PostData = new byte[request.PostData.Elements[].Bytes.Length];
request.PostData.Elements[].Bytes.CopyTo(_browser.PostData, );
}
}
return null;
}

 2、CefLifeSpanHandler类中创建IRequest

public bool OnBeforePopup(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser)
{
var chromiumWebBrowser = (ExtChromiumBrowser)browserControl; chromiumWebBrowser.Dispatcher.Invoke(new Action(() =>
{
BrowserPopupWin win = new BrowserPopupWin();
win.ShowInTaskbar = false;
win.Height = ;
win.Width = ;
win.Show(); IntPtr handle = new WindowInteropHelper(win).Handle;
windowInfo.SetAsChild(handle); _scheduler.Run(() =>
{
WaitUtil.Wait(() => chromiumWebBrowser.PostData); IRequest request = null;
if (chromiumWebBrowser.PostData != null)
{
request = frame.CreateRequest();
request.Url = targetUrl;
request.Method = "POST"; request.InitializePostData();
var element = request.PostData.CreatePostDataElement();
element.Bytes = chromiumWebBrowser.PostData;
request.PostData.AddElement(element);
chromiumWebBrowser.PostData = null;
} chromiumWebBrowser.Dispatcher.Invoke(new Action(() =>
{
NewWindowEventArgs e = new NewWindowEventArgs(targetUrl, request);
chromiumWebBrowser.OnNewWindow(e);
})); chromiumWebBrowser.Dispatcher.Invoke(new Action(() =>
{
win.Close();
}));
});
})); newBrowser = null;
return false;
}

说明:OnBeforePopup方法要return false,用BrowserPopupWin和windowInfo.SetAsChild方法弹出一个不可见的窗体,这样才能拿到PostData

3、在BrowserCtrl控件中用LoadRequest方法打开新的URL,并把post数据带过去

if (Request == null)
{
_browser.Load(Url);
}
else
{
_browser.Load(Url);
_browser.GetMainFrame().LoadRequest(Request);
Request = null;
}

 

十、效果图:

完整代码下载:https://files-cdn.cnblogs.com/files/s0611163/CefSharpDemo.zip

源码说明:为了减少源码压缩包的大小,代码中没有依赖的CefSharp文件,请自己下载(使用x86版本),用于测试的网页后台代码也没有,请自己制作测试后台

CefSharp禁止弹出新窗体,在同一窗口打开链接,或者在新Tab页打开链接,并且支持带type="POST" target="_blank"的链接的更多相关文章

  1. CefSharp.v49.0.1浏览器控件完全WPF版,实现禁止弹出新窗口,在同一窗口打开链接,并且支持带type="POST" target="_blank"的链接

    需求场景:在查询页面,填写查询条件,查询条件包括上传的图片,根据图片的特征查询,这就需要在提交的时候,使用POST提交,因为GET提交无法提交图片数据,提交查询条件之后,在新的窗口展示查询结果.(当然 ...

  2. CefSharp禁止弹出新窗体,在同一窗口打开链接,并且支持带type="POST" target="_blank"的链接

    1.实现ILifeSpanHandler接口,代码如下: using CefSharp; using CefSharp.WinForms; using System; using System.Col ...

  3. WebBrowser控件应用:弹出新窗体和关闭窗口

    缘起:上次写了一个<WebBrowser控件的简单应用2>,提到了在NewWindow事件中打开新窗口的例子.有网友“队长 ”提出那个事件得到的参数是本页面的,而不是新页面的,经过测试,果 ...

  4. WPF Prism MVVM 中 弹出新窗体. 放入用户控件

    原文:WPF Prism MVVM 中 弹出新窗体. 放入用户控件 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_37214567/artic ...

  5. jQuery UI弹出新窗体

    借助jqueryUI 的Dialog 在隐藏的div中嵌入Iframe  改变iframe的路径 如果项目经常用到弹出新窗体,则利用模板,把此代码和html 放入父页面中,实现父级调用, <in ...

  6. FineReport——弹出新窗体选值并回调

    主要实现的功能: 在主页面,通过单击按钮,弹出窗体,在窗体中通过下拉框选择值并查询,如果是多值,可以通过复选框选择,点击确定,将选中的行的字段值传递给主页面的下拉复选框,定义其编辑后事件进行查询.将想 ...

  7. Jquery 弹出新窗体

    开始先用css将这个DIV设好位置,并且隐藏 function winshow() { var winNode = $(".win"); winNode.show("sl ...

  8. 小技巧之Selenium如何切换到弹出的Tab页中

    今天群里讨论了一个问题,如何将selenium的操作焦点切换到浏览器中新弹出来的Tab页中,正好对应到了昨天的那篇文章“小技巧之在浏览器中打开新的页签”.今天就带大家来解决这个问题: 先封装一个Tab ...

  9. 使“Cmder Here”菜单在Tab页开新窗口

    Cmder是一个非常好用的的控制台命令行,我们在实际使用的时候,经常通过如下指令将其注册到右键菜单: Cmder.exe /REGISTER ALL 这样就可以在任意文件夹下快速打开Cmder,并且能 ...

随机推荐

  1. K8s 集群节点在线率达到 99.9% 以上,扩容效率提升 50%,我们做了这 3 个深度改造

    点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 本文节选自<不一样的 双11 技术:阿里巴巴经济体云原生实践>一书,点击上方图片即可下载! 作者 | 张振(守辰) ...

  2. SQL SERVER中SELECT和SET赋值相同点与不同点

    SELECT和SET在SQL SERVER中都可以用来对变量进行赋值,但其用法和效果在一些细节上有些不同. 1. 在对变量赋值方面,SET是ANSI标准的赋值方式,SELECT则不是.这也是SET方式 ...

  3. HT Vue 集成

    (本文中 dataModel = dm = 数据容器, gv = graphView = g2d = 2D 视图) 初始化项目 使用 vue-cli 生成项目.生成注意以下几个问题 1. 建议手动配置 ...

  4. linux下的du和df的区别

    du(disk usage)是通过搜索文件来计算每个文件的大小然后累加,du能看到的文件只是一些当前存在的,没有被删除的.他计算的大小就是当前他认为存在的所有文件大小的累加和. df(disk fre ...

  5. JNI教程与技术手册

    转载请标明出处:http://blog.csdn.net/shensky711/article/details/52806794 本文出自: [HansChen的博客] 概述 对于JNI,有些童鞋在没 ...

  6. Django中间件部分源码分析

    中间件源码分析 中间件简介 中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量.低级别的插件系统,用于在全局范围内改变Django的输入和输出.每个中间件组件都负责做一些特定的 ...

  7. 行内元素(inline标签)设置了行高为什么不生效,还是表现为父盒子的行高?行内元素行高问题终极解释

    最近在看张鑫旭大佬的<css世界>,读到5.2.4  内联元素 line-height 的“大值特性” ,产生了疑惑, 在开发中确实也遇到了同样的问题,深入探究后得出结果,先说结论吧,论证 ...

  8. Linux下利用nginx实现负载均衡

    linux下利用nginx实现负载均衡 前提条件: 1,安装好jdk 2,安装好tomcat和nginx(可以参考我前两篇文章) 满足前提条件后,要用nginx实现负载均衡,主要是靠配置nginx的配 ...

  9. javaWeb学习总结——文件上传、下载

    目录 1.文件上传环境搭建 2.文件上传代码实现 3.关于下载 @ 嘿,熊dei,你不得不知道在Web开发中,文件上传和下载功能是非常常用的功能,关于文件上传,浏览器上传[文件以流的形式传输]--&g ...

  10. 用launchscreen.storyboard适配启动图方法(二)

    背景 之前有写一篇实现方式比较简单的随笔用launchscreen.storyboard适配启动图方法,顺便在评论区提了一下用autolayout适配启动图的思路,现把思路和流程记录下来. 思路 整体 ...