Remove duplicate items from processes array using VB .net - arrays

I have to code to get all accessible process, but I need to remove duplicated items on this array and show only one time each process.
How is the best method to do this, because I think processes array is not like a normal array.
My code:
For Each p As Process In Process.GetProcesses
Try
'MsgBox(p.ProcessName + " " + p.StartTime.ToString)
Catch ex As Exception
'Do nothing
End Try
Next
Thanks in advance

The Process.GetProcesses() method returns an array. You can use the Distinct method, providing an IEqualityComparer to it.
An example would be as comparer:
Public Class ProcessComparer
Implements IEqualityComparer(Of Process)
Public Function Equals1(p1 As Process, p2 As Process) As Boolean Implements IEqualityComparer(Of Process).Equals
' Check whether the compared objects reference the same data.
If p1 Is p2 Then Return True
'Check whether any of the compared objects is null.
If p1 Is Nothing OrElse p2 Is Nothing Then Return False
' Check whether the Process' names are equal.
Return (p1.ProcessName = p2.ProcessName)
End Function
Public Function GetHashCode1(process As Process) As Integer Implements IEqualityComparer(Of Process).GetHashCode
' Check whether the object is null.
If process Is Nothing Then Return 0
' Get hash code for the Name field if it is not null.
Return process.ProcessName.GetHashCode()
End Function
End Class
And you can use it like this:
Sub Main()
Dim processes As Process() = Process.GetProcesses()
Console.WriteLine(String.Format("Count before Distinct = {0}", processes.Length))
' Should contain less items
Dim disProcesses As Process() = processes.Distinct(New ProcessComparer()).ToArray()
Console.WriteLine(String.Format("Count after Distinct = {0}", disProcesses.Length))
Console.ReadLine()
End Sub
You probably have to refine the Comparer to your specifications and for the situation you are going to use it.

Related

Weird data type mismatch error VBA [duplicate]

I need to pass a String array to set a class property using its setter method. Array was declared in Module and it's perfectly set the values using Redim Preserve. When calling the Class setter method it gives error. If I continued to without setting array data type it worked. But I need to declare the data type as String.
I received a compile error "Type mismatch: array or user defined type expected."
Module
Dim sPageDetails() As String
' set some values to array
' Declare class instance
dim x as new X
with x
.SetPageNumberDetails(sPageDetails) ' assume SetPageNumberDetails is the setter method in class X
end with
End module
'class module start X
Private pageDetails() as String
' Setter for pageDetails array
Public Sub SetPageNumberDetails(ByRef sPageDetails() As String)
pageDetails= sPageDetails
End Sub
' Getter for pageDetails array
Public Function GetPageNumberDetails() As String()
GetPageNumberDetails= pageDetails
End Function
.SetPageNumberDetails(sPageDetails)
Remove the parentheses:
.SetPageNumberDetails sPageDetails
Remain the parentheses and add explicit 'Call':
Call .SetPageNumberDetails(sPageDetails)
It took 5-10 CPU ticks (~30 nsec), but code wil be more readable, editable, auditable etc. And it is simply comme il faut...
.

Converting a returned array from an async function to a regular array

It's been a while since I've written absolutely any code at all so I'm a little rusty. I've recently started writing a bot and am currently stuck on converting an array within an async function to a regular array to be parsed within another function.
Private Async Function getmsgs(ByVal num As Integer) As Task(Of Array)
Dim msgids As Array = Nothing
Try
Dim msg = Await Libx.DownloadMessages(num)
'starting loop to pull each message and assign to array
For i As Integer = msg.Count - 1 To 0 Step -1
If (msg(i).Id > 0) Then
msgids(i) = msg(i).Id
End If
Next
'returning array
Return msgids
Catch ex As Exception
Return msgids
End Try
End Function
Private Sub deletemsgs(ByVal ids As Array)
If Not ids(0) = Nothing Then
'incase library failed to retrieve messages
Try
For i As Integer = ids.Length - 1 To 0 Step -1
'function called per item in array
libx.DeleteMessages(ids(i))
Next
Catch ex As Exception
End Try
End If
End Sub
The issue occurs when trying to call deletemsgs(getmsgs(argint)).
I'm getting the error message
Value of type 'Task(Of Array)' cannot be converted to 'Array'
I've searched through a few forums with every relating search term I can think of. Any help would be greatly appreciated, cheers in advance.
You need to await async functions.
An example being:
Dim arr As Array() = await getmsgs(1)
This will need to be inside of an async function for it to work correctly.

How to retrieve a VB Control instance, given its Name and Index?

If I have a string "cboEnoughMoney(0)", is it possible to retrieve the control from a control array that I have in my form, cboEnoughMoney?
In my code, I try to refer to the control in this way:
frm.Controls(sControlName).ListIndex = -1
sControlName in this case is "cboEnoughMoney(0)" and I get an error that the control was not found.
EDIT: One of the issue's i'm having is trying to as above set the .listindex to -1, another one is where I actually try to get and set value to the combobox. In a function - i pass form name as parameter called frm.
In the code what has been done is this....
dim ctlData as string
If Frm.Controls(RS!CTRLname).ListIndex > 0 Then
CtlData = Frm.Controls(RS!CTRLname).Value
Else
CtlData = ""
End If
Any idea how I'd be able to do that with cboEnoughMoney(0)....
I assume I could follow your example and check
if instr(1,RS!CTRLname, "(")
but if there is, how would I refer to that particular control in frm
It is just enough to look in the VB Properties Window: if you search "cboEnoughMoney(0)" you will find "cboEnoughMoney"(0) (without double quotes). Still the name is the same as a non-array control.
So, it is perfectly legal to refer to a VB Control with Name and Index, no need for a controls loop here:
If isControlsArray Then
Set ctrl = Me.Controls(Name)(Index) '// array
Else
Set ctrl = Me.Controls(Name) '// non array
End If
You cannot use the (index) part in a lookup via .Controls.
You can loop them manually & given that you can safely assume any control name with a ( is an array member and thus will have an Index property match on that:
Private Function GetControl(ByVal name As String) As VB.Control
Dim pos As Long: pos = InStr(name, "(")
If pos = 0 Then
Set GetControl = Me.Controls(name) '// non array
Else
Dim index As Long
index = Val(Mid$(name, pos + 1)) '// get index #
name = Left$(name, pos - 1) '// get base name
For Each GetControl In Me.Controls
If (GetControl.name = name) Then
If (GetControl.index = index) Then Exit Function
End If
Next
Set GetControl = Nothing
End If
End Function
And then:
GetControl("cboEnoughMoney(1)").ListIndex = -1

How do i pass values from view model to controller without use of list?

Continuing from my previous question, i pass the id value from 'Lookup' controller to another controller method 'Charges'.
Function Charges(id As String) As ActionResult
Dim Patient As New LookupVM()
Patient.GetHistory(paid)
Return View(Patient)
End Function
In the view model, i have the GetHistory(id) list method, and listProcedure is the list holding the values that i want to pass back to the controller to be displayed in the view.
Public Property listProcedure As List(Of LookupVM)
Public Function GetHistory(id As String) As List(Of LookupVM)
Using db As New DbContext()
' SQL query
'====================
Dim idd = New SqlParameter("#id", "%" & id & "%")
Dim query As String = "select p.id id, pv.pvid pvid
from patient p
join patient_visit pv on p.id = pv.id
where p.paid like #id"
Dim Results = db.Database.SqlQuery(Of LookupVM)(query, idd).ToList()
For Each item In Results
Dim pvid = New SqlParameter("#pvid", "%" & item.pvid & "%")
Dim query2 As String = "select po.remarks remarks, po.entereddt entereddt, po.Consultant Consultant
from procedure_order po
join procedures p on po.pdid = p.pdid
where po.pvid like #pvid
order by po.entereddt desc"
Dim Results2 = db.Database.SqlQuery(Of LookupVM)(query2, pvid).ToList()
For Each item2 In Results2
Dim ProcedureList2 As New LookupVM()
ProcedureList2.remarks = item2.remarks
ProcedureList2.entereddt = item2.entereddt
ProcedureList2.ForConsultant = item2.ForConsultant
listProcedure.Add(ProcedureList2)
Next
Next
Return listProcedure
End Using
End Function
I'm wondering if i'm able to pass those values to the controller through something else other than a list. if possible, what could it be? Because if its a list, i can't display them on the page without the use of foreach loop.
Another question is, is my code conceptually correct or wrong? Because when i run, it took me 5 minutes to display a list of 72 values which involves the code above. I think it took way too long. Is there any way to make it load faster?
About the List, there is nothing wrong with doing For Each in a View. If it is needed then it is needed, and no reason to avoid it.
Some query tips (it is hard to do better for lack of details):
If your paid and pvid columns are INT, then do not query them using LIKE #id but using = #id (without % in it). Even if they are (N)VARCHAR then using LIKE would need to be justified and explicit. If done by accident then output will often be wrong.
LIKE '%value%' causes indexes to be ignored, possibly leading to bad performance.
Make sure that you have indexes on the columns that you use to JOIN on.
Try combining the two queries into one, to limit the number of .NET/DB roundtrips.

why is the index of the one-dimensional array changing this way?

I'm a beginner and I'm encountering a problem with an index of a one-dimensional array of strings (m_nameList in the code) that I'm struggling to understand. I have one method (in a class of a Windows Form Application that is not the MainForm) that returns FALSE if a string of the array at a certain index is empty, and viceversa. It looks like this:
Public Function IsReserved(index As Integer) As Boolean
Dim reserved As Boolean = False
If (Not String.IsNullOrEmpty(m_nameList(index))) Then
reserved = True
Else
reserved = False
End If
Return reserved
End Function
I have also a method on the MainForm that calls for it, and if the first method returns true then the second one displays a dialog box, otherwise it doesn't (lstResults is a listbox that has for items the strings of the array):
Private Function CheckIfSeatIsAlreadyReserved() As Boolean
Dim reserved As Boolean = m_seatMngr.IsReserved(lstResults.SelectedIndex)
If (reserved) Then
Dim msgBox As Integer = MessageBox.Show("The seat is already reserved. Would you like to continue?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If (msgBox = DialogResult.Yes) Then
Return True
Else
Return False
End If
Else
Return True
End If
End Function
The problem I find is: if as in the code of the first method above I don't initialize index to any value, the second method will work perfectly, but I'll get a runtime error if I don't select any item on the listBox (and therefore index = -1). On the other hand, if I initialize index to 0 or to m_nameList.Length, then the program won't have any problems if I don't select any item on the ListBox and it will nicely display a warning message I wrote for that case, BUT the second method will behave in a weird way: it will find ALL the strings of the array full even if I only "write" the first one, or it will find ALL the strings empty if I "write" any string that it's not the first one (by writing I mean that I call for a method that puts my input as the text of the string selected). Any idea on why this happens and how I can fix it? Thank you so much.
I will get to the answer below, follow the logic, lets look at your first method. You can refactor it to
Public Function IsReserved(index As Integer) As Boolean
Return Not String.IsNullOrEmpty(m_nameList(index))
End Function
Everything else is called "noise". But as Fabio pointed, what if index is bad? Lets add useful code
Public Function IsReserved(index As Integer) As Boolean
If index < 0 OrElse index > m_nameList.Length - 1 Then
Throw New ArgumentOutOfRangeException(". . . . .")
End If
Return Not String.IsNullOrEmpty(m_nameList(index))
End Function
If you get this exception, your program has a bug - and you know to fix the consumer of this function.
And now lets get to your message
second method will behave in a weird way: it will find ALL the strings of the array full even if I only "write" the first one, or it will find ALL the strings empty if I "write" any string
Most likely reason why it happens - simply because you create condition when you send same value over and over again. Therefore result is same. And this is most likely a bug
If (reserved) Then
. . . . . .
Else
Return True ' <---- BUG ALLERT
End If
And two more things, your second method can shrink down to 1 line too.
Private Function CheckIfSeatIsAlreadyReserved() As Boolean
Return m_seatMngr.IsReserved(lstResults.SelectedIndex) AndAlso _
DialogResult.Yes = MessageBox.Show("The seat is already reserved. Would you like to continue?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
End Function
And, if you do some sort of reservation, array is not really good idea. How about Dictionary(Of String, Boolean)? Your theater or airplane has bunch of seats and you pre-load your dictionary with those
d.Add("1A", False)
d.Add("1B", False)
d.Add("1C", False)
d.Add("1D", False)
d.Add("1E", False)
d.Add("1F", False)
This is your whole airplane row. Now you can do much more with it

Resources