I Have below simple script from heyscriptingguy.
The problem is the strContents is consider as Junk value 'ÿ_[
http://blogs.technet.com/b/heyscriptingguy/archive/2005/10/21/how-can-i-read-a-text-file-on-a-remote-computer.aspx
Junk value: 'ÿ_[
From scripting edit tool.i can see this value
Full Script is:
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile _
("\\USCOLB1\d$\LOG\log.txt", ForReading)
strContents = objTextFile.ReadAll
objTextFile.Close
Wscript.Echo strContents
What is wrong here? The same script works perfect in LAB
The 'yunk' is probably the UTF-16 ByteOrderMark (BOM) and the file should be opened with the fourth (format/encoding) parameter of the .OpenTextFile method set to 1/TriStateTrue/Unicode (Docs)
Related
I have a folder contain texts files . The text is presented as below :
NAME Number Mail Date
xx 1 zz //
and I want to write a vba code that read all the text files and search for an information "NAME" to replace it with "name"and then save the modifications .
I did the code below , but I have an error 70 permission denied in Set f = FSO.OpenTextFile(Fichier, forWriting, True) ,
could you help me ?
Sub Sample()
dim fso=createobject("scripting.filesystemObject")
dim f
dim path as string
dim file_txt as string
path= "C:\Users\Folder\Fileshere\"
file_txt= Dir(path & "*.*")
Do While Len(file_txt) > 0
'Set objfile = FSO.CreateTextFile(path & file_txt)
Set f = FSO.OpenTextFile(file_txt, ForReading)
While Not f.AtEndOfStream
Namechange = f.ReadAll
Wend
Namechange = Replace(Namechange , "NAME", "name")
Set f = FSO.OpenTextFile(file_txt, forWriting, True)
f.Write Namechange
file_txt=dir()
loop
end sub
I'd rewrite using a bit more of the FileSystemObject functionality rather than using Dir() personally, but that's open to your own choice. The key issue I think you are having is that you have opened the file for reading and then immediately tried to open it for writing while the TextStream object is still in memory, and locking the file. This is why you are getting "Permission denied". To quote from a TechNet Article:
Opening Text Files
Working with text files is a three-step process.
Before you can do anything else, you must open the text file. This can
be done either by opening an existing file or by creating a new text
file. (When you create a new file, that file is automatically opened
and ready for use.) Either approach returns a reference to the
TextStream object. After you have a reference to the TextStream
object, you can either read from or write to the file. However, you
cannot simultaneously read from and write to the same file. In other
words, you cannot open a file, read the contents, and then write
additional data to the file, all in the same operation. Instead, you
must read the contents, close the file, and then reopen and write the
additional data. When you open an existing text file, the file can be
opened either for reading or for writing. When you create a new text
file, the file is open only for writing, if for no other reason than
that there is no content to read. Finally, you should always close a
text file. Although this is not required (the file will generally be
closed as soon as the script terminates), it is good programming
practice.
My code should work for your requirements. I've removed the While loop from the middle as if you are using ReadAll then you don't need to loop over the text.
Sub MySub()
Dim fso
Set fso = CreateObject("scripting.filesystemObject")
Dim file, folder
Dim path As String
Dim file_txt As String
path = "C:\users\folders\fileshere\"
Set folder = fso.GetFolder(path)
For Each file In folder.Files
Set file = fso.OpenTextFile(file.Path, 1)
Namechange = file.ReadAll
file.Close
Namechange = Replace(Namechange, "NAME", "name")
Set file = fso.OpenTextFile(file.Path, 2, True)
file.Write Namechange
file.Close
Next
End Sub
If you have any difficulties or would like further explanation of the above, let me know.
Some minor changes and it worked for me. Please change the path as per your own requirement in following code:
Sub change_txt()
Dim fso As Object
Set fso = CreateObject("scripting.filesystemObject")
Dim f
Dim path As String
Dim file_txt As String
path = "D:\Folder\Fileshare\"
file_txt = Dir(path & "*.*")
Do While Len(file_txt) > 0
'Set objfile = FSO.CreateTextFile(path & file_txt)
Set f = fso.opentextfile(path & file_txt, 1)
While Not f.AtEndOfStream
Namechange = f.ReadAll
Wend
Namechange = Replace(Namechange, "NAME", "name")
Set f = fso.opentextfile(path & file_txt, 2)
f.Write Namechange
file_txt = Dir()
Loop
End Sub
I was wondering if there's a way in Access VBA to open a text file, and append data to the end of each line, at a specific column / space?
Basically, I need to open the text file and place a character at column # 300 of each line in the file (which is after all of the data).
I know I could just import the data into Access, add the column, and then export it, but for business reasons I'm trying to avoid this.
Thanks!
You can accomplish this using the Microsoft Scripting Runtime library. Add a reference to that library in your VBA project.
Here is a procedure that will append a delimiter (I've used a comma in my sample) to the end of each record in the text file.
Private Const DELIMITER As String = "," 'this is the text file delimiter that will add a column
Private Const FILE_PATH As String = "C:\temp\" 'this is the directory where the text file resides
Private Sub AppendColumnToTextFile()
Dim fso As New FileSystemObject
Dim readStream As Scripting.TextStream
Dim writeStream As Scripting.TextStream
'this is the name of the text file that needs a column appended
Dim currentFile As String: currentFile = "Test.csv"
'this is a temp text file where we'll re-write each record with an additional column
Dim tempFile As String: tempFile = "Test.New.csv"
'set the read/write streams
Set readStream = fso.OpenTextFile(FILE_PATH & currentFile, ForReading)
Set writeStream = fso.OpenTextFile(FILE_PATH & tempFile, ForWriting, True)
'read each line of the text file, and add a deilimeter at the end
Do While Not readStream.AtEndOfStream
writeStream.WriteLine readStream.ReadLine & DELIMITER
Loop
'close the streams
readStream.Close
writeStream.Close
fso.CopyFile FILE_PATH & tempFile, FILE_PATH & currentFile, True 'copy the temp file to the original file path
Kill FILE_PATH & tempFile 'delete the temp file
Set writeStream = Nothing
Set appendStream = Nothing
Set fso = Nothing
End Sub
I figure that I could post this as a unique way of returning output as text instead of integers to see if this can help others that are having the same issue as I am having.
What I'm trying to accomplish is holding the output of the command, but then channeling a specific output out as a text instead of being interger based.
Here's what I have so far, and I'm currently stuck on filtering the output. I know that I can use the mid command, but since the output in general from this command is fluid, I can't use mid to count specific characters.
The command in question is PowerShell.exe manage-bde -status C:
The output is this:
Volume C: [OSDisk]
[OS Volume]
Size: 118.24 GB
BitLocker Version: Windows 7
Conversion Status: Fully Encrypted
Percentage Encrypted: 100%
Encryption Method: AES 256
Protection Status: Protection On
Lock Status: Unlocked
Identification Field: None
Key Protectors:
Numerical Password
TPM
I need to pull some information from say for instance Conversion Status. I want it to tell me if it's 100%, or 0%...or whatever it is. I can't seem to pull just that line.
Here's what I have so far.
dim outputArray
dim inputText
dim message
Dim strText
Set objShell = WScript.CreateObject("WScript.Shell")
Set objExecObject = ObjShell.Exec("PowerShell.exe manage-bde"" -status C:")
Do While Not objExecObject.StdOut.AtEndOfStream
strText = objExecObject.StdOut.ReadLine()
inputText = strText
outputArray = split(inputText,"Converstion Status:")
for each x in outputArray
message = message & x & vbCRLF
next
msgbox message
Loop
This does a line by line pull, and I know that Conversion Status is the 3rd line, so maybe something to that effect of channeling that line and echoing the 100% to a variable that I can store as a separate output.
Update: I decided not to go through the approach of parsing the output to a text file. There has to be a better way and shorter code to accomplish this methodology, plus if Bitlocker variables get changed around on the output, my line methodology might not work.
I'm now trying to see if I can use the for /F search approach to find the string and set the variable. The goal for me to do all of this is to add it to a registry key that will contain these values for reporting
Here's my revised code.
dim outputArray
dim inputText
dim message
Dim strText
dim line
dim testCase
dim strConversion
dim Currentline
Set objShell = WScript.CreateObject("WScript.Shell")
Set objExecObject = ObjShell.Exec("PowerShell.exe manage-bde"" -status C:")
Do While Not objExecObject.StdOut.AtEndOfStream
strText = objExecObject.StdOut.ReadLine()
strConversion = "for /F ""delims="" %%a in (strText) do do findstr /M /i /C:'Conversion' C:\%i var=%%a"
Wscript.echo strConversion
Loop
This does a line by line pull, and I know that Conversion Status is the 3rd line, so maybe something to that effect of channeling that line and echoing the 100% to a variable that I can store as a separate output.
Update: I decided not to go through the approach of parsing the output to a text file. There has to be a better way and shorter code to accomplish this methodology, plus if Bitlocker variables get changed around on the output, my line methodology might not work.
I'm now trying to see if I can use the for /F search approach to find the string and set the variable. The goal for me to do all of this is to add it to a registry key that will contain these values for reporting.
Here's my revised code.
dim outputArray
dim inputText
dim message
Dim strText
dim line
dim testCase
dim strConversion
dim Currentline
Set objShell = WScript.CreateObject("WScript.Shell")
Set objExecObject = ObjShell.Exec("PowerShell.exe manage-bde"" -status C:")
Do While Not objExecObject.StdOut.AtEndOfStream
strText = objExecObject.StdOut.ReadLine()
strConversion = "for /F ""delims="" %%a in (strText) do findstr /M /i /C:'Conversion' C:\%i var=%%a"
Wscript.echo strConversion
Loop
So far when running it, it parrots back the line back 14 times which is the number of lines when you run the command straight. So, it is seeing it, just not fully parsing the data. "Conversion" is one the strings that I'm having it check for.
Another reason I don't want to do longer code is this is part of a script that already has quite a few lines, and this will be a final sub process.
Try to store the output into array like this code :
Option Explicit
Dim arrData,Data
If Not WScript.Arguments.Named.Exists("elevate") Then
CreateObject("Shell.Application").ShellExecute WScript.FullName _
,WScript.ScriptFullName & " /elevate", "", "runas", 1
WScript.Quit
End If
arrData = Run_PS_Script
MsgBox arrData(6)
'To get all data from this loop For...Next
For Each Data in arrData
MsgBox Data
Next
'*****************************************************************
Function Run_PS_Script()
Dim WshShell,Command,PSFile,ret,fso,file,text,Temp
Set WshShell = CreateObject("WScript.Shell")
Temp = WshShell.ExpandEnvironmentStrings("%Temp%")
Command = "cmd /c echo manage-bde -status C: ^|" &_
"Out-File %temp%\output.txt -Encoding ascii > %temp%\PSFile.ps1"
PSFile = WshShell.Run(Command,0,True)
ret = WshShell.Run("powershell.exe -ExecutionPolicy Unrestricted -File %temp%\PSFile.ps1",0,True)
Set fso = CreateObject("Scripting.FileSystemObject")
text = ReadFile(Temp &"\output.txt","byline")
Run_PS_Script=text
End Function
'*****************************************************************
Function ReadFile(path,mode)
Const ForReading = 1
Const TriStateUseDefault = -2
Dim objFSO,objFile,i,contents,strLine
Set objFSO = CreateObject("Scripting.FileSystemObject")
If mode = "unicode" Then
Set objFile = objFSO.opentextfile(path,,,true)
contents = objFile.ReadAll
ReadFile = contents
objFile.Close
End If
If mode = "byline" then
Set objFile = objFSO.OpenTextFile(path,ForReading)
Dim arrFileLines()
i = 0
Do Until objFile.AtEndOfStream
Redim Preserve arrFileLines(i)
strLine = objFile.ReadLine
strLine = Trim(strLine)
If Len(strLine) > 0 Then
arrFileLines(i) = strLine
i = i + 1
ReadFile = arrFileLines
End If
Loop
objFile.Close
End If
If mode = "all" Then
Set objFile = objFSO.OpenTextFile(path,ForReading)
contents = objFile.ReadAll
ReadFile = contents
objFile.Close
End If
End Function
'*****************************************************************
Okay, I want to post another variation again. How about this?
dim outputArray
dim inputText
dim message
Dim strText
Dim MyArray
conversion = "Conversion Status:"
Set objShell = WScript.CreateObject("WScript.Shell")
Set objExecObject = ObjShell.Exec("PowerShell.exe manage-bde"" -status C:")
Do While Not objExecObject.StdOut.AtEndOfStream
strText = objExecObject.StdOut.ReadLine()
inputText = strText
outputArray = split(inputText,"Conversion Status:")
for each i in outputArray
output = i
next
position = InStr(1, strText,conversion, 1)
msgbox position
Loop
I've got it now where it will return the 0 or 5 value for the line. How can I convert the 5 response back to actual text that came from that line?
Here is an example of pulling values from an array of strings in VBS:
' let us mock out our expected data returned from the disk
Dim sampleData(100)
sampleData(0) = "Volume C: [OSDisk]"
sampleData(1) = "[OS Volume]"
sampleData(2) = ""
sampleData(3) = " Size: 118.24 GB"
sampleData(4) = " BitLocker Version: Windows 7"
sampleData(5) = " Conversion Status: Fully Encrypted"
sampleData(6) = " Percentage Encrypted: 100%"
sampleData(7) = " Encryption Method: AES 256"
sampleData(8) = " Protection Status: Protection On"
sampleData(9) = " Lock Status: Unlocked"
sampleData(10) = " Identification Field: None"
sampleData(11) = " Key Protectors:"
sampleData(12) = " Numerical Password"
sampleData(13) = " TPM"
'create a function to parse out the values you want
Function returnValueFromData(sampleData,fieldName)
For each infoLine in sampleData
If InStr(infoline,fieldName) Then
infoline = Trim(Replace(infoline,fieldName,""))
returnValueFromData = infoline
End If
Next
End Function
'now, we can use our function above to grab whatever field we want
'get the size of the disk
dim size
size = returnValueFromData(sampleData,"Size:")
wscript.echo size
'get the lock status of the disk
dim lockStatus
lockStatus = returnValueFromData(sampleData,"Lock Status:")
wscript.echo lockStatus
'shorthand to get the encryption algorithm
wscript.echo returnValueFromData(sampleData,"Encryption Method:")
currently i have an Email that comes in and my vba code will save the file to a folder, however since this code was made they now send me the file in a zip file. This of course breaks the code and i have to resend it in a non zip file to make it work. Here is a sample of what I am currently using:
If Left(objItem.Subject, 28) = "xxxxx report Toolbox" Then
For Each Atmt In objItem.Attachments
FileName = "O:\Automated Reports\toolbox.xlsx"
Atmt.SaveAsFile FileName
modify_file
Debug.Print "success CSAT file"
Open "O:\Automated Reports\toolboxDate.JW" For Output As #1
Write #1, Right(objItem.Subject, 5)
Close #1
Next Atmt
End If
As i stated before this code woks fine for just saving the file when it is not a .zip file. I need it to unzip the file and save it to the O: drive. I have tried to use some shell.application objects but i didn't quite get that to work. Thanks for any help ahead of time
'Create new blank zip.
Set Ag=Wscript.Arguments
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.OpenTextFile(Ag(0), 8, vbtrue)
BlankZip = "PK" & Chr(5) & Chr(6)
For x = 0 to 17
BlankZip = BlankZip & Chr(0)
Next
ts.Write BlankZip
'Unzip
Set objShell = CreateObject("Shell.Application")
Set Ag=Wscript.Arguments
set WshShell = WScript.CreateObject("WScript.Shell")
Set SrcFldr=objShell.NameSpace(Ag(1))
Set DestFldr=objShell.NameSpace(Ag(0))
Set FldrItems=SrcFldr.Items
DestFldr.CopyHere FldrItems, &H214
Msgbox "Finished"
'Zip
Set objShell = CreateObject("Shell.Application")
Set Ag=Wscript.Arguments
set WshShell = WScript.CreateObject("WScript.Shell")
Set DestFldr=objShell.NameSpace(Ag(1))
Set SrcFldr=objShell.NameSpace(Ag(0))
Set FldrItems=SrcFldr.Items
DestFldr.CopyHere FldrItems, &H214
Msgbox "Finished"
Hello Scripting Experts,
I have a log file on remote servers..
in remote servers c:\vb\text.log
I have included my remote systems in list.Txt like
server1
server2
below is the sample of log..
application working
[10/23/2012 working
[10/24/2012 nos appdown
error found you need to check this
Below is my Script.
Set Fso = CreateObject("Scripting.FileSystemObject")
Set InFile = fso.OpenTextFile("list.Txt")
Set out = fso.CreateTextFile("error.log")
Const ForReading = 1
Do While Not (InFile.atEndOfStream)
strComputer = InFile.ReadLine
today = Date()
Set fso = CreateObject("Scripting.FileSystemObject")
strFilePath = "\\" & strComputer & "\c$\vb\"
Set InputFile = fso.OpenTextFile(strFilePath & "text.log", 1)
Do While Not (InputFile.AtEndOfStream)
strLine = InputFile.ReadLine
If Left(line, Len(today)+1) = "[" & today Then
' line timestamped with today's date
If InStr(line, "nos") > 0 Then
' line contains "error"
out.WriteLine InStr & vbTab & strComputer
End If
End If
Loop
InputFile.close
Loop
out.Close
InFile.Close
Basically the above script should search from current date line only from the text.log file that is [10/24/2012 nos appdown. Then if found as "Nos" in the current date line.. then it should write to the error.log with computer Name.
In my case the output is not coming , however looks like it is searching for the string "Nos".
Kindly gail break me from this situation....
The bug is that you don't specify the explicit option. Like so,
option explicit
This will force VBScript to complain about nondeclared variables. By doing this, you easily can spot misspelled variable names. Delcare variables with dim statement, like so
dim Fso, out
Run the script again and see that you are using a non-existing and non-initialized variable in comparision:
strLine = InputFile.ReadLine ' Read stuff to strLine
If Left(line, Len(today)+1) = "[" & today Then ' ERROR. line has no value!
There are several issues with your adaptation of my script:
As was already pointed out by vonPryz this is the cause of the problem:
strLine = InputFile.ReadLine
If Left(line, Len(today)+1) = "[" & today Then
When you change a variable name from file to strFile you have to change every occurrence of that variable, not just the line where it's assigned.
out.WriteLine InStr & vbTab & strComputer
This line will also fail, because InStr is a function and you don't call it with the correct number of arguments.
today = Date()
This should not be inside a loop unless you expect the date to change during the script run and need to have the current date in every loop cycle.
Set fso = CreateObject("Scripting.FileSystemObject")
fso is instantiated at the beginning of the script. There's no need to re-instantiate it, especially not in each loop cycle. That's just a waste of resources.
Const ForReading = 1
There's no point in defining a constant when you're never using it.
Do While Not ...
Using Do Until ... would be easier to read and to understand.