How would I write this VB.Net loop functionally? - vb.net

I have a VB.Net function that translates a NameValueColletion to an IDictionary. How would I write this functionally (with Select, etc. instead of a loop)?
<Extension()>
Public Function ToDictionary(ByVal source As NameValueCollection)
As IDictionary(Of String, String)
Dim ret = New Dictionary(Of String, String)
Dim keys = source.Keys
For Each key In keys
Dim sKey = TryCast(key, String)
Dim sVal = TryCast(source(key), String)
If sKey Is Nothing OrElse sVal Is Nothing Then Continue For
ret(sKey) = sVal
Next
Return ret
End Function

Return source.Cast(Of String)().
ToDictionary(Function(key) key, Function(key) source(key))

Related

How to find a displayversion for a specific installed program in vb.net

I'm trying get a displayversion for a specific program in uninstall registry path. I can get it from a direct path or get the whole uninstall listed, but I cannot get it to find a specific program based on displayname and returns displayversion. Thank you if you can help or provide instruction.
Public Function GetDisplayLink() As String
On Error Resume Next
Dim strRegPath As String = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{772811A3-D34B-4594-AF3E-A7C655013E62}\"
Dim regVersion64 As Microsoft.Win32.RegistryKey = Microsoft.Win32.RegistryKey.OpenRemoteBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, strWorkstation, Microsoft.Win32.RegistryView.Registry64).OpenSubKey(strRegPath)
Dim strDisplayLink As String = regVersion64.GetValue("DisplayVersion")
GetDisplayLink = "DisplayLink Driver|" & strDisplayLink & "<BR>"
regVersion64 = Nothing
End Function
I cannot get it to find a specific program based on displayname and
returns displayversion.
There are several ways (WMI, Shell, Msi, ...)
WMI is the simplest one but slow
A sample with Msi, test with "Microsoft Silverlight" on Windows 10 =>
Dim sProductName As String = "Microsoft Silverlight"
Dim nResult As UInteger = 0
Dim sProductCode As StringBuilder = New StringBuilder(256)
Dim nIndex As Integer = 0
Do While (True)
nResult = MsiEnumProducts(nIndex, sProductCode)
If (nResult <> 0) Then
Exit Do
End If
Dim nSize As Integer = 256
Dim sbProductName As StringBuilder = New StringBuilder(nSize)
nResult = MsiGetProductInfo(sProductCode.ToString(), "InstalledProductName", sbProductName, nSize)
If (sbProductName.ToString() = sProductName) Then
nSize = 256
Dim sbVersionString As StringBuilder = New StringBuilder(nSize)
nResult = MsiGetProductInfo(sProductCode.ToString(), "VersionString", sbVersionString, nSize)
Console.WriteLine("Product: {0}", sProductName)
Console.WriteLine(vbTab + "Code: {0}", sProductCode.ToString())
Console.WriteLine(vbTab + "Version: {0}", sbVersionString.ToString())
Exit Do
End If
nIndex += 1
Loop
With declarations :
<DllImport("Msi.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function MsiEnumProducts(iProductIndex As Integer, lpProductBuf As StringBuilder) As UInteger
End Function
<DllImport("Msi.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function MsiGetProductInfo(szProduct As String, szAttribute As String, lpValueBuf As StringBuilder, ByRef pcchValueBuf As Integer) As UInteger
End Function

How build dynamic where clause with string argument

I try to buid a method to add a where clause to a Linq-to-SQL request (return an IQueryable). I try several methods but always use ToString, Indexof... but this result is a sql request take all element and the filter made in linq. I see request in SQL Server profiler.
I want a method to do it with result is a sql request with where include inside
I work in Visual Studio 2017 with SQL Server 2016. I code in vb.net
I see an interesting thing in linq dynamic library. But I can't to adapt to my situation
<Extension()> _
Public Function Where(ByVal source As IQueryable, ByVal predicate As String, ByVal ParamArray values() As Object) As IQueryable
If source Is Nothing Then Throw New ArgumentNullException("source")
If predicate Is Nothing Then Throw New ArgumentNullException("predicate")
Dim lambda As LambdaExpression = DynamicExpression.ParseLambda(source.ElementType, GetType(Boolean), predicate, values)
Return source.Provider.CreateQuery( _
Expression.Call( _
GetType(Queryable), "Where", _
New Type() {source.ElementType}, _
source.Expression, Expression.Quote(lambda)))
End Function
But I don't need all this complex strucutre. It's some years I buid my utilities. But Need to upgrade it. Here my code of my utilities
<Extension()>
Public Function Where(ByVal source As IQueryable, ByVal predicate As String) As IQueryable
Dim param = Expression.Parameter(GetType(String), "x")
Return source.Provider.CreateQuery(
Expression.Call(
GetType(Queryable), "Where",
New Type() {source.ElementType},
source.Expression, Expression.Quote(Expression.Lambda(Expression.Constant(predicate), param))))
End Function
Public Function TFOAppliqueFiltreTri(Of T, MaClassDatas As Class)(Origins As IQueryable(Of T), ByVal MesDonnees As TableFullOption.PagerTabEnCours(Of MaClassDatas)) As IQueryable(of T)
Dim retour As New TableFullOption.LstRetour
'Colonne de filtre
Dim strWh As String = ""
Dim Filtredrecords As IQueryable(Of T)
For Each Sort In MesDonnees.MesOptions
Dim colName = Sort.ColName
If strWh.Length > 0 Then strWh = strWh & " AND "
strWh = strWh & String.Format(colName & " like '%{0}%'", Sort.Search)
Next
If strWh.Length > 0 Then
Filtredrecords = Origins.Where(strWh) '<- Here call Where
Else
Filtredrecords = Origins
End If
Return Filtredrecords
End Function
I get this error:
Aucune méthode générique 'Where' sur le type 'System.Linq.Queryable' n'est compatible avec les arguments de type et les arguments fournis..
Then my problem is to write correctly lambda expression. My predicate argument is : Column1 like '%aaa%'. I want rewrite where method of dynamicLinq to accept string argument :Column1 like '%aaa%' directly
Thanks for your help
Finally after lot of reading in google and few feelings and certainly lot of chance.
Public Function Where(Of TEntity)(source As IQueryable(Of TEntity), searchColumn As List(Of String), searchValue As String) As IQueryable(Of TEntity)
Dim cond As Expression = Nothing
Dim ParamExpr = Expression.Parameter(GetType(TEntity), "x")
Dim conCat2 = GetType(String).GetMethod("Concat", New Type() {GetType(String), GetType(String)})
Dim conCat4 = GetType(String).GetMethod("Concat", New Type() {GetType(String), GetType(String), GetType(String), GetType(String)})
Dim Delim = Expression.Constant("/")
Dim DateName = GetType(SqlFunctions).GetMethod("DateName", New Type() {GetType(String), GetType(Nullable(Of DateTime))})
Dim DatePart = GetType(SqlFunctions).GetMethod("DatePart", New Type() {GetType(String), GetType(Nullable(Of DateTime))})
Dim DblToString = GetType(SqlFunctions).GetMethod("StringConvert", New Type() {GetType(Nullable(Of Double))})
For Each cn In searchColumn
For Each colName In cn.Split("|")
If Not colName.estVide Then
Dim body As Expression = ParamExpr
For Each member In colName.Split(".")
body = Expression.PropertyOrField(body, member)
Next
Dim Tostr As Expression
If body.Type.FullName.Contains("String") Then
Tostr = body
ElseIf body.Type.FullName.Contains("DateTime") Then
Dim day = Expression.Call(Expression.Call(conCat2, Expression.Constant("0"), Expression.Call(DateName, Expression.Constant("day"), body)), "Substring", Nothing, Expression.Constant(0), Expression.Constant(2))
Dim Month = Expression.Call(DatePart, Expression.Constant("MM"), body)
Dim toDouble = Expression.Convert(Month, GetType(Nullable(Of Double)))
Dim mois = Expression.Call(conCat2, Expression.Constant("0"), Expression.Call(Expression.Call(DblToString, toDouble), "Trim", Nothing))
Dim an = Expression.Call(DateName, Expression.Constant("year"), body)
Tostr = Expression.Call(conCat2, Expression.Call(conCat4, day, Delim, mois, Delim), an)
Else
Tostr = Expression.Call(body, "Convert.ToString", Nothing)
'Tostr = Expression.Convert(body, GetType(String))
End If
Dim condPart = Expression.Call(Expression.Call(Tostr, "ToLower", Nothing), "Contains", Nothing, Expression.Call(Expression.Constant(searchValue), "ToLower", Nothing))
If cond Is Nothing Then
cond = condPart
Else
cond = Expression.OrElse(cond, condPart)
End If
End If
Next
Next
Return source.Provider.CreateQuery(Of TEntity)(Expression.Call(GetType(Queryable), "Where", New Type() {GetType(TEntity)}, source.Expression, Expression.Lambda(cond, ParamExpr)))
End Function
Now I've dynamic filter which generated a SQL request with complete clause where

Better VB.NET String Scrambler?

I needed a function to take a string phrase and scramble it. So I wrote this, but I'm wondering if there is a more efficient/faster way to do it?
Public Function Scramble(phrase As String) As String
Dim rand As New Random()
Dim newPhrase As String = ""
Dim clist As New List(Of String)
' break phrase into characters and add to list
For i As Integer = 1 To Len(phrase)
clist.Add(Mid(phrase.ToLower(), i, 1))
Next
' remove from list randomly and add to new string
Do While clist.Count > 0
Dim r As Integer = rand.Next(0, clist.Count)
newPhrase &= clist(r)
clist.RemoveAt(r)
Loop
Return newPhrase
End Function
Here's Plutonix's one-liner:
Public Function Scramble(ByVal phrase As String) As String
Static rand As New Random()
Return New String(phrase.ToLower.ToCharArray.OrderBy(Function(r) rand.Next).ToArray)
End Function
...and here's an alternate version of your longer form:
Public Function Scramble(ByVal phrase As String) As String
Static rand As New Random()
Dim sb As New System.Text.StringBuilder
Dim chars As New List(Of Char)(phrase.ToLower.ToCharArray)
While chars.Count > 0
Dim r As Integer = rand.Next(0, chars.Count)
sb.Append(chars(r))
chars.RemoveAt(r)
End While
Return sb.ToString
End Function

Converting String to Structure

I am successfully converted structure data to string here in plain and (as suggested) in XML serialized way which obviously every has it's own good and bad side effects.
This is sample structure:
Public Structure myList
Dim a As String
Dim b As Integer
Dim c As Double
End Structure
Dim myInstance As New myList
myInstance.a = "Nemo"
myInstance.b = 10
myInstance.c = 3.14
Now I have 2 functions for converting structure data to string:
Dim xString As String = oStructToString(myInstance)
Public Function oStructToString(ByVal obj As Object) As String
Dim structString As String = ""
Dim i As Integer
Dim myType As Type = obj.GetType()
Dim myField As System.Reflection.FieldInfo() = myType.GetFields()
For i = 0 To myField.Length - 1
structString &= myField(i).GetValue(obj)
If i = myField.Length - 1 Then Exit For
structString &= Convert.ToChar(161)
Next i
Return structString
End Function
Dim xString As String = xStructToString(myInstance)
Public Function xStructToString(ByVal obj As Object) As String
Dim x As New Xml.Serialization.XmlSerializer(obj.GetType)
Dim sw As New IO.StringWriter()
x.Serialize(sw, obj)
Return sw.ToString
End Function
But I can't get data back from string to structure.
Public Function oStringToStruct(ByVal xString As String) As Object
So I can call:
Dim mySecondInstance As New myList = oStringToStruct(xString)
Or
Dim mySecondInstance As New myList = xStringToStruct(xString)
How to do that?
So far I came to this:
Public Function xStringToStruct(ByVal xString As String) As Object
Dim x As New Xml.Serialization.XmlSerializer() ''<- what here?
Dim sr As New IO.StringReader(xString)
Return x.Deserialize(sr)
End Function
and this...
By help of har07 still one error remains here...
Public Function oStringToStruct(ByVal xString As String, ByVal type As Type) As Object
Dim structString() As String = xString.Split(Convert.ToChar(161))
Dim myType As Type = type.GetType()
Dim myField As System.Reflection.FieldInfo() = myType.GetFields()
For i As Integer = 0 To structString.Length - 1
myField(i).SetValue(type, structString(i)) ''here crashes
Next i
Return type
End Function
Deserialize xml string back to struct is easier :
Public Function xStringToStruct(ByVal xString As String, ByVal type As Type) As Object
Dim x As New Xml.Serialization.XmlSerializer(type)
Dim sw As New IO.StringReader(xString)
Return x.Deserialize(sw)
End Function
You can use it like so :
Dim xObject As myList = xStringToStruct(xString, GetType(myList))

Building a multidimensional array in vb.net

I'm trying to build up a multidimensional array which will hold two bits of info for each record in a database e.g. id, description.
This is what I am currently doing.
Dim mArray(,) As String
Dim i As Integer = 0
While cmdReader.Read()
mArray(i,0) = cmdReader.Item("id")
mArray(i,1) = cmdReader.Item("description")
i = i + 1
End While
The problem I have here is that it doesn't like the i in mArray(i,0). Anyone have any ideas about this? This is the error that is given Object reference not set to an instance of an object.
Thanks for any and all help.
Nalum
Why not rather make use of List Class and Dictionary Class
You can rather then create a List of Dictionaries, with the key and value both strings. The key can then represent your key (id and description in your example, and the value can be what ever was stored).
Something like
Dim values As New List(Of Dictionary(Of String, String))()
and then in the while loop something like
values.Add(New Dictionary(Of String, String)() From { _
{"id", cmdReader.Item("id")} _
})
values.Add(New Dictionary(Of String, String)() From { _
{"description", cmdReader.Item("description")} _
})
You could then use foreach
For Each value As Dictionary(Of String, String) In values
Dim id As String = value("id")
Dim description As String = value("description")
Next
Or a for
For i As Integer = 0 To values.Count - 1
Dim value As Dictionary(Of String, String) = values(i)
Dim id As String = value("id")
Dim description As String = value("description")
Next
Try this
Dim mArray(1,1) As String
Dim i As Integer = 0
While cmdReader.Read()
mArray(i,0) = cmdReader.Item("id")
mArray(i,1) = cmdReader.Item("description")
i = i + 1
ReDim Preserve mArray(i,1)
End While
The problem is that you are not initializing the array.
This should work, until i will not reach the limits set in the initialization.
Dim mArray(100,100) As String
Dim i As Integer = 0
While cmdReader.Read()
mArray(i,0) = cmdReader.Item("id")
mArray(i,1) = cmdReader.Item("description")
i = i + 1
End While
But if the array limits are not known I suggest to follow astander's suggestion.
This works for me:
Dim values As New List(Of Dictionary(Of String, String))()
values.Add(New Dictionary(Of String, String)() From {{"quarter", q1.ToString}, {"year", y1.ToString}})
values.Add(New Dictionary(Of String, String)() From {{"quarter", q2.ToString}, {"year", y2.ToString}})
values.Add(New Dictionary(Of String, String)() From {{"quarter", q3.ToString}, {"year", y3.ToString}})
values.Add(New Dictionary(Of String, String)() From {{"quarter", q4.ToString}, {"year", y4.ToString}})
For Each value As Dictionary(Of String, String) In values
Dim quarter As String = value("quarter")
Dim year As String = value("year")
Debug.Print(quarter & "/" & year)
Next
Correct it by
Dim mArray(,) As String = ""