Hello I am writing a script that will open the windows 10 camera, then display the most recent image when I close the camera then with a GUI, ask the user if the image is okay. If they select yes then the script would copy the filepath to the clibpoard and then be able to past this filepath into a Microsoft Excel cell. I have everyhting working how I want it to until the point where I need the filepath to be copied to the clipboard. Here is my code so far.
#include <MsgBoxConstants.au3>
Camera()
Func Camera()
; Execute Camera and wait for Camera to close
Local $iPID = ShellExecuteWait("explorer.exe", "shell:AppsFolder\Microsoft.WindowsCamera_8wekyb3d8bbwe!App")
Sleep(3000)
WinWaitClose("Camera")
EndFunc
#include-once
#include <Array.au3>
#include <File.au3>
#include <GUIComboBox.au3>
#include <GUIConstantsEx.au3>
#include <Process.au3>
$dst = "C:\Users\Cex\Pictures\Camera Roll" ; specify folder
$a_FileList = _FileListToArray2()
_ArraySort($a_FileList, 1, 1, $a_FileList[0][0], 1)
ShellExecute($a_FileList[1][0])
Func _FileListToArray2($s_Mask='*')
$h_Search = FileFindFirstFile($dst & '\' & $s_Mask)
$s_FileName = FileFindNextFile($h_Search)
If Not #error Then
Dim $a_File[100][2]
While Not #error
If StringInStr($s_FileName,'.',0,-1) Then
$s_FullName = $dst & '\' & $s_FileName
$a_File[0][0] += 1
If $a_File[0][0] >= UBound($a_File) Then
ReDim $a_File[$a_File[0][0] * 2][2]
EndIf
$a_File[$a_File[0][0]][0] = FileGetLongName($s_FullName)
$a_File[$a_File[0][0]][1] = FileGetTime($s_FullName,0,1)
EndIf
$s_FileName = FileFindNextFile($h_Search)
WEnd
ReDim $a_File[$a_File[0][0] + 1][2]
Return $a_File
EndIf
Return ''
EndFunc
#include <GUIConstantsEx.au3>
#include <IE.au3>
WinWaitActive("Photos", "")
Local $qGUI = GUICreate("Example", 200, 125, 1000, 200)
GUICtrlCreateLabel("Are you happy with this image?", 30, 30)
Local $bYes = GUICtrlCreateButton("Yes", 6, 60, 85, 25)
GUICtrlSetOnEvent($bYes, "xYes")
Local $bNo = GUICtrlCreateButton("Yes", 107, 60, 85, 25)
GUICtrlSetOnEvent($bNo, "xNo")
Local $bClose = GUICtrlCreateButton("Close", 57, 90, 85, 25)
GUISetState(#SW_SHOW, $qGUI)
While 1
Switch GUIGetMsg()
Case $bYes
bYes()
GUIDelete($qGUI)
Exit
Case $bNo
bNo()
GUIDelete($qGUI)
Exit
Case $bClose, $GUI_EVENT_CLOSE
ExitLoop
EndSwitch
WEnd
Func bYes()
_RunAU3("YesTest.au3")
EndFunc
Func bNo()
_RunAU3("NoTest.au3")
EndFunc
Func _RunAU3($sFilePath, $sWorkingDir = "", $iShowFlag = #SW_SHOW, $iOptFlag = 0)
Return Run('"' & #AutoItExe & '" /AutoIt3ExecuteScript "' & $sFilePath & '"', $sWorkingDir, $iShowFlag, $iOptFlag)
EndFunc
Like I said I am looking to copy the filepath of the most recent photograph and then copy it to the clipboard which will then be pasted into a cell in excel. I have limited coding knowledge so there are probably many bad points to my code but I have just been learning as I go along so if anyone can help me please do not confuse me however, if you have to, then all help is appreciated!
AutoIT has build in functions for the clipboard, such as ClipPut and ClipGet.
ClipPut($filepath)
which would be in your case
ClipPut($a_FileList[1][0])
Related
I'd like to use nim to resize the default display resolution on a machine (windows 10 only), I want to basically do it via a command line call like setDisplay 1280 1024
I've seen and used the python example Resize display resolution using python with cross platform support which I can follow, but just can't translate. I just don't get how to fill in EnumDisplaySettings
import winim/lean
import strformat
var
cxScreen = GetSystemMetrics(SM_CXSCREEN)
cyScreen = GetSystemMetrics(SM_CYSCREEN)
msg = fmt"The screen is {cxScreen} pixels wide by {cyScreen} pixels high."
EnumDisplaySettings(Null,0, 0) #total type mismatch
MessageBox(0, msg, "Winim Example Screen Size", 0)
Tried checking stuff like https://cpp.hotexamples.com/fr/examples/-/-/EnumDisplaySettings/cpp-enumdisplaysettings-function-examples.html but wasn't much help, same for https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-changedisplaysettingsa
I wrote about 2% of this answer myself, and the rest came from pointystick on discord - thanks to them!
The solution is a bit lazy, but it's so fast that for most that won't matter.
With no cmd line args it will just set the display to the default recommendation, else with 2 cmd line args it can reset your display if it finds a match
import winim/lean
import os
import strutils
var modeToFind = (width: 1920, height: 1080, bitsPerPixel: 32,
refreshRate: 60)
var reset = 0
type ModeNotFoundError = object of CatchableError
proc getDisplayMode(): DEVMODEW =
## Finds the wanted screen resolution or raises a ModeNotFoundError.
var
nextMode: DWORD = 0
mode: DEVMODEW
while EnumDisplaySettings(nil, nextMode, mode) != 0:
echo $mode.dmPelsWidth & " x " & $mode.dmPelsHeight &
" x " & $mode.dmBitsPerPel &
" - " & $mode.dmDisplayFrequency
inc nextMode
if (mode.dmPelsWidth == modeToFind.width) and
(mode.dmPelsHeight == modeToFind.height):
echo "Found it!"
return mode
if(reset==1):
return mode
raise newException(ModeNotFoundError, "Cannot find wanted screen mode")
proc changeResolution(): bool =
## Actually changes the resolution. The return value indicates if it worked.
result = false
try:
let wantedMode = getDisplayMode()
result = ChangeDisplaySettings(wantedMode.unsafeAddr, 0.DWORD) == DISP_CHANGE_SUCCESSFUL
except ModeNotFoundError: discard
when isMainModule:
var
cxScreen:int32 = 0 #= GetSystemMetrics(SM_CXSCREEN)
cyScreen:int32 = 0 # = GetSystemMetrics(SM_CYSCREEN)
try:
cxScreen = (int32) parseInt(paramStr(1))
cyScreen = (int32) parseInt(paramStr(2))
modeToFind.width = cxScreen
modeToFind.height = cyScreen
except:
reset = 1
if not changeResolution():
echo "Change Resolution Failed"
I have a large Linux-formatted (i.e. linefeed character for a new line) text file that is a "status" file for a program as it runs. This file is updated while the program is running. It outputs some useful messages and periodic header information, but also lines of numerical status data separated by spaces. Because it is a piece of commercial software (Abaqus /Explicit), I can't do anything to modify how it writes to this status file.
I wrote a VBA script awhile back that opens the file, reads it in as a whole via "Input$", splits the file into lines via "Split(Data, vbLF)", and parses each line to extract the numerical status data and place it into an Excel spreadsheet for me to view and analyze. The problem is that, as the program continues to run, this file gets larger and larger to the point that reading the whole file into Excel is becoming impractical.
I've been trying to figure out a quick way to read the file starting from the line I left off on, without reading the entire thing to memory. I tried to save EOF() to a "helper" cell on the spreadsheet and use that with "Seek" and "Line Input" to jump right to the spot I left off on, but that won't work because "Line Input" doesn't recognize the linefeed character as a new line, only carriage return or carriage return-linefeed.
I spent some time going through other posts and it seemed like the only other solutions required reading the whole file in. Does anyone have any ideas as to how this could be done WITHOUT reading the whole file in?
Thanks for your time!
'perhaps this could be modified for new start
Sub read_bookmark()
Dim linein, tline, endmark, linevalid, filelen, fread
Dim chx As Byte
Dim fpath, mes, a
On Error GoTo ErrHand
mes = "Enter path & filename of Bookmark import file."
'fpath = InputBox(mes, "", "c:\temp\bookmarks_12_8_18.html")
fpath = "c:\temp\test.txt"
If Len(fpath) = 0 Or (Len(Dir(fpath)) = 0) Then
MsgBox ("File not found. Program canceled")
End
End If
tline = ""
linein = ""
endmark = False
linevalid = False
Open fpath For Binary Access Read As #1
filelen = LOF(1) ' Get length of file.
For fread = 1 To filelen
Get #1, , chx
If chx = 13 Or chx = 10 Then
endmark = True
ElseIf endmark = True Then 'wait till no more endmarks
endmark = False
tline = linein
linevalid = True
linein = Chr(chx) 'keep chr after endmarks
Else
linein = linein + Chr(chx)
End If
If linevalid = True Then
'proc tline
tline = ""
linevalid = False
End If
Next
'proc last linein chrs
MsgBox ("Processing Complete")
Exit Sub
ErrHand: ' Error-handling routine.
Close #1
MsgBox "Error in HTML read " + Error(Err)
End
End Sub
I am trying to automate some repetitive work for getting results from a website,
this link Drugs.com, checks for interaction between two medicines.
I must take the text of the two medicines from the Excel sheet and enter them on the website to check the interaction between them.
Here is a sample of my Excel sheet:
column(A) Column(B)
(A1)candesartan benazepril
(A2)eprosartan captopril
(A3)irbesartan enalapril
When I press 'Check For Interaction' the result of the next page must be extracted and return one of tree interactions:
-major
-moderate
-minor
This must then write the result to column(c)
I am a beginner at autoit but I can do some scripting albeit with a lot of bugs.
I will appreciate it if someone can correct/assist me with the bugs in my code. I will also appreciate it if someone can help me with the correct keywords so that I can Google for examples and solutions.
Thanks all.
#include <Excel.au3>
#include <IE.au3>
#include <File.au3>
Local $sWorkbook = "C:\Users\Aligaaly\Desktop\autoit\test\drugs.xlsx"
Local $oExcel = _Excel_Open()
Local $oWorkbook = _Excel_BookOpen($oExcel, $sWorkbook)
$oWorkbook = _Excel_BookAttach($sWorkbook)
GLOBAL $oIE = _IECreate("https://www.drugs.com/drug_interactions.php")
Local $oInputs = _IETagNameGetCollection($oIE, "input")
For $oInput In $oInputs
$text_form1 = _IEGetObjById($oIE, "livesearch-interaction")
If StringLower($oInput.classname) == "input-button search-button" and _IEFormElementGetValue($oInput) Then ; it is an input
Global $oInput_btn = $oInput
EndIf
Next
WinActivate("[CLASS:XLMAIN]", "")
For $i = 1 To 5
Global $sResulta = _Excel_RangeRead($oWorkbook, Default, 'A' & $i & ':A' & $i,1 )
For $y = 1 To 5
Global $sResultb = _Excel_RangeRead($oWorkbook, Default, 'B' & $y & ':B' & $y,1 )
WinActivate("[CLASS:IEFrame]", "")
_IEFormElementSetValue($text_form1, $sResulta )
_IEAction ($oInput_btn, "click")
sleep(5000)
_IEFormElementSetValue($text_form1, $sResultb )
_IEAction ($oInput_btn, "click")
sleep(5000)
For $oInput In $oInputs
If StringLower($oInput.value) == "check for interactions" Then
Global $check_btn = $oInput
EndIf
Next
_IEAction ($check_btn, "click")
sleep(5000)
$oButtonsa = _IETagnameGetCollection($oIE, "span")
For $oButtonn in $oButtonsa
If $oButtonn.classname == "status-category status-category-major" Then
WinActivate("[CLASS:XLMAIN]", "")
_Excel_RangeWrite($oWorkbook, $oWorkbook.Activesheet, "major","C" & $y)
ElseIf $oButtonn.classname == "status-category status-category-moderate" Then
WinActivate("[CLASS:XLMAIN]", "")
_Excel_RangeWrite($oWorkbook, $oWorkbook.Activesheet, "moderate","C" & $y)
ElseIf $oButtonn.classname == "status-category status-category-minor" Then
WinActivate("[CLASS:XLMAIN]", "")
_Excel_RangeWrite($oWorkbook, $oWorkbook.Activesheet, "minor","C" & $y)
EndIf
ExitLoop
Next
Next
Next
i have updated the code with my final touches
i think this code is now complete the steps i have write down above
but i have an error when the script finish the first iteration
The problem is in _IEFormElementSetValue function.
Probably,
$text_form1 = _IEGetObjById($oIE, "livesearch-interaction")
can't find any object.
For debug it you can insert this code before _IEFormElementSetValue:
ConsoleWrite("isObject:" & isObj($text_form1) & #CRLF)
Update: I found 3 problems.
1) You didn't return to search page after end of iteration and the input object can't be found;
2) You must get Input and Button object on the start of each iteration;
3) Exitloop must be on each If ... esleif section.
Try this code:
#include <Excel.au3>
#include <IE.au3>
#include <File.au3>
Local $sWorkbook = "C:\Users\Aligaaly\Desktop\autoit\test\drugs.xlsx"
Local $oExcel = _Excel_Open()
Local $oWorkbook = _Excel_BookOpen($oExcel, $sWorkbook)
$oWorkbook = _Excel_BookAttach($sWorkbook)
GLOBAL $oIE = _IECreate("https://www.drugs.com/drug_interactions.php")
Local $oInputs = _IETagNameGetCollection($oIE, "input")
For $oInput In $oInputs
$text_form1 = _IEGetObjById($oIE, "livesearch-interaction")
If StringLower($oInput.classname) == "input-button search-button" and _IEFormElementGetValue($oInput) Then ; it is an input
Global $oInput_btn = $oInput
EndIf
Next
WinActivate("[CLASS:XLMAIN]", "")
For $i = 1 To 5
Global $sResulta = _Excel_RangeRead($oWorkbook, Default, 'A' & $i & ':A' & $i,1 )
For $y = 1 To 5
Global $sResultb = _Excel_RangeRead($oWorkbook, Default, 'B' & $y & ':B' & $y,1 )
$oInputs = _IETagNameGetCollection($oIE, "input")
For $oInput In $oInputs
$text_form1 = _IEGetObjById($oIE, "livesearch-interaction")
If StringLower($oInput.classname) == "input-button search-button" and _IEFormElementGetValue($oInput) Then ; it is an input
$oInput_btn = $oInput
EndIf
Next
WinActivate("[CLASS:IEFrame]", "")
_IEFormElementSetValue($text_form1, $sResulta )
_IEAction ($oInput_btn, "click")
sleep(5000)
_IEFormElementSetValue($text_form1, $sResultb )
_IEAction ($oInput_btn, "click")
sleep(5000)
For $oInput In $oInputs
If StringLower($oInput.value) == "check for interactions" Then
Global $check_btn = $oInput
EndIf
Next
_IEAction ($check_btn, "click")
sleep(5000)
$oButtonsa = _IETagnameGetCollection($oIE, "span")
For $oButtonn in $oButtonsa
If $oButtonn.classname == "status-category status-category-major" Then
WinActivate("[CLASS:XLMAIN]", "")
_Excel_RangeWrite($oWorkbook, $oWorkbook.Activesheet, "major","C" & $y)
ExitLoop
ElseIf $oButtonn.classname == "status-category status-category-moderate" Then
WinActivate("[CLASS:XLMAIN]", "")
_Excel_RangeWrite($oWorkbook, $oWorkbook.Activesheet, "moderate","C" & $y)
ExitLoop
ElseIf $oButtonn.classname == "status-category status-category-minor" Then
WinActivate("[CLASS:XLMAIN]", "")
_Excel_RangeWrite($oWorkbook, $oWorkbook.Activesheet, "minor","C" & $y)
ExitLoop
EndIf
Next
_IENavigate($oIE, "https://www.drugs.com/drug_interactions.php?action=new_list")
Next
Next
I'd like to use a proxy to mask my ip surfing the net an autoit browser!
This is my code:
#NoTrayIcon
#include <GUIConstants.au3>
#Include <IE.au3>
#include <GUIConstantsEx.au3>
GUICreate("Web Browser By EMPĀ£!!",800,600)
GUISetBkColor(0x808080)
GUISetState(#SW_SHOW)
$Edit=GUICtrlCreateInput("http://www.whatismyip.com/",20,20,500,20)
$Vai=GUICtrlCreateButton("SURF!!!",600,10,150,50)
$oIE = ObjCreate("Shell.Explorer.2")
GUICtrlCreateObj($oIE, 10, 90,780, 500)
$ret = HttpSetProxy(2,"61.163.78.51:3128")
If $ret == 0 Then
MsgBox(0, "Proxy", "Proxy Error")
Exit
EndIf
While 1
$msg=GUIGetMsg()
Switch $msg
Case $Vai
$Link=GUICtrlRead($Edit)
_IENavigate($oIE,($Link))
GUICtrlSetData($Edit,$Link)
Case $GUI_EVENT_CLOSE
Exit
EndSwitch
WEnd
I navigate on http://www.whatismyip.com/ and i can see my real ip address! I'd like to hide a proxy!
The HttpSetProxy function is only for use with InetGet, it makes no difference to the internet explorer settings. In order to make a proxy for internet explorer windows you need to change the internet explorer settings.
The way I would do it is something like:
#include <GUIConstants.au3>
#include <IE.au3>
#include <GUIConstantsEx.au3>
Global Const $sInetSettingsKey = "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
GUICreate("Web Browser By EMPĀ£!!", 800, 600)
GUISetBkColor(0x808080)
GUISetState(#SW_SHOW)
$Edit = GUICtrlCreateInput("http://www.whatismyip.com/", 20, 20, 500, 20)
$Vai = GUICtrlCreateButton("SURF!!!", 600, 10, 150, 50)
$oIE = ObjCreate("Shell.Explorer.2")
GUICtrlCreateObj($oIE, 10, 90, 780, 500)
MySetProxy("61.163.78.51:3128")
While 1
$msg = GUIGetMsg()
Switch $msg
Case $Vai
$Link = GUICtrlRead($Edit)
_IENavigate($oIE, ($Link))
GUICtrlSetData($Edit, $Link)
Case $GUI_EVENT_CLOSE
ExitLoop
EndSwitch
WEnd
MySetProxy()
Func MySetProxy($sProxy = "", $fEnable = True)
Local Static $sPrev = ""
Local Static $fWasEnabled = False
If $sProxy = "" Then
If $sPrev <> "" Then __setProxyInfo($fWasEnabled, $sPrev)
Else
If $sPrev = "" Then
$sPrev = RegRead($sInetSettingsKey, "ProxyServer")
$fWasEnabled = RegRead($sInetSettingsKey, "ProxyEnable")
EndIf
__setProxyInfo($fEnable, $sProxy)
EndIf
EndFunc
Func __setProxyInfo($fEnabled, $sProxy)
RegWrite($sInetSettingsKey, "ProxyEnable", "REG_DWORD", 1)
RegWrite($sInetSettingsKey, "ProxyServer", "REG_SZ", $sProxy)
EndFunc
whatismyip.com didn't like it much though. But the IP address definitely changed.
A simulation program I'm using requires a text based input file. I need to run the simulation in different configurations by changing the values in the text file. I am looking for a way to do this automatically with any script that does not require third party compilers. It has to run natively on a Windows XP machine. I only have a little bit of coding experience in MATLAB and FORTRAN.
I will describe my idea of what the script should do in some pseudo-code:
% speed.txt - a txt file with 10 different speed values
% coeff.txt - a txt file with 10 different coefficients
% dist.txt - a txt file with 5 different distance values
% input.txt - the txt file containing the input parameters. This file has to be changed.
% output.txt- the output of the simulation
% sp - the i-th speed value
% co - the i-th coeff value
% di - the j-th distance value
% D:\FO - Final Output folder
Read input.txt
for i = 1:10
Display i on screen % so I know how much of the batch is done
Go to line 37, overwrite 1st four characters with i-th value from speed.txt
Go to line 68, overwrite 1st eight characters with i-th value from coeff.txt
for j = 1:5
Display j on screen % so I know how much of the batch is done
Go to line 67, overwrite 1st five characters with j-th value from dist.txt
Run simulation.exe
When simulation is done, get output.txt, rename it to "output_sp_co_di.txt"
and move the file to D:\FO
end
end
I hope that this is possible with a .bat or .vbs script (or anything else that will run natively). All help is greatly appreciated.
EDIT: after some advice I started a vbs script. I have never used that language before but pulled the thing here under together from scraps on the internet:
Option Explicit
Dim objFSO, strTextFile, strData, strLine, arrLines
Dim filesys, filetxt, path
Dim speed(10), ct(10), dist(4), text(73), d(4)
Dim i, j, k
i = 0
j = 0
k = 0
speed(0) = 3.0
speed(1) = 5.0
speed(2) = 7.0
speed(3) = 9.0
speed(4) = 11.0
speed(5) = 13.0
speed(6) = 15.0
speed(7) = 17.0
speed(8) = 19.0
speed(9)= 21.0
speed(10)= 22.0
ct(0) = 0.987433
ct(1) = 0.816257
ct(2) = 0.816361
ct(3) = 0.720357
ct(4) = 0.418192
ct(5) = 0.239146
ct(6) = 0.154534
ct(7) = 0.107608
ct(8) = 0.079057
ct(9)= 0.060437
ct(10)= 0.053465
dist(0) = 173.48
dist(1) = 260.22
dist(2) = 346.96
dist(3) = 433.7
dist(4) = 520.44
d(0) = 2
d(1) = 3
d(2) = 4
d(3) = 5
d(4) = 6
CONST ForReading = 1
'name of the text file
strTextFile = "TurbSim.inp"
'Create a File System Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Open the text file - strData now contains the whole file
strData = objFSO.OpenTextFile(strTextFile,ForReading).ReadAll
'Split the text file into lines
arrLines = Split(strData,vbCrLf)
'Step through the lines
For Each strLine in arrLines
text(i) = strLine
i = i + 1
Next
'Open text file to write to
path = objFSO.GetAbsolutePathName("D:\Sandbox\TurbSim.inp")
For i = 0 To 10
If i = 0 Then
text(37) = Replace(text(37),"UUUU",speed(i))
text(68) = Replace(text(68),"CCCCCCCC",ct(i))
Else
text(37) = Replace(text(37),speed(i-1),speed(i))
text(68) = Replace(text(68),ct(i-1),ct(i))
End If
For j = 0 To 4
If j = 0 Then
text(67) = Replace(text(67),"DDDDD",dist(j))
Else
text(67) = Replace(text(67),dist(j-1),dist(j))
End If
Set filetxt = objFSO.opentextfile("D:\Sandbox\TurbSim.inp", 2, True)
For k = 0 To 73
if k = 73 Then
filetxt.write text(k)
Else
filetxt.write text(k) & vbCr & vbLf
End If
objFSO.CopyFile "D:\Sandbox\TurbSim.inp", _
"D:\Sandbox\input\TurbSim_" & speed(i) & "_" & d(j) &"D.inp"
Next
filetxt.close
Next
Next
' wscript.echo text(37)
' wscript.echo text(68)
' wscript.echo text(67)
filetxt.Close
'Cleanup
' Set filesys = Nothing
Set objFSO = Nothing
Problem is now that the distance part (the j-loop) is not working properly. From the output generated (TurbSim_speed_dD.inp) I see that only the last distance (520.44) is used. I don't really understand why, I'll look into that later. If anyone has a suggestion for improvement, then you're ideas are always welcome.
The Batch file below is a .bat version of your vbs script:
#echo off
SetLocal EnableDelayedExpansion
REM Auxiliary macro for easier replacements
set Replace=for /F "tokens=1,2 delims==" %%x in
:: speed - vector with 11 different speed values
Set i=0
For %%s in (3.0 5.0 7.0 9.0 11.0 13.0 15.0 17.0 19.0 21.0 22.0) do (
Set speed[!i!]=%%s
Set /A i+=1
)
:: ct - vector with 11 different coefficients
Set i=0
For %%c in (0.987433 0.816257 0.816361 0.720357 0.418192 0.239146 0.154534 0.107608 0.079057 0.060437 0.053465) do (
Set ct[!i!]=%%c
Set /A i+=1
)
:: dist - vector with 5 different distance values
Set i=0
For %%d in (173.48 260.22 346.96 433.7 520.44) do (
Set dist[!i!]=%%d
Set /A i+=1
)
REM d does not need to be a vector because d(i) = i+2
:: Split the text file into lines, and Step through the lines
Set i=0
For /F "delims=" %%l in (TurbSim.inp) do (
Set "text[!i!]=%%l"
Set /A i=i+1
)
For /L %%i in (0,1,10) do (
If %%i == 0 (
%Replace% ("UUUU=!speed[%%i]!") do set "text[37]=!text[37]:%%x=%%y!"
%Replace% ("CCCCCCCC=!ct[%%i]!") do set "text[68]=!text[68]:%%x=%%y!"
) Else (
set /A iM1=i-1
%Replace% ("!iM1!") do set speed_iM1=!speed[%%x]!& set ct_iM1=!ct[%%x]!
%Replace% ("!speed_iM1!=!speed[%%i]!") do set "text[37]=!text[37]:%%x=%%y!"
%Replace% ("!ct_iM1!=!ct[%%i]!") do set "text[68]=!text[68]:%%x=%%y!"
)
For /L %%j in (0,1,4) do (
If %%j == 0 (
%Replace% ("DDDDD=!dist[%%j]!") do set "text[67]=!text[67]:%%x=%%y!"
) Else (
set /A jM1=j-1
%Replace% ("!jM1!") do set dist_jM1=!dist[%%x]!
%Replace% ("!dist_jM1!=!dist[%%j]!") do set "text[67]=!text[67]:%%x=%%y!"
)
set /A d=j+2
(For /L %%k in (0,1,73) do (
if %%k == 73 (
set /P =!text[%%k]!< NUL
) Else (
echo !text[%%k]!
)
)) > "D:\Sandbox\input\TurbSim_!speed[%%i]!_!d!D.inp"
)
)
echo %text[37]%
echo %text[68]%
echo %text[67]%
Notes:
1- This is a first attempt Batch file based on your vbs script; I really don't understand what you tried to do and just did a direct translation. It seems that the requirements you state in the question are not the same of the vbs script. Any problem may be solved if you give me specific details.
2- Previous Batch file remove any empty line from the input file. This may be solved if needed.
3- The text replacement in Batch is textual, NOT by numeric value. Any number must be written exactly the same as the array values in order to be replaced. I think the same behaviour apply to vbs.
4- Input file must not contain certain special Batch characters, like ! ^ and others. This may be fixed in certain cases only.
I have managed to pull together a .vbs script from various internet references that does what I want. The script does the following:
Reads in original input file
Stores the data line by line in the text array
Reads in speed, coefficient and distance data from text file
Stores this data in separate speed, coefficient and distance arrays line by line.
Takes first entry of speed and coeff. array and writes it at appropriate places in the
text array
Loops through distance array and writes the text array line by line back to an .inp file
Runs the simulation with the edited input file
Waits until simulation is terminated.
Copy output files from current directory to output folder, renaming them in the process.
Wait 10 seconds to make sure copying is finished
10.Repeat steps 6-10 with all other entries of speed and coeff. array
Requirements for this script to work:
A. An input folder with an .inp file that has "UUUU", "DDDDD", "CCCCCCCC" written at places where respectively the velocity, distance and coefficient should be written.
B. An output folder
C. The files speed.txt, ct.txt and distance.txt containing the speed, coefficient and distance values to be used.
D. You should run this script from an admin account. Otherwise you don't have the permission to check if the simulation is still running with the "Win32_process".
Option Explicit
Dim objFSO, strTextFile, strTData, strLine, arrTLines
Dim strVelFile, strCtFile, strDistFile
Dim strVData, strCData, strDData
Dim arrVLines, arrCLines, arrDLines
Dim strLineV, strLineC, strLineD
Dim strComputer, oWMI, colEvents, oEvent
Dim filesys, filetxt, path, curPath
Dim speed(), ct(), dist(), text(73)
Dim oShell
Dim i, j, k
i = 0
j = 0
k = 0
' Subroutine to start an executable
Sub Run(ByVal sFile)
Dim shell
Set shell = CreateObject("WScript.Shell")
shell.Run Chr(34) & sFile & Chr(34), 1, false
Set shell = Nothing
End Sub
CONST ForReading = 1
' Create a File System Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
' Create Shell object. Needed to change directories
Set oShell = CreateObject("WScript.Shell")
'Change current directory to \input folder
oShell.CurrentDirectory = ".\input"
' The name of the original input file
' with the UUUU, DDDDD, CCCCCCC in the correct places
strTextFile = "TurbSim.inp"
' Open the text file and read it all into strTData
strTData = objFSO.OpenTextFile(strTextFile,ForReading).ReadAll
' Go back to parent folder as there all the other .txt files reside
Set oShell = CreateObject("WScript.Shell")
oShell.CurrentDirectory = ".\.."
' name of other input text files
strVelFile = "speed.txt"
strCtFile = "ct.txt"
strDistFile = "dist.txt"
' Open the text file - str*Data now contains the whole file
strVData = objFSO.OpenTextFile(strVelFile,ForReading).ReadAll
strCData = objFSO.OpenTextFile(strCtFile,ForReading).ReadAll
strDData = objFSO.OpenTextFile(strDistFile,ForReading).ReadAll
' Split the text files into lines
arrTLines = Split(strTData,vbCrLf)
arrVLines = Split(strVData,vbCrLf)
arrCLines = Split(strCData,vbCrLf)
arrDLines = Split(strDData,vbCrLf)
' Give the speed, ct and dist arrays their dimension
ReDim speed(UBound(arrVLines))
ReDim ct(UBound(arrCLines))
ReDim dist(UBound(arrDLines))
' Add data to arrays text, speed, ct and dist line by line
For Each strLine in arrTLines
text(i) = strLine
i = i + 1
Next
'Reset counter
i = 0
' Step through the lines speed
For Each strLineV in arrVLines
speed(i) = strLineV
i = i + 1
Next
i = 0
' Step through the lines ct
For Each strLineC in arrCLines
ct(i) = strLineC
i = i + 1
Next
i = 0
' Step through the lines dist
For Each strLineD in arrDLines
dist(i) = strLineD
i = i + 1
Next
i = 0
' Get the current path. Needed to point to the executable.
curPath = objFSO.GetAbsolutePathName(".")
For i = 0 To UBound(speed)
If i = 0 Then
' Replace the UUUU and CCCCCCCC values
' Only the first run.
text(37) = Replace(text(37),"UUUU",speed(i))
text(68) = Replace(text(68),"CCCCCCCC",ct(i))
Else ' Replace the previous speed and coeff. values with the current one
text(37) = Replace(text(37),speed(i-1),speed(i))
text(68) = Replace(text(68),ct(i-1),ct(i))
End If
For j = 0 To UBound(dist)
If j = 0 And i = 0 Then
' Replace the DDDDD value (only at first run)
text(67) = Replace(text(67),"DDDDD",dist(j))
ElseIf j = 0 And i > 0 Then
' Replace the distance value of the previous speed/coeff. case
' with the current one
text(67) = Replace(text(67), dist(UBound(dist)), dist(j))
Else ' Replace the previous distance value with the current one
text(67) = Replace(text(67),dist(j-1),dist(j))
End If
Set filetxt = objFSO.opentextfile(curPath & "\TurbSim.inp", 2, True)
For k = 0 To 73 ' Write to an .inp file line by line
if k = 73 Then ' Prevent adding a new line at the end
filetxt.write text(k)
Else
filetxt.write text(k) & vbCr & vbLf
End If
Next
filetxt.close
' Execute the simulation
Run curPath &"\TurbSimGW.exe"
strComputer = "."
Set oWMI = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
'# Create an event query to be notified within 3 seconds when TurbSimGW is closed
Set colEvents = oWMI.ExecNotificationQuery _
("SELECT * FROM __InstanceDeletionEvent WITHIN 3 " _
& "WHERE TargetInstance ISA 'Win32_Process' " _
& "AND TargetInstance.Name = 'TurbSimGW.exe'")
'# Wait until TurbSimGW is closed
Set oEvent = colEvents.NextEvent
' Copy and rename output files
objFSO.CopyFile curPath & "\TurbSim.wnd", _
curPath & "\output\TurbSim_" & speed(i) & "_" & j+2 &"D.wnd"
wscript.sleep 10000 ' time to allow copying the files
Next
Next
'' ' wscript.echo text(37)
'' ' wscript.echo text(68)
'' ' wscript.echo text(67)
filetxt.Close
' Cleanup
' Set filesys = Nothing
Set objFSO = Nothing
Now it works flawlessly. However A solution to requirement D would be nice. My work-around is instead of checking if the program is terminated I just set a sleep value. For this value of sleep I know for sure the simulation is done and the output files are ready to copy.