1

A little background. I have a mapping program running in an Embedded IE browser. IE exposes IHTMLDocument2 = interface(IHTMLDocument) which I use to call external (desktop) methods. Works great but Google will stop supporting IE shortly and Edge does not support external calls.

  interface IMyExternal: IDispatch
  {
    [id(0x000000C9)]
    HRESULT _stdcall ShowQtrMinBounds([in] BSTR QtrNorth, [in] BSTR QtrSouth, [in] BSTR QtrEast, [in] BSTR QtrWest);
    [id(0x000000CA)]
    HRESULT _stdcall ShowMarker([in] BSTR MsgStream, [in] BSTR ticketID);
    [id(0x000000CD)]
    HRESULT _stdcall ManageQtrGrid([in] BSTR functionName, [in] BSTR retState);
    [id(0x000000CE)]
    HRESULT _stdcall SaveQtrMinutes([in] BSTR qtrMinuteCode);
    [id(0x000000CF)]
    HRESULT _stdcall WhoIsHere([in] BSTR qtrMinuteCode);
  };

To get around this, I've decided write to a file. I spin a thread looking for the textFile which should be named the same as the Methods. The file content will be the arguments.

My problem is that I am not that sophisticated of a JS developer. I've searched for usable script to get me started. I've found:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<table>
    <tr><td>Text to Save:</td></tr>
    <tr>
        <td colspan="3">
            <textarea id="inputTextToSave" cols="20" rows="5"></textarea>
        </td>
    </tr>
    <tr>
        <td>Filename to Save As:</td>
        <td><input id="inputFileNameToSaveAs"></input></td>
        <td><button onclick="saveTextAsFile()">Save Text to File</button></td>
    </tr>
</table>

<script type="text/javascript">
function saveTextAsFile()
{
 var textToWrite = document.getElementById("inputTextToSave").value;

var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'});
var fileNameToSaveAs = document.getElementById("inputFileNameToSaveAs").value;
var downloadLink = document.createElement("a");
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = "Download File";
if (window.webkitURL != null)
{
  downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
}

downloadLink.click();
}
</script>
</body>
</html>

Above works in principle but I cannot use it in practice. I cannot use user inputs. Here is a typical call.

function whoBeHere(point) {
    var LeftLat = (Math.floor(point.lat() / llOffset) * llOffset);
    var LeftLng = (Math.floor(point.lng() / llOffset) * llOffset);
    var qtrMinute = ddToQM(LeftLat, LeftLng);
    external.WhoIsHere(qtrMinute);  
}

I need to have my script write to a file, in the case of the above, it would be named "WhoIsHere" and its contents would be "qtrMinute = 34.0, 82.44"

I've looked at Node.JS but this has to happen client side.

More info. My program creates a grid over googlemaps I call Quarter Minutes. My users selects qtr mins using the mouse in a process I call fencing.

function SaveQtrMin() {
    for (var m in qtrArray) {
        external.SaveQtrMinutes(qtrArray[m].qtrMinute);
    }
}

Write now I call a COM object I've instantiated from IE's Winapi.ActiveX. It exposes methods that permit me to write to the desktop. SaveQtrMinutes(qtrArray[m].qtrMinute) is a COM object I wrote in Delphi 10 years ago. Google is restricting access to Google Maps from IE so my COM object will cease to function.

So, to make it work, I decided that rather than call my Delphi method, which Edge does not support, I would simply write to file.

I can monitor when a file is written by spinning a thread that looks in the folder for a file. If it finds one, it will run the procedure written in the file.

Think that you clicked on restaurant on in Google Maps. I want the browser to write out the restaurant name to a file. I will have a process running that continually looks in that folder and if it a file, it will open it and respond to it somehow.
Thanks

Meta Mussel
  • 548
  • 1
  • 5
  • 19
  • 1
    You can't do it. It would be an enormous security risk to allow developers to create arbitrary files on the user's device. – Slbox May 31 '22 at 20:56
  • @Slbox You can create a file on Frontend, even give user the option to download the file later. https://stackoverflow.com/questions/3665115/how-to-create-a-file-in-memory-for-user-to-download-but-not-through-server – vfioox May 31 '22 at 21:03
  • Writing data _somewhere_ client side is not the same as writing data to a local _file_. – Slbox May 31 '22 at 21:06
  • 1
    Does it have to be written to a file? Could you use localStorage instead? https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage – Derek-B May 31 '22 at 21:17
  • @Slbox What? This is not a public program. This is an embedded browser that will only run on company machines. My program writes to the "desktop" at present and has been doing so for 10 years. – Meta Mussel Jun 01 '22 at 00:37
  • @vfioox But I do not want the user to do the download. I want the file to be written as the result of a JS function. – Meta Mussel Jun 01 '22 at 00:39
  • You're going to have to share a lot more about this very special environment you're running in then. In a normal browser environment, this is not allowed. That's why there's new features like this in Chrome: https://web.dev/file-system-access/#what-is-it -- If it were always possible, there would be no need for this feature. – Slbox Jun 01 '22 at 00:44
  • 1
    The browser is a Google map with a special grid drawn over it. When the user selects grid(s), I want to know which grid he selected so I can respond to that in my program. – Meta Mussel Jun 01 '22 at 00:45
  • 1
    @Slbox I say in my opening line that this is an embedded browser. I wrote it. But it is limited to the processes exposed by IDocHostUIHandler = interface(IUnknown). That interface goes away with Edge. – Meta Mussel Jun 01 '22 at 01:06
  • I don't know your corporate policy, but it seems likely that unless they intend to stay with IE then you're going to need to change gears to find something that will work with Edge. One thing you could do, although rather crazy, is a Chromium extension with [native messaging](https://learn.microsoft.com/en-us/microsoft-edge/extensions-chromium/developer-guide/native-messaging?tabs=windows) to a Node-based app. I mention this only in case you find no better solution. Maybe Edge will adopt the Native Filesystem approach of Chrome? – Slbox Jun 01 '22 at 01:35
  • As already mentioned, you cannot implement this requirement for security reasons, you have to use a server-side language to implement the file write operation. IE just have methods to enable "trusted" applications to use ActiveX objects to read/write file, but Google Maps not support IE in the future. – Xudong Peng Jun 01 '22 at 10:06
  • @Xudong Peng - you are a little late to the game. I have been calling procedures through an ActiveX I wrote since 2014. But I am now have it working. – Meta Mussel Jul 06 '22 at 16:53

1 Answers1

0

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<table>
    <tr><td>Text to Save:</td></tr>
        <td><button onclick="saveTextAsFile()">Save Text to File</button></td>
    </tr>
</table>

<script type="text/javascript">
function saveTextAsFile()
{
 var textToWrite = 'Param1, param2';

var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'});
var fileNameToSaveAs =  'FileNameNow.txt';
var downloadLink = document.createElement("a");
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = "Download File";
if (window.webkitURL != null)
{
  downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
}

downloadLink.click();
}
</script>
</body>
</html>
Meta Mussel
  • 548
  • 1
  • 5
  • 19