diff --git a/CefSharp.BrowserSubprocess.Core/BrowserSubprocessExecutable.h b/CefSharp.BrowserSubprocess.Core/BrowserSubprocessExecutable.h index 874184c9c4..476a119306 100644 --- a/CefSharp.BrowserSubprocess.Core/BrowserSubprocessExecutable.h +++ b/CefSharp.BrowserSubprocess.Core/BrowserSubprocessExecutable.h @@ -28,6 +28,25 @@ namespace CefSharp } + /// + /// This function should be called from the application entry point function (typically Program.Main) + /// to execute a secondary process e.g. gpu, plugin, renderer, utility + /// This overload is specifically used for .Net Core. For hosting your own BrowserSubProcess + /// it's preferable to use the Main method provided by this class. + /// - Obtains the command line args via a call to Environment::GetCommandLineArgs + /// - Calls CefEnableHighDPISupport before any other processing + /// + /// + /// If called for the browser process (identified by no "type" command-line value) it will return immediately + /// with a value of -1. If called for a recognized secondary process it will block until the process should exit + /// and then return the process exit code. + /// ^ args) + { + auto subProcess = gcnew BrowserSubprocessExecutable(); + return subProcess->Main(args, nullptr); + } + /// /// This function should be called from the application entry point function (typically Program.Main) /// to execute a secondary process e.g. gpu, plugin, renderer, utility diff --git a/CefSharp.Core.RefAssembly/CefSharp.Core.cs b/CefSharp.Core.RefAssembly/CefSharp.Core.cs index 329adc21b7..c96a5234d6 100644 --- a/CefSharp.Core.RefAssembly/CefSharp.Core.cs +++ b/CefSharp.Core.RefAssembly/CefSharp.Core.cs @@ -152,7 +152,7 @@ public partial class ManagedCefBrowserAdapter : CefSharp.Internals.IBrowserAdapt public ManagedCefBrowserAdapter(CefSharp.Internals.IWebBrowserInternal webBrowserInternal, bool offScreenRendering) { } public virtual bool IsDisposed { get { throw null; } } public virtual CefSharp.Internals.IJavascriptCallbackFactory JavascriptCallbackFactory { get { throw null; } } - public virtual CefSharp.Internals.JavascriptObjectRepository JavascriptObjectRepository { get { throw null; } } + public virtual CefSharp.Internals.IJavascriptObjectRepositoryInternal JavascriptObjectRepository { get { throw null; } } public virtual CefSharp.Internals.IMethodRunnerQueue MethodRunnerQueue { get { throw null; } } public void CreateBrowser(CefSharp.IWindowInfo windowInfo, CefSharp.BrowserSettings browserSettings, CefSharp.RequestContext requestContext, string address) { } public void Dispose() { } @@ -329,6 +329,14 @@ public virtual void SetAsPopup(System.IntPtr parentHandle, string windowName) { public virtual void SetAsWindowless(System.IntPtr parentHandle) { } } } +namespace CefSharp.BrowserSubprocess +{ + public partial class SelfHost + { + public SelfHost() { } + public static int Main(string[] args) { throw null; } + } +} namespace CefSharp.Internals { public partial class CefDragDataWrapper : CefSharp.Internals.CefWrapper, CefSharp.IDragData diff --git a/CefSharp.Core/BrowserSubprocess/SelfHost.cpp b/CefSharp.Core/BrowserSubprocess/SelfHost.cpp new file mode 100644 index 0000000000..b5a79cbc1e --- /dev/null +++ b/CefSharp.Core/BrowserSubprocess/SelfHost.cpp @@ -0,0 +1,49 @@ +// Copyright © 2020 The CefSharp Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +#include "Stdafx.h" +#include "SelfHost.h" + +using namespace System; +using namespace System::IO; +using namespace CefSharp; + +namespace CefSharp +{ + namespace BrowserSubprocess + { + int SelfHost::Main(array^ args) + { + auto type = CommandLineArgsParser::GetArgumentValue(args, CefSharpArguments::SubProcessTypeArgument); + + if (String::IsNullOrEmpty(type)) + { + //If --type param missing from command line CEF/Chromium assums + //this is the main process (as all subprocesses must have a type param). + //Return -1 to indicate this behaviour. + return -1; + } + + auto browserSubprocessDllPath = Path::Combine(Path::GetDirectoryName(SelfHost::typeid->Assembly->Location), "CefSharp.BrowserSubprocess.Core.dll"); +#ifdef NETCOREAPP + auto browserSubprocessDll = System::Runtime::Loader::AssemblyLoadContext::Default->LoadFromAssemblyPath(browserSubprocessDllPath); +#else + auto browserSubprocessDll = System::Reflection::Assembly::LoadFrom(browserSubprocessDllPath); +#endif + auto browserSubprocessExecutableType = browserSubprocessDll->GetType("CefSharp.BrowserSubprocess.BrowserSubprocessExecutable"); + auto browserSubprocessExecutable = Activator::CreateInstance(browserSubprocessExecutableType); + + auto mainMethod = browserSubprocessExecutableType->GetMethod("MainSelfHost", System::Reflection::BindingFlags::Static | System::Reflection::BindingFlags::Public); + auto argCount = mainMethod->GetParameters(); + + auto methodArgs = gcnew array(1); + methodArgs[0] = args; + + auto exitCode = mainMethod->Invoke(nullptr, methodArgs); + + return (int)exitCode; + } + + } +} diff --git a/CefSharp.Core/BrowserSubprocess/SelfHost.h b/CefSharp.Core/BrowserSubprocess/SelfHost.h new file mode 100644 index 0000000000..5e98241957 --- /dev/null +++ b/CefSharp.Core/BrowserSubprocess/SelfHost.h @@ -0,0 +1,38 @@ +// Copyright © 2020 The CefSharp Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +#pragma once + +#include "Stdafx.h" + +namespace CefSharp +{ + namespace BrowserSubprocess + { + /// + /// SelfHost can be used to self host the BrowserSubProcess in your + /// existing application (preferred approach for .Net Core). + /// + public ref class SelfHost + { + public: + /// + /// This function should be called from the application entry point function (typically Program.Main) + /// to execute a secondary process e.g. gpu, plugin, renderer, utility + /// This overload is primarily intended to be used for .Net Core. + /// - Pass in command line args + /// - To support High DPI Displays you should call Cef.EnableHighDPISupport before any other processing + /// or add the relevant entries to your app.manifest + /// + /// command line args + /// + /// If called for the browser process (identified by no "type" command-line value) it will return immediately + /// with a value of -1. If called for a recognized secondary process it will block until the process should exit + /// and then return the process exit code. + /// ^ args); + + }; + } +} diff --git a/CefSharp.Core/CefSharp.Core.netcore.vcxproj b/CefSharp.Core/CefSharp.Core.netcore.vcxproj index 7f718bdda7..fa69982ea9 100644 --- a/CefSharp.Core/CefSharp.Core.netcore.vcxproj +++ b/CefSharp.Core/CefSharp.Core.netcore.vcxproj @@ -246,6 +246,7 @@ + Create Create @@ -305,6 +306,7 @@ + diff --git a/CefSharp.Core/CefSharp.Core.netcore.vcxproj.filters b/CefSharp.Core/CefSharp.Core.netcore.vcxproj.filters index 1a9a296275..2c54a04f14 100644 --- a/CefSharp.Core/CefSharp.Core.netcore.vcxproj.filters +++ b/CefSharp.Core/CefSharp.Core.netcore.vcxproj.filters @@ -86,6 +86,9 @@ Source Files + + Source Files + @@ -334,6 +337,9 @@ Header Files + + Header Files + diff --git a/CefSharp.Core/CefSharp.Core.vcxproj b/CefSharp.Core/CefSharp.Core.vcxproj index c082bd95b0..f65e9adc86 100644 --- a/CefSharp.Core/CefSharp.Core.vcxproj +++ b/CefSharp.Core/CefSharp.Core.vcxproj @@ -229,6 +229,7 @@ + @@ -261,6 +262,7 @@ + diff --git a/CefSharp.Core/CefSharp.Core.vcxproj.filters b/CefSharp.Core/CefSharp.Core.vcxproj.filters index c4406bb0aa..5b2ccbc032 100644 --- a/CefSharp.Core/CefSharp.Core.vcxproj.filters +++ b/CefSharp.Core/CefSharp.Core.vcxproj.filters @@ -86,6 +86,9 @@ Source Files + + Source Files + @@ -334,6 +337,9 @@ Header Files + + Header Files + diff --git a/CefSharp.WinForms.Example/Program.cs b/CefSharp.WinForms.Example/Program.cs index 209cd82b06..0c5fc8e133 100644 --- a/CefSharp.WinForms.Example/Program.cs +++ b/CefSharp.WinForms.Example/Program.cs @@ -17,15 +17,15 @@ public class Program [STAThread] public static int Main(string[] args) { - const bool simpleSubProcess = false; + const bool selfHostSubProcess = false; Cef.EnableHighDPISupport(); //NOTE: Using a simple sub processes uses your existing application executable to spawn instances of the sub process. //Features like JSB, EvaluateScriptAsync, custom schemes require the CefSharp.BrowserSubprocess to function - if (simpleSubProcess) + if (selfHostSubProcess) { - var exitCode = Cef.ExecuteProcess(); + var exitCode = CefSharp.BrowserSubprocess.SelfHost.Main(args); if (exitCode >= 0) {