Aller au contenu

Messages recommandés

Posté(e)

Salut a vous tous,

 

Voila alors j'ai un pitit soucis avec la gestion de mon appli.

Je suis en vb.Net, et j'ai un traitement a effectuer sur plusieurs plans.Sauf que lorsque je ferme le premier plan pour ouvre le deuxieme,la mémoire utilisé pour le premier plan n'est pas intégralement libéré.

Ce qui fait que une fois une 15ene de plans traité je suis out of mémory.

alors l'idée c'est de tuer mon application autocad a chaque plan. ( probleme avec les plans en lecture seule => récumpération a la réouverture ) .

 

Je voudrais faire quelquechose de propre dans ma méthode bourine,a savoir plutot que de faire :

 

For Each pProcess As Process In Process.GetProcessesByName("acad")

pProcess.Kill()

next

 

je voudrais utiliser la commande : Process.GetProcessesById(Id de ma session autotad en cours).

 

Mais voila,je ne parviens pas a obtenir l'id de ma session.

 

L'idée c'est de fermer la bonne session autocad si jamais l'utilisateur a lancé sa propre session avant le traitement.

 

Merci a vous ^^

Posté(e)

Salut,

 

Pour un traitement par lot, tu n'as pas besoin d'ouvrir vraiment chaque document, tu peux lire et écrire dans la base de donnée en utilisant la méthode ReadDwgFile.

Tu peux voir un exemple dans AutoCAD .NET Developer's Guide Develop Applications with VB.NET and C# > Handle Errors > Trap Runtime Errors > Use try Statements.

En déclarant la base de données à traiter dans un bloc using les ressources seront automatiquement libérées à la fin de l'exécution du bloc (même en cas d'erreur pendant l'exécution de ce bloc).

 

Un petit exemple en C# (désolé, mais il existes des convertisseurs C#VB.Net)

Où :

doc = MdiActiveDocument

filenames = un array de noms de fichiers (chemin complet) à traiter

DoIt(Database db) = la méthode qui contient le traitement à exécuter sur la base de données du dessin.

 

Seuls le dessin actif et les dessins fermés qui ne sont pas en lecture seule sont traités.

 

foreach (string filename in filenames)
{
char[] chr = { '\\' };
string file = filename.Substring(filename.LastIndexOfAny(chr) + 1);

// évalue si le fichier n'est pas en lecture seule
if ((File.GetAttributes(filename) & FileAttributes.ReadOnly) == 0)
{
   try
   {
       // évalue si le fichier est le document actif
       if (filename == doc.Name)
           using (Database db = doc.Database)
           {
               DoIt(db);
               db.SaveAs(filename, DwgVersion.Current);
           }

           // évalue si le fichier est ouvert (existance d'un fichier temporaire .dwl)
           else if (File.Exists(filename.TrimEnd(gChar) + "l"))
               ed.WriteMessage("\n \"{0}\" est ouvert en écriture", file);

           // traitement d'un fichier fermé
           else
           {
               using (Database db = new Database(false, true))
               {
                   db.ReadDwgFile(filename, FileShare.ReadWrite, true, string.Empty);
                   DoIt(db);
                   db.SaveAs(filename, DwgVersion.Current);
               }
           }
       }

       // capture des exceptions AutoCAD
       catch (Autodesk.AutoCAD.Runtime.Exception aex)
       {
           if (aex.ErrorStatus == ErrorStatus.FileSharingViolation)
               ed.WriteMessage("\n \"{0}\" est déjà ouvert", file);
           else if (aex.ErrorStatus == ErrorStatus.DwgNeedsRecovery)
               ed.WriteMessage("\n\"{0}\" nécessite une récupération", file);
           else if (aex.ErrorStatus == ErrorStatus.BadDwgHeader)
               ed.WriteMessage("\n\"{0}\" a une en-tête incorrecte", file);
           else
               ed.WriteMessage("\n\"{0}\" Erreur AutoCAD: {1}", file, aex.Message);
       }

       // capture des exceptions System
       catch (System.Exception ex)
       {
           ed.WriteMessage("\n\"{0}\" Erreur Système: {1}", file, ex.Message);
       }
   }

   // le fichier est en lecture seule
   else
       ed.WriteMessage("\n\"{0}\" est en lecture seule", file);
   }
}

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

  • 1 mois après...
Posté(e)

Merci de ta réponse giles,

 

Comme je bossais sur autre chose j'ai zappé le probleme,mais comme j'ai été ammené a utiliser la méthode readdwg je suis revenu sur ce post.

 

La question que je me pose,c'est peut on effectuer des jeu de sélection?

Car tous mes traitement sont sur la base de jeu de sélection....

Posté(e)

Salut,

 

La question que je me pose,c'est peut on effectuer des jeu de sélection?

Non, avec cette méthode, on a accès à la Database mais pas à l'Editor.

Mais, à mon avis, le (peu de) temps gagné avec un jeu de sélection par rapport à un scan de la base de donnée est (largement) compensé par le fait de ne pas ouvrir le dessin.

 

Pour ton problème de libération des ressources, fais-tu bien un doc.Dispose() après avoir fermé le document ? ou utilises tu un bloc Using(doc) ?

 

Sinon, pour connaître l'Id d'un processus que tu lances, tu peux faire :

// on récupère tout les processus déjà lancés
Process[] processBefore = Process.GetProcessesByName("ACAD");

// ici on lance le nouveau processus

// on récupère un nouvel array des processus après le lancement
Process[] processAfter = Process.GetProcessesByName("ACAD");

// on cherche l'Id du processus lancé avec la fonction GetProcessId
int processId = GetProcessId(ExcelProcessBefore, ExcelProcessAfter);


// La fonction GetProcessId retourne l'Id du processus
private int GetProcessId(Process[] processBefore, Process[] processAfter)
{
   bool isThisProcess = false;
   int resutl = -1;
   if (processBefore.Length == 0 && processAfter.Length == 1)
       result = processAfter[0].Id;
   else
   {
       foreach (Process after in processAfter)
       {
           isThisProcess = true;
           foreach (Process before in processBefore)
           {
               if (after.Id == before.Id)
                   isThisProcess = false;
           }
           if (isThisProcess)
               result = after.Id;
       }
   }
   return result;
}

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)
Salut,

 

Pour ton problème de libération des ressources, fais-tu bien un doc.Dispose() après avoir fermé le document ? ou utilises tu un bloc Using(doc) ?

 

Pour ce qui est du document ya pas de dispose mais un close (interop) ,du collect ... enfin,je test le coup de la database dans quelques jours et je te dis quoi.

 

  • 5 mois après...
Posté(e)

Hey giles,

 

Bon alors aprés un bon moment d'oubliettes me revoici sur le sujet de sélection d'entité via la database.

 

J'ai jetté un oeil mais a part parcourir le block ModelSpace je n'ai pas trouvé comment faire.

Suis je dans l'erreur de penser qu'il faille parcourir le contenu du block modelspace ou alors ya til un moyen de filtrer les éléments que l'on souhaite d'une quelque maniere que ce soit?

Posté(e)

Salut,

 

Comme dit plus haut, avec la méthode ReadDwgFile on ne peut pas faire de sélection (pas d'accès à l'éditeur) donc pas utiliser de filtre.

Il faut donc parcourir le ModelSpace. Ce processus n'est pas tellement plus long que l'utilisation de la méthode SelectAll qui, même avec un filtre, est bien obligée de parcourir toute la base de données.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Ok ok,donc du coup faut parcourir toutes les entités,faire le test pour savoir si elle repondent au filtre qu'on aurait utilisé ... je vais y voir sa ^^

 

EDIT

Ok donc en effet parcourir le contenues du modelspace n'est pas si long que cela en ne visant que les éléments contenue sur le calque 0 par exemple.

 

Sauf que si maintenant je veux faire une fonction générique qui prends en entré un nom de fichier + un filtre,il faut se palucher tous les cas de figure possible et inimaginable,et avec tous les cas de test possible on est pas sortie !

 

Je vais voir ça ce soir ou demain soir pour voir ce que je peux faire

 

[Edité le 5/7/2010 par bazoul]

Posté(e)

Ok alors l'ajout d'entité autocad dans un dwg sans l'ouvrir,d'après ce que j'ai fait sa donne ça :

 

 
       Dim mdatabase As Database
       Dim mDbObject As DBObject
       Dim bt As BlockTable = Nothing
       Dim btr As BlockTableRecord = Nothing
       Dim iter As BlockTableRecordEnumerator
       Dim IsOnLockLayer As Boolean


           mdatabase = New Database(False, True)
           mdatabase.ReadDwgFile(FileToRead, IO.FileShare.ReadWrite, True, "")

           Using tr As Transaction = mdatabase.TransactionManager.StartTransaction
               'Récupération de la table des blocs
               bt = CType(tr.TransactionManager.GetObject(mdatabase.BlockTableId, OpenMode.ForWrite, False), BlockTable)
               'Récupération du bloc représentant le ModelSpace
               btr = CType(tr.TransactionManager.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite, False), BlockTableRecord)
               iter = btr.GetEnumerator

               While iter.MoveNext
                   Try
                       IsOnLockLayer = False
                       mDbObject = tr.GetObject(iter.Current, OpenMode.ForWrite, False, False)
                   Catch ex As Exception
                       'Si calque verrouillé,alors on ne peux pas ouvrir en  écriture
                       IsOnLockLayer = True
                       mDbObject = tr.GetObject(iter.Current, OpenMode.ForRead, False, False)
                   End Try
                   If mDbObject.GetType Is GetType(Polyline) Then
                       mpo = CType(CType(mDbObject, Polyline).Clone, Polyline)
                       mpo.ColorIndex = 4
                       'Ajout de l'objet dans une liste pour ajout dans le fichier
                       mListOfEntityToAdd.Add(mpo)
                   End If

               End While

               'Ajout physique de tous les objets dans le ModelSpace
               For Each mentity As Entity In mListOfEntityToAdd
                   Try
                       btr.AppendEntity(mentity)
                       tr.AddNewlyCreatedDBObject(mentity, True)
                   Catch ex As Exception

                   End Try
               Next mentity

               'Enregeistrement de la DataBase
               mdatabase.SaveAs(mdatabase.Filename, mdatabase.OriginalFileVersion)
           End Using

 

Le seul problème que j'ai pu rencontrer c'est qu'un problème survienne durant le traitement en entrainant une base corrompu,résulat le fichier Dwg était mort,donc perte d'information.

Pour contourner cela,un simple back-up suffit.

 

Si quelqu'un voit quelquechose de mieux a faire dans mon code,remarque ou autre,je suis preneur !

 

Je suis toujours a la recherche d'une fonction générique me permettant de "filtrer" les entitées du ModelSpace ... du genre tanto je veux récupérer toutes les entités sur le calque 0 et tanto toutes les entitées contenues sur le calque 0 et de type de ligne = CACHE par exemple ...

 

[Edité le 8/7/2010 par bazoul]

Posté(e)

Salut,

 

Juste deux petites remarques.

D'après ce qu'a souvent expliqué Tony Tanzillo (en qui, je pense, on peut on peut faire confiance) il faut absolument éviter d'utiliser GetEnumerator, qui retourne un objet de type IEnumerator. Ces objets, suivant à quoi ils s'appliquent, héritent ou pas de IDisposable en conséquence de quoi, il faut ou pas invoquer Dispose() après utilisation.

Donc pour tout objet héritant de IEnumerable, il est beaucoup plus prudent (et plus simple) d'utiliser une expression For Each à la fin de laquelle les ressources seront automatiquement libérées si elle doivent l'être.

 

Pratiquement, remplacer :

iter = btr.GetEnumerator
While iter.MoveNext

 

par :

For Each mDbObject As DBObject in btr

 

Toujours dans ces problèmes de libération des ressources, je pense qu'il est préférable de libérer chaque Database qui a été "ouverte" :

Using mdatabase As Database = New Database(false, true)

   ' ici le code utilisant la Database

End Using

 

En ce qui concerne une méthode générique pour filtrer, j'ai peur que l'implémentation d'une telle méthode ne demande beaucoup de travail pour couvrir tous les cas possibles alors qu'il est relativement simple de tester chaque entité suivant les nécessités de chaque programme.

 

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

  • 2 semaines après...
Posté(e)

Je te remercie de ces indications,

 

Je persiste dans mon idée,qui n'a plus rien a voir avec le sujet initial certe mais,il semblerait que bien que l'on puisse insérer des éléments dans un dwg fermé,de toute évidence on ne pourrait pas ajouter des éléments personnalisé.

 

Je m'explique en interop on a:

 
ThisDrawing.ModelSpace.AddCustomObject(monObjetPerso)

 

En managé,tentative avec :

  
'Récupération du bloc représentant le ModelSpace
               btr = CType(tr.TransactionManager.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite, False), BlockTableRecord)
                       btr.AppendEntity(MyCustomObject)
                       tr.AddNewlyCreatedDBObject(MyCustomObject, True)

 

Sauf que lorsque j'éssai de sauvegarder la DataBase,que ce soit avec la méthode Save() ou SaveAs() .. bin c'est le drame,soit une méchante erreur,soit un message d'erreur ...

 

La ou je ne comprends pas,c'est que meme si on crée une nouvelle DataBase représentative du fichier que l'on veux créer,il faut bien enregistrer a un moment ou a un autre un fichier dwg représentatif de la base de donnée non?

Posté(e)

Salut,

 

Difficile d'en dire plus avec aussi peu d'informations

 

Ton code ressemble-t-il à ça ?

Imports System.Windows.Forms
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.Runtime

Namespace AddToDatabaseSample
   Public Class Class1
        _
       Public Sub Test()
           Dim ofd As New OpenFileDialog()
           If ofd.ShowDialog()  DialogResult.OK Then
               Return
           End If
           Dim filename As String = ofd.FileName
           Using db As New Database()
               db.ReadDwgFile(filename, System.IO.FileShare.ReadWrite, False, String.Empty)
               Using tr As Transaction = db.TransactionManager.StartTransaction()
                   Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
                   Dim btr As BlockTableRecord = DirectCast(tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord)
                   Dim c As New Circle(New Point3d(0.0, 0.0, 0.0), New Vector3d(0.0, 0.0, 1.0), 10.0)
                   btr.AppendEntity(c)
                   tr.AddNewlyCreatedDBObject(c, True)
                   tr.Commit()
               End Using
               db.SaveAs(filename, DwgVersion.Current)
           End Using
       End Sub
   End Class
End Namespace

 

Si ça vient du CustomObject

Quel type de CustomObject essayes-tu d'ajouter à l'espace objet ?

Hérite-t-il de la classe Entity ?

 

Dans tout les cas, tu peux toujours utiliser l'interface COM si ça marche... En convertissant btr en AcadModelSpace :

Imports Autodesk.AutoCAD.Interop.Common
...
Dim acMSpace As AcadModelSpace = DirectCast(btr.AcadObject, AcadModelSpace)
acMSpace.AddCustomObject(monObjetPerso)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Alors je confirme que mon CustomObject hérite bien de Entity.

Son type est un type que j'ai défini,d'où le coté Custom !

 

Mon code ressemble bien a ton exemple de code avec la Sub "test".

La seule différence est bien entendu que je n'ajoute pas un objet "Circle" mais un Objet de type "CustomObject" ...

 

 

Il faut bien garder à l'esprit que je crée une nouvelle DataBase dans le but de créer un nouveau fichier DWG sans l'ouvrir ...

Vu que le reste de mon code est en managé j'aurais voulu rester en managé et ne pas panaché avec de l'interop ...

 

Je vais continuer a chercher,ya pas 50.000 méthode utilisé,je vais bien finir par trouver ... a moins que le problème vienne directement de la définition de mon CustomObject comme tu le suggère ... auquel cas,ya pas grand chose a faire d'un point de vu code autodesk.

Posté(e)

J'avoue que je suis un peu perdu dans tes explications.

J'avais cru comprendre que tu faisais un traitement par lot sur plusieurs fichiers existants dont certains provoquaient une erreur, et maintenant, tu sembles dire que tu crées un nouveau fichier...

 

Dans tout les cas, je ne saisis pas bien ce que tu appelles 'CusomObject', à ma connaissance, la grosse différence entre l'API AutoCAD .NET et ObjectARX (C++ natif) est justement qu'on ne peut pas créer de CustomObject avec .NET.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)
J'avoue que je suis un peu perdu dans tes explications.

J'avais cru comprendre que tu faisais un traitement par lot sur plusieurs fichiers existants dont certains provoquaient une erreur, et maintenant, tu sembles dire que tu crées un nouveau fichier...

 

En effet,je détails un peu plus :

AU début je me suis contenté de lire la base de données d'un dwg.

Ensuite,j'ai ajouté des entités simple dans la base de données d'un DWG non ouvert physiquement.

Puis,j'ai ajouté mes CustomObjet créées depuis un dessin DWG ouvert physiquement dans la base de données d'un DWG non ouvert physiquement.

Dernière étape,je veux maintenant ajouter mes CustomObjet créés en mémoire dans une DataBase neuve dans le but de créer un nouveau DWG.

 

 

Dans tout les cas, je ne saisis pas bien ce que tu appelles 'CusomObject', à ma connaissance, la grosse différence entre l'API AutoCAD .NET et ObjectARX (C++ natif) est justement qu'on ne peut pas créer de CustomObject avec .NET.

Mes CustomObjet sont justement créés en ARX.J'utilise mon programme .NET l'ARX pour créer en CustomObjet.

 

Je n'utilise que mes CustomObjet dans mon dessin DWG.

Mon but ultime serait de réussir à créer mon DWG,avec des données bien défini ( par exemple 1CustomObjet inséré en X=10,Y=15 ) en partant de rien.Juste partir d'une DataBase vide,et générer un DWG.

 

Voila voila,j'avoue que la compréhension du post n'est pas forcément évidente vu que j'ai avancé par étape ....

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité