WinAPI CredEnumerate Marshal.PtrToStructure Exception - vb.net

I have problems with enumerating Windows Credentials from VB.Net application with WinAPI functions. My code is below.
<DllImport("advapi32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Private Shared Function CredEnumerate(filter As String, flag As Integer, ByRef count As Integer, ByRef pCredentials As IntPtr) As Boolean
End Function
Public Enum CRED_PERSIST As UInteger
SESSION = 1
LOCAL_MACHINE = 2
ENTERPRISE = 3
End Enum
Public Enum CRED_TYPE As UInteger
GENERIC = 1
DOMAIN_PASSWORD = 2
DOMAIN_CERTIFICATE = 3
DOMAIN_VISIBLE_PASSWORD = 4
GENERIC_CERTIFICATE = 5
DOMAIN_EXTENDED = 6
MAXIMUM = 7
' Maximum supported cred type
MAXIMUM_EX = (MAXIMUM + 1000)
' Allow new applications to run on old OSes
End Enum
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
Public Structure CREDENTIAL_ATTRIBUTE
Private Keyword As String
Private Flags As UInteger
Private ValueSize As UInteger
Private Value As IntPtr
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Private Class Credential
Public Flags As UInt32
Public Type As CRED_TYPE
Public TargetName As String
Public Comment As String
Public LastWritten As ComTypes.FILETIME
Public CredentialBlobSize As UInt32
Public CredentialBlob As IntPtr
Public Persist As CRED_PERSIST
Public AttributeCount As UInt32
Public Attributes As IntPtr
Public TargetAlias As String
Public UserName As String
End Class
Private Function GetCredentials() As Credential()
Dim count As Integer = 0
Dim pCredentials As IntPtr = IntPtr.Zero
Dim credentials As List(Of Credential) = New List(Of Credential)
Dim ret As Boolean = CredEnumerate(Nothing, 0, count, pCredentials)
If ret <> False Then
Dim p As IntPtr = pCredentials
For n As Integer = 0 To count - 1
If Marshal.SizeOf(p) = 4 Then
p = New IntPtr(p.ToInt32() + n)
Else
p = New IntPtr(p.ToInt64() + n)
End If
credentials.Add(Marshal.PtrToStructure(Marshal.ReadIntPtr(p), GetType(Credential)))
Next
End If
Return credentials.ToArray
End Function
Marshal.PtrToStructure function throws System.ExecetionEngineException without any useful information. I suspected with wrong credential structure but it seems correct to me. If you have any idea about what is wrong, I'm waiting your answers.
Thanks
Edit: Thanks to #Zaggler here is my corrected function now it adds credentials to array but whole structure is empty.
Here is new function.
Private Function GetCredentials() As Credential()
Dim count As Integer = 0
Dim pCredentials As IntPtr = IntPtr.Zero
Dim credentials As List(Of Credential) = New List(Of Credential)
Dim ret As Boolean = CredEnumerate(Nothing, 0, count, pCredentials)
If ret <> False Then
Dim p As IntPtr = pCredentials
For n As Integer = 0 To count - 1
Dim cred As Credential = New Credential
Dim pnt As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(cred))
Try
If Marshal.SizeOf(p) = 4 Then
p = New IntPtr(p.ToInt32() + n)
Else
p = New IntPtr(p.ToInt64() + n)
End If
Marshal.StructureToPtr(cred, pnt, False)
credentials.Add(Marshal.PtrToStructure(pnt, GetType(Credential)))
Finally
Marshal.FreeHGlobal(pnt)
End Try
Next
End If
Return credentials.ToArray
End Function

Your first attempt was better. Don't use AllocHGlobal and FreeHGlobal. Winapi is allocating memory. Lookup CredFree to release allocated memory (after marshalling structs).
There is a mistake in your pointer arithmetic. You have to increment with pointer size so try:
...
Dim p As IntPtr = pCredentials
For n As Integer = 0 To count - 1
credentials.Add(Marshal.PtrToStructure(Marshal.ReadIntPtr(p), GetType(Credential)))
p = p + IntPtr.Size
Next
...
UInt32 and UInteger are the same, so be consistent and choose one.
You could try to use Charset.Auto for everything, if that doesn't work, try Charset.Unicode and use CredEnumerateW function.

Related

Cross Correlation in .NET

I am working on an app that takes two audio channels and compares them to find the phase difference (delay). I came across this post;
Calculating FFT Correlation Coefficient
which refers to this sample code;
https://dotnetfiddle.net/1nWIgQ
I got the code working with correct results after translating it to VB.NET (its the language I started with years ago in this app).
The problem I see is that when I change the signal generated from random noise to a sine wave, then the code gives crazy unrelated results. Any suggestions would be appreciated.
Code below;
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports AForge.Math 'NuGet Package Aforge.Math module
Imports System.Runtime.InteropServices
Imports System.IO
Public Class Form2
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim c = New Xcorr4_2()
Dim size As Integer = 2048
Dim delay As Double
delay = 2
Dim signal1 = c.GenerateSignal(size)
Dim signal2 = c.GenerateSignal(size, delay)
Dim signal1Complex = c.ToComplexWithPadding(signal1, 2)
Dim fftSignal1 = c.FFT(signal1Complex)
Dim signal2Complex = c.ToComplexWithPadding(signal2, 2)
Dim fftSignal2 = c.FFT(signal2Complex)
Dim cc = c.CorrelationCoefficient(fftSignal1.ToArray(), fftSignal2.ToArray())
MsgBox(cc.Item1) 'correlation coeff
MsgBox(cc.Item2) 'recovered delay
End Sub
End Class
Class Xcorr4_2
Public Function CrossCorrelation(ByVal ffta As Complex(), ByVal fftb As Complex()) As Complex()
Dim conj = ffta.[Select](Function(i) New Complex(i.Re, -i.Im)).ToArray()
conj = conj.Zip(fftb, Function(v1, v2) Complex.Multiply(v1, v2)).ToArray()
FourierTransform.FFT(conj, FourierTransform.Direction.Backward)
Dim rr As Double() = New Double(conj.Length - 1) {}
rr = conj.[Select](Function(i) i.Magnitude).ToArray()
Return conj
End Function
Public Function CorrelationCoefficient(ByVal ffta As Complex(), ByVal fftb As Complex()) As Tuple(Of Double, Integer)
Dim tuble As Tuple(Of Double, Integer)
Dim correlation = CrossCorrelation(ffta, fftb)
Dim seq = correlation.[Select](Function(i) i.Magnitude)
Dim maxCoeff = seq.Max()
Dim maxIndex As Integer = seq.ToList().IndexOf(maxCoeff)
tuble = New Tuple(Of Double, Integer)(maxCoeff, maxIndex)
Return tuble
End Function
Public Function FFT(ByVal signal As Complex()) As Complex()
FourierTransform.FFT(signal, FourierTransform.Direction.Forward)
Return signal
End Function
Public Function IFFT(ByVal signal As Complex()) As Complex()
FourierTransform.FFT(signal, FourierTransform.Direction.Backward)
Return signal
End Function
Public Function ToComplexWithPadding(ByVal sample As Double(), ByVal Optional padding As Integer = 1) As Complex()
Dim logLength As Double = Math.Ceiling(Math.Log(sample.Length * padding, 2.0))
Dim paddedLength As Integer = CInt(Math.Pow(2.0, Math.Min(Math.Max(1.0, logLength), 14.0)))
Dim complex As Complex() = New Complex(paddedLength - 1) {}
Dim samples = sample.ToArray()
Dim i As Integer = 0
While i < sample.Length
complex(i) = New Complex(samples(i), 0)
i += 1
End While
While i < paddedLength
complex(i) = New Complex(0, 0)
i += 1
End While
Return complex
End Function
Public Function GenerateSignal(ByVal size As Integer, ByVal Optional shift As Integer = 0) As Double()
Dim list As List(Of Double) = New List(Of Double)()
Dim generator = New AForge.Math.Random.StandardGenerator()
' Changed original random signal to Sine wave below
For i As Integer = 0 To size - 1
'Dim randomNumber As Double = generator.[Next]()
'list.Add(randomNumber)
list.Add(Math.Sin(2 * Math.PI / 200 * i + shift))
Next
Dim list2 As List(Of Double) = New List(Of Double)()
For i As Integer = 0 To shift - 1
list2.Add(0)
Next
Dim ar = list.ToArray()
For i As Integer = 0 To size - shift - 1
list2.Add(ar(i))
Next
Return list2.ToArray()
End Function
End Class
Below is the output for original code vs the modified code with sine wave.
Original code random signal
Modified with sine wave inputs

How to use GetType and GetFields?

I'm updating a program and there is about 40 classes. I need to create a function that takes two lists of type object as parameters. Both lists only have one item in them (A version of the item BEFORE any changes were made, and AFTER the changes happened). I'm using these objects to create a single object to implement an UNDO button. With these parameters I need to get the type of each and make sure they match, if not then something went wrong. Next I'll need to read in the fields/properties/members (Not sure what to choose) and then compare them to each other and find what changed so I can set that as the item description. I don't want to trace the whole code and add specific functions for each and I know there has got to be a way to do this generically. I have created this small mock-up program that semi works for what I am trying to do. I can get the class type out of the object in list, but i have no idea how to get fields or whatever.
I'm using a large database with entity framework.
Also Using VB.NET!
Thanks for the help!
Here's code for generic program:
Imports System.Reflection
Module Module1
Sub Main()
Dim Myself As New Human("Matthew", "Cucco", Now, "Blonde", 19, False)
Dim NotMe As New Human("Jake", "Cucco", Now, "Blonde", 19, False)
Dim Him As New Employee("Matt", "Cucco", Now, "Blonde", 19, False, 215, "LuK", True)
Dim Her As New Customer("Jessie", "Keller", Now, "Blonde", 19, True, 25, "Cereal", "me#gmail.com")
Dim ListofPeople As IList(Of Object) = {Myself, NotMe, Him, Her}
Dim ListofPeople2 As IList(Of Object) = {Myself, NotMe, Him, Her}
ObjectsAreSameClass(ListofPeople, ListofPeople2)
Console.ReadKey()
End Sub
Private Function ObjectsAreSameClass(object1 As IList(Of Object), object2 As IList(Of Object)) As Boolean
Dim ObjectType As Type = object1.First.GetType()
Dim AreSameClass As Boolean = Nothing
Console.WriteLine(ObjectType.ToString)
If (object1.First.GetType() = object2.First.GetType()) Then
AreSameClass = True
Console.WriteLine("Object1 is of type: " + object1.First.GetType().Name)
Console.WriteLine("Object2 is of type: " + object2.First.GetType().Name)
If (object1.First.GetType().Name = "Human") Then
Console.WriteLine("Yep this works")
End If
Else
AreSameClass = False
Console.WriteLine("Object1 is of type: " + object1.First.GetType().Name)
Console.WriteLine("Object2 is of type: " + object2.First.GetType().Name)
If (object1.First.GetType().Name = "Human") Then
Console.WriteLine("Yep this works")
Console.WriteLine(object1.First.GetType().GetFields().ToString)
End If
End If
Dim MyField As PropertyInfo() = ObjectType.GetProperties()
Dim i As Integer
For i = 0 To MyField.Length - 1
Console.WriteLine(MyField(i).ToString)
Next i
Console.WriteLine("Objects are equal? t/f : " + AreSameClass.ToString)
Return AreSameClass
End Function
Public Class Human
Public FirstName As String
Public LastName As String
Public Birthdate As Date
Public HairColor As String
Public Age As Integer
Public Gender As Boolean 'False for male, true for female
Public Sub New()
FirstName = ""
LastName = ""
Birthdate = Now
HairColor = ""
Age = 0
Gender = False
End Sub
Public Sub New(f As String, l As String, b As Date, h As String, a As Integer, g As Boolean)
FirstName = f
LastName = l
Birthdate = b
HairColor = h
Age = a
Gender = g
End Sub
End Class
Public Class Employee
Inherits Human
Dim EmployeeId As Integer
Dim PlaceOfEmployment As String
Dim IsManager As Boolean
Public Sub New()
MyBase.New()
EmployeeId = 0
PlaceOfEmployment = ""
IsManager = False
End Sub
Public Sub New(f As String, l As String, b As Date, h As String, a As Integer, g As Boolean, i As Integer, p As String, m As Boolean)
MyBase.New(f, l, b, h, a, g)
EmployeeId = i
PlaceOfEmployment = p
IsManager = m
End Sub
End Class
Public Class Customer
Inherits Human
'used for testing
Dim IdNumber As Integer
Dim FavoriteItem As String
Dim email As String
Public Sub New()
MyBase.New()
IdNumber = 0
FavoriteItem = ""
email = ""
End Sub
Public Sub New(f As String, l As String, b As Date, h As String, a As Integer, g As Boolean, i As Integer, fav As String, e As String)
MyBase.New(f, l, b, h, a, g)
IdNumber = i
FavoriteItem = fav
email = e
End Sub
End Class
End Module
This Currently displays this:
TestProject.Module1+Human
Object1 is of type: Human
Object2 is of type: Human
Yep this works
Objects are equal? t/f : True
Also for reference, here is my main program that I will be implementing this into:
Function NewItem(Before As IEnumerable(Of Object), After As IEnumerable(Of Object), ObjectType As String)
ObjectsAreSameClass(Before, After, ObjectType) 'Check if objects are same class
Dim BeforeFields() As FieldInfo = GetFieldData(Before) 'gets all field info, saves to an array
Dim AfterFields() As FieldInfo = GetFieldData(After)
'Now check and make sure the objects are not the same
Dim ThisChanged As FieldInfo
If (ObjectValuesAreEqual(BeforeFields, AfterFields) = True) Then
'These objects did not not change
ThisChanged = Nothing
Else
'Change occured, find out where
ThisChanged = FindWhatChanged(BeforeFields, AfterFields)
End If
'Create a new UndoRedo item and give it these values
Dim UndoRedoNow As New ClsUndoRedo
UndoRedoNow.BeforeObject = Before.Single
UndoRedoNow.AfterObject = After.Single
UndoRedoNow.ObjectCounter += 1
UndoRedoNow.WhatChanged = ThisChanged
If WhatGroupChanged.isDeleted Then
UndoRedoNow.WhatAction = Before.Single.GetType().ToString + " item was Deleted"
ElseIf WhatGroupChanged.isNew Then
UndoRedoNow.WhatAction = After.Single.GetType().ToString + " item was created"
ElseIf WhatGroupChanged.isChanged Then
UndoRedoNow.WhatAction = After.Single.GetType().ToString + " item was changed"
End If
UndoRedoNow.WhatGroupChanged.isRedo = False 'Make sure it is not a redo object
'Now add object to list
ChangeLog.Add(UndoRedoNow)
Return Nothing
End Function
Private Function ObjectsAreSameClass(before As IEnumerable(Of Object), after As IEnumerable(Of Object), WhatType As String) As Boolean
Dim AreSameClass As Boolean = False
Try
If (before.Single.GetType() = after.Single.GetType() Or (before Is Nothing) Or (after Is Nothing)) Then
'Objects are of the same class or nothing
If before Is Nothing Then
WhatGroupChanged.isNew = True 'New item
ElseIf after Is Nothing Then
WhatGroupChanged.isDeleted = True 'Deleted item
Else
WhatGroupChanged.isChanged = True 'item was changed
End If
AreSameClass = True
End If
Catch
'Need to raise error
End Try
Return AreSameClass
End Function
''' <summary>
''' This function will return all of the fields for a certain class as well as the data stored in them
''' </summary>
''' <param name="list"></param>
''' <returns></returns>
Public Shared Function GetFieldData(ByVal list As IList(Of Object)) As FieldInfo()
Dim fields() As FieldInfo = list.Single.GetType().GetFields()
Return fields
End Function
''' <summary>
''' This function will check that the values in the datafields are not equal
''' </summary>
''' <param name="Before"></param>
''' <param name="After"></param>
''' <returns></returns>
Private Function ObjectValuesAreEqual(Before() As FieldInfo, After() As FieldInfo) As Boolean
Dim isEqual As Boolean = New Boolean 'This will keep track of if the elements are equal or not
For index As Integer = 0 To (Before.Count - 1)
If Before.ElementAt(index).GetValue(Before.ElementAt(index)).Equals(After.ElementAt(index).GetValue(After.ElementAt(index))) Then
'They are equal so set to true
isEqual = True
Else
'They are not equal so set to false and return
isEqual = False
Return isEqual
End If
Next
Return isEqual
End Function
Private Function FindWhatChanged(Before() As FieldInfo, After() As FieldInfo) As FieldInfo
Dim ThisIsChange As FieldInfo
For index As Integer = 0 To (Before.Count - 1)
If Before.ElementAt(index).GetValue(Before.ElementAt(index)).Equals(After.ElementAt(index).GetValue(After.ElementAt(index))) Then
ThisIsChange = After.ElementAt(index)
Return ThisIsChange
Else
'Raise error
End If
Next
End Function
The proper way to preserve type information when working with unknown types is to write a generic function (and if necessary generic classes, structures, etc.).
Using GetType, in a perfect world, should never be needed.
Generic functions look like this:
Public Function MyGenericFunction(Of T)(myArg as T) as Integer
' do something with myArg1, myArg2 ... without knowing their exact type
Return 0
End Function
' or with multiple types
Public Function MyGenericFunction2(Of T1, T2, ... )(myArg1 as T1, myArg2 as T2, ...) as T1()
' do something with myArg1, myArg2 ... without knowing their exact type
Return { myArg1 }
End Function
When you call these functions, the generic types are usually automatically deduced from the arguments you passed. If they can't be guessed, you will need to explicitly annotate the types, like this:
Dim x = MyGenericFunction(Of SomeClass1)(foo)
Dim x = MyGenericFunction(Of SomeClass2)(foo)
A full guide here: https://msdn.microsoft.com/en-us/library/w256ka79.aspx
However, if you need to handle specific types with the same function, then what you want to do use is a more narrow tool: overloading, or more technically parametric polymorphism.
What that means is, you will need to provide two (or more) different definitions of the same function ( = having the same name), that accept parameters of different types.
A simple example:
Public Class MyClass1
Public Foo1 As String = "foo1"
End Class
Public Class MyClass2
Public Foo2 As String = "foo2"
End Class
Public Sub MyFunction(arg as MyClass1)
Console.WriteLine(arg.Foo1)
End Sub
Public Sub MyFunction(arg as MyClass2)
Console.WriteLine(arg.Foo2)
End Sub
Dim x as Object
' let's give x a random value of either MyClass1 or MyClass2,
' and we don't know in advance which one
If DateTime.Today.DayOfWeek = DayOfWeek.Tuesday Then
x = new MyClass1
Else
x = new MyClass2
End If
' the program will automatically invoke the correct function based on x's value, and print either "foo1" or "foo2"
MyFunction(x)

Lempel-Ziv-Welch algorithm

Heys guys,
I'm trying to implement the Lempel-Ziv-Welch algorithm on byte level in VB.NET. Here is what the Code looks like so far:
Dim FileBytes As Byte() = {Convert.ToByte(12), Convert.ToByte(13), Convert.ToByte(12), Convert.ToByte(13), Convert.ToByte(12), Convert.ToByte(13)}
Dim bw As New BitWriter(New BinaryWriter(New FileStream(output, FileMode.Create)))
Dim ByteDictionary As New Dictionary(Of Byte(), Integer)
Dim DictionaryN As Integer = 1
Dim DictionaryMax As Integer = 4048
Dim outputs As New List(Of Integer)
Dim bts As New List(Of Byte)
For index As Integer = 0 To FileBytes.Length - 1
Dim currentbyte As Byte = FileBytes(index)
If ContainsByte(ByteDictionary, AddToList(bts, currentbyte).ToArray) Then
bts.Add(currentbyte)
Else
If bts.Count > 1 Then
ByteDictionary.Add(bts.ToArray, 255 + DictionaryN)
DictionaryN += 1
Else
ByteDictionary.Add(New Byte() {currentbyte}, currentbyte)
End If
Console.WriteLine(GetByteValue(ByteDictionary, bts.ToArray))
bts.Clear()
bts.Add(currentbyte)
End If
Next
End Sub
Public Function ContainsByte(ByVal dic As Dictionary(Of Byte(), Integer), ByVal bt As Byte()) As Boolean
Dim flag = True
For Each kp As KeyValuePair(Of Byte(), Integer) In dic
If ByteArrayEquals(kp.Key, bt) Then
Return True
End If
Next
Return False
End Function
Public Function AddToList(ByVal list As List(Of Byte), ByVal bt As Byte) As List(Of Byte)
Dim newlist = New List(Of Byte)(list)
newlist.Add(bt)
Return newlist
End Function
Public Function ByteArrayEquals(ByVal first As Byte(), ByVal second As Byte()) As Boolean
If first.Length = second.Length Then
Dim flag = True
For index As Integer = 0 To first.Length - 1
If first(index) <> second(index) Then
flag = False
End If
Next
Return flag
Else
Return False
End If
End Function
Public Function GetByteValue(ByVal dic As Dictionary(Of Byte(), Integer), ByVal bt As Byte()) As Integer
For Each kp As KeyValuePair(Of Byte(), Integer) In dic
If ByteArrayEquals(kp.Key, bt) Then
Return kp.Value
End If
Next
End Function
The idea behind my implementation is from https://www.cs.cf.ac.uk/Dave/Multimedia/node214.html . But somehow it doesn't work, it simply puts out the input bytes. What is wrong with it?
The main problem is these two lines:
If bts.Count > 1 Then
ByteDictionary.Add(bts.ToArray, 255 + DictionaryN)
In both lines here you're using bts where you should be using bts + currentByte, i.e. you want something like
Dim currentbyte As Byte = FileBytes(index)
Dim btsPlusCurrentByte As List(Of Byte) = AddToList(bts, currentbyte)
If ContainsByte(ByteDictionary, btsPlusCurrentByte.ToArray) Then
bts.Add(currentbyte)
Else
If btsPlusCurrentByte.Count > 1 Then
ByteDictionary.Add(btsPlusCurrentByte.ToArray, 255 + DictionaryN)
The other problem is that you'll complete the loop with data left in bts that you haven't output, so I think you'll need a block to do that afterwards. It may be safe to just do
Console.WriteLine(GetByteValue(ByteDictionary, bts.ToArray))
again after the Next but I haven't thought about that very carefully.
I also think you should be able to use .NET's own built-ins rather than your four helper functions.

Merge two Array Properties in Class

I have a Class (TestClass) with the following three properties:
Private myArr1() As String
Private myArr2() As String
Private myFinalArray() As String
Private Sub Class_Initialize()
ReDim myArr1(0 To 3)
ReDim myArr2(0 To 2)
ReDim myFinalArray(0 To 6)
End Sub
Public Property Get arr1(ByVal index As Long) As Double
arr1 = myArr1(index)
End Property
Public Property Let arr1(ByVal index As Long, ByVal myvalue As Double)
myArr1(index) = myvalue
End Property
Public Property Get arr2(ByVal index As Long) As Double
...
Public Property Let arr2(ByVal index As Long, ByVal myvalue As Double)
...
Public Property Get FinalArray(ByVal index As Long) As Double
...
Public Property Let FinalArray(ByVal index As Long, ByVal myvalue As Double)
...
Here we have just two arrays that I fill with data:
Sub test()
Dim t As TestClass
Set t = New TestClass
For i = 0 To 3
t.arr1(i) = i
Next
For i = 0 To 2
t.arr2(i) = i
Next
t.GetFinalValues (t)
End Sub
My Problem now is that these array elements must be rearranged according to a confused pattern I want to write a property for that but it is not working. My idea was to add the following function to my class:
Public Function GetFinalValues(ByRef t As TestClass) As Double()
'Imput parameter arrX can ben the Value as well as the Bench arrays.
Dim arr1(2) As Double
Dim arr2(3) As Double
Dim i As Integer
Dim arrCollection(6) As Double
arrCollection(0) = t.arr1(0)
arrCollection(1) = t.arr2(0)
arrCollection(2) = t.arr2(1)
arrCollection(3) = t.arr1(1)
arrCollection(4) = t.arr2(2)
arrCollection(6) = t.arr1(2)
arrCollection(5) = t.arr2(3)
'Assign return object
For i = 0 To 6
FinalArray(i) = arrCollection(i)
Next i
GetFinalValues
End Function
If I run this the code stops at t.GetFinalValues(t) giving me the Errormessage: Object doesent support property or method. Anyone who can help me get this working? Or has a rebuild idea for a even better solution to that problem?
EDIT: I added vb.net since this might be a construction problem that is not specified to vba
You have two issues:
First you should remove the parentheses from this line:
t.GetFinalValues (t)
so it's just:
t.GetFinalValues t
Then your function needs to return a String array not Double, since that's the type of the private variable. Your class code becomes something like this:
Private Sub Class_Initialize()
ReDim myArr1(0 To 3)
ReDim myArr2(0 To 2)
ReDim myFinalArray(0 To 6)
End Sub
Public Property Get arr1(ByVal index As Long) As Double
arr1 = myArr1(index)
End Property
Public Property Let arr1(ByVal index As Long, ByVal myvalue As Double)
myArr1(index) = myvalue
End Property
Public Property Get arr2(ByVal index As Long) As Double
arr2 = myArr1(index)
End Property
Public Property Let arr2(ByVal index As Long, ByVal myvalue As Double)
myArr2(index) = myvalue
End Property
Public Property Get FinalArray(ByVal index As Long) As Double
FinalArray = myArr1(index)
End Property
Public Property Let FinalArray(ByVal index As Long, ByVal myvalue As Double)
myFinalArray(index) = myvalue
End Property
Public Function GetFinalValues(ByRef t As TestClass) As String()
'Imput parameter arrX can ben the Value as well as the Bench arrays.
Dim arr1(2) As Double
Dim arr2(3) As Double
Dim i As Integer
Dim arrCollection(6) As Double
arrCollection(0) = t.arr1(0)
arrCollection(1) = t.arr2(0)
arrCollection(2) = t.arr2(1)
arrCollection(3) = t.arr1(1)
arrCollection(4) = t.arr2(2)
arrCollection(6) = t.arr1(2)
arrCollection(5) = t.arr1(3)
'Assign return object
For i = 0 To 6
FinalArray(i) = arrCollection(i)
Next i
GetFinalValues = myFinalArray
End Function
Note that you were also trying to use t.arr2(3) which exceeds the number of elements in arr2 so I assumed you meant t.arr1(3)

Custom sort of a SortedSet in VB.Net

I have a sortedSet with following data:
aga12
aga44
dp1
dp11
reg13
reg45
sat5
sat6
I would like this list to be sorted aphabetically but I want the dp values to be on top so like this:
dp1
dp11
aga12
aga44
reg13
reg45
...
Anyone know how I can custom sort this SortedSet. I am using VB.NET
thanks
You could sort using a custom compare class
Dim myList As New List(Of String)
....
myList.Sort(New DpCompare)
And
Private Class DpCompare
Implements IComparer(Of String)
Public Function Compare(ByVal x As String, ByVal y As String) As Integer Implements System.Collections.Generic.IComparer(Of String).Compare
Dim isDPx As Boolean = x.StartsWith("dp")
Dim isDPy As Boolean = y.StartsWith("dp")
If isDPx AndAlso isDPy = False Then
Return -1
End If
If isDPy AndAlso isDPx = False Then
Return 1
End If
Return String.Compare(x, y)
End Function
End Class