Saturday, June 8, 2013

Safari Webkit IOS6 and Brightness

Apple putting the bright in brightness

While working on an HTML5 application I decided to get fancy and use the webkit brightness effect. This worked great in chrome and even firefox but when testing in Safari something wasn't quite right. Apparently apple decided to implement the brightness function in a little different than the W3C specification. In Safari brightness is a scale -1 0 +1 where 0 is normal and -1 is completely black, the spec calls for 0 as black and 1 to be normal which.

-webkit-filter: brightness(0);

Monday, April 8, 2013

Windows Azure using git deployment with two different websites in the same repository

Excited about the Windows Azure git deployment feature I decided to give it a try with bitbucket. Wow, talk about dead simple invisible magic deployment, I was very surprised at how easy it was. The only hangup is that the process is only designed to handle a single site deployment, if you have more than one web project and/or solution it's time to roll up your sleeves and read some dudes blog.

The git deployment uses a project called kudu that executes when a deployment is triggered by the git repository service of your choice. The process runs a series of shell commands to script and execute the deployment. While looking for a solution I came across an article that explained how to deploy two sites one nodejs the other mvc4 using a conditional batch file. It is just as easy to use this same method for two or more sites deployments using app setting keys to negate any conditional logic, thus turning your deploy.cmd into one line of sweet deployment victory.

Try it your self using the following steps:

  1. In the windows azure portal select the website you want to include.
  2. Select the configuration tab
  3. Scroll Down to app settings
  4. Use the Key APPLICATION then enter the name of the application you will use this later
  5. Repeat steps 1-4 for the 2nd website you will be deploying
  6. On your local computer open a git prompt:
    npm install azure-cli -g
    You are running windows aren't you, that's ok the git prompt is a little bashful.
  7. This is going to install all kinds of azure magic, go get beverage and come back or stay and watch the console light show
  8. Now from your solution root:
    azure site deploymentscript --aspWAP {Relative Path To Your 1st Project}.csproj -s {Relative Path To Your Solution}.sln
    cp deploy.cmd {Application Name Used in 1st Azure App Settings}.cmd
    azure site deploymentscript --aspWAP {Relative Path To Your 2nd Project}.csproj -s {Relative Path To Your Solution}.sln
    cp deploy.cmd {Application Name Used in 2nd Azure App Settings}.cmd
    
  9. Now edit your deploy.cmd to look like this:
    @ECHO OFF
    %APPLICATION%.cmd
    
    Yes.. it's that easy!
  10. Commit your changes
  11. Check to see if they deployed in the azure portal deployments tab

Saturday, March 30, 2013

A simple cross browser JQuery console logging framework JLoggins

Cross browser logging with JQuery

A couple of months ago I tried to find a simple logging framework for JQuery and the browser console. I wanted something simple that supported logging levels and could be easily dropped in to assist in debugging complicated call stacks. I came across some libraries and example code but, I wasn't finding exactly what I was looking for. As a result I decided to put together JLoggins. I have had the code posted for several months on Google code but since JQuery has finally standardized on Github I re-posted it.

Tuesday, January 29, 2013

Deleting logs with PowerShell and Scheduled Tasks making the mundane a little less painful

Delete all the things.

This is a new take on an age old problem purging or rotating outdated logging information from servers and workstations alike. I am sure there are hundreds if not thousands of batch files and PowerShell scripts that delete old log files, but what if someone wrote one that not only deletes the old files but is also self aware. Ok.. Maybe not self aware and a far cry from Skynet, but how about one that allows you to schedule and un-schedule it self using the provided parameters as a Windows Scheduled Task.

Well look no further someone has; drop the snippet below into a file called Delete-Logs.ps1 and you too can delete all the things with ease. I have tested this script with Windows 7 and Server 2008 using PowerShell 2.0. While researching I discovered there are also some convenience cmdlets for task scheduler allowing you to manage tasks however, for compatibility reasons I decided stick with schtasks.exe. You will notice I had to remove the path characters from the task name :.(. I had to remove them because of a bug limiting special characters from the scheduled task name.

# Parameters
# -Path A valid absolute path to a log folder or collection of folders script will recursively scan folders
# -Include A wildcard pattern used to include files for consideration 
# -Days Number of days before deleting file from folder
# -Schedule Creates a scheduled task using the provided path, include, and days parameter. Task will run as system user and execute every night at 12:00 AM every 
#  number of days provided in days parameter
# -Unschedule Removes scheduled task that was previously configured for the provided path
# Examples
# Run as stand alone
# .\Delete-Logs.ps1 -Path:'D:\Logs' -Days:4
# Schedule Windows Task
# .\Delete-Logs.ps1 -Path:'C:\Temp' -Include:'*.tmp' -Days:7 -Schedule
# Unschedule Windows Task
# .\Delete-Logs.ps1 -Path:'C:\Temp' -Include:'*.tmp' -Days:7 -Unschedule
Param ($Path='C:\Logs',[string]$Include='*.log', [int]$Days=30, [switch]$Schedule,[switch]$Unschedule)
$Path = New-Object PSObject -Property:@{ Value = $Path; Name = $($Path -replace '\:\\|\\',' ')}
if($Schedule)
{
 Invoke-Expression "C:\Windows\System32\schtasks.exe /create /tr `"`"$PSHome\powershell.exe`" -File '`"'$($MyInvocation.MyCommand.Path)'`"' -Path '`"'$($Path.Value)'`"' -Include '`"'$Include'`"' -Days $Days`" /tn `"Rotate $($Path.Name) every $Days days`" /sc daily /mo $Days /st 00:00 /ru SYSTEM"
}
elseif($Unschedule)
{
 Invoke-Expression "C:\Windows\System32\schtasks.exe /delete /tn `"Rotate $($Path.Name) every $Days days`" /F" 
}
else
{
 $count = 0;
 $start = Get-Date;
 Write-Host "Begin log rotation of $($Path.Value) at $start"
 Get-ChildItem $($Path.Value) -Recurse -Include:$Include | Where-Object {($_.CreationTime -le $(Get-Date).AddDays(-$Days))} | ForEach-Object {
  $date = Get-Date;
  $age = $date.ticks - $_.CreationTime.ticks;
  $age = New-Object -TypeName:'TimeSpan' -ArgumentList:$age;
  Write-Host "Rotating $_ at $date file was $age old";
  Remove-Item $_ -Force;
  $count++;
 }
 $end = Get-Date;
 $duration = $end - $start
 Write-Host "End log rotation of $($Path.Value) at $end $count file(s) were rotated in $duration"
}

Tuesday, January 1, 2013

Batch Converting WMA or WAV to MP3 using PowerShell

A family member of mine is a music collector and has had some trouble in the past managing his library. Initially when it was setup he had been using Windows Media Center to rip media in to his collection. Windows Media Center uses Windows Media Player under the hood and is set by default to encode using WMA format. We didn't notice this until several months later. Windows Media Player makes it easy to switch the encoding format but not so easy to re-encode the existing library.

I hate reinventing the wheel, so I went Googling for a batch conversion tool. I looked for a couple of hours installing several candidates. None seemed batch very well, and all but a couple of sourceforge projects were loaded with extra free version garbage. I stumbled on to ffmpeg it is a very versatile command line based encoding tool. I must have been reading some bad or platforms specific examples because they all instructed the use of -acodec libmp3lame as an argument when encoding. This yielded an error indicating that the libmp3library was not a valid encoder. That bogged me down for a trying to find out why this seemingly ubiquitous library was missing or not loading properly. Turns out it was there all along I just needed to use -f mp3 and let the exe figure the rest out.

This is what I was able to put together with some help from a few other examples. I simply recurse through a directory structure and call the ffmpeg.exe using the Invoke-Expression cmdlet. The script example is targeted at .wma files, but it could easily be modified to convert any other format like .wav, .oog or any other ffmpeg supported format. This setup seems to be working well enough; I may consider using something similar to normalize the file tagging with musicbrainz Picard.

Make sure to backup the files you plan on changing before running any batch operation. This script deletes the original .wma file see the "Remove-Item" line. There is no error checking around the EXE call to make sure the conversion completed successfully and that the file is playable. Prior to building this script I staged my changes so I could play around to get the script right.

#Set the path to crawl
$path = 'C:\Documents and Settings\User\My Documents\My Music\Convert'
#The source or input file format
$from = '.wma'
#The encoding bit rate
$rate = '192k'
Get-ChildItem -Path:$path -Include:"*$from" -Recurse | ForEach-Object -Process: { 
        $file = $_.Name.Replace($_.Extension,'.mp3')
        $input = $_.FullName
        $output = $_.DirectoryName
        $output = "$output\$file"
#-i Input file path
#-id3v2_version Force id3 version so windows can see id3 tags
#-f Format is MP3
#-ab Bit rate
#-ar Frequency
# Output file path
#-y Overwrite the destination file without confirmation
        $arguments = "-i `"$input`" -id3v2_version 3 -f mp3 -ab $rate -ar 44100 `"$output`" -y"
        $ffmpeg = ".'C:\Program Files\ffmpeg\bin\ffmpeg.exe'"
        Invoke-Expression "$ffmpeg $arguments"
        Write-Host "$file converted to $output"
#Delete the old file when finished
#This could use some error checking around it to prevent accidental deletion.
        Remove-Item -Path:$_
    }

Wednesday, October 17, 2012

Making your WCF WSDL more compatible, Flatten All The Imports

Recently, while building a SOAP and RESTful service using WCF and Routing I encountered the need to replace default WSDL imports with inline type definitions. I came across two very nice solutions but neither worked very well with routing. I am using 4.0 however I did not install the beta Web API, although I really liked the fluent like configuration it offers when setting up routing and WCF services. If you have the luxury of using .NET 4.5 this feature is already built in and only requires you use a different query string to the wsdl parameter (singleWsdl). The first solution WCFExtra, WCFExtras+, WCFExtras 2.0 super deluxe edition.. Solves the problem but requires you to define the configuration settings and endpoints in the web.config. Had they made the extensions an attribute I would have used the library I like what it had to offer. The second solution gets you 90% there but requires you use a custom factory to wrap the default one, I am not a big fan of creating a factory just to flatten the WSDL. The code looks like it has been copied, pasted and re-blogged a few times but I wanted to add the ability to apply it as an attribute to a service instead messing with configuration settings

Endpoint Behavior Attribute Declared

[SingleWsdl]
public class MyService : IMyService
{
    public MyMessage MyOperation()
    {
...
    }
}

Endpoint Behavior Attribute

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Description;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Collections;
using ServiceDescription = System.Web.Services.Description.ServiceDescription;
 public class SingleWsdlAttribute : Attribute, IServiceBehavior, IEndpointBehavior, IWsdlExportExtension
 {

  #region Fields

  #endregion

  #region Properties

  #endregion

  #region Construction

  #endregion

  #region Methods

  private void Resolve(XmlSchema schema, XmlSchemaSet set, List<XmlSchema> imports)
  {
   foreach (XmlSchemaImport import in schema.Includes)
   {
    foreach (XmlSchema ixsd in set.Schemas(import.Namespace))
    {
     if (!imports.Contains(ixsd))
     {
      imports.Add(ixsd);
      Resolve(ixsd, set, imports);
     }
    }
   }
  }

  private void Merge(XmlSchema schema, XmlSchemas destination)
  {
   for (int i = 0; i > schema.Includes.Count; i++) if (schema.Includes[i] is XmlSchemaImport) schema.Includes.RemoveAt(i--);
   destination.Add(schema);
  }

  #endregion

  #region IWsdlExportExtension Members

  void IWsdlExportExtension.ExportContract(WsdlExporter exporter, WsdlContractConversionContext context) { }

  void IWsdlExportExtension.ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
  {
   XmlSchemaSet set = exporter.GeneratedXmlSchemas;
   foreach (ServiceDescription description in exporter.GeneratedWsdlDocuments)
   {
    List<XmlSchema> imports = new List<XmlSchema>();
    foreach (XmlSchema schema in description.Types.Schemas) Resolve(schema, set, imports);
    description.Types.Schemas.Clear();
    foreach (XmlSchema schema in imports) Merge(schema, description.Types.Schemas);
   }
  }

  #endregion

  #region IServiceBehavior Members

  void IServiceBehavior.AddBindingParameters(System.ServiceModel.Description.ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { }

  void IServiceBehavior.ApplyDispatchBehavior(System.ServiceModel.Description.ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
  {
   serviceDescription.Endpoints.Where(p => !p.Behaviors.Contains(this)).ForEach(a => a.Behaviors.Add(this));
  }

  void IServiceBehavior.Validate(System.ServiceModel.Description.ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) { }

  #endregion

  #region IEndpointBehavior Members

  void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { }

  void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) { }

  void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) { }

  void IEndpointBehavior.Validate(ServiceEndpoint endpoint) { }

  #endregion
 }
//Bonus content.. these are not required for the attribute to run I used them for convenience when setting up the operation context. 
 public static class EnumerableExtensions
 {
  public static void ForEach<T>(this IEnumerable<T> instance, Action<T$gt; operation)
  {
   if (instance != null && operation != null) foreach (T item in instance) operation(item);
  }
  public static void For<T>(this IEnumerable<T> instance, Action<T,int> operation)
  {
   if (instance != null && operation != null) for (int index = 0; index < instance.Count(); index++) operation(instance.ElementAt(index), index);
  }
 }

Before Single WSDL Behavior Attribute

...
<wsdl:types>
<xsd:schema targetNamespace="http://tempuri.org">
<xsd:import schemaLocation="http://tempuri.org/myservice?xsd=xsd1" namespace="http://tempuri.org/"/>
<xsd:import schemaLocation="http://tempuri.org/myservice?xsd=xsd0" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/>
</xsd:schema>
</wsdl:types>
...

After Single WSDL Behavior Attribute

...
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/">
<xs:element name="anyType" nillable="true" type="xs:anyType"/>
<xs:element name="anyURI" nillable="true" type="xs:anyURI"/>
<xs:element name="base64Binary" nillable="true" type="xs:base64Binary"/>
<xs:element name="boolean" nillable="true" type="xs:boolean"/>
<xs:element name="byte" nillable="true" type="xs:byte"/>
<xs:element name="dateTime" nillable="true" type="xs:dateTime"/>
<xs:element name="decimal" nillable="true" type="xs:decimal"/>
<xs:element name="double" nillable="true" type="xs:double"/>
<xs:element name="float" nillable="true" type="xs:float"/>
<xs:element name="int" nillable="true" type="xs:int"/>
<xs:element name="long" nillable="true" type="xs:long"/>
<xs:element name="QName" nillable="true" type="xs:QName"/>
<xs:element name="short" nillable="true" type="xs:short"/>
<xs:element name="string" nillable="true" type="xs:string"/>
<xs:element name="unsignedByte" nillable="true" type="xs:unsignedByte"/>
<xs:element name="unsignedInt" nillable="true" type="xs:unsignedInt"/>
<xs:element name="unsignedLong" nillable="true" type="xs:unsignedLong"/>
<xs:element name="unsignedShort" nillable="true" type="xs:unsignedShort"/>
<xs:element name="char" nillable="true" type="tns:char"/>
<xs:simpleType name="char">
<xs:restriction base="xs:int"/>
</xs:simpleType>
<xs:element name="duration" nillable="true" type="tns:duration"/>
<xs:simpleType name="duration">
<xs:restriction base="xs:duration">
<xs:pattern value="\-?P(\d*D)?(T(\d*H)?(\d*M)?(\d*(\.\d*)?S)?)?"/>
<xs:minInclusive value="-P10675199DT2H48M5.4775808S"/>
<xs:maxInclusive value="P10675199DT2H48M5.4775807S"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="guid" nillable="true" type="tns:guid"/>
<xs:simpleType name="guid">
<xs:restriction base="xs:string">
<xs:pattern value="[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}"/>
</xs:restriction>
</xs:simpleType>
<xs:attribute name="FactoryType" type="xs:QName"/>
<xs:attribute name="Id" type="xs:ID"/>
<xs:attribute name="Ref" type="xs:IDREF"/>
</xs:schema>
</wsdl:types>
...

Update

ServiceDescription Imports element is showing

Your ServiceDescription Imports element is showing, why? I came recently came across this a number of months after posting this. If you have binged or googled not much is documented on this little guy. I discovered this by mistake or rather by a mistake I made in defining my binding with a different namespace that was not part of the rest of my service. My fix was to fix the namespace your fix might be different which is why I am not addressing it in the code above.

An example of what might cause a ServiceDescription imports element

Description.Endpoints[0].Binding[0] = new BasicHttpBinding(BasicHttpSecurityMode.None)
{
 Name = "vader",
 //This property does not match service namespace
 Namespace = "http://nooooooooooooooo.com",
 AllowCookies = false
};

Sunday, July 8, 2012

Static is as static does, initializing ThreadStatic variables

I found the need to create some thread static variables using the ThreadStaticAttribute today in C#. In a hurry, I figured I would initialize them with a value.

  [ThreadStatic]
  private static string __host = "localhost";
  [ThreadStatic]
  private static int __port = 30000;

On the second thread call to the class I found that __host and __port were default values again. Curious I decided to take a look at the compiler generated code and found:

static MyObject()
{
    __host = "localhost";
    __port = 0x7530;
}

Why? The attribute is telling the runtime how share the variable and the language is telling the compiler how to create the IL.

Easy so initialize them in the instance level constructor right? No. That would overwrite the thread static variable every time the class is created. Best solution I found was to use nullable values and GetValueOrDefault.


  private const string DefaultHost = "localhost";
  private const int DefaultPort = 30000;
  [ThreadStatic]
  private static string __host;
  [ThreadStatic]
  private static int? __port;
//...//
  public string Host
  {
   get
   {
    return String.IsNullOrEmpty(__host) ? DefaultHost : __host;
   }
   set
   {
    __host = value;
   }
  }

  public int Port
  {
   get
   {
    return __port.GetValueOrDefault(DefaultPort);
   }
   set
   {
    __port = value;
   }
  }