2022年8月20日土曜日

 

https://qiita.com/botisle/items/87b39e7879d788c2e8d7  参照


SCPIによる測定器の自動化

ネットワーク自動化 Advent Calendar 2019 12/17分のエントリー

モチベーション

測定器を用いたネットワーク機器のパフォーマンス計測や状態計測(光量計測 など)は
決められた計測メニューを繰り返し実施する事が多く、その都度に設定するのは非効率となる。

また、一定のインターバルを設定した長期間計測やパラメーターを変えながらの繰り返し計測を実施する場合
測定器によっては、計測メニュー 等でフレキシブルに対応する事が出来ない。

上記の問題点を解消する為に測定器をプログラマブルに制御し、自動化したい。

SCPI

SCPI(Standard Commands for Programmable Instruments)は
測定器の統一的な制御を目的としたコマンド群となる。

SCPIはGPIB(※) 等で知られるIEEE 488規格の中で産まれたコマンド群である為
元々はGPIB通信 などで使用されてきたが
現在ではTCP/IP通信、シリアル通信、USB通信 等にも対応している。
※当時のHP(HP -> Agilent -> Keysight)が測定器とPC等を接続し制御する為に開発したHPIBという規格が
 他社でも広く採用されたもの(後にIEEE 488 として標準化された)

GPIBは測定器インターフェースのデファクトスタンダード的な役割を持っていたものの
GPIBケーブル、コネクタのサイズの大きさや接続数制限、ケーブル長制限といった問題を抱えていた。
様々なインターフェースに対応した事で
PCと測定器を接続する際にPC側にGPIBインターフェースを持つ必要は無くなった。

SCPIはIEEE 488.2で定義された共通コマンドと各測定器に固有なサブシステムコマンドの2種類に大別される。
どちらのコマンドも値を設定する場合はコマンドに続いてパラメーターを指定し
値を参照したい場合はコマンドの最後に?(クエスチョンマーク) を付与する。

■ 共通コマンド
 先頭が*(アスタリスク)でその後、3文字が続く

 *XXX

 例)製品名を確認する
  *IDN?
  → VIAVI Solutions,MTS 6000A V2,00001,ISU,18.00

■ サブシステムコマンド
 階層構造を持ち、階層間のキーワードを:(コロン)で区切る

 SYSTem:
      DATe
      TIMe
      SCReen

 例)システムの日付を設定する、日付を確認する
  SYSTem:DATe 2020,01,01
  SYSTem:DATe?
  → 2020,01,01

SCPIの利用形態としては様々あり、以下がその1部の例となる。

interface.png

VISA(Virtual Instrument Software Architecture)とはSCPI環境で使用されるライブラリであり
インターフェース(RJ45、RS-232、USB、GPIB)の違いを吸収し、統一的な環境を提供する。
 Python だとPyVISA という実装がある

ただ、今回はVISAライブラリを利用せずに最も汎用的に使える RAW SOCKETを利用する事とする。
 上図だと1番下の例

検証目的と環境

検証目的

光スペクトラムアナライザー(OSA)を用いて、WDM装置からの光信号を10分間隔で1日間計測する。
 OSAの種類によっては、インターバル時間と計測期間を指定できるものもあるが本検証対象は非対応

検証環境

端末:CentOS 7.2、Python 2.7.5
測定器:VIAVI Solutions MTS 6000A V2(本体) + I-PMD(OSAモジュール)

端末と測定器をUTPケーブルで接続し、測定器と計測対象である伝送装置を光ケーブルで接続する。

env1.png

伝送装置のコンポーネントであるMux/Demux や ROADMにはMonitor Portと呼ばれるポートがある事が多く
伝送装置が伝送している光信号をモニタリングする事が出来る。
これを利用する事でプロダクション環境であってもin-serviceで光信号の計測が可能となる。

検証コード

■ 実際に手動で計測する手順

前提
 計測には前もって設定してある計測メニューを使用

計測
 測定器のハードキー「START」を押下して計測を開始

計測結果のファイル保存
 測定器のハードキー「FILE」を押下
 その後、測定器のソフトキー「Store」→「Save」→「Enter」→「Exit」を押下

ハードキー
 測定器に搭載されている物理的なキー
hardkey_all.png

ソフトキー
 測定器の画面上に表示されるソフトウェア的に再現されたキー
 画面によりキーの内容が変わる
softkey_all.png

■ コード

上記のオペレーションを以下の通りにコードで表現

import socket
import time

ip = '192.168.0.100'
port = 8000
status = ''

# TCPソケットを生成し測定器に接続
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.connect((ip, port))

# リモート制御をする場合は最初に*REMコマンドを実行し、Programmed Mode に変更
# コマンドの最後に改行コードを挿入(VISAライブラリを利用している場合は考慮不要)
s1.send('*REM\n')

# 測定器本体への接続(Port 8000)とは別にOSAモジュールへの接続が必要
# MOD:FUNC:PORT?コマンドでOSAモジュールへの接続Portを確認(default Port 8002)
# コマンドパラメーターとして、モジュール搭載位置(pwrside,slic1)とモジュール名(I-PMDモジュール="PIB") を指定
s1.send('MOD:FUNC:PORT?pwrside,slic1,"PIB"\n')
port = int(s1.recv(1024))

# OSAモジュールへ接続
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.connect((ip, port))
s2.send('*REM\n')


# 計測を1日間(600秒 x 144回) 実行
for i in range(144):
    # ハードキー:START を押下
    s1.send('KEY START\n')
    time.sleep(5)

    # 計測に数秒を要する為、OSAモジュールの状態を監視
    while 'STOPPED' not in status:
        # OSAモジュールの現ステータスを確認
        s2.send('STATus:ACQ?\n')
        status = s2.recv(1024)
        time.sleep(1)

    # ハードキー:FILE を押下
    s1.send('KEY FILE\n')
    time.sleep(5)

    # ソフトキー:SK1 = Store を押下
    s2.send('KEY SK1\n')
    time.sleep(5)

    # ソフトキー:SK2 = Save を押下
    s2.send('KEY SK2\n')
    time.sleep(5)

    # ソフトキー:SK7 = Enter を押下
    s2.send('KEY SK7\n')
    time.sleep(5)

    # ソフトキー:SK7 = Exit を押下
    s2.send('KEY SK7\n')

    time.sleep(575)

s2.close()
s1.close()

■ 補足

SCPI用Port
 下記コマンドからも分かるように、IANAの割当はPort 5025 となっているが
 今回の対象測定器はPort 8000 となる。

# whatportis 5025
+----------+------+----------+-------------+
| Name     | Port | Protocol | Description |
+----------+------+----------+-------------+
| scpi-raw | 5025 | tcp, udp | SCPI-RAW    |
+----------+------+----------+-------------+

キー入力間のsleep処理
 本来であれば、共通コマンドの*WAIコマンドを使い
 実行コマンドの終了を確認後に次の処理へ移るが
 今回の対象測定器では実装が確認出来なかった為、time.sleepを利用した。
 計測のインターバルにそれ程の精度は求めていない為、許容する。

計測結果のファイル保存
 ファイル名は事前の設定により、任意の文字列+数字の連番 となっている為
 自動でユニークなファイル名となる。

以上、かなり原始的なプログラミングとはなるが
その分、手動オペレーションとのイメージの乖離がない自動計測を可能とした。

2022年7月19日火曜日

  PlaneAhead 落っこちる。32bit 起動 ISEから

参照:

https://www.haljion.net/index.php/2019-11-13-03-27-18/2019-11-13-11-33-14/120-fpga/2019-11-18-02-29-10/188-windows8-os-ise-webpack


ISE のLaunch (Plan AheadをISEからcall するプロセス)にオプションがついている。-m64 これが64bitを起動するオプション。

どこで変更するかわからないので、呼び出された側(batファイル)の分岐でどんなオプションが来てもwin32をcallするよう変更  


Xilinx社製のISE WebPACKは,Spartan6などの6シリーズより以前のFPGAに回路を構築するためのIDEです.2015年現在,Vertex7のように7シリーズに回路を構築するにはVivadoというIDEを使うことになり,おそらく今後,Vivadoで6シリーズ以前のFPGAには対応しないと思われます.つまり,6シリーズ以前のデバイスを使うには引き続きISE WebPACKを使用しなければならないということです.しかし困ったことに,ISE WebPACKはWindows8以降のOSではまともの動作しません.この文書ではこの問題の回避方法について述べています.


環境

まず,動作環境を示しておきます.

  • OS : Windows8以降(Windows8.1を含む), 64ビット
  • ISE WebPACK : 14.7(ISE WebPACKの最後のバージョン)

インストール

インストール方法についてはこちらで説明していますが,ライセンスの設定のみ行えませんので,後述の「Windows8以降で動作させるための設定」を行った後,ライセンスの設定を行ってください.ライセンスの設定方法はこちらに書いておきます.


 Windows8以降で動作させるための設定

Windows8以降のOSでISE WebPACKを動作させようとして問題となることは大きく分けて2種類あります.一つはファイルセレクタが動作しないこと,もう一つは64ビット版の外部アプリケーションであるPinAheadが起動しないことです.これらの問題を解決するため,2個の設定を行いましょう.

libPortability.dllの修正

libPortability.dllはファイルセレクタのためのダイナミックリンクライブラリです.これが悪さをしているため,ライセンスの設定やISE WebPACKのファイルを開くことができません.次に示す2個のディレクトリにあるlibPortability.dllをバックアップ(例えばファイル名に「_orig」を付ける)してください.

C:¥Xilinx¥14.7¥ISE_DS¥ISE¥lib¥nt64
C:¥Xilinx¥14.7¥ISE_DS¥common¥lib¥nt64

次に,C:¥Xilinx¥14.7¥ISE_DS¥ISE¥lib¥nt64にある「libPortabilityNOSH.dll」をコピーし,名前を「libPortability.dll」にしてください.同様に,C:¥Xilinx¥14.7¥ISE_DS¥common¥lib¥nt64へも「libPortabilityNOSH.dll」をコピーし,名前を「libPortability.dll」にしてください.

32ビット版PlanAheadを起動するように変更

PlanAheadは独立したアプリケーションで,64ビット版をWindows8以降のOSで動作させようとしても動きません.そこで,ISE WebPACKから32ビット版のPlanAheadを動作させるように変更します.ISE WebPACKからPlanAheadを呼び出すとき,下記のバッチファイルを用いています.

C:¥Xilinx¥14.7¥ISE_DS¥PlanAhead¥bin¥rdiArgs.bat

このバッチファイル内で,32ビット版PlanAheadを動作させるように変更します.このファイルをrdiArgs.bat.orig等のようなファイルとしてコピーしておいた上で,下記の変更をしてください.

  • 16,17,18,20行目の各行のはじめに「rem #」を付けてください.これにより,16~18と20行目はコメントアウトされます.
  • 32行目にある「win64」を「win32」に変更してください.

ライセンスの設定方法

通常,インストール時にライセンスを設定できるのですが,ファイルセレクタが動かないため,インストール時には設定できません.そこで,インストール時にはライセンスの設定をせずに終了したのち,ISE WebPACKを起動し,メニュー[Help]⇒[Manage License...]を選んでください.この手順ではライセンスを設定できない場合があります.具体的にはライセンスを設定するアプリケーション(xlcm.exe)が立ち上がってこない現象が見られました.その場合にはこちらにある方法で対応してください.

2022年6月21日火曜日

Ras Piカメラ RTSPほか

 


https://qiita.com/lis-hanzomon/items/cc1f7f316fbeb9579b28  参照


https://www.blogger.com/blog/post/edit/7435233686980675536/1874155317581794248

MJPEGは古いんだろうか。。


【プログラミング】

2022年2月19日土曜日

Raspberyy Pi rtsp server

 


Raspberyy Pi  rtsp

Raspberry Pi と USB接続のWebカメラ で


1 はじめに

手軽に利用できるRTSPサーバ:Raspberry Pi 

使用:v412rtspserver

https://github.com/mpromonet/v4l2rtspserver


Linux OSのディストリとバージョン

$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 9.4 (stretch)
Release: 9.4
Codename: stretch

カーネル

$ uname -a
Linux raspberrypi 4.14.79-v7+ #1159 SMP Sun Nov 4 17:50:20 GMT 2018 armv7l GNU/Linux

(3) Webカメラ

http://buffalo.jp/product/multimedia/web-camera/bsw32km01h/


3 コンパイル等


(1) カメラの認識

カメラが /dev/video0 で認識できていることの確認

$ v4l2-ctl --list-devices
USB Camera: USB Camera (usb-3f980000.usb-1.1.3):
/dev/video0

/etc/modulesにbcm2835-v4l2を追加して再起動する

# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.

i2c-dev
bcm2835-v4l2

(2) 必要モジュールのインストール

$ sudo apt-get install cmake
$ sudo apt-get install subversion
$ sudo apt-get install liblivemedia-dev

(3) コンパイル及び、インストール

$ git clone https://github.com/mpromonet/h264_v4l2_rtspserver.git
$ cd h264_v4l2_rtspserver
$ sudo cmake .
$ sudo make install

コンパイル及び、インストールが完了すると、/usr/local/bin/v4l2rtspserverが利用可能になります。

Install the project...
-- Install configuration: ""
-- Installing: /lib/systemd/system/v4l2rtspserver.service
-- Installing: /usr/local/bin/v4l2rtspserver
-- Installing: /usr/local/share/v4l2rtspserver/index.html
-- Installing: /usr/local/share/v4l2rtspserver/hls.js/dist/hls.light.min.js

4 配信

v4l2rtspserverを実行するだけで、デフォルト値でRTSPサーバとして動作します。(採用されたデフォルト値は、コンソールに表示されます。)

$ sudo v4l2rtspserver
Create V4L2 Source.../dev/video0
driver:uvcvideo capabilities:84200001 mandatory:4000001
/dev/video0 support capture
/dev/video0 support streaming
/dev/video0:YUYV size:640x480
Cannot set pixelformat to:H264 format is:YUYV
/dev/video0:MJPG size:640x480 bufferSize:614400
fps:1/30
nbBuffer:0
Device /dev/video0 nb buffer:10
Create Source .../dev/video0
begin thread

デフォルトで起動した場合、rtsp://<RaspberryPiのアドレス>:8554/unicastでアクセス出来ます。(デフォルトでポート8554、パスは/unicastとなっています)

パラメータでデフォルト値以外の指定も可能です。

./v4l2rtspserver [-v[v]] [-Q queueSize] [-O file] \
[-I interface] [-P RTSP port] [-p RTSP/HTTP port] [-m multicast url] [-u unicast url] [-M multicast addr] [-c] [-t timeout] \
[-r] [-s] [-W width] [-H height] [-F fps] [device1] [device2]
-v : verbose
-vv : very verbose
-Q length: Number of frame queue (default 10)
-O output: Copy captured frame to a file or a V4L2 device

RTSP options :
-I addr : RTSP interface (default autodetect)
-P port : RTSP port (defa-ult 8554)
-p port : RTSP over HTTP port (default 0)
-U user:password : RTSP user and password
-R realm : use md5 password 'md5(::')
-u url : unicast url (default unicast)
-m url : multicast url (default multicast)
-M addr : multicast group:port (default is random_address:20000)
-c : don't repeat config (default repeat config before IDR frame)
-t secs : RTCP expiration timeout (default 65)
-S[secs] : HTTP segment duration (enable HLS & MPEG-DASH)

V4L2 options :
-r : V4L2 capture using read interface (default use memory mapped buffers)
-w : V4L2 capture using write interface (default use memory mapped buffers)
-s : V4L2 capture using live555 mainloop (default use a separated reading thread)
-f : V4L2 capture using current capture format (-W,-H are ignored)
-fformat : V4L2 capture using format (-W,-H are used)
-W width : V4L2 capture width (default 640)
-H height: V4L2 capture height (default 480)
-F fps : V4L2 capture framerate (default 25, 0 disable setting framerate)
-G x[x] : V4L2 capture format (default 0x0x25)

ALSA options :
-A freq : ALSA capture frequency and channel (default 44100)
-C channels: ALSA capture channels (default 2)
-a fmt : ALSA capture audio format (default S16_LE)

device : V4L2 capture device and/or ALSA device (default /dev/video0)

5 自動起動

Raspberry Pi を起動しただけで、自動的に配信が開始するように、/etc/rc.local に /usr/local/bin/v4l2rtspserver を書いておきます。

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi

/usr/local/bin/v4l2rtspserver -W 1280 -H 960 -F 7

exit 0


2021年11月13日土曜日

Delphi10 など ShellExecute

 

参照:

https://www.greelane.com/ja/%e7%a7%91%e5%ad%a6%e6%8a%80%e8%a1%93%e6%95%b0%e5%ad%a6/%e3%82%b3%e3%83%b3%e3%83%94%e3%83%a5%e3%83%bc%e3%82%bf%e3%82%b5%e3%82%a4%e3%82%a8%e3%83%b3%e3%82%b9/execute-and-run-applications-1058462/

メモ帳を実行する

ShellApiを使用します。
...
ShellExecute(Handle、 'open'、
'c:\ Windows \ notepad.exe'、nil、nil、SW_SHOWNORMAL);

メモ帳でSomeText.txtを開く

ShellExecute(Handle、 'open'、
'c:\ windows \ notepad.exe'、
'c:\ SomeText.txt'、nil、SW_SHOWNORMAL);

「DelphiDownload」フォルダの内容を表示する

ShellExecute(Handle、 'open'、
'c:\ DelphiDownload'、nil、nil、SW_SHOWNORMAL);

拡張子に従ってファイルを実行する

ShellExecute(Handle、 'open'、
'c:\ MyDocuments \ Letter.doc'、nil、nil、SW_SHOWNORMAL);

拡張機能に関連付けられているアプリケーションを見つける方法は次のとおりです。

デフォルトのWebエクスプローラーでWebサイトまたは* .htmファイルを開く

ShellExecute(Handle、 'open'、
'http://delphi.about.com'、nil、nil、SW_SHOWNORMAL);

件名とメッセージ本文を記載したメールを送信する

var em_subject、em_body、em_mail:文字列; 
begin
em_subject:= 'これは件名です';
em_body:= 'メッセージ本文テキストはここにあります';

em_mail:= 'mailto:delphi@aboutguide.com?subject =' +
em_subject + '&body =' + em_body;

ShellExecute(Handle、 'open'、
PChar(em_mail)、nil、nil、SW_SHOWNORMAL);
終わり;

添付ファイル付きのメールを送信する方法は次のとおりです。

プログラムを実行し、終了するまで待ちます

次の例では、ShellExecuteExAPI関数を使用しています。

// Windows Calculatorを実行し
、計算が終了すると//メッセージをポップアップします。
ShellApiを使用します。
...
var
SEInfo:TShellExecuteInfo;
ExitCode:DWORD;
ExecuteFile、ParamString、StartInString:文字列;
開始
EXECUTEFILEを:= 'C:\ WINDOWS \ CALC.EXE';

FillChar(SEInfo、SizeOf(SEInfo)、0);
SEInfo.cbSize:= SizeOf(TShellExecuteInfo);
SEInfoを使用してfMaskを開始し
ます:= SEE_MASK_NOCLOSEPROCESS;
Wnd:= Application.Handle;
lpFile:= PChar(ExecuteFile);
{
ParamStringには、
アプリケーションパラメータを含めることができます。
}
// lpParameters:= PChar(ParamString);
{
StartInStringは、
作業ディレクトリの名前。
省略した場合は、現在のディレクトリが使用されます。
}
// lpDirectory:= PChar(StartInString);
nShow:= SW_SHOWNORMAL;
終わり;
ShellExecuteEx(@SEInfo)の場合、Application.ProcessMessagesの
繰り返しを開始し
ます。
GetExitCodeProcess(SEInfo.hProcess、ExitCode);
(ExitCode <> STILL_ACTIVE)または
Application.Terminatedまで;
ShowMessage( '電卓が終了しました');
end
else ShowMessage( 'Calcの開始中にエラーが発生しました!');
終わり;

ShellExecute in Delphi – Launch external applications.

ShellExecute is Delphi Windows API function that is mostly used for launch external applications from our Delphi application. This function is linked to the ShellExecute Windows API function. The function returns an integer that corresponds to an error code which is very useful when we need to show some status if the function worked or not.

By using ShellExecute we can also do following operations....

  • Can print documents from within my program, without explicitly starting the application that created the document, such as: print a Word-document without starting Word.
  • Can open browser with a local HTML page
  • Can surf to a site i.e. open an external URL link from a Delphi application
  • Can send mails thorugh outlook
Syntax of Windows API function

HINSTANCE ShellExecute(
  _In_opt_        HWND hwnd,
  _In_opt_        LPCTSTR lpOperation,
  _In_              LPCTSTR lpFile,
  _In_opt_        LPCTSTR lpParameters,
  _In_opt_        LPCTSTR lpDirectory,
  _In_INT         nShowCmd
);

Parameters Details

_In_opt_  HWND hwnd,
A handle to the parent window used for displaying a UI or error messages. Ex - handle

_In_opt_  LPCTSTR lpOperation,
Operations to perform.
edit      = Launches an editor and opens the document for editing
explore = Explores a folder 
find      = Initiates a search beginning in the directory 
open     = Opens an item, file, folder, link
print     = Prints the file

_In_      LPCTSTR lpFile,
FileName, link URL to open and modify. EX - PChar(filename)

_In_opt_  LPCTSTR lpParameters
the parameters to be passed to the application delimited by space. Ex - '-c -i -v'

_In_opt_  LPCTSTR lpDirectory,
the default (working) directory for the action. 

_In_      INT nShowCmd
how an application is to be displayed when it is opened. 
SW_HIDE = Hides the window and activates another window
SW_MAXIMIZE  = Maximizes the specified window
SW_MINIMIZE = Minimizes the specified window and activates the next top-level window in the z-order
SW_RESTORE  = Activates and displays the window.
SW_SHOW  = Activates the window and displays it in its current size and position.
SW_SHOWDEFAULT  = Sets the show state based on the SW_ flag specified in the STARTUPINFO
SW_SHOWMAXIMIZED  = Activates the window and displays it as a maximized window.
SW_SHOWMINIMIZED  = Activates the window and displays it as a minimized window.
SW_SHOWMINNOACTIVE  = Displays the window as a minimized window. The active window remains active
SW_SHOWNA  = Displays the window in its current state. The active window remains active.
SW_SHOWNOACTIVATE  = Displays a window in its most recent size and position. The active window remains active.
SW_SHOWNORMAL  = Activates and displays a window. If the window is minimized or maximized, Windows restores it to its original size and position. 

Return Values from ShellExecute function

If the return value of ShellExecute is greater than 32, the application was executed successfully.
If its less than 33 then the function failed.
Here is a complete list of the possible return values of ShellExecute:
0 = The operating system is out of memory or resources.
2 = The specified file was not found
3 = The specified path was not found.
5 = Windows 95 only: The operating system denied access to the specified file
8 = Windows 95 only: There was not enough memory to complete the operation.
10 = Wrong Windows version
11 = The .EXE file is invalid (non-Win32 .EXE or error in .EXE image)
12 = Application was designed for a different operating system
13 = Application was designed for MS-DOS 4.0
15 = Attempt to load a real-mode program
16 = Attempt to load a second instance of an application with non-readonly data segments.
19 = Attempt to load a compressed application file.
20 = Dynamic-link library (DLL) file failure.
26 = A sharing violation occurred.
27 = The filename association is incomplete or invalid.
28 = The DDE transaction could not be completed because the request timed out.
29 = The DDE transaction failed.
30 = The DDE transaction could not be completed because other DDE transactions were being processed.
31 = There is no application associated with the given filename extension.
32 = Windows 95 only: The specified dynamic-link library was not found.

Example...

Procedure OpenMyURL(sUrl: string)
var
  iRes: Integer;
  sMsg: String;
begin
  // If the return value of ShellExecute is greater than 32, the application was executed successfully.
  // If its less than 33 then the function failed.
  try
    iRes := -1;
    sMsg := '';
    iRes := ShellExecute(Handle, 'open', Pchar(sUrl), '', '', SW_SHOWNORMAL);
    case iRes of
      0:
        sMsg := 'The operating system is out of memory or resources.';
      2:
        sMsg := 'The specified file was not found';
      3:
        sMsg := 'The specified path was not found.';
      5:
        sMsg := 'Windows 95 only: The operating system denied access to the specified file';
      8:
        sMsg := 'Windows 95 only: There was not enough memory to complete the operation.';
      10:
        sMsg := 'Wrong Windows version';
      11:
        sMsg := 'The .EXE file is invalid (non-Win32 .EXE or error in .EXE image)';
      12:
        sMsg := 'Application was designed for a different operating system';
      13:
        sMsg := 'Application was designed for MS-DOS 4.0';
      15:
        sMsg := 'Attempt to load a real-mode program';
      16:
        sMsg := 'Attempt to load a second instance of an application with non-readonly data segments.';
      19:
        sMsg := 'Attempt to load a compressed application file.'
      20
        sMsg := 'Dynamic-link library (DLL) file failure.';
      26:
        sMsg := 'A sharing violation occurred.';
      27:
        sMsg := 'The filename association is incomplete or invalid.';
      28:
        sMsg := 'The DDE transaction could not be completed because the request timed out.';
      29:
        sMsg := 'The DDE transaction failed.';
      30:
        sMsg := 'The DDE transaction could not be completed because other DDE transactions were being processed.';
      31:
        sMsg := 'There is no application associated with the given extension.';
      32:
        sMsg := 'Windows 95 only: The specified dynamic-link library was not found.';
    end;
    if sMsg <> EmptyStr then
      MessageDlg(sMsg, mtError, [mbOK], 0);
  except
    on E: Exception do
      MessageDlg(E.Message, mtError, [mbOK], 0);
  end;
end;

Note*
In order to use the function, you first need to add the ShellApi to your uses clause, like : 

uses 
   ShellApi;

Use of ShellExecute with Example

Start an application:
ShellExecute(Handle, 'open', PChar('c:\test\app.exe'), nil, nil, SW_SHOW); 

Start NotePad and load a file (the system "knows" the location of NotePad.exe, therefore we don't have to specify the full path):
ShellExecute(Handle, 'open', PChar('notepad'), PChar('c:\test\readme.txt'), nil, SW_SHOW);

Print a document:
ShellExecute(Handle, 'print', PChar('c:\test\test.doc'), nil, nil, SW_SHOW);  

Note: probably you will see the window of Word open very briefly, but it is closed automatically.

Open an HTML page, local or remote:
ShellExecute(Handle, 'open', PChar('http://www.google.com/'), nil, nil, SW_SHOW);

You can do the previuos trick with any type of registered data-file, e.g. open a Text file:
ShellExecute(Handle, 'open', PChar('c:\test\readme.txt'), nil, nil, SW_SHOW);

HTML Help File:
ShellExecute(Handle, 'open', PChar('c:\windows\help\calc.chm'), nil, nil, SW_SHOW);

Explore a folder with Windows Explorer:
ShellExecute(Handle, 'explore', PChar('c:\windows)', nil, nil, SW_SHOW);

Run a DOS command and return immediately:
ShellExecute(Handle, 'open', PChar('command.com'), PChar('/c copy file1.txt file2.txt'), nil, SW_SHOW);

Run a DOS command and keep the DOS-window open ("stay in DOS"):
ShellExecute(Handle, 'open', PChar('command.com'), PChar('/k dir'), nil, SW_SHOW);

Run an executable and show it:
filename := 'c:\program.exe';
ShellExecute(handle,'open',PChar(filename), '','',SW_SHOWNORMAL);

Run an executable and minimize it:
filename := 'c:\program.exe';
ShellExecute(handle,'open',PChar(filename), '','',SW_MINIMIZE);

Run an executable and maximize it:
filename := 'c:\program.exe';
ShellExecute(handle,'open',PChar(filename), '','',SW_MAXIMIZE);

Run an executable and hide it:
filename := 'c:\program.exe';
ShellExecute(handle,'open',PChar(filename), '','',SW_HIDE);

Run an executable with parameters:
filename := 'c:\program.exe';
parameters := '-c -i -v';
ShellExecute(handle,'open',PChar(filename), PChar(parameters), '', SW_SHOWNORMAL);

Send a mail with attachment
ShellExecute(Self.Handle,
             nil,
             'mailto:' +
             'jiten.g.s001@gmail.com' +
             '?Subject=Test Message Subject' +
             '&Body=Test Message Body' +
             '&Attach="c:\Mail\attachment.txt"',
             nil,
             nil,
             SW_NORMAL);