Playing with Powershell

Jan 06
2011

I’ve not actually used powershell before, but we had a requirement to store a list of security camera files and dates in a database so that we could track historical camera activity and this seemed like a good excuse to use it rather than writing a short C# executable.

What I ended up with was this :

# Configuration
$camera_home = "C:\Recordings";
$connection_string = "Data Source=localhost;Initial Catalog=MyDatabase;Trusted_Connection=True";
 
# Sanity Check
if (!(Test-Path $camera_home)) 
{
    [Console]::WriteLine($camera_home + " not found!"); 
    return;
};
 
# Set up the SQL Connection
$conn = new-object System.Data.SqlClient.SqlConnection($connection_string);
$conn.Open();
 
# Get a list of all cameras
$cameras = Get-ChildItem $camera_home;
 
# Iterate over the list
foreach($camera in $cameras)
{
    [Console]::WriteLine($camera);
    $guid = $camera.Name;
 
    # Check whether the current camera exists in the database.
    $camera_getid = new-object System.Data.SqlClient.SqlCommand("select ID from dbo.Camera where CameraGUID = @CameraGUID", $conn);
    $camera_getid.Parameters.Add("@CameraGUID", [System.Data.SqlDbType]"NVarChar").Value = $guid;
    $id = $camera_getid.ExecuteScalar();
    if ($id -eq $Null)
    {
        # Create a new camera record
        $camera_create = new-object System.Data.SqlClient.SqlCommand("insert into dbo.Camera(CameraGUID, CameraName) values(@CameraGUID, 'New Camera')", $conn);
        $camera_create.Parameters.Add("@CameraGUID", [System.Data.SqlDbType]"NVarChar").Value = $guid;
        $camera_create.ExecuteNonQuery();
        $id = $camera_getid.ExecuteScalar();        
    }
 
    # Get the date of the last recording we have a record for
    $camera_getlastrecording = new-object System.Data.SqlClient.SqlCommand("select case when Max(RecordingDate) is null then convert(datetime, '1/1/2001', 103) else MAX(RecordingDate) end from dbo.CameraData where CameraID = @CameraID", $conn);
    $camera_getlastrecording.Parameters.Add("@CameraID", [System.Data.SqlDbType]"Int").Value = $id;
    $lastrecording = $camera_getlastrecording.ExecuteScalar();
    [Console]::WriteLine([String]::Concat("    Last recording date : ", $lastrecording ));
 
    # Get a list of new recordings
    $recordings = Get-ChildItem -recurse -include "*.acsm" $camera_home\$camera | Where-Object {$_.CreationTime -gt $lastrecording};
    if ($recordings -eq $Null) 
    { 
        [Console]::WriteLine([String]::Concat("    No new recordings found."));
        continue 
    }
    [Console]::WriteLine([String]::Concat("    ", $recordings.Count, " new recordings found."));
 
    # Insert new recordings into the database
    foreach($recording in $recordings)
    {
        [Console]::WriteLine([String]::Concat($recording, ",", $recording.CreationTime.ToString("dd/MM/yyyy HH:mm:ss.FF")));
        $recording_create = new-object System.Data.SqlClient.SqlCommand("insert into dbo.CameraData(CameraID, RecordingName, RecordingDate) values(@CameraID, @RecordingName, @RecordingDate)", $conn);
        $recording_create.Parameters.Add("@CameraID", [System.Data.SqlDbType]"Int").Value = $id;
        $recording_create.Parameters.Add("@RecordingName", [System.Data.SqlDbType]"NVarChar").Value = $recording.FullName;
        $recording_create.Parameters.Add("@RecordingDate", [System.Data.SqlDbType]"DateTime").Value = $recording.CreationTime;
        $recording_create.ExecuteNonQuery();
    }
}

Probably the most interesting thing about this post was how long it took to actually make it because of this :

http://wordpress.stackexchange.com/questions/6421/how-can-a-single-line-in-a-blog-post-take-down-my-server/6428#6428

I suspect this kind of thing is going to reoccur if I post anything else with SQL in it, but unfortunately, I don’t have the ability to switch off the ModSecurity rules…

An animated, Reuters-style ticker in WPF

Aug 19
2010

I just need to get this out onto the blog for posterity, as it were.

This is a class that derives from StackPanel and Implements a Reuters style ticker behaviour with its children. Anything you add to the Children collection will be ticked from left to right.

The only issue with it so far is that adding something to the Children collection makes it initially show up on the left (intialised to coordinates (0,0)). This could probably be solved by adding something like an AnimatedChildren collection, and only adding to the Children collection when the animation is initiated?

This is hugely untidy at the moment, but it does work after a fashion. I don’t in any way claim this is the right way to do this or that any of this is best practice :)

Update

Ok, so I only realised a short while ago that you don’t strictly need the Storyboard class to initiate animations when you’re not using XAML. I haven’t yet investigated removing them from this code, but I’ll probably get round to that when I have a Windows VM finally set up.

public class MyPanel : Canvas
{
    private Timer _timer = new Timer(500);
    public MyPanel()
    {
        LayoutUpdated += new EventHandler(MyPanel_LayoutUpdated);
        _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
        _timer.Start();
    }
 
    void  _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        Dispatcher.BeginInvoke(new Func<object>(RunNextAnimation));
    }
 
    object RunNextAnimation()
    {
        if (storyBoardQueue.Count == 0) return null;
 
        //check the last animated child
        //if there is space, begin the animation of the next child.
        if (lastAnimated == null)
        {
            var sb = storyBoardQueue.Dequeue();
            var child = childQueue.Dequeue();
            animatingChildQueue.Enqueue(child);
            animatingStoryBoardQueue.Enqueue(sb);
            sb.Begin(child, true);
            lastAnimated = child;
        }
        else
        {
            var x = lastAnimated.RenderTransform.Value.OffsetX;
            if (x + lastAnimated.ActualWidth < ActualWidth - 10)
            {
                var sb = storyBoardQueue.Dequeue();
                var child = childQueue.Dequeue();
                animatingChildQueue.Enqueue(child);
                animatingStoryBoardQueue.Enqueue(sb);
                sb.Begin(child, true);
                lastAnimated = child;
            }
        }
        return null;
    }
 
    void MyPanel_LayoutUpdated(object sender, EventArgs e)
    {
        foreach(var child in Children)
        {
            if (animatedChildren.Contains(child as FrameworkElement)) continue;
            AnimateChild(child as FrameworkElement);
        }
    }
 
    //just to keep track of things we've created storyboards/translations for
    private List<FrameworkElement> animatedChildren = new List<FrameworkElement>();
 
    private Queue<Storyboard> storyBoardQueue = new Queue<Storyboard>();
    private Queue<FrameworkElement> childQueue = new Queue<FrameworkElement>();
 
    private FrameworkElement lastAnimated;
 
    private Queue<Storyboard> animatingStoryBoardQueue = new Queue<Storyboard>();
    private Queue<FrameworkElement> animatingChildQueue = new Queue<FrameworkElement>();
 
    private void AnimateChild(FrameworkElement child)
    {
        if (child == null) return;
 
        NameScope.SetNameScope(child, new NameScope());
 
        var anim = new DoubleAnimation
                   {
                       From = ActualWidth,
                       To = -100,
                       By = -5,
                       Duration = new Duration(TimeSpan.FromSeconds(ActualWidth/40)),
                   };
 
        var transform = new TranslateTransform();
        child.RegisterName("translate", transform);
 
        child.RenderTransform = transform;
        Storyboard.SetTargetName(anim, "translate");
        Storyboard.SetTargetProperty(anim, new PropertyPath(TranslateTransform.XProperty));
 
        var myStoryBoard = new Storyboard();
        myStoryBoard.Children.Add(anim);
        myStoryBoard.Completed += myStoryBoard_Completed;
        storyBoardQueue.Enqueue(myStoryBoard);
        childQueue.Enqueue(child);
 
        animatedChildren.Add(child);
    }
 
    void  myStoryBoard_Completed(object sender, EventArgs e)
    {
        storyBoardQueue.Enqueue(animatingStoryBoardQueue.Dequeue());
        childQueue.Enqueue(animatingChildQueue.Dequeue());
    }
}

Visit Our Friends!

A few highly recommended friends...

Pages List

General info about this blog...