cut -d "," -f 1 file.txt | sed "s/\(.*\)/'\1'/"

In the last few months I started getting a bucket load of spam into my phpBB forum.

To solve it I set the option that new users should automatically be added to the “Newly Registered Users” group and set the permissions on that group so that all new postings went into the moderation queue. However that ended up not being an ideal solution as I have to frequently check the moderation queue and genuine users have to wait for their posts to appear.

I eventually got around to looking for a better way and came across the SpamHammer plugin. To install it I first installed the autoMod component. I had to fix up three find nodes in the SpamHammer package being:

  • The cron.php,
  • The posting.php, and
  • The /language/en/acp/board.php.

The problem was they were using spaces instead of tabs. Cutting and pasting the text that was in the find node from the original php file fixed the problem up.

After installing I couldn’t find the SpamHammer configuration pages but a quick bit of reading and it’s locating at General->Posting->SpamHammer was revealed. I set a few likely options, removed the placement of new users into the newly registered groups and sat back to a hopefully spam free existence.

mysql -h hostname -P port_number -u username -p < sql_script_filename

Original Perl Tk Forum

use Tk;$m=MainWindow->new;$c=$m->Canvas(-he,30,-wi,70,-ba,white)->pack;
%h=(1,blue,0,black);@d=('R/K6Q(W6','<&F&<4F4','5/.64(:6','?*I*?8I8');  for(@d){$i++;create $c 'line'=>map((ord($_)-30),
map(split(//),$_)),-wi,2,-fill,$h{$i%2}}MainLoop;

use Tk;$m=MainWindow->new;$c=$m->Canvas(-he,100,-wi,90)->pack;
$j=$m->Photo(p);$j->put(white,-to,0,0,90,100);
$d='D21021>23>7310276732273774673@76776766733232100100100102102112>12>10110­1 
12112212310>237312737373231632>7>3737337733>73?7310373373G76766740101G04467­6 
776776E73633766B7376B76B73673664?5012104100100100104004B0>414521414>04>0>46­7 
6766776@7636>73676756756766767363273375650400456>7C501311210100E4B011001410­4 
500>4673676?766>76B76@7667767677673>7654B511>21101001001>01>04001004G01>040­4 
5565644>544044540440404B0401?0101010>4?5040?1233A763B763677>676476?4004@012­0 
1201>01011401';
@f=split//,$d;$b=0;while($#f>-1){$a=shift(@f);
if($a=~/[0-7]/){$e[$b++]=$a}
else{$h=shift(@f);$a=ord($a)-60;while($a>=0){$e[$b++]=$h;$a--}}}
$x=7;$y=10;$i=0;for(@e){if($i==563){$x=56;$y=55}
$j->put(black,-to=>$x,$y);$i++;if(/0|7/){$o=3.5}else{$o=$_}
$x+=-($o<=>3.5);if(/0|1|4/){$y+=-1}elsif(!/2|5/){$y+=1}}
$c->createImage(45,50,-image,p);sub F($$){my($x,$y)=@_;
$q=$j->get($x,$y);if($q!~/0/){$j->put(black,-to=>$x,$y);
F($x+1,$y);F($x-1,$y);F($x,$y+1);F($x,$y-1)}}
@h=('2796','8746','8657','8558','5891','7895','2990','5688','7983',
'4550');for(@h){$r=substr $_,0,2,'';&F($r,$_)}
@d=('4e4o&e&o','7b7l)b)l',',q4z&s4p',',X4a&Z4W');for(@d)
{create $c 'line'=>map(ord($_)-30, map(split(//),$_)),-wi,2}MainLoop;

I’m not particularly demanding of my browser. I don’t want to play games in it or make telephone calls or anything else “cutting edge”. I want to check a few web pages at frequent intervals, post a few forum posts and occasionally bookmark a page.

I used to just use IE but a year or so ago switched to Firefox. About 3 or 4 months ago I noticed Firefox becoming really sluggish and chewing heaps of CPU on some web pages that use Flash. I’m no big fan of Flash but it’s hard to avoid so I’d prefer if my browser could cope with it without spiking the CPU and becoming jerky on the UI. Even writing this blog post in WordPress is annoying. The words ocassionally lag behind the typing as Firefox goes away and does some superfulous task. I put up with it fo a while but finally it got to annoying.

About a month ago I switched to Chrome and was pretty impressed. It’s definitely the most usable browser I’ve employed to date. Bookmarking is intuitive. It’s a small thing but with Firefox I find it a pain to classify a bookmark. Anway Chrome was nice but I found that I was often having to click a link wait and then click it again. Initially I put it down to the network but after a few weeks lI began to doubt that. I started opening an alternative browser whenever it happened and the other browser was always able to bring the page up while Chrome was still waiting. I half suspect the problem is that Chrome is not doing a good job with DNS processing but I’m just guessing and can’t be bothered diagnosing.

With IE I don’t have either of the above issues but I do find the UI in general very clunky and always feel a bit less productive when I’m using it.

I guess that leaves Safari and Opera. I think I’ll give Opera a spin.

Update 26 Feb 2011: I tried out Opera 11.01 for two weeks and while it was ok’ish I never really felt comfortable with it. My biggest gripe is the way it caches and load pages. It seems to very aggressively cache images which is a pain when I’m checking a status page with an image graph. I found myself having to click refresh a couple of times and double check the time stamp on the graphs to make sure Opera had actually loaded the latest version. Despite the aggressive caching it seemed slower than the other browsers when loading web sites. The element countdown in the task bar didn’t help as it just focused me on the fact that I was still waiting. A nice calming progress bar or something is better. I found a lot of sites would be rendered as raw unstylised HTML and then a second later the CSS would be applied. It wasn’t a big drama but it just made the browser fell clunky and is not something that happens with IE, Firefox or Chrome.

Back to Chrome.

When installing a new update of a .Net application with a VS.Net project there will often be a requirement to preserve some of the existing application settings. The easiest way (and only way so far) I found to do this was to use the Settings VS.Net template and specify the settings that need to be updated as UserScoped. The application can then perform a check each time it is run and if it detects itself being updated can run an Update method to preserve any UserScoped settings from a previous version.

  • Add a new Settings item to the application being installed. Add all the required settings to it. Add an additional setting called ApplicationVersion. The Settings item template generates a VS.Net code file and also an App.Config file, it will also detect changes between the two and attempt to keep them in sync. When deployed on a client machine the settings file does not get deployed as the standard executable.exe.config and is instead stored in a directory under the user’s home directory,
  • When an application update occurs with an msi file a new settings file is created based on the values in the original VS.Net settings file. However, and importantly, the settings file for the previous version are not overwritten, each install creates a unique settings file name,
  • By adding a small code snippet to the application that gets performed each time it starts up it’s possible for the application to pull the settings from the previous application version into the newly installed one and thus preserve them.

            AppSettings appSettings = new AppSettings();
            
            System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly();
            Version appVersion = a.GetName().Version;
            string appVersionString = appVersion.ToString();

            if (appSettings.ApplicationVersion != appVersion.ToString())
            {
                appSettings.Upgrade();
                appSettings.ApplicationVersion = appVersionString;
                appSettings.Save();
                Console.WriteLine("Settings file was upgraded.");
            }

It’s pretty simple but I’m bound to forget (again).

  • Click on the Setup Project (the one that’s generating the msi installation file) and in the Solution Explorer menu bar click on the Custom Actions Editor,
  • Right click on the Commit folder (Commit actions run after the install has completed) and choose Add Custom Action. In the dialog box select Application Folder (which is the destination application folder on the client performing the install) and press Ok. The Primary output should already be in the dialog box, if not add it by clicking Add Output button and selecting the appropriate project (the one that will hold the custom execution class) and choose Primary Output,
  • Add a new Installer class (that’s a specific type of Visault Studio class not a normal class caleld installer) to the Primary Output assembly,
  • Right click on the new installer class and select view code and add whatever is required to it. An example for a commit action is below.
  • public override void Commit(IDictionary savedState)
    {
        base.Commit(savedState);
        string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        System.Diagnostics.Process.Start("cmd", "/c certutil -f -p password -importpfx \"" + path + "\"\\cert.p12");
    }
    

The steps to get a Visual Studio installer package to automatically update an existing application are:

  • For the deployment project set the following properties (get the properties by clicking on the project and switching to the properties window NOT by right click->properties),
  • Set RemovePreviousVersion to true,
  • Update the Version number for each installer build. Note when the Version is updated the ProductCode should automatically be updated by VS.Net (always click yes when it asks) but the UpgradeCode should remain the same,
  • In the project(s) being deployed in the installer the AssemblyVersion AND AssemblyFileVersion need to be updated. If the AssemblyFileVersion is not updated than the installer will assume that the file has not changed and will not overwrite the file from a previous installation.

The command line to fire up a Silverlight xap file out of browser.

sllauncher /emulate: xapfilename /origin: uri

The sllauncher app should be in C:\Program Files\Microsoft Silverlight or C:\Program Files (x86)\Microsoft Silverlight. More info at MSDN Out of Browser Support.

After enabling forms authentication and attempting to add a role to a user I got the following error:

“Cannot resolve the collation conflict between “Latin1_General_CI_AS” and “SAL_Latin1_General_CP1_CI_AS” in the equal to operation.”

With a rapidly beating heart I found a thread on the LightSwitch forum dealing with the issue. Microsoft employee Matt Thalman helpfully posts a repsonse stating that the fix is to change the collation on the database and links off to an MSDN page describing how to do so. Unfortunately that information is deficient in that it doesn’t decsribe the crucial steps of how to connect to the LightSwitch ApplicationDatabase.mdf file. Beats me why Matt couldn’t have taken the 30s to add those couple of preliminary steps and saved many people having to work it out by trial and error!

These are the steps I took on my Windows 7 x64 laptop:

1. Close the Visual Studio .Net instance with the LightSwitch application in case it has the ApplicationDatabase.mdf locked,

2. Open up SQL Server Manager ensuring to select run as Administrator and connect to a local instance of an SQL Server or SQL Express Server,

3. In SQL Server Manager click on the Databases folder and select Attach,

4. In the dialog that pops up click Add and then browse to the ApplicationDatabase.mdf of the LightSwitch application which in my case was under the Bin/Data directory of my LightSwitch application directory,

5. If you are able to successfully attach the open up a new query window and run the SQL command below:

alter database [C:\yourpath\BIN\DATA\APPLICATIONDATABASE.MDF] collate Latin1_General_CI_AS

6. Detach the database by clicking on the Database folder and Tasks->Detach,

7. Reopen the LightSwitch application in Visual Studio .Net hit debug and this time you’ll hopefully be able to add a role to a user. Except it still fails with the same error. Looks like the collation isn’t getting applied for some reason.

Damn you Matt :( I could have read a whole year of Dilbert strips in the time I’ve spent fiddling around with this. Next time please take 5 minutes and put up the steps so that a poor code monkey could follow them.

New trick that did end up working was to leave Visual Studio open while making the collation change form SQL manager. That did work at least up until the next time Visual Studio was closed and opened. It looks like something in LightSwitch resets the collation of the ApplicationDatabase. Leaving VIsual Studio open while the collation is chnaged provides a window of opportunity to add a role to a user.

    Follow

    Get every new post delivered to your Inbox.