Here is an online book covering data structures in Python.
Category: Uncategorized
Custom Tool to build protobuff files in Visual Studio
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.VisualStudio.TextTemplating.VSHost;
using Microsoft.Win32;
using System.Diagnostics;
{
[Guid(CustomGuidString)]
[ComVisible(true)]
public class MinimalTool : BaseCodeGeneratorWithSite
{
//This allows this to be defined once – the com registration routines need to match the declared guid
StringBuilder _outputBuffer = new StringBuilder();
{
string inputPath = Path.GetDirectoryName(inputFileName);
psi.CreateNoWindow = true;
psi.WorkingDirectory = toolFolder;
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.RedirectStandardError = true;
psi.UseShellExecute = false;
arguments.AppendFormat(@” –proto_path=””{0};{1}”””, toolFolder, inputPath);
arguments.AppendFormat(@” –descriptor_set_out=””{0}{1}.pb”””, toolFolder, rootName);
arguments.AppendFormat(@” “”{0}googleprotobuf{1}”””, toolFolder, “descriptor.proto”);
arguments.AppendFormat(@” “”{0}{1}”””, toolFolder, “csharp_options.proto”);
arguments.AppendFormat(@” “”{0}”””, inputFileName);
{
proc.EnableRaisingEvents = true;
proc.ErrorDataReceived += ProcErrorDataReceived;
proc.BeginErrorReadLine();
proc.WaitForExit();
result = proc.ExitCode;
proc.ErrorDataReceived -= ProcErrorDataReceived;
}
{
StringBuilder results = new StringBuilder();
results.AppendLine();
results.Append(psi.FileName);
results.AppendLine();
results.Append(arguments.ToString());
results.AppendLine();
results.Append(_errorBuffer.ToString());
}
_errorBuffer = new StringBuilder();
psi = new ProcessStartInfo(toolFolder + @”protogen.exe”);
psi.CreateNoWindow = true;
psi.WorkingDirectory = toolFolder;
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.RedirectStandardError = true;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
psi.Arguments = arguments.ToString();
{
proc.EnableRaisingEvents = true;
proc.ErrorDataReceived += ProcErrorDataReceived;
proc.OutputDataReceived += ProcOutputDataReceived;
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
proc.WaitForExit();
proc.ErrorDataReceived -= ProcErrorDataReceived;
proc.OutputDataReceived -= ProcOutputDataReceived;
result = proc.ExitCode;
}
{
StringBuilder results = new StringBuilder();
results.AppendFormat(“There was a problem with the protogen compiler {0}”, result);
results.AppendLine();
results.Append(psi.FileName);
results.AppendLine();
results.Append(arguments.ToString());
results.AppendLine();
results.AppendLine(“Error:”);
results.Append(_errorBuffer.ToString());
results.AppendLine();
results.AppendLine(“Output:”);
results.Append(_outputBuffer.ToString());
return Encoding.ASCII.GetBytes(results.ToString());
}
string sourceContent = File.ReadAllText(inputFileName);
// Now I know the rules:
// 1. It can be specified in option
// (google.protobuf.csharp_file_options).umbrella_classname = “PositionBuffer”;
// 2. If not specified there then:
// take the file name, remove the extension
// Convert to PascalCase, removing punctuation. Numbers and punctuation trigger new words.
Regex re = new Regex(“umbrella_classname[ ]*=[ ]*”(.*)”[ ]*;”);
if (re.IsMatch(sourceContent))
{
// We have pulled the umbrella_classname definition from the source.
outputNamePrefix = re.Match(sourceContent).Groups[1].Value;
}
else
{
outputNamePrefix = UnderscoresToPascalOrCamelCase(rootName, true);
}
{
return Encoding.ASCII.GetBytes(“Unable to determine the umbrella_classname”);
}
{
// Try again
outputFileName = toolFolder + “\” + outputNamePrefix + “.cs”;
{
return Encoding.ASCII.GetBytes(“Unable to find file ” + outputFileName);
}
}
File.Delete(pbFileName);
File.Delete(outputFileName);
}
private static string UnderscoresToPascalOrCamelCase(string input, bool pascal)
{
StringBuilder result = new StringBuilder();
bool capitaliseNext = pascal;
for (int i = 0; i < input.Length; i++)
{
char c = input[i];
if (‘a’ <= c && c <= ‘z’)
{
if (capitaliseNext)
{
result.Append(char.ToUpper(c, CultureInfo.InvariantCulture));
}
else
{
result.Append(c);
}
capitaliseNext = false;
}
else if (‘A’ <= c && c <= ‘Z’)
{
if (i == 0 && !pascal)
{
// Force first letter to lower-case unless explicitly told to capitalize it.
result.Append(char.ToLower(c, CultureInfo.InvariantCulture));
}
else
{
// Capital letters after the first are left as-is.
result.Append(c);
}
capitaliseNext = false;
}
else if (‘0’ <= c && c <= ‘9’)
{
result.Append(c);
capitaliseNext = true;
}
else
{
capitaliseNext = true;
}
}
return result.ToString();
}
{
_outputBuffer.AppendLine(e.Data);
}
{
_errorBuffer.AppendLine(e.Data);
}
{
return “.cs”;
}
new Guid(“{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}”);
= @”SOFTWAREMicrosoftVisualStudio{0}Generators{1}{2}”;
{
string subKey = String.Format(KeyFormat,
vsVersion, categoryGuid.ToString(“B”), CustomToolName);
{
key.SetValue(“”, CustomToolDescription);
key.SetValue(“CLSID”, CustomToolGuid.ToString(“B”));
key.SetValue(“GeneratesDesignTimeSource”, 1);
}
vsVersion, categoryGuid.ToString(“B”), SourceFileExtension);
{
key.SetValue(“”, CustomToolName);
}
}
{
string subKey = String.Format(KeyFormat,
vsVersion, categoryGuid.ToString(“B”), CustomToolName);
public static void RegisterClass(Type t)
{
// Register for both VS.NET 2002, 2003, 2008 and 2010 (C#)
Register(new Version(8, 0), CSharpCategory);
Register(new Version(9, 0), CSharpCategory);
Register(new Version(10, 0), CSharpCategory);
}
public static void UnregisterClass(Type t)
{ // Unregister for both VS.NET 2002, 2003, 2008 and 2010 (C#)
Unregister(new Version(8, 0), CSharpCategory);
Unregister(new Version(9, 0), CSharpCategory);
Unregister(new Version(10, 0), CSharpCategory);
}
}
}
Cheap NAS – Add a USB Drive to your network
This is a great little gadget. Plug one end into your network plug a usb drive in the other end and you have a NAS Router.
It does seem to use samba (if it does then it has failed on the GPL clause of informing the user of the rights).
sc syntax
sc is the utility used to configure a service in windows.
It has the very special syntax insisting on a space after equals signs.
This can be very frustrating until you work this out.
Where to find the System.Management.Automation assembly
Recent deployments of powershell don’t come with this assembly, which you need to write cmdlets in C#.
You need to install the powershell 2.0 sdk and look for:
$(ProgramFiles)Reference AssembliesMicrosoftWindowsPowerShellv1.0System.Management.Automation.dll
Here is a simple cmdlet:
using System.Management.Automation;
namespace SimpleGreeting
{
[Cmdlet(VerbsCommunications.Send, “Greeting”)]
public class SendGreetingCommand : Cmdlet
{
[Parameter(Mandatory=true)]
public string Name { get; set; }
protected override void ProcessRecord()
{
WriteObject(“Hello” + Name + “!”);
}
}
}
And here is the installer required:
using System.Management.Automation;
using System.ComponentModel;
namespace SimpleGreeting
{
[RunInstaller(true)]
public class RegisterSimpleGreeting : PSSnapIn
{
public override string Description
{
get { return “This is a demo snapin”; }
}
public override string Name
{
get { return “SendGreetingSnapin”; }
}
public override string Vendor
{
get { return “C.J Eyre Harlequin Design”; }
}
}
}
You need to use installutil to register the snapin.
OAuth
I have been looking at open source authentication schemes.
Here is a great post on using OAuth from a winforms app.
Printing in wpf
Redirecting Output and Error Streams
This is the code needed to capture both the output and error streams from a console mode application.
using System;
using System.Text;
using System.Diagnostics;
namespace RedirectOutput
{
class Program
{
static StringBuilder errorBufffer = new StringBuilder();
static StringBuilder outputBufffer = new StringBuilder();
static void Main(string[] args)
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.RedirectStandardError = true;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
psi.FileName = “cmd.exe”;
psi.Arguments = “/C dir”;
psi.WorkingDirectory = @”c:photos”;
using (Process p = new Process())
{
p.StartInfo = psi;
p.EnableRaisingEvents = true;
p.OutputDataReceived += p_OutputDataReceived;
p.ErrorDataReceived += p_ErrorDataReceived;
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();
p.WaitForExit();
}
Console.WriteLine(“Error”);
Console.WriteLine(errorBufffer.ToString());
Console.WriteLine(“Output”);
Console.WriteLine(outputBufffer.ToString());
Console.ReadLine();
}
static void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
outputBufffer.AppendLine(e.Data);
}
static void p_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
errorBufffer.AppendLine(e.Data);
}
}
}
Build Providers for Windows Forms
This is a useful article on adding custom build providers.
I am interested in seeing the difference between build providers and custom build tasks.
Mercurial HG
This is my new favorite version control system.
I personally like to develop under the cover of a version control system. I don’t consider professional development to be occurring unless one is being used.
Hg is great for quick refactoring developments. It’s a distributed vcs (like git) so that the application does not enforce a centralised server.
This means that you can commit multiple changes to your local repository before pushing these up to the shared server.
You can also push changesets from developer to developer without going via a central server!
This is wonderful for collaborative development or for those developers who code on the train or plane!
This neatly solves the problems that the PVCS promotion model handles (i.e. how to check in changes without breaking the tested build).
Since you can freely clone a repository refactoring becomes a breeze.
Clone then hack away (checking in whenever it actually compiles and runs the tests). The cloned repository can be thrown away or merged back into the master (or just your current working copy).