bazoul Posté(e) le 15 décembre 2009 Posté(e) le 15 décembre 2009 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 ^^
(gile) Posté(e) le 19 décembre 2009 Posté(e) le 19 décembre 2009 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 = MdiActiveDocumentfilenames = un array de noms de fichiers (chemin complet) à traiterDoIt(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
bazoul Posté(e) le 26 janvier 2010 Auteur Posté(e) le 26 janvier 2010 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....
(gile) Posté(e) le 26 janvier 2010 Posté(e) le 26 janvier 2010 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
bazoul Posté(e) le 27 janvier 2010 Auteur Posté(e) le 27 janvier 2010 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.
bazoul Posté(e) le 5 juillet 2010 Auteur Posté(e) le 5 juillet 2010 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?
(gile) Posté(e) le 5 juillet 2010 Posté(e) le 5 juillet 2010 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
bazoul Posté(e) le 5 juillet 2010 Auteur Posté(e) le 5 juillet 2010 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 ^^ EDITOk 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]
bazoul Posté(e) le 8 juillet 2010 Auteur Posté(e) le 8 juillet 2010 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]
(gile) Posté(e) le 8 juillet 2010 Posté(e) le 8 juillet 2010 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
bazoul Posté(e) le 16 juillet 2010 Auteur Posté(e) le 16 juillet 2010 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?
(gile) Posté(e) le 16 juillet 2010 Posté(e) le 16 juillet 2010 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 CustomObjectQuel 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
bazoul Posté(e) le 20 juillet 2010 Auteur Posté(e) le 20 juillet 2010 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.
(gile) Posté(e) le 20 juillet 2010 Posté(e) le 20 juillet 2010 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
bazoul Posté(e) le 20 juillet 2010 Auteur Posté(e) le 20 juillet 2010 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 ....
Messages recommandés
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 compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant