Reputation: 257075
I have code (and for decades) that:
string
in memoryIn other words:
void SpawnIEWithSource(string szSourceHTML)
{
IWebBrowser ie = (IWebBrowser)CoCreateInstance(CLASS_InternetExplorer, null, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
UuidOf(IUnknown));
ie.Navigate2("about:blank");
ie.Document.Write(szSourceHtml);
ie.Document.Close;
ie.Visible = True;
}
Microsoft recently announced that Internet Explorer (the product) will no longer come with Windows, but Internet Explorer (the programming api) will continue to work:
As announced today, Microsoft Edge with IE mode is officially replacing the Internet Explorer 11 desktop application on Windows 10. As a result, the Internet Explorer 11 desktop application will go out of support and be retired on June 15, 2022 for certain versions of Windows 10.
Out of scope at the time of this announcement (unaffected):
- Internet Explorer mode in Microsoft Edge
- Internet Explorer platform (MSHTML/Trident), including WebOC
- Internet Explorer 11 desktop application on:
- Windows 8.1
- Windows 7 Extended Security Updates (ESU)
- Windows 10 Server SAC (all versions)
- Windows 10 IoT Long-Term Servicing Channel (LTSC) (all versions)
- Windows 10 Server LTSC (all versions)
- Windows 10 client LTSC (all versions)
What is the MSHTML (Trident) engine? How does that relate to IE mode?
The MSHTML (Trident) engine is the underlying platform for Internet Explorer 11. This is the same engine used by IE mode and it will continue to be supported (in other words, unaffected by this announcement). WebOC will also continue to be supported. If you have a custom or third-party app that relies on the MSHTML platform, you can expect it to continue to work.
(emphasis mine)
Which means that Microsoft is breaking 23 years of backwards compatibility - and replacing it with...nothing.
So i need to find a way to replace it.
For now i am using @corbin-c's buggy workaround:
procedure SpawnBrowserWithSource(const szSourceHTML: UnicodeString);
var
html: RawByteString; //utf8 encoded
dataUri: string;
szPath: string;
function GetDefaultBrowser: string;
var
nch: DWORD;
hr: HRESULT;
begin
//Get the default browser (i.e. the association for .html file type)
nch := 1000;
SetLength(Result, nch);
hr := AssocQueryString(0, ASSOCSTR_EXECUTABLE, '.html', nil, PChar(Result), @nch);
if hr = E_POINTER then
begin
//Try again if the buffer was too small
SetLength(Result, nch);
hr := AssocQueryString(0, ASSOCSTR_EXECUTABLE, '.html', nil, PChar(Result), @nch);
end;
OleCheck(hr);
SetLength(Result, nch-1); //don't include the null terminator
end;
begin
{
With Internet Explorer being deprecated, this also means that the automation will fail.
So we try to marshall the HTML into base64 encoded URI, and spawn that.
So spawn it as:
data:text/html;base64,[base64 encoded html]
E.g.:
data:text/html;base64,PEhUTUw+PEJPRFk+SGVsbG8sIHdvcmxkITwvQk9EWT48L0hUTUw+
ExecuteFile('data:text/html;base64,PEhUTUw+PEJPRFk+SGVsbG8sIHdvcmxkITwvQk9EWT48L0hUTUw+');
}
html := UnicodeToRawByteString(#$FEFF+szSourceHTML, CP_UTF8);
dataUri := 'data:text/html;base64,'+TBase64.ToBase64String(html);
szPath := GetDefaultBrowser;
if szPath = '' then
raise Exception.Create('Could not locate default browser');
ExecuteFile(szPath, dataUri);
end;
Upvotes: 4
Views: 897
Reputation: 698
I'd encode HTML into Base64 and make it a Data-URI. All modern browsers are able to handle such URIs. This however won't work if your HTML string is too big.
Basically, it'd go like this:
String Base64Encode(string plainText)
{
//Don't forget to add the leading U+FEFF character so that Chrome can recognize the encoding.
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes("\uFEFF"+plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
void SpawnBrowserWithSource(string szSourceHTML)
{
System.Diagnostics.Process.Start("data:text/html;base64," + Base64Encode(szSourceHTML));
}
Resulting in:
(code snippets are from the following Stackoverflow answers: base64 encoding and opening default browser)
Upvotes: 1
Reputation: 77
If you know the user uses Chrome or Edge, you can replace the WebBrowser instance with ChromiumWebBrowser, and use the LoadHtml method to inject the content.
Relevant links:
web browser control in winform with google chrome c# https://www.telerik.com/support/kb/winforms/details/how-to-embed-chrome-browser-in-a-winforms-application https://cefsharp.github.io/api/51.0.0/html/T_CefSharp_WinForms_ChromiumWebBrowser.htm
Upvotes: 0