I tried to write a code block which displays all of the pre-declared processes in a MessageBox:
Dim pro As String = "chrome" & "firefox"
Dim prox() As Process
Try
prox = Process.GetProcesses()
For Each process As Process In prox
If (pro = process.ProcessName) Then
MsgBox("Process Found: " & pro & " ,")
End If
Next process
But whenever I try to match from a list with more than one program, it fails to match any of them. How can I rewrite the code so it can match from a list of processes?
In a generic way, and looking into future maintaining and ease of reading you could use this:
'use ; as separator, keep one at the beginning and one at the end
Dim pro As String = ";chrome;firefox;iexplorer;safari;etc;"
Then instead of doing a straight equality test if pro = processname do
If (pro.Contains(";" & process.ProcessName & ";") Then
To read you only need to look at two lines (instead of several for an array based solution).
To maintain (add/remove from the list), just update the first line.
Related
I have a very simple program that converts .HEIC images to .JPEG images; this is a batch operation. This task is a simple loop that runs following code. The code takes quite long to process when processing a large batches of 1000+ images. (I am using nuget package FileOnQ.Imaging.Heif).
How can I speed up the process? Can I perform the loop execution on different threads? Or is there another alternative.
For each File as String in System.IO.Directory.GetFiles(oBasePath, "*.*", SearchOption.AllDirectories)
Dim oHEICimage As New HeifImage(FullPath)
Dim oNewPath As String = System.IO.Path.Combine(Directory, Name & ".jpeg")
oHEICimage.PrimaryImage.Write(oNewPath)
Next
Note: I removed some code that determinates the file naming etc. because this is not relevant to the question.
If you are looking for a multithread example in a for loop, you can use Threading.Tasks.Parallel.ForEach:
https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-write-a-simple-parallel-foreach-loop
However, be aware of creating too many resources in the loop, as it may not speed up the processing. You can also limit the number of threads running running on the loop by specifying MaxDegreeOfParallelism in ParallelOptions.
For example:
Dim files As String() = System.IO.Directory.GetFiles(oBasePath, "*.*", IO.SearchOption.AllDirectories)
Threading.Tasks.Parallel.ForEach(files, Sub(imgFile)
Dim oHEICimage As New HeifImage(imgFile)
Dim oNewPath As String = System.IO.Path.Combine(outDirectory, Name & ".jpeg")
oHEICimage.PrimaryImage.Write(oNewPath)
End Sub)
I'm busy with software that uses Rs232 Com port communication module.
I send a roll-call out 1st to all users (Ping all users) and then wait 10 min to receive all the roll-calls back, thereafter I send to all the outstanding names (Ping outstanding active individual) using a listview with the remaining members names, I send all the outstanding names in burst of 3's with 3.5 sec in-between. I'm using Threading.Thread.Sleep() to prevent flooding my repeater.
Is there an alternative to Threading.Thread.Sleep() that allows the software to still receive roll-call feedbacks sending the roll-Call pings through the Rs232 Module?
For i As Integer = 0 To LsvCopyRemove.Items.Count - 1
If LsvCopyRemove.Items(i).SubItems(11).Text = "Yes" Then
Dim Group As String = LsvCopyRemove.Items(i).Text
StringData = vbCrLf & "MY String Information comes here"
_rs232.Write("" & vbCrLf)
Threading.Thread.Sleep(500)
_rs232.Write(StringData & vbCrLf) 'The text contained in the txtText will be sent to the serial port as ascii
Threading.Thread.Sleep(3500)
_rs232.Write(StringData & vbCrLf)
Threading.Thread.Sleep(3500)
_rs232.Write(StringData & vbCrLf)
Threading.Thread.Sleep(3500)
Me.rtbTX.AppendText(.Text & vbCr)
'***********************************************************************************************************************************************************************************************************************************************
.Text = String.Empty & vbCrLf
Data = Encoding.Default.GetBytes(.Text)
_rs232.SendData(Data)
'***************************************************************************************************************************************************************************************************************************************************
Threading.Thread.Sleep(6500)
End If
Next
What you are looking for is asynchronous programming, which allows you to execute multiple threads simultaneously. In your example, you'll have to execute the code above which sends the outstanding names in a seperate thread. There are two ways to accomplish this:
Using System.Threading: Put the code you want to execute in a seperate thread in a sub routine, then call it like this:
Dim newThread As New Threading.Thread(AddressOf myFunction)
newThread.Start()
Now the code in the function called myFunction is executed, but the execution of the current function is continued, which allows you to still receive events.
You can also use the newer Threading.Tasks namespace, which can be used in a similar way:
Dim newTask As Task = Task.Factory.StartNew(AddressOf myFunction)
The software I'm writing is being run in a service installed on a computer.
I want to read a text file, process it, and code it to a different path.
the software is doing exactly what it's supposed to do but it only processes 2 files and it stops. I believe that its something to do with the for each loop. I found some information online saying that its to do with the amount of memory being allocated to each cycle of the for each loop.
Any help is appreciated.
my code goes like this.
For Each foundFile As String In My.Computer.FileSystem.GetFiles("C:\Commsin\", FileIO.SearchOption.SearchTopLevelOnly, "ORDER-*.TXT")
Dim filenum As Integer
filenum = FreeFile()
FileOpen(filenum, foundFile, OpenMode.Input)
While Not EOF(filenum)
<do a bunch of stuff>
End While
<more code>
Dim arrayFileName() As String = GetFileName.Split("\")
Dim FileName As String = arrayFileName(2)
My.Computer.FileSystem.CopyFile(foundFile, "C:\Commsin\Done\" & FileName)
If IO.File.Exists("C:\Commsin\Done\" & FileName) Then
My.Computer.FileSystem.DeleteFile(foundFile, Microsoft.VisualBasic.FileIO.UIOption.AllDialogs, Microsoft.VisualBasic.FileIO.RecycleOption.SendToRecycleBin)
NoOfOrders -= NoOfOrders
End If
Next
Fundamental mistake: Don't modify the collection you are iterating over, i.e. avoid this pattern (pseudocode):
For Each thing In BunchOfThings:
SomeOperation()
BunchOfThings.Delete(thing)
Next thing
It's better to follow this pattern here (pseudocode again):
While Not BunchOfThings.IsEmpty()
thing = BunchOfThings.nextThing()
SomeOperation()
BunchOfThings.Delete(thing)
End While
I'll leave it as an exercise for you to convert your code from the first approach to the second.
It looks like you're trying to extract the filename from the full path using Split().
Why not just use:
Dim fileName As String = IO.Path.GetFileName(foundFile)
Instead of:
Dim arrayFileName() As String = GetFileName.Split("\")
Dim FileName As String = arrayFileName(2)
Thank you, everyone, for your suggestions, I have successfully implemented the recommended changes. It turned out that the issue wasn't with the code itself.
It was with one of the files I was using it had a text row that once split into an array it wasn't at a required length giving an error "Index was outside the bounds of the array."
It was a mistake on the file, I also added some check to prevent this error in the future.
Thank You.
As per title. Using this code example (3rd example down) as my starting point.
Here's my effort at VBA code, but it stalls at the first hurdle ("Run time error 438: object doesn't support this property or method")
Sub Test()
Set objConnection = GetObject("WinNT://HM10")
Set colResources = objConnection.Resources
For Each objResource In colResources
Debug.Print objResource.Path
Next
End Sub
HM10 is my computer name. Eventually it will need to be an environmental variable (if that's the right term) for whatever machine it happens to be on.
EDIT: Ok, more searching has led me to this:
Sub test()
Filename = "."
Set wmi = GetObject("winmgmts://./root/cimv2")
qry = "SELECT * FROM Win32_Process WHERE CommandLine LIKE '%" & Filename & "%'"
For Each p In wmi.ExecQuery(qry)
Debug.Print p.commandline
Next
End Sub
which is closer, but only shows local files, not network files. I only need network files, how do I get them?
Using Attachmate, I am trying to write a VBA script that reacts when a specific phrase occurs and automatically executes commands via inline commands. Essentially, when a phrase appears, an inputbox appears asking the user for a specific quantity and the VBA code takes that quantity, inserts it into the terminal and then jumps around different menus to create an internal label. However, my problem is that I don't know how to have the VBA code react to the different strings that may be returned by the host. Sometimes it says "enter to continue" and sometimes it says "select user". So what I want it to do is based on the statement it receives to do a certain action, but I don't know what the command is for capturing what the terminal is receiving from the host. I've tried "waitforstring" and "readline" but it is obvious I am not using them correctly. Below is the code I have built thus far, please be gentle as it is still very unfinished. I have commented out several parts of it in attempts to troubleshoot my problems:
'variable declarations
Dim count As Long 'var used to indicate how many times code should loop (how many labels should be print)
Dim drugname As String
Dim qtyinput As Long
Dim CR As String ' Chr(rcCR) = Chr(13) = Control-M
Dim LF As String ' Chr(rcLF) = Chr(10) = Control-J
Dim strcheck As String
'assign values to variables
count = 0
CR = Chr(Reflection2.ControlCodes.rcCR)
LF = Chr(Reflection2.ControlCodes.rcLF)
qtyinput = InputBox("Number of items being sent", Quantity)
drugname = .GetText(22, 15, 22, 46) ' StartRow:=22, StartColumn:=15,EndRow:=22, EndColumn:=46 'copies text from screen
' Press EditCopy (Copy the selection and put it on the Clipboard).
'.Copy rcSelection, rcAsPlainText -- not needed
.Transmit qtyinput & CR
.Transmit CR
'strcheck = .readline("00:00:01")
'MsgBox strcheck
'If .WaitForString("Press " & Chr(34) & "RETURN" & Chr(34) & " to continue, " & Chr(34) & "^" & Chr(34) & " to stop: ") Then .Transmit CR
'Select Case strcheck
' Case strcheck Like "to continue"
' .Transmit CR
'Case strcheck Like "*Select CLIENT*"
' .Transmit CR
'End Select
.Transmit "^MED" & CR
.Transmit "3" & CR
.Transmit "10" & CR
First of all, Attachmate is the company, and they have a few products for accessing Mainframe sessions from Windows including EXTRA! and Reflections, both of which share a common scripting language, which is nice and easy to use from within VBA.
However, EXTRA! tends to have fewer commands available to use than Reflections, which is the more expensive product, so you have to get a little creative with your VBA.
I think you are using EXTRA!, so the command you are looking for is "GetString"
I use VBA to interact with a mainframe session in EXTRA!, and I know that my mainframe command is successful when three stars appear on the screen in a certain position.
The mainframe command can take anywhere between 1 second and 5 minutes to complete, so I use "GetString" to poll the mainframe session every second, waiting for the three stars before I continue:
Do Until Sess0.Screen.GetString(14, 2, 3) = "***"
Application.Wait (Now + TimeValue("0:00:01"))
Loop
The syntax for "GetString" is: GetString(Row, Column, Length)
In my case the stars appear at row 14, column 2, and I know there will always be 3 of them, so I set my string length to 3.