I need a working function for Delphi 2010 to check if there is Internet connection available.
I say working because so far I tried 4 different methods e.g. http://delphi.about.com/b/2005/04/22/how-to-check-for-internet-connection-using-delphi-code.htm but neither worked.
For example one method alway gave back that there was internet connection even when the cable was not in the pc, the other the opposite (it always said there was no connection).
procedure TForm1.Button1Click(Sender: TObject) ;
function FuncAvail(_dllname, _funcname: string;
var _p: pointer): boolean;
{return True if _funcname exists in _dllname}
var _lib: tHandle;
begin
Result := false;
if LoadLibrary(PChar(_dllname)) = 0 then exit;
_lib := GetModuleHandle(PChar(_dllname)) ;
if _lib <> 0 then begin
_p := GetProcAddress(_lib, PChar(_funcname)) ;
if _p <> NIL then Result := true;
end;
end;
{
Call SHELL32.DLL for Win < Win98
otherwise call URL.dll
}
{button code:}
var
InetIsOffline : function(dwFlags: DWORD):
BOOL; stdcall;
begin
if FuncAvail('URL.DLL', 'InetIsOffline',
#InetIsOffline) then
if InetIsOffLine(0) = true
then ShowMessage('Not connected')
else ShowMessage('Connected!') ;
end;
The only reliable method is to attempt to connect to a real server on the Internet somewhere and see if it succeeds or fails. Don't use OS functions that rely on OS state information, because that data can easily get out of sync.
Add in your uses the unit "WinNet". With the function "InternetGetConnectedState" return a value for internet state and type. See below:
function YourFunctionName : boolean;
var
origin : cardinal;
begin
result := InternetGetConnectedState(#origin,0);
//connections origins by origin value
//NO INTERNET CONNECTION = 0;
//INTERNET_CONNECTION_MODEM = 1;
//INTERNET_CONNECTION_LAN = 2;
//INTERNET_CONNECTION_PROXY = 4;
//INTERNET_CONNECTION_MODEM_BUSY = 8;
end;
update i newer Delphi versions add "wininet" as uses class.
You can use the TIdHTTP component:
function TMainF.isInternetConnection: Boolean;
begin
try
IdHTTP.Get('http://www.svtech.cz');
except
on E: Exception do begin
if not (E is EIdHTTPProtocolException) then begin
Result := False;
Exit;
end;
end;
end;
Result := True;
end;
Related
I'm using Windows 10 and I am logged in as Administrator.
When I try to reboot the system, all it does is it logs me off.
ExitWindowsEx(EWX_REBOOT and EWX_FORCE, 0);
Can someone please tell me why is this not rebooting?
So it seems that even though I am a administrator I need to set the rights with the following function
function NTSetPrivilege(sPrivilege: string; bEnabled: Boolean): Boolean;
var
hToken: THandle;
TokenPriv: TOKEN_PRIVILEGES;
PrevTokenPriv: TOKEN_PRIVILEGES;
ReturnLength: Cardinal;
begin
Result := True;
// Only for Windows NT/2000/XP and later.
if not (Win32Platform = VER_PLATFORM_WIN32_NT) then Exit;
Result := False;
// obtain the processes token
if OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then
begin
try
// Get the locally unique identifier (LUID) .
if LookupPrivilegeValue(nil, PChar(sPrivilege),
TokenPriv.Privileges[0].Luid) then
begin
TokenPriv.PrivilegeCount := 1; // one privilege to set
case bEnabled of
True: TokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
False: TokenPriv.Privileges[0].Attributes := 0;
end;
ReturnLength := 0; // replaces a var parameter
PrevTokenPriv := TokenPriv;
// enable or disable the privilege
AdjustTokenPrivileges(hToken, False, TokenPriv, SizeOf(PrevTokenPriv),
PrevTokenPriv, ReturnLength);
end;
finally
CloseHandle(hToken);
end;
end;
// test the return value of AdjustTokenPrivileges.
Result := GetLastError = ERROR_SUCCESS;
if not Result then
raise Exception.Create(SysErrorMessage(GetLastError));
end;
like this :
procedure TMain.Neustart1Click(Sender: TObject);
const
SE_SHUTDOWN_NAME = 'SeShutdownPrivilege';
begin
NTSetPrivilege(SE_SHUTDOWN_NAME, True);
ExitWindowsEx(EWX_REBOOT or EWX_FORCE, 0);
end;
Now it works.
I was looking for a better solution to the one I had done about 5 years ago (posted below), I needed to do some tweaking for it to run on latest Delphi, older Delphi versions simply use Windows.AdjustTokenPrivileges. Code below is tried and tested since windows XP. Be careful - it works, make sure you save your work before running!
//Uses WinApi.Windows on Latest Delphi 10.3.2
function MyExitWindows(RebootParam: Longword): Boolean;
var
TTokenHd: THandle;
TTokenPvg: TTokenPrivileges;
cbtpPrevious: DWORD;
rTTokenPvg: TTokenPrivileges;
pcbtpPreviousRequired: DWORD;
tpResult: Boolean;
const
SE_SHUTDOWN_NAME = 'SeShutdownPrivilege';
begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
tpResult := OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,
TTokenHd);
if tpResult then
begin
tpResult := LookupPrivilegeValue(nil,
SE_SHUTDOWN_NAME,
TTokenPvg.Privileges[0].Luid);
TTokenPvg.PrivilegeCount := 1;
TTokenPvg.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
cbtpPrevious := SizeOf(rTTokenPvg);
pcbtpPreviousRequired := 0;
if tpResult then
//Older Delphi - replace the WinApi. to read WinApi.AdjustTokenPrivileges
WinApi.Windows.AdjustTokenPrivileges(TTokenHd,
False,
TTokenPvg,
cbtpPrevious,
rTTokenPvg,
pcbtpPreviousRequired);
end;
end;
Result := ExitWindowsEx(RebootParam, 0);
end;
//Examples
//Shutdown the computer
MyExitWindows(EWX_POWEROFF or EWX_FORCE);
//Reboot the computer
MyExitWindows(EWX_REBOOT or EWX_FORCE);
We have a legacy Delphi application which uses IcmpSendEcho (from iphlpapi.dll) to perform echo requests. As I understand it, this performs the same function as "ping" from the command prompt.
On Windows XP, the code below works fine. When the IPv4 address is correct the response is quick and if not error code 11010 (IP_REQ_TIMED_OUT) is returned as expected.
However, on my 32-bit Windows 10 machine, the error code is 87 (ERROR_INVALID_PARAMETER). I've carefully reviewed the Microsoft documentation for IcmpSendEcho and cannot see anything obvious that is wrong.
"ping 200.1.2.121" (the example IPv4 address I use in the code sample) works as expected from the command prompt in both XP and 10.
type
PIpAddress = ^TIpAddress;
TIpAddress = record
case Integer of
0: (S_un_b: TSunB);
1: (S_un_w: TSunW);
2: (S_addr: LongWord);
end;
IpAddress = TIpAddress;
// Functions imported from external DLLs
function IcmpCreateFile() : THandle; stdcall; external 'iphlpapi.dll';
function IcmpCloseHandle(icmpHandle: THandle) : Boolean; stdcall; external 'iphlpapi.dll';
function IcmpSendEcho(IcmpHandle: THandle; ipDest: IpAddress;
pRequestData: Pointer; nRequestSize: SmallInt; RequestOptions: Pointer;
pReplyBuffer: Pointer; dwReplySize: DWORD; dwTimeout: DWORD) : DWORD; stdcall; external 'iphlpapi.dll';
procedure TranslateStringToIpAddress(strIP: String; var ipAddress);
var
phe: PHostEnt;
pac: PChar;
begin
try
phe := GetHostByName(PChar(strIP));
if (Assigned(phe)) then
begin
pac := phe^.h_addr_list^;
if (Assigned(pac)) then
begin
with TIpAddress(ipAddress).S_un_b do
begin
by1 := Byte(pac[0]);
by2 := Byte(pac[1]);
by3 := Byte(pac[2]);
by4 := Byte(pac[3]);
end;
end
else
begin
raise Exception.Create('Error getting IP from HostName');
end;
end
else
begin
raise Exception.Create('Error getting HostName');
end;
except
FillChar(ipAddress, SizeOf(ipAddress), #0);
end;
end;
function Ping(strIpAddress : String) : Boolean;
const
ICMP_ECHO_BUFFER = 128; // Works as low as 28 on Windows XP (nothing works on Windows 10)
var
address: IpAddress;
dwReplies: DWORD;
{$IFDEF DBG} dwErrorCode: DWORD; {$ENDIF}
abyReplyBuffer: array[1..ICMP_ECHO_BUFFER] of BYTE;
begin
// Use this function to determine if an IPv4 address can be reached
Result := False;
// "m_cache.hPingHandle" is generated earlier with a call to "IcmpCreateFile"
if (m_cache.hPingHandle = INVALID_HANDLE_VALUE) then
Exit;
TranslateStringToIpAddress(strIpAddress, address);
dwReplies := IcmpSendEcho(
m_cache.hPingHandle, address, nil, 0, nil, #abyReplyBuffer, ICMP_ECHO_BUFFER, 0);
{$IFDEF DBG}
if (dwReplies = 0) then
begin
dwErrorCode := GetLastError();
// dwErrorCode = 87 (ERROR_INVALID_PARAMETER, "The parameter is incorrect")
Application.MessageBox(
PAnsiChar(Format('WinError = %d', [dwErrorCode])), 'Ping failed', MB_ICONEXCLAMATION);
end;
{$ENDIF}
// Success?
Result := (dwReplies <> 0);
end;
// Usage elsewhere in the application...
Ping('200.1.2.121'); // Works on Windows XP, but fails on Windows 10
Based on the comment from #FredS (thanks!), the answer is simply to make the last parameter for the IcmpSendEcho non-zero (eg. "200").
The MSDN documentation for IcmpSendEcho does not make this clear, so Microsoft have probably changed the internal implementation of this method from the version in Windows XP so that a non-zero Timeout is now required.
I'm stuck in my debugging efforts with a call to WlanGetNetworkBssList and would appreciate some pointers. My end objective is to construct a Wifi scanner/profiler tool to help me troubleshoot networking issues on remote sites.
I am using the Windows Native Wifi API (link) and Delphi/Pascal interface found here using Delphi Berlin 10.1 Update 2 under Windows 10 (VCL).
I started with a simple and crude test app (VCL) to get a feel for the API and ran into a problem calling WlanGetNetworkBssList so I created a small console app focused on that problem. The issue is that it works in a console app running in a command prompt but not in my VCL test app. The functions are pretty much copy-paste equivalent and stepping through the code side-by-side shows that the data is identical except for the return data from WlanGetNetworkBssList call (pWlanBssList)
Question: Since the call is to an external DLL what steps can I do to further debug this and understand the difference between the VCL and the console app.
Note: The WlanGetNetworkBssList has two modes of operation where an SSID can be supplied to get the BSSID (MAC of the access point) for that specific SSID. By passing NULL instead of an SSID the API will return the BSSIDs of all APs. Passing NULL works on both the VLC and console app. What breaks is when a specific SSID is requested. After verification, the SSID data structure is identical in both apps but the data buffer returned is invalid with the VCL app. How can this be?
Console app:
program CWifiScan;
{$APPTYPE CONSOLE}
uses
Windows,
System.SysUtils,
nduWlanAPI,
nduWlanTypes;
const
WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES = $00000001;
var
hWlan: THandle;
guid : TGUID;
dwSupportedVersion: DWORD = 0;
dwClientVersion: DWORD = 1;
i,j : integer;
pInterfaceInfo : Pndu_WLAN_INTERFACE_INFO;
pInterfaceList : Pndu_WLAN_INTERFACE_INFO_LIST;
pAvailableNetworkList : Pndu_WLAN_AVAILABLE_NETWORK_LIST;
procedure GetBSSIDList(clientHandle : THandle;
interfaceGUID : TGUID;
pSSID : Pndu_DOT11_SSID = nil;
SSID_Type : Tndu_DOT11_BSS_Type = dot11_BSS_type_any;
SecurityEnabled : BOOL = True);
var
//to check if interface is connected
pData : Pndu_WLAN_INTERFACE_STATE;
pdwDataSize : DWORD;
isConnected : Boolean;
//to get list of BSSids from available APs
pWlanBssList : Pndu_WLAN_BSS_LIST;
items : integer;
itemIndex : integer;
SSID : string;
MAC : string;
begin
//check if interface is connected
isConnected := False;
if WlanQueryInterface(clientHandle,
#interfaceGUID,
wlan_intf_opcode_interface_state,
nil,
#pdwDataSize,
#pData,
nil) = ERROR_SUCCESS then
begin
isConnected := (pData^ = Tndu_WLAN_INTERFACE_STATE.wlan_interface_state_connected);
end;
//get the list of BSSids for the provided interface
if isConnected then
begin
if WlanGetNetworkBssList(clientHandle,
#interfaceGUID,
pSSID,
SSID_Type,
SecurityEnabled,
nil,
#pWlanBssList) = ERROR_SUCCESS then
begin
items := pWlanBssList^.dwNumberOfItems;
for itemIndex := 0 to items - 1 do
begin
SSID := String(PAnsiChar(#pWlanBssList^.wlanBssEntries[itemIndex].dot11Ssid.ucSSID));
MAC := Format('%.2x:%.2x:%.2x:%.2x:%.2x:%.2x', [
pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[0],
pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[1],
pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[2],
pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[3],
pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[4],
pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[5]]);
Writeln('');
Writeln('SSID: ................ '+SSID);
Writeln('Physical Address: .... '+MAC);
end; {for itemIndex}
Writeln(#10+#13+'Done.');
end; {WlanGetNetworkBssList succeeds}
end; {isConnected}
end;
begin
hWlan := 0;
if WlanOpenHandle(2, nil,#dwSupportedVersion, #hWlan)= ERROR_SUCCESS then
begin
if WlanEnumInterfaces(hWlan, nil, #pInterfaceList) = ERROR_SUCCESS then
begin
try
for i := 0 to pInterfaceList^.dwNumberOfItems-1 do
begin
Writeln('Wifi Adapter - '+GUIDToString( pInterfaceList^.InterfaceInfo[i].InterfaceGuid ) );
Writeln('Scanning: .... '+pInterfaceList^.InterfaceInfo[i].strInterfaceDescription);
guid := pInterfaceList^.InterfaceInfo[i].InterfaceGuid;
//Get all BSSids for this interface
GetBSSIDList(hWlan, guid);
if WlanGetAvailableNetworkList(hWlan,
#guid,
WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES,
nil,
pAvailableNetworkList) = ERROR_SUCCESS then
begin
try
for j := 0 to pAvailableNetworkList^.dwNumberOfItems - 1 do
begin
//Get BSSid for this specific SSID
GetBSSIDList(hWlan,
guid,
#pAvailableNetworkList^.Network[j].dot11Ssid,
pAvailableNetworkList^.Network[j].dot11BssType,
pAvailableNetworkList^.Network[j].bSecurityEnabled);
end;
finally
if pAvailableNetworkList<>nil then
WlanFreeMemory(pAvailableNetworkList);
end;
end;
end;
finally
if pInterfaceList<>nil then
WlanFreeMemory(pInterfaceList);
end;
end;
WlanCloseHandle(hWlan, nil);
readln;
end;
end.
The relevant parts of the VCL app are:
uses
... nduWlanAPI, nduWlanTypes, nduWinDot11;
function TForm1.GetBSSID(clientHandle: THandle;
interfaceGuid: TGUID;
pSSID: Pndu_DOT11_SSID = nil;
SSID_Type : Tndu_DOT11_BSS_TYPE = dot11_BSS_type_any;
SecurityEnabled: boolean = true): string;
var
//used to determin if the interface is connected
pData : Pndu_WLAN_INTERFACE_STATE;
isConnected : boolean;
//used to extract a list of BSSIDs for a given interface
pWlanBssList : Pndu_WLAN_BSS_LIST;
lastError : DWORD;
pdwDataSize : DWORD;
items,
itemIndex: Integer;
begin
pData := nil;
pdwDataSize := 0;
isConnected := False;
//check if the interface is connected
lastError := WlanQueryInterface(clientHandle,
#interfaceGuid,
wlan_intf_opcode_interface_state,
nil,
#pdwDataSize,
#pData,
nil);
if (lastError = ERROR_SUCCESS) then
begin
//isConnected := (Tndu_WLAN_INTERFACE_STATE(pData^.isState) = Tndu_WLAN_INTERFACE_STATE.wlan_interface_state_connected);
isConnected := (pData^ = Tndu_WLAN_INTERFACE_STATE.wlan_interface_state_connected);
end
else
DisplayError('Error in WlanQueryInterface() function', lastError);
if isConnected then
begin
pWlanBssList := nil;
lastError := WlanGetNetworkBssList(clientHandle,
#interfaceGuid,
pSSID,
SSID_Type,
SecurityEnabled,
nil,
#pWlanBssList);
try
if (lastError = ERROR_SUCCESS) then
begin
items := pWlanBssList^.dwNumberOfItems;
for itemIndex := 0 to items-1 do
begin
Result := (Format('%.2x:%.2x:%.2x:%.2x:%.2x:%.2x', [
pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[0],
pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[1],
pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[2],
pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[3],
pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[4],
pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[5]]));
end;
end
else
DisplayError('Error in the WlanGetNetworkBssList() function call', lastError);
finally
if pData<>nil then
WlanFreeMemory(pData);
if pWlanBssList<>nil then
WlanFreeMemory(pWlanBssList);
end;
end;
end;
Which is called as follows:
function TForm1.ScanWifi(): THandle;
const
WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES = $00000001;
var
hClient : THandle;
dwVersion : DWORD;
lastError : DWORD;
pInterface : Pndu_WLAN_INTERFACE_INFO_LIST;
i : Integer;
j : Integer;
pAvailableNetworkList: Pndu_WLAN_AVAILABLE_NETWORK_LIST;
interfaceGuid : TGUID;
BSSID : string;
begin
lastError:=WlanOpenHandle(NDU_WLAN_API_VERSION, nil, #dwVersion, #hClient);
if lastError<> ERROR_SUCCESS then
begin
//DisplayError('Error in the WlanOpenHandle() function call', lastError);
Result := 0;
Exit;
end;
//L(Format('Requested WLAN interface version [%d], negotiated version [%d]', [NDU_WLAN_API_VERSION, dwVersion]));
Result := hClient;
try
lastError:=WlanEnumInterfaces(hClient, nil, #pInterface);
try
if lastError<> ERROR_SUCCESS then
begin
//DisplayError('Errorin the WlanEnumInterfaces() function call', lastError);
Exit;
end;
for i := 0 to pInterface^.dwNumberOfItems - 1 do
begin
interfaceGuid:= pInterface^.InterfaceInfo[i].InterfaceGuid;
lastError:=WlanGetAvailableNetworkList(hClient,
#interfaceGuid,
WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES,
nil,
pAvailableNetworkList);
try
if lastError<> ERROR_SUCCESS then
begin
//DisplayError('Error WlanGetAvailableNetworkList', lastError);
Exit;
end
else
begin
for j := 0 to pAvailableNetworkList^.dwNumberOfItems - 1 do
Begin
BSSID := GetBssid(hClient,
interfaceGuid,
#pAvailableNetworkList^.Network[j].dot11Ssid,
pAvailableNetworkList^.Network[j].dot11BssType,
pAvailableNetworkList^.Network[j].bSecurityEnabled
);
//FAPList.AddOrSetValue(BSSID,J);
end;
end;
finally
if pAvailableNetworkList <> nil then
WlanFreeMemory(pAvailableNetworkList);
end;
end;
finally
if pInterface <> nil then
WlanFreeMemory(pInterface);
end;
finally
WlanCloseHandle(FhClient, nil);
end;
end;
Comparing the data between the two apps the only difference is the result (pWlanBssList) as seen here (left=console, right=VCL):
Looks like compiler bug in boolean conversion, problem is following line in VCL code
SecurityEnabled: boolean = true
you need to change it to
SecurityEnabled: bool = true
i have Call Center Using Avaya System I need To manage this System
by my application that's developed by my
there are dll Called devlink have 4 Events
DEVLINK_COMMS_OPERATIONAL
DEVLINK_COMMS_NORESPONSE
DEVLINK_COMMS_REJECTED
DEVLINK_COMMS_MISSEDPACKETS
the first Event
DEVLINK_COMMS_OPERATIONAL
meen the connection was establish
when Click The Button Connect
procedure TfrmMain.btnConnectClick(Sender: TObject);
var
hEvent:integer;
vPass,vAddress:PChar;
begin
with frmSetup.tblConnections do
begin
First;
while not Eof do
begin
if FieldByName('IPEnabled').AsInteger=1 then
Begin
vPass:=PChar(FieldByName('IPPassword').AsString);
vAddress:=PChar(FieldByName('IpAddress').AsString);
DLOpen(fNextHandle, vAddress,vPass, nil, nil,HandleCommsEvent);
Edit;
FieldByName('pbxh').AsInteger:=fNextHandle;
Post;
hEvent := CreateEvent(nil, FALSE, FALSE, nil);
try
WaitForSingleObject(hEvent, 10000);
if (Locate('pbxh',fNextHandle,[]))and(FieldByName('connected').AsInteger=1) then
else
LogAddLine(fNextHandle,'No Responce');
finally
CloseHandle(hEvent);
inc(fNextHandle);
end;
End;
next;
end;
end;
end;
we note DlOpen Method Take the IP of system And Password
and Event that will fire to test the Dlopen
Always appear message of the event DEVLINK_COMMS_NORESPONSE
that is no response
i need to know where the error where the IP And Password Was correct. There
are The HandleCommsEvent
procedure HandleCommsEvent(pbxh: LongInt; Comms_status: DWORD; Parm1: DWORD);stdcall;
stdcall;
begin
//4 cases for event of DLOPEN
LogAddLine(pbxh,'HandleCommsEvent happend');
case Comms_status of
DEVLINK_COMMS_OPERATIONAL:
Begin
DLRegisterType2CallDeltas(pbxh, HandleEvent);
LogAddLine(pbxh,'Connected Done');
if frmSetup.tblConnections.Locate('pbxh',pbxh,[]) then
Begin
frmSetup.tblConnections.Edit;
frmSetup.tblConnections.FieldByName('connected').AsInteger:=1;
frmSetup.tblConnections.Post;
End;
end;
DEVLINK_COMMS_NORESPONSE:
begin
LogAddLine(pbxh,'Connected NORESPONSE There Are Problem In network ');
if frmSetup.tblConnections.Locate('pbxh',pbxh,[]) then
Begin
frmSetup.tblConnections.Edit;
frmSetup.tblConnections.FieldByName('pbxh').AsInteger:=pbxh;
frmSetup.tblConnections.FieldByName('connected').AsInteger:=0;
frmSetup.tblConnections.Post;
End;
end ;
DEVLINK_COMMS_REJECTED:
begin
LogAddLine(pbxh,'Connected REJECTED,Password was incorrect');
if frmSetup.tblConnections.Locate('pbxh',pbxh,[]) then
Begin
frmSetup.tblConnections.Edit;
frmSetup.tblConnections.FieldByName('pbxh').AsInteger:=pbxh;
frmSetup.tblConnections.FieldByName('connected').AsInteger:=0;
frmSetup.tblConnections.Post;
End;
end;
// Case of Packets were generated by IP Office System unit ,but Not recieved by Devlink
DEVLINK_COMMS_MISSEDPACKETS:
begin
LogAddLine(pbxh,'Connected MISSEDPACKETS ,Packets were generated by IP Office System unit ,but Not recieved by Devlink ');
end;
//Case of NO Response from From System Unit
end;
end;
if Any one need more info and details i'm ready.
The Message of NO Response Always appear
for more Details
This is Devlink
unit UDevLink;
{**************************************************************************}
{ Delphi unit for DevLink (c) 2001 Avaya Global SME Solutions }
{ Contents:- }
{ IP Office DevLink DLL provides an interface for managing }
{ the IP Office product ranges from a Windows PC }
{**************************************************************************}
interface
uses
Windows, SysUtils , Classes, UfrmMain,strutils,Ustrings;
const
DEVLINK_SUCCESS = 0;
DEVLINK_UNSPECIFIEDFAIL = 1;
DEVLINK_LICENCENOTFOUND = 2;
const
DEVLINK_COMMS_OPERATIONAL = 0;
DEVLINK_COMMS_NORESPONSE = 1;
DEVLINK_COMMS_REJECTED = 2;
DEVLINK_COMMS_MISSEDPACKETS = 3;
type
TCallLogEvent = procedure(pbxh: LongInt; info: PChar); stdcall;
type
TCommsEvent = procedure(pbxh: LongInt;
Comms_status: DWORD;
Parm1: DWORD); stdcall;
function DLOpen(pbxh: LongInt;
pbx_address: PChar;
pbx_password: PChar;
reserved1: PChar;
reserved2: PChar;
cb: TCommsEvent): LongInt; stdcall;
function DLClose(pbxh: THandle): LongInt; stdcall;
function DLRegisterType2CallDeltas(pbxh: LongInt;
cb: TCallLogEvent): LongInt; stdcall;
implementation
function DLOpen; external 'DEVLINK.DLL';
function DLClose; external 'DEVLINK.DLL';
function DLRegisterType2CallDeltas; external 'DEVLINK.DLL';
end.
Your DB management is manipulating the DB cursor while you are iterating with the same cursor. There is no need to Locate() the record that you are actively processing.
Your call to DlOpen() should look more like this, based on the Delphi example provided in the official Avaya DevLink API documentation (which I assume you have read):
var
hEvent: THandle;
Status: DWORD;
Starting: Boolean;
procedure HandleCommsEvent(pbxh: LongInt; Comms_status: DWORD; Parm1: DWORD); stdcall;
begin
//4 cases for event of DLOPEN
LogAddLine(pbxh, 'HandleCommsEvent happend');
case Comms_status of
DEVLINK_COMMS_OPERATIONAL,
DEVLINK_COMMS_NORESPONSE,
DEVLINK_COMMS_REJECTED:
begin
if Starting then begin
Status := Comms_status;
SetEvent(hEvent);
end;
end;
// Case of Packets were generated by IP Office System unit ,but Not recieved by Devlink
DEVLINK_COMMS_MISSEDPACKETS:
begin
LogAddLine(pbxh,'Connected MISSEDPACKETS ,Packets were generated by IP Office System unit ,but Not recieved by Devlink ');
end;
//Case of NO Response from From System Unit
end;
end;
procedure TfrmMain.btnConnectClick(Sender: TObject);
var
vPass, vAddress: String;
begin
hEvent := CreateEvent(nil, TRUE, FALSE, nil);
try
with frmSetup.tblConnections do
begin
First;
while not Eof do
begin
if FieldByName('IPEnabled').AsInteger = 1 then
begin
vPass := FieldByName('IPPassword').AsString;
vAddress := FieldByName('IpAddress').AsString;
Edit;
FieldByName('pbxh').AsInteger := fNextHandle;
FieldByName('connected').AsInteger := 0;
Post;
Status := DEVLINK_COMMS_NORESPONSE;
Starting := True;
ResetEvent(hEvent);
DLOpen(fNextHandle, PChar(vAddress), PChar(vPass), nil, nil, HandleCommsEvent);
WaitForSingleObject(hEvent, 10000);
Starting := False;
if Status = DEVLINK_COMMS_OPERATIONAL then
begin
DLRegisterType2CallDeltas(fNextHandle, HandleEvent);
LogAddLine(fNextHandle, 'Connected Done');
Edit;
FieldByName('connected').AsInteger := 1;
Post;
end else
begin
DLClose(fNextHandle);
case Status of
DEVLINK_COMMS_NORESPONSE:
begin
LogAddLine(fNextHandle, 'Connected NORESPONSE There Are Problem In network ');
end;
DEVLINK_COMMS_REJECTED:
begin
LogAddLine(fNextHandle, 'Connected REJECTED,Password was incorrect');
end;
end;
end;
end;
Inc(fNextHandle);
end;
Next;
end;
finally
CloseHandle(hEvent);
end;
end;
upload logs for more details..
and write else part of case to check value of Comms_status
How I can get information about Windows OS type? Is it 32bit or 64bit? How I can get this information programatically?
function IsWin64: Boolean;
var
IsWow64Process : function(hProcess : THandle; var Wow64Process : BOOL): BOOL; stdcall;
Wow64Process : BOOL;
begin
Result := False;
IsWow64Process := GetProcAddress(GetModuleHandle(Kernel32), 'IsWow64Process');
if Assigned(IsWow64Process) then begin
if IsWow64Process(GetCurrentProcess, Wow64Process) then begin
Result := Wow64Process;
end;
end;
end;
You need to use GetProcAddress() to check the availability of the IsWow64Process() function at runtime, like so:
function Is64BitWindows: boolean;
type
TIsWow64Process = function(hProcess: THandle; var Wow64Process: BOOL): BOOL;
stdcall;
var
DLLHandle: THandle;
pIsWow64Process: TIsWow64Process;
IsWow64: BOOL;
begin
Result := False;
DllHandle := LoadLibrary('kernel32.dll');
if DLLHandle <> 0 then begin
pIsWow64Process := GetProcAddress(DLLHandle, 'IsWow64Process');
Result := Assigned(pIsWow64Process)
and pIsWow64Process(GetCurrentProcess, IsWow64) and IsWow64;
FreeLibrary(DLLHandle);
end;
end;
because that function is only available on Windows versions that do have a 64 bit flavour. Declaring it as external would prevent your application from running on Windows 2000 or Windows XP pre SP2.
Edit:
Chris has posted a comment about caching the result for performance reasons. This may not be necessary for this particular API function, because kernel32.dll will always be there (and I can't imagine a program that would even load without it), but for other functions things may be different. So here's a version that caches the function result:
function Is64BitWindows: boolean;
type
TIsWow64Process = function(hProcess: THandle; var Wow64Process: BOOL): BOOL;
stdcall;
var
DLLHandle: THandle;
pIsWow64Process: TIsWow64Process;
const
WasCalled: BOOL = False;
IsWow64: BOOL = False;
begin
if not WasCalled then begin
DllHandle := LoadLibrary('kernel32.dll');
if DLLHandle <> 0 then begin
pIsWow64Process := GetProcAddress(DLLHandle, 'IsWow64Process');
if Assigned(pIsWow64Process) then
pIsWow64Process(GetCurrentProcess, IsWow64);
WasCalled := True;
FreeLibrary(DLLHandle);
end;
end;
Result := IsWow64;
end;
Caching this function result is safe, as the API function will either be there or not, and its result can't change on the same Windows installation. It is even safe to call this concurrently from multiple threads, as two threads finding WasCalled to be False will both call the function, write the same result to the same memory location, and only afterwards set WasCalled to True.
If a) you're on windows and b) you can access the registry then HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion should be informative.
In addition to IsWow64Process, the GetNativeSystemInfo API function may be of interest to you (it's defined in the Windows unit) to find out more about the CPU you're on (or you can use assembly and CPUID).
for delphi XE+
Uses System.SysUtils
Function IsWin64Or32: string;
Begin
if Pos( '64-bit', TOSVersion.ToString ) > 0 then
Result := '64-bit'
Else
Result := '32-bit';
End;
Example
lbl1.Caption := IsWin64Or32;
function TForm2.Arch: string;
begin
if TOSVersion.Architecture=arIntelX86 then
Result := '32-bit' Else Result := '64-bit'
end;
I don't know how to call Win32 function in Delphi.
But if you write a 32-bit program, you can call the Win32 API IsWow64Process to know if you are in a 64-bit OS.
Of course, if you write a 64-bit exe, it will only run on 64-bit Windows, so there is no need to ask.
//not tested but u can try this
is64 := (Environment.GetEnvironmentVariable('ProgramW6432') <> '');