【问题标题】:Using file input element in hta file prevents deleting selected file在 hta 文件中使用文件输入元素可防止删除选定的文件
【发布时间】:2016-10-01 16:47:01
【问题描述】:

如果使用 type=file 的输入 html 元素选择文件,则 hta 程序无法删除该文件。

此 MVCE 工作但不使用文件对话框 - 您必须手动输入文件名:

<html>
<HEAD>
<SCRIPT Language="VBScript">
Sub Process
    Set x = CreateObject("Scripting.FileSystemObject")
    MsgBox "this will actually delete "& INIFile.Value
    x.DeleteFile INIFile.Value
    MsgBox "see? "& INIFile.Value &" is gone"
    Set x = Nothing
End Sub
</SCRIPT>
</HEAD>
<body id='body'>
<input type="text" name="INIFile" >
<input type="button" value="Go!" onClick="Process" >
</body>
</html>

但是这个 MVCE 不起作用——文件没有被删除;只是推迟到程序退出:

<html>
<HEAD>
<SCRIPT Language="VBScript">
Sub Process
    Set x = CreateObject("Scripting.FileSystemObject")
    MsgBox "try to manually delete "& INIFile.Value &" (and then undo it)"
    x.DeleteFile INIFile.Value
    MsgBox "now try to delete file "& INIFile.Value &" (now it can't be deleted until the app is closed)"
    Set x = Nothing
End Sub
</SCRIPT>
</HEAD>
<body id='body'>
<input type="file" name="INIFile" >
<input type="button" value="Go!" onClick="Process" >
</body>
</html>

不知何故,使用文件类型输入 html 元素使得可以从程序外部手动删除文件,直到调用 DeleteFile 函数。 DeleteFile 函数实际上并没有删除文件——它只是推迟删除,直到 hta 程序退出——此时文件最终会自行删除。

我需要在程序仍在运行时删除文件。有什么方法可以在 hta 文件中使用文件类型输入 html 元素,并且在 hta 程序运行时仍然删除该文件?

编辑

我的实际用例!在尝试生成可用的 MVCE 时,我没有意识到会找到不符合我的特定要求的解决方案。

我删除文件的原因是我可以用其他东西替换它,所以我需要文件在函数结束之前消失。 Call window.location.reload() 绝对有效,但文件在函数结束时消失。

我实际上想做的是这样的:

<HTML>
<HEAD>
<SCRIPT Language="VBScript">
Sub Process
    Dim file: file = INIFile.Value
    Call window.location.reload()

    'backup the file to tempfile.tmp
    'Now edit tempfile.tmp with all the changes and preview it
    'then ask the user whether they are happy with the changes
    'delete the original file
    'and put the tempfile.tmp in its place

    Dim x: Set x = CreateObject("Scripting.FileSystemObject")
    x.CopyFile file,"tempfile.tmp"
    x.DeleteFile file
    MsgBox "why is "& file &" still there?"
    x.MoveFile "tempfile.tmp",file ' this produces "file already exists"
    Set x = Nothing
End Sub
</SCRIPT>
</HEAD>
<BODY id='body'>
<INPUT type="file" name="INIFile" onChange="Process">
</BODY>
</HTML>

【问题讨论】:

  • 如果将INIFile.Value 设置为变量,然后在调用x.DeleteFile 之前将INIFile.Value 设置为"",会发生什么情况?文件输入 HTML 元素是为通过表单上传文件而设计的,它存储文件的句柄是有意义的。如果您将value 属性设置为空,想知道它是否会继续持有它。

标签: vbscript delete-file hta html-input


【解决方案1】:

使用常规文本输入框

<input type="text" name="FileName" size="30">

添加按钮点击打开文件

<input type="button" onClick="SelectFile" value="Browse...">

添加文件对话框对象

<OBJECT id=Dlg classid="CLSID:3050F4E1-98B5-11CF-BB82-00AA00BDCE0B" width=0 height=0>

添加一个 sub 来获取该对象的返回值并将其放入您的文本框中。

Sub SelectFile
    FileName.value = ""
    strStartPath = "C:\Test"
    strFilter = "Text (*.txt;*.csv)| *.txt;*.csv|VBScript (*.vbs;*.vbc)|*.vbs;*.vbc|HTML (*.htm;*.html;*.hta)|*.htm;*.html;*.hta|All Files (*.*)|*.*|"
    strCaption = "Select a File"
    FileName.value = Dlg.openfiledlg(CStr(strStartPath), , CStr(strFilter), CStr(strCaption))
End Sub

可以根据需要排除或自定义 strStartPath、strFilter 和 strCaption 变量。

FileName.value 将包含文件的路径,它不会被锁定。

编辑:
这是整个 HTA,不包括删除文件的代码(我已经用删除代码对此进行了测试):

<html>
<HEAD>
<HTA:APPLICATION
  APPLICATIONNAME="Select File"
  ID="SelectFileApplication"
  VERSION="1.0"/>
<SCRIPT Language="VBScript">

Sub SelectFile
    FileName.value = ""
    strStartPath = "C:\Test"
    strFilter = "Text (*.txt;*.csv)| *.txt;*.csv|VBScript (*.vbs;*.vbc)|*.vbs;*.vbc|HTML (*.htm;*.html;*.hta)|*.htm;*.html;*.hta|All Files (*.*)|*.*|"
    strCaption = "Select a File"
    FileName.value = Dlg.openfiledlg(CStr(strStartPath), , CStr(strFilter), CStr(strCaption))
    'The file at FileName.value can be deleted at this point.
End Sub

</SCRIPT>
</HEAD>
<body id="body">
<input type="text" name="FileName" size="30">
<input type="button" onClick="SelectFile" value="Browse...">
<OBJECT id=Dlg classid="CLSID:3050F4E1-98B5-11CF-BB82-00AA00BDCE0B" width=0 height=0>
</body>
</html>

【讨论】:

  • 一个重要的一点是对象标签必须是正文中的最后一件事——如果由于某种原因你把它放得更远,页面的其余部分就不会呈现。感谢您的帮助。
【解决方案2】:

更新: 基于feedback from OP

现在我自己测试了这种方法,结果与 OP 相似,所以我想我会进一步调查。

文件句柄似乎在页面的生命周期内被保留,尝试以下操作

  • 封装在&lt;form&gt; 中,然后调用Reset() 方法
  • 清除&lt;input&gt;value属性并使用变量来保存文件路径。

这两种方法都不起作用,但经过测试后发现,如果您在 HTA 中刷新页面,则会发生文件删除,这意味着强制页面重新加载应该可以工作,所以最终还是这样做了。

<html>
<HEAD>
<HTA:APPLICATION ID="oHTA"
     APPLICATIONNAME="myApp"
     BORDER="thin"
     BORDERSTYLE="normal"
     CAPTION="yes"
     ICON=""
     MAXIMIZEBUTTON="yes"
     MINIMIZEBUTTON="yes"
     SHOWINTASKBAR="no"
     SINGLEINSTANCE="no"
     SYSMENU="yes"
     VERSION="1.0"
     WINDOWSTATE="normal"/>
<SCRIPT Language="VBScript">
Sub Process
    Set x = CreateObject("Scripting.FileSystemObject")
    MsgBox "try to manually delete "& INIFile.Value &" (and then undo it)"
    x.DeleteFile INIFile.Value
    'Reload page
    Call window.location.reload()
End Sub
</SCRIPT>
</HEAD>
<body id='body'>
<input type="file" name="INIFile" >
<input type="button" value="Go!" onClick="Process" >
</body>
</html>

这行得通,显然这对于​​捕获文件已在页面重新加载时被删除的事实并不理想,但 OP 并未详细说明他们的要求。

您还可以将Go 按钮设为&lt;input type="submit"&gt; 并使用OnSubmit 事件调用Process(),这可能比调用window.location.reload() 更简洁。

进一步更新:

从对多个文件的测试中发现,一旦使用&lt;input type="file"&gt; 选择了另一个文件,当句柄被释放并提供给新选择的文件时,前一个文件就会被删除。

我想知道克隆&lt;input type="file"&gt;元素并删除前一个元素是否会产生相同的效果并避免需要重新加载页面?


更新: 已经测试并且仍然保留文件句柄

&lt;input type="file"&gt; 是为上传文件而设计的,因此一旦您选择了一个文件,HTA 就会为它打开一个句柄。话虽如此,你没有理由必须直接调用INIFile 的值,而不是将其存储在变量中(毕竟它只是一个字符串),然后清除Value 的属性&lt;input&gt;

Sub Process
    Dim x: Set x = CreateObject("Scripting.FileSystemObject")
    'Get file path from INPUT
    Dim file: file = INIFile.Value
    'Reset file INPUT
    INIFile.Value = ""
    MsgBox "this will actually delete "& file
    x.DeleteFile file
    MsgBox "see? "& file &" is gone"
    Set x = Nothing
End Sub

有用的链接

【讨论】:

  • 我确信我在发布之前尝试过这个(以及许多其他事情),我刚刚又试了一次 - 它做了同样的事情(锁定文件并且直到程序结束)它对你有用吗?我想知道我做错了什么......
  • @JerryJeremiah 调试它怎么样,添加一行来检查INIFile.Value 是否为空,这可能是HTA 阻止了对Value 的访问,所以它永远不会被取消设置。您是否尝试过添加&lt;form&gt; 并使用Reset() 方法来空白&lt;input&gt;
  • @JerryJeremiah 您也将其视为标准 HTML 页面,&lt;HTA:APPLICATION /&gt; 标签在哪里?没有它,您将无法访问浏览器中标准 HTML 中受保护的某些功能.
  • 我把所有不必要的东西都留在了 MVCE 之外。这两种方式都行不通。 - 删除 HTA 标签并没有改变任何东西,所以我把它排除在外。您对 INIFile.value 的写入是正确的-它没有做任何事情。但是表单 reset() 函数确实清除了它 - 不幸的是,它不会阻止脚本锁定文件而不是删除它。我将使用我当前的测试 MVCE 更新问题。
  • 我真希望我们能以某种方式完成这项工作。感谢所有建议。
猜你喜欢
  • 2014-10-16
  • 2013-06-05
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多