Tuesday, June 10, 2008

How to set custom attributes / file properties on a file in C# .Net

In the office here we have developed a document management system, which uses Custom Properties on PDF and DWG files to keep a track of what revision etc they are.

In my Revit API development, we required an easy way of settings these from inside of Revit, so I set about creating a plotting external command using the new Print methods in the 2009 API and PDF995's ini file.

Once I'd printed the documents, I wanted to rename them and set the custom properties such as Revision, drawer, designer etc. I thought, surely .Net has this built into a library, but after many hours of googling my life away I realized it in fact does not, so the Com object used in the Autocad version of this plotting macro would need to be used again.

What you need to get is "DSOFile" from Microsoft, it is intended for editing word document properties, but works on anything. There is an easy to understand VB.Net example included in the download.

In C# I just added a reference to the DLL file, and away I went.

DSO File works by creating a new DSOFile.OleDocumentPropertiesClass, and then performing actions on that.

So, I created a new:

private DSOFile.OleDocumentPropertiesClass m_file;

Then in my constructor for my ParamaterSetter class I created an instance of OleDocumentPropertiesClass and then called the Open() Method with my filename:

//create new isntance of OleDocumentPropertiesClass
m_file = new DSOFile.OleDocumentPropertiesClass();

// select the file you would like to open
m_file.Open(path, false, DSOFile.dsoFileOpenOptions.dsoOptionDefault);

From there you can perform actions such as :
m_file.CustomProperties.Add(key, ref valueForKey);

where key is the name of your property, and valueForKey is the value.

For more standard properties, such as the "Summary" properties (in summary tab when you go properties on the file), you can access them directly, such as:

m_file.SummaryProperties.Comments = value;

Have a play around, look at the example and away you go!

Tuesday, May 20, 2008

System.Security.SecurityException Request for the permision of type..... errors

I have been developing applications using the Revit API (based on the .Net framework) for my workplace. I have been storing these applications on a network drive and having each user simply run them from there. This allows easy updating and easy deployment.

Unfortunately, Microsoft have battened down the hatches when it comes to security for applications not running off your hard drive. There are "Security Zones" in .net (you can see these on most machines in Administrative tools in .Net Framework Configuration), Intranet is one of them. The security level on Intranet is very high, just below the Internet level!

So, any application running off a network drive will have issues if it tries to do anything other than basic GUI functionality. This includes TCP Streams (SocketPermission) and File Access(IOPermission).

We have a file server which stores our files and programs, I want anything on that server to be trusted fully. After some searching I found a very helpful blog from "ShawnFa", who is a bit of a .Net security guru.

So then, I just made a script which does:
echo y|C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\caspol.exe -m -ag 1.2 -url file://server/share/* FullTrust

changing the server and the share to the ones you want to allow. Echo Y takes away hte need for the user to confirm. I've added the full path to the .net framework as the script didn't work for me without it, you might just need caspol.exe. But adding the full path gives you the ability to set it for different frameworks (.Net 1.1 applications don't use the .net 2.0 security I believe etc)

Now I've dumped that in a startup script for my users, and all is good!

Sunday, May 18, 2008

How to update your facebook status via SMS

This post is a little different to my usual posts, in that it's not overly technical.

I recently discovered Twitter, after initially thinking it would be useless, I've been thinking of more and more good uses for it, particularly to do with the API and the SMS functionality.

But one that I don't need to code, is to update your facebook status via SMS. All you need to do is create a Twitter account, setup the SMS section of it (really easy), and then in your facebook, add TwitterSync (There is another twitter app too, but it wasn't working when I tried it). You dont need to put in your password if your twitter is public (as they are by default), then just allow it to update your facebook status when it asks and you are set.

If you use your twitter for things you dont want to show on facebook (I use it to send reminders to myself for when I get home), there is a section in setup to put certain characters that tell facebook that its not meant to be your facebook display. I put "Nf" as mine, but you could put anything. It would be good if they could do it the other way (ie only update facebook status if you put facebook as the first word or something), but I haven't found this feature (let me know if its there!)

Then you are all set, be careful, you'll get addicted and flood your facebook with useless updates, remember, your friends don't care if you are buying new toothpaste!

Thursday, May 15, 2008

Help, my database updates don't stick

Just a quick post to remind people of the ASP.net life cycle.

Most people learn this early on in their ASP.Net life, but it's something that can be overlooked and leave you slapping your head in frustration.

Recently, I was working on a simple page that has some text box fields, which are pre-populated with a users details, you edit those and click submit, it submits the new details and refreshes the page, hopefully with the new details.

My database updates didnt seem to work, I searched through my data access layer and business logic layer to no avail, then I slapped my head and mouthed a few curse words when I realized that I'd populated my text boxes in the Page_Load section, when really I should have done it on the OnPreRender or a similar event (or, as mentioned in comments, use the !Page.IsPostBack method, though this way would simply retain the data inserted into the text boxes from viewstate, I wanted it to regenerate it from the database to ensure my data was inserted correctly and in the format I wanted)

To brush up on the events life cycle check out this article.

Thursday, March 20, 2008

Using Revit KeyboardShortcuts for your external commands

In the previous post, I showed you how to connect your external commands into Revit, ready to be opened from the Tools -> External Tools menu.

But what if you want to make a shortcut to it, lets say for example you want to create "HW" as the shortcut for your Hello World application.

All you need to do is go to your Revit program directory, and open KeyboardShortcuts.txt, then scroll down to the Tools section, and add:

"HW" menu:"Tools-External Tools-Hello World"

Where HW is your shortcut, and Hello World is the ECName you added.

Then typing HW in revit will open your command, easy!

Wednesday, March 19, 2008

Revit commands and the revit.ini file

My previous blog post on getting started with the Revit API showed you how to setup a template to start creating the .DLL files needed for revit external commands, but how do you actually get these into revit?

Lets say, you have made a simple hello world command, one of which is in the API SDK for you to use as a reference.

I mentioned, that the public IExternalCommand.Result Execute method is the start of your command, this is what gets called first, from here you can direct it to do what you would like it to do.

For a simple example, import System.Windows.Forms, and add "MessageBox.Show("Hello World")" to your IExternalCommand.Result method, remember, we added try catch into the template, so put it into the try section.

Now right click on your assembly, and click properties. Go to the "Build" section, and change the output path to the location you would like to store your .DLL files - I store mine on a network drive so that there only needs to be one copy of them for all users in our workplace, perhaps this isn't the best practice (I have to login to the server and kick others out of it if I want to update it), but it makes sense for my situation.

Then go into the "Debug" section, and choose "Start external program:", and choose the Revit.exe on your system. This means that when we start Visual Studio's debugging mode, it will fire up Revit and provide some good debugging features.

Now, you're set to start building your file. Go to "Build" at the top of your screen and go to Build *SolutionName* (this will be whatever you called your project). This builds the solution, ready for use.

Now is where we get to the icky part, the Revit.Ini file. Autodesk, remembering the glory days of the 90's, have used a .ini text file to tell revit that we have some external commands that we would like to use. There is documentation on this in the Revit SDK, but here is what you need to do. :
  1. Open your Revit.Ini file
  2. Find [ExternalCommands] if there is one, if not, create that section.
  3. Insert the reference to your .DLL external command file, it should look similar to as follows
[ExternalCommands]
ECCount=1
ECName1=ImportedCategoriesToggle
ECClassName1=ElementProperties.Command
ECAssembly1=L:\Revit\bwtools\ElementProperties\ElementProperties.dll
ECDescription1=ImportedCategoriesToggle

There, you can see the [ExternalCommands] header, and then under that is the ECCount, which tells revit how many External Commands are present. This will need to be incremented each time you add another command.

ECName1 states the name which will show up in revit, ECClassName1 points to the Namespace.Class of your DLL file. So say you called your project RevitCommandOne and then made a class called 'Command' (as many of the examples do - you can call it what you like, or even have more than one in each Namespace), it would be RevitCommandOne.Command
ECAssembly1 points to the dll file you exported, remember how you chose where to store this in the Visual Studio 'Build' properties? ECDescription1 is just a description of your command, add what you like.

Of course, the '1' on the end of each of these fields is just saying its the first one, change this to 2 for your second and so on.

As you can see, the Revit.ini file is a bit of a weak point, it would be much better if it was an XML file or something, so that you could programmatically change it without fiddling with text streams and regular expressions, but thats the way it is, hopefully in 2010 this might be fixed....

Once you have inserted that section, save it, and start Revit (you must restart revit each time you change the revit.ini file), then your command should show up in the Tools > External Tools menu. Simply click to run it.

If Hello World does not show up, then chances are you have made a mistake in your revit.ini file, double check it all, make sure the numbers are correct, you've incremented the ECCount etc.

Sunday, March 9, 2008

How to make Vista look like XP

I just made the jump to Vista, purely for a 64bit Windows Operating system that has hardware support (There is of course 64bit XP, but it seems most hardware vendors put their hands over their ears and say "la la la I'm not listening" whenever you mention it).

The most annoying thing for me, was the theme. I hate it, I hate the visual styles, I hate aero, I hate all of the shadows and transparency effects, in fact, it gives me a headache, literally. I tried to get used to it, tried tweaking it, turning off stuff etc but it didn't help. The main qualm for me was the black two-toned taskbar. The windows classic theme for Vista is a joke, it looks worse than it did in windows 98. I just wanted Vista to look like XP.

So, I set about googling, though most of my results returned people wanting XP to look like Vista, it seemed I was one of the few who want it the other way around. I soon found out, that basically, Microsoft has done its best to stop custom themes, to perserve the branding of vista I believe (ie you look at a vista pc and you know its a vista pc), only themes created by Microsoft can be used.

One option, is to use Windows blinds or something similar, but I want to increase performance, not reduce it! So that was out. I then stumbled upon Deviant Arts collection of custom themes, and noticed they used a hack to get the standard .theme files to work. I was told that Vista Glazz did the hacking for me and then all I had to do was double click the theme file. This didn't work either - I'm not sure why though.

In the end, I used Tune Up Utilities. This allowed me to simply select what theme I want, and apply it, nice and easy.

Then, after searching around and downloading a few themes, I discovered that a DeviantART user by the name of 'psychoB' has converted the old XP themes to vista, brilliant! Here they are:

Luna Metallic (the theme I am using)
Royale (Standard XP theme)
and even the Zune theme

See his other work at psychoB's deviantART gallery.