在hta文件中使用文件输入元素可防止删除所选文件

时间:2016-06-02 05:41:46

标签: vbscript delete-file hta html-input

如果使用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元素使得可以从程序外部手动删除文件UNTIL调用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>

2 个答案:

答案 0 :(得分:3)

使用常规文字输入框

<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 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>

答案 1 :(得分:2)

更新: 基于feedback from OP

现在我已经测试了这种方法,并且与OP的结果相似,所以我想进一步调查。

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

  • 封装在<form>然后调用Reset()方法
  • 清除<input> 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按钮设为<input type="submit">并使用OnSubmit事件来调用Process(),这可能是更清晰的方法,然后调用window.location.reload()

进一步更新:

从多个文件的测试中发现,一旦使用<input type="file">选择了另一个文件,就会删除上一个文件,因为句柄被释放并被提供给新选择的文件。

我想知道克隆<input type="file">元素并删除前一个元素会产生相同的效果并避免重新加载页面吗?

  

更新: 已经过测试,仍然坚持使用文件句柄

<input type="file">用于上传文件,因此一旦您选择了一个文件,HTA会持有一个句柄,这是有意义的。话虽这么说,没有理由你必须直接调用INIFile的值而不是将它存储在变量中(毕竟它只是一个字符串)然后清除Value的{​​{1}}属性。

<input>

有用的链接