Filesystemobject Textstream, immediately disappears upon executing Textstream.Close (.vbs extension being created) - vba

I have a situation that is really flummoxing me. Simple code I've used for years is failing in the weirdest way. I have a feeling the cause is related to either anti-virus junk or GPO, but, even those, I have seen them operate before on this scenario--but nothing like how I am seeing it now.
Note - this code has been working perfectly for several people, until one end-user got a new Surface laptop from I.T., purportedly for better compatibility with Teams and 365. ALL users (working, non-working) are on Windows 10.
Scenario:
I'm using Scripting.Filesystemobject
setting an object variable (Textstream intent), as fso.createtextfile
The filepath (name) I am creating is actually filename.vbs...At the moment this line executes, I can see the vbs file successfully in the folder
I use Textstream.Write to put some content in the file
I then use Textstream.Close (normally at this point you get a solid, stable, useable file). Immediately upon execution of the last line, Textstream.Close, the file DISAPPEARS from the folder-GONE.
The folder I'm writing to is the same as Start > Run > %appdata%
I've also tried this in Documents folder (Environ$("USERPROFILE") & "\My Documents") and get the exact same result
I've seen group policies and AV stuff that will prevent VBS from running, but that isn't my case--I've tested with this user, and she has no problem:
Creating a txt file in either of those folders
Manually creating a .vbs file in either of those folders
Even RUNNING the resulting vbs file in either folder
But somehow when I programmatically create .VBS in code, the second I close the textstream, the file is gone from the folder.
Any insight? The internet searches I did were void of all information on this scenario!! It would take me 2 weeks to open a ticket and get any help from I.T.
This is Excel VBA, but I highly doubt the problem has anything to do with Excel nor VBA...this is standard usage of windows scripting.filesystemobject:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
'initiate full backup vbs script:
Dim ts As Object, fso As Object, strScriptText As String, strScriptPath As String
'populate our variable with the full text of the script: found on QLoader in this range:
strScriptText = ThisWorkbook.Worksheets("QLoader").Range("z_BackupScriptText").Value
'replace the text "placeholder" with this workbook's actual full path/name:
strScriptText = Replace(strScriptText, "placeholder", ThisWorkbook.FullName)
'fire up FSO:
Set fso = CreateObject("scripting.filesystemobject")
'determine the new VBS file's path
strScriptPath = Environ("AppData") & "\Backup_" & Format(Now, "yymmddhhmmss") & ".vbs"
'create our textstream object:
Set ts = fso.createtextfile(strScriptPath)
'write our script into it
ts.write strScriptText
'save and close it
ts.Close 'RIGHT HERE THE FILE DISAPPEARS FROM THE FOLDER ***********
'GO:
Shell "wscript " & strScriptPath, vbNormalFocus
End Sub

It does look like an antivirus thing...
If the issue is just the vbs extension though, you can use something like this:
Sub tester()
Dim ts As Object, fso As Object, strScriptText As String, strScriptPath As String
Set fso = CreateObject("scripting.filesystemobject")
strScriptPath = Environ("AppData") & "\Backup_" & Format(Now, "yymmddhhmmss") & ".txt"
Set ts = fso.createtextfile(strScriptPath)
ts.write "Msgbox ""Hello"""
ts.Close
'need to specify the script engine to use
Shell "wscript.exe /E:vbscript """ & strScriptPath & """ ", vbNormalFocus
End Sub

Related

Write txt first line instead of last

It is easy to find in the internet a way of write into a txt file but all I find is always writing in the very last line:
Sub write_log(sentence_to_be_written As String)
Dim strFile_Path As String
strFile_Path = "C:\Users\[user_name]\Desktop\log.txt"
Open strFile_Path For Append As #1
Print #1, Now() & " --> " & sentence_to_be_written
Close #1
End Sub
I would like to write instead into the first line of the txt file.
Try the next code, please. It needs a reference to Microsoft Scripting Runtime. It can be adapted to work without such a reference. In fact, I will also post a pice of code able to automatically add the necessary reference... It is possible to read the text using standard VBA Open, but only concatenating line by line and I think this solution is more elegant:
Sub write_log_OnTop(sentence_to_be_written As String)
'It neds a reference to 'Microsoft Script Runtime'
Dim strFile_Path As String, strText As String
Dim fso As New FileSystemObject, txtStr As TextStream
strFile_Path = "C:\Users\Fane Branesti\OneDrive\Desktop\log.txt"
If Dir(strFile_Path) <> "" Then 'check if file exists
Set txtStr = fso.OpenTextFile(strFile_Path)
strText = txtStr.ReadAll
txtStr.Close
Else
MsgBox "Wrong file path...": Exit Sub
End If
strText = Now() & " --> " & sentence_to_be_written & vbCrLf & strText
Open strFile_Path For Output As #1
Print #1, strText
Close #1
End Sub
And Microsoft Scripting Runtime reference can be automatically add by running of the next code:
Private Sub Add_Scripting_Reference() 'Adds 'Microsoft Scripting Runtime'
Dim wb As Workbook, r As Reference
Set wb = ThisWorkbook
For Each r In wb.VBProject.References
If r.name = "Scripting" Then Exit Sub
Next
wb.VBProject.References.AddFromFile Environ("windir") & "\system32\scrrun.dll"
End Sub
If you do not want the reference, even if I would not understand such a choice, it is enough to comment/replace the code line
Dim fso As New FileSystemObject, txtStr As TextStream
with:
Dim fso As Object, txtStr As Object: Set fso = CreateObject("Scripting.FileSystemObject")
There is no command to add text at the top (or the middle) of any file. I never heard about such command in any programming language. It's about (disk-)space management, if you add a line of text in front of any other text, the existing text needs to be moved, and this is a rather complicated operation.
If you deal with short files, you could solve that by reading the content of the file into memory and then recreate the file by first writing the new line(s) and the add the content - as Joerg Wood suggested in the comments. However, this would need lot of memory and/or disk IO if the file gets larger, and the process has to be repeated every time you want to add a line - maybe not an issue if you write only one line per hour, but quite an issue if you are writing multiple lines per second.
It seems you are writing a log file and probably you want to see what was going on lately. You could use a windows version of the tail command (that comes from Unix) or use the powershell command Get-Content "C:\Users\[user_name]\Desktop\log.txt" -Tail 10 (see https://stackoverflow.com/a/188126/7599798) for that - it will display the last lines of a file.
An alternative could be to write the log into an Excel sheet or a database - in both cases it is easy to fetch the data in any order.

copyfile ini to txt: permission-denied

I just want to copy the Content of a ini-File into a txt-file. But it tells me, that permission is denied.
The source file is closed
the Ini-file "Aly_complete.ini" was previously executed in the code via "java -jar"
As you see, I already tried another file, which wasn't used by the code before
Here is the code
Sub Kopieren_Ini(strPathQuelle As String, strPathErg As String)
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim oFile As Object
Dim Quelle As String
Dim Ziel As String
If Sheets(1).TxtBoxIni.Text <> "" Then
Quelle = Sheets(1).TxtBoxIni.Text
Else
Quelle = strPathQuelle & "Aly_MitDatum.ini"
'Quelle = strPathQuelle & "Aly_complete.ini"
End If
Set oFile = fso.CreateTextFile(strPathErg & "\" & "Config_Test.txt")
Ziel = strPathErg & "\" & "Config_Test.txt"
FileSystem.FileCopy Quelle, Ziel
Thanks in advance for your help
Sounds like the .ini is being used by another application or process. What else is running? Does this still occur after you reboot? ( Source: my comment ☺)
Your code is incomplete (it doesn't End) so I can't say for sure, but I bet your issue is same common mistake that [imho] is the culprit in almost every complaint of Excel crashes caused by VBA code...
It's just like parenta are always telling their children:
The file is Open (and locked and taking up memory) until you .Close it.
Objects that are opened need to be closed & cleared.
Try adding these 3 lines to the end of your code (or where ever you're finished using the objects):
oFile.Close
Set oFile = Nothing
Set fso = Nothing
...then save your work, reboot, and try it again.
More Information:
Stack Overflow : Is there a need to set Objects to Nothing inside VBA Functions?
MSDN : FileSystemObject Object
MSDN : CreateTextFile Method
MSDN : Close Method (FileSystemObject)
EDIT: "Copy & Rename"
If you simply need to copy a file (and rename the copy at the same time), use this:
Option Explicit
Sub copyFile()
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
fso.copyFile "c:\sourcePath\sourceFile.ini", "c:\destinationPath\destFile.txt"
Set fso = Nothing
End Sub
More More Information:
Rob de Bruin : Copying & Moving Files with VBA
Excel Trick : FileSystemObject in VBA – Explained
MSDN : CopyFile Method

Textstream object remains open in Excel after being closed by VBA

I have some VBA code in Excel 2007 which creates, fills, then closes a Textstream file object (abbreviated snippet below).
Set CSV = FSO.CreateTextFile(strPathOut & Application.PathSeparator & strFileOut)
'Fill the file
CSV.Close
The code works perfectly, including the CSV.Close instruction, however if I then try to delete or modify the file (e.g. in Windows Explorer or Notepad) the system claims Excel still has the file open. Seemingly the only way to release it is to close Excel itself.
I've checked that CSV.Close is doing what it's supposed to from the VBA side; it's not causing a runtime error, and certainly the file is no longer available to be written to after that instruction.
My project is early bound to the Microsoft Scripting Runtime, scrrun.dll. I've tried removing that reference but I get the same result.
This is not a showstopper for the project, but it's a PITA during development. Anybody know what's going on?
Try this simple example - the file is available for editing through e.g. Notepad, after the code has run:
Option Explicit
Sub Test()
Dim objFSO As New FileSystemObject
Dim objStream As TextStream
Dim i As Integer
Set objStream = objFSO.CreateTextFile("D:\temp.txt")
With objStream
For i = 1 To 10
.WriteLine CStr(i)
Next i
.Close
End With
Set objStream = Nothing
Set objFSO = Nothing
End Sub

Changing the Folder security permissions using Excel VBA

I am trying to write some code to put a text file into a secure folder. The folder has attributes already set to read-only so that the files within are secure and cannot be altered but still read.
The FileSystemObject will allow me to use the attribute property which I can set to 1 (read-only) but this is easily overridden.
My next port of call was to GetAclInformation etc.
I downloaded some code and I got through a large portion of it but, at GetAclInformation it crashes Excel.
I then continued to look and so used the ADsSecurity dll. This returns an error stating
the ActiveX cannot create the object.
I have downloaded a copy of the dll and put it into the windows\syswow64 directory and then registered it with RegSvr32 which returned a success.
I can add the references required and see the object in the object viewer. But trying both late and early binding has no affect and it still errors saying the ActiveX cannot create the object.
Does anyone have any other ideas or a suggestion on what to try?
Sub TestApproval()
Dim oSec As New ADsSecurity
Dim oSd As Object, oDac1 As Object, oAce As Object
Set oSec = New ADsSecurity
Set oSd = oSec.GetSecurityDescriptor(CStr("FILE://C:\Test"))
Set oDac1 = oSd.DiscretionaryAcl
For Each oAce In oDac1
Debug.Print oAce.trustee & "|" & oAce.AceType & "|" & oAce.AccessMask & "|" & oAce.AceFlags & "|" & oAce.Flags & "|" & oAce.ObjectType & "|" & oAce.InheritedObjectType
Next oAce
Set oSec = Nothing
Set oSd = Nothing
Set oDac1 = Nothing
End Sub
Thanks in advance :)

VBA excel: how to add text to all files on a folder

I need to add text string to all files on a folder, as a footer
For example, on the folder on the path and called C:\mobatchscripts\
I have a random number of txt files, with text.
I want to add a line for example "text" on each of the text files on the folder
I have little knowledge of vba programming, but for what I have read I can use append, but I need something that loop on the files on the folder, and modify them.
So far I tried this:
Sub footer()
Dim FolderPath As String
Dim FileName As String
Dim wb As Excel.Workbook
FolderPath = "C:\mobatchscripts\"
FileName = Dir(FolderPath)
Do While FileName <> ""
Open FileName For Append As #1
Print #1, "test"
Close #1
FileName = Dir
Loop
End Sub
But seems that its not looking into the files, or appending the text.
On the assumption that you're writing to text files (I see "batchscripts" in the path), you need a reference to the Microsoft Scripting Runtime (Within the VBE you'll find it in Tools, References)
Option Explicit
Public Sub AppendTextToFiles(strFolderPath As String, _
strAppendText As String, _
blnAddLine As Boolean)
Dim objFSO As FileSystemObject
Dim fldOutput As Folder
Dim filCurrent As File
Dim txsOutput As TextStream
Set objFSO = New FileSystemObject
If objFSO.FolderExists(strFolderPath) Then
Set fldOutput = objFSO.GetFolder(strFolderPath)
For Each filCurrent In fldOutput.Files
Set txsOutput = filCurrent.OpenAsTextStream(ForAppending)
If blnAddLine Then
txsOutput.WriteLine strAppendText
Else
txsOutput.Write strAppendText
End If
txsOutput.Close
Next
MsgBox "Wrote text to " & fldOutput.Files.Count & " files", vbInformation
Else
MsgBox "Path not found", vbExclamation, "Invalid path"
End If
End Sub
I'd recommend adding error handling as well and possibly a check for the file extension to ensure that you're writing only to those files that you want to.
To add a line it would be called like this:
AppendTextToFiles "C:\mobatchscripts", "Test", True
To just add text to the file - no new line:
AppendTextToFiles "C:\mobatchscripts", "Test", False
Alternatively, forget the params and convert them to constants at the beginning of the proc. Next time I'd recommend working on the wording of your question as it's not really very clear what you're trying to achieve.