|
Is there a way to tell which process last wrote to a file? I can't see anything in the .NET File class or the FileAttributes enum which you get back from the File.GetAttributes call or the Win32 API either.
My program is reading a log file which gets written to by multiple processes. Each process opens the log file, writes to it and closes it. I would like to know which process last wrote to it.
Any ideas?
Thanks,
-Darryl
|
|
|
|
|
I would have thought it was easier for each process to tag the entry/entries in the log file with a moniker unique to that process - I guess it depends on the lifetime of the process as to what you're doing with the information
I dont think there's an 'easy' way of looking at a file and saying 'who last wrote to it' from an o/s point of view
- I think you can :-
enumerate active processes
for each process, see what file(s) its using
or maybe use a hook and detect when a particular file (the log file) is opened, then raise an event
or use a filesystem watcher to raise an event when the log file is modified, but Im not sure if that gives you the process details
but thats a lot of overhead isnt it ?
if anyone else knows how to solve this I'd love to see the answer myself
'g'
|
|
|
|
|
Garth J Lancaster wrote: I would have thought it was easier for each process to tag the entry/entries in the log file with a moniker unique to that process - I guess it depends on the lifetime of the process as to what you're doing with the information
Unfortunatley I don't think this can be done in my case.
Garth J Lancaster wrote:
or use a filesystem watcher to raise an event when the log file is modified, but Im not sure if that gives you the process details
FileSystemWatcher is what I am using now. In the Changed event handler I don't seem to have access to any process information. I get only the change type (Changed, Created, Deleted, or Renamed) and the file name and directory name.
Since the file is opened only a very brief time while 1 line is written to it I'm not sure if I will be able to hook off of processes opening files but that may be a possibility.
Thanks for your advice and maybe someone else has other insights as well?
Darryl
|
|
|
|
|
Identify the writer process in log file with an additional field.
The file attributes alone do not keep track of the last process, only timestamps. Neither ReadDirectoryChangesW and FILE_NOTIFY_INFORMATION can offer a PID, at least (even if PIDs are reusable so you can't "make a guess" based on a PID value alone).
The closest thing could be the USN_RECORD structure, but that implies you are on a filesystem with journaling of some sort, although I can't see process-related data either in journaling structures.
So, AFAIK, the process should write additional info themselves in the log file.
|
|
|
|
|
Thanks for your help Cristian. This is pretty much what I expected but I hoped I was missing something. Unfortunatly the code writing to the file is out of my control but maybe I can get them to make changes for the next version.
Darryl
|
|
|
|
|
|
Filemonitor does not offer process identification, just file events (but not source).
|
|
|
|
|
|
Do you want to show a dialog that you created(Create) if yes use of ShowWindow
|
|
|
|
|
If you want it modal you can always use DoModal(); .
If you want it to be non modal, then you must create that dialog and then show it using ShowWindow();
Hope this helps.
|
|
|
|
|
How can be tested - in VC++6 that a driver is installed or not? We know the driver name.
36. When you surround an army, leave an outlet free.
...
Do not press a desperate foe too hard.
SUN-TZU - Art of War
|
|
|
|
|
How about starting with:
EnumDeviceDrivers(aDrivers, sizeof(aDrivers), &cbNeeded)
(SDK)
and test if the driver is in the list?
You could get additional infos with
GetDeviceDriverBaseName(aDrivers[i], szBaseName,sizeof(szBaseName))
and
GetDeviceDriverFileName(aDrivers[i], szDriverFileName,sizeof(szDriverFileName))
greetings,
ralf.
|
|
|
|
|
Thanks!
=======================================================================
36. When you surround an army, leave an outlet free.
...
Do not press a desperate foe too hard.
SUN-TZU - Art of War
|
|
|
|
|
Sorry, I've not been able to place here a better title...
Hello all,
A strange thing that deserves a code sample and somebody that know what could happen... (this is not me).
BOOL CTCC::InitInstance()
{
m_pLogAE = new A;
m_pXmlAEInternal = new B;
m_pXmlConfig = new C;
if (!FunctionX() ||
!m_pControl->FunctionY() ||
!m_pXmlFile->LoadFile(csPath, csReason))
{
DoSomething();
}
else
{
CTCCDlg dlg;
m_pMainWnd = &dlg;
dlg.DoModal();
m_pControl->RestoreSettings();
if(m_pLogAE) delete m_pLogAE;
if(m_pXmlAEInternal) delete m_pXmlAEInternal;
if(m_pXmlConfig) delete m_pXmlConfig;
}
if(m_pLogAE) delete m_pLogAE;
if(m_pXmlAEInternal) delete m_pXmlAEInternal;
if(m_pXmlConfig) delete m_pXmlConfig;
return FALSE;
As you can see there is a terrible design: I've repeated some code: after the POINT 1 there are three lines that should be only after the POINT 2 as they are intended to clear some memory that has been filled before the first if clause.
It surprises me a lot, but if I place a breakpoint in the line where POINT 1 is, I can see how the application continues until the bracket that is before POINT 2 "}". If I remove the code that is before that bracket and after POINT 1, and execute again the code I can see how if the code reach that bracket it gets stopped again and don't go further the POINT 2.
Any idea?
Thank you in advance.
PS: I've made a "Clean" and a "Rebuild All".
|
|
|
|
|
The 3 if/delete statements below POINT 1 are not necessary. Other than that, I'm not sure what you are asking.
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
this is exactly what I mean, the code cannot reach those three second if/delete statements, and I cannot get any idea about what is happening here.
Of course I didn't had the first ones there, in that way that was general and was being used independent from the previous condition, but I've been forced to do that, it is impossible to reach that code.
|
|
|
|
|
Try this as a test:
BOOL CTCC::InitInstance()
{
m_pLogAE = new A;
m_pXmlAEInternal = new B;
m_pXmlConfig = new C;
CTCCDlg dlg;
m_pMainWnd = &dlg;
dlg.DoModal();
if(m_pLogAE) delete m_pLogAE;
if(m_pXmlAEInternal) delete m_pXmlAEInternal;
if(m_pXmlConfig) delete m_pXmlConfig;
return FALSE;
} If this works, put the call to RestoreSettings() back in.
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
Ok, done, but it continues making the same.
In fact, when I press F10 in order to continue executing the next instruction, everything is correct but when I reach the bracket "}" and then I press F10 again then I get the application finished suddenly. (Even if I try to use F11)...
|
|
|
|
|
Joan Murt wrote: ...when I reach the bracket "}" and then I press F10 again then I get the application finished suddenly.
This makes no sense, other than this is what should be happening. In the code snippet I provided, there is only one closing curly brace. Once code execution reaches that point, your program is effectively done.
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
yes in your code snippet, but not in mine, there you can see how there is a previous condition (if) that must not be accomlpished in order to be able to make that main dialog appear. Once this has been reached, I had the if/delete clauses general (outside that condition) in order to clear all the memory in the two situations.
so:
InitInstance
{
if (A)
{
}
else
{
dlg.DoModal();
<code><big> }</big></code>
if/delete clauses
return FALSE;
}
If I place the if/delete clauses before the bold closing curly brace then I can see how the program goes through it.
If I place that code after that bold closing curly brace it cannot be reached.
I know that this is very strange... but it happens to me.
|
|
|
|
|
I've found that the problem is that when I reach that closing curly brace the dialog gets destroyed and during that process somiething nasty is happening. I must find out what.
Thank you.
|
|
|
|
|
Here we are still at 2006 and I'm not drunk... I promise...
|
|
|
|
|
Joan Murt wrote: If I remove the code that is before that bracket and after POINT 1, and execute again the code I can see how if the code reach that bracket it gets stopped again and don't go further the POINT 2.
Could be possible that in RestoreSettings (or perhaps in dialog) could be a access violation or so causing a jump outside the POINT 2?
* * *
As a suggestion: get rid of those explicit deletion statements with something like
template<typename T>
class Ptr {
public:
explicit Ptr(T *pT = 0)
: m_pT(pT) {
}
virtual ~Ptr() {
erase(); }
public:
operator const T *() const {
return (const T *)m_pT; }
operator T *() {
return m_pT; }
T* operator->() {
return m_pT; }
T** operator&() {
return &m_pT; }
Ptr& operator=(T *pT) {
m_pT = pT;
return *this; }
operator bool() const {
return (m_pT != 0) ? true : false; }
bool operator !() const {
return (m_pT == 0) ? true : false; }
protected:
virtual void erase() {
T *pT = m_pT;
m_pT = 0;
if(pT) {
delete pT;
} }
protected:
T *m_pT;
};
and use as
Ptr<A> m_pLogAE = new A;
Ptr<B> m_pXmlAEInternal = new B;
Ptr<C> m_pXmlConfig = new C;
You don't have to manage the deletions yourself anymore. (Check the code, however).
-- modified at 5:16 Saturday 30th December, 2006
|
|
|
|
|
Cristian Amarie wrote: (or perhaps in dialog)
Yes, you are right, but I cannot understand or find why do this happens.
I have the code in this way:
if(a)
{
}
else
{
CDialog a;
...
}
if/delete clauses
Of course when the Dialog destructor is called, it generates some kind of error, so I must try to find it out, but it will be hard... this dialog has one embedded property sheet with 5 propoerty pages and inside those property pages there is another propoerty sheet embedded with 3 property pages each, and all of them with several controls, so I must track all those dialogs...
Thank you!
|
|
|
|
|
One possibility is that you end up doing the delete twice; once after POINT 1, and then again at POINT 2. In a debug build, this will cause an assertion, and in a release build you will probably exit with an access violation.
On a style note, I would code this as follows:
BOOL CTCC::InitInstance(){
m_pLogAE = new A;
m_pXmlAEInternal = new B;
m_pXmlConfig = new C;
if (!FunctionX() ||
!m_pControl->FunctionY() ||
!m_pXmlFile->LoadFile(csPath, csReason)) {
DoSomething();
}
else {
CTCCDlg dlg;
m_pMainWnd = &dlg;
dlg.DoModal();
m_pControl->RestoreSettings();
}
delete m_pLogAE;
delete m_pXmlAEInternal;
delete m_pXmlConfig;
return FALSE;
} I removed the extra if /delete lines at POINT 1. I also removed the if tests on the delete lines at POINT 2. Even if the pointers are NULL , it's still perfectly valid to delete them.
Software Zen: delete this;
|
|
|
|