System.Diagnostics.Process and speed
I was working on some code that seemed to take an age to get going. Simple I thought: run it throught the Red Gate ANTS Profiler, look at the offending code and sort the problem. I wish it was as straightforward. Profiling or debugging the code seemed to make it run quickly, so I had to resort to the good old technique of logging debug output line by line.
After finding the lethargic code, the line that stalled progress for almost a minute didn’t look that concerning:
Process.GetCurrentProcess().ProcessNameA bit of Googling turned up trumps. A post by Brian Grunkemeyer from the BCL team gave the answer:
The way the Process class currently works, the first time you try to do anything that requires knowing the state of the current process, we take a snapshot of all the processes in the system. So yes, this operation is slow the first time you call it. We could potentially limit this snapshot to just the current process by requesting MORE information about the current process from Windows (CreateToolhelp32Snapshot is a peculiar method), but that leads into peculiar situations where the snapshot information for the current process then gets out of sync if you call another method on the Process class to enumerate all the other processes.
This initial snapshot must have been the cause of the delay. A quick code-edit later to avoid the use of the Process class (I was actually interested in the name of the executing file so I used Assembly.GetExecutingAssembly()) and the almost 60 second pause was gone.
So why was it running quicker when debugging/profiling? I presume that the debugger/profiler would have been using the System.Diagnostics namespace, and more specifically the Process class, as part of its internals, thus the costly first call snapshot had already happened.
Fusion log viewer
Whilst trying to work out why some code was running very slowly (see System.Diagnostics.Process and speed), I tried to see whether the slowness was caused by loading code contained in a separate dll. To get this information, I needed to look at the fusion logs. Configuring these logs is not fool-proof, so having spent a few hours getting it working, I thought I’d document the process.
Suzanne Cook’s blog was quite useful, as was the Assembly Binding Log Viewer article on MSDN, but neither of them contained exactly what was needed.
To set up the fusion logs ready for viewing, some entries need to be added to the registry in the HKEY_LOCAL_MACHINE\Software\Microsoft\Fusion key. The combination needed depends on what you’re trying to inspect. The keys are:
-
LogFailures = 1 (DWORD Value)
This turns on failure logging so that failed attempts to locate all assemblies are logged. -
LogResourceBinds = 1 (DWORD Value)
This turns on failure logging so that failed attempts to locate satellite assemblies are logged. This is not logged by default. -
ForceLog = 1 (DWORD Value)
This turns on logging for all assembly binds - both failures and successes. By default, only failures are logged. This is useful if you want to verify that an assembly is loading from a specific directory instead of from the global assembly cache. -
LogPath = “C:\fusionlogs" (String Value)
If you want to view the fusion logs easily, set the LogPath to a directory to output them to. By default the log files go into the Temporary Internet Files folder of the current user’s profile. For an ASP.Net or a .Net Windows service application, the only way to view the fusion log is to use this option. This is because they run as users other than the current user. The directory specified must already exist and have appropriate file permissions to be written to. For ASP.Net applications, the ASPNET user must have write permission to the directory. If the permissions are wrong, there will be no log output.
Once you have configured the relevant logging options, running the .Net application will generation the fusion logs. Once generated, the logs can be viewed using the fuslogvw.exe tool that comes as part of the framework SDK (mine was inside the SDK folder inside Visual Studio’s installation folder). I found that either the 1.1 or 2.0 version will work, but the 2.0 version is a little better as it has a few more options in the GUI:
To view a specific log, choose it from the main section and click the view log button. The log will open in an internet browser showing the assembly binding details.
DNS error when adding a computer to a domain
After having several problems with my laptop accessing files on my server (the domain controller for my domain), I had a look in the event log and found this error:
The computer [computername] tried to connect to the server \\[servername] using the trust relationship established by the [domainname] domain. However, the computer lost the correct security identifier (SID) when the domain was reconfigured. Reestablish the trust relationship.
I figured that this may be the cause of the problems and so set about reestablishing the trust relationship between the laptop and the server. Sounded like a simple task, but the only (easy) way I could find to do this was to remove the laptop from the domain and then add it again. After removing it successfully, I kept getting an error when trying to re-add it:
The domain name [domainname] might be a NetBIOS domain name. If this is the case, verify that the domain name is properly registered with WINS. If you are certain that the name is not a NetBIOS domain name, then the following information can help you troubleshoot your DNS configuration. An error occurred when DNS was queried for the service location (SRV) resource record used to locate a domain controller for domain [domainname]. The error was: "No DNS servers configured for local system." (error code 0×0000267C DNS_ERROR_NO_DNS_SERVERS) The query was for the SRV record for _ldap._tcp.dc._msdcs.[domain]”
After puzzling for ages as to why it wasn’t happy, I checked my IP settings and found the problem. Somehow, the IP settings had changed to a specified IP address instead of using DHCP. Changing them back solved the problem straight away.
Cats game
I don’t really play games on my PC, but this Cats game from Ferry Halim’s site has me addicted. I think it must be because of the pure simplicity of the game, but I suspect it also has something to do with the hypnotic accompanying music. De doo de doo duh, de doo duh. Doo duh, doo de doo duh…
Security applications break .Net 2.0 remoting
Jamie Cansdale from TestDriven.Net posted about certain security software breaking remoting with .Net 2.0. He also includes a downloadable example to demonstrate the problem.
The current list of culprits is:
The common thread amongst these is that they all have some network monitoring functionality.
The error occurs whenever a .Net TCP remoting channel is closed. Perculiarly, the error happens not on the end that closes the channel, but in the application on the other end of the channel.
The stack trace of the error is:
Exception: System.AccessViolationException Message: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. Server stack trace: at System.Net.UnsafeNclNativeMethods.OSSOCK.WSAGetOverlappedResult(SafeCloseSocket socketHandle, IntPtr overlapped, UInt32& bytesTransferred, Boolean wait, IntPtr ignored) at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
I tried the sample code as described with NOD32, remoting to both localhost and to a separate PC but could not get the behaviour.
Update: Jon Cole from Microsoft has posted on the MSDN forums verifying that this is indeed a bug, and that it should be fixed in the next release.
