Type Vs Structure VB.NET

Signaler
Messages postés
4525
Date d'inscription
dimanche 29 septembre 2002
Statut
Modérateur
Dernière intervention
22 avril 2019
-
Messages postés
1098
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
22 octobre 2019
-
Bonjour @ tous voici ma deuxieme question sur ce jolie forum de vbfrance. Un moment HISTORIQUE lol, voici ma question :

Je voudrais declarer une structure en vb.net pour lire
dans un fichier en vb 6 cela donne :

Type MASTRUCT
- Var1(7) as byte
- Var2 as long
- Var3 as integer
- Var4 as string *4
- Var5 as RECT
End Type

alors tout betement j'ai tenté ceci :

Structure MASTRUCT
- Dim Var1(7) as byte '/!\ ahahah ben la ça marche pas !!!
- Dim Var2 as Integer
- Dim Var3 as short
- Dim Var4 as string *4 '/!\ bien vue mais interdit aussi !!!
- Dim Var5 as RECT
End Structure

j'ai tenté aussi ceci :

Structure MASTRUCT
- Dim Var1() as byte
- sub Init()
- - Redim Var1(7)
- End Sub
End Structure

Mais la ça plante lors de la lecture !!!

J'ai tenté avec une TLB :

typedef struct {
- char Name[8];
- long VirtualSize;
} MASTRUCT;

Mais le il me crée une interop dll qui plante a la lecture !!!

Alors si qlq1 peut me dire comment c'est possible en vb.net je lui serait infiniment reconnaissant.

Merci

@+

E.B.

6 réponses

Messages postés
1356
Date d'inscription
samedi 8 décembre 2001
Statut
Membre
Dernière intervention
23 octobre 2006
7
labout

Voici un exemple
Private Structure OSVERSIONINFO
Dim OSVSize As Integer
Dim dwVerMajor As Integer
Dim dwVerMinor As Integer
Dim dwBuildNumber As Integer
Dim PlatformID As Integer
Dim szCSDVersion As String
End Structure

Private Structure LUID
Dim dwLowPart As Integer
Dim dwHighPart As Integer
End Structure

Private Structure LUID_AND_ATTRIBUTES
Dim udtLUID As LUID
Dim dwAttributes As Integer
End Structure

Private Structure TOKEN_PRIVILEGES
Dim PrivilegeCount As Integer
Dim laa As LUID_AND_ATTRIBUTES
End Structure

@+
Messages postés
4525
Date d'inscription
dimanche 29 septembre 2002
Statut
Modérateur
Dernière intervention
22 avril 2019
9
Merci labout,

mais je crois que tu n'as pas compris la question...
je sait faire une structure de ce type la dessus ya
aucun soucis j'ai egalement des livre vb.net et j'ai consulté
la MSDN mais je n'ai pas trouvé de reponse a cette question :

Comment traduire ceci :

Type MASTRUCT
- Var1(7) as byte
- Var2 as long
- Var3 as integer
- Var4 as string *4
- Var5 as RECT
End Type

sachant que la structure doit etre lut dans un fichier !
le probleme vient de Var1(7) as byte et de Var4 as string * 4
qui n'est pas compatible avec VB.NET.

merci tout de même

@+

E.B.
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
http://www.dotnetspider.com/Technology/KB/ShowSample.aspx?SampleId=204

http://www.dotnet247.com/247reference/msgs/18/91920.aspx

 EXTRAIT : 
    Marina 
I have 2 suggestions:
1) write your own fixed length string class
2) Use class StringBuilder, it has a Capacity property, which you can set.
However, if you append something to it, and the capacity needs to be
increased to accomodate, it will be increased, and you will have to check
for that sort of thing. 
Messages postés
4525
Date d'inscription
dimanche 29 septembre 2002
Statut
Modérateur
Dernière intervention
22 avril 2019
9
Meme probleme

quand on redim la chaine dans un constructeur
la lecture dans un fichier plante....

@+

E.B.
Messages postés
1098
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
22 octobre 2019

Bonjour, à tu trouvé la solution à ton problème ? (oui je sait ça date un peut quand même, mais je cherche moi aussi à lire un fichier de donnée et de chargé tout ça dans des structure, et j'ai réussi, enfin c'est ce que je croyais, avec de l'aide quand même, MERCI NHenry : 2 ici )

Personnellement pour la déclaration d'une chaine de longueur fixe j'ai fait ça (trad auto proposé par VB.NET quand on lui fait ouvrir un fichier VB6) :
8<-----------------------------------------------------------------------
        <VBFixedString(LG_TABCRI_NOM), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=LG_TABCRI_NOM)> _
        Dim nom() As Char '25 carac
----------------------------------------------------------------------->8

Et ça marche bien quand c'est une structure 'simple' . Mais il me faut la même chose dans une structure 'complexe' (structure contant des structures) et là rien ne vas plus ??? Mes chaine (ou plus exactement mes tableau de char) sont égale à nothing !!!

Du coup j'ai pris un autre chemin :
8<-----------------------------------------------------------------------
Public Sub Initialise()
    [...]
    For Each Item As S_TAB_UNI In TAB_UNI
        Item.Initialise()
    Next
    [...]
----------------------------------------------------------------------->8

(Avec bien sure une procédure "Initialise" dans mes structure d'un niveau au dessous, ici S_TAB_UNI, fessant un redim de mes tableau de char. Heeeee par contre, une structure contenant des données pouvant être privé, ET des fonctions/procédures, pouvant également être privé ??? Ça ne se nommerais pas une classe ??? Je sait pas moi, mais quand même, il me semble TRÈS fortement que se sont mes cours de débutant ça... J'ai rien dit...). Bà même avec tout cas ça ne marche pas mieux...

Un troisième chemin :
8<-----------------------------------------------------------------------
Public Sub Initialise()
    [...]
    For Cpt As UInt16 = 0 To NB_EXP_UNI - 1
        TAB_UNI(Cpt).Initialise()
    Next
----------------------------------------------------------------------->8

Et là... ÇA FONCTIONNE !?!?!?
(Déjà pourcois avec un "for" ça fonction alors qu'avec un "foreach" non ?!?!? Bref...)
Forcément je me dit que voila "La victoire de l'homme sur Microbof"... C'étais oublier tout ce que j'ai pue apprendre en utilisant mon Windows 95 à l'époque. (Chez Microbof quand il n'y en à plus il y en à encore, des saleté qui font que tout plante j'entends bien sure)

Grossssse
erreur (si vous avez été jeter un coup d'oeil sur le lien plus haut ces codes vont vous dire quelque chose) :
-> Alors déjà 1ér problème la ligne ci dessous me retourne 16 (je présise quand même que dans la structure de plus haut niveau, soit celle qui contien toute les autres structures, se trouve un tableau de char de 20 carac plus 10 structure contant chaqu'une un tableau de char de 26, plus d'autre pitite chose) !!!
8<-----------------------------------------------------------------------

System.Runtime.InteropServices.Marshal.SizeOf(ConteneurTest)

----------------------------------------------------------------------->8

-> Ensuite (non ce n'été pas suffisant...) 2ème problème restant lorsque malgré tout je tente de collé mes données dans ma structure (j'ai mit sa taille en dur dans mon prog, 307 octet exactement) j'ai un message d'erreur à l'execution de la dernierre ligne ci dessous : "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

8<-----------------------------------------------------------------------

StreamFichier.Read(Tampon, 0, C_TailleDeLaStructure) 'Lit les données et les met dans le tampon

CopyMemory(DonneesFichier(Compteur), Tampon(0), C_TailleDeLaStructure) 'Copie des données du tampon dans la structure

----------------------------------------------------------------------->8

Dot.Net ou l'art de ne plus pouvoir utilisé les structure....

SVP si vous avez une solution AIDEZ MOI !!! JE CRAQUE !!!

PS : Désol pour le pavé mais il falais absolument que je parle de tout ça pour ne pas devenir moi même un produit Microbof (un truc dont on ne comprend pas toujours très bien l'intérêt et en plus qui bug, lol). Grâce à Micobof je vais bientôt pouvoir allé à Psychostar show
Amicalement
Pensez "Réponse acceptée"
Messages postés
1098
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
22 octobre 2019

J'ai fini par trouvé une solution
Attention ça ne fonctionneras pas dans tout les cas, à moins de l'adapter à mort...

La déclaration de chaine de longueur fixe (qui ne fonctionne que dans le cas ci-dessous, tout du moins dans mes test) :
Il faut cette déclaration dans une structure simple (soit dans une structure ne contenant pas d'autre structure)
8<----------------------------------------------------------------------------------------------------
<VBFixedString(LG_DU_TEXT), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=LG_DU_TEXT)> _
Dim Chaine() as Char

---------------------------------------------------------------------------------------------------->8

Mon objectif été de lire dans un fichier binaire des données écrite avec la méthode put de VB6 et de les chargé dans une structure complexe (j'entends par là contenant d'autre structures)
Méthode :
1) Déclaration de mes structures et variables comme d'habitude
2) Déclaration de nouvelle structure simple basé sur le même schéma que les structure complexe mais sans les sous structures
3) Lecture du fichier en placent les données dans un tableau de byte (mentionnés pour contenir le bon nombre de données)
4) Copie des données grâce à CopyMemory (ou sans doute marchal.copy mais je n'es pas fait de test avec, donc à valider) dans les structures simples.
5) Copie des structure simple dans les structure complexe.

Bon je suis conscient que ça peut paraitre obscure je mes donc un exemple.
8<----------------------------------------------------------------------------------------------------
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As S_Simple, ByRef Source As Byte, ByVal Length As Int16)
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As S_Creation, ByRef Source As Byte, ByVal Length As Int16)

    Private Const C_NbSousStrucutre = 10
    Private Const C_TailleChaine = 10

    'Déclaration des structures
    Private Structure S_Simple
        <VBFixedString(C_TailleChaine), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=C_TailleChaine)> _
        Public SousChaine() As Char
        Public SousValeur As Int16
    End Structure

    Private Structure S_Objectif
        <VBFixedString(C_TailleChaine), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=C_TailleChaine)> _
        Public Chaine() As Char
        Public Valeur As Int16
        Public SousDonnees() As S_Simple
        Public Sub Initialise()
            ReDim SousDonnees(0 To C_NbSousStrucutre - 1)
        End Sub
    End Structure

    'Structure basé sur le même schema que S_Objectif mais sans le tableau de sous structure
    Private Structure S_Creation
        <VBFixedString(C_TailleChaine), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=C_TailleChaine)> _
        Public Chaine() As Char
        Public Valeur As Int16
        'Public SousDonnees() As S_Simple
        'Public Sub Initialise()
        '    ReDim SousDonnees(0 To C_NbSousStrucutre - 1)
        'End Sub
    End Structure

    'Fonction de lecture
    Public Function LitFichier(ByVal ChemainNomFichier As String, ByRef DonneesFichier() As S_Objectif) As Boolean
        Dim Compteur As UInt16 'Compteur utilisé pour remplire le tableau de structure
        Dim NombreDeStructure As UInt16 'Varable utilisé pour stocké le nombre de structure à extraire
        Dim StreamFichier As System.IO.FileStream 'Streameur fichier (ce qui permet de lire le fichier)
        Dim TailleRacine As UInt16
        Dim TailleNiveau1 As UInt16
        Dim TailleTotalDeLaStructure As UInt16 'Variable utilisé pour stocké la taille de la structure
        Dim ConstruitRacine As S_Creation
        Dim ConstruitNiveau1() As S_Simple
        ReDim ConstruitNiveau1(0 To C_NbSousStrucutre - 1)
        TailleRacine = System.Runtime.InteropServices.Marshal.SizeOf(ConstruitRacine)
        TailleNiveau1 = System.Runtime.InteropServices.Marshal.SizeOf(ConstruitNiveau1(0))
        TailleTotalDeLaStructure = TailleRacine + (TailleNiveau1 * C_NbSousStrucutre) 'Sauvegarde de la taille de la structure
        Dim Tampon(0 To TailleTotalDeLaStructure - 1) As Byte 'Le tampon ou les données vont être placé à la lecture (-1 car le tableau commence à 0 et non pas à 1)
        Compteur = 0 'Init du compteur si non le complo renvoie un Warning
        StreamFichier = New System.IO.FileStream(ChemainNomFichier, System.IO.FileMode.Open, IO.FileAccess.Read) 'L'ouverture du fichier
        NombreDeStructure = StreamFichier.Length / TailleTotalDeLaStructure 'Sauvegarde du nombre de structure à priorie présente dans le fichier
        ReDim DonneesFichier(0 To NombreDeStructure - 1) 'Création du tableau de structure servant à recevoir les données
        While Compteur < NombreDeStructure 'Temps que toute les structure n'ont pas été lut
            Try 'Gestion d'erreur
                Dim Position As UInt16
                StreamFichier.Read(Tampon, 0, TailleTotalDeLaStructure) 'Lit les données et les met dans le tampon
                CopyMemory(ConstruitRacine, Tampon(0), TailleRacine) 'Copie des données du tampon dans la structure
                For CompteurMaj As UInt16 = 0 To C_NbSousStrucutre - 1
                    CopyMemory(ConstruitNiveau1(CompteurMaj), Tampon(TailleRacine + TailleNiveau1 * CompteurMaj), TailleNiveau1) 'Copie des données du tampon dans la structure
                Next
                DonneesFichier(Compteur).Initialise()
                DonneesFichier(Compteur).Chaine = ConstruitRacine.Chaine
                DonneesFichier(Compteur).Valeur = ConstruitRacine.Valeur
                DonneesFichier(Compteur).SousDonnees = ConstruitNiveau1

                Compteur = Compteur + 1 'Incrémentation du compteur de boucle
            Catch ex As Exception 'Si une erreur se déclenche dans le block Try Catch
                StreamFichier.Close() 'Ferme le fichier
                Return False 'Retourne faux
                Exit Function 'Quite la fonction
            End Try 'Fin de la gestion d'erreur
        End While 'Fin de la boucle
        StreamFichier.Close() 'Ferme le fichier
        Return True 'Retourne Vrais (sous entendu tout c'est passé correctement)
    End Function

---------------------------------------------------------------------------------------------------->8

Si la sous structure avais par exemple été entre "Chaine" et "Valeur" il aurais fallut ajouté encore une étape à la lecture.
1) CopyMemory de "Chaine"
2) CopyMemory des sous structure
3) CopyMemory de "Valeur"
(et sans doute une variable qui sauvegarde la position courante dans le tampon)

Voila j'espère avoir été claire. Mais franchement sur ce coup Microbof ne cherche vraiment pas à nous arrangé.

ATTENTION : Je parle ici de lecture d'un fichier binaire qui aurais été crée et/ou encore utilisé par d'autre programme si non il existe des méthode "BinaryFormatter.Serialize" et "BinaryFormatter.Deserialize" simple à utilisé mais qui insère une entête de fichier contenant le type et la version de ce qui à été sauvegarder. Il n'est donc pas possible de lire avec ces méthode si l'entête est absent. De plus le développeur n'a plus complètement les main libre sur la façon dont ses données seront sauvegarder.

Amicalement
Pensez "Réponse acceptée"