Wednesday, August 27, 2008

 

Make a Bootable USB from a DMG

Here's the simplest process I have seen...



Note: --erase will cause the usb key to be wiped AND is what 'bless'es the device so it becomes bootable.

There you go..
 

Running a .NET Executable from a Network Drive

Rob Smyth is developing NUnitGridRunner, a tool to run nunit.console on several machines at once.

As any application under test grows, so does the number of UATs. Rob's project aims to allow us to scale the running of UATs by adding network boxes.

What does this have to do with Running .NET executables on network drives?

Well, Rob needs to distribute the latest version of the assemblies and tests to each machine so they could run the tests. It's simpler if they just all run from a network path. ,However .NET got in the way.

1/2 a day later we had a solution.

If you run nunit-console.exe from a command shell accessing it from the network drive, you get the following error.


Unhandled Exception: System.Security.SecurityException: That assembly does not allow partially trusted callers.
at System.Security.CodeAccessSecurityEngine.ThrowSecurityException(Assembly asm, PermissionSet granted, PermissionSet refused, Runti
ityAction action, Object demand, IPermission permThatFailed)
at NUnit.ConsoleRunner.Class1.Main(String[] args)
The action that failed was:
LinkDemand
The assembly or AppDomain that failed was:
nunit-console, Version=2.4.6.0, Culture=neutral, PublicKeyToken=null
The method that caused the failure was:
Int32 Main(System.String[])
The Zone of the assembly that failed was:
Internet
The Url of the assembly that failed was:
file://aumelw021202/GridRunnerSandPit/AUMELW061120/nunit-console.exe


This is due to .NET's permissions system. There are lots of articles online telling you how to recompile your exe to make it run. This is a 3rd party exe though, so I don't want to have to recompile it. That would mean that each time I want to upgrade I would have to do extra steps.

Anyway.. here is the solution I used.

First I changed the Zone that .Net things the network drive belongs to.


Control Panel >> Internet Options >> Security >> Local Intranet >> Click Sites... >> Advanced...
in 'Add this Web site to the zone:' enter the network path.. and click Add
eg. \\MyNetworkMachine\DirectoryContainingExe

You can test this worked by running the executable again from a dos prompt...

The Zone of the assembly that failed was:
Intranet


Notice it moved to Intranet.

Now all you have to do is tell .NET to trust executables in that zone.


Control Panel >> Administrative Tools >> .NET Framework 2.0 Configuration >> Configure Code Access Security Policy >> Adjust Zone Security >> Next >>

Click "Local Intranet" and slide the slider up to Full. Then click Next a couple to of times.

You can now run the executable... TADA!

What you've done is allow .NET assemblies in the local intranet to be executable on your machines. If this represents a security risk for your machines then this is not the right solution for you.

For us it works great.

Labels: , , , ,


Sunday, August 24, 2008

 

Design Patterns in Ruby

Neal Ford gave a great talk at erubycon about the use of Design Patterns in ruby.

I really liked a couple of tips on how to use interfaces as named groups of methods and mixin's for states.

Tuesday, July 29, 2008

 

ActiveRecord SQLite3 "unable to open database file"

I am starting up a Hobo based project that will appear sometime soon. I made a simple mistake, so I thought I should share.

I ran something like this... sudo hobo code_blog
I got a few missing gem problems, so I did a few sudo gem install X.
I did a few ./script/generate hobo_model_resource X.
Finally I get to ./script/generate hobo_migration
and ./script/server

With excitement I fire up firefox and get a lovely screen. I attempt to sign up and get

ActiveRecord::StatementInvalid: SQLite3::SQLException: unable to open database file: INSERT INTO users ("salt", "updated_at", "crypted_password", "remember_token_expires_at", "username", "administrator", "remember_token", "created_at") VALUES('xxxxxxxxxxxxxxxxba4739cda76', '2008-07-28 22:16:31', 'xxxxxxxxxxxxxxxxxxx99537dd568', NULL, 'nigel', 't', NULL, '2008-07-28 22:16:31')
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract_adapter.rb:150:in `log'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/sqlite_adapter.rb:132:in `execute'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/sqlite_adapter.rb:345:in `catch_schema_changes'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/sqlite_adapter.rb:132:in `execute'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:156:in `insert_sql'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/sqlite_adapter.rb:146:in `insert_sql'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:44:in `insert_without_query_dirty'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract/query_cache.rb:19:in `insert'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:2272:in `create_without_callbacks'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/callbacks.rb:226:in `create_without_timestamps'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/timestamp.rb:29:in `create'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:2238:in `create_or_update_without_callbacks'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/callbacks.rb:213:in `create_or_update'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:1972:in `save_without_validation'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/validations.rb:934:in `save_without_transactions'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:108:in `save'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:66:in `transaction'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:80:in `transaction'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:100:in `transaction'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:108:in `save'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:120:in `rollback_active_record_state!'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:108:in `save'
from (irb):7>> exit


OK, so do you spot the mistake?

Well it's the sudo in sudo hobo code_blog.

This made the hobo files all owned by sudo.

The fix.. sudo chown nigelthorne code_blog/* obviously with your username and project directory.

We live a learn. :)

Monday, July 28, 2008

 

Removing Redundant code with NDepend

As we refactor our code, some design changes make some existing code redundant. When you have unit tests on all your code you can't find this using coverage. So finding this redundant code can be tricky.

What you need is a tool that can analyze your code base. The best I have found for .Net is NDepend.

NDepend provides a query language for code.

I started a project and added all assemblies except the test ones. I then ran the query :
SELECT TYPES WHERE TypeCa == 0

TypeCa refers to the 'Afferent Coupling' of the type.. ie. how many other types refer to this one.

This found 40 files I could delete.

I used Resharper to double check each one was not used (except in tests).

I got a couple of false positives with types I am only using to pass as type parameters to generic classes. This is the only thing stopping me adding this check as part of our build script.

Finding all those classes by hand would have taken much longer, so...

Works for us!

Labels: , , , , ,


This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]