2

NOTE: This question is not a duplicate of Can I embed an icon to a .hta file? - For more details, compare the issues and read the comments

I am trying to build an HTA that will automatically perform certain tasks when executed, without user action. The reason I want to use an HTA instead of just a bare VBScript is to inform the user of progress as the routine executes, since it takes some time, and I don't want the user wondering if it hung, maybe restarting it, and so on. There are ten tasks, and I would like to have ten lines in my HTA display, each one with a few words describing what is happening at that point. So far, so good – that is simple enough.

I would also like to have a small icon before each line, that would initially display one icon. When the task on that line begins, it would switch to a second icon, and when it completes it would switch to a third icon.

For several reasons not pertinent to my question, I want to keep it ALL in my HTA – no references to external files. I found a site that led me to using a tag like:

<img src='data:image/gif;base64,R0lGODlhIAAgAOY…'/>

to display a green check mark. It does that very nicely, but I would like to change that dynamically, and there I am running aground. In my HTA, I have VBScript that does this:

x="<img src='data:image/gif;base64,R0lGODlhIAAgAOY…'/>"

(Shortened – the actual image string is quite long.)

and then I have:

img1.InnerHTML = x

to refer to this placeholder in my HTML code:

<span id = "img1"></span>

The code executes, but does not display the green check, only a small black square with a white 'x'. Am I doing something wrong, or is this just not possible? It seems like it should be possible, but no syntax I have tried so far has worked.

Stephen Quan
  • 21,481
  • 4
  • 88
  • 75
Pete Danes
  • 179
  • 1
  • 11
  • 2
    First consider using [Unicode characters](https://unicode-table.com/) for your "icons". That could save you a lot of trouble. – LesFerch Jul 15 '22 at 11:06
  • 3
    In addition to the methods shown in the referenced duplicate, you can also create a zip file of all your icons and then encode that to base64 using the `certutil encode` command line. Then tack that zip file onto the end of your HTA and extract it (to a temp directory) using `certutil decode` and then [unzip the file](https://stackoverflow.com/a/911796/15764378) to get your icons. Here's an [example HTA](https://github.com/LesFerch/DesktopPic/blob/main/DesktopPic.hta) that has an embedded exe using `certutil`. – LesFerch Jul 15 '22 at 11:15
  • 2
    Also, be sure to set your HTA to [IE=9 document mode](https://stackoverflow.com/a/70358044/15764378). Otherwise, your HTA will likely be running in IE 5 mode. – LesFerch Jul 15 '22 at 11:36
  • "Does this answer your question? Can I embed an icon to a .hta file?" Thank you, that has quite a bit of information, and the code in one of the examples does exactly what I have posted here, except that mine does not work. The only difference I see is that they use: data:image/bmp;base64, while I use data:image/gif;base64,. I tried changing mine to match, but it did not help. – Pete Danes Jul 15 '22 at 14:49
  • 1
    "First consider using Unicode characters for your "icons". & Also, be sure to set your HTA to IE=9 document mode." That is not exactly what I wanted to do, but it may be the easiest compromise. I will try it. But the IE=9 line breaks my code - I get the error that the engine was unable to find my code. When I remove that, it works again. – Pete Danes Jul 15 '22 at 14:53
  • 3
    That's typical. If you start coding your HTA for IE 5 mode, you often get an error when switching to IE 9 mode. Usually it's case. IE 5 mode is not case sensitive. IE 9 mode is. It's worth making the change. There are lots of bugs and limits in IE 5 mode. – LesFerch Jul 15 '22 at 15:46
  • 1
    If you post your code (instead of snippets) I'd be happy to help you debug it. – LesFerch Jul 15 '22 at 15:48
  • Stephen Quan - "This question is incorrectly titled..." My question is titled exactly correctly. Is there a way to remove the duplicate marking? – Pete Danes Oct 12 '22 at 05:31
  • Stephen Quan - Once again, my question is titled exactly correctly. I said nothing about embedding, nor about the application icon. YOU have imagined both of those - I make no mention of either one, neither in the title, nor in the text of the question. I have explained my problem as clearly as it is possible to do. If you do not understand it, which seems to be the case, since you accuse me of using terminology that in fact appears nowhere in my question, would you please at least leave my question alone. Maybe someone else who does understand it will have something useful to offer. – Pete Danes Oct 25 '22 at 05:39
  • @Pete Danes. I deleted my comments. I am sorry if you were upset by them. I actually was rooting for you and wanted to get to know your question better and I wanted to contribute assistance. The problem is I cannot. It's because of the duplicate mark. I also nominated for the duplicate mark to be removed. But, my nomination and suggested changes were rejected. I did try. – Stephen Quan Nov 20 '22 at 10:42
  • @Stephen Quan In that case, I apologize. It seemed to me that you were the one saying my question was incorrectly titled. I do not know who gave it the duplicate marking, nor why it was evaluated as being incorrectly titled. In any case, I never did manage to get it figured out, so I went with the Unicode solution, which works well enough for what I wanted. But it still irks me that I could not get my original version working. Seems to me that it should work, and I don't like not being able to figure out why not. – Pete Danes Nov 21 '22 at 11:13
  • @PeteDanes I have something for you. (1) I put HTA in IE mode, (2) I use data uri, (3) I use SVGs. Basically, embedded SVGs in HTML/HTA is the best because you can quickly modify the image since it is clear text. https://gist.github.com/stephenquan/9d20a79c99476e9d4ee240e4fd5bd300 – Stephen Quan Nov 21 '22 at 23:55
  • @PeteDanes I created another version, this one uses CSS: https://gist.github.com/stephenquan/8a4a138ef15ee0fd079bded7f3591463 – Stephen Quan Nov 22 '22 at 06:06
  • @user692942 can you clarify why this question is marked as a duplicate? – Stephen Quan Nov 23 '22 at 20:55
  • @Stephen Quan Thank you, those both work very nicely. I will try modifying both these and my original towards each other and see if I can figure out what was wrong with mine. Appreciate the effort you put in. – Pete Danes Nov 26 '22 at 00:22

2 Answers2

2

It seems that this question is now unlocked, so I am posting the two answers that I posted in the comments.

The first answer is more imperative, in that we need Javascript to convert SVG into a data URI via the svgToDataURL() function. This example is good because you can see the SVG definition in clear text which makes it easier to maintain and change.

<html>
<head> 
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<script>
function svgToDataURL(svg) {
  return "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg);
  //return "data:image/svg+xml;base64," + btoa(svg); // this works too!
  //return "data:image/svg+xml;charset=utf-8," + svg; // this only works in modern browsers
}
var assets = {
    redCross: svgToDataURL('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path stroke="red" d="M23.985 8.722L16.707 16l7.278 7.278-.707.707L16 16.707l-7.278 7.278-.707-.707L15.293 16 8.015 8.722l.707-.707L16 15.293l7.278-7.278z"/></svg>'),
    greenTick: svgToDataURL('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path stroke="green" d="M13.5 22.142L7.59 16.42l.636-.636L13.5 20.87 26.721 7.8l.637.637z"/></svg>')
};
</script>
</style>
</head>

<body>

1 + 1 = 2 <img id="demoSVG" width="16" height="16"> <p>

<script>
var demoSVG = document.getElementById("demoSVG");
demoSVG.src = assets.redCross;
</script>

<button type="button" onclick="demoSVG.src = assets.greenTick">Change SVG!</button>
</body>
</html>

The second answer uses CSS style to configure the image as a background style. This means the Javascript required to change the image is shorter. However, it requires you to URL encode your SVG. Note that this full encoding requirement exists because HTA is more sensitive to what it accepts as a URL. If this was an HTML question instead of HTA, the URL encoding requirement is relaxed and you could have used unencoded SVG in this solution as well.

<html>
<head> 
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<style>
div.redCross {
  display: inline-block; 
  width: 16px;
  height: 16px;
  background-image: url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%3E%3Cpath%20stroke%3D%22red%22%20d%3D%22M23.985%208.722L16.707%2016l7.278%207.278-.707.707L16%2016.707l-7.278%207.278-.707-.707L15.293%2016%208.015%208.722l.707-.707L16%2015.293l7.278-7.278z%22%2F%3E%3C%2Fsvg%3E);
}
div.greenTick {
  display: inline-block; 
  width: 16px;
  height: 16px;
  background-image: url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%3E%3Cpath%20stroke%3D%22green%22%20d%3D%22M13.5%2022.142L7.59%2016.42l.636-.636L13.5%2020.87%2026.721%207.8l.637.637z%22%2F%3E%3C%2Fsvg%3E);
}
</style>
</head>

<body>

<div>1 + 1 = 2 <div id="demo2" class="redCross"></div></div> <p>

<script>
var demo2 = document.getElementById("demo2");
</script>

<button type="button" onclick="demo2.className = 'greenTick'; ">Change SVG!</button>
</body>
</html>
Stephen Quan
  • 21,481
  • 4
  • 88
  • 75
1

Below, are two examples that demonstrate how to dynamically select among different base64 embedded images (icons) in an HTA file. The first one switches the display style from none to inline to cycle through the images. The second one changes the image by replacing the innerHTML contents. The complete examples are here.

Here are the examples with the base64 code truncated:

Example 1:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" http-equiv="X-UA-Compatible" content="IE=9">
<script language="VBScript">
window.resizeTo 250,350
Dim Text,TextIndex
Text = "ABCD"
TextIndex = 1

Sub window_onLoad
  idTitle.innerText = Text
  document.getElementById(Mid(Text,TextIndex,1)).Style.Display = "inline"
  idLetter.innerText = Mid(Text,TextIndex,1)
End Sub

Sub GoLeft
  If TextIndex=1 Then Exit Sub
  document.getElementById(Mid(Text,TextIndex,1)).Style.Display = "none"
  TextIndex = TextIndex - 1
  document.getElementById(Mid(Text,TextIndex,1)).Style.Display = "inline"
  idLetter.innerText = Mid(Text,TextIndex,1)
End Sub

Sub GoRight
  If TextIndex=Len(Text) Then Exit Sub
  document.getElementById(Mid(Text,TextIndex,1)).Style.Display = "none"
  TextIndex = TextIndex + 1
  document.getElementById(Mid(Text,TextIndex,1)).Style.Display = "inline"
  idLetter.innerText = Mid(Text,TextIndex,1)
End Sub

</script>
<style>
body  {background-color:Black; color:White}
.NoShow {display:none}
.Show {display:inline}
.LgFont {font-size:24pt}
</style>
</head>
<body>
  <h2 id=idTitle></h2>
  <img id=A class=NoShow src='data:image/gif;base64,iVBORw0KGgo...'>
  <img id=B class=NoShow src='data:image/gif;base64,iVBORw0KGgo...'>
  <img id=C class=NoShow src='data:image/gif;base64,iVBORw0KGgo...'>
  <img id=D class=NoShow src='data:image/gif;base64,iVBORw0KGgo...'>
  <br><br>
  <input class=LgFont id=GL type=button value= onClick=GoLeft()>
  <input class=LgFont id=GR type=button value= onClick=GoRight()>
  <span class=LgFont id=idLetter>
</body>
</html>

Example 2:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" http-equiv="X-UA-Compatible" content="IE=9">
<script language="VBScript">
window.resizeTo 250,350
Const BeginTag = "<img src='data:image/gif;base64,"
Const EndTag = "'>"
Dim Text,TextIndex
ReDim AImg(128)
AImg(65) = "iVBORw0KGgo..."
AImg(66) = "iVBORw0KGgo..."
AImg(67) = "iVBORw0KGgo..."
AImg(68) = "iVBORw0KGgo..."
Text = "ABCD"
TextIndex = 1

Sub window_onLoad
  idTitle.innerText = Text
  idImage.innerHTML = BeginTag & AImg(Asc(Mid(Text,TextIndex,1))) & EndTag
  idLetter.innerText = Mid(Text,TextIndex,1)
End Sub

Sub GoLeft
  If TextIndex=1 Then Exit Sub
  TextIndex = TextIndex - 1
  idImage.innerHTML = BeginTag & AImg(Asc(Mid(Text,TextIndex,1))) & EndTag
  idLetter.innerText = Mid(Text,TextIndex,1)
End Sub

Sub GoRight
  If TextIndex=Len(Text) Then Exit Sub
  TextIndex = TextIndex + 1
  idImage.innerHTML = BeginTag & AImg(Asc(Mid(Text,TextIndex,1))) & EndTag
  idLetter.innerText = Mid(Text,TextIndex,1)
End Sub

</script>
<style>
body  {background-color:Black; color:White}
.LgFont {font-size:24pt}
</style>
</head>
<body>
  <h2 id=idTitle></h2>
  <div id=idImage></div>
  <br><br>
  <input class=LgFont id=GL type=button value= onClick=GoLeft()>
  <input class=LgFont id=GR type=button value= onClick=GoRight()>
  <span class=LgFont id=idLetter>
</body>
</html>
LesFerch
  • 1,540
  • 2
  • 5
  • 21