Showing posts with label WinAPI. Show all posts
Showing posts with label WinAPI. Show all posts

Thursday, December 21, 2006

Memory usage of axapta task

On a job client we had some troubles with memory wastage.
The reason was an external application with which we communicate across an OCX.
On each call the application needs more and more memory.
Our experience shows, on about 100MB Axapta crashed.
To solve this problem, our idea was, to monitor the used memory and if axapta reaches an defined limit, to shut down the axapta client.
With windows task manager it should be restartet automatic.

Now, after approximately three weeks in production system, we can say it works without problems, it works marvelously.


Solution:
Three new WinAPI-functions:


getProcessMemoryInfo
Retrieves information about the memory usage of the specified process.
Link to ms...


static container getProcessMemoryInfo(int _processHandle)
{
#define.structSize(4*10)
DLLFunction _getProcessMemoryInfo ;
Binary struct = new Binary(#structSize);
DLL _dLL = new DLL(#PSAPIDLL);
_getProcessMemoryInfo = new DLLFunction(_DLL, 'GetProcessMemoryInfo');

_getProcessMemoryInfo.returns(ExtTypes::DWord);

_getProcessMemoryInfo.arg(ExtTypes::DWord,
ExtTypes::Pointer, ExtTypes::DWord);

struct.dWord (#offset0, 0 );
struct.dWord (#offset4, #structSize );
struct.dWord (#offset8, 0 );
struct.dWord (#offset12, 0 );
struct.dWord (#offset16, 0 );
struct.dWord (#offset20, 0 );
struct.dWord (#offset24, 0 );
struct.dWord (#offset28, 0 );
struct.dWord (#offset32, 0 );
struct.dWord (#offset36, 0 );

if (_getProcessMemoryInfo.call(_processHandle, struct, #structSize))
{
return [struct.dWord(#offset0),
struct.dWord(#offset4),
struct.dWord(#offset8),

struct.dWord(#offset12),
struct.dWord(#offset16),
struct.dWord(#offset20),
struct.dWord(#offset24),
struct.dWord(#offset28),
struct.dWord(#offset32),
struct.dWord(#offset36)];
}

return conNull();

}


getCurrentProcessId
Retrieves the process identifier of the calling process.
Link to ms...

client server static int getCurrentProcessId()
{
//The return value is the process identifier of the calling process.

DLL winApiDLL = new DLL(#KERNELDLL);
DLLFunction getCurrentProcessId = new DLLFunction(winApiDLL, 'GetCurrentProcessId');

getCurrentProcessId.returns(ExtTypes::DWord);
return getCurrentProcessId.call();
}

OpenProcess
Opens an existing local process object.
Link to ms...

static int openProcess(boolean _openForQuery = true, int _processId = winapi::getCurrentProcessId())
{
//If the function succeeds, the return value is an open handle of the specified process.

#define.PROCESS_QUERY_INFORMATION (1024) //&h400
#define.PROCESS_VM_READ (16) //&h10
#define.PROCESS_ALL_ACCESS (2035711) //&H1F0FFF
DLL _winApiDLL = new DLL('KERNEL32');
DLLFunction _openProcess = new DLLFunction(_winApiDLL, 'OpenProcess');
int call = _openForQuery ? #PROCESS_QUERY_INFORMATION : #PROCESS_ALL_ACCESS;
;
_openProcess.returns(ExtTypes::DWord);
_openProcess.arg(ExtTypes::DWord, ExtTypes::DWord, ExtTypes::DWord);
return _openProcess.call(call, 0, _processId);
}

Usage:
Simple job:
static int getCurrentMemoryUsage(boolean _kiloByte = true)
{
hwnd curhwnd = winapi::openProcess();
container memInfo;
;
memInfo = winapi::getProcessMemoryInfo(curhwnd);
winapi::closeHandle(curhwnd);
if(_kiloByte)
return conpeek(memInfo, 4) / 1024;
else
return conpeek(memInfo, 4);
}

Friday, November 10, 2006

WTSQuerySessionInformation

The WTSQuerySessionInformation function retrieves session information for the specified session on the specified terminal server.

With the function below you can find out the ip-Address of the client-computer if they logged in on a terminal server!
Under it, there is a function to get the client machine name!

Take a look to
http://www.microsoft.com/Businesssolutions.....
http://msdn.microsoft.com/library/...

#define.WTSClientIP(14)
#define.WTS_CURRENT_SESSION(-1)
#define.WTS_CURRENT_SERVER_HANDLE(0)
#define.structSize(256)
client server static str getRDPIPAddress()
{
DLL _winApiDLL = new DLL('WTSAPI32');
DLLFunction _getRDPName = new DLLFunction(_winApiDLL, 'WTSQuerySessionInformationA');
Binary dwPointer;
Binary structPointer;
Binary structAccess;
int spRet;
int dwret;
str rdpIP = "";
;
structpointer = new Binary(4); // will receive the pointer to result struc
dwPointer = new Binary(4); // wiil receive the length of reult struc


_getRDPName.returns(ExtTypes::DWORD);
_getRDPName.arg(ExtTypes::DWORD,
ExtTypes::DWORD,
ExtTypes::DWORD,
ExtTypes::POINTER,
ExtTypes::POINTER);


if(_getRDPName.call(#WTS_CURRENT_SERVER_HANDLE, #WTS_CURRENT_SESSION,
#WTSClientIP, structpointer, dwpointer) != 0)
{
spRet = structpointer.dWord(0);
dwRet = dwPointer.dWord(0);
structAccess = new Binary(0);
structAccess.attach(spRet,dwRet);

rdpIP = strfmt("%1", structAccess.byte(6));
rdpIP = rdpip + "." + strfmt("%1", structAccess.byte(7));
rdpIP = rdpip + "." + strfmt("%1", structAccess.byte(8));
rdpIP = rdpip + "." + strfmt("%1", structAccess.byte(9));
}
WinAPI::WTSFreeMemory(spRet);
return rdpIP;
}

client static void WTSFreeMemory(int _buffer)
{
DLL wtsapi32DLL = new DLL('wtsapi32.dll');
DLLFunction wtsfm = new DLLFunction(wtsapi32DLL, 'WTSFreeMemory');
;
wtsfm.arg(ExtTypes::DWord);
wtsfm.call(_buffer);
}

To get the client machine name:

#define.WTSClientName(10)
client server static str getRDPComputerName()
{
/*
Franz Aigner 20050922

*/
DLL _winApiDLL = new DLL('WTSAPI32');
DLLFunction _getRDPName = new DLLFunction(_winApiDLL, 'WTSQuerySessionInformationA');
Binary dwPointer;
Binary structPointer;
Binary structAccess;
int spRet;
int dwret;
str rdpName = "";
;
structpointer = new Binary(4); // will receive the pointer to result struc
dwPointer = new Binary(4); // wiil receive the length of reult struc


_getRDPName.returns(ExtTypes::DWORD);
_getRDPName.arg(ExtTypes::DWORD,
ExtTypes::DWORD,
ExtTypes::DWORD,
ExtTypes::POINTER,
ExtTypes::POINTER);

if(_getRDPName.call(#WTS_CURRENT_SERVER_HANDLE, #WTS_CURRENT_SESSION,
#WTSClientName, structpointer, dwpointer) != 0)
{
spRet = structpointer.dWord(0);
dwRet = dwPointer.dWord(0);
structAccess = new Binary(0);
structAccess.attach(spRet,dwRet);
rdpName = structAccess.string(0);
}
WinAPI::WTSFreeMemory(spRet);
return rdpName;
}

Thursday, November 02, 2006

MakeSureDirectoryPathExists

The powerfully WinApi-Function 'MakeSureDirectoryPathExists' implementet in X++!

The MakeSureDirectoryPathExists function creates all the directories in the specified _filePath, beginning with the root.

This function resides in imagehlp.dll, but also in
dbghelp.dll.
Take a look to http://msdn2.microsoft.com/en-us/library/ms680352.aspx

static int MakeSureDirectoryPathExits(FilePath _filePath)
{
/*
fa 20061102
Returnvalue:
0... OK
>0.. Error
*/

#define.imagehlp('imagehlp.dll')
DLL winApiDLL = new DLL(#imagehlp);
DLLFunction pathExits = new DLLFunction(winApiDLL, 'MakeSureDirectoryPathExists');
int retVal = 0;
;
if(substr(_filePath, strlen(_filePath), 2) != "\\")
_filePath += "\\";


pathExits.returns(ExtTypes::DWord);
pathExits.arg(ExtTypes::String);

if (pathExits.call(_filePath) == 0)
{
retVal = WinAPI::getLastError();
retVal = retVal == 0 ? 1 : retVal;
}

return retVal;

}