DotNet Interop, RunOnClient and WithEvents
February 5th, 2013
And it sounded so promising… Using the FileSystemWatcher .NET class from a NAV 2013 page object to detect changes in a file system folder. I had it all figured out: using the right .NET assembly, responding to the FileSystemWatcher’s events and making sure the object runs on the RTC (as opposed to on the Service Tier).

In the OnOpenPage trigger, I instantiated the FileSystemWatcher, told it to monitor my desktop folder (Environment is another .NET Interop variable, also running on the client), and started the event raising mechanism.

The code above, which worked just fine in a Visual Studio console application, does not produce any results in NAV, i.e. does not trigger any of the events below.

Any ideas, anyone?
February 7th, 2013 at 12:33 am
Unfortunately, this is how NAV2013 currently works. The Client does not know about the Page until after the OnOpenPage trigger has been run so it cannot associate the dotnet object triggers with the page (it does not hook up the events correctly)
So in the current codebase, as a work around, the user can place the initialization in a trigger that gets run after the OnOpenPage trigger - e.g. the OnAfterGetRecord() trigger like this:
IF ISNULL(myVar) THEN
myVar := myVar.myVarType();
But of course that requires a record
Another workaround is to use a client add-in, as that gets instantiated and hooked up to events by the client code.
I know that the current behavior is not as desired. Unfortunately it is not trivial to change, so for us to consider a hotfix would require feedback indicating that this is indeed very important.
Jens Møller-Pedersen [MSFT]
Comment provided ‘as-is’ and does not promise anything on MS behalf
February 8th, 2013 at 8:38 am
Thanks for your explanation, Jens - much appreciated!
The pages of the solution that I made this proof-of-concept for do have source tables, so that shouldn’t be a problem (assuming that’s what you mean by “But of course that requires a record”).
With this new knowledge in mind, I think I’ll give it another try, and post my findings here.
Thanks again!
February 8th, 2013 at 9:09 am
BTW, for those wondering why my FileSystemWatcher variable is a global, despite my frequent and religious pleas to use locals only: this is all about the lifetime of the variable.
As a local, upon leaving the block of code in which it is defined, the variable would go out of scope and be destroyed. In our case, there would be nobody left to fire the events in response to file system changes; not what we want.
We want the FileSystemWatcher to be around for the entire lifetime of the page, so that it, while the page is open, it can trigger the event code. That is of course why we need a global variable - its lifecycle is a long as the lifecycle of the page it lives in.
February 8th, 2013 at 9:56 am
@Jens: The initialization of the FileSystemWatcher variable got moved to a separate function, that, judging from the page’s caption, is called successfully from the OnAfterGetRecord trigger.
InitializeFileSystemWatcher()IF ISNULL(FileSystemWatcher) THEN BEGIN
FileSystemWatcher := FileSystemWatcher.FileSystemWatcher();
FileSystemWatcher.Path := Environment.GetFolderPath(EnvironmentSpecialFolder.Desktop);
FileSystemWatcher.EnableRaisingEvents := TRUE;
CurrPage.CAPTION := FileSystemWatcher.Path;
END;
However, still none of my events are being triggered…
I must be doing something else wrong, eh?
February 8th, 2013 at 12:15 pm
@Jens: I think it really would be good to have that. If not through a hotfix, at least in nav8
With client add-ins there is similar “problem”: I love the new possibilities to access methods and properties of the add-in. Unfortunately they are only accessible in certain triggers (OnAfterGetRecord, but not OnInsertRecord), which makes it bit of a pain to use.