tag:blogger.com,1999:blog-50964371126549147382024-02-19T14:12:46.911+10:00Rod Howarthblog.rodhowarth.com - Bits and pieces on software development and technology. Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.comBlogger127125tag:blogger.com,1999:blog-5096437112654914738.post-17617416807373090902019-01-09T02:57:00.002+10:002019-01-09T03:01:56.702+10:00Tips from my experience as an Aussie moving to San FranciscoIt's been a while since I posted anything on this blog - I figured it was about time to rectify that!<br />
<br />
Since my last post I've spent nearly 4 years working at <a href="https://invoice.2go.com/">Invoice2go</a>, an Australian startup that received funding from some VC firms in Silicon Valley. I spent the first couple of years working out of their <a href="https://invoice.2go.com/blog/inside-invoice2go/invoice2go-sydney-office/">office in North Sydney</a> before the opportunity came up to relocate to the Bay Area to work out of the <a href="https://invoice.2go.com/blog/inside-invoice2go/invoice2go-new-home-redwood-city/">Redwood City office</a>. This was something I'd wanted to do at some point in my life so I jumped on the chance to make the move. 15 months on I am settled into the area and thought I would share some tips that I found during the relocation process. Hopefully this post comes in handy for anyone else looking to make the move.<br />
<br />
<h2>
Background</h2>
<div>
First of all, some context. There were a number of things that made this move easier on me than perhaps it would have been for other people. First of all, I'm fortunate enough to have been born and raised in Australia, which has a long history of being a very close ally of the United States. As a result we have access to a special class of visa called the <a href="https://en.wikipedia.org/wiki/E-3_visa">E-3</a>. This (strangely enough) was created as part of free trade deal negotiations that happened during the wars in Iraq & Afghanistan - it <a href="http://gothamist.com/2014/06/09/australians_everywhere.php">supposedly was added a a sweetener</a> to try and get Australia to continue it's commitment of troops. This visa is much simpler than other visas like the H1-B in that it's purely reserve for Australians, with a yearly limit that we never come close to hitting. It's a 2 year visa that you can renew indefinitely by leaving the country and doing another interview. It's also very cheap and the process is relatively simple. I often reflect on how fortunate I am to have access to this visa and have sympathy for others who have a tougher visa situation.</div>
<div>
<br /></div>
<div>
Secondly, as I was relocated by my existing employer I'd already had the chance to visit the Bay Area a number of times and knew the team quite well over there. I was also continuing in a pretty similar role to what I was doing in the Sydney office, so there wasn't any stress of starting a new job added into the move - I simply continued my job the next week but in a different office. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJAafMgTJllUs9LwRAXh3cOnXTaREvW-tHm7gCc8mEGe925SAjvB7Iwi0jgm5NoBjQEojcHcAknnRqIav2HBrJPi3Vb9lmc2UYOPkaR9QJMAoPJrBMLkQ-JZ-iN5TPERYWY7hNdfY-zgIb/s1600/20160521_153516.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJAafMgTJllUs9LwRAXh3cOnXTaREvW-tHm7gCc8mEGe925SAjvB7Iwi0jgm5NoBjQEojcHcAknnRqIav2HBrJPi3Vb9lmc2UYOPkaR9QJMAoPJrBMLkQ-JZ-iN5TPERYWY7hNdfY-zgIb/s640/20160521_153516.jpg" width="640" /></a></div>
<div>
<br />
<h2>
Prior to the move</h2>
</div>
<div>
If you are planning to make a similar move there are some things you can do to make things easier on you when you come over. </div>
<div>
<br /></div>
<h3>
Get an American Express credit card</h3>
<div>
Building credit in the USA takes a long time, and most credit providers won't recognize your great Australian credit rating. This means that when you arrive in the USA you'll be stuck either with your Australian credit cards, your debit card from your bank (which may take a few paychecks to build up in funds) or a secured credit card with a very low limit. However American Express is an exception to this rule - they can transfer you from Australia to the USA, and they will take into account your internal credit history with them. So as soon as you are thinking of making a move to the USA I'd recommend applying for an Amex. You can often find good bonus points deals for Amex cards on <a href="https://www.ozbargain.com.au/">Ozbargain</a> which might help you pay for some flights in the future. Sign up, use it as much as you can and always pay it off promptly. Then when you move to the USA give them a call and ask to do a <a href="https://www.americanexpress.com/global-card-transfers/">global transfer</a>. </div>
<div>
<br /></div>
<div>
Thanks to my history with Amex in Australia I was able to get approved for a Platinum Amex card, which was very helpful in the first month until a couple of my paychecks at come through. This allowed me to avoid transferring too much money from my Australian bank account (with the associated fees). Even after a year the only credit cards I had were this fancy Amex and a bunch of secured credit cards meant for people with bad credit scores - kind of weird, but it works.</div>
<div>
<br /></div>
<div>
<h3>
Move your mobile number to a prepaid sim card</h3>
</div>
<div>
This may not apply to everyone, but I wanted to keep my Australian number active while living in the USA. There are a few reasons that I wanted to do this:</div>
<div>
<ul>
<li>I planned to keep bank accounts, credit cards etc active in Australia - so a local phone number is useful for authentication purposes where a 2fa app isn't an option</li>
<li>While many USA sim cards offer free global data roaming at slow speeds, I'd prefer to use my old number when I visit Australia and pay for high speed data</li>
<li>You never know what is tied to your old phone number that you'll suddenly need access to, or who will attempt to contact you</li>
</ul>
<div>
Obviously you don't want to pay a high monthly fee for the phone when you aren't using it, so move your phone to a prepaid sim that has the option of a small yearly top-up. I went with <a href="https://www.aldimobile.com.au/">Aldi Mobile</a>. They had a pay as you go option with <a href="https://www.aldimobile.com.au/plans/15payg/">365 day expiry for $15</a>. Whenever I visit Australia I just top up with a 'value pack' (last time was $25 for 9gb and unlimited calls/sms). It's great. </div>
<div>
<br /></div>
<div>
It's worth moving to this plan before you go as transferring your number gets more complicated if the address is different on your two phone accounts and it is more complicated to do it from overseas.</div>
</div>
<div>
<br /></div>
<div>
<h3>
Plan your Australian mailing address</h3>
</div>
<div>
If you're planning on keeping some accounts open in Australia (bank, credit card, super, etc) it's useful to have an Australian mailing address. Hopefully your parents, siblings or close friends are ok with you sending your mail to their place, or you could do a P.O. box or something like that. I'd recommend starting to update all of your addresses before you move. Once you move out of your place in Australia you can also setup a mail redirection through Australia post to this new address to catch any accounts you've forgotten to update. </div>
<div>
<br /></div>
<div>
<h3>
Renew your passport and drivers license</h3>
</div>
<div>
This is something I didn't do, but wish I did. My passport had a 10 year expiry and I was over 8 years through it when I got my E3 visa. The visa gets affixed to a page inside your passport, and if you get a new passport it doesn't get transferred. There are generally problems with traveling to the USA on a passport with less than 6 months until the expiry, so after a year of living in the USA I had to get a new passport. This involved finding a a place who understood the strict Australian passport photo requirements (<a href="https://goo.gl/maps/iTzX2oetp5G2">A Better Passport Photo</a> in San Francisco was perfect for this) and then going to the <a href="https://goo.gl/maps/Byit1naneZB2">Australian Consulate</a> to renew the passport. This wasn't such a big deal, but as the E-3 doesn't transfer you I now had to carry around two passports everywhere I went. It would have been easier if I just renewed it in Australia prior to applying for the visa.</div>
<div>
<br /></div>
<div>
I also have a NSW drivers license that is going to expire soon, and I'm sure renewing it will be a pain - I have no NSW residential address (my parents are in QLD) and even just getting to the office to renew it will be a pain given I mainly transfer over the holiday period. It would be easier if I had a longer expiration date on my license to begin with. </div>
<div>
<br /></div>
<div>
<h2>
The visa application process</h2>
</div>
<div>
After receiving the offer to relocate we kicked off the visa process. There's a <a href="http://sundaychampagne.com/get-e3-visa-someone-successfully-done/">few</a> <a href="https://americajosh.com/learn-more/immigration/e3-visas/step-step-guide-e3-visa/">good</a> <a href="https://www.brightlightsofamerica.com/2018/03/e3-visa-interview-step-step-guide/">posts</a> online about it so I won't go into too much detail, but in my experience the process from engaging the lawyers to receiving my passport with visa attached was around 3 weeks. This fluctuates depending on appointment timing and other factors, but for me it went quite smoothly.</div>
<div>
<br /></div>
<div>
Some people opt to do this process without the assistance of an immigration lawyer, but I'd recommend getting your employer to engage with one - it reduces the stress and uncertainty of the process. </div>
<div>
<br /></div>
<div>
I was living in Sydney and did my interview at the consulate there, whilst working with the lawyers in the USA. Here's an idea of the timings:</div>
<div>
<br /></div>
<div>
<b>Day 1</b> - Lawyers started the process<br />
<b>Day 3</b> - LCA filed<br />
<b>Day 8</b> - LCA certified<br />
<b>Day 14</b> - Documentation signed & case filed<br />
<b>Day 20</b> - Visa interview at consulate, approved on the spot<br />
<b>Day 22</b> - Received passport with visa in the mail</div>
<div>
<br /></div>
<div>
<h2>
Logistics of the move </h2>
</div>
<div>
Moving country is always going to be a logistical challenge. My partner and I had no pets or children and our apartment lease was month to month which meant that things were simpler for us than they might otherwise have been. It was still a lot of work to pack pup the apartment, sell my car & a bunch of other possessions, make good on the lease, move to temporary accommodation and then get to the airport. </div>
<div>
<br /></div>
<div>
Every situation is likely to be unique, but some tips that I have in general are:</div>
<div>
<ul>
<li>Before you sell every little thing on Gumtree/Ebay consider if it's worth your time. It may not be worth the hassle to sell various $10-50 smaller items in the rush of planning a big move. The weird and wonderful people of Gumtree can take up quite a lot of your time!</li>
<li>Take note of the local council rubbish collection policy in your area. My area only collected large items (like mattresses) on a certain day of certain weeks. We thought someone was going to buy our whole bed/mattress setup so we didn't put it out for collection on that day, but they didn't end up coming. As a result we had to pay a bunch of money for a garbage collection agency to come pick up the mattress and some other items in a last minute rush. Granted we could have just dumped it outside our apartment but we wanted to do the right thing.</li>
<li>Use the recommended cleaners from your real estate agent. It just makes the process easier - they know each-other and if the cleaners don't do a good enough job they'll chase up with them directly. You don't want that stress just before you fly out of the country!</li>
<li>Think about if you really want to move your stuff to the USA. I decided that it wasn't worth it. The cost of shipping is quite high and it takes a long time. Consumer goods are much cheaper in the USA, chances are you can furnish your whole apartment with Ikea and Amazon for around the same price as shipping everything across. We ended up just maxing out our luggage allowance on the flight over (we had status with Virgin Australia so were able to get 6 checked bags total).</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjNfBfprD2buUP3CkGsgOHNkPONcRqLIrtn-6maXEpwjcjF11ksyEnO5x1O5cO3JufwpEwL9iktph0Tu6E1EIoaIqA4MTNRkD_9zUUO0LB4Tq5EKJHWlqfTUA_4XaK8zzjUoDg40MqczmD/s1600/20171008_073548.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjNfBfprD2buUP3CkGsgOHNkPONcRqLIrtn-6maXEpwjcjF11ksyEnO5x1O5cO3JufwpEwL9iktph0Tu6E1EIoaIqA4MTNRkD_9zUUO0LB4Tq5EKJHWlqfTUA_4XaK8zzjUoDg40MqczmD/s640/20171008_073548.jpg" width="640" /></a></div>
<div>
<br /></div>
</div>
<div>
<h2>
Getting setup in the USA</h2>
</div>
<div>
<div>
When we arrived in the USA we were in a motel for a few weeks while we found an apartment to live. It'll probably take 3-4 weeks to find an apartment so you'll definitely need some temporary accommodation, and in the Bay Area even Airbnb is not cheap, so make sure you factor this into your costs/negotiation with employers. </div>
</div>
<div>
<br /></div>
<div>
<h3>
Finding an apartment</h3>
</div>
<div>
The Bay Area has a real housing shortage at the moment, so housing is competitive and very overpriced. A one bedroom apartment can set you back between 3 and 4.5 thousand dollars a month. If you thought Sydney was expensive wait until you arrive here! </div>
<div>
<br />
There's a few websites for finding rental properties - <a href="https://www.zillow.com/">Zillow</a>, <a href="https://www.trulia.com/">Trulia</a> and <a href="https://sfbay.craigslist.org/">Craiglist</a> are some popular ones. Craiglist can be known for scams - if it looks too good to be true it probably is. </div>
<div>
<br /></div>
<div>
Given that you've just arrived in the area, you won't have any credit or rental history, so some of the cheaper more competitive places might be harder for you to get. Given that we had limited time in our temporary accommodation and were brand new to the area our strategy was to just pay a little extra for an apartment in a large building. There's a number of newer developments that have a rental office attached to them, you can book an appointment and go for a tour of the amenities and see some example apartments. We figured we'd rather pay more for at least the first year and avoid any stress with bad landlords or not-so-great areas. </div>
<div>
<br /></div>
<div>
When we applied for a place our lack of credit history meant we needed to pay a months worth of rent up front as a deposit, not a big deal but it was lucky we had a couple of pays in our bank account by this point. </div>
<div>
<br /></div>
<div>
Something else to keep in mind here is the location of your work and what your commute will be like. As we were working in Redwood City we ended up in Mission Bay as it's close to the Caltrain. There's only 2 Caltrain stops in the city, so it really constraints your options unless you are willing to do a commute that involves multiple forms of transport. </div>
<div>
<br /></div>
<h3>
Social Security Number</h3>
<div>
One of your top priorities after landing should be to get your Social Security Number. The advice I received is that you need to wait 4-5 days after entering the USA in order for your information to be in the system, so we waited a week and then tried to go into the social security office. <a href="https://www.brightlightsofamerica.com/2017/05/social-security-number-for-expats">Katherine has a good post on this process</a>. It took me 3 visits to get it done, first day I went there was a public holiday that government offices observed so it was closed. Second day I went as soon as they opened and the line was massive already - part of this is because of the build up from the day before I'm sure, but from what I've read this isn't uncommon. Third day I decided to get there 40 mins before they opened, and was 6th person in line. This is what I'd recommend you do - get there before they open and line up. </div>
<div>
<br /></div>
<div>
Once you've got your SSN, you should provide it to your employer. Strangely enough I didn't need it in order to get my first pay - a temporary SSN was used and the tax agency was updated afterwards. I'm not really sure how that works, but it was helpful.</div>
<div>
<br /></div>
<h3>
Bank accounts</h3>
<div>
Getting a bank account was surprisingly easy. I walked into a Wells Fargo office and was able to get a bank account by bringing in my Australian passport. I didn't have an SSN (I added it later - it's important for your credit score) and put in my companies address. It's important to fix all this information up later, and apparently you should remember that your companies address was once used as a bank account location as it may come up when dealing with credit score related things later on. </div>
<div>
<br /></div>
<div>
For a credit card, as mentioned above I did a global transfer with Amex. A couple of months later I also setup a couple of secured credit cards in order to build my credit score. Don't rely on your Amex alone to build the score as it's a charge card rather than a traditional credit card so it will hold you back a bit. </div>
<div>
<br /></div>
<h3>
Drivers license</h3>
<div>
Your Australian drivers license will only work for a short period of time in California. There's a bit of confusing information flying around (apparently the DMV has been giving out conflicting information). The guide I followed was that 10 days after arriving in the state on your E-3 visa you won't be able to legally drive with your Australian license anymore. It will probably be different in other states as each state has a different set of rules. Some people choose to continue driving after this point, but the main thing I was worried about is not being covered under insurance if you are technically driving unlicensed. </div>
<div>
<br /></div>
<div>
So after 10 days you'll need to look at getting a Californian drivers license. Katherine has <a href="https://www.brightlightsofamerica.com/2016/11/swapping-your-australian-drivers-license-for-a-california-license-part-one/">a great blog pos</a>t with some information on this. It involves taking a knowledge test, much like the learners license in Australia, and then a practical test. In my experience the knowledge test took a bit of study, as there's a different enough set of rules to remember and all the speeds and distances aren't in the metric system like I was used to. The DMV website has a downloadable <a href="https://www.dmv.ca.gov/web/eng_pdf/dl600.pdf">handbook</a> to refer to, and I found a great website with <a href="https://www.dmv-written-test.com/california/practice-test-1.html">extra practice tests</a>. With some study I was able to pass the written test. </div>
<div>
<br /></div>
<div>
Even though I had signed up for <a href="https://www.zipcar.com/">Zipcar</a> (possible even with an Australian license) to get easy access to a car to drive around, you cannot use it for the practical test. Because you aren't legally allowed to drive, you need someone to bring you to the test and you apparently can't just bring a rental car. I found a great service called <a href="https://yogov.org/">YoGov</a> who will pick you up, let you practice for a couple of hours and then come with you to the test. The couple of hours of practice were more than enough for me - the practical test was much less strict than in Australia - instead of parallel parking all I had to do was reverse in a straight line! </div>
<div>
<br /></div>
<div>
Make sure to refer to the DMV website to find out what forms of I.D. you need to bring to your appointment, and be sure to make an appointment - the lines can be very long without it. </div>
<div>
<br /></div>
<div>
<h2>
Useful resources </h2>
</div>
<div>
There's a good community of fellow Aussie expats that have also made the move to the USA. I found some great Facebook groups that are useful to search through for information, particularly around the visa process. Here's a list of useful resources I found:</div>
<div>
<a href="https://www.facebook.com/groups/AustraliansInSanFrancisco/">Australians in San Francisco Facebook Group</a></div>
<div>
<a href="https://www.facebook.com/groups/AustraliansInNewYorkCity/">Australians in New York City Facebook Group</a></div>
<div>
<a href="https://www.facebook.com/groups/AustraliansInTheUSA/">Australians in the USA Facebook Group</a></div>
<div>
<a href="https://www.brightlightsofamerica.com/">Bright Lights of America Blog</a></div>
<div>
<a href="https://www.facebook.com/Sydney-Ducks-Aussies-in-San-Francisco-869448483187439/">Sydney Ducks SF Aussies meetup</a><br />
<div>
<a href="https://gdaysf.com/">G'day SF Newsletter</a></div>
</div>
<div>
<br /></div>
<div>
<h2>
Good luck!</h2>
</div>
<div>
Hopefully there's some useful information in this post for anyone who is looking to make a similar move. The USA is a great country to live in and explore, and is full of great people. Feel free to reach out to me if there's anything I can do to help you on your journey, or post on one of the Facebook groups - there's lost of helpful Aussies there. </div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com0tag:blogger.com,1999:blog-5096437112654914738.post-66575916748275404442015-01-24T20:55:00.000+10:002015-01-24T20:57:33.959+10:00Layouts in Xamarin FormsI recently gave a presentation at the second <a href="http://xamarinhackday.com/">Xamarin Hack Day</a> in Sydney. While <a href="http://blog.rodhowarth.com/2014/08/video-introduction-to-ibeacons-with.html">I spoke about iBeacons at the first hack day</a>, this time around I spoke about the various options for laying out UI's in Xamarin Forms. For those of you that don't know, Forms is a cross platform UI abstraction from Xamarin, which translates the Forms controls and layouts into the native UI appropriate for each platform. A ListView in iOS translates to a UITableView for example. It doesn't cover all scenarios, but for the common tasks it can save a lot of time, and you can break in and out of the abstraction whenever you like. <br />
<br />
With any new UI abstraction comes new things to learn, new quirks and tricks. Much like HTML and CSS, if you are just starting out your options for laying out your web pages are limited by how much you know. As a result, your UI's don't look as nice as they do once you learn more about the box model etc. I've noticed a similar thing happens to developers starting out with Xamarin Forms. As the documentation is still a bit of a work in progress, there can be a temptation to stick to UI's that are easy to layout, but I found once I took the time to dig in and learn more about the various controls and layouts, I was able to create much nicer interfaces. <br />
<br />
There's no video online of this one, however you can <a href="http://slides.com/rodhowarth/layouts-in-xamarin-forms">view the slides</a>, and the accompanying <a href="https://github.com/RodH257/xamarin-forms-layouts-examples">GitHub examples</a>. I also thoroughly recommend reading the preview of <a href="http://blogs.msdn.com/b/microsoft_press/archive/2014/10/06/free-ebook-creating-mobile-apps-with-xamarin-forms-preview-edition.aspx">Petzold's Xamarin Forms book</a>, as it's the best Xamarin Forms UI documentation. <br />
<br />
<iframe src="//slides.com/rodhowarth/layouts-in-xamarin-forms/embed" width="576" height="420" scrolling="no" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com0tag:blogger.com,1999:blog-5096437112654914738.post-72217487369752254332014-09-07T22:43:00.003+10:002014-09-07T22:44:18.880+10:00Handling references to images in Xamarin iOSI recently submitted a minor cosmetic update to an iOS app that I had created, and had a user report that after updating the app the app would crash on a certain screen (which was puzzling, given that it hadn't been affected by the update). I did some investigation and uncovered what is potentially a trap for app developers, so I thought I'd share it.<br />
<br />
The app allowed users to take photos and would store them in the app's Documents directory (Environment.SpecialFolder.Personal in Xamarin) waiting to be uploaded to a web server. A SQLite database would maintain a reference to the full path of the documents directory and access that path when the time came to upload the image. The user in question had taken some photos and then updated the app before uploading them, which caused the app to crash. It turns out that when an iOS app is updated, the GUID of the path to the data directory for that app is changed and all of the existing files are moved there, meaning that the paths in the SQLite database were now invalid and caused a crash upon trying to access them. This scenario, and the workaround for Objective-C apps is outlined on <a href="http://stackoverflow.com/questions/5607655/first-app-update-user-data-lost-was-stored-in-documents-directory">this Stack Overflow question</a>.<br />
<br />
Basically, the way to stop this from happening is to not store the full path to the file on disk, but instead store just the filename, and append it the Documents directory each time you access it. In Xamarin I did this via a helper class:<br />
<br />
<script src="https://gist.github.com/RodH257/142314f2c60afca4b2de.js"></script><br />
<br />
To illustrate it's usage, here is the code used to save the image:<br />
<br />
var path = GetFullImagePath.ForFileName(imageFileName);<br />
System.IO.File.Copy (t.Result.Path, path);<br />
<br />
Then imageFileName is stored in SQLite, not 'path'.<br />
<br />
If you implement this code you may not need the check to see if the path supplied is a full path, however it was necessary in my example because some of our users, including the one that reported the issue, will have the full path stored in the SQLite database - which will now call that helper method.<br />
<br />
The moral of the story is: if you store a reference to files stored in your Documents directory in your iOS apps, make sure you don't store the full path or this will cause problems when your app is updated.Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com0tag:blogger.com,1999:blog-5096437112654914738.post-18210907872694277672014-08-03T19:00:00.002+10:002014-12-07T14:04:44.311+10:00[Video] Introduction to iBeacons with XamarinRecently I attended a '<a href="http://xamarinhackday.com/">Xamarin Hack Day</a>' organised by <a href="http://www.michaelridland.com/">Michael Ridland</a> & <a href="http://ssw.com.au/">SSW</a> here in Sydney. It was a great day which started with a few presentations, and led into everyone sitting down and coding away on Xamarin applications.<br />
<br />
SSW are taking the concept around the world, so if you're interested in learning more about Xamarin you should check out <a href="http://xamarinhackday.com/">XamarinHackDay.com</a><br />
<br />
In the morning I gave a presentation on iBeacons and how to use them with Xamarin. I've got a keen interest in beacons and think there are big opportunities for developers that create applications which leverage them. I've spent some time trying out different beacon brands and trying out the iOS and third party Android SDK's. I've also been involved in discussing potential use cases to customers of <a href="http://envoyat.com/">Envoy</a> as part of our <a href="http://www.envoyat.com/services/mobile-apps/ibeacon-app-development/">iBeacon software development</a> offering.<br />
<br />
SSW recorded and edited the video, and have put it online <a href="http://tv.ssw.com/5467/introduction-to-ibeacons-with-xamarin-rod-howarth">here on their SSW TV website</a>.<br />
<br />
For convenience, here is the youtube video embedded:<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="//www.youtube.com/embed/jq2q_PKuYpU" width="560"></iframe><br />
<br />
And here are the slides:<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="420" mozallowfullscreen="" scrolling="no" src="//slides.com/rodhowarth/intro-to-ibeacons/embed" webkitallowfullscreen="" width="576"></iframe>Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com0tag:blogger.com,1999:blog-5096437112654914738.post-29730808651862100402014-03-29T18:11:00.002+10:002014-03-29T20:08:32.758+10:00Thoughts on Xamarin for iOS developmentRecently I had the opportunity to develop an iPad/iPhone application using <a href="http://xamarin.com/ios">Xamarin iOS</a>. For those of you that don't know Xamarin are a company that develop cross-platform implementations of the .NET framework. Their two main mobile product are Xamarin.iOS and Xamarin.Android, which are wrappers around the native iOS and Android SDK's. This allows you to write C# code that is compiled into native mobile apps.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://xamarin.com/"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFiw7kQ-yffk9Z-_UZ9uNmH7LnbYJ_t8fIxXlQ_jg8VV7qBSf3nFHx0S69p4w7Rp6Ex1C7DDKv2VZ_7pRzxM4kLjHEi7I-7svUKqbkJs1gPRhZENPSVjDCpfLI_tqCJUnHOlu3BSGYA9EO/s3200/image+(3).png" height="160" width="200" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
The good thing about this is that it allows you to write applications that have a shared 'core' library of platform agnostic code (for instance connections to web services, in-app database, business logic) while the user interface is written individually for each platform, providing an a good user experience while allowing for some code-sharing. This is in contrast to writing the app twice, in either Java for Android, or Objective C for iOS, and also differs from fully cross-platform solutions like PhoneGap, which requires some compromise in terms of the user interface. I often say the benefit of Xamarin is you write your app 1.5 times instead of 2, while maintaining an optimal user experience.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.google.com.au/url?sa=t&rct=j&q=&esrc=s&source=web&cd=4&cad=rja&uact=8&ved=0CEcQFjAD&url=https%3A%2F%2Fitunes.apple.com%2Fau%2Fapp%2Fbuildaform%2Fid767401706%3Fmt%3D8&ei=Wng2U5LqJITakAXezoD4Cw&usg=AFQjCNHfyZWYcgBP6HWKOuuEIyde1N64Mg&sig2=tiyLInnMKMLQK_lqfZm-nQ&bvm=bv.63808443,d.dGI"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6HYUSazs1JVZK-5n6n9PL7Zn_aPIzvhDhAw_zYEAbC3MRyMUJtD39ymgaJ2CMhqA3dP6kuNmWLdrehdJObB4OPiBGocEO3gPC5ikvbJ4JRiSacaughchZDTxXm8mpavHQUAkoyM06IiOX/s3200/iOS-Icon.png" height="200" width="200" /></a></div>
<br />
The project I was tasked with was to create a <a href="https://itunes.apple.com/au/app/buildaform/id767401706?mt=8">mobile inspection app for building certifiers</a> which was to replace a JQuery mobile website. The goals of the replacement app were to improve the offline support, which was subject to some limitation in HTML5 offline storage API's on iOS devices, to improve the user interface and to add some extra features like the ability to take photos of defects. Given these requirements, and especially that we really wanted to give a top quality experience for the user, I decided that a native app was the best way to go (note that I'm referring to Xamarin as native apps, which isn't technically correct however the terms native, hybrid and cross-platform are often mixed around. I consider hybrid to be a combination of native UI elements and webviews, others consider Xamarin to be hybrid).<br />
<br />
Having decided on a 'native' app, it came down to writing it with XCode and Objective-C, or giving Xamarin a go. <a href="http://envoyat.com/">Envoy</a> (the company I work for) specialise in .NET development, which is one factor, however I'm a believer in choosing the best tool for the job, and that learning new languages/technologies isn't something to be afraid of. In the end I went with Xamarin because it allows code sharing with a possible future Android version of the app, and because the core library could be built out faster in C#.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWG39WiVE55G_IPap_gmaKwk5fbEwgjsjd0l0IN_KpDfN2fsspfQ-RvufFfPWoq86WlH9-k5nLluvlz7cV8qs9Dxz0MezuUa0ZRZBTVmDZIyIcPsxMvrbvaFEuY3sC5jmT8APVAAD7Db7_/s3200/35484-244747-VqOlGXzJbZOUfKP-baf_inspection_mockup.png" height="545" width="640" /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
The app was finished in around 7 developer-weeks (including back-end work), and is <a href="https://itunes.apple.com/au/app/buildaform/id767401706?mt=8">live on the app store</a>. After completing the app, and having worked on Objective-C iOS projects previously, I thought I'd share some of my observations on the current state of Xamarin.<br />
<br />
<b><span style="font-size: large;"> The Good</span></b><br />
<b><br /></b>
<b>Xamarin is a high quality product</b><br />
<b><br /></b>
One concern I had was that if Xamarin goes broke the code we produce is probably useless as the framework and tooling won't get updated for new iOS updates, however they are well funded and have been around for quite a while now in various forms, and just keep getting bigger and bigger. Updates are pushed frequently, documentation is well written and kept up to date, and they even put on a yearly conference that has some great presentations. They also have a partnership with Microsoft, and there's all sorts of rumours about Microsoft possibly buying them.<br />
<br />
Our app ended up performing well and I didn't feel my development time was held back by the Xamarin product at all.<br />
<br />
<b>C# and Xamarin Studio fit in well with Cocoa Touch</b><br />
<b><br /></b>
I don't think Objective C is that bad, however there's no doubt that I found C# to be a more productive language, you can use Linq, Async/Await and some great .NET libraries including the <a href="https://github.com/praeclarum/sqlite-net">SQLite.NET mini ORM</a>. Xamarin Studio, which is their IDE for the Mac worked well, and integration with storyboards in Xcode works well enough.<br />
<br />
<b>Growing community</b><br />
<br />
There is a growing community of developers who are making great things in Xamarin, there are open source projects like <a href="https://github.com/MvvmCross/MvvmCross">MVVMCross</a> (which I chose not to use this time, but will look at in the future) that are actively contributed to and user groups around the globe full of developers. There are many blog posts and Stack Overflow questions that are Xamarin specific, which helps to accompany the official documentation.<br />
<br />
<b><span style="font-size: large;">
The Bad</span></b><br />
<b><br /></b>
<b>Missing out on iOS open source </b><br />
<b><br /></b>
This is the biggest one for me, so many components and UI widgets for iOS are available as open-source drop-ins to your app. Xamarin has a component store where they attempt to make up for this, however it still has a long way to go. For me, if I knew I was creating an app that was only ever going to be on iOS, this factor alone would probably mean I gave Xamarin a miss for that particular project so that I can make use of <a href="http://cocoapods.org/">CocoaPods</a>, however it's pretty rare that you know for certain you are never going to want an android version of an app.<br />
<br />
<b>Visual studio integration is flaky</b><br />
<br />
Xamarin has a feature that allows you to write code in Visual Studio and have it remotely compile and launch on a network connected Mac. This was very flaky and slow for me, so I didn't bother with it, Xamarin Studio isn't too bad, and if you like you can develop your core library code as a separate PCL DLL on Windows so you can use <a href="http://ncrunch.net/">NCrunch</a> for increase test driven development productivity and then develop the UI of the app on the Mac.<br />
<b><br /></b>
<b>Extra layer of potential bugs</b><br />
<br />
While the Xamarin team are extremely smart, and have created a great platform, they are not infallible. There is still an extra layer of code between your app and the hardware which could cause bugs, either in the Xamarin code itself, or as a result of you needing to know about how both iOS and the Xamarin garbage collectors/compilation works. After we released the app, we wanted to add some image resizing features, and came across a memory leak (Xamarin ships their own garbage collector in your app) that we had a hard time fixing. After contacting support with a trimmed down app to reproduce the problem they indicated to us they found a bug in Xamarin and were going to push an update shortly. They also gave us a workaround which got us going straight away which was great, however it still cost us a few days of developer time debugging it.<br />
<br />
<b><span style="font-size: large;">
Other things to note</span></b><br />
<b><br /></b>
<b>Using Xamarin is not an excuse not to learn Cocoa Touch and bits of Objective C</b><br />
<br />
My earlier point about not being afraid to learn new things applies here as you'll still be reading Objective C code from blog posts and Apple's official documentation. Xamarin just wraps the Cocoa Touch libraries so you'll need to understand how that works - it's different to the web, and different to WPF, so don't think you Xamarin is a choice to help you just use your .NET developer knowledge to ship an iOS app. A great book to get introduced is <a href="http://ijoshsmith.com/ios-for-dotnet-devs/">iOS programming for .NET developers</a>.<br />
<b><br /></b>
<b>License Fees</b><br />
<br />
Xamarin licenses for companies are $999 USD a year, per platform. This isn't cheap, but compared to developers salaries, or some of the common license fees for Microsoft developer products this is as cheap as chips.<br />
<br />
<b><span style="font-size: large;">Overall</span></b><br />
<b><br /></b>
All in all I'm a fan of Xamarin and would definitely use it again in the future, however I wouldn't say it's what you should <i>always</i> use for mobile development, it's a matter of picking the best tool for the job, which may be an Objective C/Android app, a Xamarin app, PhoneGap or a responsive website depending on the project, budget, goals etc. I do however believe Xamarin should definitely be something you consider as a serious option.<br />
<br />
<b>
Also..</b><br />
<div>
I'd like to give some credit to <a href="http://vanessagrixti.com/">Vanessa Grixti</a> (<a href="http://twitter.com/vgrixti">@vgrixti</a>) for the visual design/UX work on the Buildaform app, she did a great job working to a tight deadline. Also if you are looking for <a href="http://www.envoyat.com/services/mobile-apps/">Xamarin mobile developers in Sydney</a>, get into contact with <a href="http://envoyat.com/">Envoy</a>, as I'd love to work on some more Xamarin projects. </div>
Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com0tag:blogger.com,1999:blog-5096437112654914738.post-75811544382063471482014-02-16T15:56:00.000+10:002014-02-16T16:00:48.817+10:00[Revit API] Binding a project parameter to all categoriesIn a recent project I had the need to create a new project parameter, and then set the value of it on certain elements. <a href="http://spiderinnet.typepad.com/blog/2011/05/parameter-of-revit-api-31-create-project-parameter.html">This post</a> has great information on creating project parameters, however that post along with much of the Autodesk documentation add certain parameters to the CategorySet for the InstanceBinding method, what I wanted to do was add all of them. Unfortunately adding all categories in document.Settings.Categories throws an error as not all categories can have parameters bound.<br><br>There is a simple solution to this, only add categories to the CategorySet if they have their AllowsBoundParameters property set to true. It’s an obvious solution once you know this flag is available. <br><br><pre class="csharpcode">CategorySet categories = app.Application.Create.NewCategorySet();
<span class="kwrd">foreach</span> (Category category <span class="kwrd">in</span> doc.Settings.Categories)
{
<span class="kwrd">if</span> (category.AllowsBoundParameters)
{
categories.Insert(category);
}
}</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style> Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com0tag:blogger.com,1999:blog-5096437112654914738.post-35075118899827995612014-01-04T22:44:00.001+10:002014-01-04T22:44:25.401+10:00Setting up node-postgres with a new PostgreSQL installation on OSXI was getting a PostgreSQL installation setup with NodeJS today on my computer and ran into some difficulty that I thought I'd write a post about in case someone else comes across the issue.<br />
<br />
I started off by downloading the PostgreSQL installer from the <a href="http://www.postgresql.org/download/macosx/">PostgreSQL website</a> (I had also tried Postgres.app) and running through the installer with mostly default settings.<br />
<br />
Once that was done I went to install the <a href="https://github.com/brianc/node-postgres">node-postgres</a> module in my node project via 'npm install pg', this threw the following error:<br />
<br />
<blockquote class="tr_bq">
gyp: Call to 'pg_config --libdir' returned exit status 127. while trying to load binding.gyp</blockquote>
<br />
After some searching I found this <a href="https://github.com/TooTallNate/node-gyp/issues/223">Github issue</a> which pointed me to the solution. The problem is that the installer did not add the PostgreSQL binary folder to my PATH. To get around this, I updated my ~/.bash_profile (vim ~/.bash_profile is the easiest way to do this) to add the following line:<br />
<br />
export PATH=/Library/PostgreSQL/9.3/bin:$PATH<br />
<br />
(be sure to use the version of PostgreSQL you installed. Also, if you already have that line, you should just add '/Library/PostgreSQL/9.3/bin:' after PATH=)<br />
<br />
Save that file, restart terminal and you should be able to type pg_config and get some output on your screen. Once you've done that, reinstall the node-postgres module and you should not see the error anymore.<br />
<br />
Hope this helps!Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com0tag:blogger.com,1999:blog-5096437112654914738.post-23435239843127257572013-11-13T00:23:00.000+10:002013-11-13T00:24:16.640+10:00SQLite.Net ORM with Task Parallel Library in XamarinI've recently had the opportunity to work on a Xamarin.iOS project with Envoy. Having previously built iOS applications with Objective C I've been enjoying the chance to investigate techniques to share code across platforms.<br />
<br />
With Xamarin, you can share some common code between Android and iOS projects if you structure it in a certain way. One technique that is commonly used to share code is to use the SQLite.NET ORM with SQLite rather than using Core Data or other device specific data access API's. Xamarin themselves have used this for an application which they've open sourced as example code: <a href="https://github.com/xamarin/mobile-samples/tree/master/MWC">MWC 2012 </a><br />
<br />
<a href="https://github.com/xamarin/mobile-samples/blob/master/MWC/MWC.Core/DL/MwcDatabase.cs">In that application</a>, they create a subclass of SQLiteConnection with a static constructor that initialises a static variable to hold a reference to itself, as a kind of singleton. I followed this pattern in my code, however I've since discovered that this is perhaps not the best approach in all circumstances.<br />
<br />
My application makes use of the Task Parallel Library to do some web service calls and subsequent database updates on a background thread. Much like the MWC sample I wrapped my calls to the database with a lock so that multiple threads won't update the database at once, and the application appeared to work correctly. However at various stages during my testing I came across seemingly random crashes, where the application which had been working fine would crash out of the blue with an error similar to the following:<br />
<br />
<blockquote class="tr_bq">
<div style="border: 0px; color: #777777; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.5; margin-bottom: 10px; margin-top: 10px; outline: 0px; padding: 0px; vertical-align: baseline;">
mono-rt: Stacktrace:</div>
<div style="border: 0px; color: #777777; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.5; margin-bottom: 10px; margin-top: 10px; outline: 0px; padding: 0px; vertical-align: baseline;">
mono-rt: at <0xffffffff><!--0xffffffff--></0xffffffff></div>
<div style="border: 0px; color: #777777; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.5; margin-bottom: 10px; margin-top: 10px; outline: 0px; padding: 0px; vertical-align: baseline;">
mono-rt: at (wrapper managed-to-native) SQLite.SQLite3.Prepare2 (intptr,string,int,intptr&,intptr)</div>
<div style="border: 0px; color: #777777; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.5; margin-bottom: 10px; margin-top: 10px; outline: 0px; padding: 0px; vertical-align: baseline;">
mono-rt: at SQLite.SQLite3.Prepare2 (intptr,string)</div>
<div style="border: 0px; color: #777777; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.5; margin-bottom: 10px; margin-top: 10px; outline: 0px; padding: 0px; vertical-align: baseline;">
mono-rt: at SQLite.SQLiteCommand.Prepare ()</div>
<div style="border: 0px; color: #777777; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.5; margin-bottom: 10px; margin-top: 10px; outline: 0px; padding: 0px; vertical-align: baseline;">
mono-rt: at SQLite.SQLiteCommand.ExecuteNonQuery ()</div>
<div style="border: 0px; color: #777777; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.5; margin-bottom: 10px; margin-top: 10px; outline: 0px; padding: 0px; vertical-align: baseline;">
mono-rt: at SQLite.SQLiteConnection.Execute (string,object[])</div>
</blockquote>
<br />
This isn't particularly helpful and originally made me worried that perhaps the SQLite.NET ORM wasn't stable. However after some more research I've discovered that <a href="http://forums.xamarin.com/discussion/7059/sigsegv-fatal-mono-error">others were having the same problem</a> and that they believed it was caused by the SQLite connection being accessed on different threads, even if it's not at the same time. When you think about it, of course this is an issue - the subclass of SQLiteConnection shouldn't be a singleton, it's a connection similar to those seen in ADO.NET and should be thread specific and closed when not needed. I believe the MWC application musn't have ran into this issue as they were only doing updates to the database on certain threads, not leaving it up to the Task Parallel Library.<br />
<br />
So now, instead of having a singleton in my SQLite Connection, I'm using it in the IDisposable fashion it is designed to be used so that a connection is opened and closed with each query.<br />
<blockquote class="tr_bq">
using (var db = MyDatabse.NewConnection())<br />
{<br />
db.Insert(itemToInsert);<br />
}</blockquote>
I've since stopped having the random application crashes. Hopefully this helps someone out who is having the same issue.<br />
<br />Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com3tag:blogger.com,1999:blog-5096437112654914738.post-3802128426329310772013-05-28T09:00:00.002+10:002013-05-28T09:01:23.924+10:00Styling Two or More Fusion Tables Layers in Google MapsThe Google Maps API has a feature called '<a href="https://developers.google.com/maps/documentation/javascript/layers#FusionTables">Fusion Tables Layer</a>' which lets you overlay data from a <a href="http://www.google.com/drive/apps.html#fusiontables">Google Fusion Tables</a>. Using this feature, you can upload some KML data into a Fusion Table and see it represented on the map (for example, you can highlight an area on a map to represent some sort of data). The Maps API has in built support for using KML directly, however KML files can get quite large for complex data, so using Fusion Tables is a high performance alternative (Google handles large data sets with ease) This is what my exmaple Fusion Table with KML data uploaded looks like:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsY8JMwLgjiorNQ8Cyx7nrZN7vXvozGxQuM5UaxKsfqACUUQm_VjThjIiT-M4ukWfz7UVS4ChZIIY3WSykZ72OpFFnMXmYmEVL-D06HisujzULuIQ7ZvU46zsuKVRgHhbL2WlB9YAsy4zK/s1600/Screen+Shot+2013-05-28+at+8.57.03+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsY8JMwLgjiorNQ8Cyx7nrZN7vXvozGxQuM5UaxKsfqACUUQm_VjThjIiT-M4ukWfz7UVS4ChZIIY3WSykZ72OpFFnMXmYmEVL-D06HisujzULuIQ7ZvU46zsuKVRgHhbL2WlB9YAsy4zK/s320/Screen+Shot+2013-05-28+at+8.57.03+AM.png" width="228" /></a></div>
<br />
<br />
You can display markers, polygons, and polylines on a layer and can style each of these as you wish using the options supplied to the API call. <a href="https://developers.google.com/maps/documentation/javascript/examples/layer-fusiontables-styling">An example of the code to do this is available here.</a><br />
<br />
If you have multiple bits of data to show, you can add multiple layers from a range of different Fusion Tables. However, there is one limitation, which is pointed out in the documentation:<br />
<blockquote class="tr_bq">
<span style="background-color: #efefef; color: #222222; font-family: Arial, sans-serif; font-size: 13px; line-height: 21px;">Styles can only be applied to a single Fusion Tables layer per map. You may apply up to five styles to that layer.</span></blockquote>
I recently ran into this limitation when trying to overlay two separate (complex) data sets. For my use case, I wanted to show data from two different Fusion Tables with two different styles, which means I was out of luck. I tried a number of workarounds to avoid this (seemingly odd) limitation. I attempted to combine them into the one table, but the queries don't allow OR statements, I then tried using my own KML file, however that came out larger than 1MB, which loaded very slowly, whereas the Fusion Tables layer handled that data with ease.<br />
<br />
I then attempted to add styling information to the KML file before uploading it into the Fusion Table interface (as KML supports this), however the upload process strips that information out. It was while searching for a way to get around this that I found the solution. I discovered that in the Fusion Tables interface you can add your own map, style it there, and it will give you code to easily embed it. This is designed to allow those without coding skills to style and embed a map on a blog or web page. Great! I thought, a bit annoying that I have to store that information in an external dependency instead of in my own code in source control, but at least I can solve this problem (I could perhaps use the Fusion Tables API to set this style from within my application, at the cost of a few HTTP requests).<br />
<br />
However when I went to find this map tab that <a href="https://support.google.com/fusiontables/answer/185991?hl=en">the documentation</a> mentions, it was greyed out...<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2zcOFO4GHmG62QnYylnLPQRDHE8pdsZjqUCgxYdxX38Z4GeQ-xQ32wPshkRZeBNin1di8NXU5jmOrXrTvYMFkNXyf2cwE2FLQ5iT3r0mzhHxWfQavupwHJokvtnfXUW2bdp0rxYaPrQEc/s1600/Screen+Shot+2013-05-28+at+8.33.53+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2zcOFO4GHmG62QnYylnLPQRDHE8pdsZjqUCgxYdxX38Z4GeQ-xQ32wPshkRZeBNin1di8NXU5jmOrXrTvYMFkNXyf2cwE2FLQ5iT3r0mzhHxWfQavupwHJokvtnfXUW2bdp0rxYaPrQEc/s320/Screen+Shot+2013-05-28+at+8.33.53+AM.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
There's no mention that I could easily find on the page explaining why it was greyed out, but I had a hunch. Given how terribly Google has dealt with Google Apps accounts, I figured that seeing as I was signed in with a Google Apps email, it might have something to do with that. Signing into my personal Gmail revealed that my hunch was indeed correct, I can add a map (you may need to give that account write permissions or copy the table to your personal account).</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkIlTp-0KZN1NgamIS4hT3oNPKwKNXnXX0ktCLP_KEoDOI0HrgTBi9oGbG2eWw4Q6p_su4UNoOWc-jtS4PThP7ZmCHsRgZ13mTZ8vZJyMFUnCII-pjb-3W5Rg5FqXAnPk5GS6NHaD_Iarm/s1600/Screen+Shot+2013-05-21+at+9.15.07+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkIlTp-0KZN1NgamIS4hT3oNPKwKNXnXX0ktCLP_KEoDOI0HrgTBi9oGbG2eWw4Q6p_su4UNoOWc-jtS4PThP7ZmCHsRgZ13mTZ8vZJyMFUnCII-pjb-3W5Rg5FqXAnPk5GS6NHaD_Iarm/s320/Screen+Shot+2013-05-21+at+9.15.07+AM.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Sigh. Some searching uncovered <a href="https://support.google.com/fusiontables/answer/1657096">some documentation on this</a>. You have to submit a request to Google asking them to turn it on. Would be nice if they just mentioned this in the interface...</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Once you've added a map, tools > change map styles will let you style it.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH8uAQ_k58CTU60SnWwBAqCc3xW3_STlyFj9EQ5mlkZdAVqQlC5B3_q3YXrWnR0vKGjgLRVH3Xj4TIoxYh-5b4W4SvSOfa8WhZ9EhgXamLYcZFseTAWcQzEHVMe6ltJFPIk6zLPQi5qoas/s1600/Screen+Shot+2013-05-28+at+8.39.45+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH8uAQ_k58CTU60SnWwBAqCc3xW3_STlyFj9EQ5mlkZdAVqQlC5B3_q3YXrWnR0vKGjgLRVH3Xj4TIoxYh-5b4W4SvSOfa8WhZ9EhgXamLYcZFseTAWcQzEHVMe6ltJFPIk6zLPQi5qoas/s1600/Screen+Shot+2013-05-28+at+8.39.45+AM.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8QoMW8e6perG1bcklPkYX0OhxOk3iWkgGUGagi2g7ZwqINelxPLBbcZUjHZOaWUhbeVZLFbwXwJ6KOiQE_8IjhfSnC4Tx1DGfnHM_M_bMVqBJhW_wzYdn7BBRx7oL9gD5j0EyecdQLWzR/s1600/Screen+Shot+2013-05-28+at+8.40.44+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="295" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8QoMW8e6perG1bcklPkYX0OhxOk3iWkgGUGagi2g7ZwqINelxPLBbcZUjHZOaWUhbeVZLFbwXwJ6KOiQE_8IjhfSnC4Tx1DGfnHM_M_bMVqBJhW_wzYdn7BBRx7oL9gD5j0EyecdQLWzR/s320/Screen+Shot+2013-05-28+at+8.40.44+AM.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
You're note quite done yet though, simple embedding this table into the API won't do it, you need to tell the API which style and which template to use in your map. <a href="https://developers.google.com/fusiontables/docs/v1/using#WorkingStyles">There's some documentation on getting the style number and setting it in the Maps API here</a>. I couldn't find an easy way to get this Id from the API, but it's probably a small number if you just want to try numbers up from 1,2,3,4 etc. Next you need the template ID, which you can find by clicking on the map tab's dropdown and clicking publish. At the end of the URL the querystring will have the template ID as 'tmplt'. </div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit_ETKH3dLh6UC6ZTg4yUeUpadeNGaje7AlQdZ3qqFTChrjGbr_iZiPdKmZEB3z0GM6P8bFyID6aiDwhO5dGWiycBzPTVb7xzHyPjrSQRM1V34YtZRRiGh40LhwShf0mGVzxmTCR7ptcbk/s1600/Screen+Shot+2013-05-28+at+8.52.05+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="217" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit_ETKH3dLh6UC6ZTg4yUeUpadeNGaje7AlQdZ3qqFTChrjGbr_iZiPdKmZEB3z0GM6P8bFyID6aiDwhO5dGWiycBzPTVb7xzHyPjrSQRM1V34YtZRRiGh40LhwShf0mGVzxmTCR7ptcbk/s320/Screen+Shot+2013-05-28+at+8.52.05+AM.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
You then pass these through in your maps API call like so:</div>
<div class="separator" style="clear: both;">
gridLayer = new googleMap.FusionTablesLayer({</div>
<div class="separator" style="clear: both;">
query: {</div>
<div class="separator" style="clear: both;">
select: 'geometry',</div>
<div class="separator" style="clear: both;">
from: fusionTableId,</div>
<div class="separator" style="clear: both;">
},</div>
<div class="separator" style="clear: both;">
map: map,</div>
<div class="separator" style="clear: both;">
templateId: 2,</div>
<div class="separator" style="clear: both;">
styleId: 2,</div>
<div class="separator" style="clear: both;">
clickable: false</div>
<div class="separator" style="clear: both;">
});</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
You should them see your styled map embedded in your page. Simple... right?</div>
Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com2tag:blogger.com,1999:blog-5096437112654914738.post-2362337813147271432012-06-29T23:20:00.000+10:002012-06-29T23:35:59.861+10:00Using C# Named Parameters for Code ReadabilityIn C# 4.0, Microsoft introduced a feature called 'Named Parameters', which lets you refer to parameters in a method that you are calling in a syntax like this: <div> </div> <div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> MyMethod(firstParameter: firstValue, secondParameter: secondValue)</pre><br></div>
<div>This lets you call the method with parameters in a different order, and also helps to facilitate optional parameters. Aside from these benefits, I've come to like using them to improve code clarity, particularly in unit tests. </div>
<div> </div>
<div>Lets say you have a method like this one:</div>
<div> </div>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">public decimal CalculateFuelCostPerKm(double kilometresTravelled, double litresInFuelTank, decimal costToFillTank) <!--CRLF--></div></div>
<div> </div>
<div>If you were to call that method, you might do something like this:</div>
<div> </div>
<div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">CalculateCostPerKm(500D, 60D, 72.58M);</pre><br></div>
<div>However if you are reading that and don't know the parameters, you're going to have to dive deeper to understand it. A way to improve it might be:</div>
<div> </div>
<div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">var kilometresTravelled = 500D;<br>var litresInFuelTank = 60D;<br>var costToFillTank = 72.58M;<br>CalculateCostPerKm(kilometresTravelled, litresInFuelTank, costToFillTank);<br></pre><br></div>
<div>Which is much clearer, but is a fair bit of effort. But with C# named parameters you can do this:</div>
<div> </div>
<div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">CalculateCostPerKm(kilometresTravelled: 500D, litresInFuelTank: 60D, costToFillTank: 72.58M);</pre><br>Simple to do, and clear to read. In fact, this is probably one of the rare situations where C# being written </div>
<div>more like Objective-C is a good thing. Take this example for creating an alert dialog in the iOS SDK:</div>
<div> </div>
<div><span style="font-family: courier, consolas, monospace; font-size: 13px">- (id)initWithTitle:(</span><a style="font-family: courier, consolas, monospace; color: #003366; font-size: 13px; text-decoration: none" href="https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/doc/c_ref/NSString">NSString</a><span style="font-family: courier, consolas, monospace; font-size: 13px"> *)</span><em style="font-family: 'Lucida Grande', geneva, helvetica, arial, sans-serif; font-size: 13px">title</em><span style="font-family: courier, consolas, monospace; font-size: 13px"> message:(</span><a style="font-family: courier, consolas, monospace; color: #003366; font-size: 13px; text-decoration: none" href="https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/doc/c_ref/NSString">NSString</a><span style="font-family: courier, consolas, monospace; font-size: 13px"> *)</span><em style="font-family: 'Lucida Grande', geneva, helvetica, arial, sans-serif; font-size: 13px">message</em><span style="font-family: courier, consolas, monospace; font-size: 13px"> delegate:(id)</span><em style="font-family: 'Lucida Grande', geneva, helvetica, arial, sans-serif; font-size: 13px">delegate</em><span style="font-family: courier, consolas, monospace; font-size: 13px"> cancelButtonTitle:(</span><a style="font-family: courier, consolas, monospace; color: #003366; font-size: 13px; text-decoration: none" href="https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/doc/c_ref/NSString">NSString</a><span style="font-family: courier, consolas, monospace; font-size: 13px">*)</span><em style="font-family: 'Lucida Grande', geneva, helvetica, arial, sans-serif; font-size: 13px">cancelButtonTitle</em><span style="font-family: courier, consolas, monospace; font-size: 13px"> otherButtonTitles:(</span><a style="font-family: courier, consolas, monospace; color: #003366; font-size: 13px; text-decoration: none" href="https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/doc/c_ref/NSString">NSString</a><span style="font-family: courier, consolas, monospace; font-size: 13px"> *)</span><em style="font-family: 'Lucida Grande', geneva, helvetica, arial, sans-serif; font-size: 13px">otherButtonTitles,</em><span style="font-family: courier, consolas, monospace; font-size: 13px"> </span><em style="font-family: 'Lucida Grande', geneva, helvetica, arial, sans-serif; font-size: 13px">...</em> </div>
<div> </div>
<div>Which you would call like:</div>
<div> </div>
<div>
<div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">[[UIAlertView alloc] initWithTitle:<span style="color: #006080">@"Error"</span> message:<span style="color: #006080">@"You stuffed up"</span> delegate:self cancelButtonTitle:<span style="color: #006080">@"OK"</span> otherButtonTitles:nil];</pre><br>Or in C# you might do something like this (ignoring the delegate business):</div>
<div> </div>
<div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">UIAlertView.InitWithTitle(<span style="color: #006080">"Error"</span>, <span style="color: #006080">"You stuffed up"</span>, myDelegate, <span style="color: #006080">"OK"</span>, <span style="color: #0000ff">null</span>);</pre><br>As you can see, the verbose nature of Objective-C makes for clearer code in this instance, however, we could write the C# method like: </div>
<div> </div>
<div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">UIAlertView.InitWithTitle(title: <span style="color: #006080">"Error"</span>, message: <span style="color: #006080">"You stuffed up"</span>, <span style="color: #0000ff">delegate</span>: myDelegate, cancelButtonTitle: <span style="color: #006080">"OK"</span>, otherButtonTitles: <span style="color: #0000ff">null</span>);</pre><br>Which makes it just as clear. </div></div>
<div> </div>
<div>I've found this technique particularly useful in unit tests, which often tend towards using constant values. For instance I might often have a method to setup a certain state in my stubs where I take in the important parameters required, this technique makes this much easier to read. </div>
<div> </div>
<div>I’d love to hear your thoughts on this technique, either in the comments on this post or via <a href="http://twitter.com/rodh257">Twitter (@rodh257)</a></div> Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com9tag:blogger.com,1999:blog-5096437112654914738.post-57024513551696251782012-06-17T18:09:00.000+10:002012-06-17T18:09:42.850+10:00What's been happening?It's been a fair while since I last posted to this blog, so as I start lining up a few more blog posts I thought I'd make a quick post to let you know what I've been up to over the last 6 months. <br />
<br />
The last post I made was about <a href="http://blog.rodhowarth.com/2011/11/at-last-years-autodesk-university.html">an experimental technique I'd created for running Revit API add-ins as scheduled tasks</a>. This was a part of my <a href="http://au.autodesk.com/?nd=class&session_id=9580">Autodesk University 2011 virtual presentation</a>, which is online now. If you don't have access to the AU Online website I've uploaded the slides and handout and the <a href="https://github.com/RodH257/RevitRemoteBoot">sample code for the Revit Remote Boot</a> and <a href="https://github.com/RodH257/RevitServerHtmlAdmin">Html Server Admin</a> are on Github. This was a pretty niche topic, but it was fun to dive into, and I hope people got some good use out of it. It's worth noting that <a href="http://wikihelp.autodesk.com/enu?adskContextId=EXLINK_RS_OVERVIEW&product=REVIT&release=2013&language=enu">Revit Server 2013</a> is now out, and makes a few changes which could affect this code (I'd be interested to hear if you were using this code).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://envoyat.com/"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNUDgWvqc1OCV1vLhgP1wP-Ygd1G2yRyTpG2b2zO9OZX7ZemvN6Y16UWjUEEmo2yyJ2VMOoErxqMlRPDqY6nqg8xSL9Ed8XnUE5S38cWAImAPzhZ2k1xFHhES7cIUJ_-juUW7oX3nxh55u/s1600/envoyLogo+(1).gif" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
After this post was made I have started work with a new company, <a href="http://envoyat.com/">Envoy Advanced Technologies</a>. Envoy are an agile software development firm that primarily work on web-based business applications. This has given me the opportunity to work on some big software systems with some really brilliant developers using some great development techniques (as a shameless plug, if you're looking to have a software system developed, whether it involves Revit or not, you could do much worse than to get into contact with Envoy).<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgckGmzF5614EJiE6Ff9aE5X_UvhEKPCbo6HoL2xq3aeCLERPd7d3q3__p_xFYOK5KF9bn2T1ewMTHgV0C-taG4pkvHKdqmIr3e3CkjwQQGkThThyoMVHMMgaV6OZ17xpGG9St0wmuyTH4P/s1600/rtcapp.PNG" /></div>
Aside from the larger projects, I recently worked on the<a href="http://www.rtcevents.com/blog/?p=270"> iOS and mobile web apps</a> for this years <a href="http://rtcevents.com/">Revit Technology Conference</a>. Envoy were a sponsor of RTC AUS and the USA version of the conference is starting in a couple of weeks time, if you haven't had a look yet I recommend you head to <a href="http://revitconference.com.au/rtc2012us/index.htm">their website</a> and look over the schedule. It looks to have some really good classes, including one on Revit Server.<br />
<br />
This change in employer has meant that I've not been working as much on Revit add-ins as I used to, hence the lack of posts on the topic. I am however still tinkering away with it in my spare time, and have a few ideas floating around my head for nifty ways to use the new <a href="http://thebuildingcoder.typepad.com/blog/2012/03/revit-2013-and-its-api.html">2013 API features</a> which I hope to post about in the future.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://budurl.com/ConvoyiOS"><img border="0" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8OAqBgeoklhCxC0lxDeQ_Qdk0c189cvzsO_b2CVfYeN-uiUqz3PKtHdoZvX_OTkGMWZGOqQo-ggPgKN9BKy_YzCQaKQjZT7VI0zARJUFLfSwSWOF5dXmiO6Z7mMZJbz8Iv3KCE_UTZ_Hs/s320/convoy-logo@2x.png" width="320" /></a></div>
In my spare time, I've released an update to <a href="http://budurl.com/ConvoyiOS">Convoy</a>, my iOS app to make it easier to communicate when travelling in a group of vehicles. Primarily it includes a graphics overhaul which is thanks to <a href="http://grixdesigns.wordpress.com/">Vanessa Grixti</a>.<br />
<br />
This and other projects I've been working on are great as they give me the chance to dive into some product development/management, which is an interest of mine, I've been blogging about these sorts of topics over at <a href="http://cejest.com/">Cejest</a>, but I'm planning on moving those posts over to this blog.<br />
<br />
In addition to these posts, I'll be writing more about general software development topics, both technical (C#, ASP.NET MVC, iOS etc) and non-technical, including posts on workflows, development practices etc. A reminder that if you aren't interested in reading this, and just want Revit content, there's a link to a Revit topics only RSS feed on the right of the blogs main page.<br />
<br />
If you've got any feedback or questions feel free to <a href="mailto:mail@rodhowarth.com">email me (mail@rodhowarth.com)</a> or <a href="http://twitter.com/rodh257">ping me on twitter (@rodh257)</a>.Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com0tag:blogger.com,1999:blog-5096437112654914738.post-11523959771593092232011-11-15T17:43:00.001+10:002012-04-13T17:29:46.576+10:00[Revit API]– Revit Remote Boot - A technique to run an API add-in on a particular Revit model without user interactionAt last years Autodesk University, someone mentioned that they were looking for a way to run an export on their model once a day, on a schedule. This is not something that the Revit API is generally used for, but it got me thinking of ways that I could make it happen. While flying around the USA after AU I hacked together some prototype code which did just this, but left it shelved. For my AU 2011 virtual class, I decided to finish it off and make it public, in case someone else wants to use it.<br />
The program is called ‘Revit Remote Boot’, and is really more of a ‘system’ than a program, there are a number of moving parts to make it all happen. Put simply, it is a couple of interacting programs that allow you to perform an operation on a Revit model from a script. <br />
Take a look at this video, which is a small part of my AU Virtual class, for a full demonstration of what it does. Note that while it talks about using Revit Server to create a local model, if you are running just a pure file server, this is fine as well – you could just directly open the file. It’s just that running Revit Server opens up some interesting possibilities and was the topic of my AU presentation. <br />
<br />
<iframe allowfullscreen="allowfullscreen" frameborder="0" height="300" src="http://player.vimeo.com/video/32118121?title=0&byline=0&portrait=0" webkitallowfullscreen="webkitallowfullscreen" width="400"></iframe> <br />
<a href="http://vimeo.com/32118121">Revit Remote Boot Demonstration</a> from <a href="http://vimeo.com/user2797832">Rod Howarth</a><br />
(you should head to <a href="http://vimeo.com/32118121">the Vimeo page</a> and watch it in high definition there to read the text)<br />
Basically your application can save an xml file in a certain directory, which ads a ‘job’ to the queue. Then, using the RevitServerToolCommand, you can, from a batch file, create a local copy of the Revit Model you want to work on, and open it in Revit. From there, a Revit API add-in will detect that you’ve opened a model that corresponds to a job, and will run the <i>other</i> Revit API add-in that was specified in the job file. After this is done, the job is marked complete, and Revit is closed. <br />
In my example, I’ve done a simple export to DWF of the model, the idea being you could set this up to run at 1am every night, and export the DWF model to a certain location – perhaps for viewing in Design Review on mobile devices. However, you could use it for any Revit API add-in. For instance, you could have a high powered server which you setup as a local Revit Server just purely to run this Revit Remote Boot. On this server you could create a job to run a structural analysis add-in, or other computationally expensive stuff. This way you can setup your own “cloud”, running Revit directly. You could also run certain audits on a model, for example, you could create an add-in that counts the number of warnings present in the model and saves this to a database, for displaying in a ‘hall of shame’ on your company intranet. <img alt="Smile" class="wlEmoticon wlEmoticon-smile" src="http://lh3.ggpht.com/-62YhRvM0jKA/TsIYHrtG-eI/AAAAAAAAAgw/CedFE8AQz0I/wlEmoticon-smile%25255B2%25255D.png?imgmax=800" style="border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none;" /><br />
This is highly experimental, and has some pitfalls, so should be considered as a proof of concept, rather than a production ready program. The main pitfall is that any errors that come up are shown as dialog boxes, and there is no easy way to deal with this in Revit. To get around this I’ve used AutoHotKey (<a href="http://www.autohotkey.com/">http://www.autohotkey.com/</a>) to detect certain dialogs and close them, but if there are unexpected ones, it will fall over. <br />
If you are interested in the code behind this, check it out here: <a href="https://github.com/RodH257/RevitRemoteBoot">https://github.com/RodH257/RevitRemoteBoot</a> you can use the ‘zip’ button there to download it if you don’t have git. <br />
I’d love to hear your thoughts on this, and whether you think Autodesk should work towards making this kind of thing easier to do? <br />
<a class="twitter-follow-button" data-show-count="false" data-size="large" href="https://twitter.com/rodh257">Follow @rodh257</a><br />
<script>
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
</script>Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com1tag:blogger.com,1999:blog-5096437112654914738.post-89252324712692944862011-11-05T00:28:00.001+10:002013-02-02T18:13:49.709+10:00[General Dev]–How to push to two Git remote locations at onceNow that <a href="http://bitbucket.org/">BitBucket</a> supports Git, I’ve been utilizing both <a href="http://github.com/">GitHub</a> and <a href="http://bitbucket.org/">BitBucket</a> for my project hosting, and have been looking into migrating to BitBucket for my private repositories (as they are free). This is part of the beauty of using a distributed version control system, you can have your code in multiple locations, rather than one central Subversion server. <br />
In Git, I could add two remotes and each time I want to push/pull code I would type something like:<br />
git push github master <br />git push bitbucket master<br />
However, I want to make things as easy as possible for myself, and I’m simply using these two repositories as a mirror of each other, so I’ll be telling git to push to multiple URL’s with the same remote.<br />
To do this, I need to edit the .git/config file for my project. You can navigate here via the command line, or in Windows you can turn on hidden file display and open the .git folder in Windows Explorer<br />
<a href="http://lh5.ggpht.com/-kc4ekkFMQ1c/TrPhjStI-GI/AAAAAAAAAeo/q80Yniiru2M/s1600-h/image%25255B11%25255D.png"><img alt="image" border="0" height="245" src="http://lh3.ggpht.com/-lEIsYhRSM1k/TrPhkpOFdfI/AAAAAAAAAew/IqUvRRIZ2Tg/image_thumb%25255B5%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="502" /></a><br />
<a href="http://lh6.ggpht.com/-YCMzYZixU78/TrPhlvcAm3I/AAAAAAAAAe4/gFXF2Ktpw5A/s1600-h/image%25255B12%25255D.png"><img alt="image" border="0" height="252" src="http://lh6.ggpht.com/-qKVShN2UmV4/TrPhmvYsizI/AAAAAAAAAfA/wJ1LjX2aj1U/image_thumb%25255B6%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="508" /></a><br />
In this file, I’ve already added one of my remotes using the git remote add command, as you can see here:<br />
<a href="http://lh5.ggpht.com/-ENzIXT7mHAA/TrPhnvCj9mI/AAAAAAAAAfI/PYrHwKztCwM/s1600-h/image%25255B24%25255D.png"><img alt="image" border="0" height="261" src="http://lh5.ggpht.com/-0kTZPaZxX9A/TrPhpNhB9zI/AAAAAAAAAfQ/45HkJr4dM8U/image_thumb%25255B12%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="522" /></a><br />
To make it push to BitBucket at the same time as GitHub, you simply duplicate this URL line and add the BitBucket URL to it<br />
<a href="http://lh6.ggpht.com/-yHvgeOCpl1k/TrPhp_ZfGzI/AAAAAAAAAfY/Bc-VYFjqLoA/s1600-h/image%25255B28%25255D.png"><img alt="image" border="0" height="261" src="http://lh4.ggpht.com/-V5zDTjQJk-A/TrPhrKmopaI/AAAAAAAAAfg/9lP_i0VFUmc/image_thumb%25255B14%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="522" /></a><br />
Then if you do a git push origin master (where master is name of your branch), you will see it will push to these URLs in succession:<br />
<a href="http://lh6.ggpht.com/-8TquvoTb6yk/TrPhsHQyMaI/AAAAAAAAAfo/EBFp1HKQD0I/s1600-h/image%25255B32%25255D.png"><img alt="image" border="0" height="239" src="http://lh4.ggpht.com/-gc0QPguhhWo/TrP2cijOjPI/AAAAAAAAAf4/AeWxMrhVbCw/image_thumb%25255B16%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="530" /></a><br />
Unfortunately if you have a password protected ssh key it will still ask twice for your password.<br />
Now each time you push to your origin remote, you’ll be taking full advantage of gits distributed nature, and will have two remote copies of your code.Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com5tag:blogger.com,1999:blog-5096437112654914738.post-21504970657212806812011-10-03T12:36:00.001+10:002011-10-03T12:36:17.898+10:00[Revit]– HTML Version of the Silverlight Revit Server Administrator Tool<p>If you’ve used Revit Server Before, you might recognize this:</p> <p><a href="http://lh6.ggpht.com/-BwsICbQSwmM/TokflfOrSoI/AAAAAAAAAeM/Leniz0nSGqI/s1600-h/image%25255B3%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-d2C862C-cgU/TokfmfmDVBI/AAAAAAAAAeQ/vy4GF36B_jg/image_thumb%25255B1%25255D.png?imgmax=800" width="688" height="477" /></a></p> <p>It’s the Revit Server Administrator Tool which you access by going to <a href="http://servername/revitserveradmin">http://servername/revitserveradmin</a> it lets you see what Revit Server projects you have present, what files are stored in them, and their version history. It also lets you create, move, copy, delete or lock files and folders. </p> <p>It’s a vital tool for anyone who runs a Revit Server, and it generally works well, but it has one problem – it’s written in Silverlight. Whatever your opinion on Silverlight may be, it requires an extra installation and won’t run on any mobile devices. This is where the Revit Server API comes in. Using this REST API, I was able to recreate this website in HTML and Javascript. The result looks like this:</p> <p><a href="http://lh3.ggpht.com/-M98Tw0ABSDw/TokfnGR9qvI/AAAAAAAAAeU/3gqjuywQ6fU/s1600-h/image%25255B13%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-9rsPWrqQeo8/TokfoL0mdjI/AAAAAAAAAeY/GuORhKNh3_A/image_thumb%25255B7%25255D.png?imgmax=800" width="728" height="560" /></a></p> <p>As my main motivation for this was to give the Revit Server REST API a run through, I’ve not made it absolutely the same, there are some minor visual and functional differences, but for the most part, it behaves in the same way. All of the action buttons are functional, you can see a submission history and folder structure. </p> <p>For the moment, the main limitations are:</p> <ul> <li>When you create or paste a folder, the treeview on the left gets recreated and starts collapsed again. This is fixable, and if there is interest, I’ll polish this up (probably by replacing the treeview library with a new one)</li> <li>The submission history isn’t paged or sortable, its just a table with all the information in it. This should be fixable as well. </li> </ul> <p>I’m interested to hear if anyone is genuinely interested in using this tool in their environment, if so, I’ll keep improving it, if not, then it will serve as a demonstration of the Revit Server API’s capabilities, and will form a part of <a href="http://blog.rodhowarth.com/2011/09/revit-autodesk-university-2011-virtual.html">my AU Virtual session</a> this year.</p> <p><strong>The website is available </strong><a href="https://github.com/RodH257/RevitServerHtmlAdmin"><strong>on Github</strong></a><strong>, to install it on your server simply download the zip file from that site, and create a folder called ‘html’ in ‘C:\Program Files\Autodesk\Revit Server 2012\Sites\RevitServerAdmin’ on the machine you have Revit Server installed. Put all the files in there, and you should be able to navigate to </strong><a href="http://localhost/RevitServeradmin/html/"><strong>http://localhost/RevitServeradmin/html/</strong></a><strong> to access it. </strong></p> <p>For those interested in the technical details, the page is simple HTML (it’s named Default.aspx even though it isn’t an ASP.NET web page, it’s named this way because this allows us to access it by going to /html/ instead of /html/default.htm), with a CSS stylesheet and some images to replicate the interface of the Silverlight tool. The real work happens in the RevitServer.js file, which, with the help of Jquery, calls the REST web service for each of the various actions that the user performs, and updates the DOM with the results. There is no server side ASP.NET code involved, it’s all Javascript with the Revit Server REST API doing the heavy lifting. </p> <p>Of course, if you want to use the Revit Server API, you don’t need to use Javascript, you could write a similar thing in C# or VB code and service up in an ASP.NET web page, or just about any language you like as long as they can make HTTP Requests. </p> <p>If you want to know more about how it all works, or more about the Revit Server API, I’ll be going into more detail in my <a href="http://blog.rodhowarth.com/2011/09/revit-autodesk-university-2011-virtual.html">AU 2011 Virtual session</a>. </p> Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com4tag:blogger.com,1999:blog-5096437112654914738.post-90064728777891025622011-09-30T01:04:00.001+10:002011-09-30T01:04:06.990+10:00[Revit Server]– How to get a listing of all Revit Server projects through the REST interface<p>I’ve been writing some code that utilizes the Revit Server REST API, and in particular, I’m working on a HTML replacement for the Revit Server Admin page, which is currently written in Silverlight. More details on that will come (and will be included in my <a href="http://blog.rodhowarth.com/2011/09/revit-autodesk-university-2011-virtual.html">AU virtual class</a>), but for now I ran into a bit of a stumbling block that others may encounter. </p> <p>The REST API has an endpoint that lets you list the contents of a certain folder. This endpoint requires a GET request to the path ‘/{folderpath}/contents’ with folderpath being the path of your folder, for example a request to ‘/My_Project/contents’ would list the contents of the My_Project folder. But how do you find out that there is a My_Project folder in the first place? You need to get a listing of all of the folders underneath the parent folder on the server, but how would you do that? You can’t send you request to ‘/contents’, as you are missing the folder path section, and thus it’s not a valid endpoint according to the API. I tried a number of different combinations of URL’s before I finally found one that seems to work.</p> <p>To get a listing of all the folders underneath the parent folder, send your GET request to:</p> <p><strong>‘/ /contents’</strong></p> <p>That is, use a space instead of a folder path, like so:</p> <p>“<a href="http://localhost/RevitServerAdminRESTService/AdminRESTService.svc/">http://localhost/RevitServerAdminRESTService/AdminRESTService.svc/</a> /contents” </p> <p>This will be treated as if it is the root folder, and will list the folders underneath that. </p> Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com0tag:blogger.com,1999:blog-5096437112654914738.post-23548818416354372382011-09-30T00:56:00.001+10:002011-09-30T00:56:47.819+10:00[Revit]– Autodesk University 2011 Virtual Class: Automating Autodesk Revit Server<p>The Autodesk University conference in Las Vegas is approaching us once again. I’ve had the great privilege of presenting at this event for the past two years on topics concerning the Revit API. At this stage it doesn’t look like I’ll be making the trip from Australia this year to attend the physical conference, but that hasn’t stopped me from being involved virtually! I’ve been accepted to present a class on “<a href="http://au.autodesk.com/?nd=event_class&session_id=9580&jid=1747607">Automating Autodesk Revit Server</a>”.  Here is the class description:</p> <h3>Class Description</h3> <p>The latest version of Revit Server offers a number of automation capabilities, from locking files and creating directories to generating a new local file for a Revit central model. This class will explore these options and consider some scenarios where they can be leveraged along with existing Microsoft® Windows® and Revit APIs to perform time-saving tasks. A number of examples will be showcased, including how to create a HTML replacement for the Silverlight® admin tool, how to create a Revit Server folder from an existing system, and how it is possible to have a scheduled task that runs once a day, creates a local file, opens it, and exports the model to a DWF™ without user interaction.</p> <h3>Key Learning</h3> <ul> <li>Explain how Revit server automation can be integrated into existing software processes </li> <li>Describe the REST interface to Revit Server </li> <li>Combine the Revit Server command line and the Revit API to perform a task in a Revit model on a schedule </li> <li>Use the supplied command line utilities to automate Revit Server</li> </ul> <p>The idea for this class came about when I was playing around with Revit Server and noticed that there is a document on the REST API in the Revit SDK. I had a few ideas for interesting things to do with this API, and Revit Server in general, and what better motivation to put them into action than the pressure of presenting an AU class on the topic :) </p> <p>Virtual classes only go for 45 minutes, so the code will mostly be read through and explained rather than written live, but I’ll have a bunch of code available for download and in the handout. </p> <p>If you are interested in Revit Server, be sure to check it out! If you aren’t, but are interested in Revit API development, check out the <a href="http://thebuildingcoder.typepad.com/blog/2011/09/revit-and-aec-api-classes-at-autodesk-university.html">various other Revit API classes</a> that will be a part of the event, the Revit API team have once again put together a great curriculum to help you get as much API knowledge as you can out of AU. </p> Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com0tag:blogger.com,1999:blog-5096437112654914738.post-81864098589698382432011-08-22T15:37:00.002+10:002011-08-22T15:40:00.018+10:00[Revit API]–How to create an installer for your Revit AddinsOften I see Revit API utilities distributed with instructions to copy manifest files around and put the files in a certain directory (I’ve done it myself in the past), which works fine, but there is a more user friendly way of setting up your addins. You can use Visual Studios ‘Setup Project’ functions to create an installer, which isn’t the pretties installer going around, but it gets the job done. <br />
Doing this is a little harder than you’d think, there’s a few gotchas, so this post aims to step you through it. <br />
Add a new project to your solution, under ‘Other Project Types’, ‘Setup and Deployment’ choose ‘Setup Project’.<br />
<a href="http://lh3.ggpht.com/-JQpQ0ocZ6nU/TlHqyhirLZI/AAAAAAAAAdE/gQ9M-CBox9U/s1600-h/image%25255B50%25255D.png"><img alt="image" border="0" height="419" src="http://lh6.ggpht.com/-nWDBnla_e2Q/TlHqznES3jI/AAAAAAAAAdI/EgnNvb1I6GQ/image_thumb%25255B30%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="604" /></a><br />
You’ll see a view like this, delete ‘Users Desktop’, ‘User Programs Menu’<br />
<a href="http://lh5.ggpht.com/-Qvedl6BpyUU/TlHq0vEx3MI/AAAAAAAAAdM/3AX2XMpmzmE/s1600-h/image%25255B49%25255D.png"><img alt="image" border="0" height="615" src="http://lh3.ggpht.com/-LtHRzJWmBtg/TlHq1oxjZnI/AAAAAAAAAdQ/nhBbz65Na8I/image_thumb%25255B29%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="605" /></a><br />
Right click on Application folder and go to add > project output. Choose the Addin project.<br />
<a href="http://lh3.ggpht.com/-oUCYd2igzpE/TlHq2VPkARI/AAAAAAAAAdU/bGP-3P1AnKU/s1600-h/image%25255B30%25255D.png"><img alt="image" border="0" height="361" src="http://lh6.ggpht.com/-CrqaE9EL_aA/TlHq3G9kufI/AAAAAAAAAdY/Od186oc3MLk/image_thumb%25255B16%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="313" /></a><br />
Right click on application folder again, go to properties and change the DefaultLocation to be:<br />
<em>[ProgramFiles64Folder][Manufacturer]\[ProductName] </em><br />
This is so that it will always be in a consistent install location, rather than program files (x86). <br />
Now, we don’t want to distribute RevitAPI and RevitAPIUI dlls, so in the solution explorer, expand detected dependencies and right click on those and click exclude.<br />
<a href="http://lh5.ggpht.com/-qomA72fUmwQ/TlHq4f-uhpI/AAAAAAAAAdc/7lNmPhGmAqw/s1600-h/image%25255B48%25255D.png"><img alt="image" border="0" height="386" src="http://lh5.ggpht.com/-NYUSknOH8uI/TlHq5IpLelI/AAAAAAAAAdg/-s2o-quXE38/image_thumb%25255B28%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="624" /></a><br />
Click on the installer project, then click the properties tab, and set the ‘Manufacturer’ and ‘ProductName’ to match your company/addin name. Also, while you are here, change the ‘TargetPlatform’ to X64. Unfortunately with these types of installers you need a separate install for X86 and X64, but I think most of you will be building API addins for X64 systems, as Revit generally needs at least 4gb of RAM, and if you are enough of a power user to be installing add-ins, you are going to be running a 64bit operating system I’m sure. But keep in mind that it may vary for you. <br />
We need to create a .addin manifest file that points to the program files folder as follows, make sure you generate a new GUID. <br />
<RevitAddIns> <br /> <AddIn Type="Command"> <br /> <Text>My Revit Util</Text> <br /> <Assembly>C:\Program Files\COMPANY NAME\PRODUCT NAME\Addin.dll</Assembly> <br /> <AddInId>18520534-3ee1-473e-ae97-a68dfbda3754</AddInId> <br /> <FullClassName>MyRevitUtil.Command</FullClassName><br />
<VendorId>COMP </VendorId><br />
<VendorDescription>MY COMPANY </VendorDescription> <br /> </AddIn> <br /></RevitAddIns><br />
<br />
In The primary output screen, add a new custom folder, called Autodesk Addins. Right click on it and go to properties and set the DefaultLocation to<br />
<em>[CommonAppDataFolder]\Autodesk\Revit\Addins\2012</em><br />
and Property to AUTODESKADDINS<br />
This will install it for all users. Right click in the middle panel and go to add file, and choose your manifest. <br />
<a href="http://lh4.ggpht.com/-JKlzF7v11yk/TlHq6QTlssI/AAAAAAAAAdk/5QYla7Wjqoc/s1600-h/image%25255B47%25255D.png"><img alt="image" border="0" height="571" src="http://lh4.ggpht.com/-fpzzKx6AjjY/TlHq7QzFnbI/AAAAAAAAAdo/9AQr2hn3YS4/image_thumb%25255B27%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="598" /></a><br />
At this point you’re almost done, there’s just a couple of .NET settings to tweak. First of all, we don’t need to bundle an installer for .NET framework as Revit installs it by default, so right click on your installer project, go to properties and hit prerequisites<br />
<a href="http://lh3.ggpht.com/-kY-7XxDnFqk/TlHq8CyBObI/AAAAAAAAAds/4w-vpB2PNH0/s1600-h/image%25255B46%25255D.png"><img alt="image" border="0" height="426" src="http://lh3.ggpht.com/-XBq0zfaK0uE/TlHq9OLR37I/AAAAAAAAAdw/Ru_ZpXx-vVI/image_thumb%25255B26%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="596" /></a><br />
Then untick the first checkbox<br />
<a href="http://lh6.ggpht.com/-yU3mO8f9l8w/TlHq97uJhRI/AAAAAAAAAd0/3NqfdD8PRDA/s1600-h/image%25255B45%25255D.png"><img alt="image" border="0" height="464" src="http://lh4.ggpht.com/-0TLuJ23BDDs/TlHq--_nI9I/AAAAAAAAAd4/Ey3ETlfg9GY/image_thumb%25255B25%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="597" /></a><br />
Finally, right click on your project, click View > Launch Conditions, click .NET framework and change it to .NET Framework 4 (or lower if you are in Revit 2011 mode still).<br />
<a href="http://lh5.ggpht.com/-jLcaF7u2msY/TlHq_7P8LwI/AAAAAAAAAd8/x91tp4w66Bo/s1600-h/image%25255B36%25255D.png"><img alt="image" border="0" height="566" src="http://lh4.ggpht.com/-BqS50SUSIuU/TlHrA2XfnrI/AAAAAAAAAeA/4-oh4fPoPMQ/image_thumb%25255B20%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="593" /></a><br />
Now you are done, you can right click your project and go to Build and your .msi installer will be output.Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com1tag:blogger.com,1999:blog-5096437112654914738.post-2538503414882288722011-08-01T11:45:00.000+10:002011-08-01T11:45:10.221+10:00[WPF]–How to select checkbox of items in ListBox by clicking textIn WPF, you can create a checked list box by creating a normal ListBox and using an ItemTemplate as follows:<br />
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><ListBox Margin=<span style="color: #006080;">"10"</span> HorizontalAlignment=<span style="color: #006080;">"Stretch"</span> Name=<span style="color: #006080;">"lbSheets"</span> </pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> VerticalAlignment=<span style="color: #006080;">"Stretch"</span> Width=<span style="color: #006080;">"Auto"</span> Grid.Row=<span style="color: #006080;">"1"</span> MinWidth=<span style="color: #006080;">"321"</span></pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> MinHeight=<span style="color: #006080;">"40"</span> HorizontalContentAlignment=<span style="color: #006080;">"Left"</span> </pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> ItemTemplate=<span style="color: #006080;">"{StaticResource ListBoxItemTemplate}"</span> VerticalContentAlignment=<span style="color: #006080;">"Top"</span> Background=<span style="color: #006080;">"#FFDCEBEE"</span> SelectionMode=<span style="color: #006080;">"Single"</span> SelectionChanged=<span style="color: #006080;">"lbSheets_SelectionChanged"</span>></pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> </pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> </ListBox></pre>
</div>
</div>
<br />
<br />
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><DataTemplate x:Key=<span style="color: #006080;">"ListBoxItemTemplate"</span> ></pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> </pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> <WrapPanel></pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> <CheckBox Focusable=<span style="color: #006080;">"False"</span> IsChecked=<span style="color: #006080;">"{Binding Selected}"</span> VerticalAlignment=<span style="color: #006080;">"Center"</span> /></pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> <ContentPresenter Content=<span style="color: #006080;">"{Binding FullName, Mode=OneTime}"</span> Margin=<span style="color: #006080;">"2,0"</span> /></pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> </WrapPanel></pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> </pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> </DataTemplate></pre>
</div>
</div>
<br />
In my example, I am then binding a domain model object that implements INotifyPropertyChanged, and I have a boolean property for Selected, when the checkbox is checked, it will toggle this value, and vice versa. The text that is displayed is from a property called ‘FullName’, as specified in the DataTemplate.<br />
<a href="http://lh3.ggpht.com/-KNXnGSFJ_xQ/TjYCzvmyeKI/AAAAAAAAAck/rfwksi1JQKE/s1600-h/image%25255B3%25255D.png"><img alt="image" border="0" height="346" src="http://lh3.ggpht.com/-LQc2VL49iR4/TjYC0ihq1zI/AAAAAAAAAco/EQqtIBjjipI/image_thumb%25255B1%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="346" /></a><br />
<br />
However, I wanted to be able to check the checkboxes by clicking on the text next to them, not by pinpointing the check box. I tried a number of ways of doing this before finally arriving at a solution.<br />
I ended up suing the ‘MouseUp’ event on the ContentPresenter from my DataTemplate <br />
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><DataTemplate x:Key=<span style="color: #006080;">"ListBoxItemTemplate"</span> ></pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> </pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> <WrapPanel></pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> <CheckBox Focusable=<span style="color: #006080;">"False"</span> IsChecked=<span style="color: #006080;">"{Binding Selected}"</span> VerticalAlignment=<span style="color: #006080;">"Center"</span> /></pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> <ContentPresenter Content=<span style="color: #006080;">"{Binding FullName, Mode=OneTime}"</span> Margin=<span style="color: #006080;">"2,0"</span> MouseUp=<span style="color: #006080;">"ContentPresenter_MouseUp"</span> /></pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> </WrapPanel></pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> </pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> </DataTemplate></pre>
</div>
</div>
And in this method I did the following:<br />
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">private</span> <span style="color: blue;">void</span> ContentPresenter_MouseUp(<span style="color: blue;">object</span> sender, MouseButtonEventArgs e)</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> <span style="color: blue;">string</span> text = ((TextBlock) e.OriginalSource).Text;</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> </pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> <span style="color: blue;">foreach</span> (var item <span style="color: blue;">in</span> <span style="color: blue;">this</span>.lbSheets.Items)</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> {</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> PrintableSheet sheetItem = (PrintableSheet) item;</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> <span style="color: blue;">if</span> (sheetItem.FullName.Equals(text))</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> {</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> sheetItem.Selected = !sheetItem.Selected;</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> }</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> }</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> </pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre>
</div>
</div>
I used the OriginalSource proprety from the event arguments to get the TextBlock, I used its text, and matched it up with my domain object (PrintableSheet) using the property that was bound. So now when you click the text on the item, it will toggle the checkbox.Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com5tag:blogger.com,1999:blog-5096437112654914738.post-23651663027226655672011-07-15T18:42:00.001+10:002011-07-15T18:48:31.894+10:00[General]– ‘Convoy’ iPhone app now live on the App StoreIt’s been a bit quiet around here for a while – I apologize for the lack of posts. I’ve been busy working on a number of things that have sapped all of my time. Firstly, I created the iPhone apps for the <a href="http://revitconference.com.au/">Revit Technology Conference</a>, these were proposed in the 11th hour, so they were fairly simple – but were well received. <br />
<br />
My next mobile project has been under development for a number of months now, and I’m proud to say that it is now live on the iOS app store. The project is called ‘<a href="http://convoyapp.net/">Convoy</a>’, and is an iPhone application designed to make driving in a ‘convoy’ a less stressful experience. Over the years I’ve come across a number of situations where myself and a group of people would be heading somewhere, be it one of Queensland’s great beaches, or a theme park, or a friends house, and someone will know the way, so everyone will try to follow them. Inevitably the group breaks up, and it becomes a stressful game of phone tag to try and organize everyone. <a href="http://convoyapp.net/">Convoy</a> aims to solve this. <br />
<br />
Check out this promo video for an in depth explanation of the problem and how it solves it:<br />
<div class="wlWriterEditableSmartContent" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:624fc3b8-2e3a-4511-aab5-955f044c307f" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">
<div id="5caa3010-d365-4caa-a1ad-b89b369a9515" style="display: inline; margin: 0px; padding: 0px;">
<div>
<a href="http://www.youtube.com/watch?v=KuTFoV8son4" target="_new"><img alt="" galleryimg="no" onload="var downlevelDiv = document.getElementById('5caa3010-d365-4caa-a1ad-b89b369a9515'); downlevelDiv.innerHTML = "<div><object width=\"564\" height=\"317\"><param name=\"movie\" value=\"http://www.youtube.com/v/KuTFoV8son4?hl=en&hd=1\"><\/param><embed src=\"http://www.youtube.com/v/KuTFoV8son4?hl=en&hd=1\" type=\"application/x-shockwave-flash\" width=\"564\" height=\"317\"><\/embed><\/object><\/div>";" src="http://lh3.ggpht.com/-ERFDYyltZNQ/Th_9HTLC1KI/AAAAAAAAAUA/x2ywcgdBkXE/videoee16f20548e6%25255B32%25255D.jpg?imgmax=800" style="border-style: none;" /></a></div>
</div>
<div style="clear: both; font-size: .8em; width: 564px;">
Convoy Promo Video</div>
</div>
<br />
Basically, the application lets you create a new Convoy on our server, which will give you a unique code to give to your friends. They enter the code into their devices and they are then presented by a map which updates ever 5 seconds with the locations of your peers. Additionally, you can then communicate with everyone in the Convoy at once using the quick communication buttons. There is a button two identify a location to pull over for a pit stop, and a button to indicate hazards. You simply tap on the map where you want to indicate, and this location is shown on everyones screens. If you need to send a more detailed message, there is a group messaging feature. <br />
<br />
The app is currently completely free. I’ve got plans to make a ‘lite’, advertising supported version in which you can only join Convoys but not create them, and then charge a small amount for the current, full version – so get in quick and grab it while it’s free. <br />
<br />
<span style="font-size: medium;"><strong>You can check out the website for the app at </strong></span><a href="http://convoyapp.net/"><span style="font-size: medium;"><strong>ConvoyApp.net</strong></span></a><span style="font-size: medium;"><strong>, or see it </strong></span><a href="http://budurl.com/convoyIOS"><span style="font-size: medium;"><strong>live on the iTunes app store</strong></span></a><span style="font-size: medium;"><strong>. For fellow Android fans, I’ve got an Android version in the works, stay tuned. </strong></span><br />
<strong><span style="font-size: medium;"></span></strong><br />
For those interested in the technical details, I’ll make a post soon outlining the various libraries and web services that I used for this app and my experiences with them. But briefly, the back end uses NodeJS (hosted on Heroku), MongoDB (hosted on MongoHQ) and Amazon S3 (for icon storage). I’ve used a bunch of great open source Objective C libraries as well which I look forward to writing about. <br />
<br />
Let me know what you think, if you have an suggestions I’d love to hear them, my email address is listed <a href="http://rodhowarth.com/">HERE</a>.<br />
<br />
PS, I would have loved to have licensed the <a href="http://www.youtube.com/watch?v=xdc0Oq1VwH4">Convoy song</a> for the video, but it wasn’t to be :)Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com2tag:blogger.com,1999:blog-5096437112654914738.post-20264693552601433992011-05-17T07:35:00.000+10:002011-05-17T11:19:27.704+10:00[Revit API]–API Wishlists<p>The yearly Autodesk API wish list surveys are available online now, I encourage you to fill them out to help shape future releases of the API.</p> <p>AutoCAD <br /><a href="http://www.zoomerang.com/Survey/WEB22C9QA2TDYR">http://www.zoomerang.com/Survey/WEB22C9QA2TDYR</a></p> <p>Autodesk Inventor <br /><a href="http://www.zoomerang.com/Survey/WEB22C9QBPTEZ5">http://www.zoomerang.com/Survey/WEB22C9QBPTEZ5</a></p> <p><strong>Autodesk Revit <br /></strong><a href="http://www.zoomerang.com/Survey/WEB22C9QACTE6V"><strong>http://www.zoomerang.com/Survey/WEB22C9QACTE6V</strong></a></p> <p>AutoCAD Civil 3D <br /><a href="http://www.zoomerang.com/Survey/WEB22C9Q8JTD3G">http://www.zoomerang.com/Survey/WEB22C9Q8JTD3G</a></p> <p>Autodesk Navisworks <br /><a href="http://www.zoomerang.com/Survey/WEB22C9QBRTF2C">http://www.zoomerang.com/Survey/WEB22C9QBRTF2C</a></p> Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com0tag:blogger.com,1999:blog-5096437112654914738.post-71604035250072696102011-05-08T00:05:00.001+10:002011-05-08T00:05:29.233+10:00[Revit] Running a local Revit Server on Windows 7 safely–free utility<p>Autodesk Revit Server is a product that comes bundled with Revit 2011 and 2012. It provides a way for you to better coordinate Revit access over a wide area network by hosting your central model in Revit Server and connecting your Revit to that instead of opening a .rvt file on a network drive. This is particularly useful for companies with multiple offices, as Revit Server allows you to setup a ‘central’ server and ‘local’ servers are different locations. Saves to the Local servers are done over a LAN, and the local server then synchronizes the model back to the central server in an optimized fashion. Thus providing an alternative to expensive WAN optimization devices such as those provided by Riverbed. </p> <p> <br />One usage instance that many people are interested in, is having a local Revit server instance installed on their laptop for when they work remotely. That way saves to central over a VPN are done quickly, and Revit Server will synchronize the model back to the office in the background. The problem is, Revit Server only supports Windows Server 2008 R2, which is very expensive. However there is a way around this, you can, unofficially install Revit Server on your Windows 7 computer. I’ve had success in getting this setup, and <a href="http://do-u-revit.blogspot.com/2011/04/revit-server-goes-desktop.html">so has Dave Baldacchino</a> from the blog <a href="http://do-u-revit.blogspot.com/">Do U Revit</a>. Check out <a href="http://do-u-revit.blogspot.com/2011/04/revit-server-goes-desktop.html">his post</a> on the topic and read the ‘setup’ section for instructions on how you can get it running. There is some danger in this approach, as Robert from the blog <a href="http://dorevit.blogspot.com/2011/05/taking-revit-server-off-road.html">‘Don’t think: Do Revit’</a> warns, that shutting the server down while it is still trying to synchronize back to the central server <a href="http://dorevit.blogspot.com/2011/05/taking-revit-server-off-road.html">can cause some issues.</a> </p> <p>This is a problem, as Revit Server has no inbuilt way to tell when it is synchronizing. To solve this issue, I’ve created a small utility that sits in your system tray, and tells you when Revit Server is communicating with anyone. I call it ‘Revit Server Monitor’</p> <p><a href="http://lh6.ggpht.com/_PZEkMtbO9tU/TcVRmLLgYTI/AAAAAAAAAOY/PzajWU-l__Y/s1600-h/image%5B3%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_PZEkMtbO9tU/TcVRnI4qDWI/AAAAAAAAAOc/06B3VQd73Wk/image_thumb%5B1%5D.png?imgmax=800" width="485" height="194" /></a></p> <p>You run the program, and minimize it to your computers tray. You will then see a green arrow to indicate that the Revit Server is not currently communicating with anyone.</p> <p><a href="http://lh3.ggpht.com/_PZEkMtbO9tU/TcVRn79aG-I/AAAAAAAAAOg/18pWr3SjOac/s1600-h/image%5B6%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_PZEkMtbO9tU/TcVRomEMfhI/AAAAAAAAAOk/cn0RggPEQ-Q/image_thumb%5B2%5D.png?imgmax=800" width="243" height="39" /></a></p> <p>Or if any sort of communication is in progress, you will see a red arrow. </p> <p><a href="http://lh3.ggpht.com/_PZEkMtbO9tU/TcVRpOPhULI/AAAAAAAAAOo/VaaTOZ1JfUc/s1600-h/image%5B9%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_PZEkMtbO9tU/TcVRp8TZCSI/AAAAAAAAAOs/TLB1tzIKB3M/image_thumb%5B3%5D.png?imgmax=800" width="244" height="43" /></a></p> <p>So if there is a red arrow, don’t shut your computer down. Wait for a green arrow to be safe. </p> <p>This works by reading port 808, which is the primary port that Revit Server uses to communicate. Using the WinPCap utility, my code can monitor traffic on this port, if it detects any, it will show the red signal. If there has been no traffic on that port for 5 seconds, the signal will turn green. You can download the tool from <a href="http://rodhowarth.com/Downloads/Software/RevitServerMonitorv0.2.zip">here</a>. To set it up, you must first install WinPCap, which is included in the zip, and then just run the RevitServerMonitor exe (perhaps add it to your computers startup folder as well so you don’t forget to run it). The program itself requires .NET 3.5 to run, but if you have Revit installed you will have that installed as well. If you are a little worried about having software that monitors packets running on your PC, feel free to <a href="https://github.com/RodH257/RevitServerMonitor">browse the source code here</a>, it’s fairly simple!</p> <p>If you are running a Revit Server on your Windows PC, do try it and let me know how it goes, I’m not guaranteeing it will prevent model corruption but I’d love to hear your feedback on how well it worked.</p> <p><a href="http://rodhowarth.com/Downloads/Software/RevitServerMonitorv0.2.zip">Download the software here.</a></p> <p><a href="https://github.com/RodH257/RevitServerMonitor">View the source code here.</a></p> Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com4tag:blogger.com,1999:blog-5096437112654914738.post-13855560736901494832011-05-03T17:00:00.001+10:002011-05-03T17:00:30.431+10:00[Revit API] How to allow add-ins to be loaded off a network drive, in code<p>I previously posted about how in Revit 2012, you can no longer store your add-ins on a network drive, unless you edit the revit.exe.config. This is a bit of a pain if you have to go to each users machine and edit this file individually, especially given that if you make a typo, your Revit won’t open.</p> <p>Here’s how to do this edit in C# code, so if you make an installation utility to run on your users computers, you can add this bit of code in to do the changes for you.</p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">Configuration revitExeConfig = ConfigurationManager.OpenExeConfiguration(</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #006080">@"C:\Program Files\Autodesk\Revit Structure 2012\Program\Revit.exe"</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">ConfigurationSection section = revitExeConfig.GetSection(<span style="color: #006080">"runtime"</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">string</span> xml = section.SectionInformation.GetRawXml();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">if</span> (!xml.Contains(<span style="color: #006080">"<loadFromRemoteSources enabled=\"true\" />"</span>))</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> xml = xml.Replace(<span style="color: #006080">"<runtime>"</span>, <span style="color: #006080">"<runtime> \r\n <loadFromRemoteSources enabled=\"true\" />"</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> section.SectionInformation.SetRawXml(xml);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> revitExeConfig.Save();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre>
<!--CRLF--></div>
</div>
<p> </p>
<p>Of course, I’ve hard coded in Revit Structure 2012 here as Revit installation to edit. You could change this to the installation that suits yours, or alternatively you could use the RevitAddinUtility.dll that ships with Revit. If you add a reference to that to your project you can then get the install location of all Revit products using:</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">foreach</span> (RevitProduct product <span style="color: #0000ff">in</span> RevitProductUtility.GetAllInstalledRevitProducts())</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #008000">//no point editing the Revit 2011 exe config files</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (product.Version == RevitVersion.Revit2012)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">string</span> productLocation = product.InstallLocation + <span style="color: #006080">"program\\revit.exe"</span>;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre>
<!--CRLF--></div>
</div>
<p> </p>
<p>If you put that all together with the above code you can do something like:</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> EditExeConfigs()</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">foreach</span> (RevitProduct product <span style="color: #0000ff">in</span> RevitProductUtility.GetAllInstalledRevitProducts())</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #008000">//no point editing the Revit 2011 exe config files</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (product.Version == RevitVersion.Revit2012)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">string</span> productLocation = product.InstallLocation + <span style="color: #006080">"program\\revit.exe"</span>;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Configuration revitExeConfig = ConfigurationManager.OpenExeConfiguration(productLocation);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> ConfigurationSection section = revitExeConfig.GetSection(<span style="color: #006080">"runtime"</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">string</span> xml = section.SectionInformation.GetRawXml();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (!xml.Contains(<span style="color: #006080">"<loadFromRemoteSources enabled=\"true\" />"</span>))</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> xml = xml.Replace(<span style="color: #006080">"<runtime>"</span>, <span style="color: #006080">"<runtime> \r\n <loadFromRemoteSources enabled=\"true\" />"</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> section.SectionInformation.SetRawXml(xml);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> revitExeConfig.Save();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre>
<!--CRLF--></div>
</div>
<p>Which will edit the exe.config file for all 3 Revit products if they are installed, or do nothing if they aren’t. </p> Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com0tag:blogger.com,1999:blog-5096437112654914738.post-37939025707930345782011-04-27T18:08:00.000+10:002011-04-27T18:08:40.746+10:00[General Dev]–Using Git with an SVN server<a href="http://git-scm.com/" target="_blank">Git</a> is a great version control system, one which has <a href="http://whygitisbetterthanx.com/" target="_blank">many benefits over Subversion</a>. However, many companies may already have existing Subversion setups that they are reluctant to move away from. In our office we use <a href="http://www.visualsvn.com/server/" target="_blank">VisualSVN</a> server and the <a href="http://www.jetbrains.com/teamcity/" target="_blank">TeamCity</a> continuous integration server, and while we could migrate fully to Git, I don’t want to make the jump just yet, as I’m the only Git convert here – for now. <br />
Enter <a href="http://www.kernel.org/pub/software/scm/git/docs/git-svn.html" target="_blank">Git SVN</a>. Git SVN allows you to use a local git repository with a remote subversion server. This means that you can initialize git and commit like crazy, and then when you are ready to share your changes with the rest of your team, you synchronize them with the Subversion server. <br />
This is not without its pitfalls – they are two very different version control systems, so if you are doing complex things with them, you may run into some troubles. However where I work we have small teams, and many of my projects are done solely by me, so Git SVN works out great for us, as the main reason for pushing the code to the Subversion server is so that it’s backed up and easily retrieved in the future. <br />
I’ve run into a few issues at times with setting this up, so I thought that I’d create a quick guide for how I am now doing it on new projects. <br />
First of all, I create my subversion repository in VisualSVN. <br />
<a href="http://lh6.ggpht.com/_PZEkMtbO9tU/TZqYgkDVyQI/AAAAAAAAALQ/CZwrYlex2wA/s1600-h/image%5B6%5D.png"><img alt="image" border="0" height="212" src="http://lh6.ggpht.com/_PZEkMtbO9tU/TZqYhQbCYAI/AAAAAAAAALU/auOjRLKjCIM/image_thumb%5B2%5D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="382" /></a><br />
I like to setup the standard SVN directory structure, and Git SVN can accommodate this. <br />
I then open a git bash at the parent folder of where my project will go (or where it currently is – this still works if you’ve already created your solution/folders, as long as they are named the same, or you move the files).<br />
run the command ‘git svn clone –s URL’ where URL is the path to your subversion server. I’ve found that this must be in all lowercase. The –s tag specifies that you are using the standard SVN directory structure – emit this if you didn’t create it when you setup your repository. <br />
<a href="http://lh6.ggpht.com/_PZEkMtbO9tU/TZqYiQASuMI/AAAAAAAAALY/0qZGdXlsEaM/s1600-h/image%5B10%5D.png"><img alt="image" border="0" height="310" src="http://lh3.ggpht.com/_PZEkMtbO9tU/TZqYjWazz7I/AAAAAAAAALc/EmCKfkWl-ME/image_thumb%5B4%5D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="518" /></a><br />
This command will then check out your subversion repository into a directory of the same name as the repository – it will either create this, or use an existing one if it has the same name. <br />
Next, make sure your .gitignore file is setup in the directory and then cd into it with ‘cd REPOSITORY_NAME’. Git status will show you the current files ready to be checked in.<br />
<a href="http://lh4.ggpht.com/_PZEkMtbO9tU/TZqYkXH0yrI/AAAAAAAAALg/XFAelAubj_4/s1600-h/image%5B14%5D.png"><img alt="image" border="0" height="238" src="http://lh3.ggpht.com/_PZEkMtbO9tU/TZqYlMxMPFI/AAAAAAAAALk/3eTV4Mek_Ag/image_thumb%5B6%5D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="397" /></a><br />
Then you should be able to do your first git commit <br />
<a href="http://lh4.ggpht.com/_PZEkMtbO9tU/TZqYl38aTbI/AAAAAAAAALo/jtS6E1Lla5s/s1600-h/image%5B18%5D.png"><img alt="image" border="0" height="173" src="http://lh4.ggpht.com/_PZEkMtbO9tU/TZqYmvkPYJI/AAAAAAAAALs/1pB4B_gcZ-s/image_thumb%5B8%5D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="464" /></a><br />
Now your local git repository is up to date – so you are doing version control, and you can go along like this checking in regularly, then when it’s time to send the commits to the server, use ‘git svn dcommit’ <br />
<a href="http://lh6.ggpht.com/_PZEkMtbO9tU/TZqYnR3C5II/AAAAAAAAALw/nzejUBMBqx4/s1600-h/image%5B22%5D.png"><img alt="image" border="0" height="337" src="http://lh3.ggpht.com/_PZEkMtbO9tU/TZqYoMPQpBI/AAAAAAAAAL0/MV8PFqgpG4I/image_thumb%5B10%5D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="466" /></a><br />
Then you are all up to date! You can also use ‘git svn fetch’ to to a svn update from the server if others on your team have committed.Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com0tag:blogger.com,1999:blog-5096437112654914738.post-83928468125909863432011-04-20T13:18:00.002+10:002011-04-20T13:38:22.220+10:00[Revit API]– Running your add-ins from a network drive in Revit 2012In previous years our office has run our add-ins directly off a network drive. I’ve placed the DLL files in a network directory, and then installed the .addin manifest file on each users computer that points to these DLL’s. This way when I update the add-ins I only need to update one location and the users simply need to reboot Revit.<br />
<br />
To get this to work, I just had to run caspol.exe on each machine to make their machines trust that certain location, for example:<br />
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">echo y|C:\WINDOWS\Microsoft.NET\Framework\v3.5\caspol.exe -cg LocalIntranet_Zone FullTrust </pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">echo y|C:\WINDOWS\Microsoft.NET\Framework\v3.5\caspol.exe -m -ag 1.2 -url file://L:\* FullTrust</pre>
</div>
</div>
<br />
However in upgrading the add-ins to Revit 2012, this method did not work. The add-ins simply would not load, and in the journal file I was seeing this error:<br />
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">Jrn.RibbonEvent <span style="color: #006080;">"Execute external command:35015:Plotting.PLT"</span></pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: #006080;">' 0:< DBG_WARN: Could not load file or assembly '</span>file:///L:\Plotting.dll' or one of its dependencies. Operation <span style="color: blue;">is</span> not supported. (Exception from HRESULT: 0x80131515): line 171 of AddIn\AddInItem.cpp. </pre>
</div>
</div>
<br />
This was when my assemblies were compiled in .NET 4 and the same error occurred after I recompiled them in .NET 3.5. I had a feeling that it might have something to do with the changes in security that were introduced with .NET 4, but the fact that it happened to .NET 3.5 dll’s as well was odd. <br />
Turns out there’s a fix for it, which is a little bit of a pain, your user needs to update their revit.exe.config file in the Revit program directory (C:\Program Files\Autodesk\Revit Structure 2012\Program) and make the following change:<br />
<br />
look for the <runtime> tag, and just after it’s opening, put:<br />
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"><</span><span style="color: maroon;">loadFromRemoteSources</span> <span style="color: red;">enabled</span><span style="color: blue;">="true"</span> <span style="color: blue;">/></span></pre>
</div>
</div>
making it:<br />
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"><</span><span style="color: maroon;">runtime</span><span style="color: blue;">></span></pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">loadFromRemoteSources</span> <span style="color: red;">enabled</span><span style="color: blue;">="true"</span> <span style="color: blue;">/></span></pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">generatePublisherEvidence</span> <span style="color: red;">enabled</span><span style="color: blue;">="false"</span><span style="color: blue;">/></span></pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"></</span><span style="color: maroon;">runtime</span><span style="color: blue;">></span></pre>
</div>
</div>
<br />
The add-ins should then run correctly. This is however a bit of a pain, I’ll have to incorporate this into an installation tool. I’d love to hear of a better solution to this problem if anyone knows of one, however for now, this will work around it. <br />
<br />
Thanks to <a href="http://aaronwball.com/2010/08/22/visual-studio-2010-debugging-in-remote-locations/">this post</a> for helping to point me in the right direction.Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com6tag:blogger.com,1999:blog-5096437112654914738.post-46534321216452682542011-04-19T17:35:00.001+10:002011-04-19T17:35:01.708+10:00[Revit]–Where have the journal files gone in Revit 2012?<p>If you’ve made the jump to Revit 2012, you may have noticed that there is a new directory structure in the program files dir. </p> <p><a href="http://lh4.ggpht.com/_PZEkMtbO9tU/Ta07IWJF8gI/AAAAAAAAAOQ/HLAiBafHjGg/s1600-h/image%5B3%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_PZEkMtbO9tU/Ta07JHAwuoI/AAAAAAAAAOU/A529MirC68k/image_thumb%5B1%5D.png?imgmax=800" width="476" height="161" /></a></p> <p>There is no longer a journals folder. So where has it gone? The answer is that It appears to have been moved to the AppData directory.</p> <p>C:\Users\USERNAME\AppData\Local\Autodesk\Revit\Autodesk Revit Structure 2012\Journals</p> <p>Replace the uername with your username, and also enter the correct Revit vertical you are using. </p> Rod Howarthhttp://www.blogger.com/profile/07098343984635127435noreply@blogger.com0