public class GenericIntToEnumConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (((Type)parameter).IsEnum && value is int) { return Enum.GetName((Type)parameter, value); } return null; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return (int)value; } } public enum ExampleEnum { First = 1, Second =2, Third =3 }Usage is very easy we just pass as the parametr the destination enum:
poniedziałek, 17 czerwca 2013
Generic Int to Enum Converter - WPF example
I'm proud to present how to convert integer value to any enum you ever would like to :-)
Below example ilustrates use it e.g in WPF application.
We need to create Converter class as showed below. And of course create some enums
wtorek, 12 lutego 2013
Deploy SQLite .net application
Below I describe how to configure C# .net application to work with SQLite database client.
First download and install sqlite ado.net provider. Then include to your project configuration below settings:
Enjoy.
First download and install sqlite ado.net provider. Then include to your project configuration below settings:
Add to project references files:
- SQLite.Designer
- System.Data.SQLite
- System.Data.SQLite.Linq
Enjoy.
sobota, 19 stycznia 2013
C# Command Line Arguments Parser
There is probably several good ways to parse command line arguments in C# console application. But when I encountered such problem in my work first what I thought was to stop inventing wheel once again :-)
After short research I realized that in most cases I need lightweight reusable code which I can easily adapt for current requirements. At first I found ConsoleFx library. After short code analysis I was sure that it looks really good for me but... In my opinion it's heavy: a lot of classes with really reach functionality. So that wasn't exactly what I need because I also required lightweight solution. And then I found sample of small handler which is great and you will find it below.
So how is the magic happens?
args.Process( () => Console.WriteLine("Usage is switch1=value1,value2 switch2=value3"), new CommandLine.Switch("switch1", val => Console.WriteLine("switch 1 with value {0}", string.Join(" ", val))), new CommandLine.Switch("switch2", val => Console.WriteLine("switch 2 with value {0}", string.Join(" ", val)), "s1")); }
All of the magic happens inside the Process method, where the query tries to match the arguments against the ones we want to check for. The .Sum() aggregate method does two things. It enumerates the elements of the IQueryable, actually calling the handlers in the process. Nothing happens till then! Each of the InvokeHandler calls returns 1, so the result of the .Sum() is 0 if there were no matches (which is when we call the supplied printUsage handler).
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace SampleConsoleApplication { /* Simple commandline argument parser written by Ananth B. http://www.ananthonline.net */ static class CommandLine { public class Switch // Class that encapsulates switch data. { public Switch(string name, Action<IEnumerable<string>> handler, string shortForm) { Name = name; Handler = handler; ShortForm = shortForm; } public Switch(string name, Action<IEnumerable<string>> handler) { Name = name; Handler = handler; ShortForm = null; } public string Name { get; private set; } public string ShortForm { get; private set; } public Action<IEnumerable<string>> Handler { get; private set; } public int InvokeHandler(string[] values) { Handler(values); return 1; } } /* The regex that extracts names and comma-separated values for switches in the form (<switch>[="value 1",value2,...])+ */ private static readonly Regex ArgRegex = new Regex(@"(?<name>[^=]+)=?((?<quoted>\""?)(?<value>(?(quoted)[^\""]+|[^,]+))\""?,?)*", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase); private const string NameGroup = "name"; // Names of capture groups private const string ValueGroup = "value"; public static void Process(this string[] args, Action printUsage, params Switch[] switches) { /* Run through all matches in the argument list and if any of the switches match, get the values and invoke the handler we were given. We do a Sum() here for 2 reasons; a) To actually run the handlers and b) see if any were invoked at all (each returns 1 if invoked). If none were invoked, we simply invoke the printUsage handler. */ if ((from arg in args from Match match in ArgRegex.Matches(arg) from s in switches where match.Success && ((string.Compare(match.Groups[NameGroup].Value, s.Name, true) == 0) || (string.Compare(match.Groups[NameGroup].Value, s.ShortForm, true) == 0)) select s.InvokeHandler(match.Groups[ValueGroup].Value.Split(','))).Sum() == 0) printUsage(); // We didn't find any switches } } }Author Licence
The code above is for you to do whatever you want to. Even if it blows you up (like Dr. Manhattan blows Rorschach up), don’t come back from the dead to haunt me. I would, however appreciate it if you kept the comment attributing that code to me.My comments So far I haven't found any bugs in such code. Click here to go to my repository with appropriate unit tests
niedziela, 13 stycznia 2013
How set up WOL (Wake On Lan) on Thin Client with ubuntu
I set up small home server using HP TERMINAL HP T5000 (Thin Client). I installed Ubuntu server on it. It works great - but recently I realized that I need to have this server up only for very limited number of scenarios i.e. when I'm working on one of my PCs (so I want to have access to server resources e.g. samba, cups, DNS server etc) or I'm downloading something from the internet using transmission-daemon. To optimize my server power consumption I decided to set up Wake On Lan on my ubuntu and wrote 2 simple scripts in ruby.
How to set up WOL on ubuntu?
Log in as administrator.
Install ethtool:
sudo apt-get install ethtoolChange to the startup script directory and start editing a new file:
cd /etc/init.d/ nano wakeonlanconfigPaste, or type this into the file, replacing eth0 with your network device, repeat the ethtool line as many times for your devices before the exit line:
#!/bin/bash ethtool -s eth0 wol g exitSet the permissions of the file:
chmod a+x wakeonlanconfigMake the script run on startup:
update-rc.d -f wakeonlanconfig defaultsYou should see something like:
Adding system startup for /etc/init.d/wakeonlanconfig ... /etc/rc0.d/K20wakeonlanconfig -> ../init.d/wakeonlanconfig /etc/rc1.d/K20wakeonlanconfig -> ../init.d/wakeonlanconfig /etc/rc6.d/K20wakeonlanconfig -> ../init.d/wakeonlanconfig /etc/rc2.d/S20wakeonlanconfig -> ../init.d/wakeonlanconfig /etc/rc3.d/S20wakeonlanconfig -> ../init.d/wakeonlanconfig /etc/rc4.d/S20wakeonlanconfig -> ../init.d/wakeonlanconfig /etc/rc5.d/S20wakeonlanconfig -> ../init.d/wakeonlanconfigNow finish by running it, and making sure there are no errors.
/etc/init.d/wakeonlanconfigNow when the server can be started remotely I want to present you 2 scrips which I wrote in ruby to make my life easier. First for client machines. All I need to do in this script is checking state of my server and if it is down send magic packet to power it on.
begin require 'Win32/Console/ANSI' rescue LoadError raise 'You must gem install win32console to use color on Windows' end require 'logger' require 'net/ping' require File.dirname(__FILE__) + "/wakeonlan.rb" class String def red; colorize(self, "\e[1m\e[31m"); end def green; colorize(self, "\e[1m\e[32m"); end def dark_green; colorize(self, "\e[32m"); end def yellow; colorize(self, "\e[1m\e[33m"); end def blue; colorize(self, "\e[1m\e[34m"); end def dark_blue; colorize(self, "\e[34m"); end def pur; colorize(self, "\e[1m\e[35m"); end def colorize(text, color_code) "#{color_code}#{text}\e[0m" end end log = Logger.new(File.dirname(__FILE__) + '/logs/log.txt', 'monthly') log.debug "Script has been started" puts "Ping ubuntu server" log.debug "Ping ubuntu server" p = Net::Ping::TCP.new('my_server_IP', 'http').ping? if !p puts "Getting server up" log.debug "Getting server up" puts "Sending magic packet to ubuntu server" wol=WakeOnLan.new wol.wake("my_server_mac_address", "broadcast", "my_server_IP") # args: MAC_address Broadcast IP_address wol.close else puts "Server is running".dark_green log.debug "Server is running" endBelow I present code for WakeOnLan class which I used in above code:
# K.Kodama 2003-04-20 revised/bug fix # K.Kodama 2000-05-10 # This program is distributed freely # in the sense of GNU General Public License or ruby's. require "socket" class WakeOnLan attr :socket def initialize @socket=UDPSocket.open() @socket.setsockopt(Socket::SOL_SOCKET,Socket::SO_BROADCAST,1) end; def close; @socket.close; @socket=""; end def wake(mac_addr, broadcast="", ip_addr="") wol_magic=(0xff.chr)*6+(mac_addr.split(/:/).pack("H*H*H*H*H*H*"))*16 if broadcast==""; # Set broadcast. Assume that standard IP-class. ips=ip_addr.split(/\./);c=ips[0].to_i if c<=127; ips[1]="255";end # class A:1--127 if c<=191; ips[2]="255";end # class B:128--191 if c<=223; ips[3]="255";end # class C:192--223 # class D:224--239 multicast broadcast=ips.join(".") end 3.times{ @socket.send(wol_magic,0,broadcast,"discard") } end end if $0 == __FILE__ =begin Sample for WakeOnLan class. Use as: ruby wakeonlan.rb [broadcast_address] < data_text line format of data_text: ip-address hostname MAC-address Data sample: 10.20.30.40 wake-pc 100:110:120:130:140:150 Note. To check WOL packet, use tcpdump -x. =end if ARGV.size>=1; broadcast=ARGV[0]; ARGV.clear; else broadcast=""; end wol=WakeOnLan.new while gets ip,name,hw=$_.sub(/^\s+/,"").split(/\s+/) wol.wake(hw, broadcast, ip) end wol.close endSecond for server. I'm checking here state of network i.e. if any of my PCs is working. In case when all my PCs are offline server could be turn off but before I'll send halt command I have to check status of transmission-daemon - check if there are any elements being downloaded at the moment. If all conditions passed server is going to be shut down.
require 'net/ping' require 'logger' require 'transmission_api' class TorrentStatus attr_accessor :all_torrents_finished def initialize() @transmission_api = TransmissionApi.new( :username => "my_user", :password => "password", :url => "http://myserver:9091/transmission/rpc" ) torrents = @transmission_api.all @all_torrents_finished = true torrents.each{|t| #puts "#{t["name"]} - [#{t["percentDone"]}]" @all_torrents_finished &= (t["percentDone"] == 1) } end end class LanStatus def initialize() @interfaces = ["192.168.zzz.xxx","192.168.zzz.yyy"] end def active_computers_in_network? active = false @interfaces.each{|ip| active |= Net::Ping::External.new(ip).ping? } active end end log = Logger.new(File.dirname(__FILE__) + '/logs/shutdown_log.txt') log.debug "Script has been started" puts "Checking system state" log.debug "Checking system state" print " * Torrent status " torrent_status = TorrentStatus.new all_torrents_finished = torrent_status.all_torrents_finished puts "- [#{all_torrents_finished ? "idle" : "active"}]" log.debug " * Torrent status - [#{all_torrents_finished ? "idle" : "active"}]" print " * Lan status" lan_status = LanStatus.new active_computers_in_network = lan_status.active_computers_in_network? puts "- [#{active_computers_in_network ? "active" : "inactive"}]" log.debug " * Lan status - [#{active_computers_in_network ? "active" : "inactive"}]" if (all_torrents_finished && !active_computers_in_network) puts "Sending HALT command to system" log.debug "Sending HALT command to system" system "sudo shutdown -h now" endThere was still problem how to make it automated process. From the server side i use cron to schedule job which will execute in every 5 minutes and run ruby script. To read more about setting cron please read this post. I added to crontab below entry:
0/5 * * * * ruby /home/luke/scripts/shut_down.rbAll my clients work under windows system and they are not attached to domain. So i just added ruby script to logon scripts. To add logon script for Windows 7 Home Premium: I've created a script at C:\Windows\System32\repl\import\scripts\start.bat Which executes command:
ruby /path_to_my_script/login.rbThen I invoked from command line
net user USERNAME /scriptpath:start.bat
How to schedule Cron to run jobs every 5 Minutes, 12 hours, etc.
Linux Crontab Format
00 – 0th Minute (Top of the hour)
10,16 – 10 AM and 4 PM
* – Every day
* – Every month
* – Every day of the week
00 – 0th Minute (Top of the hour)
10-15 – 10 am,11 am, 12 am, 1 pm, 2 pm, 3 pm
* – Every day
* – Every month
* – Every day of the week
In the same way, use */10 for every 10 minutes, */15 for every 15 minutes, */30 for every 30 minutes, etc.
In the same way, use */2 for every 2 hours, */3 for every 3 hours, */4 for every 4 hours, etc.
Table: Cron special keywords and its meaning
Keyword Equivalent
@yearly 0 0 1 1 *
@daily 0 0 * * *
@hourly 0 * * * *
@reboot Run at startup.
This configuration execute the financial database annual maintenance using sell-db-annual-maintenance shell script at 00:00 on Jan 1st for every year.
MIN HOUR DOM MON DOW CMD
Schedule a job for more than one instance (e.g. twice a day)
Below example executes the specified script (send_reports.rb) at 10:00 and 16:00 on every day. The comma separated value in a field specifies that the command needs to be executed in all the mentioned time.00 10,16 * * * ruby /home/luke/scripts/send_reports.rb
10,16 – 10 AM and 4 PM
* – Every day
* – Every month
* – Every day of the week
Schedule a job for specific range of time (e.g. only on weekdays)
To schedule a job to be ran for every hour with in a specific range of time then use the following. This example checks the status of the server everyday (including weekends) during the working hours 10 a.m – 3 p.m00 10-15 * * * ruby /home/luke/scripts/check-server-status.rb
10-15 – 10 am,11 am, 12 am, 1 pm, 2 pm, 3 pm
* – Every day
* – Every month
* – Every day of the week
Execute a job every 5 minutes
*/5 * * * * /home/luke/scripts/do_work.sh
Execute a job every 5 hours
0 */5 * * * /home/luke/scripts/backup.sh
Keyword Equivalent
@yearly 0 0 1 1 *
@daily 0 0 * * *
@hourly 0 * * * *
@reboot Run at startup.
Schedule a job for first minute of every year using @yearly
When you want a job to be executed on the first minute of every year, then you can use the @yearly cron keyword in way shown below.@yearly /home/luke/scripts/sell-db-annual-maintenance
Schedule a background job every day using @daily
Use the @daily cron keyword to do a daily backup file using backup-invoices shell script at 00:00 on every day.@daily /home/luke/scripts/backup-invoices "day started"
Subskrybuj:
Posty (Atom)