I have a working .vbs file which reads a binary file, changes one byte and the saves the file. Up until Windows 1607 this worked fine on many different Windows systems.
However, now with 1607 and later versions of Windows 10 it no longer works!
I have changed the code because the read file code I had no longer works correctly in 1607, but I am still having problems with the
data = Mid(data, 1, 21) & Chr(b21) & Mid(data, 23) line which worked perfectly before Windows 10 1607!
I get
(60, 3) ADODB.Stream: Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another.
This code creates a shortcut on the Desktop and then changes one bit of one byte so that the shortcut will be run as admin. If I comment out the offending line then it seems to work.
Is this a bug in Windows 10 1607 VBScript?
' Make shortcut on Desktop and Set as Run As Admin
Q = Chr(34)
Dim fso
Dim curDir
Dim WinScriptHost
If WScript.Arguments.Count < 2 Then
WScript.Echo "Please run CreateShortcuts.cmd"
WScript.Quit
End If
' --- SET Target and Desktop Link Name from command line ---
strTargetName = WScript.Arguments.Item(0)
strLinkName = WScript.Arguments.Item(1)
'Target - e.g. %windir%\system32\cmd.exe /c C:\"temp\MakePartImage_AutoRun_FAT32.cmd"
Set WshShell = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
strWinDir =WshShell.ExpandEnvironmentStrings("%windir%")
strSysDir = strWinDir & "\System32"
strMyDir = fso.GetParentFolderName(wscript.ScriptFullName)
strDesktop = WshShell.SpecialFolders("Desktop")
strCurDir = WshShell.CurrentDirectory ' e.g. C:\temp
strMyDirSpecial = Mid(strMyDir, 1, 3) & Q & Mid(strMyDir, 4) & "\" & strTargetName & Q
Set oMyShortCut= WshShell.CreateShortcut(strDesktop + "\" & strLinkName)
oMyShortCut.WindowStyle = 1 '1=default 3=max 7=Min
oMyShortCut.TargetPath = Q & strSysDir & "\cmd.exe" & Q
oMyShortCut.Arguments= " /c " & strMyDirSpecial
oMyShortcut.IconLocation = "%windir%\system32\cmd.exe"
oMyShortCut.WorkingDirectory = Q & strMyDir & Q
oMyShortCut.Save
Set fso = Nothing
'read binary geometry into byte array
Dim stream, data
Set stream = CreateObject("ADODB.Stream")
stream.Open
stream.Type = 1
stream.LoadFromFile(strDesktop + "\" & strLinkName)
data = stream.Read
stream.Close
WScript.Echo "BYTES 16-23 " & Hex(Asc(Mid(data, 16, 1))) & " " & Hex(Asc(Mid(data, 17, 1))) & " " & Hex(Asc(Mid(data, 18, 1))) & " " & Hex(Asc(Mid(data, 19, 1))) & " " & Hex(Asc(Mid(data, 20, 1))) & " " & Hex(Asc(Mid(data, 21, 1))) & " " & Hex(Asc(Mid(data, 22, 1))) & " " & Hex(Asc(Mid(data, 23, 1)))
' --- PATCH .LNK FILE to set byte 21 bit 5 for Admin rights
Dim b21
b21 = Asc(Nid(data, 22, 1)) Or 32 'set bit 6 0x20
' THIS NEXT LINE CAUSES PROBLEMS!
data = Mid(data, 1, 21) & Chr(b21) & Mid(data, 23)
WScript.Echo "BYTES 16-23 " & Hex(Asc(Mid(data, 16, 1))) & " " & Hex(Asc(Mid(data, 17, 1))) & " " & Hex(Asc(Mid(data, 18, 1))) & " " & Hex(Asc(Mid(data, 19, 1))) & " " & Hex(Asc(Mid(data, 20, 1))) & " " & Hex(Asc(Mid(data, 21, 1))) & " " & Hex(Asc(Mid(data, 22, 1))) & " " & Hex(Asc(Mid(data, 23, 1)))
Const adTypeBinary = 1
Const adTypeText = 2
Const adSaveCreateOverWrite = 2
Dim BinaryStream
Set BinaryStream = CreateObject("ADODB.Stream")
BinaryStream.Type = adTypeBinary
BinaryStream.Open
BinaryStream.Write data
BinaryStream.SaveToFile strDesktop+"\" & strLinkName, adSaveCreateOverWrite
WScript.Echo "Shortcut " & strLinkName & " created on Desktop."
' THIS NEXT LINE CAUSES PROBLEMS!
data = Mid(data, 1, 21) & Chr(b21) & Mid(data, 23)
This line causes problems because it changes the type of data from Byte() to String. This would illustrate it:
WScript.Echo TypeName(data)
' THIS NEXT LINE CAUSES PROBLEMS!
data = Mid(data, 1, 21) & Chr(b21) & Mid(data, 23)
WScript.Echo TypeName(data)
ADODB Stream.Write function only accepts Byte() arrays.
The solution is to use this function from motobit website:
' http://www.motobit.com/tips/detpg_binarytostring/
Function MultiByteToBinary(MultiByte)
'� 2000 Antonin Foller, http://www.motobit.com
' MultiByteToBinary converts multibyte string To real binary data (VT_UI1 | VT_ARRAY)
' Using recordset
Dim RS, LMultiByte, Binary
Const adLongVarBinary = 205
Set RS = CreateObject("ADODB.Recordset")
LMultiByte = LenB(MultiByte)
If LMultiByte>0 Then
RS.Fields.Append "mBinary", adLongVarBinary, LMultiByte
RS.Open
RS.AddNew
RS("mBinary").AppendChunk MultiByte & ChrB(0)
RS.Update
Binary = RS("mBinary").GetChunk(LMultiByte)
End If
MultiByteToBinary = Binary
End Function
But the string needs to be converted to multi-byte first. For this purpose there is another function:
' http://www.motobit.com/help/regedit/pa26.htm
'Converts unicode string to a multibyte string
Function StringToMB(S)
Dim I, B
For I = 1 To Len(S)
B = B & ChrB(Asc(Mid(S, I, 1)))
Next
StringToMB = B
End Function
So, this is how to make it work:
data = Mid(data, 1, 21) & Chr(b21) & Mid(data, 23)
data = MultiByteToBinary(StringToMB(data))
Related
What I'm trying to achieve here is getting the two folder size values of objLibrarySource and objLibraryDest and using an if statement to compare the two filesize's and if they equal each other pipe this to the textfile ->
objFile.WriteLine "Match". But my issue is im only getting the value for arrayList(0) and not arrayList(1)
Code:
myArray = Array(objLibrarySource, objLibraryDest)
For Each item In myArray
Set objFolder = objFSO.GetFolder(item)
totalSize = objFolder.Size / 1073741824
arrayList = Array()
arrayList = AddItem(arrayList, totalSize)
arrayList = Split(Join(arrayList) & " ")
objFile.WriteLine objFolder & " File Size: " & Round(totalSize, 2) & " GB"
If (arrayList(0) = arrayList(1)) Then
objFile.WriteLine "Match"
End If
Next
objFile.WriteLine arrayList(0) & vbCrLf
objFile.WriteLine arrayList(1)
Function AddItem(arr, val)
ReDim Preserve arr(UBound(arr) + 1)
arr(UBound(arr)) = val
AddItem = arr
End Function
Output:
D:\LIBRARY_TEST File Size: 7.01 GB
D:\seed_backup\LIBRARY File Size: 7.01 GB
7.01436613406986
I had to refactor my code to
Dim libsizesrc, libsizedst, libsizesrcSize, libsizedstSize
Set libsizesrc = objFSO.GetFolder(objLibrarySource)
Set libsizedst = objFSO.GetFolder(objLibraryDest)
libsizesrcSize = libsizesrc.Size / 1073741824
libsizedstSize = libsizedst.Size / 1073741824
objFile.WriteLine libsizesrc & " File Size: " & Round(libsizesrcSize, 2) & " GB"
objFile.WriteLine libsizedst & " File Size: " & Round(libsizedstSize, 2) & " GB"
'Source & Dest SMPDevices Sizes
Dim SMPsizesrc, SMPsizedst, SMPsizesrcSize, SMPsizedstSize
Set SMPsizesrc = objFSO.GetFolder(objSMPDriversSource)
Set SMPsizedst = objFSO.GetFolder(objSMPDriversDest)
SMPsizesrcSize = SMPsizesrc.Size / 1073741824
SMPsizedstSize = SMPsizedst.Size / 1073741824
objFile.WriteLine SMPsizesrc & " File Size: " & Round(SMPsizesrcSize, 2) & " GB"
objFile.WriteLine SMPsizedst & " File Size: " & Round(SMPsizedstSize, 2) & " GB"
'Library & Source Folder Size Verification
If (libsizesrcSize = libsizedstSize) Then
objFile.Write "Library Folder FileSize Match!" & vbCrLf
End If
If (SMPsizesrcSize = SMPsizedstSize) Then
objFile.Write "SMPDrivers Folders FileSize Match!"
End If
it work as needed!
I want to output selected parameters from movie files.
I'm doing this in that way:
arrGeneral = Array("General;Video Format List: %Video_Format_List%","General;File name: %FileNameExtension%","General;Commercial name: %Format_Commercial%")
arrVideo = Array("Video;ID: %ID%","Video;Format: %Format/String%","Video;Format info: %Format/Info%","Video;Format profile: %Format_Profile%","Video;Bit rate: %BitRate/String%")
arrAudio = Array("Audio;ID: %ID%\n","Audio;Format: %Format%\n","Audio;Format info: %Format/Info%\n","Audio;Commercial name: %Format_Commercial%\n","Audio;Codec ID: %CodecID%\n")
arrText = Array("Text;ID: %ID%\n","Text;Format: %Format/String%\n","Text;Codec ID: %CodecID/Info%\n","Text;Title: %Title%\n","Text;Language: %Language/String%\n")
' == General section ==
objFileToWrite.Write "General" & vbCrLf
for i = 0 to UBound(arrGeneral)
commandToRun = chr(34) & ProgramToExecute & chr(34) & " --Output=" & chr(34) & arrGeneral(i) & chr(34) & " " & chr(34) & InVideoFile & chr(34)
result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
objFileToWrite.Write result
next
objFileToWrite.Write "----------" & vbCrLf
' == Video section ==
objFileToWrite.Write "Video" & vbCrLf
for i = 0 to UBound(arrVideo)
commandToRun = chr(34) & ProgramToExecute & chr(34) & " --Output=" & chr(34) & arrVideo(i) & chr(34) & " " & chr(34) & InVideoFile & chr(34)
result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
objFileToWrite.Write result
next
objFileToWrite.Write "----------" & vbCrLf
' == Audio section ==
' Here is a problem beacuse it might be more than 1 Audio stream
objFileToWrite.Write "Audio" & vbCrLf
for i = 0 to UBound(arrAudio)
commandToRun = chr(34) & ProgramToExecute & chr(34) & " --Output=" & chr(34) & arrAudio(i) & chr(34) & " " & chr(34) & InVideoFile & chr(34)
result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
objFileToWrite.Write result
next
objFileToWrite.Write "----------" & vbCrLf
For General and Video streams these commands (examples):
MediaInfo.exe --Output="General;Video Format List: %Video_Format_List%" "Sample.mkv"
MediaInfo.exe --Output="Video;Format info: %Format/Info%" "Sample.mkv"
are generating single line results like for instance:
Video Format List: HEVC
Format info: High Efficiency Video Coding
so my script is properly creating output file that contain:
General
Video Format List: HEVC
File name: Sample.mkv
Commercial name: Matroska
Format version: Version 4
File size: 10.03 GiB
Duration: 1 h 52 min 15 s 744 ms
Overall bit rate: 12.8 Mb/s
----------
Video
ID: 1
Format: HEVC
Format info: High Efficiency Video Coding
Format profile: Main 10#L4#Main
Bit rate: 8 525 kb/s
Width: 1 920 pixels
Height: 1 080 pixels
Display aspect ratio: 1.778
Display aspect ratio: 16:9
Frame rate mode: Constant
Frame rate: 23.976 (24000/1001) FPS
Color space: YUV
Chroma subsampling: 4:2:0
Bit depth: 10 bits
Video stream size: 6.68 GiB (67%)
----------
But for the Audio and Text (subtitle) there might be more than one stream and the single command:
MediaInfo.exe --Output="Audio;Format info: %Format/Info%\n" "Sample.mkv"
is generating two or more lines (depends on how many streams movie file contain) like this:
Format info: Digital Theater Systems
Format info: Audio Coding 3
As the result in output file I'm getting something like this:
Audio
ID: 2
ID: 3
Format: DTS
Format: AC-3
Format info: Digital Theater Systems
Format info: Audio Coding 3
Commercial name: DTS-HD Master Audio
Commercial name: Dolby Digital
Codec ID: A_DTS
Codec ID: A_AC3
Bit rate: 3 958 kb/s
Bit rate: 192 kb/s
but expected result is:
Audio #2
ID: 2
Format: DTS
Format info: Digital Theater Systems
Commercial name: DTS-HD Master Audio
Codec ID: A_DTS
Bit rate: 3 958 kb/s
Audio #3
ID: 3
Format: AC-3
Format info: Audio Coding 3
Commercial name: Dolby Digital
Codec ID: A_AC3
Bit rate: 192 kb/s
I think it would be necessary to insert "multiline" results of Audio and Text streams into some dynamic arrays and in the next step to go through them and insert into output file "sorted" values or the second option is to sort final output file but in both cases but I have no clue how to do that.
Here is the vbs script that can be used to collect selected attributes:
InVideoFile = "C:\Temp\Sample.mkv"
InVideoFile = replace(InVideoFile,chr(34),"")
inFile = Left(InVideoFile, Len(InVideoFile) -4) & "-All.txt"
outFile = Left(inFile, Len(inFile) -4) & "-MediaInfo.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")
if objFSO.FileExists(inFile) then
objFSO.DeleteFile inFile
end if
' MediaInfo.exe location below in ProgramToExecute variable
' MediaInfo.exe (Interface CLI) download location: https://mediaarea.net/en/MediaInfo/Download/Windows
ProgramToExecute = "C:\Program Files\MediaInfo\MediaInfo_CLI\MediaInfo.exe"
commandToRun = "cmd /C " & chr(34) & chr(34) & ProgramToExecute & chr(34) & " -f " & chr(34) & InVideoFile &chr(34) & " > " &chr(34) & inFile &chr(34) & chr(34)
Dim objShell
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run commandToRun,1,true
Set objShell = Nothing
Set objFileToRead = objFSO.OpenTextFile(inFile, 1)
Set objFileToWrite = objFSO.CreateTextFile(outFile,True)
Dim arrGeneral
Dim arrVideo
Dim arrAudio
Dim arrText
' Attributes that are need to be collected are taken from the result of command MediaInfo.exe --Info-Parameters
' Arrays elements are build in the following way:
' section;Text %Attribute%Delimiter
' examples:
' "General;Video Format List: %Video_Format_List%"
' "Video;Format profile: %Format_Profile%"
' "Audio;Channel(s): %Channel(s)/String%|"
' "Text;Format: %Format/String%|"
' Audio and Text sections might contain more than one stream. Result is delimited by "|" character (can be used another) and later on is split
arrGeneral = Array("General;Video Format List: %Video_Format_List%","General;File name: %FileNameExtension%","General;Commercial name: %Format_Commercial%","General;Format version: %Format_Version%","General;File size: %FileSize/String4%","General;Duration: %Duration/String1%","General;Overall bit rate: %OverallBitRate/String%")
arrVideo = Array("Video;ID: %ID%","Video;Format: %Format/String%","Video;Format info: %Format/Info%","Video;Format profile: %Format_Profile%","Video;Bit rate: %BitRate/String%","Video;Width: %Width/String%","Video;Height: %Height/String%","Video;Display aspect ratio: %DisplayAspectRatio/String%","Video;Frame rate mode: %FrameRate_Mode/String%","Video;Frame rate: %FrameRate/String%","Video;Color space: %ColorSpace%","Video;Chroma subsampling: %ChromaSubsampling/String%","Video;Bit depth: %BitDepth/String%","Video;Video stream size: %StreamSize/String5%","Video;Colour primaries: %colour_primaries%","Video;Transfer characteristices: %transfer_characteristics%","Video;Matrix coefficients: %matrix_coefficients%")
arrAudio = Array("Audio;ID: %ID%|","Audio;Format: %Format%|","Audio;Format info: %Format/Info%|","Audio;Commercial name: %Format_Commercial%|","Audio;Codec ID: %CodecID%|","Audio;Bit rate: %BitRate/String%|","Audio;Channel(s): %Channel(s)/String%|","Audio;Channel positions: %ChannelPositions%|","Audio;Channel layout: %ChannelLayout%|","Audio;Sampling rate: %SamplingRate/String%|","Audio;Bit depth: %BitDepth/String%|","Audio;Compression mode: %Compression_Mode/String%|","Audio;Audio stream size: %StreamSize/String5%|","Audio;Title: %Title%|","Audio;Language: %Language/String%|","Audio;Default: %Default/String%|","Audio;Forced: %Forced/String%|")
arrText = Array("Text;ID: %ID%|","Text;Format: %Format/String%|","Text;Codec ID: %CodecID/Info%|","Text;Title: %Title%|","Text;Language: %Language/String%|","Text;Default: %Default/String%|","Text;Forced: %Forced/String%|")
' == General section ==
objFileToWrite.Write "General" & vbCrLf
for i = 0 to UBound(arrGeneral)
commandToRun = chr(34) & ProgramToExecute & chr(34) & " --Output=" & chr(34) & arrGeneral(i) & chr(34) & " " & chr(34) & InVideoFile & chr(34)
result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
resultNoCRLF = Replace(result, vbCRLF, "")
if right(resultNoCRLF,2) <> ": " then
objFileToWrite.Write result
end if
next
objFileToWrite.Write "----------" & vbCrLf
' == Video section ==
objFileToWrite.Write "Video" & vbCrLf
for i = 0 to UBound(arrVideo)
commandToRun = chr(34) & ProgramToExecute & chr(34) & " --Output=" & chr(34) & arrVideo(i) & chr(34) & " " & chr(34) & InVideoFile & chr(34)
result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
resultNoCRLF = Replace(result, vbCRLF, "")
if right(resultNoCRLF,2) <> ": " then
objFileToWrite.Write result
end if
next
objFileToWrite.Write "----------" & vbCrLf
' == Audio section ==
' It might be more than 1 Audio stream
objFileToWrite.Write "Audio" & vbCrLf
for i = 0 to UBound(arrAudio)
commandToRun = chr(34) & ProgramToExecute & chr(34) & " --Output=" & chr(34) & arrAudio(i) & chr(34) & " " & chr(34) & InVideoFile & chr(34)
result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
Dim arrAudioSplit
arrAudioSplit = Split(result,"|")
ReDim Preserve arrA(UBound(arrAudio),UBound(arrAudioSplit)-1)
for z = 0 to UBound(arrAudioSplit)-1
arrA(i,z) = arrAudioSplit(z)
next
next
for j = 0 to Ubound(arrAudioSplit) - 1
for k = 0 to Ubound(arrAudio)
if right(arrA(k,j),2) <> ": " then
objFileToWrite.Write arrA(k,j) & vbCrLf
end if
next
objFileToWrite.Write "----------" & vbCrLf
next
' == Text (subtitles) section ==
' It might be more than 1 Text stream
objFileToWrite.Write "Text" & vbCrLf
for i = 0 to UBound(arrText)
commandToRun = chr(34) & ProgramToExecute & chr(34) & " --Output=" & chr(34) & arrText(i) & chr(34) & " " & chr(34) & InVideoFile & chr(34)
result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
Dim arrTextSplit
arrTextSplit = Split(result,"|")
ReDim Preserve arrT(UBound(arrText),UBound(arrTextSplit)-1)
for z = 0 to UBound(arrTextSplit)-1
arrT(i,z) = arrTextSplit(z)
next
next
for j = 0 to Ubound(arrTextSplit) - 1
for k = 0 to Ubound(arrText)
if right(arrT(k,j),2) <> ": " then
objFileToWrite.Write arrT(k,j) & vbCrLf
end if
next
objFileToWrite.Write "----------" & vbCrLf
next
' == Menu (Chapters) section ==
' Have to be handled in different way by checking result of the command MediaInfo.exe -f inputfile
Set objFileToRead = objFSO.OpenTextFile(inFile, 1)
startReadingMenu = false
menuNextLine = 1
do while not objFileToRead.AtEndOfStream
strLineOriginal = Trim(objFileToRead.ReadLine())
MenuNextLine = MenuNextLine + 1
if Left(strLineOriginal,16) = "Chapters_Pos_End" then
startReadingMenu = true
MenuNextLine = 0
end if
if startReadingMenu then
objFileToWrite.Write "Chapters" & vbCrLf
startReadingMenu = false
end if
if MenuNextLine = 1 then
objFileToWrite.Write strLineOriginal & vbCrLf
MenuNextLine = 0
end if
loop
' Close files
objFileToRead.Close
Set objFileToRead = Nothing
objFileToWrite.Close
Set objFileToWrite = Nothing
' Dislay result file in notepad
DisplayInNotepad = "notepad.exe " & chr(34) & outFile &chr(34)
commandToRun = "cmd /C " & DisplayInNotepad
Dim objSh
Set objSh = WScript.CreateObject("WScript.Shell")
objSh.Run commandToRun,0,true
Set objSh = Nothing
' Cleanup
if objFSO.FileExists(inFile) then
objFSO.DeleteFile inFile
end if
if objFSO.FileExists(outFile) then
objFSO.DeleteFile outFile
end if
The only remaining issue is how to hide cmd window that is blinking when the line is invoked:
result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
but this is cosmetic issue.
This question already has answers here:
VBScript to loop through all files in a folder
(4 answers)
Closed 6 years ago.
I have this VBScript mainly for replace function for multiple text files.
Const ForReading = 1
Const ForWriting = 2
'''''''''''''''''''''''''''''''''''''''''''''''''' START OF 1st REPORTS ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("D:\rep01_" & Year(Now) & Right("0" & Month(Now), 2) & Right("0" & Day(Now - 1), 2) & ".txt", ForReading)
IF objFSO.GetFile("D:\rep01_" & Year(Now) & Right("0" & Month(Now), 2) & Right("0" & Day(Now - 1), 2) & ".txt").size <> 0 then
strText = objFile.ReadAll
objFile.Close
strNewText = Replace(strText, "$$$970A1", "SSS970A1",1,1)
strNewText1 = Replace(strNewText, "$$$979A1", "SSS979A1",1,1)
strNewText2 = Replace(strNewText1, "$$$983A1", "SSS983A1",1,1)
Set objFile = objFSO.OpenTextFile("D:\rep01_" & Year(Now) & Right("0" & Month(Now), 2) & Right("0" & Day(Now - 1), 2) & ".txt", ForWriting)
objFile.WriteLine strNewText2
objFile.Close
END IF
'''''''''''''''''''''''''''''''''''''''''''''''''' END OF 1st REPORTS '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''''''''''''''' START OF 2nd REPORTS '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("D:\rep01_UnmatchAP_" & Year(Now) & Right("0" & Month(Now), 2) & Right("0" & Day(Now - 1), 2) & ".txt", ForReading)
IF objFSO.GetFile("D:\rep01_UnmatchAP_" & Year(Now) & Right("0" & Month(Now), 2) & Right("0" & Day(Now - 1), 2) & ".txt").size <> 0 then
strText = objFile.ReadAll
objFile.Close
strNewText = Replace(strText, "$$$970A1", "SSS970A1",1,1)
strNewText1 = Replace(strNewText, "$$$979A1", "SSS979A1",1,1)
strNewText2 = Replace(strNewText1, "$$$983A1", "SSS983A1",1,1)
Set objFile = objFSO.OpenTextFile("D:\rep01_UnmatchAP_" & Year(Now) & Right("0" & Month(Now), 2) & Right("0" & Day(Now - 1), 2) & ".txt", ForWriting)
objFile.WriteLine strNewText2
objFile.Close
END IF
'''''''''''''''''''''''''''''''''''''''''''''''''' END OF 2nd REPORTS ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''''''''''''''' START OF 3rd REPORTS ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("D:\rep01_UnmatchAR_" & Year(Now) & Right("0" & Month(Now), 2) & Right("0" & Day(Now - 1), 2) & ".txt", ForReading)
IF objFSO.GetFile("D:\rep01_UnmatchAR_" & Year(Now) & Right("0" & Month(Now), 2) & Right("0" & Day(Now - 1), 2) & ".txt").size <> 0 then
strText = objFile.ReadAll
objFile.Close
strNewText = Replace(strText, "$$$970A1", "SSS970A1",1,1)
strNewText1 = Replace(strNewText, "$$$979A1", "SSS979A1",1,1)
strNewText2 = Replace(strNewText1, "$$$983A1", "SSS983A1",1,1)
Set objFile = objFSO.OpenTextFile("D:\rep01_UnmatchAR_" & Year(Now) & Right("0" & Month(Now), 2) & Right("0" & Day(Now - 1), 2) & ".txt", ForWriting)
objFile.WriteLine strNewText2
objFile.Close
END IF
'''''''''''''''''''''''''''''''''''''''''''''''''' END OF 3rd REPORTS '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''''''''''''''' START OF 4th REPORTS ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("D:\rep01_UnmatchCutOff_" & Year(Now) & Right("0" & Month(Now), 2) & Right("0" & Day(Now - 1), 2) & ".txt", ForReading)
IF objFSO.GetFile("D:\rep01_UnmatchCutOff_" & Year(Now) & Right("0" & Month(Now), 2) & Right("0" & Day(Now - 1), 2) & ".txt").size <> 0 then
strText = objFile.ReadAll
objFile.Close
strNewText = Replace(strText, "$$$970A1", "SSS970A1",1,1)
strNewText1 = Replace(strNewText, "$$$979A1", "SSS979A1",1,1)
strNewText2 = Replace(strNewText1, "$$$983A1", "SSS983A1",1,1)
Set objFile = objFSO.OpenTextFile("D:\rep01_UnmatchCutOff_" & Year(Now) & Right("0" & Month(Now), 2) & Right("0" & Day(Now - 1), 2) & ".txt", ForWriting)
objFile.WriteLine strNewText2
objFile.Close
END IF
'''''''''''''''''''''''''''''''''''''''''''''''''' END OF 4th REPORTS '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
But this kind of code is taking too long (since its a specific filename based) and repetition of the same replace function, I would like to ask for a help on how to make replace function loops for all the files in the same folder.
A big appreciation for the answer.
Set fso = CreateObject("Scripting.FileSystemObject")
Set fldr = fso.GetFolder("C:\windows")
Set Fls = fldr.files
For Each thing in Fls
msgbox thing.path
Next
also set contents = thing.readall.
Using VBScript, is there any way to allow for multiple simultaneous writes to a text file from multiple computers? I need to run a script from multiple computers at the same time. The script will perform a DEFRAG and save the results to a text file. After that, the script will read from the DEFRAG log file, pull the fragmentation percentage, and write it to another MASTER log file that is meant to contain these results from every computer across the enterprise. If I always only run the script from one computer at a time, then everything works find and dandy. However, once I use a distribution point to throw the script out to the enterprise, the script works perfectly up until the point where more than one computer attempts to access the MASTER log file at the same time. That's when I'm running into access denied errors and the like. Here's what I've got so far...
strDrivePreCheckStarted = (Year(Date) & "-" & AEZiR(Month(Date)) & "-" & AEZiR(Day(Date)) & " # " & AEZiR(Hour(Time)) & ":" & AEZiR(Minute(Time)) & ":" & AEZiR(Second(Time)))
a=("===================================================================================")
b=(" Script started on " & strDrivePreCheckStarted)
Set objWMIService = GetObject( "winmgmts:\\.\root\cimv2" )
Set colSettings = objWMIService.ExecQuery ( "Select * from Win32_ComputerSystem", , 48 )
For Each objComputer in colSettings
CompNam = objComputer.Name
If CompNam = "" Then
CompNam = "ComputerNameNotFound"
End If
CompMfr = replace(objComputer.Manufacturer,",","")
If CompMfr = "" Then
CompMfr = "ComputerMfrNotFound"
End If
CompMdl = objComputer.Model
If CompNam = "" Then
CompNam = "ComputerModelNotFound"
End If
Next
Set dClient = GetObject( "winmgmts://" & CompNam & "/root/ccm:SMS_Client" )
Set result = dClient.ExecMethod_("GetAssignedSite")
mClient = result.sSiteCode
If mClient = "OLD" Then
mClient = "SMS"
End If
If mClient = "NEW" Then
mClient = "SCCM"
End If
If mClient = "" Then
mClient = "UNKNOWN"
End If
c=(" Computer: " & "[" & mClient & "] " & CompNam & " (" & CompMfr & " " & CompMdl & ")")
Set FSO = CreateObject("Scripting.FileSystemObject")
Set wshShell = CreateObject("WScript.Shell")
Set objShell = WScript.CreateObject("WScript.Shell")
Set strWinDir = FSO.GetSpecialFolder(0)
Set strSys32 = FSO.GetSpecialFolder(1)
Set strTempDir = FSO.GetSpecialFolder(2)
strLogsDir = "\\fileserver\shared\logs\"
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Const OverwriteExisting = False
If FSO.FileExists(strLogsDir & CompNam & ".TXT") Then
WScript.Quit
Else
If FSO.FileExists(strLogsDir & CompNam & "_CHKDSK.LOG") Then
WScript.Quit
Else
If FSO.FileExists(strLogsDir & CompNam & "_DEFRAG.LOG") Then
WScript.Quit
Else
strCHKDSKStarted = (Year(Date) & "-" & AEZiR(Month(Date)) & "-" & AEZiR(Day(Date)) & " # " & AEZiR(Hour(Time)) & ":" & AEZiR(Minute(Time)) & ":" & AEZiR(Second(Time)))
d=(" CHKDSK Started: " & strCHKDSKStarted)
If FSO.FileExists(strSys32 & "\chkdsk.exe") Then
strCHKDSKReturn = objShell.Run("%COMSPEC% /c chkdsk.exe C: > " & chr(34) & strLogsDir & CompNam & "_CHKDSK.LOG" & chr(34), 0, True)
End If
If FSO.FileExists(strLogsDir & CompNam & "_CHKDSK.LOG") Then
Set ChkDskLog = FSO.OpenTextFile(strLogsDir & CompNam & "_CHKDSK.LOG", ForReading, True)
Do While ChkDskLog.AtEndOfStream <> True
Curline = ChkDskLog.ReadLine
If InStr(Curline, "KB in bad sectors.") Then
Curline = Trim(Curline)
strKBpos = InStr(1, Curline, "KB")-2
strBadKB = Left(Curline, strKBpos)
strBadKB = Trim(strBadKB)
If strBadKB > 0 Then
ChkDskFail = "Failed"
e=(" " & strBadKB & "KB Of Bad Sectors Found In Used Space")
f=(" Drive has Failed Integrity Check")
Else
ChkDskFail = "Passed"
e=(" " & strBadKB & "KB Of Bad Sectors Found In Used Space")
f=(" Drive has Passed Integrity Check")
End If
End If
Loop
If strBadKB = "" Then
ChkDskFail = "Failed"
e=(" Check Disk Log Existed But Was Incomplete: " & Date & " # " & Time)
f=(" Drive has Failed Integrity Check")
End If
Else
ChkDskFail = "Passed"
e=(" No Bad Sectors Found in Used Space")
f=(" Drive has Passed Integrity Check")
End If
ChkDskLog.Close
strCHKDSKFinished = (Year(Date) & "-" & AEZiR(Month(Date)) & "-" & AEZiR(Day(Date)) & " # " & AEZiR(Hour(Time)) & ":" & AEZiR(Minute(Time)) & ":" & AEZiR(Second(Time)))
g=(" CHKDSK Finished: " & strCHKDSKFinished)
strDEFRAGStarted = (Year(Date) & "-" & AEZiR(Month(Date)) & "-" & AEZiR(Day(Date)) & " # " & AEZiR(Hour(Time)) & ":" & AEZiR(Minute(Time)) & ":" & AEZiR(Second(Time)))
h=(" DEFRAG Started: " & strDEFRAGStarted)
If FSO.FileExists(strSys32 & "\defrag.exe") Then
strDEFRAGReturn = objShell.Run("%COMSPEC% /c defrag.exe C: -a -v > " & chr(34) & strLogsDir & CompNam & "_DEFRAG.LOG" & chr(34), 0, True)
End If
If FSO.FileExists(strLogsDir & CompNam & "_DEFRAG.LOG") Then
Set DefragLog = FSO.OpenTextFile(strLogsDir & CompNam & "_DEFRAG.LOG", ForReading, True)
Do While DefragLog.AtEndOfStream <> True
CurLine = DefragLog.ReadLine
If InStr(CurLine, "Total fragmentation") Then
FragPosition = InStr(1,CurLine," %",1)-2
CurLine = CurLine
strFragAmount = Right(CurLine,4)
strFragAmount = Left(strFragAmount,2)
strFragAmount = Ltrim(strFragAmount)
End If
Loop
Else
DefragFail = "Failed"
i=(" Log File Could not be Located. Please try Again.")
j=(" Drive has Passed Defragmentation Check")
End If
If strFragAmount = "" Then
DefragFail = "Failed"
i=(" An Unknown Error has Occured. Please try Again.")
j=(" Run 'DEFRAG -v' from this machine manually.")
Else
If strFragAmount < 30 Then
DefragFail = "Passed"
i=(" Drive is " & strFragAmount & "% Fragmented")
j=(" Drive has Passed Defragmentation Check")
End If
If strFragAmount >= 30 Then
DefragFail = "Failed"
i=(" Drive is " & strFragAmount & "% Fragmented")
j=(" Drive has Failed Defragmentation Check")
End If
End If
DefragLog.Close
strDEFRAGFinished = (Year(Date) & "-" & AEZiR(Month(Date)) & "-" & AEZiR(Day(Date)) & " # " & AEZiR(Hour(Time)) & ":" & AEZiR(Minute(Time)) & ":" & AEZiR(Second(Time)))
k=(" DEFRAG Finished: " & strDEFRAGFinished)
strDrivePreCheckFinished = (Year(Date) & "-" & AEZiR(Month(Date)) & "-" & AEZiR(Day(Date)) & " # " & AEZiR(Hour(Time)) & ":" & AEZiR(Minute(Time)) & ":" & AEZiR(Second(Time)))
l=(" Script finished on " & strDRIVEPreCheckFinished)
m=("===================================================================================")
Set TXTLog = FSO.CreateTextFile(strLogsDir & CompNam & ".TXT", True)
TXTLog.WriteLine(strDrivePreCheckStarted & "," & mClient & "," & CompNam & "," & CompMfr & "," & CompMdl & "," & strCHKDSKStarted & "," & strBadKB & "KB" & "," & ChkDskFail & "," & strCHKDSKFinished & "," & strDEFRAGStarted & "," & strFragAmount & "%" & "," & DefragFail & "," & strDEFRAGFinished & "," & strDrivePreCheckFinished)
TXTLog.Close
If FSO.FileExists(strLogsDir & "_FDE.CSV") Then
Set CSVLog = FSO.OpenTextFile(strLogsDir & "_FDE.CSV", ForAppending, True)
CSVLog.WriteLine(strDrivePreCheckStarted & "," & mClient & "," & CompNam & "," & CompMfr & "," & CompMdl & "," & strCHKDSKStarted & "," & strBadKB & "KB" & "," & ChkDskFail & "," & strCHKDSKFinished & "," & strDEFRAGStarted & "," & strFragAmount & "%" & "," & DefragFail & "," & strDEFRAGFinished & "," & strDrivePreCheckFinished)
Else
Set CSVLog = FSO.CreateTextFile(strLogsDir & "_FDE.CSV", True)
CSVLog.WriteLine("Pre-Check Started,Management Client,Asset Tag,Computer Manufacturer,Computer Model,CHKDSK Started,CHKDSK Bad Sectors,CHKDSK Results,CHKDSK Finished,DEFRAG Started,DEFRAG Amount,DEFRAG Results,DEFRAG Finished,Pre-Check Finished")
CSVLog.WriteLine(strDrivePreCheckStarted & "," & mClient & "," & CompNam & "," & CompMfr & "," & CompMdl & "," & strCHKDSKStarted & "," & strBadKB & "KB" & "," & ChkDskFail & "," & strCHKDSKFinished & "," & strDEFRAGStarted & "," & strFragAmount & "%" & "," & DefragFail & "," & strDEFRAGFinished & "," & strDrivePreCheckFinished)
End If
CSVLog.Close
If FSO.FileExists(strLogsDir & "_FDE.LOG") Then
Set InstallLog = FSO.OpenTextFile(strLogsDir & "_FDE.LOG", ForAppending, True)
InstallLog.WriteLine(b)
InstallLog.WriteLine(c)
InstallLog.WriteLine(d)
InstallLog.WriteLine(e)
InstallLog.WriteLine(f)
InstallLog.WriteLine(g)
InstallLog.WriteLine(h)
InstallLog.WriteLine(i)
InstallLog.WriteLine(j)
InstallLog.WriteLine(k)
InstallLog.WriteLine(l)
InstallLog.WriteLine(m)
Else
Set InstallLog = FSO.CreateTextFile(strLogsDir & "_FDE.LOG", True)
InstallLog.WriteLine(a)
InstallLog.WriteLine(b)
InstallLog.WriteLine(c)
InstallLog.WriteLine(d)
InstallLog.WriteLine(e)
InstallLog.WriteLine(f)
InstallLog.WriteLine(g)
InstallLog.WriteLine(h)
InstallLog.WriteLine(i)
InstallLog.WriteLine(j)
InstallLog.WriteLine(k)
InstallLog.WriteLine(l)
InstallLog.WriteLine(m)
End If
InstallLog.Close
FSO.DeleteFile(strLogsDir & CompNam & "_CHKDSK.LOG")
FSO.DeleteFile(strLogsDir & CompNam & "_DEFRAG.LOG")
End If
End If
End If
Function AEZiR(plngValue)
Dim pstrValue
Dim plngChars
Dim i
pstrValue = CStr(plngValue)
plngChars = Len(pstrValue)
If plngChars < 2 Then
For i = 1 to plngChars Step -1
pstrValue = "0" & pstrValue
Next
End If
AEZiR = pstrValue
End Function
What am I missing? Is this task even possible with VBScript? Thank you in advance.
As neither VBScript, nor the FileSystemObject provide locking, someone/thing else has to do it:
a [scripting] language with proper file locks
a data store (DBMS) that allows simultaneous access
a programmer who uses a semaphore (e.g. a renamed file) to control the file access
In my opinion, the third option is the worst, because
the programmer has to do all the work and to take all
the risks/responsibilities. Using a database would solve
the problem of access control out of the box; using a
suitable language would allow a standard/non-hacking
solution.
But if you like to live in interesting times - that's
the code structure I would try to get away with:
While it make sense to continue (# of tries, timeout, successfully written)
rename FileIsFree.log to FileIsLocked.log
If success
open FileIsLocked.log
write to FileIsLocked.log
close FileIsLocked.log
rename FileIsLocked.log to FileIsFree.log
break/exit
End If
End While
If Not successfully written
Panic
End If
ADDED:
Some food for thought:
discussion
code
I hope you come to the conclusion, that using a DBMS is the better idea.
What is wrong with this script?
Option Explicit
Dim objRootDSE, strDNSDomain, adoConnection
Dim strBase, strFilter, strAttributes, strQuery, adoRecordset
Dim dtmStart, dtmEnd, strStart, strEnd
Dim strID, strFirst, strLast, strNTName
dtmEnd = Now()
dtmStart = DateAdd("d", -7, dtmEnd)
strStart = CStr(Year(dtmStart)) _
& Right("0" & CStr(Month(dtmStart)), 2) _
& Right("0" & CStr(Day(dtmStart)), 2) & "000000.0Z"
strEnd = CStr(Year(dtmEnd)) _
& Right("0" & CStr(Month(dtmEnd)), 2) _
& Right("0" & CStr(Day(dtmEnd)), 2) & "235959.0Z"
' Determine DNS domain name.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
' Use ADO to search Active Directory.
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
Set adoRecordset = CreateObject("ADODB.Recordset")
adoRecordset.ActiveConnection = adoConnection
' Search entire domain.
strBase = "<LDAP://" & strDNSDomain & ">"
'For user accounts for people created in the last week
strFilter = "(&(objectCategory=person)(objectClass=user)" _
& "(whenCreated>=" & strStart & ")(whenCreated<=" & strEnd & "))"
' Comma delimited list of attribute values to retrieve.
strAttributes = "employeeID,sn,givenName,sAMAccountName"
' Construct the LDAP query.
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
' Run the query.
adoRecordset.Source = strQuery
adoRecordset.Open
' Enumerate the resulting recordset.
Do Until adoRecordset.EOF
' Retrieve values.
strID = adoRecordset.Fields("employeeID").Value
strLast = adoRecordset.Fields("sn").Value
strFirst = adoRecordset.Fields("givenName").Value
strNTName = adoRecordset.Fields("sAMAccountName").Value
Wscript.Echo """" & strID & """,""" & strLast & """,""" & strFirst
& """,""" & strNTName & """"
adoRecordset.MoveNext
Loop
' Clean up.
adoRecordset.Close
adoConnection.Close
cscript //nologo test.vbs > users.csv
returns
(53, 1) Microsoft VBScript compilation error: Expected statement
You're missing an underscore line continuation at the end of the first line of this snippet:
Wscript.Echo """" & strID & """,""" & strLast & """,""" & strFirst
& """,""" & strNTName & """"
It should look like this:
Wscript.Echo """" & strID & """,""" & strLast & """,""" & strFirst _
& """,""" & strNTName & """"