<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9223352140090705474</id><updated>2012-01-24T10:55:16.493+01:00</updated><category term='response'/><category term='revit'/><category term='python'/><title type='text'>Daren@Work</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>33</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-2014056870808923284</id><published>2012-01-18T14:29:00.001+01:00</published><updated>2012-01-18T14:29:30.453+01:00</updated><title type='text'>Converting line endings on the cheap</title><content type='html'>&lt;p&gt;You're at a client's PC, installing some scripts and need to edit a text file.
Of course your client has no &lt;em&gt;real&lt;/em&gt; editor, just that stupid &lt;tt class="docutils literal"&gt;notepad.exe&lt;/tt&gt;!
And then you notice: All the line endings are wrong, that is, they're &lt;tt class="docutils literal"&gt;LF&lt;/tt&gt;
(unix convention) as opposed to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;CR-LF&lt;/span&gt;&lt;/tt&gt; (dos convention). That is because you
&lt;em&gt;do&lt;/em&gt; have a real editor, and so does the other guy working on that file and one
of you was not working on windows, because it's only an OS, right? A tool, not a
religion.&lt;/p&gt;
&lt;p&gt;Not religous either: What escapes your mouth when you are confronted with a single line
of script and black box characters laughing at you where line breaks should be.&lt;/p&gt;
&lt;p&gt;Now, users of cygwin are probably familiar with a myriad of tools (e.g.
&lt;tt class="docutils literal"&gt;dos2unix.exe&lt;/tt&gt;) to convert from dos line endings to unix line endings. You
might be able to get &lt;tt class="docutils literal"&gt;tr&lt;/tt&gt; to work for you too. Or you could just open the
file in your trusty &lt;em&gt;real&lt;/em&gt; editor and type away.&lt;/p&gt;
&lt;p&gt;But your client has none of this installed.&lt;/p&gt;
&lt;p&gt;What your client &lt;em&gt;does&lt;/em&gt; have installed, is MS Word. Seriously. I'm going to use MS Word now. This is how:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;open the script/text file in notepad&lt;/li&gt;
&lt;li&gt;select all text, copy it to the clipboard ([CTRL]+[A], [CTRL]+[C])&lt;/li&gt;
&lt;li&gt;open a blank document in MS Word&lt;/li&gt;
&lt;li&gt;paste from the clipboard ([CTRL]+[V])&lt;/li&gt;
&lt;li&gt;select all text in MS Word, copy it to the clipboard ([CTRL]+[A], [CTRL]+[C])&lt;/li&gt;
&lt;li&gt;paste over (replacing) the selection in notepad ([CTRL]+[V])&lt;/li&gt;
&lt;li&gt;close MS Word and wash your hands to get rid of the dirty hack feeling...&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-2014056870808923284?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/2014056870808923284/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2012/01/converting-line-endings-on-cheap.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/2014056870808923284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/2014056870808923284'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2012/01/converting-line-endings-on-cheap.html' title='Converting line endings on the cheap'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-2541894939359527185</id><published>2011-11-11T16:37:00.003+01:00</published><updated>2011-11-11T16:37:53.440+01:00</updated><title type='text'>How to install Trac on a Synology DS2011+</title><content type='html'>&lt;p&gt;In a &lt;a class="reference external" href="http://darenatwork.blogspot.com/2011/03/how-to-install-trac-on-synology-ds209ii.html"&gt;previous post&lt;/a&gt;, I described installing &lt;a class="reference external" href="http://trac.edgewall.org/"&gt;Trac&lt;/a&gt; on a Synology DS209+II. I
recently had to migrate this installation to a Synology DS2011+ and ran into
some snags. This post will help you avoid spending all the hours I did on getting it to work.&lt;/p&gt;
&lt;div class="section" id="modifying-the-synology-diskstation"&gt;
&lt;h1&gt;Modifying the Synology DiskStation&lt;/h1&gt;
&lt;p&gt;To be able to do anything to your DS2011+, you first have to install the &lt;tt class="docutils literal"&gt;ipkg&lt;/tt&gt; bootstrap. I basically followed along with page on the synology forum &lt;a class="reference external" href="http://forum.synology.com/wiki/index.php/Overview_on_modifying_the_Synology_Server,_bootstrap,_ipkg_etc."&gt;Overview on modifying the Synology Server, bootstrap, ipkg etc.&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;You need to &lt;cite&gt;enable ssh access&lt;/cite&gt; to your NAS and then log in with &lt;a class="reference external" href="http://www.chiark.greenend.org.uk/~sgtatham/putty/"&gt;PuTTY&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The Synology DS2011+ has a &amp;quot;Marvell Kirkwood mv6282&amp;quot; processor, so these steps should do the trick:&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000"&gt;cd&lt;/span&gt; /volume1/@tmp
wget http://wizjos.endofinternet.net/synology/archief/syno-mvkw-bootstrap_1.2-7_arm-ds111.xsh
chmod +x syno-mvkw-bootstrap_1.2-7_arm-ds111.xsh
sh syno-mvk-bootstrap_1.2-7_arm-ds111.xsh
rm syno-mvk-bootstrap_1.2-7_arm-ds111.xsh
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After rebooting the NAS, you can enter these commands:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;ipkg update
ipkg upgrade
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We are now ready to start installing all the stuff needed for running Trac!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="software-to-install"&gt;
&lt;h1&gt;Software to install&lt;/h1&gt;
&lt;div class="section" id="apache"&gt;
&lt;h2&gt;Apache&lt;/h2&gt;
&lt;p&gt;Log on to your DS2011+ and install the following package:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;ipkg install apache
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we have a second &lt;tt class="docutils literal"&gt;httpd&lt;/tt&gt; listening on port 8000. The configuration file
for this instance of apache is &lt;tt class="docutils literal"&gt;/opt/etc/apache2/httpd.conf&lt;/tt&gt;. You can find
the log files in &lt;tt class="docutils literal"&gt;/opt/var/apache2/log&lt;/tt&gt;. Also note that it is started on
system boot by the script &lt;tt class="docutils literal"&gt;/opt/etc/init.d/S80apache&lt;/tt&gt;. I suggest you execute
this script and see if apache starts up nicely.&lt;/p&gt;
&lt;p&gt;I ran into some problems with this installation: A syntax error on line 74 of
&lt;tt class="docutils literal"&gt;/opt/etc/apache2/httpd.conf&lt;/tt&gt;. Somehow apache can't load the
&lt;tt class="docutils literal"&gt;mod_ext_filter.so&lt;/tt&gt;. I didn't really care and just commented out that line.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="subversion"&gt;
&lt;h2&gt;Subversion&lt;/h2&gt;
&lt;p&gt;Create a new share using the DSM (that web interface on port 5000) - call it
&amp;quot;svn&amp;quot;. It will show up on your box as &lt;tt class="docutils literal"&gt;/volume1/svn&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;I mainly followed the &lt;a class="reference external" href="http://forum.synology.com/wiki/index.php/Step-by-step_guide_to_installing_Subversion_on_ARM-based_Synology_Products"&gt;Step-by-step guide to installing Subversion&lt;/a&gt; on the
Synology wiki. But I didn't bother messing with &lt;cite&gt;inetd.conf&lt;/cite&gt;, since I am
running svn under apache with &lt;tt class="docutils literal"&gt;mod_dav_svn&lt;/tt&gt;. So, that leaves the following
steps:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;ipkg install svn
su svnowner
&lt;span style="color: #008000"&gt;cd&lt;/span&gt; /volume1/svn
svnadmin create testsvn
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You now have a new repository on your NAS called &amp;quot;testsvn&amp;quot;. You just can't
access it yet - but we'll fix that next! Also note that the &lt;a class="reference external" href="http://forum.synology.com/wiki/index.php/Step-by-step_guide_to_installing_Subversion_on_ARM-based_Synology_Products"&gt;Step-by-step guide
to installing Subversion&lt;/a&gt; includes a few hints on how to get &lt;tt class="docutils literal"&gt;su svnowner&lt;/tt&gt;
to work if you get an error message.&lt;/p&gt;
&lt;p&gt;To get Apache to serve your subversion repository, append this to &lt;tt class="docutils literal"&gt;/opt/etc/apache2/httpd.conf&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #408080; font-style: italic"&gt;# Subversion&lt;/span&gt;
Include etc/apache2/conf.d/mod_dav_svn.conf
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You will have to create &lt;tt class="docutils literal"&gt;/opt/etc/apache2/conf.d/mod_dav_svn.conf&lt;/tt&gt; of course:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000"&gt;LoadModule&lt;/span&gt; dav_svn_module     libexec/mod_dav_svn.so
&lt;span style="color: #008000"&gt;LoadModule&lt;/span&gt; authz_svn_module   libexec/mod_authz_svn.so

&lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;Location&lt;/span&gt; &lt;span style="color: #BA2121"&gt;/svn&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;&amp;gt;&lt;/span&gt;
   &lt;span style="color: #008000"&gt;DAV&lt;/span&gt; svn
   &lt;span style="color: #008000"&gt;SVNParentPath&lt;/span&gt; &lt;span style="color: #008000"&gt;/volume1/svn&lt;/span&gt;
   &lt;span style="color: #008000"&gt;AuthType&lt;/span&gt; Basic
   &lt;span style="color: #008000"&gt;AuthName&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;Subversion repository&amp;quot;&lt;/span&gt;
   &lt;span style="color: #008000"&gt;AuthUserFile&lt;/span&gt; &lt;span style="color: #008000"&gt;/volume1/svn/svn-auth-file&lt;/span&gt;
   &lt;span style="color: #008000"&gt;Require&lt;/span&gt; valid-user
&lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This expects a file &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/volume1/svn/svn-auth-file&lt;/span&gt;&lt;/tt&gt; to be present. That file
contains the passwords used for Subversion (and, via Apache, Trac
authentication). This file is generated with apaches &lt;tt class="docutils literal"&gt;htpasswd &lt;span class="pre"&gt;-c&lt;/span&gt;&lt;/tt&gt; command. I
used the &lt;tt class="docutils literal"&gt;cm&lt;/tt&gt; too, to force md5 hashing of the passwords.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="id1"&gt;
&lt;h2&gt;Trac&lt;/h2&gt;
&lt;p&gt;So far, this guide is much the same as the one it replaces. The new stuff is in the version of python used:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;ipkg install python26 py26-trac py26-genshi py26-setuptools sqlite svn-py
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The need for upgrading comes from the package &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;svn-py&lt;/span&gt;&lt;/tt&gt;, which is now python 2.6.&lt;/p&gt;
&lt;p&gt;Create a share (using the DSM) called &amp;quot;trac-env&amp;quot;. This is where we will keep our trac installations.&lt;/p&gt;
&lt;p&gt;I am now running Trac version 0.12. The Trac environments can be found at &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/volume1/trac-env&lt;/span&gt;&lt;/tt&gt;. They are called &amp;quot;MYTRAC1&amp;quot; and &amp;quot;MYTRAC2&amp;quot;. Access to them is via the following URLs:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="http://myserver.example.com:8888/MYTRAC1"&gt;http://myserver.example.com:8888/MYTRAC1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://myserver.example.com:8888/MYTRAC2"&gt;http://myserver.example.com:8888/MYTRAC2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Trac is run using tracd. This is configured to start automatically on system start by creation of the following file: &lt;tt class="docutils literal"&gt;/opt/etc/init.d/S81trac&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #408080; font-style: italic"&gt;#!/bin/sh&lt;/span&gt;
&lt;span style="color: #408080; font-style: italic"&gt;# run tracd&lt;/span&gt;
/opt/bin/tracd -d -p 8888 -e /volume1/trac-env
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The file must be set to executable for root (see documentation for &lt;tt class="docutils literal"&gt;chmod&lt;/tt&gt;), so that it will be run at system start.&lt;/p&gt;
&lt;p&gt;Trac configuration files can be found at&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/volume1/trac-env/MYTRAC1/conf/trac.ini&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/volume1/trac-env/MYTRAC2/conf/trac.ini&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class="section" id="authentication-via-apache"&gt;
&lt;h2&gt;Authentication via Apache&lt;/h2&gt;
&lt;p&gt;appended following lines to &lt;tt class="docutils literal"&gt;/opt/etc/apache2/httpd.conf&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #408080; font-style: italic"&gt;# Subversion&lt;/span&gt;
&lt;span style="color: #008000"&gt;Include&lt;/span&gt; etc/apache2/conf.d/trac.conf
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then, create the file &lt;tt class="docutils literal"&gt;/opt/etc/apache2/conf.d/trac.conf&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #408080; font-style: italic"&gt;# allow Apache to be used for authenticating Trac&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;Directory&lt;/span&gt; &lt;span style="color: #BA2121"&gt;/opt/share/www/trac&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;&amp;gt;&lt;/span&gt;
   &lt;span style="color: #008000"&gt;AuthType&lt;/span&gt; Basic
   &lt;span style="color: #008000"&gt;AuthName&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;Subversion repository&amp;quot;&lt;/span&gt;
   &lt;span style="color: #008000"&gt;AuthUserFile&lt;/span&gt; &lt;span style="color: #008000"&gt;/volume1/svn/svn-auth-file&lt;/span&gt;
   &lt;span style="color: #008000"&gt;Require&lt;/span&gt; valid-user
&lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;/Directory&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Authentication is done with the AccountManager plugin for trac
(&lt;a class="reference external" href="http://trac-hacks.org/wiki/AccountManagerPlugin"&gt;http://trac-hacks.org/wiki/AccountManagerPlugin&lt;/a&gt;). The website has a good
explanation on how that works. See the copies of the &lt;tt class="docutils literal"&gt;trac.ini&lt;/tt&gt; files for
reference. I'd like to point out the last section:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;[account-manager]&lt;/span&gt;
&lt;span style="color: #7D9029"&gt;password_store&lt;/span&gt; &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;HttpAuthStore&lt;/span&gt;
&lt;span style="color: #7D9029"&gt;authentication_url&lt;/span&gt; &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;http://myserver.example.com:8000/trac&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is where we tell Trac to use our Apache Server for authentication. Note how the &lt;tt class="docutils literal"&gt;authentication_url&lt;/tt&gt; is the same as the &lt;tt class="docutils literal"&gt;Directory&lt;/tt&gt; in &lt;tt class="docutils literal"&gt;trac.conf&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="backup"&gt;
&lt;h1&gt;Backup&lt;/h1&gt;
&lt;p&gt;Backup is still the same as in the previous post, so I'll just point you there: &lt;a class="reference external" href="http://darenatwork.blogspot.com/2011/03/how-to-install-trac-on-synology-ds209ii.html"&gt;http://darenatwork.blogspot.com/2011/03/how-to-install-trac-on-synology-ds209ii.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-2541894939359527185?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/2541894939359527185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2011/11/how-to-install-trac-on-synology-ds2011_11.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/2541894939359527185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/2541894939359527185'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2011/11/how-to-install-trac-on-synology-ds2011_11.html' title='How to install Trac on a Synology DS2011+'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-3702209273199543957</id><published>2011-08-12T16:19:00.001+02:00</published><updated>2011-08-12T16:26:54.917+02:00</updated><title type='text'>Using the Snoop Objects dialog from RevitLookup in RevitPythonShell</title><content type='html'>&lt;p&gt;One of my main goals with &lt;a class="reference external" href="http://code.google.com/p/revitpythonshell/"&gt;RevitPythonShell&lt;/a&gt; is to provide a handy environment
for exploring the Autodesk Revit API. But anyone seriously interested in exploring
the Revit API should also be familiar with &lt;a class="reference external" href="http://cadappdev.blogspot.com/2010/04/revit-2011-api-series-revitlookup-new.html"&gt;RevitLookup&lt;/a&gt;, formally known as
&lt;a class="reference external" href="http://thebuildingcoder.typepad.com/blog/2009/02/rvtmgddbg.html"&gt;RvtMgdDbg&lt;/a&gt;. This tool can be found in the SDK  and includes a handy command
for &amp;quot;snooping&amp;quot; a selected element called &amp;quot;Snoop Current Selection...&amp;quot;. I use
this so often, that I created a keyboard shortcut to invoke it. It provides
vital information for working with Revit objects - information you probably
want access to while inside an interactive RPS shell!&lt;/p&gt;
&lt;p&gt;Unfortunately, you can't execute plugins while inside the RPS shell. Well, not
through the Revit UI. You &lt;em&gt;can&lt;/em&gt; access them via code. This blog is about a
simple little module I wrote that let's you do this anywhere inside the shell:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;revitsnoop&lt;/span&gt;

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;snooper &lt;span style="color: #666666"&gt;=&lt;/span&gt; revitsnoop&lt;span style="color: #666666"&gt;.&lt;/span&gt;RevitSnoop(__revit__)

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;snooper&lt;span style="color: #666666"&gt;.&lt;/span&gt;snoop(doc&lt;span style="color: #666666"&gt;.&lt;/span&gt;ProjectInformation)
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And have a dialog like this popped up:&lt;/p&gt;
&lt;img alt="http://dl.dropbox.com/u/8112069/20110812-snoop-objects-dialog.png" src="http://dl.dropbox.com/u/8112069/20110812-snoop-objects-dialog.png" style="width: 100%;" /&gt;
&lt;p&gt;Notice how you specify the object you want to snoop &lt;em&gt;in code&lt;/em&gt;, as opposed to
having to select it in the UI. Pretty nifty, eh?&lt;/p&gt;
&lt;div class="section" id="how-it-works"&gt;
&lt;h1&gt;How it works&lt;/h1&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;Autodesk.Revit.UI.UIApplication&lt;/tt&gt; object has a property
&lt;tt class="docutils literal"&gt;LoadedApplications&lt;/tt&gt; that returns a list of all loaded external applications.
As long as you have RevitLookup installed (quick test: can you find it in the
Add-Ins tab?), it will show up in this list. It is pretty easy to find it:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;rlapp &lt;span style="color: #666666"&gt;=&lt;/span&gt; [app &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; app &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; uiApplication&lt;span style="color: #666666"&gt;.&lt;/span&gt;LoadedApplications
         &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; app&lt;span style="color: #666666"&gt;.&lt;/span&gt;GetType()&lt;span style="color: #666666"&gt;.&lt;/span&gt;Namespace &lt;span style="color: #666666"&gt;==&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;RevitLookup&amp;#39;&lt;/span&gt;
         &lt;span style="color: #AA22FF; font-weight: bold"&gt;and&lt;/span&gt; app&lt;span style="color: #666666"&gt;.&lt;/span&gt;GetType()&lt;span style="color: #666666"&gt;.&lt;/span&gt;Name &lt;span style="color: #666666"&gt;==&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;App&amp;#39;&lt;/span&gt;][&lt;span style="color: #666666"&gt;0&lt;/span&gt;]
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I can't test with &lt;a class="reference external" href="http://docs.python.org/library/functions.html#isinstance"&gt;isinstance&lt;/a&gt;, since RPS doesn't know about &lt;tt class="docutils literal"&gt;RevitLookup&lt;/tt&gt;
yet and therefore I can't name the type. That is why I used &lt;tt class="docutils literal"&gt;GetType()&lt;/tt&gt; and
compared the namespace and name of the type.&lt;/p&gt;
&lt;p&gt;Once we have the type, though, we can load the assembly and import &lt;tt class="docutils literal"&gt;RevitLookup&lt;/tt&gt; as a module into IronPython:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;clr&lt;/span&gt;
clr&lt;span style="color: #666666"&gt;.&lt;/span&gt;AddReference(rlapp&lt;span style="color: #666666"&gt;.&lt;/span&gt;GetType()&lt;span style="color: #666666"&gt;.&lt;/span&gt;Assembly)
&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;RevitLookup&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The statement &lt;tt class="docutils literal"&gt;import RevitLookup&lt;/tt&gt; will only work after adding a reference to
the assembly, but afterwards, we can start using the classes inside. To figure
out what had to be done, I checked the source for &lt;tt class="docutils literal"&gt;RevitLookup&lt;/tt&gt;, specifically
the &lt;tt class="docutils literal"&gt;ExternalCommand&lt;/tt&gt; that implements the &amp;quot;Snoop Current Selection...&amp;quot;
functionality: &lt;tt class="docutils literal"&gt;RevitLookup.CmdSnoopModScope&lt;/tt&gt;. It would have been possible to
create an instance of this class and call its &lt;tt class="docutils literal"&gt;Execute&lt;/tt&gt; method, but it turned
out to be quicker and easier to just implement the body myself:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #408080; font-style: italic"&gt;# See note in CollectorExt.cs in the RevitLookup source:&lt;/span&gt;
RevitLookup&lt;span style="color: #666666"&gt;.&lt;/span&gt;Snoop&lt;span style="color: #666666"&gt;.&lt;/span&gt;CollectorExts&lt;span style="color: #666666"&gt;.&lt;/span&gt;CollectorExt&lt;span style="color: #666666"&gt;.&lt;/span&gt;m_app &lt;span style="color: #666666"&gt;=&lt;/span&gt; __revit__

&lt;span style="color: #408080; font-style: italic"&gt;# create a list of elements to snoop&lt;/span&gt;
elementSet &lt;span style="color: #666666"&gt;=&lt;/span&gt; ElementSet()
elementSet&lt;span style="color: #666666"&gt;.&lt;/span&gt;Insert(doc&lt;span style="color: #666666"&gt;.&lt;/span&gt;ProjectInformation)

&lt;span style="color: #408080; font-style: italic"&gt;# create and show the dialog&lt;/span&gt;
form &lt;span style="color: #666666"&gt;=&lt;/span&gt; RevitLookup&lt;span style="color: #666666"&gt;.&lt;/span&gt;Snoop&lt;span style="color: #666666"&gt;.&lt;/span&gt;Forms&lt;span style="color: #666666"&gt;.&lt;/span&gt;Objects(elementSet)
form&lt;span style="color: #666666"&gt;.&lt;/span&gt;ShowDialog()
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code is wrapped up in a module called &lt;a class="reference external" href="http://revitpythonshell.googlecode.com/files/revitsnoop.py"&gt;revitsnoop&lt;/a&gt; for your convenience
in the RevitPythonShell download section. To use it, place it inside one of the
search paths configured in RPS.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-code"&gt;
&lt;h1&gt;The Code&lt;/h1&gt;
&lt;p&gt;For completeness sake, here is the whole module:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #BA2121; font-style: italic"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span style="color: #BA2121; font-style: italic"&gt;revitsnoop.py&lt;/span&gt;

&lt;span style="color: #BA2121; font-style: italic"&gt;a simple library to access the RevitLookup snoop functionality&lt;/span&gt;
&lt;span style="color: #BA2121; font-style: italic"&gt;while inside the interactive shell...&lt;/span&gt;
&lt;span style="color: #BA2121; font-style: italic"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;clr&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Autodesk.Revit.DB&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; ElementSet

&lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;RevitSnoop&lt;/span&gt;(&lt;span style="color: #008000"&gt;object&lt;/span&gt;):
    &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;__init__&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;, uiApplication):
        &lt;span style="color: #BA2121; font-style: italic"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span style="color: #BA2121; font-style: italic"&gt;        for RevitSnoop to function properly, it needs to be instantiated&lt;/span&gt;
&lt;span style="color: #BA2121; font-style: italic"&gt;        with a reverence to the Revit Application object.&lt;/span&gt;
&lt;span style="color: #BA2121; font-style: italic"&gt;        &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
        &lt;span style="color: #408080; font-style: italic"&gt;# find the RevitLookup plugin&lt;/span&gt;
        rlapp &lt;span style="color: #666666"&gt;=&lt;/span&gt; [app &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; app &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; uiApplication&lt;span style="color: #666666"&gt;.&lt;/span&gt;LoadedApplications
                 &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; app&lt;span style="color: #666666"&gt;.&lt;/span&gt;GetType()&lt;span style="color: #666666"&gt;.&lt;/span&gt;Namespace &lt;span style="color: #666666"&gt;==&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;RevitLookup&amp;#39;&lt;/span&gt;
                 &lt;span style="color: #AA22FF; font-weight: bold"&gt;and&lt;/span&gt; app&lt;span style="color: #666666"&gt;.&lt;/span&gt;GetType()&lt;span style="color: #666666"&gt;.&lt;/span&gt;Name &lt;span style="color: #666666"&gt;==&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;App&amp;#39;&lt;/span&gt;][&lt;span style="color: #666666"&gt;0&lt;/span&gt;]
        &lt;span style="color: #408080; font-style: italic"&gt;# tell IronPython about the assembly of the RevitLookup plugin&lt;/span&gt;
        clr&lt;span style="color: #666666"&gt;.&lt;/span&gt;AddReference(rlapp&lt;span style="color: #666666"&gt;.&lt;/span&gt;GetType()&lt;span style="color: #666666"&gt;.&lt;/span&gt;Assembly)
        &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;RevitLookup&lt;/span&gt;
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;RevitLookup &lt;span style="color: #666666"&gt;=&lt;/span&gt; RevitLookup
        &lt;span style="color: #408080; font-style: italic"&gt;# See note in CollectorExt.cs in the RevitLookup source:&lt;/span&gt;
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;RevitLookup&lt;span style="color: #666666"&gt;.&lt;/span&gt;Snoop&lt;span style="color: #666666"&gt;.&lt;/span&gt;CollectorExts&lt;span style="color: #666666"&gt;.&lt;/span&gt;CollectorExt&lt;span style="color: #666666"&gt;.&lt;/span&gt;m_app &lt;span style="color: #666666"&gt;=&lt;/span&gt; uiApplication

    &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;snoop&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;, element):
        elementSet &lt;span style="color: #666666"&gt;=&lt;/span&gt; ElementSet()
        elementSet&lt;span style="color: #666666"&gt;.&lt;/span&gt;Insert(element)
        form &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;RevitLookup&lt;span style="color: #666666"&gt;.&lt;/span&gt;Snoop&lt;span style="color: #666666"&gt;.&lt;/span&gt;Forms&lt;span style="color: #666666"&gt;.&lt;/span&gt;Objects(elementSet)
        form&lt;span style="color: #666666"&gt;.&lt;/span&gt;ShowDialog()
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I think a logical further improvement would be to add some methods (e.g.
&lt;tt class="docutils literal"&gt;snoopDocument&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;snoopApplication&lt;/tt&gt;) for accessing the other useful
functions of RevitLookup. But by now you should already know how to do it
yourself!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-3702209273199543957?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/3702209273199543957/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2011/08/using-snoop-objects-dialog-from.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/3702209273199543957'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/3702209273199543957'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2011/08/using-snoop-objects-dialog-from.html' title='Using the Snoop Objects dialog from RevitLookup in RevitPythonShell'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-5884737411950843555</id><published>2011-06-30T13:36:00.001+02:00</published><updated>2011-06-30T13:38:51.694+02:00</updated><title type='text'>Wall.Orientation Property for walls based on arcs in Autodesk Revit 2011</title><content type='html'>&lt;p&gt;This is what the documentation for the &lt;tt class="docutils literal"&gt;Wall.Orientation&lt;/tt&gt; property in Autodesk Revit 2011 says:&lt;/p&gt;
&lt;blockquote&gt;
The normal vector projected from the exterior side of the wall.&lt;/blockquote&gt;
&lt;p&gt;While this is tried and tested, it is only half of the story. I don't know the whole story, but this post is about one exception i found: Walls based on an arc.&lt;/p&gt;
&lt;div class="section" id="repro-steps"&gt;
&lt;h1&gt;Repro steps:&lt;/h1&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;create a new Revit document&lt;/li&gt;
&lt;li&gt;in the ribbon, on the &amp;quot;Home&amp;quot; tab click &amp;quot;Wall&amp;quot;&lt;/li&gt;
&lt;li&gt;in the &amp;quot;Draw&amp;quot; panel, choose the icon &amp;quot;Start-End-Radius Arc&amp;quot;&lt;/li&gt;
&lt;li&gt;create a wall by specifying the start, the end... well, you get it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, we now have a wall that isn't planar:&lt;/p&gt;
&lt;img alt="http://dl.dropbox.com/u/8112069/20110630-start-end-radius-arc.png" src="http://dl.dropbox.com/u/8112069/20110630-start-end-radius-arc.png" /&gt;
&lt;p&gt;What is its orientation? What do you think it should be? Let's ask Revit! I'm going to use the &lt;a class="reference external" href="http://code.google.com/p/revitpythonshell/"&gt;RevitPythonShell&lt;/a&gt; (RPS) to query this wall, so we can see interactivly what is going on:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;collector &lt;span style="color: #666666"&gt;=&lt;/span&gt; FilteredElementCollector(doc)

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;wall &lt;span style="color: #666666"&gt;=&lt;/span&gt; collector&lt;span style="color: #666666"&gt;.&lt;/span&gt;OfClass(Wall)&lt;span style="color: #666666"&gt;.&lt;/span&gt;ToElements()[&lt;span style="color: #666666"&gt;0&lt;/span&gt;]

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;wall&lt;span style="color: #666666"&gt;.&lt;/span&gt;Orientation

&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;XYZ &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x000000000000002F&lt;/span&gt; [(&lt;span style="color: #666666"&gt;-0.858104216&lt;/span&gt;, &lt;span style="color: #666666"&gt;0.513475563&lt;/span&gt;, &lt;span style="color: #666666"&gt;0.000000000&lt;/span&gt;)]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I was &lt;em&gt;expecting&lt;/em&gt; the orientation to be due North: &lt;tt class="docutils literal"&gt;(0, 1, 0)&lt;/tt&gt;. That is where
the orientation handle bars are shown. But that is not what we get. What we get
is a vector from the curve center point to the start point of the arc:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;curve &lt;span style="color: #666666"&gt;=&lt;/span&gt; wall&lt;span style="color: #666666"&gt;.&lt;/span&gt;Location&lt;span style="color: #666666"&gt;.&lt;/span&gt;Curve

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;P0 &lt;span style="color: #666666"&gt;=&lt;/span&gt; curve&lt;span style="color: #666666"&gt;.&lt;/span&gt;get_EndPoint(&lt;span style="color: #666666"&gt;0&lt;/span&gt;)

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;M &lt;span style="color: #666666"&gt;=&lt;/span&gt; curve&lt;span style="color: #666666"&gt;.&lt;/span&gt;Center

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;Vector(P0, M)

IronTextBoxControl error: name &lt;span style="color: #BA2121"&gt;&amp;#39;Vector&amp;#39;&lt;/span&gt; &lt;span style="color: #AA22FF; font-weight: bold"&gt;is&lt;/span&gt; &lt;span style="color: #AA22FF; font-weight: bold"&gt;not&lt;/span&gt; defined
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;XYZ(P0&lt;span style="color: #666666"&gt;.&lt;/span&gt;X &lt;span style="color: #666666"&gt;-&lt;/span&gt; M&lt;span style="color: #666666"&gt;.&lt;/span&gt;X, P0&lt;span style="color: #666666"&gt;.&lt;/span&gt;Y &lt;span style="color: #666666"&gt;-&lt;/span&gt; M&lt;span style="color: #666666"&gt;.&lt;/span&gt;Y, P0&lt;span style="color: #666666"&gt;.&lt;/span&gt;Z &lt;span style="color: #666666"&gt;-&lt;/span&gt; M&lt;span style="color: #666666"&gt;.&lt;/span&gt;Z)

&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;XYZ &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000030&lt;/span&gt; [(&lt;span style="color: #666666"&gt;-34.284776903&lt;/span&gt;, &lt;span style="color: #666666"&gt;20.515451146&lt;/span&gt;, &lt;span style="color: #666666"&gt;0.000000000&lt;/span&gt;)]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;r &lt;span style="color: #666666"&gt;=&lt;/span&gt; XYZ(P0&lt;span style="color: #666666"&gt;.&lt;/span&gt;X &lt;span style="color: #666666"&gt;-&lt;/span&gt; M&lt;span style="color: #666666"&gt;.&lt;/span&gt;X, P0&lt;span style="color: #666666"&gt;.&lt;/span&gt;Y &lt;span style="color: #666666"&gt;-&lt;/span&gt; M&lt;span style="color: #666666"&gt;.&lt;/span&gt;Y, P0&lt;span style="color: #666666"&gt;.&lt;/span&gt;Z &lt;span style="color: #666666"&gt;-&lt;/span&gt; M&lt;span style="color: #666666"&gt;.&lt;/span&gt;Z)

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;r&lt;span style="color: #666666"&gt;.&lt;/span&gt;Normalize()

&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;XYZ &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000031&lt;/span&gt; [(&lt;span style="color: #666666"&gt;-0.858104216&lt;/span&gt;, &lt;span style="color: #666666"&gt;0.513475563&lt;/span&gt;, &lt;span style="color: #666666"&gt;0.000000000&lt;/span&gt;)]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, the orientation has the same direction as a vector from the arc center to the start point of the arc. This is for walls that face away from the arc center. Let's flip the wall and see what happens:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&amp;gt;&amp;gt;&amp;gt;t.Start()

&amp;lt;Autodesk.Revit.DB.TransactionStatus object at 0x0000000000000032 [Started]&amp;gt;
&amp;gt;&amp;gt;&amp;gt;wall.flip()

&amp;gt;&amp;gt;&amp;gt;t.Commit()

&amp;lt;Autodesk.Revit.DB.TransactionStatus object at 0x0000000000000033 [Committed]&amp;gt;
&amp;gt;&amp;gt;&amp;gt;wall.Orientation

&amp;lt;Autodesk.Revit.DB.XYZ object at 0x0000000000000034 [(0.858104216, -0.513475563, 0.000000000)]&amp;gt;
&amp;gt;&amp;gt;&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you see, the vector changed it's orientation too. So, for arcs with wall orientation facing the arc center, the &lt;tt class="docutils literal"&gt;Wall.Orientation&lt;/tt&gt; property is the normalized vector from the arc start point to the arc center.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-5884737411950843555?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/5884737411950843555/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2011/06/wallorientation-property-for-walls_30.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/5884737411950843555'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/5884737411950843555'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2011/06/wallorientation-property-for-walls_30.html' title='Wall.Orientation Property for walls based on arcs in Autodesk Revit 2011'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-2906738602404737907</id><published>2011-05-27T16:59:00.001+02:00</published><updated>2011-05-27T16:59:03.836+02:00</updated><title type='text'>Which of the parameters on the ProjectInfo are built in?</title><content type='html'>&lt;p&gt;Yesterday I needed to know which of the ProjectInfo parameters are actually
built in and can be relied on to be found in any Autodesk Revit Architecture
document. Of course I fired up RPS and had a go at finding a solution. Here is
what I came up with:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;clr&lt;/span&gt;
clr&lt;span style="color: #666666"&gt;.&lt;/span&gt;AddReference(&lt;span style="color: #BA2121"&gt;&amp;#39;RevitAPI&amp;#39;&lt;/span&gt;)
clr&lt;span style="color: #666666"&gt;.&lt;/span&gt;AddReference(&lt;span style="color: #BA2121"&gt;&amp;#39;mscorlib&amp;#39;&lt;/span&gt;)
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Autodesk.Revit.DB&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #666666"&gt;*&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;System&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; Enum

doc &lt;span style="color: #666666"&gt;=&lt;/span&gt; __revit__&lt;span style="color: #666666"&gt;.&lt;/span&gt;ActiveUIDocument&lt;span style="color: #666666"&gt;.&lt;/span&gt;Document
pi &lt;span style="color: #666666"&gt;=&lt;/span&gt; doc&lt;span style="color: #666666"&gt;.&lt;/span&gt;ProjectInformation
params &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;list&lt;/span&gt;(pi&lt;span style="color: #666666"&gt;.&lt;/span&gt;Parameters)
builtInParameterIds &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;set&lt;/span&gt;([p&lt;span style="color: #666666"&gt;.&lt;/span&gt;Id&lt;span style="color: #666666"&gt;.&lt;/span&gt;IntegerValue &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; p &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; params &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; p&lt;span style="color: #666666"&gt;.&lt;/span&gt;Id&lt;span style="color: #666666"&gt;.&lt;/span&gt;IntegerValue &lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color: #666666"&gt;0&lt;/span&gt;])
&lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; &lt;span style="color: #008000"&gt;id&lt;/span&gt; &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; builtInParameterIds:
    parameter &lt;span style="color: #666666"&gt;=&lt;/span&gt; pi&lt;span style="color: #666666"&gt;.&lt;/span&gt;get_Parameter(Enum&lt;span style="color: #666666"&gt;.&lt;/span&gt;ToObject(BuiltInParameter, &lt;span style="color: #008000"&gt;id&lt;/span&gt;))
    name &lt;span style="color: #666666"&gt;=&lt;/span&gt; Enum&lt;span style="color: #666666"&gt;.&lt;/span&gt;GetName(BuiltInParameter, &lt;span style="color: #008000"&gt;id&lt;/span&gt;)
    &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; parameter:
        &lt;span style="color: #008000; font-weight: bold"&gt;print&lt;/span&gt; name, &lt;span style="color: #BA2121"&gt;&amp;#39;: &amp;#39;&lt;/span&gt;, parameter&lt;span style="color: #666666"&gt;.&lt;/span&gt;AsString()
    &lt;span style="color: #008000; font-weight: bold"&gt;else&lt;/span&gt;:
        &lt;span style="color: #008000; font-weight: bold"&gt;print&lt;/span&gt; name, &lt;span style="color: #BA2121"&gt;&amp;#39;: &amp;lt;NULL&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are some aspects of this script I'd like to point out, since they might help you writing your own scripts:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This gives you access to the &lt;tt class="docutils literal"&gt;System.Enum&lt;/tt&gt; type. The &lt;tt class="docutils literal"&gt;BuiltInParameter&lt;/tt&gt; enumeration has to be marshalled back and forth to IronPython integers using &lt;tt class="docutils literal"&gt;Enum&lt;/tt&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;Enum.ToObject(BuiltInParameter, id)&lt;/tt&gt; returns the enum constant that has the integer value &lt;tt class="docutils literal"&gt;id&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;Enum.GetName(BuiltInParameter, id)&lt;/tt&gt; returns the name of the enum constant (handy for printing to the user)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Also note that all the predefined parameters in Revit have negative ids - that is how we find them:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The output on a test project on my computer is:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
PROJECT_ISSUE_DATE :  Projekt Datum
GBXML_EDIT_DATA_PARAM : &amp;lt;NULL&amp;gt;
PROJECT_STATUS :  Projekt  Status
CLIENT_NAME :  Bauherr
PROJECT_ADDRESS :  Projektadresse
PROJECT_NAME :  Projekt Name
PROJECT_NUMBER :  01212
&lt;/pre&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-2906738602404737907?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/2906738602404737907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2011/05/which-of-parameters-on-projectinfo-are_27.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/2906738602404737907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/2906738602404737907'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2011/05/which-of-parameters-on-projectinfo-are_27.html' title='Which of the parameters on the ProjectInfo are built in?'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-8006926328695748387</id><published>2011-05-19T15:56:00.001+02:00</published><updated>2011-05-19T15:56:52.137+02:00</updated><title type='text'>Adding both 32 and 64 bit versions of DLLs to a Visual Studio 2010 Setup project</title><content type='html'>&lt;p&gt;I ran into a snag, when trying to create an installer using a Visual Studio
2010 Setup project that would install for 32 and 64 bit versions of Autodesk
Revit Architecture. Since my program depends on a DLL (in this case
&lt;tt class="docutils literal"&gt;System.Data.SQLite.dll&lt;/tt&gt;) that ships in two different versions, I wanted
to include both in the MSI and then copy the correct one to the
installation folder with a &lt;tt class="docutils literal"&gt;CustomAction&lt;/tt&gt; project. The snag consists of
this pesky error message whenever you add a 64 bit dll to a Setup project
that is targeting x86:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
File 'System.Data.SQLite.dll' of project output 'Content Files from MYPROJECT (Active)' targeting 'AMD64' is not compatible with the project's target platform 'x86'
&lt;/pre&gt;
&lt;p&gt;That was easy to fix! All I had to do was include the file with a different
extension, right? So... I renamed &lt;tt class="docutils literal"&gt;System.Data.SQLite.dll&lt;/tt&gt; to
&lt;tt class="docutils literal"&gt;System.Data.SQLite.txt&lt;/tt&gt; and added it to MYPROJECT as a new content file.
Same error when building the setup project:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
File 'System.Data.SQLite.txt' of project output 'Content Files from MYPROJECT (Active)' targeting 'AMD64' is not compatible with the project's target platform 'x86'
&lt;/pre&gt;
&lt;p&gt;It seems, the setup project figures out that you have a DLL here, even if the
extension doesn't is something totally different. I tried various extensions to
no avail.&lt;/p&gt;
&lt;p&gt;So, the next logical step would be to use the old email zip file trick, right?
It is rather easy to zip a DLL. Any number of tools will do that for you. It
turns out to be rather tricky to unzip a DLL in C# inside your &lt;tt class="docutils literal"&gt;CustomAction&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;It is possible to use a 3rd party library for unzipping, but I didn't really want to add a dependency &lt;em&gt;just for the installer&lt;/em&gt;.
Instead, I opted to use the DEFLATE algorithm provided in .NET here: &lt;tt class="docutils literal"&gt;System.IO.Compression.DeflateStream&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Given a file compressed with this algorithm, the code to inflate it back to normal size is trivial:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;using&lt;/span&gt; (var srcFile = File.OpenRead(&lt;span style="color: #BA2121"&gt;@&amp;quot;C:\MYPATH\System.Data.SQLite.x64&amp;quot;&lt;/span&gt;))
{
    &lt;span style="color: #008000; font-weight: bold"&gt;using&lt;/span&gt; (var dstFile = File.OpenWrite(&lt;span style="color: #BA2121"&gt;@&amp;quot;C:\MYPATH\System.Data.SQLite.dll&amp;quot;&lt;/span&gt;))
    {
        &lt;span style="color: #008000; font-weight: bold"&gt;using&lt;/span&gt; (var deflator = &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; DeflateStream(srcFile, CompressionMode.Decompress))
        {
            CopyStream(deflator, dstFile);
        }
    }
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Just... how to get the original file into the deflated version? I couldn't find a tool that reliably did this for me, so I created my own: &lt;a class="reference external" href="http://code.google.com/p/deflate/"&gt;http://code.google.com/p/deflate/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To quote from the projects page:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This project provides two simple programs:&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;deflate.exe&lt;/tt&gt;
&lt;tt class="docutils literal"&gt;inflate.exe&lt;/tt&gt;
They are implented using the System.IO.Compression.DeflateStream provided in .NET.&lt;/p&gt;
&lt;p&gt;Usage:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
C:\&amp;gt; type MYFILE | deflate.exe &amp;gt; MYFILE.deflated
C:\&amp;gt; type MYFILE.deflated | inflate.exe &amp;gt; MYFILE
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;I now have the honour to present the steps to create a DLL targeted at a different architecture as your setup:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;deflate the file using &lt;tt class="docutils literal"&gt;deflate.exe&lt;/tt&gt;, naming it with a different extension (e.g. &lt;tt class="docutils literal"&gt;.x64&lt;/tt&gt;)&lt;/li&gt;
&lt;li&gt;add it to your main project as a content file&lt;/li&gt;
&lt;li&gt;add a custom action project to your solution&lt;/li&gt;
&lt;li&gt;add the custom action to the setup projects &amp;quot;Install&amp;quot; custom actions&lt;/li&gt;
&lt;li&gt;inflate the file inside the custom actions &lt;tt class="docutils literal"&gt;Install&lt;/tt&gt; method using &lt;tt class="docutils literal"&gt;System.IO.Compression.DeflateStream&lt;/tt&gt; (see code above)&lt;/li&gt;
&lt;li&gt;do a little dance around your desk, down the hall, and past as many coworkers as you care to annoy :)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-8006926328695748387?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/8006926328695748387/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2011/05/adding-both-32-and-64-bit-versions-of.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/8006926328695748387'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/8006926328695748387'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2011/05/adding-both-32-and-64-bit-versions-of.html' title='Adding both 32 and 64 bit versions of DLLs to a Visual Studio 2010 Setup project'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-9220068808159751678</id><published>2011-04-14T10:27:00.001+02:00</published><updated>2011-04-14T10:27:56.396+02:00</updated><title type='text'>Listing Window Dimensions with RevitPythonShell</title><content type='html'>&lt;p&gt;I wrote this quick script this morning and thought I should share:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;clr&lt;/span&gt;
clr&lt;span style="color: #666666"&gt;.&lt;/span&gt;AddReference(&lt;span style="color: #BA2121"&gt;&amp;#39;RevitAPI&amp;#39;&lt;/span&gt;)
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Autodesk.Revit.DB&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #666666"&gt;*&lt;/span&gt;

doc &lt;span style="color: #666666"&gt;=&lt;/span&gt; __revit__&lt;span style="color: #666666"&gt;.&lt;/span&gt;ActiveUIDocument&lt;span style="color: #666666"&gt;.&lt;/span&gt;Document

&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;revitutil&lt;/span&gt;

&lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;main&lt;/span&gt;():
    windows &lt;span style="color: #666666"&gt;=&lt;/span&gt; revitutil&lt;span style="color: #666666"&gt;.&lt;/span&gt;listWindows(doc)

    &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; w &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; windows:
        instance_width &lt;span style="color: #666666"&gt;=&lt;/span&gt; revitutil&lt;span style="color: #666666"&gt;.&lt;/span&gt;meters(w&lt;span style="color: #666666"&gt;.&lt;/span&gt;get_Parameter(BuiltInParameter&lt;span style="color: #666666"&gt;.&lt;/span&gt;WINDOW_WIDTH)&lt;span style="color: #666666"&gt;.&lt;/span&gt;AsDouble())
        instance_height &lt;span style="color: #666666"&gt;=&lt;/span&gt; revitutil&lt;span style="color: #666666"&gt;.&lt;/span&gt;meters(w&lt;span style="color: #666666"&gt;.&lt;/span&gt;get_Parameter(BuiltInParameter&lt;span style="color: #666666"&gt;.&lt;/span&gt;WINDOW_HEIGHT)&lt;span style="color: #666666"&gt;.&lt;/span&gt;AsDouble())

        wt &lt;span style="color: #666666"&gt;=&lt;/span&gt; doc&lt;span style="color: #666666"&gt;.&lt;/span&gt;get_Element(w&lt;span style="color: #666666"&gt;.&lt;/span&gt;GetTypeId())

        type_width &lt;span style="color: #666666"&gt;=&lt;/span&gt; revitutil&lt;span style="color: #666666"&gt;.&lt;/span&gt;meters(wt&lt;span style="color: #666666"&gt;.&lt;/span&gt;get_Parameter(BuiltInParameter&lt;span style="color: #666666"&gt;.&lt;/span&gt;WINDOW_WIDTH)&lt;span style="color: #666666"&gt;.&lt;/span&gt;AsDouble())
        type_height &lt;span style="color: #666666"&gt;=&lt;/span&gt; revitutil&lt;span style="color: #666666"&gt;.&lt;/span&gt;meters(wt&lt;span style="color: #666666"&gt;.&lt;/span&gt;get_Parameter(BuiltInParameter&lt;span style="color: #666666"&gt;.&lt;/span&gt;WINDOW_HEIGHT)&lt;span style="color: #666666"&gt;.&lt;/span&gt;AsDouble())

        rough_width &lt;span style="color: #666666"&gt;=&lt;/span&gt; revitutil&lt;span style="color: #666666"&gt;.&lt;/span&gt;meters(wt&lt;span style="color: #666666"&gt;.&lt;/span&gt;get_Parameter(BuiltInParameter&lt;span style="color: #666666"&gt;.&lt;/span&gt;FAMILY_ROUGH_WIDTH_PARAM)&lt;span style="color: #666666"&gt;.&lt;/span&gt;AsDouble())
        rough_height &lt;span style="color: #666666"&gt;=&lt;/span&gt; revitutil&lt;span style="color: #666666"&gt;.&lt;/span&gt;meters(wt&lt;span style="color: #666666"&gt;.&lt;/span&gt;get_Parameter(BuiltInParameter&lt;span style="color: #666666"&gt;.&lt;/span&gt;FAMILY_ROUGH_WIDTH_PARAM)&lt;span style="color: #666666"&gt;.&lt;/span&gt;AsDouble())

        wid &lt;span style="color: #666666"&gt;=&lt;/span&gt; w&lt;span style="color: #666666"&gt;.&lt;/span&gt;Id&lt;span style="color: #666666"&gt;.&lt;/span&gt;IntegerValue
        wname &lt;span style="color: #666666"&gt;=&lt;/span&gt; w&lt;span style="color: #666666"&gt;.&lt;/span&gt;Name

        &lt;span style="color: #008000; font-weight: bold"&gt;print&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(wid)d&lt;/span&gt;&lt;span style="color: #BB6622; font-weight: bold"&gt;\t&lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(wname)s&lt;/span&gt;&lt;span style="color: #BB6622; font-weight: bold"&gt;\t&lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(instance_width).2f&lt;/span&gt;&lt;span style="color: #BB6622; font-weight: bold"&gt;\t&lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(instance_height).2f&lt;/span&gt;&lt;span style="color: #BB6622; font-weight: bold"&gt;\t&lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(type_width)s&lt;/span&gt;&lt;span style="color: #BB6622; font-weight: bold"&gt;\t&lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(type_height).2f&lt;/span&gt;&lt;span style="color: #BB6622; font-weight: bold"&gt;\t&lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(rough_width).2f&lt;/span&gt;&lt;span style="color: #BB6622; font-weight: bold"&gt;\t&lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%(rough_height).2f&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color: #666666"&gt;%&lt;/span&gt; &lt;span style="color: #008000"&gt;locals&lt;/span&gt;()


&lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; __name__ &lt;span style="color: #666666"&gt;==&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;:
    &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;traceback&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;try&lt;/span&gt;:
        main()
    &lt;span style="color: #008000; font-weight: bold"&gt;except&lt;/span&gt;:
        traceback&lt;span style="color: #666666"&gt;.&lt;/span&gt;print_exc()
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It doesn't do much more than you could do with a window schedule in the Revit GUI, except that I couldn't figure out how to distinguish instance width and type width in window schedules. As I was trying to debug some code that made that distinction, I needed some goggles! Out pops RPS to the rescue ;)&lt;/p&gt;
&lt;p&gt;One thing I'd like to point out is the structure of the script. I tend to write my canned commands in RPS following this structure:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;import stuff and create a &lt;tt class="docutils literal"&gt;doc&lt;/tt&gt; variable (I normally just copy the contens of the &lt;a class="reference external" href="http://code.google.com/p/revitpythonshell/wiki/InitScript"&gt;InitScript&lt;/a&gt; for this)&lt;/li&gt;
&lt;li&gt;define a &lt;tt class="docutils literal"&gt;main()&lt;/tt&gt; function that handles the code&lt;/li&gt;
&lt;li&gt;use the &lt;tt class="docutils literal"&gt;if __name__ == '__main__'&lt;/tt&gt; idiom to wrap calling the main function in a &lt;tt class="docutils literal"&gt;try&lt;/tt&gt; block&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;The reason for using the &lt;tt class="docutils literal"&gt;try&lt;/tt&gt; block is &lt;tt class="docutils literal"&gt;traceback.print_exc()&lt;/tt&gt; which prints a nice error message to the console that helps debugging!&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-9220068808159751678?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/9220068808159751678/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2011/04/listing-window-dimensions-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/9220068808159751678'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/9220068808159751678'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2011/04/listing-window-dimensions-with.html' title='Listing Window Dimensions with RevitPythonShell'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-1441978314934541060</id><published>2011-04-06T14:55:00.001+02:00</published><updated>2011-04-06T14:55:33.687+02:00</updated><title type='text'>List Parameters of Current Selection</title><content type='html'>&lt;p&gt;This is another post about using the &lt;a class="reference external" href="http://code.google.com/p/revitpythonshell/"&gt;RevitPythonShell&lt;/a&gt; (RPS) for accessing the Revit API. I assume you are using a variation of the &lt;a class="reference external" href="http://code.google.com/p/revitpythonshell/wiki/InitScript"&gt;default InitScript&lt;/a&gt;, as that provides a handy &lt;tt class="docutils literal"&gt;selection&lt;/tt&gt; variable.&lt;/p&gt;
&lt;p&gt;The following session in the RPS shell assumes you have selected a wall in your Revit model. It then provides a list of the names of all parameters on the walls type:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&amp;gt;&amp;gt;&amp;gt;w

&amp;lt;Autodesk.Revit.DB.Wall object at 0x000000000000002B [Autodesk.Revit.DB.Wall]&amp;gt;
&amp;gt;&amp;gt;&amp;gt;wt = doc.get_Element(w.GetTypeId())

&amp;gt;&amp;gt;&amp;gt;plist = list(wt.Parameters)

&amp;gt;&amp;gt;&amp;gt;pnames = [p.Definition.Name for p in plist]

&amp;gt;&amp;gt;&amp;gt;pnames

[&amp;#39;Description&amp;#39;, &amp;#39;DPV:DpvConstruction&amp;#39;, &amp;#39;Fire Rating&amp;#39;, &amp;#39;Structure&amp;#39;, &amp;#39;Assembly Description&amp;#39;, &amp;#39;Type Mark&amp;#39;, &amp;#39;Cost&amp;#39;, &amp;#39;Coarse Scale Fill Color&amp;#39;, &amp;#39;URL&amp;#39;, &amp;#39;Function&amp;#39;, &amp;#39;Width&amp;#39;, &amp;#39;Wrapping at Inserts&amp;#39;, &amp;#39;Assembly Code&amp;#39;, &amp;#39;Type Comments&amp;#39;, &amp;#39;Coarse Scale Fill Pattern&amp;#39;, &amp;#39;Keynote&amp;#39;, &amp;#39;Model&amp;#39;, &amp;#39;Wrapping at Ends&amp;#39;, &amp;#39;Manufacturer&amp;#39;]
&amp;gt;&amp;gt;&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-1441978314934541060?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/1441978314934541060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2011/04/list-parameters-of-current-selection.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/1441978314934541060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/1441978314934541060'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2011/04/list-parameters-of-current-selection.html' title='List Parameters of Current Selection'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-6456465873535391381</id><published>2011-03-31T16:24:00.001+02:00</published><updated>2011-03-31T16:26:30.847+02:00</updated><title type='text'>Exporting Images with the Autodesk Revit API</title><content type='html'>&lt;p&gt;I tried to find some sample code for using the &lt;tt class="docutils literal"&gt;Document.ExportImage&lt;/tt&gt; method in Autodesk Revit 2011 but couldn't find any. So I wrote my own sample code and posted it on the &lt;a class="reference external" href="http://code.google.com/p/revitpythonshell/"&gt;RevitPythonShell&lt;/a&gt; wiki as a &lt;a class="reference external" href="http://code.google.com/p/revitpythonshell/wiki/FeaturedScriptExportImage"&gt;featured script&lt;/a&gt;. I'd like to share it here too:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #BA2121; font-style: italic"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span style="color: #BA2121; font-style: italic"&gt;exportImage.py&lt;/span&gt;

&lt;span style="color: #BA2121; font-style: italic"&gt;Export the currently visible view as a PNG image to a location specified by the user.&lt;/span&gt;
&lt;span style="color: #BA2121; font-style: italic"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;clr&lt;/span&gt;
clr&lt;span style="color: #666666"&gt;.&lt;/span&gt;AddReference(&lt;span style="color: #BA2121"&gt;&amp;#39;RevitAPI&amp;#39;&lt;/span&gt;)
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Autodesk.Revit.DB&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #666666"&gt;*&lt;/span&gt;

doc &lt;span style="color: #666666"&gt;=&lt;/span&gt; __revit__&lt;span style="color: #666666"&gt;.&lt;/span&gt;ActiveUIDocument&lt;span style="color: #666666"&gt;.&lt;/span&gt;Document

&lt;span style="color: #408080; font-style: italic"&gt;# collect file location from user&lt;/span&gt;
clr&lt;span style="color: #666666"&gt;.&lt;/span&gt;AddReference(&lt;span style="color: #BA2121"&gt;&amp;#39;System.Windows.Forms&amp;#39;&lt;/span&gt;)
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;System.Windows.Forms&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; DialogResult, SaveFileDialog
dialog &lt;span style="color: #666666"&gt;=&lt;/span&gt; SaveFileDialog()
dialog&lt;span style="color: #666666"&gt;.&lt;/span&gt;Title &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;Export current view as PNG&amp;#39;&lt;/span&gt;
dialog&lt;span style="color: #666666"&gt;.&lt;/span&gt;Filter &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;PNG files (*.PNG)|*.PNG&amp;#39;&lt;/span&gt;

&lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; dialog&lt;span style="color: #666666"&gt;.&lt;/span&gt;ShowDialog() &lt;span style="color: #666666"&gt;==&lt;/span&gt; DialogResult&lt;span style="color: #666666"&gt;.&lt;/span&gt;OK:
    &lt;span style="color: #408080; font-style: italic"&gt;# set up the export options&lt;/span&gt;
    options &lt;span style="color: #666666"&gt;=&lt;/span&gt; ImageExportOptions()
    options&lt;span style="color: #666666"&gt;.&lt;/span&gt;ExportRange &lt;span style="color: #666666"&gt;=&lt;/span&gt; ExportRange&lt;span style="color: #666666"&gt;.&lt;/span&gt;VisibleRegionOfCurrentView
    options&lt;span style="color: #666666"&gt;.&lt;/span&gt;FilePath &lt;span style="color: #666666"&gt;=&lt;/span&gt; dialog&lt;span style="color: #666666"&gt;.&lt;/span&gt;FileName
    options&lt;span style="color: #666666"&gt;.&lt;/span&gt;HLRandWFViewsFileType &lt;span style="color: #666666"&gt;=&lt;/span&gt; ImageFileType&lt;span style="color: #666666"&gt;.&lt;/span&gt;PNG
    options&lt;span style="color: #666666"&gt;.&lt;/span&gt;ImageResolution &lt;span style="color: #666666"&gt;=&lt;/span&gt; ImageResolution&lt;span style="color: #666666"&gt;.&lt;/span&gt;DPI_72
    options&lt;span style="color: #666666"&gt;.&lt;/span&gt;ZoomType &lt;span style="color: #666666"&gt;=&lt;/span&gt; ZoomFitType&lt;span style="color: #666666"&gt;.&lt;/span&gt;Zoom
    options&lt;span style="color: #666666"&gt;.&lt;/span&gt;ShadowViewsFileType &lt;span style="color: #666666"&gt;=&lt;/span&gt; ImageFileType&lt;span style="color: #666666"&gt;.&lt;/span&gt;PNG

    doc&lt;span style="color: #666666"&gt;.&lt;/span&gt;ExportImage(options)

__window__&lt;span style="color: #666666"&gt;.&lt;/span&gt;Close()
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above code does some stuff necessary for any canned command in RPS: It adds references to the &lt;tt class="docutils literal"&gt;RevitAPI&lt;/tt&gt; and imports the &lt;tt class="docutils literal"&gt;Autodesk.Revit.DB&lt;/tt&gt; types. I also open a &lt;tt class="docutils literal"&gt;SaveFileDialog&lt;/tt&gt; using code found here: &lt;a class="reference external" href="http://www.ironpython.info/index.php/SaveFileDialog"&gt;http://www.ironpython.info/index.php/SaveFileDialog&lt;/a&gt;.&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-6456465873535391381?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/6456465873535391381/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2011/03/exporting-images-with-autodesk-revit.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/6456465873535391381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/6456465873535391381'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2011/03/exporting-images-with-autodesk-revit.html' title='Exporting Images with the Autodesk Revit API'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-1626819987313163059</id><published>2011-03-16T11:35:00.001+01:00</published><updated>2011-04-26T15:35:44.486+02:00</updated><title type='text'>How to install Trac on a Synology DS209+II</title><content type='html'>&lt;p&gt;These are some short notes on how I (successfully) installed Trac on a Synology DS209+II. The process should be similar for many other Synology servers. Please comment on any errors you find or snags you run into.&lt;/p&gt;
&lt;p&gt;I modified my Synology server from the original Synology setup:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;installed ipkg bootstrap (&lt;a class="reference external" href="http://forum.synology.com/wiki/index.php/Overview_on_modifying_the_Synology_Server,_bootstrap,_ipkg_etc"&gt;http://forum.synology.com/wiki/index.php/Overview_on_modifying_the_Synology_Server,_bootstrap,_ipkg_etc&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;installed subversion according to (&lt;a class="reference external" href="http://forum.synology.com/wiki/index.php/Step-by-step_guide_to_installing_Subversion_on_ARM-based_Synology_Products"&gt;http://forum.synology.com/wiki/index.php/Step-by-step_guide_to_installing_Subversion_on_ARM-based_Synology_Products&lt;/a&gt;)&lt;ul&gt;
&lt;li&gt;omitted WebSVN installation&lt;/li&gt;
&lt;li&gt;Subversion directory is &lt;tt class="docutils literal"&gt;/volume1/svn&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;did not configure &lt;tt class="docutils literal"&gt;inetd&lt;/tt&gt; to run &lt;tt class="docutils literal"&gt;svnserve&lt;/tt&gt;, as we are using Apache (see below)&lt;ul&gt;
&lt;li&gt;no changes to &lt;tt class="docutils literal"&gt;/etc/inetd.conf&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;no changes to &lt;tt class="docutils literal"&gt;/etc/services&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;since subversion is served by apache, we need to make sure the repositories have the same user as the apache server.&lt;ul&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;chown &lt;span class="pre"&gt;-R&lt;/span&gt; nobody:users /volume1/svn/MYREPO1&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;chown &lt;span class="pre"&gt;-R&lt;/span&gt; nobody:users /volume1/svn/MYREPO2&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;issued following commands in the root console:&lt;ul&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;ipkg update&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;ipkg install &lt;span class="pre"&gt;py25-trac&lt;/span&gt; &lt;span class="pre"&gt;py25-genshi&lt;/span&gt; &lt;span class="pre"&gt;py25-setuptools&lt;/span&gt; &lt;span class="pre"&gt;svn-py&lt;/span&gt;&lt;/tt&gt;&lt;ul&gt;
&lt;li&gt;maybe also: &lt;tt class="docutils literal"&gt;ipkg install sqlite&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;ipkg install apache&lt;/tt&gt;&lt;ul&gt;
&lt;li&gt;Now we have a second httpd listening on port 8000&lt;/li&gt;
&lt;li&gt;Configuration file is /opt/etc/apache2/httpd.conf&lt;/li&gt;
&lt;li&gt;Log files are in /opt/var/apache2/log/&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;div class="section" id="configuration-of-apache-for-subversion"&gt;
&lt;h1&gt;Configuration of Apache for Subversion&lt;/h1&gt;
&lt;p&gt;I appended following lines to &lt;tt class="docutils literal"&gt;/opt/etc/apache2/httpd.conf&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #408080; font-style: italic"&gt;# Subversion&lt;/span&gt;
&lt;span style="color: #008000"&gt;Include&lt;/span&gt; etc/apache2/conf.d/mod_dav_svn.conf
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Also, I created a file &lt;tt class="docutils literal"&gt;/opt/etc/apache2/conf.d/mod_dav_svn.conf&lt;/tt&gt; with following contents:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000"&gt;LoadModule&lt;/span&gt; dav_svn_module     libexec/mod_dav_svn.so
&lt;span style="color: #008000"&gt;LoadModule&lt;/span&gt; authz_svn_module   libexec/mod_authz_svn.so

&lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;Location&lt;/span&gt; &lt;span style="color: #BA2121"&gt;/svn&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;&amp;gt;&lt;/span&gt;
   &lt;span style="color: #008000"&gt;DAV&lt;/span&gt; svn
   &lt;span style="color: #008000"&gt;SVNParentPath&lt;/span&gt; &lt;span style="color: #008000"&gt;/volume1/svn&lt;/span&gt;
   &lt;span style="color: #008000"&gt;AuthType&lt;/span&gt; Basic
   &lt;span style="color: #008000"&gt;AuthName&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;Subversion repository&amp;quot;&lt;/span&gt;
   &lt;span style="color: #008000"&gt;AuthUserFile&lt;/span&gt; &lt;span style="color: #008000"&gt;/volume1/svn/svn-auth-file&lt;/span&gt;
   &lt;span style="color: #008000"&gt;Require&lt;/span&gt; valid-user
&lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;

&lt;span style="color: #408080; font-style: italic"&gt;# allow Apache to be used for authenticating Trac&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;Directory&lt;/span&gt; &lt;span style="color: #BA2121"&gt;/opt/share/www/trac&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;&amp;gt;&lt;/span&gt;
   &lt;span style="color: #008000"&gt;AuthType&lt;/span&gt; Basic
   &lt;span style="color: #008000"&gt;AuthName&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;Subversion repository&amp;quot;&lt;/span&gt;
   &lt;span style="color: #008000"&gt;AuthUserFile&lt;/span&gt; &lt;span style="color: #008000"&gt;/volume1/svn/svn-auth-file&lt;/span&gt;
   &lt;span style="color: #008000"&gt;Require&lt;/span&gt; valid-user
&lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;/Directory&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This expects a file &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/volume1/svn/svn-auth-file&lt;/span&gt;&lt;/tt&gt; to be present. That file
contains the passwords used for Subversion (and, via Apache, Trac
authentication). This file is generated with apaches &lt;tt class="docutils literal"&gt;htpasswd &lt;span class="pre"&gt;-c&lt;/span&gt;&lt;/tt&gt; command. I
used the &lt;tt class="docutils literal"&gt;cm&lt;/tt&gt; too, to force md5 hashing of the passwords. Also, I added the folder &lt;tt class="docutils literal"&gt;/opt/share/www/trac`&lt;/tt&gt; - this is used later on for Trac authentication, as I instruct Apache to authenticate this URL and tell Trac to use it for authentication.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="trac-configuration"&gt;
&lt;h1&gt;Trac configuration&lt;/h1&gt;
&lt;p&gt;I am running Trac version 0.11.7. The Trac environments can be found at &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/volume1/trac-env&lt;/span&gt;&lt;/tt&gt;. They are called &amp;quot;MYTRAC1&amp;quot; and &amp;quot;MYTRAC2&amp;quot;. Access to them is via the following URLs:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="http://myserver.example.com:8888/MYTRAC1"&gt;http://myserver.example.com:8888/MYTRAC1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://myserver.example.com:8888/MYTRAC2"&gt;http://myserver.example.com:8888/MYTRAC2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Trac is run using tracd. This is configured to start automatically on system start by creation of the following file: &lt;tt class="docutils literal"&gt;/opt/etc/init.d/S81trac&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #408080; font-style: italic"&gt;#!/bin/sh&lt;/span&gt;
&lt;span style="color: #408080; font-style: italic"&gt;# run tracd&lt;/span&gt;
/opt/bin/tracd -d -p 8888 -auth&lt;span style="color: #666666"&gt;=&lt;/span&gt;*,/volume1/svn/svn-auth-file,myserver.example.com -e /volume1/trac-env
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The file must be set to executable for root (see documentation for &lt;tt class="docutils literal"&gt;chmod&lt;/tt&gt;), so that it will be run at system start.&lt;/p&gt;
&lt;p&gt;Trac configuration files can be found at&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/volume1/trac-env/MYTRAC1/conf/trac.ini&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/volume1/trac-env/MYTRAC2/conf/trac.ini&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;div class="section" id="authentication-via-apache"&gt;
&lt;h2&gt;Authentication via Apache&lt;/h2&gt;
&lt;p&gt;Authentication is done with the AccountManager plugin for trac (&lt;a class="reference external" href="http://trac-hacks.org/wiki/AccountManagerPlugin"&gt;http://trac-hacks.org/wiki/AccountManagerPlugin&lt;/a&gt;). The website has a good explanation on how that works. See the copies of the &lt;tt class="docutils literal"&gt;trac.ini&lt;/tt&gt; files for reference. I'd like to point out the last section:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;[account-manager]&lt;/span&gt;
&lt;span style="color: #7D9029"&gt;password_store&lt;/span&gt; &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;HttpAuthStore&lt;/span&gt;
&lt;span style="color: #7D9029"&gt;authentication_url&lt;/span&gt; &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;http://myserver.example.com:8000/trac&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is where we tell Trac to use our Apache Server for authentication.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="backup"&gt;
&lt;h1&gt;Backup&lt;/h1&gt;
&lt;div class="section" id="backing-up-trac"&gt;
&lt;h2&gt;Backing up Trac&lt;/h2&gt;
&lt;p&gt;Trac is backed up with the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;trac-admin&lt;/span&gt; hotcopy&lt;/tt&gt; command. The configuration of the backup is in &lt;tt class="docutils literal"&gt;/etc/crontab&lt;/tt&gt;. It is done by executing the script &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/volume1/trac-env/tracbackup&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #408080; font-style: italic"&gt;#!/bin/sh&lt;/span&gt;

/opt/bin/trac-admin /v9olume1/trac-env/MYTRAC1 hotcopy &lt;span style="color: #BA2121"&gt;`&lt;/span&gt;date +/volumeUSB1/usbshare/TracBackup/%Y%m%d_trac_hotcopy_MYTRAC1&lt;span style="color: #BA2121"&gt;`&lt;/span&gt;
/opt/bin/trac-admin /v9olume1/trac-env/MYTRAC2 hotcopy &lt;span style="color: #BA2121"&gt;`&lt;/span&gt;date +/volumeUSB1/usbshare/TracBackup/%Y%m%d_trac_hotcopy_MYTRAC2&lt;span style="color: #BA2121"&gt;`&lt;/span&gt;

&lt;span style="color: #408080; font-style: italic"&gt;# make sure other computers connecting to the share&lt;/span&gt;
&lt;span style="color: #408080; font-style: italic"&gt;# can delete these files&lt;/span&gt;
chmod 777 /volumeUSB1/usbshare/TracBackup/*
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;FIXME: these still have to be deleted regularly. I do this from my PC, so as to keep the complexity on the server minimal.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="backing-up-subversion"&gt;
&lt;h2&gt;Backing up Subversion&lt;/h2&gt;
&lt;p&gt;Subversion is backed up with the &lt;tt class="docutils literal"&gt;svnadmin dump&lt;/tt&gt; command, since this can then be read in from other subversion versions. The configuration of the backup is in &lt;tt class="docutils literal"&gt;/etc/crontab&lt;/tt&gt;. It is done by executing the script &lt;tt class="docutils literal"&gt;/volume1/svn/svnbackup&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #408080; font-style: italic"&gt;#!/bin/sh&lt;/span&gt;

/opt/bin/svnadmin dump /volume1/svn/MYREPO1 &amp;gt; &lt;span style="color: #BA2121"&gt;`&lt;/span&gt;date +/volumeUSB1/usbshare/SvnBackup/%Y%m%d_svn_dump_MYREPO1&lt;span style="color: #BA2121"&gt;`&lt;/span&gt;
/opt/bin/svnadmin dump /volume1/svn/MYREPO2 &amp;gt; &lt;span style="color: #BA2121"&gt;`&lt;/span&gt;date +/volumeUSB1/usbshare/SvnBackup/%Y%m%d_svn_dump_MYREPO2&lt;span style="color: #BA2121"&gt;`&lt;/span&gt;

&lt;span style="color: #408080; font-style: italic"&gt;# make sure other computers connecting to the share&lt;/span&gt;
&lt;span style="color: #408080; font-style: italic"&gt;# can delete these files&lt;/span&gt;
chmod 777 /volumeUSB1/usbshare/SvnBackup/*
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;FIXME: these still have to be deleted regularly. I do this from my PC, so as to keep the complexity on the server minimal.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-1626819987313163059?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/1626819987313163059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2011/03/how-to-install-trac-on-synology-ds209ii.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/1626819987313163059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/1626819987313163059'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2011/03/how-to-install-trac-on-synology-ds209ii.html' title='How to install Trac on a Synology DS209+II'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-1107989877510271620</id><published>2011-02-10T16:39:00.001+01:00</published><updated>2011-02-10T16:43:25.369+01:00</updated><title type='text'>Status Bar Text and WPF</title><content type='html'>&lt;p&gt;Yesterday, Jeremy Tammik posted &lt;a class="reference external" href="http://thebuildingcoder.typepad.com/blog/2011/02/status-bar-text.html"&gt;how to change the status bar text in Revit&lt;/a&gt;.
Toward the end of his post, he mentions using &lt;tt class="docutils literal"&gt;GetCurrentProcess&lt;/tt&gt; to find the
HWND of the main Revit window.&lt;/p&gt;
&lt;p&gt;Yay! says I: Now I can print out status text, without cluttering up my shiny WPF window.&lt;/p&gt;
&lt;p&gt;Nay! says WPF: It doesn't work.&lt;/p&gt;
&lt;p&gt;Imagine my frustration... I spent some time analysing this using &lt;a class="reference external" href="http://msdn.microsoft.com/en-us/library/aa264396(v=VS.60).aspx"&gt;SPY++&lt;/a&gt; and found out, that WPF dialogs are not children of the main application window. If your &lt;tt class="docutils literal"&gt;IExternalCommand&lt;/tt&gt; starts a WPF window, then you should note the HWND &lt;em&gt;first&lt;/em&gt; and &lt;em&gt;then&lt;/em&gt; show the dialog. You can keep the HWND in a class variable, since it won't change. I ended up with a utility static class &lt;cite&gt;StatusText&lt;/cite&gt;:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;static&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;StatusText&lt;/span&gt;
{
&lt;span style="color: #7D9029"&gt;    [DllImport(&amp;quot;user32.dll&amp;quot;, SetLastError = true, CharSet = CharSet.Auto)]&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;static&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;extern&lt;/span&gt; &lt;span style="color: #B00040"&gt;int&lt;/span&gt; &lt;span style="color: #0000FF"&gt;SetWindowText&lt;/span&gt;(IntPtr hWnd, &lt;span style="color: #B00040"&gt;string&lt;/span&gt; lpString);

&lt;span style="color: #7D9029"&gt;    [DllImport(&amp;quot;user32.dll&amp;quot;, SetLastError = true)]&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;static&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;extern&lt;/span&gt; IntPtr &lt;span style="color: #0000FF"&gt;FindWindowEx&lt;/span&gt;(IntPtr hwndParent, IntPtr hwndChildAfter,
                                      &lt;span style="color: #B00040"&gt;string&lt;/span&gt; lpszClass, &lt;span style="color: #B00040"&gt;string&lt;/span&gt; lpszWindow);

    &lt;span style="color: #008000; font-weight: bold"&gt;private&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;static&lt;/span&gt; IntPtr _hwndRevit = &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; IntPtr();

    &lt;span style="color: #408080; font-style: italic"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span style="color: #408080; font-style: italic"&gt;/// Set the handle to the revit main window here before calling&lt;/span&gt;
    &lt;span style="color: #408080; font-style: italic"&gt;/// SetStatusText.&lt;/span&gt;
    &lt;span style="color: #408080; font-style: italic"&gt;/// (also, set it in the IExternalCommand.Execute thread, not&lt;/span&gt;
    &lt;span style="color: #408080; font-style: italic"&gt;/// in your WPF thread)&lt;/span&gt;
    &lt;span style="color: #408080; font-style: italic"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;static&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;SetRevitWindowHandle&lt;/span&gt;(IntPtr hwnd)
    {
        _hwndRevit = hwnd;
    }

    &lt;span style="color: #408080; font-style: italic"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span style="color: #408080; font-style: italic"&gt;/// Set the status text of the current revit instance.&lt;/span&gt;
    &lt;span style="color: #408080; font-style: italic"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;static&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;SetStatusText&lt;/span&gt;(&lt;span style="color: #B00040"&gt;string&lt;/span&gt; text)
    {
        IntPtr statusBar = FindWindowEx(_hwndRevit, IntPtr.Zero,
                                        &lt;span style="color: #BA2121"&gt;&amp;quot;msctls_statusbar32&amp;quot;&lt;/span&gt;, &lt;span style="color: #BA2121"&gt;&amp;quot;&amp;quot;&lt;/span&gt;);

        &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; (statusBar != IntPtr.Zero)
        {
            SetWindowText(statusBar, text);
        }
    }

}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can then just issue a&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;StatusText.SetStatusText(&lt;span style="color: #BA2121"&gt;&amp;quot;hello, world!&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;whenever you need to display something cool. Bonus points for hooking this up to a &lt;cite&gt;TraceListener&lt;/cite&gt; ;)&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-1107989877510271620?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/1107989877510271620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2011/02/status-bar-text-and-wpf.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/1107989877510271620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/1107989877510271620'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2011/02/status-bar-text-and-wpf.html' title='Status Bar Text and WPF'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-5952186693099359766</id><published>2010-11-26T09:29:00.001+01:00</published><updated>2010-11-26T09:32:56.803+01:00</updated><title type='text'>A Pattern For Asynchronously Updating Revit Documents</title><content type='html'>&lt;p&gt;With Revit 2011 we got a new event: &lt;tt class="docutils literal"&gt;UIApplication.Idling&lt;/tt&gt;. This post is
about how to use the &lt;tt class="docutils literal"&gt;Idling&lt;/tt&gt; event to update a Revit document outside the
scope of an &lt;tt class="docutils literal"&gt;IExternalCommand&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Imagine a dialog, opened by an &lt;tt class="docutils literal"&gt;IExternalCommand&lt;/tt&gt;. Let us leave the dialog
open and return &lt;tt class="docutils literal"&gt;Result.Succeeded&lt;/tt&gt;. Let us also set the dialog to stay on top
always. A bit like a tool window with some funky gadgets and commands. We want
those commands to alter something in the Revit document and then update its
gadgets to display stuff.&lt;/p&gt;
&lt;p&gt;If you just stash away the &lt;tt class="docutils literal"&gt;ExternalCommandData&lt;/tt&gt; and try to access the Revit
application using that, you will crash Revit sooner or later. I forget the
exact message, but something along the lines of reading/writing memory you
shouldn't be. But you were warned by the docs, so, stop whining: Outside of the
&lt;tt class="docutils literal"&gt;IExternalCommand.Execute&lt;/tt&gt; method, the command data becomes stale and should not
be used anymore.&lt;/p&gt;
&lt;p&gt;Create a static &lt;tt class="docutils literal"&gt;Queue&lt;/tt&gt; of &lt;tt class="docutils literal"&gt;Action&amp;lt;UIApplication&amp;gt;&lt;/tt&gt;. You can store this in
your &lt;tt class="docutils literal"&gt;IExternalApplication&lt;/tt&gt; implementation and initialize it to an empty list
on startup. This queue has to be &lt;tt class="docutils literal"&gt;static&lt;/tt&gt; as you want it to persist while the
class is loaded in memory (the class will be loaded by Revit on startup).&lt;/p&gt;
&lt;p&gt;Next, hook up to the &lt;tt class="docutils literal"&gt;Idling&lt;/tt&gt; event in your &lt;tt class="docutils literal"&gt;IExternalApplication.OnStartup&lt;/tt&gt; method:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;private&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;static&lt;/span&gt; Queue&amp;lt;Action&amp;lt;UIApplication&amp;gt;&amp;gt; _tasks;
&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; Result &lt;span style="color: #0000FF"&gt;OnStartup&lt;/span&gt;(UIControlledApplication revit)
{
    _tasks = &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; Queue&amp;lt;Action&amp;lt;UIApplication&amp;gt;&amp;gt;()
    revit.Idling += OnIdling;
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Great. Now for the implementation of &lt;tt class="docutils literal"&gt;OnIdling&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;private&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;OnIdling&lt;/span&gt;(&lt;span style="color: #B00040"&gt;object&lt;/span&gt; sender, IdlingEventArgs e)
{
    var app = (UIApplication)sender;
    &lt;span style="color: #008000; font-weight: bold"&gt;lock&lt;/span&gt; (_tasks)
    {
        &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; (_tasks.Count &amp;gt; &lt;span style="color: #666666"&gt;0&lt;/span&gt;)
        {
            Action&amp;lt;UIApplication&amp;gt; task = _tasks.Dequeue();

            &lt;span style="color: #408080; font-style: italic"&gt;// execute the task!&lt;/span&gt;
            task(app);
        }
    }
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is one half of the equation. Next, we have to get the tasks into queue.
Also, note that I'm locking the queue before reading it, since the dialog might
access it at the same time as we are reading and I just want to be safe here.&lt;/p&gt;
&lt;p&gt;To add a tasks to the queue, we just need a method in the
&lt;tt class="docutils literal"&gt;IExternalApplication&lt;/tt&gt; that will accept it:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;static&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;EnqueueTask&lt;/span&gt;(Action&amp;lt;UIDocument&amp;gt; task)
{
    &lt;span style="color: #008000; font-weight: bold"&gt;lock&lt;/span&gt; (_tasks)
    {
        _tasks.Enqueue(task);
    }
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This can then be called from your dialogs code, e.g. when a button is pressed.
Assuming your &lt;tt class="docutils literal"&gt;IExternalApplication&lt;/tt&gt; is called &lt;tt class="docutils literal"&gt;FooPlugin&lt;/tt&gt;, an invocation
could look something like this:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;YouPushedMyButton&lt;/span&gt;(&lt;span style="color: #B00040"&gt;object&lt;/span&gt; sender, EventArgs args)
{
     FooPlugin.Enqueue((app) =&amp;gt; {
         var doc = app.ActiveUIDocument.Document;
         doc.ProjectInformation.ClientName = &lt;span style="color: #BA2121"&gt;&amp;quot;Boss Murphy&amp;quot;&lt;/span&gt;;
     });
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you are not familiar with the &lt;tt class="docutils literal"&gt;(app) =&amp;gt; { /* statements */ }&lt;/tt&gt; this is a
statement lambda. You might want to read the chapter &lt;a class="reference external" href="http://msdn.microsoft.com/en-us/library/bb397687.aspx"&gt;Lambda Expressions&lt;/a&gt; from
the C# Programming Guide on msdn.&lt;/p&gt;
&lt;p&gt;A nice property of these lambda expressions is, that they create a closure around the variables that were in scope at the time of creation. Instead of &lt;tt class="docutils literal"&gt;&amp;quot;Boss Murphy&amp;quot;&lt;/tt&gt; I could also have assigned some instance value from the dialog or a local variable from &lt;tt class="docutils literal"&gt;YouPushedMyButton&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;The next time Revit fires an &lt;tt class="docutils literal"&gt;Idling&lt;/tt&gt; Event, your tasks will be executed!&lt;/p&gt;
&lt;p&gt;Oh, one thing: You will have to make sure you open a transaction. I haven't done this in the example, to keep things short and simple, but it's going to go &lt;em&gt;boom&lt;/em&gt; on you! There are two possible places for this: Either in the lambda statement directly, or, if you know for sure that you are always going to need a transaction (all your tasks will be writing to the document), you could add it in the &lt;tt class="docutils literal"&gt;OnIdling&lt;/tt&gt; event handler, wrapping the &lt;tt class="docutils literal"&gt;task(app)&lt;/tt&gt; call.&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-5952186693099359766?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/5952186693099359766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/11/pattern-for-asynchronously-updating.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/5952186693099359766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/5952186693099359766'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/11/pattern-for-asynchronously-updating.html' title='A Pattern For Asynchronously Updating Revit Documents'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-8693712342274507820</id><published>2010-11-12T16:52:00.001+01:00</published><updated>2010-11-12T16:57:07.427+01:00</updated><title type='text'>Listing Level Elevations with RevitPythonShell</title><content type='html'>&lt;p&gt;I recently stumbled apon the &lt;a class="reference external" href="http://blog.revitapp.com/"&gt;Revit APP blog&lt;/a&gt; and spotted a simple code
listing for &lt;cite&gt;getting all level elevations&lt;/cite&gt;. This should be a no-brainer using
the &lt;a class="reference external" href="http://revitpythonshell.googlecode.com"&gt;RevitPythonShell&lt;/a&gt; (RPS), so I fired up a shell and started typing. This is
a session transcript in the shell:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;clr&lt;/span&gt;

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;clr&lt;span style="color: #666666"&gt;.&lt;/span&gt;AddReference(&lt;span style="color: #BA2121"&gt;&amp;#39;RevitAPI&amp;#39;&lt;/span&gt;)

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Autodesk.Revit.DB&lt;/span&gt;

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;collector &lt;span style="color: #666666"&gt;=&lt;/span&gt; Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;FilteredElementCollector(__revit__&lt;span style="color: #666666"&gt;.&lt;/span&gt;ActiveUIDocument&lt;span style="color: #666666"&gt;.&lt;/span&gt;Document)

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;elems &lt;span style="color: #666666"&gt;=&lt;/span&gt; collector&lt;span style="color: #666666"&gt;.&lt;/span&gt;WhereElementIsNotElementType()&lt;span style="color: #666666"&gt;.&lt;/span&gt;OfClass(Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;Level)&lt;span style="color: #666666"&gt;.&lt;/span&gt;ToElements()

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; lv &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; elems:
&lt;span style="color: #666666"&gt;...&lt;/span&gt;    &lt;span style="color: #008000; font-weight: bold"&gt;print&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%s&lt;/span&gt;&lt;span style="color: #BA2121"&gt;: &lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%.2f&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;#39;&lt;/span&gt; &lt;span style="color: #666666"&gt;%&lt;/span&gt; (lv&lt;span style="color: #666666"&gt;.&lt;/span&gt;Name, lv&lt;span style="color: #666666"&gt;.&lt;/span&gt;Elevation)
&lt;span style="color: #666666"&gt;...&lt;/span&gt;
Level &lt;span style="color: #666666"&gt;1&lt;/span&gt;: &lt;span style="color: #666666"&gt;0.00&lt;/span&gt;
Level &lt;span style="color: #666666"&gt;2&lt;/span&gt;: &lt;span style="color: #666666"&gt;9.84&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I am getting a bit fed up of typing &lt;tt class="docutils literal"&gt;import clr&lt;/tt&gt; and referencing &lt;tt class="docutils literal"&gt;RevitAPI&lt;/tt&gt; whenever I use RPS so
my next step will be to try and add that by default. I'll keep you posted about that.&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-8693712342274507820?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/8693712342274507820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/11/listing-level-elevations-with.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/8693712342274507820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/8693712342274507820'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/11/listing-level-elevations-with.html' title='Listing Level Elevations with RevitPythonShell'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-8130182942647489568</id><published>2010-11-10T09:21:00.001+01:00</published><updated>2010-11-12T16:59:20.180+01:00</updated><title type='text'>Unit Testing Revit Plugins</title><content type='html'>&lt;p&gt;Yesterday, Jeremy Tammik brought an interesting thread on augi (&lt;a class="reference external" href="http://forums.augi.com/showthread.php?t=98536"&gt;Unit testing
with Revit API&lt;/a&gt;) to my attention, suggesting that I might like to add
something on the &lt;a class="reference external" href="http://code.google.com/p/revitpythonshell/"&gt;RevitPythonShell&lt;/a&gt; (RPS).&lt;/p&gt;
&lt;p&gt;I couldn't register as a member on augi (some mail thing I don't want to digg
into), so I thought I'd add my thoughts here.&lt;/p&gt;
&lt;p&gt;First a disclaimer: I'm not test infected. I don't floss my teeth every day either -
unit testing is just one of those things you &lt;em&gt;should&lt;/em&gt; be doing, but
nothing really bad happens if you don't. Especially if you use tooth
picks etc.&lt;/p&gt;
&lt;p&gt;Unit tests (as I understand the term) cannot be dependent on an
environment (in this case: Revit). So running a test as a Revit plugin
with a Revit document is not a unit test. It is an integration test. I
do plenty of these. Here is how:&lt;/p&gt;
&lt;p&gt;Using the RPS, I create a &amp;quot;driver&amp;quot; script that
loads the assembly to be tested (see the &lt;a class="reference external" href="http://darenatwork.blogspot.com/2010/03/using-revitpythonshell-to-dynamically.html"&gt;loadplugin module&lt;/a&gt;) and
executes its public methods, much the same way as the &lt;tt class="docutils literal"&gt;IExternalCommand&lt;/tt&gt;
implementation would. Note here, that I tend to keep my
&lt;tt class="docutils literal"&gt;IExternalCommand&lt;/tt&gt; implementations &amp;quot;dumb&amp;quot;, refactoring the logic to
other parts of the assembly, so that I don't have to test the
&lt;tt class="docutils literal"&gt;IExternalCommand&lt;/tt&gt; itself (it should just be evident that it works, e.g.
instantiate plugin object, call public method on it passing some
command data, return).&lt;/p&gt;
&lt;p&gt;The &amp;quot;driver&amp;quot; script can be registered as an RPS command and will then
show up in the Revit Ribbon. You can even assign a keyboard shortcut to it
using the standard Revit procedure for shortcuts (you will have to
restart Revit after registering the RPS command first, as it only then
gets promoted to an &lt;tt class="docutils literal"&gt;IExternalCommand&lt;/tt&gt;). Run it often (after every
compile)!&lt;/p&gt;
&lt;p&gt;I generally don't register plugins that are under development with
Revit, so that Revit doesn't lock the assembly on startup - this way,
I can keep the source open in Visual Studio and build to my hearts
content. The &amp;quot;driver&amp;quot; script will just pick up the newest build and
test it.&lt;/p&gt;
&lt;p&gt;Anything written to &amp;quot;Debug.WriteLine&amp;quot; will be output in the RPS
window. This is handy for testing stuff!&lt;/p&gt;
&lt;p&gt;Once you are at the &amp;quot;driver&amp;quot; script level, you can employ pythons unit
testing libraries: unittest and also use the doc tests. This also
keeps your tests separate from your production code, especially since
you are using another language to write the tests!&lt;/p&gt;
&lt;p&gt;If you really want to do unit testing, you will have to go the full
monty - this is the reason for unit testing anyway:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;dl class="first docutils"&gt;
&lt;dt&gt;Split up your code into Revit dependent functionality and modules.&lt;/dt&gt;
&lt;dd&gt;&lt;ul class="first last simple"&gt;
&lt;li&gt;Study refactoring as taught by the masters of the discipline (I like &lt;a class="reference external" href="http://martinfowler.com/books.html#refactoring"&gt;Martin Fowlers Refactoring&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Make sure your plugin abstracts from the Revit stuff into a logical model that you can then mock and write tests to.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Regard the Revit API as an I/O interface or a database connection that is not part of unit testing.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-8130182942647489568?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/8130182942647489568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/11/unit-testing-revit-plugins_10.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/8130182942647489568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/8130182942647489568'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/11/unit-testing-revit-plugins_10.html' title='Unit Testing Revit Plugins'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-2370472523986012384</id><published>2010-11-09T17:19:00.001+01:00</published><updated>2010-11-09T17:19:14.934+01:00</updated><title type='text'>Revit Room Boundaries</title><content type='html'>&lt;p&gt;This came up today at work: For a given room, what are the room bounding objects?&lt;/p&gt;
&lt;p&gt;Questions like these can easily be solved with &lt;a class="reference external" href="http://code.google.com/p/revitpythonshell/"&gt;RevitPythonShell&lt;/a&gt;. So I fired up an RPS shell and came up with the following script:&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;clr&lt;/span&gt;
clr&lt;span style="color: #666666"&gt;.&lt;/span&gt;AddReference(&lt;span style="color: #BA2121"&gt;&amp;#39;RevitAPI&amp;#39;&lt;/span&gt;)
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Autodesk.Revit.DB.Architecture&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; Room
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Autodesk.Revit.DB&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; Wall

sel &lt;span style="color: #666666"&gt;=&lt;/span&gt; __revit__&lt;span style="color: #666666"&gt;.&lt;/span&gt;ActiveUIDocument&lt;span style="color: #666666"&gt;.&lt;/span&gt;Selection&lt;span style="color: #666666"&gt;.&lt;/span&gt;Elements
rooms &lt;span style="color: #666666"&gt;=&lt;/span&gt; [e &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; e &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; sel &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; &lt;span style="color: #008000"&gt;type&lt;/span&gt;(e) &lt;span style="color: #AA22FF; font-weight: bold"&gt;is&lt;/span&gt; Room]
&lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; room &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; rooms:
    &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; bsa &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; room&lt;span style="color: #666666"&gt;.&lt;/span&gt;Boundary:     &lt;span style="color: #408080; font-style: italic"&gt;# bsa = BoundarySegmentArray&lt;/span&gt;
        &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; bs &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; bsa:            &lt;span style="color: #408080; font-style: italic"&gt;# bs = BoundarySegment&lt;/span&gt;
            &lt;span style="color: #008000; font-weight: bold"&gt;print&lt;/span&gt; bs&lt;span style="color: #666666"&gt;.&lt;/span&gt;Element
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This gets you quite close. I added a &lt;a class="reference external" href="http://code.google.com/p/revitpythonshell/wiki/FeaturedScriptRevitRoomBoundaries"&gt;featured script to the RPS site&lt;/a&gt; that can be used as an RPS command and prints the element id for boundary segments that are model elements.&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-2370472523986012384?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/2370472523986012384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/11/revit-room-boundaries.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/2370472523986012384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/2370472523986012384'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/11/revit-room-boundaries.html' title='Revit Room Boundaries'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-6765641217028093869</id><published>2010-10-06T15:06:00.001+02:00</published><updated>2010-11-12T17:01:24.708+01:00</updated><title type='text'>Obfuscating an Autodesk Revit Plugin</title><content type='html'>&lt;p&gt;Jeremy Tammik mentions obfuscation for Revit plugins in his post &lt;a class="reference external" href="http://thebuildingcoder.typepad.com/blog/2009/08/obfuscation-tools.html"&gt;Obfuscation Tools&lt;/a&gt;. I would like to mention two free obfusctators I have used:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="http://www.foss.kharkov.ua/g1/projects/eazfuscator/dotnet/Default.aspx"&gt;Eazfuscator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://www.babelfor.net/"&gt;Babel .NET&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Both of these can be hooked up to your build script so that they obfuscate automatically. Please read their documentation on how to do this.&lt;/p&gt;
&lt;p&gt;I liked Eazfuscator a lot and used it for all dependant assemblies of my project, but sadly, it chokes on references to the assembly &lt;tt class="docutils literal"&gt;RevitAPI&lt;/tt&gt;. So for developing Autodesk Revit Plugins, it will not work.&lt;/p&gt;
&lt;p&gt;Babel .NET &lt;em&gt;can&lt;/em&gt; obfuscate assemblies that reference &lt;tt class="docutils literal"&gt;RevitAPI.dll&lt;/tt&gt;. I tied it into my build process in Visual Studio 2010 as a Post-build event command line:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;select your project in the Solution Explorer&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;right-click and choose &lt;em&gt;Properties&lt;/em&gt; from the context menu&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;in the tab &lt;em&gt;Build Events&lt;/em&gt;, enter the following in the field &lt;em&gt;Post-build event command line&lt;/em&gt;:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
if /I &amp;quot;$(ConfigurationName)&amp;quot; NEQ &amp;quot;Debug&amp;quot; &amp;quot;C:\Program Files\Babel\Babel.exe&amp;quot; &amp;quot;$(TargetPath)&amp;quot; --stringencrypt --output &amp;quot;$(TargetPath)&amp;quot;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;This assumes, of course, that you have installed Babel .NET to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;C:\Program&lt;/span&gt; Files\Babel&lt;/tt&gt;. Also note, that the build configuration &amp;quot;Debug&amp;quot; is excluded from obfuscation.&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-6765641217028093869?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/6765641217028093869/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/10/obfuscating-autodesk-revit-plugin.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/6765641217028093869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/6765641217028093869'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/10/obfuscating-autodesk-revit-plugin.html' title='Obfuscating an Autodesk Revit Plugin'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-3307172586873296161</id><published>2010-08-19T10:27:00.001+02:00</published><updated>2010-08-19T10:41:28.291+02:00</updated><title type='text'>Deleting a bunch of Elements By ElementId in RevitPythonShell</title><content type='html'>&lt;p&gt;I know I promised examples for &lt;a class="reference external" href="http://code.google.com/p/revitpythonshell/"&gt;RevitPythonShell&lt;/a&gt; and never delivered. Well,
here is an example I came across this morning:&lt;/p&gt;
&lt;p&gt;I had to delete a bunch of elements from a document. I new the ids of the
elements and was about to manually delete them using the &amp;quot;Select by ID&amp;quot; tool in
Revit and deleting them one by one. I know this works, because I did the exact
same thing yesterday on the exact same document, but forgot to save the
changes. I'd just have to do all that tedious work again.&lt;/p&gt;
&lt;p&gt;But then I thought: Wait a minute...  aren't we supposed to be scripting this
stuff?&lt;/p&gt;
&lt;p&gt;So, here is a session in the shell part of &lt;a class="reference external" href="http://code.google.com/p/revitpythonshell/"&gt;RevitPythonShell&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;ids &lt;span style="color: #666666"&gt;=&lt;/span&gt; [&lt;span style="color: #666666"&gt;136116&lt;/span&gt;, &lt;span style="color: #666666"&gt;136119&lt;/span&gt;, &lt;span style="color: #666666"&gt;136120&lt;/span&gt;, &lt;span style="color: #666666"&gt;136121&lt;/span&gt;, &lt;span style="color: #666666"&gt;136122&lt;/span&gt;, &lt;span style="color: #666666"&gt;136131&lt;/span&gt;, &lt;span style="color: #666666"&gt;136132&lt;/span&gt;, &lt;span style="color: #666666"&gt;136133&lt;/span&gt;, &lt;span style="color: #666666"&gt;136134&lt;/span&gt;, &lt;span style="color: #666666"&gt;136135&lt;/span&gt;, &lt;span style="color: #666666"&gt;136136&lt;/span&gt;, &lt;span style="color: #666666"&gt;136137&lt;/span&gt;, &lt;span style="color: #666666"&gt;136138&lt;/span&gt;, &lt;span style="color: #666666"&gt;136139&lt;/span&gt;, &lt;span style="color: #666666"&gt;136140&lt;/span&gt;, &lt;span style="color: #666666"&gt;136141&lt;/span&gt;, &lt;span style="color: #666666"&gt;136142&lt;/span&gt;, &lt;span style="color: #666666"&gt;136143&lt;/span&gt;, &lt;span style="color: #666666"&gt;136144&lt;/span&gt;, &lt;span style="color: #666666"&gt;136145&lt;/span&gt;, &lt;span style="color: #666666"&gt;136155&lt;/span&gt;, &lt;span style="color: #666666"&gt;136165&lt;/span&gt;, &lt;span style="color: #666666"&gt;136206&lt;/span&gt;, &lt;span style="color: #666666"&gt;136306&lt;/span&gt;, &lt;span style="color: #666666"&gt;136309&lt;/span&gt;, &lt;span style="color: #666666"&gt;136419&lt;/span&gt;, &lt;span style="color: #666666"&gt;136422&lt;/span&gt;]

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;clr&lt;/span&gt;

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;clr&lt;span style="color: #666666"&gt;.&lt;/span&gt;AddReference(&lt;span style="color: #BA2121"&gt;&amp;quot;RevitAPI&amp;quot;&lt;/span&gt;)

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Autodesk.Revit.DB&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #666666"&gt;*&lt;/span&gt;

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;transaction &lt;span style="color: #666666"&gt;=&lt;/span&gt; Transaction(doc, &lt;span style="color: #BA2121"&gt;&amp;quot;find all the mutants!&amp;quot;&lt;/span&gt;)

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;transaction&lt;span style="color: #666666"&gt;.&lt;/span&gt;Start()

&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; &lt;span style="color: #008000"&gt;id&lt;/span&gt; &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; ids:
&lt;span style="color: #666666"&gt;...&lt;/span&gt;    doc&lt;span style="color: #666666"&gt;.&lt;/span&gt;Delete(doc&lt;span style="color: #666666"&gt;.&lt;/span&gt;get_Element(ElementId(&lt;span style="color: #008000"&gt;id&lt;/span&gt;)))
&lt;span style="color: #666666"&gt;...&lt;/span&gt;
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x000000000000002D&lt;/span&gt; [&lt;span style="color: #666666"&gt;136116&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x000000000000002E&lt;/span&gt; [&lt;span style="color: #666666"&gt;136119&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x000000000000002F&lt;/span&gt; [&lt;span style="color: #666666"&gt;136120&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000030&lt;/span&gt; [&lt;span style="color: #666666"&gt;136121&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000031&lt;/span&gt; [&lt;span style="color: #666666"&gt;136122&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000032&lt;/span&gt; [&lt;span style="color: #666666"&gt;136131&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;, &lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000033&lt;/span&gt; [&lt;span style="color: #666666"&gt;170627&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000034&lt;/span&gt; [&lt;span style="color: #666666"&gt;136132&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000035&lt;/span&gt; [&lt;span style="color: #666666"&gt;136133&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000036&lt;/span&gt; [&lt;span style="color: #666666"&gt;136134&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;, &lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000037&lt;/span&gt; [&lt;span style="color: #666666"&gt;170628&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000038&lt;/span&gt; [&lt;span style="color: #666666"&gt;136135&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000039&lt;/span&gt; [&lt;span style="color: #666666"&gt;136136&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x000000000000003A&lt;/span&gt; [&lt;span style="color: #666666"&gt;136137&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;, &lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x000000000000003B&lt;/span&gt; [&lt;span style="color: #666666"&gt;170629&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x000000000000003C&lt;/span&gt; [&lt;span style="color: #666666"&gt;136138&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x000000000000003D&lt;/span&gt; [&lt;span style="color: #666666"&gt;136139&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x000000000000003E&lt;/span&gt; [&lt;span style="color: #666666"&gt;136140&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;, &lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x000000000000003F&lt;/span&gt; [&lt;span style="color: #666666"&gt;170630&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000040&lt;/span&gt; [&lt;span style="color: #666666"&gt;136141&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000041&lt;/span&gt; [&lt;span style="color: #666666"&gt;136142&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000042&lt;/span&gt; [&lt;span style="color: #666666"&gt;136143&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;, &lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000043&lt;/span&gt; [&lt;span style="color: #666666"&gt;170631&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000044&lt;/span&gt; [&lt;span style="color: #666666"&gt;136144&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000045&lt;/span&gt; [&lt;span style="color: #666666"&gt;136145&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000046&lt;/span&gt; [&lt;span style="color: #666666"&gt;136155&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000047&lt;/span&gt; [&lt;span style="color: #666666"&gt;136165&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000048&lt;/span&gt; [&lt;span style="color: #666666"&gt;136206&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x0000000000000049&lt;/span&gt; [&lt;span style="color: #666666"&gt;136306&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x000000000000004A&lt;/span&gt; [&lt;span style="color: #666666"&gt;136309&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x000000000000004B&lt;/span&gt; [&lt;span style="color: #666666"&gt;136419&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
List[ElementId]([&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;ElementId &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x000000000000004C&lt;/span&gt; [&lt;span style="color: #666666"&gt;136422&lt;/span&gt;]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;])
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;transaction&lt;span style="color: #666666"&gt;.&lt;/span&gt;Commit()

&lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt;Autodesk&lt;span style="color: #666666"&gt;.&lt;/span&gt;Revit&lt;span style="color: #666666"&gt;.&lt;/span&gt;DB&lt;span style="color: #666666"&gt;.&lt;/span&gt;TransactionStatus &lt;span style="color: #008000"&gt;object&lt;/span&gt; at &lt;span style="color: #666666"&gt;0x000000000000004D&lt;/span&gt; [Committed]&lt;span style="color: #666666"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here a few notes that might illuminate some parts of working with RevitPythonShell:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;access to the Revit API is added by the following lines&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;clr&lt;/span&gt;
clr&lt;span style="color: #666666"&gt;.&lt;/span&gt;AddReference(&lt;span style="color: #BA2121"&gt;&amp;quot;RevitAPI&amp;quot;&lt;/span&gt;)
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Autodesk.Revit.DB&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #666666"&gt;*&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;the document is provided via the &lt;tt class="docutils literal"&gt;__revit__&lt;/tt&gt; variable&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;doc &lt;span style="color: #666666"&gt;=&lt;/span&gt; __revit__&lt;span style="color: #666666"&gt;.&lt;/span&gt;ActiveUIDocument&lt;span style="color: #666666"&gt;.&lt;/span&gt;Document
&lt;/pre&gt;&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;you need to start a transaction before changing the document&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;transaction &lt;span style="color: #666666"&gt;=&lt;/span&gt; Transaction(doc, &lt;span style="color: #BA2121"&gt;&amp;quot;call this whatever you like&amp;quot;&lt;/span&gt;)
transaction&lt;span style="color: #666666"&gt;.&lt;/span&gt;Start()
&lt;span style="color: #408080; font-style: italic"&gt;# do stuff&lt;/span&gt;
transaction&lt;span style="color: #666666"&gt;.&lt;/span&gt;Commit()
&lt;/pre&gt;&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;to get an element given an integer, use this technique&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight" style="background: #f8f8f8"&gt;&lt;pre style="line-height: 125%"&gt;element &lt;span style="color: #666666"&gt;=&lt;/span&gt; doc&lt;span style="color: #666666"&gt;.&lt;/span&gt;get_Element(ElementId(myinteger))
&lt;/pre&gt;&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;Document.Delete()&lt;/tt&gt; returns a list of deleted elements on each call. That is what the clutter (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;List[ElementId]([Autodesk.Revit.DB.ElementID&lt;/span&gt; object &lt;span class="pre"&gt;at...&lt;/span&gt;&lt;/tt&gt;) is all about in the session transcript above.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-3307172586873296161?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/3307172586873296161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/08/deleting-bunch-of-elements-by-elementid.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/3307172586873296161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/3307172586873296161'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/08/deleting-bunch-of-elements-by-elementid.html' title='Deleting a bunch of Elements By ElementId in RevitPythonShell'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-1802818199257956738</id><published>2010-07-15T11:50:00.001+02:00</published><updated>2010-07-15T12:15:38.451+02:00</updated><title type='text'>New release of RevitPythonShell for x64 and Revit 2011 only</title><content type='html'>&lt;p&gt;I upgraded my development machine a couple of weeks ago to Windows 7 64-bit. At the same time I migrated all my Revit Addin projects to Autodesk Revit 2011.  This includes RevitPythonShell. I finally got round to building a new installer using the RevitAddInUtility. This was as good a project as any to try out building x64 applications and installers for Revit 2011.&lt;/p&gt;
&lt;p&gt;Most of the port was done with the help of code I recieved from Jason Schaeffer (joespiff) via the &lt;a class="reference external" href="http://groups.google.com/group/revitpythonshell"&gt;RevitPythonShell google group&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I ran into some snares:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Visual Studio 2010 has some restrictions with x64 managed applications&lt;ul&gt;
&lt;li&gt;The Designer will not show your forms unless you set the build platform to &amp;quot;Any CPU&amp;quot; and rebuild.&lt;/li&gt;
&lt;li&gt;The Setup projects bundle the wrong &amp;quot;InstallUtilLib.dll&amp;quot; shim when building x64 .msi packages&lt;ul&gt;
&lt;li&gt;this has to be manually patched with orca (see &lt;a class="reference external" href="http://stackoverflow.com/questions/3253796/how-to-modify-contents-replace-a-binary-of-an-msi-file-as-a-post-build-step"&gt;my question on stackoverflow.com&lt;/a&gt; for current status on how to do this automatically)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Windows 7 doesn't like it when programs modify stuff in the &amp;quot;Program Files&amp;quot; folder, so I moved the &lt;tt class="docutils literal"&gt;RevitPythonShell.xml&lt;/tt&gt; file to the AppData folder.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-1802818199257956738?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/1802818199257956738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/07/new-release-of-revitpythonshell-for-x64_5362.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/1802818199257956738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/1802818199257956738'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/07/new-release-of-revitpythonshell-for-x64_5362.html' title='New release of RevitPythonShell for x64 and Revit 2011 only'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-5649592027308428875</id><published>2010-06-09T10:22:00.001+02:00</published><updated>2010-06-09T10:25:06.815+02:00</updated><title type='text'>My .vimrc</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: Arial; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-size: 13px;"&gt;This is another post for my future self: At the time of writing, my .vimrc looks like this:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;
" --------------------------------------------------------------------------------
" call system vimrc
" --------------------------------------------------------------------------------
source $VIM/_vimrc

" --------------------------------------------------------------------------------
" startup
" --------------------------------------------------------------------------------
autocmd GUIEnter * simalt ~X    " maximize window

" --------------------------------------------------------------------------------
" opening files
" --------------------------------------------------------------------------------

" change working directory to path of file
autocmd BufEnter * lcd %:p:h    

" reformat xml files (pretty print)
autocmd FileType xml exe ":silent 1,$!xmllint --format --encode UTF-8 --recover - 2&amp;gt;/dev/null"

" --------------------------------------------------------------------------------
" saving files
" --------------------------------------------------------------------------------
set backupdir=./_Backup,$TEMP,.

" --------------------------------------------------------------------------------
" searching
" --------------------------------------------------------------------------------
set hlsearch        " highlight matches to search pattern
set incsearch        " incremental search
set smartcase       " case sensitive if search string contains uppercase letters
set ignorecase        " case insensitive searching

" --------------------------------------------------------------------------------
" configure editor with tabs and nice stuff...
" --------------------------------------------------------------------------------
set expandtab           " enter spaces when tab is pressed
set textwidth=0         " do not break lines when line length increases
set tabstop=4            " use 4 spaces to represent tab
set softtabstop=4
set shiftwidth=4        " number of spaces to use for auto indent
set autoindent          " copy indent from current line when starting a new line

" make backspaces more powerfull
set backspace=indent,eol,start 

set ruler               " show line and column number


" --------------------------------------------------------------------------------
" encoding
" --------------------------------------------------------------------------------
set encoding=utf-8
"set printencoding=utf-8

" --------------------------------------------------------------------------------
" keyboard mappings
" --------------------------------------------------------------------------------
set langmap=¨]
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Future Daren, you can find the location of the &lt;i&gt;.vimrc&lt;/i&gt; by editing the file &lt;i&gt;$MYVIMRC&lt;/i&gt; in vim itself! Unless it hasn't been created yet (&lt;i&gt;$MYVIMRC&lt;/i&gt; will then point to the system-wide version). In Windows, just plop a &lt;i&gt;_vimrc&lt;/i&gt; file in your &lt;i&gt;%userprofile%&lt;/i&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-5649592027308428875?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/5649592027308428875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/06/my-vimrc.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/5649592027308428875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/5649592027308428875'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/06/my-vimrc.html' title='My .vimrc'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-139314361528380419</id><published>2010-05-12T10:09:00.000+02:00</published><updated>2010-05-12T10:09:37.014+02:00</updated><title type='text'>Google Charts: AnnotatedTimeline</title><content type='html'>Note to future self: The &lt;a href="http://code.google.com/apis/visualization/documentation/gallery/annotatedtimeline.html"&gt;Google Charts visualization "AnnotatedTimeline"&lt;/a&gt; displays inside a div element. As per documentation, you need to provide height and width of the div element. If you don't (or specify a size too small), the script goes into an infinite loop - I guess it is trying to scale to fit inside the div, but I didn't feel like debugging squashed code...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-139314361528380419?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/139314361528380419/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/05/google-charts-annotatedtimeline.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/139314361528380419'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/139314361528380419'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/05/google-charts-annotatedtimeline.html' title='Google Charts: AnnotatedTimeline'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-4158673687587787886</id><published>2010-04-28T12:13:00.000+02:00</published><updated>2010-04-28T12:13:23.316+02:00</updated><title type='text'>CakePHP and Umlauts (utf-8)</title><content type='html'>I spent the last couple of weeks writing PHP. Not my favorite language, but it does get the job done. I won't bitch about PHP here, since that would be snobbery.&lt;br /&gt;
&lt;br /&gt;
What eases the pain a lot is the CakePHP framework. Except, I couldn't get Umlauts to work. Umlauts are special characters, like a, o and u, but with two dots on them: ä, ö, ü.&lt;br /&gt;
&lt;br /&gt;
I found the solution on this page:&amp;nbsp;&lt;a href="http://www.missingfeatures.com/2008/10/23/using-utf8-in-your-cakephp-app/"&gt;http://www.missingfeatures.com/2008/10/23/using-utf8-in-your-cakephp-app/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Not only must you tell your browser that you are using UTF-8, but you must also tell the database connection to use utf-8. Check the &lt;i&gt;database.php&lt;/i&gt; file in your &lt;i&gt;app/config&lt;/i&gt;&amp;nbsp;directory and add &lt;i&gt;'encoding' =&amp;gt; 'utf8'&lt;/i&gt;&amp;nbsp;to the end of the database configuration.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-4158673687587787886?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/4158673687587787886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/04/cakephp-and-umlauts-utf-8.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/4158673687587787886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/4158673687587787886'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/04/cakephp-and-umlauts-utf-8.html' title='CakePHP and Umlauts (utf-8)'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-4429668832152516391</id><published>2010-04-14T17:01:00.000+02:00</published><updated>2010-04-14T17:01:44.598+02:00</updated><title type='text'>Wiki syntax for UML diagrams</title><content type='html'>Yay! I have just implemented my very first &lt;a href="http://trac.edgewall.org/wiki/WikiStart"&gt;Trac&lt;/a&gt; &lt;a href="https://trac-hacks.org/wiki"&gt;Hack&lt;/a&gt;: &lt;a href="https://trac-hacks.org/wiki/YumlPreprocessorMacro"&gt;YumlPreprocessorMacro&lt;/a&gt;&amp;nbsp;for integrating &lt;a href="http://yuml.me/"&gt;yuml.me&lt;/a&gt; diagrams into the trac wiki.&lt;br /&gt;
&lt;br /&gt;
I have come to depend on using Trac as a bug tracking and documentation tool. I really like using wikis for documentation. I like being able to create links quickly. I like being able to search the documentation in a webby way. I absolutely hate using MS Word for technical documentation.&lt;br /&gt;
&lt;br /&gt;
Often, you want to add little UML sketches to your docs. The workflow normally goes like this:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Open your UML editor of choice&lt;/li&gt;
&lt;li&gt;Create UML diagram&lt;/li&gt;
&lt;li&gt;Export as image&lt;/li&gt;
&lt;li&gt;Include in documentation&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;Notice how that can be a little disruptive for just a sketch? Most UML tools want you to go &lt;a href="http://en.wikipedia.org/wiki/Big_Design_Up_Front"&gt;BDUF&lt;/a&gt;. They want you to create a whole model of everything, when all you really want to do is a little use case. I like the Violet UML Editor precisely because it lets me sketch. But &lt;a href="http://yuml.me/"&gt;yuml.me&lt;/a&gt; really changes the whole game!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-4429668832152516391?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/4429668832152516391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/04/wiki-syntax-for-uml-diagrams.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/4429668832152516391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/4429668832152516391'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/04/wiki-syntax-for-uml-diagrams.html' title='Wiki syntax for UML diagrams'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-5116543125676317186</id><published>2010-03-23T16:14:00.000+01:00</published><updated>2010-03-23T16:14:46.166+01:00</updated><title type='text'>Adding canned scripts to the Revit RibbonPanel</title><content type='html'>I feal really smug about myself today! I finally figured out how to add&lt;br /&gt;
shortcuts to the canned python scripts defined in &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;RevitPythonShell.xml&lt;/span&gt; to the&lt;br /&gt;
Revit RibbonPanel. I'd like to share some of the fancy magic that went into &lt;a href="http://code.google.com/p/revitpythonshell/source/detail?r=65"&gt;r65&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://code.google.com/p/revitpythonshell/"&gt;RevitPythonShell&lt;/a&gt; lets you define a list of named scripts in the&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt; RevitPythonShell.xml&lt;/span&gt; file. An exerpt from my personal file looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;  &amp;lt;Commands&amp;gt;
    &amp;lt;!-- a list of preconfigured commands --&amp;gt;
    &amp;lt;Command name="dumpdpvfolder" src="C:\RevitPythonShell\Commands\dpvdumpfolder.py"/&amp;gt;
    &amp;lt;Command name="read model" src="C:\RevitPythonShell\Commands\readmodel.py"/&amp;gt;
    &amp;lt;Command name="Report" src="C:\RevitPythonShell\Commands\report.py"/&amp;gt;
    &amp;lt;Command name="View Model" src="C:\RevitPythonShell\Commands\viewmodel.py"/&amp;gt;
  &amp;lt;/Commands&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
These are commands I use all the time during development of the&lt;br /&gt;
&lt;a href="http://www.keoto.net/?page_id=379"&gt; DesignPerformanceViewer&lt;/a&gt; (&lt;a href="http://www.gt.arch.ethz.ch/research/DPV_EN"&gt;DPV&lt;/a&gt;). I use these commands to test parts of the &lt;a href="http://www.gt.arch.ethz.ch/research/DPV"&gt;DPV&lt;/a&gt;, run&lt;br /&gt;
automated tests on lots of input projects etc.&lt;br /&gt;
&lt;br /&gt;
So far, these commands where only displayed in a toolbar above the interactive&lt;br /&gt;
shell. On the RibbonPanel provided by Autodesk Revit Architecture 2010 only a&lt;br /&gt;
single button was displayed: &lt;i&gt;Open Python Shell&lt;/i&gt;. The main reason being: To add&lt;br /&gt;
an item to the RibbonPanel, you have to provide a path to an assembly and the&lt;br /&gt;
name of a type inside that assembly implementing &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;IExternalCommand&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
In the case of RevitPythonShell, we can't specify such an assembly. There is none. &lt;br /&gt;
And we can't use a generic type as the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;IExternalCommand&lt;/span&gt; and load the python script&lt;br /&gt;
in the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Execute()&lt;/span&gt; method either, since the arguments to &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Execute&lt;/span&gt; don't contain any hints as&lt;br /&gt;
to which button was clicked!&lt;br /&gt;
&lt;br /&gt;
This is where dynamic assemblies and &lt;a href="http://msdn.microsoft.com/en-us/library/system.reflection.emit.aspx"&gt;Reflecion.Emit&lt;/a&gt; enters the stage: When RevitPythonShell&lt;br /&gt;
starts up (&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;IExternalCommand.OnStartup&lt;/span&gt;), the list of canned commands is read and a dynamic assembly&lt;br /&gt;
is created to hold a dynamically created class for each canned command defined in &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;RevitPythonShell.xml&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
This is done with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Reflection.Emit&lt;/span&gt; in the method &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;RevitPythonShellApplication.CreateCommandLoaderAssembly()&lt;/span&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;        /// &amp;lt;summary&amp;gt;
        /// Creates a dynamic assembly that contains types for starting the canned commands.
        /// &amp;lt;/summary&amp;gt;
        private static void CreateCommandLoaderAssembly()
        {
            var assemblyName = new AssemblyName {Name = "CommandLoaderAssembly", Version = new Version(1, 0, 0, 0)};
            var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
            var moduleBuilder = assemblyBuilder.DefineDynamicModule("CommandLoaderModule", "CommandLoaderAssembly.dll");

            foreach (var command in GetCommands())
            {
                var typebuilder = moduleBuilder.DefineType("Command" + command.Index,
                                                        TypeAttributes.Class | TypeAttributes.Public,
                                                        typeof(CommandLoaderBase));

                var ci = typeof(CommandLoaderBase).GetConstructor(new[] { typeof(string) });

                var constructorBuilder = typebuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[0]);
                var gen = constructorBuilder.GetILGenerator();
                gen.Emit(OpCodes.Ldarg_0);                // Load "this" onto eval stack
                gen.Emit(OpCodes.Ldstr, command.Source);  // Load the path to the command as a string onto stack
                gen.Emit(OpCodes.Call, ci);               // call base constructor (consumes "this" and the string)
                gen.Emit(OpCodes.Nop);                    // Fill some space - this is how it is generated for equivalent C# code
                gen.Emit(OpCodes.Nop);
                gen.Emit(OpCodes.Nop);
                gen.Emit(OpCodes.Ret);                    // return from constructor
                typebuilder.CreateType();
            }
            assemblyBuilder.Save("CommandLoaderAssembly.dll");            
        }
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Now, this is the first time I have ever emitted IL in my life. Naturally, I wanted to get as much done in C# as possible, so the types&lt;br /&gt;
generated all inherit &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;CommandLoaderBase&lt;/span&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;    /// &amp;lt;summary&amp;gt;
    /// Starts up a ScriptOutput window for a given canned command.
    /// 
    /// It is expected that this will be inherited by dynamic types that have the field
    /// _scriptSource set to point to a python file that will be executed in the constructor.
    /// &amp;lt;/summary&amp;gt;
    public abstract class CommandLoaderBase: IExternalCommand
    {
        protected string _scriptSource = "";

        public CommandLoaderBase(string scriptSource)
        {
            _scriptSource = scriptSource;
        }

        public IExternalCommand.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            var executor = new ScriptExecutor(commandData, message, elements);

            string source;
            using (var reader = File.OpenText(_scriptSource))
            {
                source = reader.ReadToEnd();
            }

            var result = executor.ExecuteScript(source);
            message = executor.Message;
            switch (result)
            {
                case (int)IExternalCommand.Result.Succeeded:
                    return IExternalCommand.Result.Succeeded;
                case (int)IExternalCommand.Result.Cancelled:
                    return IExternalCommand.Result.Cancelled;
                case (int)IExternalCommand.Result.Failed:
                    return IExternalCommand.Result.Failed;
                default:
                    return IExternalCommand.Result.Succeeded;
            }
        }
    }
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
This base class has a constructor that accepts the path to a python script and&lt;br /&gt;
creates a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ScriptExecutor&lt;/span&gt;&amp;nbsp;(check &lt;a href="http://code.google.com/p/revitpythonshell/source/browse/trunk/RevitPythonShell/ScriptExecutor.cs"&gt;RevitPythonShell source code&lt;/a&gt;) to execute that script in its implementation of&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt; IExternalCommand.Execute()&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
And now the Reflection/IL stuff starts to make sense: Create a type inheriting from &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;CommandLoaderBase&lt;/span&gt;, adding a parameterless constructor (called by&lt;br /&gt;
Revit) which in turn calls the base constructor with the path to the script. The resulting IL looks something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;    .class public auto ansi Command0
        extends [RevitPythonShell]RevitPythonShell.CommandLoaderBase
    {
        .method public specialname rtspecialname instance void .ctor() cil managed
        {
            .maxstack 2
            L_0000: ldarg.0 
            L_0001: ldstr "C:\\RevitPythonShell\\Commands\\dpvdumpfolder.py"
            L_0006: call instance void [RevitPythonShell]RevitPythonShell.CommandLoaderBase::.ctor(string)
            L_000b: nop 
            L_000c: nop 
            L_000d: nop 
            L_000e: ret 
        }

    }
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
With "Command0" being the name of the type to instantiate for the first canned script in &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;RevitPythonShell.xml&lt;/span&gt;. The C# equivalent looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;    public class Command0 : CommandLoaderBase
    {
        // Methods
        public Command0() : base(@"C:\RevitPythonShell\Commands\dpvdumpfolder.py")
        {
        }
    }
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
I used &lt;a href="http://www.red-gate.com/products/reflector/"&gt;Red Gate's .NET Reflector&lt;/a&gt; to disassemble the resulting assembly and also as a hint on how to write the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Reflection.Emit&lt;/span&gt; stuff (created a dummy subclass of &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;CommandLoaderBase&lt;/span&gt; with the desired constructor, compiled and then disassembled in Reflector).&lt;br /&gt;
&lt;br /&gt;
Now I need to add a nice interface to manage the canned commands - any ideas?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-5116543125676317186?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/5116543125676317186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/03/adding-canned-scripts-to-revit.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/5116543125676317186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/5116543125676317186'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/03/adding-canned-scripts-to-revit.html' title='Adding canned scripts to the Revit RibbonPanel'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-4203203710461048182</id><published>2010-03-10T16:49:00.003+01:00</published><updated>2010-03-10T16:56:26.332+01:00</updated><title type='text'>Using RevitPythonShell to dynamically load plugins for debugging</title><content type='html'>Ever since I read Jeremy Tammiks blog post &lt;a href="http://thebuildingcoder.typepad.com/blog/2010/03/reload-an-addin-to-debug.html"&gt;Reload an Add-In to Debug&lt;/a&gt;, where he&lt;br /&gt;
describes about John Morse's technique for dynamically loading plugins without&lt;br /&gt;
having to restart Revit, I have been itching to get this working in&lt;br /&gt;
&lt;a href="http://code.google.com/p/revitpythonshell/"&gt;RevitPythonShell&lt;/a&gt;!&lt;br /&gt;
&lt;br /&gt;
Finally, with &lt;a href="http://revitpythonshell.googlecode.com/files/Setup_RAC32_r55.msi"&gt;revision 55&lt;/a&gt; and the &lt;a href="http://code.google.com/p/revitpythonshell/wiki/FeaturedScriptLoadplugin"&gt;loadplugin script&lt;/a&gt;, I can rapidly iterate&lt;br /&gt;
working on my C# projects - no more waiting for Autodesk Revit to restart after&lt;br /&gt;
fixing a small mistake!&lt;br /&gt;
&lt;br /&gt;
Here is a little sampe session from the &lt;a href="http://code.google.com/p/revitpythonshell/wiki/FeaturedScriptLoadplugin"&gt;project page&lt;/a&gt;:&lt;br /&gt;
&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
&amp;gt;&amp;gt;&amp;gt;import loadplugin
&amp;gt;&amp;gt;&amp;gt;# use actual path here... (if you don't already have RvtMgdDbg.dll installed, you probably want to go and do so 
&amp;gt;&amp;gt;&amp;gt;# right now - check ADN!)
&amp;gt;&amp;gt;&amp;gt;assembly = loadplugin.loadAssembly(r'C:\...\Visual Studio 2008\Projects\RvtMgdDbg\bin\RvtMgdDbg.dll')
&amp;gt;&amp;gt;&amp;gt;# result is an assembly object
&amp;gt;&amp;gt;&amp;gt;assembly

&amp;lt;Assembly RvtMgdDbg, Version=1.0.3671.26458, Culture=neutral, PublicKeyToken=null&amp;gt;

&amp;gt;&amp;gt;&amp;gt;# pretty cool: IronPython lets you use the assembly like a namespace
&amp;gt;&amp;gt;&amp;gt;# also note the use of the special predefined variables for executing plugins!
&amp;gt;&amp;gt;&amp;gt;assembly.RvtMgdDbg.CmdSnoopDb().Execute(__commandData__, __message__, __elements__)

(&amp;lt;Autodesk.Revit.IExternalCommand+Result object at 0x000000000000002D [Succeeded]&amp;gt;, '')
&amp;gt;&amp;gt;&amp;gt;

&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
So how dows it work? Basically, you load an assembly as a byte array and then&lt;br /&gt;
use &lt;a href="http://msdn.microsoft.com/en-us/library/aa329934(v=VS.71).aspx"&gt;Assembly.Load&lt;/a&gt; to load the assembly from the byte array. Dynamically loading&lt;br /&gt;
assemblies this way does not lock them on the hard disk, allowing Visual Studio&lt;br /&gt;
to overwrite the DLLs at build time.&lt;br /&gt;
&lt;br /&gt;
I suggest you write a test script for your plugin, that you can then save as a&lt;br /&gt;
canned command in RevitPythonShell, that loads it via &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;loadplugin.loadAssembly&lt;/span&gt; and&lt;br /&gt;
does some exercising: Instantiate some types, execute &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;IExternalCommand&lt;/span&gt; instances etc.&lt;br /&gt;
&lt;br /&gt;
To make interaction with plugins easier, RevitPythonShell now supports some &lt;a href="http://code.google.com/p/revitpythonshell/wiki/PredefinedVariables"&gt;predefined&amp;nbsp;variables&lt;/a&gt;, that give you more access to the context in which the plugin itself was loaded.&lt;br /&gt;
This lets you simulate the user clicking on PushButtons in the Ribbon.&lt;br /&gt;
&lt;br /&gt;
Also, I have included a fork of the &lt;a href="http://www.codeproject.com/KB/edit/irontextbox2.aspx"&gt;IronPythonTextBox&lt;/a&gt; control, to make plain interactive&lt;br /&gt;
use of RevitPythonShell smoother.&lt;br /&gt;
&lt;br /&gt;
Please let me know, if this is of any use to you. Also, I would really&amp;nbsp;appreciate&amp;nbsp;some help, especially in getting the system more user friendly (e.g. script repository etc.).&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-4203203710461048182?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/4203203710461048182/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/03/using-revitpythonshell-to-dynamically.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/4203203710461048182'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/4203203710461048182'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/03/using-revitpythonshell-to-dynamically.html' title='Using RevitPythonShell to dynamically load plugins for debugging'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-1753055774118800573</id><published>2010-02-25T15:57:00.000+01:00</published><updated>2010-02-25T15:57:52.489+01:00</updated><title type='text'>Extracting music from Mac formatted iPod in Windows XP</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: Arial; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-size: 13px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;I used these tools to extract the music from my iPod (Mac formatted) under windows:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://hem.bredband.net/catacombae/hfsx.html"&gt;HFSExplorer&lt;/a&gt; (0.21)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.mp3tag.de/en/"&gt;Mp3tag &lt;/a&gt;v2.45a&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;HFSExplorer lets you extract data from an HFS file system hooked up to your PC. In this case my iPod. After loading the filesystem from a device (see file menue), navigate to the folder /iPod_Control/Music and extract it to your PCs filesystem, e.g. your Desktop.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;The music shows up as a lot of funny folders and files (F00, F01, ...). This is where Mp3tag comes in: One of the functions of this tool is to read the meta information from your music files and create a directory structure from them, with proper file names, folder names for the albums etc. Sweet!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-1753055774118800573?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/1753055774118800573/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/02/extracting-music-from-mac-formatted.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/1753055774118800573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/1753055774118800573'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/02/extracting-music-from-mac-formatted.html' title='Extracting music from Mac formatted iPod in Windows XP'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-5843231346409997482</id><published>2010-02-25T15:38:00.000+01:00</published><updated>2010-02-25T15:38:28.123+01:00</updated><title type='text'>How to create a 3D wireframe with X3D</title><content type='html'>All I wanted to do was &lt;a href="http://stackoverflow.com/questions/1345485/how-to-quickly-easy-to-script-preview-3d-vectors-lines"&gt;display some lines in a 3D coordinate system&lt;/a&gt; to make sure everything was as it should be. That can't be hard, can it?&lt;br /&gt;
&lt;br /&gt;
Well, it seems it &lt;i&gt;is&lt;/i&gt; hard. At least, it's hard to figure out &lt;i&gt;how&lt;/i&gt; to do it, because there aren't that many tools that will show you a 3D scene from a file you generate by hand/script.&lt;br /&gt;
&lt;br /&gt;
I quickly found out about the VRML/X3D stuff. It looked ancient. Rotten. Neglected. All sad. A bunch of tutorials made me sure that I &lt;i&gt;didn't&lt;/i&gt;&amp;nbsp;want to go that route: None of the tutorials talked about how to display a line in a 3D scene. Instead, it seemed VRML was all about showing shapes: Boxes, cylinders, spheres and stuff like that.&lt;br /&gt;
&lt;br /&gt;
Ugh! Ok. I guess I could just draw really thin boxes and call them lines. But it just gets worse: All shapes are defined in distinces from an origin - so your sphere has a radius. That's it. It is stuck at [0, 0, 0]. But you then &lt;i&gt;translate&lt;/i&gt;&amp;nbsp;your shape to where you want it to go. Move it around, rotate it. Etc.&lt;br /&gt;
&lt;br /&gt;
Argh! I had all these nice 3D coordinates for my lines ready. But the docs said I would have to transform them all into this complicated scheme. Which, I am sure makes a lot of sense for 3D modelling. It's just for simple wireframe output that it seems a little bloated.&lt;br /&gt;
&lt;br /&gt;
Well, It's not really that bad: X3D has an element called &lt;i&gt;LineSet&lt;/i&gt;&amp;nbsp;that lets you specify... lines! You just write a list of 3D points to the file and off you go!&lt;br /&gt;
&lt;br /&gt;
So, if you are the next person to try creating a simple wireframe with X3D, you might want to have a look at this stub file:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN"
  "http://www.web3d.org/specifications/x3d-3.0.dtd"&amp;gt;
&amp;lt;X3D profile="Immersive" &amp;gt;
  &amp;lt;Scene&amp;gt;

    &amp;lt;Transform&amp;gt;
      &amp;lt;Shape&amp;gt;
        &amp;lt;LineSet vertexCount="5"&amp;gt;
            &amp;lt;Coordinate point="1 0 0
                               1 1 0
                               0 1 0
                               0 0 0
                               1 0 0"
                               /&amp;gt;
        &amp;lt;/LineSet&amp;gt;
    &amp;lt;/Shape&amp;gt;
    &amp;lt;Shape&amp;gt;
        &amp;lt;LineSet vertexCount="5"&amp;gt;
            &amp;lt;Coordinate point="1 0 1
                               1 1 1
                               0 1 1
                               0 0 1
                               1 0 1"
                               /&amp;gt;
        &amp;lt;/LineSet&amp;gt;
    &amp;lt;/Shape&amp;gt;
    &amp;lt;Shape&amp;gt;
        &amp;lt;LineSet vertexCount="5"&amp;gt;
            &amp;lt;Coordinate point="0 0 1
                               1 0 1
                               1 0 0
                               0 0 0
                               0 0 1"
                               /&amp;gt;
        &amp;lt;/LineSet&amp;gt;
    &amp;lt;/Shape&amp;gt;
    &amp;lt;Shape&amp;gt;
        &amp;lt;LineSet vertexCount="5"&amp;gt;
            &amp;lt;Coordinate point="0 1 1
                               1 1 1
                               1 1 0
                               0 1 0
                               0 1 1"
                               /&amp;gt;
        &amp;lt;/LineSet&amp;gt;
      &amp;lt;/Shape&amp;gt;
    &amp;lt;/Transform&amp;gt;
  &amp;lt;/Scene&amp;gt;
&amp;lt;/X3D&amp;gt;

&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
This will create a simple 1x1x1 cube. You can view this with an X3D browser. I used &lt;a href="http://freewrl.sourceforge.net/"&gt;FreeWRL&lt;/a&gt;. It is supposed to be only for OSX and Linux, but they do have a windows binary that sort of works. At least for &lt;i&gt;my&lt;/i&gt;&amp;nbsp;purposes it is really enough. The other browsers out there (ones that also act as web browser plugins) seem scammy. They let you download a "test" version. What does that meen? Is this a trial version? Do I have to buy it? Where? How much?&lt;br /&gt;
&lt;br /&gt;
So, here is a screenshot of FreeWRL rendering the X3D file above:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_rrtfawcDo4o/S4aK3QLvsuI/AAAAAAAAAAM/mdGrHcqfszg/s1600-h/FreeWRL_simplecube.Png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_rrtfawcDo4o/S4aK3QLvsuI/AAAAAAAAAAM/mdGrHcqfszg/s320/FreeWRL_simplecube.Png" /&gt;&lt;/a&gt;&lt;/div&gt;I rotated the cube a bit (this is the nice thing about having a dedicated browser - try writing your own!) to make it more recognizable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-5843231346409997482?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/5843231346409997482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/02/how-to-create-3d-wireframe-with-x3d.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/5843231346409997482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/5843231346409997482'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/02/how-to-create-3d-wireframe-with-x3d.html' title='How to create a 3D wireframe with X3D'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_rrtfawcDo4o/S4aK3QLvsuI/AAAAAAAAAAM/mdGrHcqfszg/s72-c/FreeWRL_simplecube.Png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-5939248703436253436</id><published>2010-02-05T11:55:00.000+01:00</published><updated>2010-02-05T11:55:20.247+01:00</updated><title type='text'>Where are all the posts I promised?</title><content type='html'>Why oh why have I not delivered on my promise to post neat stuff you can do with &lt;a href="http://code.google.com/p/revitpythonshell/"&gt;RevitPythonShell&lt;/a&gt;? Well, what exactly would you want to do with it? I use this tool to scratch an itch - automate a plugin I am writing. I mainly use the Interactive button and type away at the prompt. I also have some canned scripts I like to use, but I'm not sure if posting them here would make a lot of sense: They are very specific to the plugin. But I'll show a little bit, just for the curious among you:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;Python 2.5.0 () on cli
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
&amp;gt;&amp;gt;&amp;gt; apps = [a for a in __revit__.LoadedApplications if 'DpvApplication' in str(a)]
&amp;gt;&amp;gt;&amp;gt; dpv = apps[0]
&amp;gt;&amp;gt;&amp;gt; dir(dpv)
['ActiveDocument', 'Calculators', 'GetHistory', 'OnShutdown', 'OnStartup', 'Result', 'TakeSnapshot', '__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']
&amp;gt;&amp;gt;&amp;gt; dpv.TakeSnapshot()
&amp;gt;&amp;gt;&amp;gt; snapshot = dpv.GetHistory(dpv.ActiveDocument).CurrentSnapshot
&amp;gt;&amp;gt;&amp;gt; for room in snapshot.Rooms:
...    print room.Area, room.Name
... 
163.14989375 Raum 1
&amp;gt;&amp;gt;&amp;gt; 

&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Right after the banner, I create a reference to my plugin. This uses the &lt;i&gt;LoadedApplications&lt;/i&gt;&amp;nbsp;collection on &lt;i&gt;Autodesk.Revit.Application&lt;/i&gt;. As you can see, I then proceed to exercise the plugin, calling its methods (&lt;i&gt;TakeSnapshot&lt;/i&gt;, &lt;i&gt;GetHistory&lt;/i&gt;, &lt;i&gt;ActiveDocument&lt;/i&gt;) etc. You can call any public methods defined in your plugin this way!&lt;br /&gt;
&lt;br /&gt;
But working in the interactive shell for some period has shown some of its weaknesses. I'm busy trying to fix that, but this might still take a while - the last couple of revisions have gone in that direction (but there is no new release yet).&lt;br /&gt;
&lt;br /&gt;
Since this is a tool to make exploring your (C#) plugins easier, it makes sense to customize it a bit. I have configured&amp;nbsp;&lt;i&gt;RevitPythonShell.xml&lt;/i&gt; like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;RevitPythonShell&amp;gt;
  &amp;lt;SearchPaths&amp;gt;
    &amp;lt;!-- a list of paths to add to the engines search path --&amp;gt;
    &amp;lt;SearchPath name="C:\Python25\Lib"/&amp;gt;
    &amp;lt;SearchPath name="C:\RevitPythonShell"/&amp;gt;
  &amp;lt;/SearchPaths&amp;gt;
  &amp;lt;Commands&amp;gt;
    &amp;lt;!-- a list of preconfigured commands --&amp;gt;
    &amp;lt;Command name="dumpdpvfolder" src="C:\RevitPythonShell\Commands\dpvdumpfolder.py"/&amp;gt;
    &amp;lt;Command name="read model" src="C:\RevitPythonShell\Commands\readmodel.py"/&amp;gt;
    &amp;lt;Command name="Report" src="C:\RevitPythonShell\Commands\report.py"/&amp;gt;
    &amp;lt;Command name="Interactive" src="C:\RevitPythonShell\Commands\interactive.py"/&amp;gt;
  &amp;lt;/Commands&amp;gt;
  &amp;lt;DefaultScript&amp;gt;&amp;lt;![CDATA[
# type in a python script to run here and click "Execute"
# you can access the Autodesk.Revit.Application object with the variable __revit__
# the default script (shown below) opens up an interactive interpreter

import code
code.interact(None, None,
  {
    '__name__' : '__console__',
    '__doc__'  : None,
    '__revit__': __revit__
  })]]&amp;gt;&amp;lt;/DefaultScript&amp;gt;
&amp;lt;/RevitPythonShell&amp;gt;

&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Notice the Commands section: These are shortcuts to stuff I execute often. Conserved scripts that use the technique explained above to exercise the DesignPerformanceViewer plugin.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-5939248703436253436?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/5939248703436253436/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/02/where-are-all-posts-i-promised.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/5939248703436253436'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/5939248703436253436'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/02/where-are-all-posts-i-promised.html' title='Where are all the posts I promised?'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-1386177235974605289</id><published>2010-01-27T14:36:00.000+01:00</published><updated>2010-01-27T14:36:10.342+01:00</updated><title type='text'>Name your GUIDs</title><content type='html'>Here is a little idea that came to me while waiting for my computer to become responsive again (don't ask):&lt;br /&gt;
&lt;br /&gt;
Wouldn't it be really cool, if there was a name generator for GUIDs? You could submit a GUID and claim a name. That way, people could talk about GUIDs on the phone:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;i&gt;Guy on phone:&lt;/i&gt;&amp;nbsp;I'm having problems with foobaz&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Supporter: &lt;/i&gt;Oh, you want to check the registry for the GUID "PurpleRain"&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Guy on phone: &lt;/i&gt;(checks up GUID via webservice)&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;I'll have to think some more about this... You'd want to make sure the names are easy to pronounce, easy to type and hard to get wrong. I'm sure someone has done similar stuff before.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-1386177235974605289?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/1386177235974605289/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2010/01/name-your-guids.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/1386177235974605289'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/1386177235974605289'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2010/01/name-your-guids.html' title='Name your GUIDs'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-5317950725019660586</id><published>2009-12-23T13:08:00.001+01:00</published><updated>2010-01-05T16:22:41.604+01:00</updated><title type='text'>Adding your plugin to the [ExternalApplications] section of Revit.ini</title><content type='html'>For the installer for &lt;a href="http://revitpythonshell.googlecode.com/"&gt;RevitPythonShell&lt;/a&gt;, I need to programmatically add the plugin to the [ExternalApplications] section of Revit.ini. Instead of writing a one-off solution, I decided to create a little commandline tool that can be reused for my next project or even your project: &lt;a href="http://revitpythonshell.googlecode.com/files/addrevitplugin.exe"&gt;addrevitplugin.exe&lt;/a&gt;. You can &lt;a href="http://code.google.com/p/revitpythonshell/source/browse/trunk/addrevitplugin/addrevitplugin.au3"&gt;look at the source&lt;/a&gt; too!&lt;br /&gt;
The tool is written using &lt;a href="http://www.autoitscript.com/autoit3/index.shtml"&gt;AutoIt v3&lt;/a&gt;, a BASIC derivative with lots of useful functions for automating windows tasks. Expect to see some more samples of such scripts on this blog...&lt;br /&gt;
The commandline options to &lt;i&gt;addrevitplugin.exe&lt;/i&gt; are:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;i&gt;EAClassName&lt;/i&gt;: This corresponds to the key "EAClassName#" in the &lt;i&gt;Revit.ini&lt;/i&gt; file&lt;/li&gt;
&lt;li&gt;&lt;i&gt;EAAssembly&lt;/i&gt;: (optional) This corresponds to the key "EAAssembly#" in the &lt;i&gt;Revit.ini&lt;/i&gt; file and is the full path to the .NET assembly containing the plugin class.&lt;/li&gt;
&lt;/ul&gt;Using &lt;i&gt;addrevitplugin.exe&lt;/i&gt;, you can either add, update or delete a plugin entry in the "ExternalApplications" section. By specifying &lt;i&gt;EAClassName&lt;/i&gt; without &lt;i&gt;EAAssembly&lt;/i&gt;, the corresponding plugin is deleted from &lt;i&gt;Revit.ini&lt;/i&gt;. If &lt;i&gt;EAAssembly&lt;/i&gt; is provided, then the plugin is either added (if it was not yet installed) or updated with the assembly.&lt;br /&gt;
&lt;br /&gt;
I also use this tool in conjunction with &lt;a href="http://www.launchy.net/"&gt;Launchy&lt;/a&gt; to quickly switch between environments when developing Revit plugins:&amp;nbsp;Create a batch file for each location of your plugin (Debug, Release, Installed) with contents similar to:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;addrevitplugin.exe RevitPythonShell.RevitPythonShellApplication "C:\Projects\revitpythonshell\RevitPythonShell\bin\Debug\RevitPythonShell.dll"
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Make sure the second argument is enclosed in double quotes if it contains spaces. Create a separate file for each environment.&lt;br /&gt;
&lt;br /&gt;
I named the files &lt;i&gt;debug_RevitPythonShell.bat&lt;/i&gt;, &lt;i&gt;release_RevitPythonShell.bat&lt;/i&gt; and &lt;i&gt;installed_RevitPythonShell.bat&lt;/i&gt;. By saving these files in a directory scanned by Launchy, I can quickly switch between the environments before starting Autodesk Revit Architecture 2010.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Note:&lt;/b&gt;If you are not using Autodesk Revit Architecture 2010 on a 32bit system, you will want to &lt;a href="http://thebuildingcoder.typepad.com/blog/2009/02/revit-install-path-and-product-guids.html"&gt;change the GUID used to look up the install path&lt;/a&gt; in the script &lt;i&gt;addrevitplugin.au3&lt;/i&gt;. You will then need to recompile the script using &lt;i&gt;Aut2Exe.exe&lt;/i&gt;, which can be obtained from the Auto It website.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update&lt;/b&gt;: I have renamed &lt;i&gt;addrevitplugin.exe&lt;/i&gt; to &lt;a href="http://revitpythonshell.googlecode.com/files/rac32plugin.exe"&gt;rac32plugin.exe&lt;/a&gt; and &lt;a href="http://revitpythonshell.googlecode.com/files/rac64plugin.exe"&gt;rac64plugin.exe&lt;/a&gt; so that now a 32-bit and a 64-bit version comes precompiled. Also, the scripts have changed somewhat. Please check the project website.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-5317950725019660586?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/5317950725019660586/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2009/12/adding-your-plugin-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/5317950725019660586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/5317950725019660586'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2009/12/adding-your-plugin-to.html' title='Adding your plugin to the [ExternalApplications] section of Revit.ini'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-3662844916031571672</id><published>2009-12-18T14:36:00.005+01:00</published><updated>2009-12-18T15:03:40.976+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='revit'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Introducing RevitPythonShell</title><content type='html'>&lt;a href="http://revitpythonshell.googlecode.com/"&gt;RevitPythonShell&lt;/a&gt; is a little tool I built to make life in RevitAPI-land a little easier.&lt;br /&gt;
&lt;br /&gt;
When writing plugins for Autodesk Revit Architecture 2010, you have to restart Revit each time you create a new build and manually click your way to the plugins functionality. If you are not so sure about how a given method or property from the API works (or what values to expect when reading it), you will end up with a lot of these edit-compile-run cycles. I don't know how fast your machine is, but starting Revit on mine is not as snappy as I would like. Plus, you can't really experiment, can you?&lt;br /&gt;
&lt;br /&gt;
So, with &lt;a href="http://code.google.com/p/revitpythonshell/"&gt;RevitPythonShell&lt;/a&gt;, you can. It embeds &lt;a href="http://ironpython.net/"&gt;IronPython&lt;/a&gt;, a .NET port of the python language as a plugin. The main window provides a simple text editor that lets you write a script and execute it. The most useful script is probably this one:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;import code
code.interact(None, None, 
        {
            '__name__': '__console__', 
            '__doc__':None, 
            '__revit__': __revit__
        })

&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
This will open up an interactive interpreter loop (known as a &lt;a href="http://en.wikipedia.org/wiki/Read-eval-print_loop"&gt;REPL&lt;/a&gt;), that will let you explore the RevitAPI. And by &lt;i&gt;explore&lt;/i&gt;, I mean type a statement, hit enter, see the results, carry on. It doesn't get easier as this!&lt;br /&gt;
&lt;br /&gt;
The above script is actually saved as a "&lt;i&gt;canned command&lt;/i&gt;" - an button (in this case named "Interactive") in the toolbar above the &lt;a href="http://code.google.com/p/revitpythonshell/wiki/ScreenShots#The_(_-_Input)"&gt;main window&lt;/a&gt;. Canned commands like these are an ideal place to save scripts you have developed and found useful - a sort of mini-plugin-in-a-plugin architecture.&lt;br /&gt;
&lt;br /&gt;
The default script shown when you start the &lt;a href="http://code.google.com/p/revitpythonshell/"&gt;RevitPythonShell &lt;/a&gt;plugin is this one:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;
# type in a python script to run here...
try:
  # assumes the following file exists: C:\RevitPythonShell\current.py
  import current  
  reload(current)
  
  current.main(__revit__)
except:
  import traceback
  traceback.print_exc()
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
It imports the module &lt;i&gt;current.py&lt;/i&gt;&amp;nbsp;from the search path (normally C:\RevitPythonShell) which contains a script you are currently working on.&amp;nbsp;Clicking the button&amp;nbsp;&lt;i&gt;Execute&lt;/i&gt;&amp;nbsp;(or pressing&amp;nbsp;&lt;i&gt;CTRL+RETURN&lt;/i&gt;) will execute the contents of the main window, which will in turn import the module and run its &lt;i&gt;main()&lt;/i&gt;&amp;nbsp;method.&lt;br /&gt;
&lt;br /&gt;
Loading a script from the file system instead of typing it into the simple editor provided by RevitPythonShell is probably a good idea, since most editors make life a lot easier compared to the TextBox control used here - even &lt;i&gt;Notepad.exe&lt;/i&gt; would be preferable!&lt;br /&gt;
&lt;br /&gt;
Note the parameter &lt;i&gt;__revit__&lt;/i&gt;&amp;nbsp;passed into the main method: This is a reference to the &lt;i&gt;Autodesk.Revit.Application&lt;/i&gt;&amp;nbsp;API object used by plugins to gain access to Revit.&lt;br /&gt;
&lt;br /&gt;
I will be showing off some of the things you can do with &lt;a href="http://code.google.com/p/revitpythonshell/"&gt;RevitPythonShell &lt;/a&gt;in later posts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-3662844916031571672?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/3662844916031571672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2009/12/introducing-revitpythonshell.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/3662844916031571672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/3662844916031571672'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2009/12/introducing-revitpythonshell.html' title='Introducing RevitPythonShell'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-872710504615735069</id><published>2009-12-09T11:26:00.000+01:00</published><updated>2009-12-09T11:26:43.040+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='revit'/><title type='text'>Using C# extension methods for Revit Element Parameters</title><content type='html'>One of the places using C# extension methods shines is writing getters and setters for element parameters in Autodesk Revit Architecture 2010. Parameters are user defined meta data bound to either an instance or a type in Revit. Accessing these is a bit cumbersome:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;public IExternalCommand.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
    var document = commandData.Application.ActiveDocument;    
    
    Parameter parameter = document.ProjectInformation.get_Parameter("BuildingCategory");
    if (parameter != null)
    {                
        var buildingCategory = parameter.AsInteger();
        // do something with this information
    }        
}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Imagine typing all that code &lt;i&gt;every time you want to access your parameter in code&lt;/i&gt;! Of course you will wrap it up in a method, but wrapping it in an extension method allows for neat syntax:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;public static int GetBuildingCategory(this ProjectInfo self)
{
        
    Parameter parameter = self.get_Parameter("BuildingCategory");
    if (parameter != null)
    {
                
        return parameter.AsInteger();
    }        
    // you could also throw an exception here...
    return 0;
}

&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Now, you can access the property through the element itself, and it shows up in intellisense!&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;int buildingCategory = document.ProjectInformation.GetBuildingCategory();
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
In fact, I go a step further in my project, utilizing the &lt;a href="http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx"&gt;t4 templating engine &lt;/a&gt;to generate the parameter accessors as well as routines to bind them to the document from an XML file. But that will have to wait for another blog post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-872710504615735069?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/872710504615735069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2009/12/using-c-extension-methods-for-revit.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/872710504615735069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/872710504615735069'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2009/12/using-c-extension-methods-for-revit.html' title='Using C# extension methods for Revit Element Parameters'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-2550770741306758901</id><published>2009-12-03T08:32:00.003+01:00</published><updated>2009-12-09T11:27:23.942+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='revit'/><title type='text'>Using C# extension methods to extend plugin architectures</title><content type='html'>I've spent a lot of time recently writing a plugin for &lt;a href="http://usa.autodesk.com/adsk/servlet/pc/index?id=3781831&amp;amp;siteID=123112"&gt;Autodesk Revit Architecture 2010&lt;/a&gt;. Extending Revit involves writing managed code that implements a special interface (&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Autodesk.Revit.IExternalApplication&lt;/span&gt;) that gets called by the host application when special events occur - the application starts up, one of your toolbar buttons was clicked, a document was opened / closed / saved etc.&lt;br /&gt;
Access to the host is provided as a parameter to the methods defined in the interface. One of the main objects of interest for the work I'm doing is the &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Autodesk.Revit.Document&lt;/span&gt; class. This is my window into Revit documents, providing information about elements in the document.&lt;br /&gt;
The catch: You cannot change how these objects behave, since they are provided by the host. If &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Autodesk.Revit.Document&lt;/span&gt; is missing a &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Rooms&lt;/span&gt; property that lists all the rooms in the document, well, you are out of luck.&lt;br /&gt;
The traditional object oriented solution to this problem is&amp;nbsp;inheritance. You subclass the lacking class in question and add the desired functionality.&amp;nbsp;This will not work in a plugin situation. You have no control of how Revit instantiates its document object.&lt;br /&gt;
You could decorate the object with new functionality: Implement the &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Document&lt;/span&gt; interface (in this case you would have to &lt;a href="http://www.refactoring.com/catalog/extractInterface.html"&gt;extract the interface&lt;/a&gt; first) and delegate all invocations to a stashed away instance&amp;nbsp;received&amp;nbsp;via Revit. This can fly, but its pretty ugly to do by hand - you might want to generate this.&lt;br /&gt;
C# 3.0 comes with a new solution to this problem: &lt;a href="http://msdn.microsoft.com/en-us/library/bb383977.aspx"&gt;Extension Methods&lt;/a&gt;. Lets look at some code.&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// Provides some utility methods for working with Revit.Document objects.
/// &amp;lt;/summary&amp;gt;
public static class RevitDocumentExtensions
{
    /// &amp;lt;summary&amp;gt;
    /// Returns a list of all room objects in a Revit document.
    /// This excludes room
    /// &amp;lt;/summary&amp;gt;
    public static IEnumerable&amp;lt;Room&amp;gt; GetRooms(this Document document)
    {
        var roomElements = new List&amp;lt;Element&amp;gt;();
        var filterFactory = document.Application.Create.Filter;
        var filter = filterFactory.NewTypeFilter(typeof(Room));
            document.get_Elements(filter, roomElements);

        // filter the rooms so only the placed ones are returned.
        return roomElements.Cast&amp;lt;Room&amp;gt;().Where(r =&amp;gt; r.Location != null);
    }
}
&lt;/code&gt;&lt;/pre&gt;Given an &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Autodesk.Revit.Document&lt;/span&gt; object, &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;GetRooms&lt;/span&gt; can be called like so:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;var rooms = RevitDocumentExtensions.GetRooms(document);
&lt;/code&gt;&lt;/pre&gt;This is nothing new, hardly exciting, but works.&lt;br /&gt;
Did you notice the magic keyword this in the functions signature?&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;public static IEnumerable&amp;lt;Room&amp;gt; GetRooms(&lt;b&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;&lt;/b&gt; Document document)
&lt;/code&gt;&lt;/pre&gt;That's new. We are still talking static methods here, and that is all the .NET runtime ever sees, but the C# compiler will allow you to use this method syntactically as if it were defined in the &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Document &lt;/span&gt;class! So our usage chages to this:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;var rooms = document.GetRooms();
&lt;/code&gt;&lt;/pre&gt;Neat, huh? It looks as if we have subclassed &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Autodesk.Revit.Document&lt;/span&gt; and added a new instance method. Using this technique, a plugin API can be extended to better suit the needs of the plugin.&lt;br /&gt;
I will post more examples on how I used extension methods to augment Revit in my next post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-2550770741306758901?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/2550770741306758901/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2009/12/using-c-extension-methods-to-extend.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/2550770741306758901'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/2550770741306758901'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2009/12/using-c-extension-methods-to-extend.html' title='Using C# extension methods to extend plugin architectures'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9223352140090705474.post-9186208895323945423</id><published>2009-11-05T07:44:00.000+01:00</published><updated>2009-11-05T08:20:10.497+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='response'/><title type='text'>Response to "Bug tracking isn't a network-effect business"</title><content type='html'>Ok, so my first post is going to be a bit of a fanboy post. I've been a keen reader of Joel Spolkys blog since the aticle series "&lt;a href="http://www.joelonsoftware.com/articles/fog0000000009.html"&gt;Working on CityDesk&lt;/a&gt;". Its fun to read stuff written by a guy who actually knows what writing is all about: Entertaining your audience. A lot of Joels stuff should also be taken in that vain: The reason people read him is not that he is always right, it's that his posts are entertaining. So are the &lt;a href="http://blog.stackoverflow.com/category/podcasts/"&gt;Stackoverflow Podcasts&lt;/a&gt;, btw.&lt;div&gt;
&lt;div&gt;I'm kind of surprised about articles like &lt;a href="http://37signals.com/svn/posts/2002-bug-tracking-isnt-a-network-effect-business"&gt;this one on 37signals&lt;/a&gt;, that read &lt;a href="http://www.inc.com/magazine/20091101/does-slow-growth-equal-slow-death.html?partner=fogcreek"&gt;Joel Spolskys&lt;/a&gt; latest post and jump to all kinds of conclusions.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;No, building every feature a customer could ever want is not really a bad idea, &lt;i&gt;given that the new FogBugz has a new plugin system&lt;/i&gt;! I suspect Joel will be adding stuff missing via the plugin architecture one piece at a time and thus removing reasons for customers not to choose their product.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;I for one have certainly seen people choose an inferior product, just because it had one shiny feature - even though it didn't work right.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Using a  plugin system to add such features is a rather cool solution to the problem.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Secondly, regarding how Joel apparently wants to move to a sales force-driven company. Wow. Did he say that? I don't think so! There is a big difference between being "sales force-driven" and actually trying to sell your product.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;So far, Joel has been able to rely on word of mouth to sell his products. We all fell for them. CityDesk, anyone? It was a cool personal blog thingy (before online blogging tools were invented), but don't try using it as a CMS, just hoping it will eventually grow the features you need. His blog &lt;a href="http://www.joelonsoftware.com/"&gt;Joel On Software&lt;/a&gt; is very popular among developers and I'm sure all his fanboys tried to get their companies to buy FogBugz. Well, at least they all got their bosses to start using bug tracking! And consider FogBugz at the same time.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;But, Joel has pretty much said what he has to say. Anything new will be torn apart by the new kids on the blogging block. So his sales machine is coming to a halt. At the same time, his software is getting more and more mature and thus can start to go after the entreprises, that only want big names and sales reps that actually come and visit them etc. We are talking proper business here, not that web stuff you all think is the real world!&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Hiring sales people will prove difficult. What makes a good sales person? Snake oil selling qualities (in large quantities)? Heck if I know. And according to Joel, he doesn't really know either.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9223352140090705474-9186208895323945423?l=darenatwork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darenatwork.blogspot.com/feeds/9186208895323945423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://darenatwork.blogspot.com/2009/11/response-to-bug-tracking-isnt-network.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/9186208895323945423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9223352140090705474/posts/default/9186208895323945423'/><link rel='alternate' type='text/html' href='http://darenatwork.blogspot.com/2009/11/response-to-bug-tracking-isnt-network.html' title='Response to &quot;Bug tracking isn&apos;t a network-effect business&quot;'/><author><name>Daren Thomas</name><uri>http://www.blogger.com/profile/16173188589736612418</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
