Brian Clifton . com

Programming Articles: Example code and more.

Previous   1 2 3   Next
Showing articles 1 - 10 (27 posts total)

ASP.NET (C#) - Quick and dirty redirect module

Posted by Brian Clifton
Written March 7, 2012 at 00:44
If you maintain a website for a while, chances are you're going to change your content around. When you do, it's likely you'll break someone that's linking to your content. Even if no humans are linking to your content, crawlers like Google have a copy of your site in their cache.

A redirect module is a great way to find out what resources are broken so that you can fix the source (for example, edit a post on a forum and update the URL) or so you can choose a redirect behavior.

Below is a stripped down version of the module I wrote for this website.

Continue reading this article

Taking a screenshot using XNA 4.0 and C#

Posted by Brian Clifton
Written August 8, 2011 at 07:49
I've been working a lot on an old game that a few friends and I made in college. We ported it to C# using the XNA framework and it's working great! You can read more about that project by clicking here.

The old code was C++ with OpenGL. One of the functions I had a hard time porting was taking a screenshot. Older versions of XNA seemed to have a way to do it, but the newest version, 4.0, didn't have an easy way to do it. Here's what I ended up doing:
public void ScreenShot(string prefix) {
    #if WINDOWS
    int w = GraphicsDevice.PresentationParameters.BackBufferWidth;
    int h = GraphicsDevice.PresentationParameters.BackBufferHeight;

    //force a frame to be drawn (otherwise back buffer is empty)
    Draw(new GameTime());

    //pull the picture from the buffer
    int[] backBuffer = new int[w * h];
    GraphicsDevice.GetBackBufferData(backBuffer);

    //copy into a texture
    Texture2D texture = new Texture2D(GraphicsDevice, w, h, false, GraphicsDevice.PresentationParameters.BackBufferFormat);
    texture.SetData(backBuffer);

    //save to disk
    Stream stream = File.OpenWrite(prefix + "_" + Guid.NewGuid().ToString() + ".png");
    texture.SaveAsPng(stream, w, h);
    stream.Close();

    #elif XBOX
    throw new NotSupportedException();
    #endif
}

Here's an article you can check out that explains the new behavior:
http://blogs.msdn.com/b/shawnhar/archive/2010/03/30/resolvebackbuffer-and-resolvetexture2d-in-xna-game-studio-4-0.aspx

Getting the assembly version in ASP.NET

Posted by Brian Clifton
Written February 11, 2011 at 10:43
I typically update the .NET assembly for this website by hand whenever I have a new major release and I'd like to be able to get the version.

Unlike a Windows Forms application, there is no Application.ProductVersion. I Googled for answers and it looked like I needed to do this:using System.Reflection;

string version = Assembly.GetExecutingAssembly().GetName().Version.ToString();

However, that causes a SecurityException to be thrown. I'm running my website at GoDaddy.com in a shared hosting environment and the permissions are limited.

Here's how I solved the problem...using System.Reflection;

Type t = typeof(*pick any class that's in the assembly you want the version of*);
AssemblyName an = new AssemblyName(Assembly.GetAssembly(t).FullName);
string version = an.Version.ToString();

Some examples that I found use Assembly.GetExecutingAssembly(), but I found that this doesn't work. It'll compile, but always returns back 0.0.0.0 as the version. That's why you'll have to use Assembly.GetAssembly() and provide a type as shown above.

Searching the database for text in SQL Server

Posted by Brian Clifton
Written May 9, 2010 at 23:57
In SQL Server, there's a lot of times where you need to find out where a stored procedure, user function, or value is referenced in the database.

For example, let's say we have a stored procedure called "InsertUser". We can search all database text for any references of this:SELECT *
FROM syscomments
WHERE text LIKE '%InsertUser%'

Simple object pool in C++

Posted by Brian Clifton
Written November 26, 2009 at 02:52
This is a simple object pool I use in my C++ code. It provides good performance and avoids memory fragmentation. I based the code on an example from Game Programming Gems 4.
#include <stdlib.h>
#include <list>

using namespace std;

class TestObject{
    public:
        int _TestValue;
        TestObject(void)
        {
            _TestValue = 0;
        }
};

template<class OPDataType> class ObjectPool{
    protected:
        OPDataType* _ObjectData;
        OPDataType** _ObjectFree;
        int _ObjectCount,_Top;

    protected:
        void FreeAll(void)
        {
            int i = (_ObjectCount-1);

            for(_Top=0;_Top<_ObjectCount;_Top++){
                _ObjectFree[_Top] = &_ObjectData[i--];
            }
            return;
        }
    public:
        void FreeInstance(OPDataType* instance)
        {
            if((instance) && (_Top<_ObjectCount) && (instance>=&_ObjectData[0]) && (instance<=&_ObjectData[_ObjectCount-1])){
                _ObjectFree[_Top++] = instance;
            }
            return;
        }

        OPDataType* NewInstance(void)
        {
            if(_Top>0){
                return(_ObjectFree[--_Top]);
            }
            return(0);
        }

        ObjectPool(int count)
        {
            _ObjectData = new OPDataType[count];
            _ObjectFree = new OPDataType*[count];

            _ObjectCount = count;

            FreeAll();
        }

        virtual ~ObjectPool(void)
        {
            delete[] _ObjectData;
            delete[] _ObjectFree;
        }
};

#define TEST_POOL_SIZE 200

int main(int argc,char** argv)
{
    ObjectPool<TestObject> pool(TEST_POOL_SIZE);
    list<TestObject*> objects;

    for(int i=0;i<TEST_POOL_SIZE;i++){
        TestObject* test = pool.NewInstance();
        test->_TestValue = rand();
        objects.push_back(test);
    }

    list<TestObject*>::iterator it = objects.begin();
    while(it != objects.end()){
        pool.FreeInstance( (*it) );
        ++it;
    }

    objects.clear();

    return(0);
}

Handling NIC information on Windows

Posted by Brian Clifton
Written August 6, 2009 at 22:00
If you need to programmatically get info about the NIC, you can find it in the registry:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}

You can enumerate through all of the sub-keys; they're labeled as 0000, 0001, 0002, etc. If you're on Windows Vista / Server 2008, be sure to catch exceptions because there is a sub-key called Properties that you will get an access violation on.

For example, in my Shuttle SG33G5, I have my primary NIC under a sub-key called 0004. I can tell it's my primary NIC because of the DriverDesc value. From this key, you can set duplex, buffer sizes, and other NIC driver settings.

Just as an example, lets say you want to set your NIC to be 100Mbps full duplex. Before you make an automated solution, you can see the values passed to the NIC driver in the sub-key called NDI under the sub-key Params. In my case, I would need to open this key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0004\Ndi\Params\*SpeedDuplex

There is a value here called default and it's set to 0. Looking at the sub-key called enum, there are some values I could use:
0 = Auto Negotiation
1 = 10 Mbps Half Duplex
2 = 10 Mbps Full Duplex
3 = 100 Mbps Half Duplex
4 = 100 Mbps Full Duplex

So when it's time for automating this, my code would:
1) Open this key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}
2) Go through each sub-key (0000,0001,0002...), until it finds a value DriverDesc called "Generic Marvell Yukon Chipset based Ethernet Controller".
3) I know for this card, the value 4 is 100Mbps. So I can set the value data for "*SpeedDuplex" to 4. The full path to this registry value is
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0004\*SpeedDuplex
4) After making the change you can restart your network interface by making a shell execute call to netsh.exe
netsh interface set interface "Local Area Connection" DISABLED
netsh interface set interface "Local Area Connection" ENABLED

This article is basically documentation of some code my friend Daymion wrote. You can probably achieve the same result with WMI, but it's a lot nastier to do that in C or C++.

Getting the current page name in ASP.NET

Posted by Brian Clifton
Written August 6, 2009 at 20:57
string strPage = Request.FilePath.ToLower();

chroot and mounting

Posted by Brian Clifton
Written May 19, 2009 at 12:23
Recently I've ran into problems when I am using a 32-bit OS and dealing with 64-bit files. In my case, I have a layout like this:
/tmp/64-bit-files-here
The main system I have is 32-bit and I untar a 64-bit root file system to the folder /tmp/64-bit-files-here. At this point, I want to chroot and run a shell script but I'm unable to. Since I would be chroot-ed, the binaries that would be used are coming from /tmp/64-bit-files-here/bin and /tmp/64-bit-files-here/sbin and they are 64-bit and won't run.

Symlinks won't work because as soon as you chroot, that path is invalid. I had to read some man pages and do some searching, but I found a solution. The way I got around this is by using mount. I made the appropriate folders in my 64-bit file system folder:
mkdir /tmp/64-bit-files-here/tmp-root
mkdir /tmp/64-bit-files-here/tmp-root/bin
mkdir /tmp/64-bit-files-here/tmp-root/etc
mkdir /tmp/64-bit-files-here/tmp-root/lib
mkdir /tmp/64-bit-files-here/tmp-root/sbin
#create other directories here
cp /tmp/MyShellScript.sh /tmp/64-bit-files-here/tmp-root

Then I used mount to provide a link-like functionality. I mount the 32-bit executable directories but I load the 64-bit file directories such as etc. Note the --bind argument:
mount --bind /bin /tmp/64-bit-files-here/tmp-root/bin
mount --bind /tmp/64-bit-files-here/etc /tmp/64-bit-files-here/tmp-root/etc
mount --bind /lib /tmp/64-bit-files-here/tmp-root/lib
mount --bind /sbin /tmp/64-bit-files-here/tmp-root/sbin
#mount other directories here
chroot /tmp/64-bit-files-here/tmp-root /MyShellScript.sh

When you do chroot, you'll have access to run the 32-bit executables but modify your 64-bit file system. This specific example might only be useful if you're doing imaging but the chroot / mount example should be useful for any kind of scripting.

Cron Quick Reference

Posted by Brian Clifton
Written April 28, 2009 at 08:58
On Linux you can schedule tasks using cron. To open up cron just run:
crontab -e
Something useful to paste into your crontab is this line:
#mh hd dm my dw command
Like most Linux configuration files, lines starting with # are comments. This comment shown above is helpful to show you the field order that a cron line is broken down into. Each cron is on it's own line and it's parameters are space separated. Here's an explanation of the abbreviations found in the comment:
mh - minute of the hour (0-59)
hd - hour of the day (0-23)
dm - day of the month (1-31)
my - month of the year (0-12)
dw - day of the week (0-6, with 0 being Sunday)
command - command to run

For each value you can put an asterisk if you always want it to run. For example, if you put an asterisk for mh, the command will run every minute (see example 1).

You can also add a list by comma seperating values ...
(see example 2).

Alternatively, you can use a range by using the hyphen ...
(see example 3 and 4).

The last way you can provide a value is using a step value. For example, if you want to run a command every other day, you can basically provide the dm field with */2 ...
(see example 5).

Here are a few examples that should help show how crontab entries work:
#mh hd dm my dw command

#example 1: executes once per minute (every day)
* * * * * echo "This is a test"

#example 2: executes every day at 10am, noon, and 2pm
0 10,12,14 * * * echo "This is a test"

#example 3: executes every day on every hour between at 10am and 2pm
0 10-14 * * * echo "This is a test"

#example 4: executes Monday thru Friday at 2pm
0 14 * * 1-5 echo "This is a test"

#example 5: executes every other day at 2pm
0 14 */2 * * echo "This is a test"

#example 6: executes every day at 2pm and logs
0 14 * * * echo "This is a test" >> /var/log/results.log 2>&1

Note that in example 6 above, I redirect standard output and standard error into a log file. This is the best way to grab the output from your cron.

This information was put together using these articles:
http://troy.jdmz.net/cron/
http://www.unixgeeks.org/security/newbie/unix/cron-1.html

grep -P is not supported on Ubuntu

Posted by Brian Clifton
Written April 20, 2009 at 11:40
On Ubuntu, the man page of grep states that the flag -P or --perl-regexp can be used to use a PERL regular expression. But when the command is run with either flags you get the following error message:
grep: The -P option is not supported
This has officially been a bug for a while; it appears to be a hot issue. Some folks have even suggested "fixing it" by removing -P from the man page. More details can be found here:
https://bugs.launchpad.net/ubuntu/+source/grep/+bug/15051

Regardless of all that chatter, I found a pretty easy solution that works. You can copy the grep executables and libraries from a machine that has a Red Hat distribution installed. Just SCP the files over and you're ready to go:
mv /bin/grep /bin/grep.bak
scp user@192.168.1.1:/bin/grep /bin/grep
scp user@192.168.1.1:/lib/libpcre.so.0.0.1 /lib
cd /lib
ln -s libpcre.so.0.0.1 libpcre.so.0
Previous   1 2 3   Next
Showing articles 1 - 10 (27 posts total)
© Brian Clifton. All rights reserved.