Wednesday, October 1, 2008

C# convert PDF to image format

The solution generally is provided by 3rd party component. In many cases it is not free. E.g., PDFRasterizer.NET component, PDF4NET etc.

Here's one solution: http://www.mobileread.com/forums/showthread.php?t=10137

The GFL SDK/GFLAx (http://www.xnview.com/en/gfl.html) free library component can be used to convert PDF to image format. It works for ASP, VB, C# etc. GhostScript (http://sourceforge.net/projects/ghostscript/) is required for it to work.

Example code in C#:

{
string file = "D:/test.pdf";
string image = "D:\\test.png";

try
{
GflAx.GflAxClass g = new GflAx.GflAxClass();
g.EpsDpi = 150;
g.Page = 1;
g.LoadBitmap(file);
g.SaveFormat = GflAx.AX_SaveFormats.AX_PNG;
g.SaveBitmap(image);
MessageBox.Show(this, "PDF to PNG conversion ended");
}
catch (Exception ex) {
MessageBox.Show(this, "GflAx error: " + ex.Message);
}
}

barcode reader and writer

libdmtx - library of data matrix. Currently hosted at http://www.libdmtx.org/

Thursday, July 10, 2008

SQL statements

- Return primary key of the new inserted entry:

Method 1:
INSERT (..) VALUES (..) INTO tbl ; SELECT @@IDENTITY AS NewID;
Method 2 (preferred over Method 1 in some cases):
INSERT (..) VALUES (..) INTO tbl ; SELECT NEWID = SCOPE_IDENTITY();

An article for more.

- Create a table from another table:

SELECT * FROM tbl_old INTO tbl_new

- Create an empty table from an existing table:

SELECT * INTO tbl_new FROM tbl_old where 1 = 0

- Get column names in a table:

SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.Columns where TABLE_NAME = 'tbl_name'

- Count rows in union statement:

SELECT count(*) FROM (
SELECT field1 FROM table1
UNION
SELECT field2 FROM table2
) as t

- COALESCE - returns first non-null value in list, or null if all values are null

See COALESCE (Transact-SQL).

- Insert from another table in batch mode
 
INSERT INTO MyTable (FirstCol, SecondCol) SELECT Col1, Col2 FROM MyTable2

Thursday, July 3, 2008

C# simulate mouse and keyboard events

This is achieved by calling windows API functions.
Also see
reference.
using System.Runtime.InteropServices;

public class Form1 : System.Windows.Forms.Form {
public enum VK : ushort
{
SHIFT = 0x10,
CONTROL = 0x11,
MENU = 0x12,
ESCAPE = 0x1B,
BACK = 0x08,
TAB = 0x09,
RETURN = 0x0D,
PRIOR = 0x21,
NEXT = 0x22,
END = 0x23,
HOME = 0x24,
LEFT = 0x25,
UP = 0x26,
RIGHT = 0x27,
DOWN = 0x28,
SELECT = 0x29,
PRINT = 0x2A,
EXECUTE = 0x2B,
SNAPSHOT = 0x2C,
INSERT = 0x2D,
DELETE = 0x2E,
HELP = 0x2F,
NUMPAD0 = 0x60,
NUMPAD1 = 0x61,
NUMPAD2 = 0x62,
NUMPAD3 = 0x63,
NUMPAD4 = 0x64,
NUMPAD5 = 0x65,
NUMPAD6 = 0x66,
NUMPAD7 = 0x67,
NUMPAD8 = 0x68,
NUMPAD9 = 0x69,
MULTIPLY = 0x6A,
ADD = 0x6B,
SEPARATOR = 0x6C,
SUBTRACT = 0x6D,
DECIMAL = 0x6E,
DIVIDE = 0x6F,
F1 = 0x70,
F2 = 0x71,
F3 = 0x72,
F4 = 0x73,
F5 = 0x74,
F6 = 0x75,
F7 = 0x76,
F8 = 0x77,
F9 = 0x78,
F10 = 0x79,
F11 = 0x7A,
F12 = 0x7B,
OEM_1 = 0xBA, // ',:' for US
OEM_PLUS = 0xBB, // '+' any country
OEM_COMMA = 0xBC, // ',' any country
OEM_MINUS = 0xBD, // '-' any country
OEM_PERIOD = 0xBE, // '.' any country
OEM_2 = 0xBF, // '/?' for US
OEM_3 = 0xC0, // '`~' for US
MEDIA_NEXT_TRACK = 0xB0,
MEDIA_PREV_TRACK = 0xB1,
MEDIA_STOP = 0xB2,
MEDIA_PLAY_PAUSE = 0xB3,
LWIN =0x5B,
RWIN =0x5C
}

#region Dll Imports

[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}

[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}

[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public uint uMsg;
public ushort wParamL;
public ushort wParamH;
}

[StructLayout(LayoutKind.Explicit)]
struct INPUT
{
[FieldOffset(0)]
public int type;
[FieldOffset(4)]
public MOUSEINPUT mi;
[FieldOffset(4)]
public KEYBDINPUT ki;
[FieldOffset(4)]
public HARDWAREINPUT hi;
}

[DllImport("user32.dll", SetLastError=true)]
private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

const int INPUT_MOUSE = 0;
const int INPUT_KEYBOARD = 1;
const int INPUT_HARDWARE = 2;
const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
const uint KEYEVENTF_KEYUP = 0x0002;
const uint KEYEVENTF_UNICODE = 0x0004;
const uint KEYEVENTF_SCANCODE = 0x0008;
const uint XBUTTON1 = 0x0001;
const uint XBUTTON2 = 0x0002;
const uint MOUSEEVENTF_MOVE = 0x0001;
const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
const uint MOUSEEVENTF_LEFTUP = 0x0004;
const uint MOUSEEVENTF_RIGHTDOWN = 0x0008;
const uint MOUSEEVENTF_RIGHTUP = 0x0010;
const uint MOUSEEVENTF_MIDDLEDOWN = 0x0020;
const uint MOUSEEVENTF_MIDDLEUP = 0x0040;
const uint MOUSEEVENTF_XDOWN = 0x0080;
const uint MOUSEEVENTF_XUP = 0x0100;
const uint MOUSEEVENTF_WHEEL = 0x0800;
const uint MOUSEEVENTF_VIRTUALDESK = 0x4000;
const uint MOUSEEVENTF_ABSOLUTE = 0x8000;


private MOUSEINPUT createMouseInput(int x, int y, uint data, uint t, uint flag) {
MOUSEINPUT mi = new MOUSEINPUT();
mi.dx = x;
mi.dy = y;
mi.mouseData = data;
mi.time = t;
//mi.dwFlags = MOUSEEVENTF_ABSOLUTE| MOUSEEVENTF_MOVE;
mi.dwFlags = flag;
return mi;
}

private KEYBDINPUT createKeybdInput(short wVK, uint flag)
{
KEYBDINPUT i = new KEYBDINPUT();
i.wVk = (ushort) wVK;
i.wScan = 0;
i.time = 0;
i.dwExtraInfo = IntPtr.Zero;
i.dwFlags = flag;
return i;
}

private short getCVal(char c) {
if (c >= 'a' && c <= 'z') return c - 'a' + 0x61;
else if (c >= '0' && c <= '9') return c - '0' + 0x30;
else if (c == '-') return 0x6D; // Note it's NOT 0x2D as in ASCII code!
else return 0; // default
}

///
/// Each time first move the upper left corner, then move from there.
/// x, y: pixel value of position.
///

private void sim_mov(int x, int y) {
INPUT[] inp = new INPUT[2];
inp[0].type = INPUT_MOUSE;
inp[0].mi = createMouseInput(0, 0, 0, 0, MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE);
inp[1].type = INPUT_MOUSE;
inp[1].mi = createMouseInput(x, y, 0, 0, MOUSEEVENTF_MOVE);
SendInput((uint)inp.Length, inp, Marshal.SizeOf(inp[0].GetType()));
}

private void sim_click()
{
INPUT[] inp = new INPUT[2];
inp[0].type = INPUT_MOUSE;
inp[0].mi = createMouseInput(0, 0, 0, 0, MOUSEEVENTF_LEFTDOWN);
inp[1].type = INPUT_MOUSE;
inp[1].mi = createMouseInput(0, 0, 0, 0, MOUSEEVENTF_LEFTUP);
SendInput((uint)inp.Length, inp, Marshal.SizeOf(inp[0].GetType()));
}

private void sim_type(string txt)
{
int i, len;
char[] c_array;
short c;
INPUT[] inp;

if (txt == null || txt.Length == 0) return;

c_array = txt.ToCharArray();
len = c_array.Length;
inp = new INPUT[2];

for (i = 0; i < len; i ++)
{
c = getCVal(txt[i]);

inp[0].type = INPUT_KEYBOARD;
inp[0].ki = createKeybdInput(c, 0);
inp[1].type = INPUT_KEYBOARD;
inp[1].ki = createKeybdInput(c, KEYEVENTF_KEYUP);

SendInput((uint)inp.Length, inp, Marshal.SizeOf(inp[0].GetType()));
}
}

private void sim_actions() {
sim_mov(x0, y0);
sim_click();
}

public Form1() {
InitializeComponent();
//sim_actions();
}

[STAThread]
static void Main() {
Application.Run(new Form1());
}
}

C# screen capture

This is achieved by calling windows API functions.
Also see Reference.

using System.Runtime.InteropServices;
using System.Drawing.Imaging;

public class Form1 : System.Windows.Forms.Form {
#region Dll Imports
[DllImport("user32.dll")]
private static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags);
#endregion

private void screen_capture() {
try {
Bitmap bm = new Bitmap(this.Width, this.Height);
Graphics g = Graphics.FromImage(bm);
IntPtr hdc = g.GetHdc();
Form1.PrintWindow(this.Handle, hdc, 0);
//MessageBox.Show("color: " + bm.GetPixel(550, 300));
g.ReleaseHdc(hdc);
g.Flush();
g.Dispose();
//this.pictureBox1.Image = bm;
bm.Save("test.bmp");
} catch (Exception e) {
MessageBox.Show(this, "error: " + e.Message);
}
}

public Form1() { InitializeComponent(); /* screen_capture(); */ }

[STAThread]
static void Main() { Application.Run(new Form1()); }
}

Thursday, June 19, 2008

Setup Suse 10.3 & Linux notes

This is a memo of setting up Suse 10.3 on Mon Mar 17, 5:18 PM

Download Open Suse: http://en.opensuse.org and see http://en.opensuse.org/Download_Help

Summary - These tools were configured to use:

  • Apache 2.2 web server
  • Bison 2.3
  • Flex 2.5.33
  • Ftp server
  • Gcc 4.2.1 (C/C++)
  • Java 1.5.0
  • Mono (C# cross compiler)
  • MySQL (Ver 14.12 Distrib 5.0.45, for suse-linux-gnu (i686) using readline 5.2)
  • Perl (v5.8.8 built for i586-linux-thread-multi)
  • Php (PHP 5.2.4 with Suhosin-Patch 0.9.6.2 (cli) (built: Sep 23 2007 14:12:53))
  • phpBB 3.0.1
  • Python 2.5.1
  • SSH server

Demos


Apache

  • www root is /srv/www/htdocs/
  • config files are in /etc/apache2/
  • See apache.txt for configuration change.

Crontab

MySQL

Menhir

  • Menhir install records

OCaml

phpBB

  • phpBB website
  • To install is very easy, follow the instruction guide. Note that the database needs to be created manually.
    (For MySQL, in MySQL shell, type "create DATABASE [database_name]")

Python

Ruby on Rails

General note





=hi.cgi=

#!/usr/bin/perl -w
print "Content-type: text/html\n\n";

print "<html><head><title>Hello World! </title></head>\n";
print "<body><h1>Hello world! From Perl CGI</h1></body></html>\n";

=hi.pl=

#!/usr/bin/perl
#use CGI qw(:standard);
#use DBI;
#use strict;

#print header;
#print end_html;

print "Content-type: text/html\n\n";
print "<html><head><title>Hello World! </title></head>\n";
print "<body><h1>Hello world! From public_html/cgi-bin/</h1></body></html>\n";

=chi.cgi=

#include <stdio.h>

int main() {
   printf("Content-type: text/html\n\n");
   printf("hello world from C\n");
   return 0;
}

=index.php=

<?php echo "hello world from php!<br/>"; ?>
<?php phpinfo(); ?>
</p>

=hi.py=

#!/usr/bin/python

import cgitb; cgitb.enable() # provides HTML error support
import cgi

form = cgi.FieldStorage()

def CGI(content_type = "text/html"):
   return 'Content-type: %s\n\n' % content_type

def form_value(key):
   """
   Use this simple method to get http POST's
   """
   val = form.getlist(key)
   if (val == None): return None
   return val

user_name = form_value('user_name')

def display_page(name):
   print CGI()
   print "<html><head><title>"\
   "This is %s's page</title>"\
   "</head><body><h1>Welcome, %s"\
   "</h1><body></html>" %(name, name)
   return 1 #

display_page(user_name)

=index.py=

# This is useless
#def html_header(content_type = "text/html"):
# return 'Content-type: %s\n\n' % content_type

def hello(req, who="nobody"):
   val = "<html><body><h1>Hello, %s</h1></body></html>" % who;
   return val

=everest.pl=

#!/usr/bin/perl -w
use CGI qw(:standard);
use DBI;
use strict;

print header;
#print start_html("Test MySQL Database");
print "<html>\n<head><title>Test MySQL Database</title>\n";
print "<link href="'../everest.css'" rel="'stylesheet'" type="'text/css'">\n";
print "</head>\n<body>\n";

print "<h1>Test MySQL Database</h1><br />\n";

my $dbh;
db_connect();
if (not $dbh) {
   print "cannot open databse<br />\n" . DBI::errstr;
   exit(0);
}
#print "Database opened<br />\n";

# prepare and execute query
my $sort = param("sort");
my $orderby = param("orderby");
get_sortinfo();
my $query = "SELECT * FROM tblEverest ORDER BY $orderby $sort";
#print $query . "<br />";
my $sth = $dbh->prepare($query);
$sth->execute;

# assign fields to variables
my ($id, $pdate, $pname, $pdesc);
$sth->bind_columns(\$id, \$pdate, \$pname, \$pdesc);

print "rows = " . $sth->rows() . "<br />\n";

# output name list to the browser
print "Data in the tblEverest table:<p>\n";
print "<table class="'dataTbl'">\n";
print "<tr class="'dataTitle'">\n" .
   "<td width="50"><a href="'?orderby="id&sort="$sort'">ID</a></td>\n" .
   "<td><a href="'?orderby="date&sort="$sort'">Insertion Date</a></td>\n" .
   "<td><a href="'?orderby="name&sort="$sort'">Protein name</a></td>\n" .
   "<td><a href="'?orderby="desc&sort="$sort'">Description</a></td>\n" .
   "</tr>\n";
while($sth->fetch()) {
   print "<tr><td>$id</td>";
   print "<td>$pdate</td>";
   print "<td>$pname</td><td>$pdesc</td></tr>\n";
}
print "</table>\n";

$sth->finish();

# disconnect from database
$dbh->disconnect;

print end_html;

1;

sub get_sortinfo {
   if ($orderby eq "" or $orderby eq "id") { $orderby = "tblEverestID"; }
   elsif ($orderby eq "date") { $orderby = "InsertDate"; }
   elsif ($orderby eq "name") { $orderby = "Name"; }
   elsif ($orderby eq "desc") { $orderby = "Description"; }

   if ($sort eq "DESC" or $sort eq "") { $sort = "ASC"; }
   else { $sort = "DESC"; }
}

sub db_connect() {
   my ($db, $host, $userid, $passwd, $connectionInfo);
   #database information
   $db="dbname";
   $host="localhost";
   $userid="uid"; # check mysql.user for valid user.
   $passwd="pwd";
   $connectionInfo="DBI:mysql:$db;$host";

   # make connection to database
   $dbh = DBI->connect($connectionInfo,$userid,$passwd);
}


=apache.txt=

http://bozziesfw.wordpress.com/2007/02/24/configuring-apache-using-yast-opensuse-102/
Try this, configure apache2 using YaST.

The apache's www folder is in /srv/www/htdocs/
The index.html file for "It works!" is there.

Add this to /etc/apache2/mod_userdir.conf:

   <Directory /home/*/public_html/cgi-bin>
      AllowOverride None
      Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
      #SetHandler cgi-script
      AddHandler cgi-script .cgi .plx .pp
      Order allow,deny
      Allow from all
   </Directory>

Then restart the httpd server using: /etc/init.d/apache2 force-reload

Then it's ok.

--
php already works by default.
--

Added these to /etc/apache2/mod_userdir.conf:

   <Directory /home/*/public_html/python>
      AddHandler mod_python .py
      PythonHandler mod_python.publisher
      PythonDebug On
   </Directory>

   <Directory /home/*/public_html/cgi-python>
      AddHandler mod_python .py
      PythonHandler mod_python.cgihandler
      PythonDebug On
   </Directory>

Now python works:
# cgi-python/hi.py?user_name=me
(Python as cgi, use mod_python.cgihandler as handler)
# python/index.py (with a function hello(req, who))
(Python, use mod_python.publisher as handler, the better way)

=crontab.txt=

crontab -e : edit the crontab file for the current user.

The result is stored one entry for each user in /var/spool/cron/tabs/.

In /etc/ there are these files:
cron.deny, crontab, cron.d, cron.daily, cron.hourly, cron.monthly, cron.weekly.

I have created a cron job to back up wikidb database. The script is:
/srv/www/htdocs/wiki/database_bck/autobackup

Then use "/etc/init.d/cron restart" to restart the cron daemon.

=Mysql install note=
MySQL

Setup: http://vias.org/linux-knowhow/lnag_09_06.html

Suse-Everest:/etc # /usr/bin/mysql_install_db
Installing MySQL system tables...
OK
Filling help tables...
OK
PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
To do so, start the server, then issue the following commands:
/usr/bin/mysqladmin -u root password 'new-password'
/usr/bin/mysqladmin -u root -h host.dummy.edu password 'new-password'
See the manual for more instructions.
You can start the MySQL daemon with:
cd /usr ; /usr/bin/mysqld_safe &

You can test the MySQL daemon with mysql-test-run.pl
cd mysql-test ; perl mysql-test-run.pl

Please report any problems with the /usr/bin/mysqlbug script!

The latest information about MySQL is available on the web at
http://www.mysql.com
Support MySQL by buying support/licenses at http://shop.mysql.com

Suse-Everest:/etc # chown -R mysql /var/lib/mysql
Suse-Everest:/etc # chgrp -R mysql /var/lib/mysql
Suse-Everest:/etc # /usr/share/mysql/mysql.server start
Suse-Everest:/etc # mysqladmin --user=root password '********'

=ocaml.txt=

Download from:
http://caml.inria.fr/download.en.html
http://caml.inria.fr/pub/distrib/ocaml-3.10/ocaml-3.10.2.tar.gz

Copy ocaml-3.10.2.tar.gz to /usr/local/src/, unzip it.
Then read README, then read INSTALL and follow the instruction in it.

--

Objective Caml system has these commands:

   ocamlc the batch bytecode compiler
   ocamlopt the batch native-code compiler (if supported)
   ocamlrun the runtime system for the bytecode compiler
   ocamlyacc the parser generator
   ocamllex the lexer generator
   ocaml the interactive, toplevel-based system
   ocamlmktop a tool to make toplevel systems that integrate
   user-defined C primitives and Caml code
   ocamldebug the source-level replay debugger
   ocamldep generator of "make" dependencies for Caml sources
   ocamldoc documentation generator
   ocamlprof execution count profiler
   ocamlcp the bytecode compiler in profiling mode

and also, if you built them during step 5, [yes I did]

   ocamlc.opt the batch bytecode compiler compiled with ocamlopt
   ocamlopt.opt the batch native-code compiler compiled with ocamlopt
   ocamllex.opt the lexer generator compiled with ocamlopt

=More notes=

- switch b/w GUI and command line:
press Ctrl+Alt+F2 to leave the graphical user interface.
If you want to go back to the graphical user interface you
should log out from your shell session first. To do so, type
exit and press Enter. Then press Alt+F7 to switch back to the
graphical user interface.

When you are already logged in to the GNOME or the KDE desktop
and want to start a terminal window within the desktop, press
Alt+F2 and enter konsole (for KDE) or gnome-terminal (for GNOME).
To close the terminal window press Alt+F4.

- Bash shortcut keys
http://linuxhelp.blogspot.com/2005/08/bash-shell-shortcuts.html

- Exmaples.
sudo chown wilber kde_quick.xml
History: You can also search for a certain command in the history.
   Press Ctrl+R to start an incremental search function.
Completion: Completing a filename or directory name to its full
   length after typing its first letters is another helpful
   feature of Bash. To do so, type the first letters then
Browse in the history of executed commands:
   press Tab (Tabulator).
8.8 Searching for Files or Contents: locate, find, grep.
   locate .gnome
   find ~ -name *.txt
   grep "music is great" ~*.*
8.10 Redirection and pipe:
   ls -l >> filelist.txt
   ls -l | grep tux
8.11 Handling Processes
   Press Ctrl+Z to suspend the process and enter bg to send
   the process to the background.
   Sending a process to the background directly when starting
   it. To do so, add an ampersand at the end of the command.

-jobs-

Whereas job only shows the background processes started from
a specific shell, the ps command (run without options) shows
a list of all your processes—those you started.

To bring a job to the foreground again, enter fg job number.
Use the kill command to stop a process. This sends a TERM signal
that instructs the program to shut itself down.
e.g., kill 30187
// Alternatively, if the program or process you want to terminate
is a background job and is shown by the jobs command, you can also
use the kill command in combination with the job number to
terminate this process:
kill % job number
kill -9 PID // This sends a KILL signal instead of a TERM signal,
bringing the specified process to an end in most cases.

* Show IP: /sbin/ifconfig
* Configure network card for LAN and Internet access: http://www.swerdna.net.au/linhowtonic.html
* Remote admin: http://en.opensuse.org/YaST_Remote_Administration
* VNC (http://www.realvnc.com/):
192.168.100.1:5900 Use F8 to get menu in full screen mode.
* Setting bash: http://tldp.org/LDP/abs/html/sample-bashrc.html
* Reboot: reboot
* Now sshd and apache2 can automatically start at boot time.
* Enable mysql auto start at boot time: Copy "/usr/share/mysql/mysql.server start" to the end of /etc/init.d/rc
* Configure apache2: /etc/apache2/httpd.conf Add "/etc/apache2/httpd.conf.local" to to value of APACHE_CONF_INCLUDE_FILES in /etc/sysconfig/apache2
* Restart apache2: /etc/init.d/apache2 restart
* Apache: http://httpd.apache.org/
* umask 022: umask 022 - Assigns permissions so that only you have read/write access for files, and read/write/search for directories you own. See http://linuxzoo.net/page/sec_umask.html
* crontab
* Show CPU and Memory information:
   cat /proc/cpuinfo, cat /proc/meminfo

Saturday, March 29, 2008

Wikipedia content copyrights and installation

When trying to copy some material about hyacc to wikipedia, and also put a link to the original source, I was warned by a copyright notice. The effort was aborted.

Later I found this information on copyrights problem when publishing on wikipedia: http://en.wikipedia.org/wiki/Wikipedia:Copyrights

Wikipedia is an open source project: http://sourceforge.net/projects/wikipedia/
From http://en.wikipedia.org/wiki/Mediawiki: "MediaWiki is a web-based wiki software application used by all projects of the Wikimedia Foundation".

The Wikipedia source download page is: http://www.mediawiki.org/wiki/Download
The current stable version is 1.11.1. It can be installed on platforms from FreeBSD, GNU/Linux, MacOS X, Netware, Solaris to Windows.

If install it on linux, I would want to install on Open Suse: http://en.opensuse.org and see http://en.opensuse.org/Download_Help

Blog Archive

Followers