How to access AutoCad elements / get xyz coordinates from Autocad - c#

I'm looking for a way to access a linked Autocad File using the Revit API. I have SnoopDB already installed which is a huge help.
I found this which was also another step forward however I'm not able to get the points or lines of the file.
I've explored a bit and have found that I am able to access the filename and then get the hashcode of the cadlink but after that, idk how to get the goemetry within.
Any and all help is appreciated.
here is what I have so far:
UIApplication uiapp = commandData.Application;
UIDocument uidoc = uiapp.ActiveUIDocument;
Application app = uiapp.Application;
Document doc = uidoc.Document;
Selection sel = uidoc.Selection;
using (Transaction tx = new Transaction(doc))
{
try
{
tx.Start("Tracing Cad");
Reference refer = sel.PickObject(ObjectType.Element, "Select a CAD Link");
Element elem = doc.GetElement(refer);
GeometryElement geoElem = elem.get_Geometry(new Options());
Debug.WriteLine("elem.Category.Name: " + elem.Category.Name); // can grab title of CAD
foreach (GeometryObject geoObj in geoElem)
{
GeometryInstance instance = geoObj as GeometryInstance;
foreach (GeometryObject instObj in instance.SymbolGeometry)
{
Debug.WriteLine("geoObj.GraphicsStyleId: " + geoObj.GraphicsStyleId);
Debug.WriteLine("geoObj.GetHashCode(): " + geoObj.GetHashCode()); // gets hashcode of selected cad link
if (instObj.GetType().Name == "PolyLine")
// if (instObj.GetType().Name == "GeometryInstance")
{
}
else
{
Debug.WriteLine("there are no blocks found in this CAD File");
}
}
}
tx.Commit();
} catch (Exception e )
{
Debug.WriteLine(e.StackTrace);
}

The Revit API does not provide any access to the internals of a linked CAD file.
All you can do is implement some AutoCAD.NET code to read the DWG file itself, provided you have access to the DWG and AutoCAD is installed.
The Building Coder shares some samples showing how to launch AutoCAD within a Revit add-in.

Related

Accessing Pages in Section file from OneNote Interop

I have a handful of OneNote .one files. I would like to extract their contents programatically. I'm getting stuck trying to access pages.
I'm calling:
app.OpenHierarchy(#"C:\test\TestSection.one",
System.String.Empty, out strXML, CreateFileType.cftNone);
in strXML is an ID.
Then I call:
app.GetHierarchy(strXML, HierarchyScope.hsPages, strXML2);
This returns an XML block with only <one:Section.../>. It has attributes that match the ID in strXML and the path to the physical .one file.
I have verified these .one files open in OneNote. I can see that this test.one has a bunch of pages. What am I doing wrong or missing here?
I'm using Office 2013 (v.15) and VS 2013 (I had to set Embed InteropTypes to False in the OneNote Interop v.15 reference to get things to build).
Once you call app.GetHierarchy using the HiearchyScope.hsPages, you will now have all of the notebooks, sections, and pages that were stored in your TestSection.one file. Here is an example if you wanted to traverse through the hieararchy of the notebooks, sections, and pages after you have called GetHierarchy.
var notebookName = "My Notebook";
var sectionName = "My Meetings";
var xdoc = XDocument.Parse(strXML2);
var ns = xdoc.Root.Name.Namespace;
var myNotebook = xdoc.Root.Descendants(ns + "Notebook").SingleOrDefault(n => n.Attribute("name").Value == notebookName);
if (myNotebook != null)
{
var mySection = myNotebook.Descendants(ns + "Section").SingleOrDefault(s => s.Attribute("name").Value == sectionName);
if (mySection != null)
{
var pages = mySection.Descendants(ns + "Page");
// Now do something here with the pages!
// ...
}
}

Opening AutoCAD drawing inside a Windows Form in C#

I have the following function which opens a dxf file in an Autocad Exe, by zooming a specific coordinate via my C# desktop application.
public static void zoomDrwaing(String drawingFile, String lotId)
{
AcadApplication acadApp = null;
AcadDocument doc = null;
double[] coordinates = new double[3];
String errorMessage = "";
try
{
coordinates = ReadCoordinates(drawingFile, lotId); // done via netDxf api
acadApp = new Autodesk.AutoCAD.Interop.AcadApplication();
acadApp.Visible = true;
doc = acadApp.Documents.Open(drawingFile, true);
double[] points = new double[3] { coordinates[0], coordinates[1], coordinates[2] };
acadApp.ZoomCenter(points, 30);
}
catch (Exception ex)
{
errorMessage = ex.ToString();
}
finally
{
if (acadApp != null) Marshal.FinalReleaseComObject(acadApp);
}
}
I would like to know whether there is any possibility of loading the Autocad Exe (with the zoomed dxf file) inside one of the Windows forms in my desktop application it-self rather than opening the exe separately.
I haven't tried it but apparently you can use the ActiveX control from DWG Trueview Here is a forum post on the Autodesk forum with some sample code. Googling DWG Trueview Activex should generate some reading material. Or you may just read this and abandon all hope. The $$ alternative is RealDwg or Open Design. Read the AutoCAD Tag wiki for more resources and info on that.
Because Autodesk love to destroy their inbound links from time to time, you should be able to land on the first topic I mentioned using Google if they kill it again. Don't get me started on that.

How to launch a process which will open a text file in any editor and automatically move cursor to a certain line number?

From c#, I want to launch a process which will open a text file in any editor and automatically move cursor to a certain line number.
I can open a file using
Process.Start(#"c:\myfile.txt");
but I don't know how to move cursor at specific location in that file.
Answer with source code:
yes, I used notepad++
private void openLog() {
try {
// see if notepad++ is installed on user's machine
var nppDir = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Notepad++", null, null);
if (nppDir != null) {
var nppExePath = Path.Combine(nppDir, "Notepad++.exe");
var nppReadmePath = Path.Combine(yourDirectory,fileName );
var line = 20;
var sb = new StringBuilder();
sb.AppendFormat("\"{0}\" -n{1}", nppReadmePath, lineNo);
Process.Start(nppExePath, sb.ToString());
} else {
string newPath = #"\\mySharedDrive\notpad++\bin\notepad++.exe";
Process.Start(newPath, #"\\" + filePath + " -n" + lineNo); // take exe from my shared drive
}
} catch (Exception e) {
Process.Start(#"\\" + FilePath); // open using notepad
}
}
Get Notepad++, then you can do this:
var nppDir = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Notepad++", null, null);
var nppExePath = Path.Combine(nppDir, "Notepad++.exe");
var nppReadmePath = Path.Combine(nppDir, "readme.txt");
var line = 20;
var sb = new StringBuilder();
sb.AppendFormat("\"{0}\" -n{1}", nppReadmePath, line);
Process.Start(nppExePath, sb.ToString());
In this example we get install path of n++ from the registry, build path to exe and readme.txt file, opens its own readme.txt file with cursor on line 20.
Using StringBuilder is more efficient than using multiple appends (explanation somewhere on SO).
The solution very heavily depends on which process/editor is opened on your system. That editor would have to have a developer API that you could use to access functionality such as setting ranges and altering the cursor position. For example, if the editor that is opened is Microsoft Word, you would use the Word Interop API to set a selection at a specific position. There is no universal way to do this in 'any editor' since each one has its own API (or no outward facing API at all).
Perhaps you are going this the wrong way. I'm not sure what you are trying to accomplish, but I think it would be alot easier to just open the text file in an editor that belongs to your application. Perhaps another form with a WYSIWYG editor control. That way you have full control on where the cursor will land in that editor. Otherwise, there are just way too many unknowns for anything feasibly workable.

ResourceMap not found error when referencing a resource file within a portable class library

The problem I am facing has as follows:
I have developed a portable class library to encapsulate a service connection. Inside this class library there is a Resources.resw file containing strings. These strings are called only by methods of the class library (for example to override ToString() methods).
As I said this is a portable class library. If I reference it as a dll, or even as a project inside another solution, it gets built and compiles correctly. Then I make a call using a method of this library within my application, say
ClientFacadeConnector connector = new ClientFacadeConnector();
ICollection<SearchResult> results = null;
string message = string.Empty;
if (maxResults != -1) //Search with max Results
{
try
{
if (!contextQuery.Trim().Equals(string.Empty))
{
results = await connector.GetConnected().SearchAsync(contextQuery, query, maxResults);
message = "Search with ContextQuery " + contextQuery + ", Query " + query + ", max results " + maxResults.ToString();
}
else
{
results = await connector.GetConnected().SearchAsync(query, maxResults, true);
message = "...using normal Query search, Query " + query + ", max results " + maxResults.ToString();
}
}
catch (IQserException ex)
{
message = ex.Message;
}
}
if (results != null)
{
ICollection<LocalSearchResult> contentResults = new List<LocalSearchResult>();
foreach (SearchResult s in results)
{
var q = s.ToString();
var contentItem = await connector.GetConnected().GetContentAsync(s.ContentId);
LocalSearchResult lContent = new LocalSearchResult(contentItem);
lContent.Score = s.Score;
lContent.Relevance = s.Relevance;
lContent.MarkFullText(query);
contentResults.Add(lContent);
}
At the point where I call s.ToString() method, I get an error "Resource Map not found".
To explain where this comes from:
public static class AppResources
{
private static ResourceLoader resourceLoader;
static AppResources()
{
// Load local file Resources.resw by default
resourceLoader = new ResourceLoader();
}
public static string GetResources(string key)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException("key");
return resourceLoader.GetString(key);
}
}
and inside the overridden ToString() method there is code that looks as follows:
public override string ToString()
{
StringBuilder buf = new StringBuilder(AppResources.GetResources("InstrSearchResultContent"));
if (ContentId != -1)
{
buf.Append(AppResources.GetResources("StringContent") + " ID:" + ContentId.ToString() + " | ");
}
else
{
buf.Append(AppResources.GetResources("StringNo") + AppResources.GetResources("StringContent") + "ID" + " | ");
}
...
The resource file is called resources.resw and is the default resw file that ResourceLoader calls if no other is called.
Strangely enough, if I copy the resource file inside the client application locally, it is referenced correctly by all calls to the class library resource file and everything works.
This class library is supposed to be an SDK when finished. Do I need to distribute the resource file separately?
Such a problem I have never experienced with normal Class libraries and resx files. Resw is giving me the creeps..
It looks like you have to specify the name of the resource map when you create the ResourceLoader, like this:
resourceLoader = new ResourceLoader("Assembly/ResourceFile");
For example, if your class library was called "Company.Lib.dll", and your resource file was "Resources.resw", you would use:
resourceLoader = new ResourceLoader("Company.Lib/Resources");
This doesn't seem to be documented fully on MSDN - it suggests that you can just specify the name of your resource file, but it might be that that only works for resource files that are in the Windows Store application project. It was this page that showed me that, for libraries, you need to specify the assembly name as well.
I also had similar issue even with repeating all steps from How to load string resources.
The problem was that my Resources.resw file was empty. When I added some fake string to it all started working as expected.
I had a similar issue which i resolved by changing the Build Action of the resw file to PRIResource in the properties. I had renamed an existing resx to resw but the documentation doesn't mention that you also have to change the build action.
Accepted answer posted by #Rory MacLeod may no longer be true. I tried and VS warned that ResourceLoader(String) is deprecated. The following worked in my case:
var loader = ResourceLoader.GetForCurrentView();
string localName = loader.GetString("someKey");
I faced a similar issue when developing a UWP app with a class library.
So I have a /Strings/en-Us/Resource.resw file in my library.
ResourceLoader.GetForCurrentView().GetString("someKey");
gives an exception
new ResourceLoader("Company.Lib/Resources").GetString("someKey");
gives me a deprecation warning but works.
My solution which does not give a warning is this:
ResourceLoader.GetForViewIndependentUse("AssemblyNamespace/Resources").GetString("someKey");

Merging word documents C#

I am trying to merge c# documents. My idea is to have a master document and just append the other documents to this master document. Environment is in SharePoint, so basically the documents exist in the document library and I have no problem with my code being able to find the documents. Once I locate them programattically I have no clue how to open and merge them. I have been searching and seems to be like OpenXML SDK 2.0 is a way to do it, but I am not familar with that tool at all and was trying to see if their is a way to do it with the current tools I have in Visual Studio 3.5 . Either using Microsoft.Office.Interop.Word or something else. From what I understand, the actual files are stored in the content database as binary form so the physical file doesn't actually exist, so I cant just easily open them with word. Any help.
I think this link is exactly what you're looking for:
Merging Word Documents on the Server Side with SharePoint 2010
There's a little Open Xml, but nothing too bad. If you decide that this isn't giving you the control you need, you can check this article out:
Creating Documents by Using the Open XML Format SDK 2.0 (Part 3 of 3)
The following script, taken from Tortoise SVN, could help you to get a clue about how to merge .doc files. Be careful with the license if your going to distribute it.
You need to invoke the script from C# using the following:
wscript.exe "C:\<path_to_the_script>\merge-doc.js" merged.doc theirs.doc mine.doc base.doc //E:javascript
This is the script code, only for doc, there is other for docx that I have not included here, but you can take a look installing Tortoise SVN.
//
// TortoiseSVN Merge script for Word Doc files
//
// Copyright (C) 2004-2008 the TortoiseSVN team
// This file is distributed under the same license as TortoiseSVN
//
// Last commit by:
// $Author: tortoisesvn $
// $Date: 2008-12-05 17:38:43 +0100 (Fr, 05 Dez 2008) $
// $Rev: 14781 $
//
// Authors:
// Dan Sheridan, 2008
// Davide Orlandi and Hans-Emil Skogh, 2005
//
var objArgs,num,sTheirDoc,sMyDoc,sBaseDoc,sMergedDoc,objScript,word,baseDoc,WSHShell;
// Microsoft Office versions for Microsoft Windows OS
var vOffice2000 = 9;
var vOffice2002 = 10;
var vOffice2003 = 11;
var vOffice2007 = 12;
// WdCompareTarget
var wdCompareTargetSelected = 0;
var wdCompareTargetCurrent = 1;
var wdCompareTargetNew = 2;
objArgs = WScript.Arguments;
num = objArgs.length;
if (num < 4)
{
WScript.Echo("Usage: [CScript | WScript] merge-doc.js merged.doc theirs.doc mine.doc base.doc");
WScript.Quit(1);
}
sMergedDoc=objArgs(0);
sTheirDoc=objArgs(1);
sMyDoc=objArgs(2);
sBaseDoc=objArgs(3);
objScript = new ActiveXObject("Scripting.FileSystemObject")
if ( ! objScript.FileExists(sTheirDoc))
{
WScript.Echo("File " + sTheirDoc +" does not exist. Cannot compare the documents.", vbExclamation, "File not found");
WScript.Quit(1);
}
if ( ! objScript.FileExists(sMergedDoc))
{
WScript.Echo("File " + sMergedDoc +" does not exist. Cannot compare the documents.", vbExclamation, "File not found");
WScript.Quit(1);
}
objScript = null
try
{
word = WScript.CreateObject("Word.Application");
}
catch(e)
{
WScript.Echo("You must have Microsoft Word installed to perform this operation.");
WScript.Quit(1);
}
word.visible = true
// Open the base document
baseDoc = word.Documents.Open(sTheirDoc);
// Merge into the "My" document
if (parseInt(word.Version) < vOffice2000)
{
baseDoc.Compare(sMergedDoc);
}
else if (parseInt(word.Version) < vOffice2007)
{
baseDoc.Compare(sMergedDoc, "Comparison", wdCompareTargetNew, true, true);
} else {
baseDoc.Merge(sMergedDoc);
}
// Show the merge result
if (parseInt(word.Version) < 12)
{
word.ActiveDocument.Windows(1).Visible = 1;
}
// Close the first document
if (parseInt(word.Version) >= 10)
{
baseDoc.Close();
}
// Show usage hint message
WSHShell = WScript.CreateObject("WScript.Shell");
if(WSHShell.Popup("You have to accept or reject the changes before\nsaving the document to prevent future problems.\n\nWould you like to see a help page on how to do this?", 0, "TSVN Word Merge", 4 + 64) == 6)
{
WSHShell.Run("http://office.microsoft.com/en-us/assistance/HP030823691033.aspx");
}

Categories

Resources