Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.
We have an application that runs as a service and takes request from users to open, read and write to files. So for example if I want to open file X, I tell the Dataserver what file I want to open and the data I want from it. Then it spawns a service specifically for me(my account) and it will go open the file(locally..) then read the data from the file then send it all back to me. This is keeps my machine from handling all the traffic that would be required to do all those operations and reduces it down to just sending a few requests. The problem is that when the file is opened it is opened locally by the spawned process so MS File Management stuff wont report it and I need to see who has what files opened and to do that I need to see which spawn of the proserv.exe file belongs to which user.
Here's some code to look over. I have not added any error handling to the UDF, but it works on my test system. I need still need to test it on a workstation that is a domain member with a domain user logged on, but the basic principle of the UDF is sound and should work OK for your needs.
; GetAccountFromPID_UDF.wbt ; 32-bit ; ; UDF library to obtain the account name associated with a process. ; ; Rigorous error handling has not been implemented in this UDF. ; ; #DEFINEFUNCTION udfGetAccountFromPID(nPID) if (!IsInt(nPID)) then return '' ; Set up the constants & binary buffers needed to do the job. hProcess = 0 hToken = 0 AcctName = '' DomainName = '' ; #define PROCESS_QUERY_INFORMATION (0x0400) ; #define TOKEN_QUERY (0x0008) ProcQueryInfo = 1024 TokQueryInfo = 8 TokenUser = 1 nHandleBufSize = 4 hHandleBuf = BinaryAlloc(nHandleBufSize) nDWORDBufSize = 4 hDWORDBuf = BinaryAlloc(nDWORDBufSize) nSIDBufSize = 1024 ; Semi-arbitrary length that is good for all known SID values as of Win2K3 & older hSIDBuf = BinaryAlloc(nSIDBufSize) nNameBufSize = 512 ; Semi-arbitrary length that is good for all known account name values as of Win2K3 & older hNameBuf = BinaryAlloc(nNameBufSize) nNameLenBufSize = 4 hNameLenBuf = BinaryAlloc(nNameLenBufSize) nDomainBufSize = 512 ; Semi-arbitrary length that is good for all known account name values as of Win2K3 & older hDomainBuf = BinaryAlloc(nDomainBufSize) nDomainLenBufSize = 4 hDomainLenBuf = BinaryAlloc(nDomainLenBufSize) ; Open a handle to the process for query information access. hProcess = DllCall('KERNEL32.DLL',long:'OpenProcess',long:ProcQueryInfo,long:0,long:nPID) ; Open a handle to the process' access token for query information access. Result = DllCall('ADVAPI32.DLL',long:'OpenProcessToken',long:hProcess,long:TokQueryInfo,lpbinary:hHandleBuf) BinaryEodSet(hHandleBuf,nHandleBufSize) hToken = BinaryPeek4(hHandleBuf,0) ; Obtain the SID associated with the access token. Result = DllCall('ADVAPI32.DLL',long:'GetTokenInformation',long:hToken,long:TokenUser,lpbinary:hSIDBuf,long:nSIDBufSize,lpbinary:hDWORDBuf) BinaryEodSet(hSIDBuf,BinaryPeek4(hDWORDBuf,0)) ; Lookup the account name associated with the SID. ; Please note that we cannot use the lpbinary parameter passing method with hSIDBuf as the actual SID pointer within the buffer ; does not translate properly once the binary buffer is being manipulated within WinBatch. To work around this, we must account ; for the fact that the SID structure within the buffer begins 8 bytes after the start of the buffer. So, we're going to revert ; to using an IntControl() call that existed prior to the implementation of lpbinary in order to get the address of the buffer's ; data segment in memory and then we'll do some pointer arithmetic to make things work out properly. BinaryPoke4(hNameLenBuf,0,nNameBufSize) BinaryPoke4(hDomainLenBuf,0,nDomainBufSize) Result = DllCall('ADVAPI32.DLL',long:'LookupAccountSidA',lpnull,long:IntControl(42,hSIDBuf,0,0,0)+8,lpbinary:hNameBuf,lpbinary:hNameLenBuf,lpbinary:hDomainBuf,lpbinary:hDomainLenBuf,lpbinary:hDWORDBuf) RC = DllLastError() BinaryEodSet(hNameBuf,BinaryPeek4(hNameLenBuf,0)) BinaryEodSet(hDomainBuf,BinaryPeek4(hDomainLenBuf,0)) AcctName = BinaryPeekStr(hNameBuf,0,nNameBufSize) DomainName = BinaryPeekStr(hDomainBuf,0,nDomainBufSize) if (DomainName == 'BUILTIN') then DomainName = '' if (DomainName != '') AcctName = StrCat(DomainName,'\',AcctName) endif ; Close the handles we used. Result = DllCall('KERNEL32.DLL',long:'CloseHandle',long:hProcess) hProcess = 0 Result = DllCall('KERNEL32.DLL',long:'CloseHandle',long:hToken) hToken = 0 ; Free up the buffers we used. hHandleBuf = BinaryFree(hHandleBuf) hDWORDBuf = BinaryFree(hDWORDBuf) hSIDBuf = BinaryFree(hSIDBuf) hNameBuf = BinaryFree(hNameBuf) hNameLenBuf = BinaryFree(hNameLenBuf) hDomainBuf = BinaryFree(hDomainBuf) hDomainLenBuf = BinaryFree(hDomainLenBuf) return AcctName #ENDFUNCTION ; Sample code ; ;Title01 = 'Get Account Name From PID' ; Provide a valid PID value (integer) ;PID = 0 ;Result = udfGetAccountFromPID(PID) ;TempMsg = StrCat('PID = ',PID,@CRLF,'User = "',Result,'"') ;Message(Title01,TempMsg) ;exit
Article ID: W16679
File Created: 2005:02:18:12:21:52
Last Updated: 2005:02:18:12:21:52