Summary of CEF function development experience

Source: Internet
Author: User
Tags file copy message queue rar

Reprint please explain the original source, thank ~~:http://blog.csdn.net/zhuhongshu/article/details/70159672

This is when I develop CEF function on the pit, carried on the summary, saying that CEF pit really many. It's nice to use it when you're done. The final code can download NetEase cloud Letter pc Demo point I jump data preparation

This is the information that I have found in the process of integration, including all aspects of CEF development.

When debugging CEF, you need CEF pdb and source code: CEF and PDB file download address, where cefclient contains CEF most of the features of the example: Https://cefbuilds.com/Cef and corresponding Chromiun source download address: http ://opensource.spotify.com/cefbuilds/index.html CEF and JS Interaction: http://blog.csdn.net/foruok/article/details/50573612 CEF and JS Interactive two: http://www.cnblogs.com/guolixiucai/p/4943748.html CEF Official document Chinese translation version, including CEF guidance (this is very important information) and some experience documents, very useful: HTTPS ://github.com/fanfeilong/cefutil CEF Basic structure Cefapp interface

The Cefapp interface provides customizable callback functions for different processes, with each process corresponding to a Cefapp interface. Cefbrowserprocesshandler the callback for the browser process, cefrenderprocesshandler the corresponding rendering process. We should inherit Cefapp, Cefbrowserprocesshandler, Cefrenderprocesshandler interfaces. If you fully use the multiple process pattern, you can separate the interfaces from the browser process and the rendering process separately

The Cefapp::onbeforecommandlineprocessing method can append the command line arguments passed to CEF, where you can attach a lot of control parameters

The Cefrenderprocesshandler::onwebkitinitialized method can be used to register the JS extension code when the rendering process is initialized, and to realize C + + interaction with JS.

The Cefrenderprocesshandler::onfocusednodechanged method detects the currently acquired focus HTML element and obtains some element information that can be sent to the browser process via process communication to assist in further judgment

The Cefrenderprocesshandler::onprocessmessagereceived method is used to receive messages from the browser process and use the cefclient interface when doing C + + interaction with JS.

Each Cefbrowser object corresponds to a cefclient interface that handles various callback information for the browser page, including the browser lifecycle, right-click menu, dialog box, status notification display, download events, drag events, focus events, keyboard events, off-screen rendering events. With the CEF version of the update these interfaces will also be extended and updated, most of the CEF behavior control methods are concentrated in these interfaces, if there is a new functional requirements for CEF, generally can be turned over these interfaces have not provided the relevant functions

The Cefclient::onprocessmessagereceived method is used to receive messages sent by the render process and to use the cefsettings structure when doing C + + interaction with JS.

The cefsettings structure defines the CEF global configuration information, such as specifying a single process mode, specifying the render subprocess path, setting the Localstorage path, setting the log level, and CEF the resource file path. The most important fields for the project are single_process, Multi_threaded_message_loop, windowless_rendering_enabled, which are used to specify single process mode, multithreaded rendering mode, Off-screen rendering mode. compatible with existing message loops

If the UI thread message loop is a simpler project, you can call Cefrunmessageloop directly to use the CEF message loop, which blocks the thread until the Cefquitmessageloop function is called. Cefrunmessageloop is compatible with the traditional Win32 message loop.

The bottom of the NIM project, however, is to use the multithreaded architecture of the Google Base library, so there is no direct use of cefrunmessageloop. (PS: Actually CEF's underlying message loop is Google's base library)

There are two ways to allow Nim's message loop to be compatible with the CEF message loop. The first of these methods

The first approach is to use the Cefdomessageloopwork function instead of the Cefrunmessageloop to complete the message loop. The role of the Cefdomessageloopwork function is to let CEF execute a message loop that does not block threads, so it is necessary to actively invoke the Cefdomessageloopwork function in our existing message loop, as appropriate. If the call is too frequent will be very consuming CPU, if the call frequency is too low can cause CEF too late processing internal message, let the CEF interface reflects slow, so this function is called timing is very important.

Because the Cefdomessageloopwork function should be invoked in the original message loop, the UI thread message loop for the base library is encapsulated. First, here's how to customize the base library message loop. The code to invoke the UI message loop in the WinMain entry function is as follows:

{
    mainthread thread;//create main thread
    thread. Runoncurrentthreadwithloop (Nbase::messageloop::kuimessageloop); Execute main thread Loop
}

In the second argument of the Runoncurrentthreadwithloop method, you can specify a message dispatcher pointer Dispatcher,dispatcher inherited from Nbase::D ispatcher. The UI message looping code in the base library is as follows:

preProcessMessage (msg);

if (State_->dispatcher)
{
    if (!state_->dispatcher->dispatch (msg))
        State_->should_quit = true;
}
else
{
    translatemessage (&msg);
    DispatchMessage (&msg);
}

Postprocessmessage (msg);

If we specify the second parameter of the Runoncurrentthreadwithloop method, we will not invoke the original message loop, so we can customize the message loop in this dispatcher. I implement the Cefmessageloopdispatcher class and rewrite the dispatch interface.

BOOL cefmessageloopdispatcher::isidlemessage (const msg* PMSG)
{
    switch (pmsg->message)
    {case
    WM _mousemove: Case
    wm_ncmousemove: Case
    WM_PAINT: return
        FALSE;
    }

    return TRUE;
}

BOOL Cefmessageloopdispatcher::D ispatch (const MSG &msg)
{
    static BOOL bdoidle = TRUE;

    TranslateMessage (&msg);
    DispatchMessage (&msg);

    if (Isidlemessage (&msg))
    {
        bdoidle = TRUE;
    }

    while (Bdoidle &&!::P eekmessage (const_cast<msg*> (&msg), NULL, 0, 0, pm_noremove))
    {
        Cefdomessageloopwork ();
        Bdoidle = FALSE;
    }

    return true;
}

In a custom message loop, call the Cefdomessageloopwork function if you decide that the current message queue is empty and that the message you just processed does not specify a few messages. WM_PAINT, Wm_mousemove and other messages are more complex to handle, so the Cefdomessageloopwork function is not called here

This method is basic to use, but there are some problems, where the cefdomessageloopwork function is not good enough, CEF interface is not smooth, and because the CEF and the project base library conflict, resulting in the end of the program some problems. This method needs to be optimized by the second method

When the Multi_threaded_message_loop (multithreaded message loop) of the cefsettings structure is false, You can invoke the Cefrunmessageloop or Cefdomessageloopwork function to trigger the CEF message loop. The UI thread of the browser process is the thread that invokes the Cefrunmessageloop or Cefdomessageloopwork function. If the multi_threaded_message_loop of the cefsettings struct is true. The UI thread for the browser process is another thread. Set Multi_threaded_message_loop to True to use a multithreaded message loop.

By comparing the multithreaded message loop code of CEF demo, you can decide to open a multithreaded message loop directly in the NIM project, and you can use CEF without modifying the existing message loop code. It should be noted, however, that some functions cannot be used after using a multithreaded message loop, such as Createbrowsersync, which requires that the CEF UI thread be invoked.

In addition, in many versions of CEF, if a multithreaded message loop is turned on, it causes the program to end with an interrupt, which is a CEF bug, but there is no problem in release version CEF. You should use this method in your project. However, after using a multithreaded message loop, many of the callback functions triggered by the CEF object are in the CEF UI thread rather than our UI thread, so it is troublesome to operate our UI thread, to pay attention to some multithreaded problems, and to forward the operation to our UI thread as much as possible, If you do not forward, you must determine that the code that is being manipulated does not affect our UI thread, remember. Introduction to Cefclient interface Ceflifespanhandler

The callback interface for the life cycle events of the Cefbrowser object. Onaftercreated: When you invoke the Createbrowser function to create a browser object, it immediately triggers the callback, where you can save the pointer to the browser object Doclose: This callback is triggered when the CloseBrowser function is invoked Onbeforeclose: This callback is triggered when the browser object is about to be destroyed, so be sure to release all references to the Cefbrowser object, otherwise it will cause the program to quit. Remember this pit. Onbeforepopup: This callback is triggered when a link that pops up a new window is clicked. We should ban the pop-up of new windows in our project, and jump links in the original control Cefrenderhandler

To use the off-screen rendering feature, you must implement this interface class. Because the Duilib library used in the project is currently using a layered form mechanism to implement an profiled form effect, it is not supported to display child windows that can only draw controls, so it is not possible to display CEF browser objects in the form of simpler child windows. Only the off-screen rendering method can be used, and the data rendered from the screen will be recalled via the Cefrenderhandler interface.

You must first open the Windowless_rendering_enabled field of the cefsettings structure Getrootscreenrect: A callback that triggers after the browser object is created, returning the position of the outermost form on the screen getviewrect: Triggers the callback to get the location of the browser object when the browser object is initialized, or when the browser size changes. This returns the position of the control, because the browser object is tiled over the entire control. The upper left position returned is accurate, otherwise CEF will have an error processing some coordinate information getscreenpoint: Here the incoming coordinates are converted from client coordinates to screen coordinates Oncursorchange: This callback is triggered when the mouse cursor needs to be modified OnPaint: When the browser object has new render data, it triggers the callback, which contains the dirty area and renders the data. You should save this data and then post it on the target form when appropriate onpopupshow: When the internal dialog box pops up in the browser (such as a drop-down menu), triggers the callback, notifies you to show or hide the pop-up box onpopupsize: When you want to eject the internal dialog box in the browser, Triggers this callback, notifies the popup of the position and size of the off-screen rendering implementation

Off-screen rendering efficiency is not as good as the real window rendering, if you do not have to leave the screen rendering the situation, or use the real window is better. The Cefcontrol control implements the Duilib embedded CEF browser object.

When the control initializes the INIT function, the Createbrowser function is invoked to create the Cefbrowser object, which triggers the cefrenderhandler::getviewrect callback, which returns the position of the control in this callback. The Cefrenderhandler::onpaint callback is triggered when the page is rendered for the first time. the process of drawing the rendered data triggers the Cefrenderhandler::onpaint callback when the page renders the data change, or when we actively invoke the Invalidate method of the Cefbrowser object. I wrote a memory bitmap buffer class MEMORYDC to hold the render data from CEF, and in the Cefcontrol control dc_cef_ the member variable is responsible for saving the rendered data. In the Cefrenderhandler::onpaint callback, the Dc_cef_ is initialized based on the rendered data, and the rendered data is copied to the dc_cef_ according to the dirty area. After copying the data, call the Cefcontrol control's Invalidate method notification form to redraw the control in the Cefcontrol control's Paint method, copy the Dc_cef_ bitmap data to the Duilib incoming HDC Cefcontrol The handling of events

Modify Cefbrowser Dimensions
In off-screen rendering mode, you cannot directly modify the dimensions of the Cefbrowser object. The Cefcontrol control overrides the SetPos function, where the wasresized interface of the Cefbrowser object is called to notify the Cefbrowser that the object needs to resize, and then the GetViewRect interface is triggered. This is still the place to return to the Cefcontrol control. The OnPaint interface is then automatically triggered and a refresh of the rendered data is performed in the previous section of the process

Set Cefbrowser hide (show)
The Cefcontrol control overrides the SetVisible function and the setinternvisible function, where the Washidden interface of the Cefbrowser object is called to notify the Cefbrowser object to hide or displayprocessing of system messagesWhen the control initializes the INIT function, the Addmessagefilter function of the form class is invoked to register itself in the message filtering queue of the form. The Cefcontrol control inherits the Iuimessagefilter interface class and overrides the MessageHandler function. When the system message enters the form, it calls the message Filter queue pointer in turn to filter the message. In the MessageHandler function we are interested in the message, other messages do not filter the processing of various mouse class messages, the decision if the mouse is not within the scope of the control does not process the relevant messages. Gets the coordinates of the current mouse, because the coordinate value of the cefbrowser is the origin in its upper-left corner, so the mouse coordinates are obtained to subtract the upper-left coordinate value of the Cefcontrol control. When processing Buttondown, Buttonup, MouseMove messages, the message continues to be passed to the form, where you need to have the Duilib form class handle keyboard messages with functions such as SetCapture, ReleaseCapture, and so on. Determines whether the current control gets the focus, handles only the situation with focus wm_setcursor message processing, intercepts the wm_setcursor message in the MessageHandler function, and calls the default message handler function of the form class directly, not allowing Duilib to process the message. The Cefrenderhandler::oncursorchange interface modifies the mouse cursor and modifies the default cursor style of the form, and duilib changes the cursor when processing the WM_SETCURSOR message, so it is necessary to interceptRender popup Pop-up boxIn the browser, the render data of the pop-up box needs to be handled by itself. The following pop-up box, such as Drop-down menu, or the browser will not display a pop-up box when you need to display a pop-up box, the Cefrenderhandler::onpopupsize interface will pass in the position and size of the pop-up box, where the data is saved to the RECT_POPUP_ member variable The Cefrenderhandler::onpaint callback is then triggered and the render type is specified as a pop-up type Pet_popup. When you save the render data of the pop-up box to the DC_CEF_POPUP_ member variable in the MEMORYDC type, the Invalidate method of calling the Cefcontrol control notifies the form to redraw the control in the Cefcontrol method of the paint control. Copy the Dc_cef_popup_ bitmap data to the Duilib incoming HDC when the pop-up box disappears, rect_popup_ the Cefrenderhandler::onpopupshow interface, reset the RECT_POPUP_ Information and notifies Cefbrowser to refresh the pageMulti-Process rendering

CEF3 supports multiple processes and single process rendering, but the single process rendering is not stable and should only be used for debugging purposes in debug mode. In several versions, such as Cef3.1916, the single process mode is used in the debug state, triggering interrupts when the program initializes or exits. However, there is no problem in multiple process mode. The official also explicitly stated that the use of single process mode is not recommended

The Cefmanager class implements the initialization and destruction functions of the CEF3. The cefexecuteprocess function called in the initialization function initialize detects the current process type, and if it is a browser process, the function returns directly, and in other processes the function blocks direct process destruction.

The ClientApp class inherits Cefbrowserprocesshandler and Cefrenderprocesshandler, and can handle messages for both the browser process and the render process. In the original multi-process mode, the browser process and the render process can use a single program. But because our main program code is more complex, if the main program to open the process, it will occupy more memory and CPU, while triggering unnecessary problems. So a separate Cef_render project was specifically written to render the child process

Cef_render Project code is simpler, and the main code is the Cefrenderprocesshandler class that inherits the Cefrenderprocesshandler interface. Considering the code is comprehensive, you can later add some crash dump processing code in the Cef_render project. It is important to ensure that the Cefrenderprocesshandler interface implementation code of the main program is consistent with the Cefrenderprocesshandler interface of the Cef_render program. Otherwise, there will be different processing results in single process and multi process mode

When the browser process starts, you can specify the path of the render child process with additional parameters

Command_line->appendswitchwithvalue ("Browser-subprocess-path", "Render.exe");
C + + and JS interaction C + + call JS

In both the browser process and the render process can directly execute the JS code, directly invoke the Cefframe object Executejavascript method can be JS call C + +

Some JS callbacks in the Web page and JS extensions to the Web page must be manipulated in the render process. Let JS call C + + method has three, http://www.cnblogs.com/guolixiucai/p/4943748.html inside introduced two kinds, https://github.com/fanfeilong/cefutil inside is more complex and stronger third kind.

Our project, only need to give JS to open a function interface, and the interface is not complex, so directly using the JS extension method to register the JS callback function.

In the Cefrenderprocesshandler::onwebkitinitialized interface, register JS extension code

std::string Extensioncode =
    "(function () {"
    "  ceftestwebfunction = function (param) {"
    "    native function ceftestwebfunction (param); "
    "    return ceftestwebfunction (param); "
    "    }; "
    "}) ();";

cefrefptr<cefv8handler> handler = new Cefjshandler ();
Cefregisterextension ("V8/extern", Extensioncode, Handler);

The Cefregisterextension function executes the extended code. The online example is to create a global object, and then bind the JS function and variable to this object. This directly declares a funexternal global function. When the JS code calls the Funexternal function, according to the native keyword function name, to notify the C + + code calls the corresponding native function

The Cefjshandler class inherits the Cefv8handler interface and implements the Execute method, passing the Cefjshandle pointer in Cefregisterextension, when the JS code needs to call the native function, Will trigger the Cefjshandler::execute method actively

BOOL Cefjshandler::execute (const cefstring& Name, Cefrefptr<cefv8value> object, const cefv8valuelist& Arguments, cefrefptr<cefv8value>& retval, cefstring& exception) {if (name = = "Ceftestwebfunction" &
            & Arguments.size () = = 1) {for (auto &it:arguments) {if (it->isstring ())

                {cefstring param = it->getstringvalue ();
                cefrefptr<cefbrowser> browser = Cefv8context::getcurrentcontext ()->getbrowser ();

                Cefrefptr<cefprocessmessage> message = Cefprocessmessage::create (kjscallbackmessage);
                Message->getargumentlist ()->setstring (0, name);
                Message->getargumentlist ()->setstring (1, param);

                Browser->sendprocessmessage (pid_browser, message);
            retval = Cefv8value::createbool (true);
    } return true;
   }//Function does not exist. return false;
 }

Here you can get the name of the function to be called JS, as well as the parameters such as incoming information. When this information is obtained, they are packaged as cefprocessmessage structures, and the information is sent through IPC to the browser process for asynchronous processing. Call the Sendprocessmessage method to send information to the browser process

The Cefclient::onprocessmessagereceived method of the browser process receives a message from the render process. Browser process message processing, you can call JS through C + + method to notify the Web side of the process of the end of the message processing results

In Https://github.com/fanfeilong/cefutil/blob/master/doc/CEF_ CLOSE.MD has a complete CEF end process analysis and processing code, but because our project is not only CEF components, but also use the scene and CEF demo, so different from the shutdown process Cefcontrol control destruction Process Call the CloseBrowser (True) method in the destructor of the Cefcontrol control to notify the browser object to turn off the Browserhandler::D The Oclose interface is triggered, no extra processing is required, and direct return can The Browserhandler::onbeforeclose interface is then triggered, where it is important to release all references to the Cefbrowser object, otherwise it will cause the program to not exit. Process exit Process user clicks the Exit menu item of the lower-right pallet to trigger to Logincallback::D ologout function, where it is invoked to code Nim_comp:: Windowsmanager::getinstance ()- >destroyallwindows (), where all forms are destroyed and all controls are destroyed, naturally triggers the destruction process for all cefcontrol controls, and all browser objects are closed Logincallback::D The Ologout function will then call to the Uilogoutcallback function, which would have called the PostQuitMessage (0) function to end the message loop, but we should wait for all browser objects to close after the end of the message loop, otherwise an error will occur. The Cefbrowser shutdown is asynchronous, so it is not guaranteed that all cefbrowser are turned off when the Uilogoutcallback function is invoked, and I implement the PostQuitMessage function in the Cefmanager class, Wait here for all cefbrowser to close and then end the message loop the program ends normally.

Cefmanager::P ostquitmessage function to determine the number of current browser objects to decide whether to exit the message loop, if there is no shutdown browser objects Wait 500 milliseconds before detection:

void Cefmanager::P ostquitmessage (int nexitcode)
{
    if (Browser_count_ = = 0)
    {
        Post2ui ([Nexitcode] ()
        {
            ::P ostquitmessage (Nexitcode);}
        );
    else
    {
        Auto cb = [Nexitcode] ()
        {
            cefmanager::getinstance ()->postquitmessage (Nexitcode);
        };

        Nbase::threadmanager::P ostdelayedtask (Kthreadui, CB, nbase::timedelta::frommilliseconds);
    }

integrating the CEF component into the Cloud letter Nim Project Copy the CEF module components that are written in the TOOL_KITS\CEF directory to the corresponding directory of your own project and add them to the solution. Where the Cef_render project is a CEF rendering process, is an independent Exe;libcef_dll_wrapper project is CEF exported C-language interface of the + + packaging class; Cef_module project is the core package code that encapsulates the CEF function in Nim The classes that are used directly in the demo include Cefmanager and Cefcontrol, Cefnativecontrol two controls that manage CEF functions. The source file copy of the NIM_WIN_DEMO\GUI\CEF directory is a directory of their own project, which Cefcontrol, Cefnativecontrol two control of the test window code, optional access to the Libs directory, decompression cef_ Sandbox.rar the compressed package and put the Cef_sandbox.lib, cef_sandbox_d.lib files into the Libs directory, enter the Libs\x64 directory, extract the Cef_sandbox.rar compressed package and put Cef_sandbox.lib , cef_sandbox_d.lib files to the libs\x64 directory. This is the static library that adds sandbox functionality to the CEF module when compiling the CEF component. The BIN\CEF directory is a CEF-related DLL that the CEF module relies on. When the main program initializes, it loads the required DLL configuration Nim_demo project properties from the BIN\CEF directory, and joins Libcef.dll;libegl.dll;libglesv2.dll in linker \ Input \ Deferred DLLs CEF ( Because we put the DLLs required by CEF into the BIN\CEF directory, this will not cause directory clutter, but in order to successfully load the CEF DLL, you need to delay loading, if you do not want to use deferred loading, the BIN\CEF directory of DLLs directly into the bin directory)

The first sentence in the WinMain function is added (used to delay loading the CEF DLL, which is not required if loading is not deferred)
NIM_UI:: Initmanager::getinstance ()->addcefdlltopath ();
Add the following code to initialize the CEF function before starting the cloud-letter component initialization (be sure to precede the cloud-letter component initialization)
if (!nim_cef::cefmanager::getinstance ()->initialize (True)
return 0;
After starting the UI thread message loop, add the following code to clean the CEF feature
Nim_ui::initmanager::getinstance ()->cleanupuikit ();

Locate the original project call::P ostquitmessage function, modified to NIM_CEF:: Cefmanager::getinstance ()->postquitmessage (0); Other configurations If you have questions, see the configuration of the CEF Nim demo for CEF support for Flash, MP3, MP4

The CEF-related DLLs used in the accompanying NIM demo are now specifically downloaded after CEF source code addition MP3, MP4 functionality (compile Cef3.2623 under Windows and join MP3, MP4 support (with source packages and final DLLs)). So if you use the DLL I provided, you can support MP3, MP4 playback directly (CEF not supported by the official download directly). If you have other requirements for the CEF feature, download the compile CEF and replace the DLL in the demo

The DLLs included with the demo are release versions with no debug version attached

Flash playback is already supported by default in the Cef_module project, and the DLL for Flash playback is included in the Bin\cef\pepperflash directory, and you can delete this directory if you don't need flash functionality

The Cef_module project provides two controls to display the Cef browser, Cefcontrol, Cefnativecontrol,cefcontrol for off-screen rendering mode, Cefnativecontrol for true window mode, Select one of these two controls, depending on your requirements. Off-screen Rendering mode control the browser to control their own rendering, so it can be combined with NIM duilib more perfect, support transparent profiled form; True window mode because CEF need to rely on a child window, by CEF rendering, so can not support transparent profiled form. For the vast majority of requirements, the use of Cefcontrol rendering mode is better, because the combination with duilib more perfect. However, if the content of the Web page is refreshed very frequently (especially when it is used to play flash), you should use the true window mode, otherwise the frequent drawing operations caused by flash playback will cause the CPU occupancy rate of the program to soar.

Our code default is to open out of the screen rendering mode, if there is the need to play flash or other browser screen frequently needs, should turn off the screen rendering mode and use the true window mode, about the method when the WinMain function initialization CEF function when the parameters passed into the FALSE,NIM_CEF:: Cefmanager::getinstance ()->initialize (false). In addition, our Duilib window by default is to use a layered window that supports transparent aliens, is not support child windows, so if you use CEF true window mode, you should close the Duilib window of the layered window style, the Close method is to create Windows window:: The fifth parameter Islayeredwindow of the CREATE function is set to false. The Cefform, Cefnativeform in the demo are used to demonstrate the function of the off-screen rendering mode (corresponding to the Cefcontrol control) and the True window mode (corresponding to the Cefnativecontrol control) respectively. The creation code for these two Windows has demo code in mainform::onclicked to disable the CEF module feature

The Cef_module project has a CEF macro SUPPORT_CEF, Support_cef_flash that adds two controls to the module's functionality. SUPPORT_CEF macros control whether the CEF feature is enabled, Support_cef_flash controls whether CEF supports Flash playback (this SUPPORT_CEF works only when macro macros are enabled).

If you do not need the browser functionality brought by CEF, you can remove the SUPPORT_CEF macros in the Cef_module project so that the CEF related features are disabled. At the same time *bin\cef* directory can be deleted without affecting the operation of the program.

If you need CEF functionality but you don't need flash

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.