Pages

Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Windows services - Converting between key and display names

We've demonstrated how to check the status of Windows services and how to control them. One element missing from those functions was a way to convert between key and display names of Windows services.

That's right, a Windows service has two names. The long name you see in the Control Panel is the display name of the service. The internal shorter name of the serivce is called the key name. Most functions require that you use the key name of a service, so here's a function to convert a display name to a key name.

uses WinSvc;

//-------------------------------------
// Get the service key name that is
// associated with a specified
// service's display name
// ie: 'Browser' is the key name for
// 'Computer Browser'
//
// sMachine:
// machine name, ie: \SERVER
// empty = local machine
//


// sService
// service display name,
// ie: 'Computer Browser'
//
function ServiceGetKeyName(
sMachine,
sServiceDispName : string ) : string;
var
//
// service control
// manager handle
schm : SC_Handle;

//
// max key name len
nMaxNameLen : integer;

//
// temp. string
psServiceName : PChar;
begin
Result := '';

// expect a service key
// name shorter than 255
// characters
nMaxNameLen := 255;

// connect to the service
// control manager
schm := OpenSCManager(
PChar(sMachine),
Nil,
SC_MANAGER_CONNECT);

// if successful...
if(schm > 0)then
begin
psServiceName :=
StrAlloc(nMaxNameLen+1);

if(nil <> psServiceName)then
begin
if( GetServiceKeyName(
schm,
PChar(sServiceDispName),
psServiceName,
nMaxNameLen ) )then
begin
psServiceName
[nMaxNameLen] := #0;

Result :=
StrPas( psServiceName );
end;

StrDispose(psServiceName);
end;

// close service control
// manager handle
CloseServiceHandle(schm);
end;
end;
Delphi code. Download disp2key

For example, "ServiceGetKeyName( '', 'Computer Browser' )" will return "Browser", "browser" being the key name that you can pass to Windows services related functions. Of course, you may also have a need to convert a key name to a display name:

uses WinSvc;

//-------------------------------------
// Get the service display name that is
// associated with a specified
// service's display name
// ie: 'Computer Browser' is the
// display name for 'Browser'
//
// sMachine:
// machine name, ie: \SERVER
// empty = local machine
//
// sService
// service key name,
// ie: 'Browser'
//
function ServiceGetDisplayName(
sMachine,
sServiceKeyName : string ) : string;
var
//
// service control
// manager handle
schm : SC_Handle;

//
// max display name len
nMaxNameLen : integer;

//
// temp. string
psServiceName : PChar;
begin
Result := '';

// expect a service display
// name shorter than 255
// characters
nMaxNameLen := 255;

// connect to the service
// control manager
schm := OpenSCManager(
PChar(sMachine),
Nil,
SC_MANAGER_CONNECT);

// if successful...
if(schm > 0)then
begin
psServiceName :=
StrAlloc(nMaxNameLen+1);

if(nil <> psServiceName)then
begin
if( GetServiceDisplayName(
schm,
PChar(sServiceKeyName),
psServiceName,
nMaxNameLen ) )then
begin
psServiceName
[nMaxNameLen] := #0;

Result :=
StrPas( psServiceName );
end;

StrDispose(psServiceName);
end;

// close service control
// manager handle
CloseServiceHandle(schm);
end;
end;
Delphi code. Download key2disp

Windows services - Getting a list of installed services

Want to get a list of active, inactive or all Windows services? Following function can help you to do this, but be sure to read other Windows services related tips for details.

const
//
// Service Types
//
SERVICE_KERNEL_DRIVER = $00000001;
SERVICE_FILE_SYSTEM_DRIVER = $00000002;
SERVICE_ADAPTER = $00000004;
SERVICE_RECOGNIZER_DRIVER = $00000008;

SERVICE_DRIVER =
(SERVICE_KERNEL_DRIVER or
SERVICE_FILE_SYSTEM_DRIVER or
SERVICE_RECOGNIZER_DRIVER);

SERVICE_WIN32_OWN_PROCESS = $00000010;
SERVICE_WIN32_SHARE_PROCESS = $00000020;
SERVICE_WIN32 =
(SERVICE_WIN32_OWN_PROCESS or
SERVICE_WIN32_SHARE_PROCESS);

SERVICE_INTERACTIVE_PROCESS = $00000100;

SERVICE_TYPE_ALL =
(SERVICE_WIN32 or
SERVICE_ADAPTER or
SERVICE_DRIVER or
SERVICE_INTERACTIVE_PROCESS);

uses WinSvc;

//-------------------------------------
// Get a list of services
//
// return TRUE if successful
//
// sMachine:
// machine name, ie: \SERVER
// empty = local machine
//
// dwServiceType
// SERVICE_WIN32,
// SERVICE_DRIVER or
// SERVICE_TYPE_ALL
//
// dwServiceState
// SERVICE_ACTIVE,
// SERVICE_INACTIVE or
// SERVICE_STATE_ALL
//
// slServicesList
// TStrings variable to storage
//
function ServiceGetList(
sMachine : string;
dwServiceType,
dwServiceState : DWord;
slServicesList : TStrings )
: boolean;
const
//
// assume that the total number of
// services is less than 4096.
// increase if necessary
cnMaxServices = 4096;

type
TSvcA = array[0..cnMaxServices]
of TEnumServiceStatus;
PSvcA = ^TSvcA;

var
//
// temp. use
j : integer;

//
// service control
// manager handle
schm : SC_Handle;

//
// bytes needed for the
// next buffer, if any
nBytesNeeded,

//
// number of services
nServices,

//
// pointer to the
// next unread service entry
nResumeHandle : DWord;

//
// service status array
ssa : PSvcA;
begin
Result := false;

// connect to the service
// control manager
schm := OpenSCManager(
PChar(sMachine),
Nil,
SC_MANAGER_ALL_ACCESS);

// if successful...
if(schm > 0)then
begin
nResumeHandle := 0;

New(ssa);

EnumServicesStatus(
schm,
dwServiceType,
dwServiceState,
ssa^[0],
SizeOf(ssa^),
nBytesNeeded,
nServices,
nResumeHandle );

//
// assume that our initial array
// was large enough to hold all
// entries. add code to enumerate
// if necessary.
//

for j := 0 to nServices-1 do
begin
slServicesList.
Add( StrPas(
ssa^[j].lpDisplayName ) );
end;

Result := true;

Dispose(ssa);

// close service control
// manager handle
CloseServiceHandle(schm);
end;
end;
Delphi code. Download getlist

To get a list of all Windows services into a listbox named ListBox1:

ServiceGetList( '',
SERVICE_WIN32,
SERVICE_STATE_ALL,
ListBox1.Items );
Delphi code. Download demo

Displaying local HTML files using the THTML component or other browser

Looking for a way to display local HTML files using the THTML component or other browser? This is possible, but be sure to format the URL to your local files correctly. You may want to display local HTML files if you're using HTML files to provide help for your program or if you wish to ship a snap-shot of your web site with your programs.

URLs to local files should be formatted as:

file://<host>/<path>

For example:

c:\my_pages\home.htm should be specified as:

file:///c|/my_pages/home.htm

To display a file on a network such as \\server_name\c_drive\my_pages\home.htm

file://server_name/c_drive/my_pages/home.htm

If you're using a browser or some other program that can accept standard URLs, simply pass the correctly formatted local file path as demonstrated above.

To display a local file using a THTML component named HTML1:

HTML1.RequestDoc( 'file:///c|/my_pages/home.htm' ); < Delphi code. Download url_demo>

If you're using C++Builder's THTML component:

HTML1->RequestDoc( "file:///c|/my_pages/home.htm" ); <C/C++ code. Download url_demo >

bin2hex - script to convert data files into source code arrays

Looking for a way to convert a binary (or even a text) file into a Perl, Pascal/Delphi, C/C++, or Java source code array? For example, you may want to do this to include a GIF or other binary file directly inside your Perl CGI script, rather than reading the data from a file to reduce file access. If you're writing Windows programs, you could use the same method to store resource files in your executable files.

The bin2hex.pl script will take a binary file name and output a source code array, in the specified language, necessary to recreate the input data inside a program.

To run the script, first make sure that you have a Perl interpreter installed on your system and download the bin2hex.pl script. Then execute the following command from your command prompt (assuming you want to convert a file named banner.gif to a Perl string):


perl bin2hex.pl banner.gif 0 >source.txt
-Download demo1.bat-

You will end-up with a source.txt file with content similar to the following:

# begin binary data:
$bin_data = # 42
"x47x49x46x38x39x61x01".
"x00x01x00x80x00x00x00x00".
"x00xFFxFFxFFx21xF9x04".
"x01x00x00x00x00x2Cx00x00".
"x00x00x01x00x01x00x40".
"x02x01x44x00x3B";
# end binary data. size = 42 bytes

-Download result1.txt-

bin2hex.pl script

Usage:
perl bin2hex.pl <binary_file_name> <language_id>

binary_file_name
The input file name

language_id
The language identifier
(source code array will be generated in this language):
0 - Perl or similar language(default)
1 - C / C++ / Java or similar language
2 - Pascal / Delphi or similar language

#
# bin2hex.pl by tips-notebook
# http://tips-notebook.blogspot.com/tips/
#

# number of characters per line
$chars_per_line = 15;

# -------------------------------------

# language id
#
# 0 = Perl (default)
# 1 = C / C++
# 2 = Pascal / Delphi
#
$lang = $ARGV[1];

$rem_begin = "begin binary data:";
$rem_end = "end binary data.";

# initialize for Perl strings
# by default
$_var = "# $rem_beginn".
"$bin_data = # %dn";
$_begin = """;
$_end = "";n";
$_break = "".n"";
$_format = "\x%02X";
$_separator = "";
$_comment = "# $rem_end ".
"size = %d bytes";


# C / C++
if(1 == $lang)
{
$_var = "/* $rem_begin */n".
"char bin_data[] = ".
"/* %d */n";
$_begin = "{";
$_end = "};n";
$_break = "n";
$_format = "0x%02X";
$_separator = ",";
$_comment = "/* $rem_end ".
"size = %d bytes */";
}
elsif(2 == $lang)
{
$_var = "{ $rem_begin }n".
"const bin_data : ".
"array [1..%d] of ".
"byte = n";
$_begin = "(";
$_end = ");n";
$_break = "n";
$_format = "$%02X";
$_separator = ",";
$_comment = "{ $rem_end ".
"size = %d bytes }";
}

if(open(F, "<".$ARGV[0])) { binmode(F); $s = ''; $i = 0; $count = 0; $first = 1; $s .= $_begin; while(!eof(F)) { if($i >= $chars_per_line)
{
$s .= $_break;
$i = 0;
}
if(!$first)
{
$s .= $_separator;
}
$s .= sprintf(
$_format, ord(getc(F)));
++$i;
++$count;
$first = 0;
}
$s .= $_end;
$s .= sprintf $_comment, $count;
$s .= "nn";

$s = "n".sprintf($_var, $count).$s;

print $s;

close( F );
}
else
{
print
"bin2hex.pl by Chami.comn".
"n".
"usage:n".
" perl bin2hex.pl ".
" n".
"n".
" : path to the ".
"binary filen".
" : 0 = Perl, ".
"1 = C/C++/Java, ".
"2 = Pascal/Delphin".
"n";
}
-Download bin2hex.pl-

Calling Control Panel applets from your programs and scripts

Looking for a way to open Control Panel applets from your programs without opening the Control Panel?

Whether you want your users to change the system date/time properties, add a new modem or change joystick settings, there's an easy way to call all such Control Panel applets (icons) without opening the Control Panel folder. The good news is that you can use this method in any Windows programming environment or even in a simple BATch file.

Running the following command from your program will do the trick (CPL being the file name of the Control Panel applet to open. a list of such applets can be found at the bottom of this document):

rundll32.exe shell32.dll,Control_RunDLL CPL


For example, to bring up the "Date/Time Properties" dialog box, run:


rundll32.exe shell32.dll,Control_RunDLL timedate.cpl


To open a Control Panel applet from a Windows BATch file, simply include the above command in a line by itself. Since we're using a regular executable file, rundll32.exe, you can include the above command in any location you can execute a program, such as a shortcut icon, Intranet web page anchor, script, etc.

Although the concept is simple enough, let's look at some code samples on how to ease calling the above command from a C/C++ or Delphi program. Note that you can use any "WinExec()" equivalent function to achieve the same effect.

C Language / C++ / C++Builder code sample

Include the following code in your program and call "RunControlPanelApplet()". Example call: RunControlPanelApplet("timedate.cpl");

#include
#include

int RunControlPanelApplet(
char*sAppletFileName)
{
char s[1024];

sprintf(s,
"rundll32.exe shell32.dll,"
"Control_RunDLL %s",
sAppletFileName);

return
WinExec(s, SW_SHOWNORMAL);
}

Download opencpl2.c

Delphi / C++Builder code sample

Include the following unit into your project and call "RunControlPanelApplet()" with the name of the applet to open. Example: RunControlPanelApplet( 'timedate.cpl' );

unit open_cpl;

interface

function RunControlPanelApplet(
sAppletFileName : string) : integer;

implementation

uses Windows;

function RunControlPanelApplet(
sAppletFileName : string) : integer;
begin
Result :=
WinExec(
PChar('rundll32.exe shell32.dll,'+
'Control_RunDLL '+sAppletFileName),
SW_SHOWNORMAL);
end;

end.

Download opencpl1.pas

How to find the names of the applet files

Control Panel applet files have the extension CPL. To get a list of applets installed on your system, go to your Windows SYSTEM (Windows 95) or SYSTEM32 (Windows NT) directory and look for files with the CPL extension. Example: DIR C:\WINDOWS\SYSTEM\*.CPL

Following is a list of applets common to Windows 95 and Windows NT:

access.cpl: Accessibility Properties
appwiz.cpl: Add/Remove Programs Properties
desk.cpl: Display Properties
intl.cpl: Regional Settings Properties
joy.cpl: Joystick Properties
main.cpl: Mouse Properties
mmsys.cpl: Multimedia Properties
modem.cpl: Modems Properties
sysdm.cpl: System Properties
timedate.cpl: Time/Date Properties