Skip to main content

3 posts tagged with "windows"

View All Tags

Windows Defender Step Away From npm

Update 18/06/2017#

Whilst things did improve by fiddling with Windows Defender it wasn't a 100% fix which makes me wary. Interestingly, VS Code was always open when I did experience the issue and I haven't experienced it when it's been closed. So it may be the cause. I've opened an issue for this against the VS Code repo - it sounds like other people may be affected as I was. Perhaps this is VS Code and not Windows Defender. Watch that space...

Update 12/07/2017#

The issue was VS Code. The bug has now been fixed and shipped last night with VS Code 1.14.0. Yay!


I've recently experienced many of my npm installs failing for no consistent reason. The error message would generally be something along the lines of:

npm ERR! Error: EPERM: operation not permitted, rename 'C:\dev\training\drrug\node_modules\.staging\@exponent\ngrok-fc327f2a' -> 'C:\dev\training\drrug\node_modules\@exponent\ngrok'

I spent a good deal of time changing the versions of node and npm I was running; all seemingly to no avail. Regular flakiness which I ascribed to node / npm. I was starting to give up when I read of other people experiencing similar issues. Encouragingly Fernando Meira suggested a solution:

I got the same problem just doing an npm install. Run with antivirus disabled (if you use Windows Defender, turn off Real-Time protection and Cloud-based protection). That worked for me!

I didn't really expect this to work - Windows Defender has been running in the background of my Windows 10 laptop since I've had it. There's been no problems with npm installs up until a week or so ago. But given the experience I and others have had I thought I should put it out there: it looks like Windows Defender has it in for npm. Go figure.

Alas Windows Defender doesn't stay dead for long; it's like a zombie that rises from the grave no matter how many times you kill it. So you might want to try configuring it to ignore node.exe:

Or switching to Linux...

npm please stop hurting Visual Studio

I don't know about you but I personally feel that the following sentence may well be the saddest in the English language:

2>ASPNETCOMPILER : error ASPRUNTIME: The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.

The message above would suggest there is some kind of ASP.Net issue going on. There isn't - the problem actually lies with Windows. It's not the first time it's come up but for those of you not aware there is something you need to know about Windows: It handles long paths badly.

There's a number of caveats which people may attach the above sentence. But essentially what I have said is true. And it becomes brutally apparent to you the moment you start using a few node / npm powered tools in your workflow. You will likely see that horrible message and you won't be able to get much further forward. Sigh. I thought this was the future...

This post is about how to deal with the long path issue when using npm with Visual Studio. This should very much be a short term workaround as npm 3.0 is planned to make long paths with npm a thing of the past. But until that golden dawn....

The Latest Infraction#

I'm a big fan of Gulp and Bower. They rock. Steve Cadwallader wrote an excellent blog post about integrating Gulp into your Visual Studio build. Essentially the Gist of his post is this: forget using Task Runner Explorer to trigger your Gulp / Grunt jobs. No, actually plug it into the build process by tweaking your .csproj file. The first time I used this approach it was a dream come true. It just worked and I was a very happy man.

Since this approach was so marvellous I took a look at the demo / docs part of jQuery Validation Unobtrusive Native with a view to applying it there. I originally wrote this back in 2013 and at the time used NuGet for both server and client side package management. I decided to migrate it to use Bower for the client side packages (which I planned to combine with a Gulp script which was going to pull out the required JS / CSS etc as needed). However it wasn't the plain sailing I'd imagined. The actual switchover from NuGet to Bower was simple. Just a case of removing NuGet packages and adding their associated Bower counterpart. The problem came when the migration was done and I hit "compile". That's when I got to see 2>ASPNETCOMPILER : error ASPRUNTIME: The specified path, file name, or both are too long... etc

For reasons that I don't fully understand, Visual Studio is really upset by the presence in the project structure of one almighty long path. Oddly enough, not a path that's actually part of the Visual Studio project in question at all. Rather one that has come along as a result of our Gulp / Bower / npm shenanigans. Quick as a flash, I whipped out Daniel Schroeder's Path Length Checker to see where the problem lay:

And lo, the fault lay with Bower. Poor show, Bower, poor show.

rimraf to the Rescue#

rimraf is "the UNIX commandrm -rf for node". (By the way, what is it with node and the pathological hatred of capital letters?)

What this means is: rimraf can delete. Properly. So let's get it: npm install -g rimraf. Then at any time at the command line we can dispose of a long path in 2 shakes of lamb's tail.

In my current situation the contents of the node_modules folder is causing me heartache. But with rimraf in play I can get rid of it with the magic words: rimraf ./node_modules. Alakazam! So let's poke this command into the extra commands that I've already shoplifted from Steve's blog post. I'll end up with the following section of XML at the end of my .csproj:

<PropertyGroup>
<CompileDependsOn>
$(CompileDependsOn);
GulpBuild;
</CompileDependsOn>
<CleanDependsOn>
$(CleanDependsOn);
GulpClean
</CleanDependsOn>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CollectGulpOutput;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
CollectGulpOutput;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
</PropertyGroup>
<Target Name="GulpBuild">
<Exec Command="npm install" />
<Exec Command="bower install" />
<Exec Command="gulp" />
<Exec Command="rimraf ./node_modules" />
</Target>
<Target Name="GulpClean">
<Exec Command="npm install" />
<Exec Command="gulp clean" />
<Exec Command="rimraf ./node_modules" />
</Target>
<Target Name="CollectGulpOutput">
<ItemGroup>
<_CustomFiles Include="build\**\*" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>build\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
<Message Text="CollectGulpOutput list: %(_CustomFiles.Identity)" />
</Target>

So let's focus on the important bits in the GulpBuild target:

  • &lt;Exec Command="npm install" /&gt; - install the node packages our project uses as specified in package.json. This will include Gulp and Bower. The latter package is going to contain super-long, Windows wrecking paths.
  • &lt;Exec Command="bower install" /&gt; - install the bower packages specified in bower.json using Bower (which was installed by npm just now).
  • &lt;Exec Command="gulp" /&gt; - do a little dance, make a little love, copy a few files, get down tonight.
  • &lt;Exec Command="rimraf ./node_modules" /&gt; - remove the node_modules folder populated by the npm install command.

With that addition of rimraf ./node_modules to the build phase the problem goes away. During each build a big, big Windows path is being constructed but then it's wiped again before it has chance to upset anyone. I've also added the same to the GulpClean target.

You are very welcome.

WCF Transport Windows authentication using NetTcpBinding in an Intranet environment

Update#

Since I wrote this initial post I've taken thinks on a bit further. Take a look at this post to see what I mean: http://icanmakethiswork.blogspot.com/2012/03/wcf-moving-from-config-to-code-simple.html I know I said I'd write about JSON this time. I will get to that but not this time. This time WCF authentication quirks. I've been working on a project that uses .NET Remoting to have a single central point to which web applications and Windows services can call into. This is used in an intranet environment and all the websites and Windows services were hosted on the same single server along with our .NET Remoting Windows service. (They could quite easily have been on different servers but there was no need in this case.) It was decided to "embrace the new" by migrating this .NET Remoting project over to WCF. The plan wasn't to do anything revolutionary, just to move from one approach to the other as easily as possible. I found the following useful article on MSDN: http://msdn.microsoft.com/en-us/library/aa730857%28v=vs.80%29.aspx This particular article was helpful and following the steps enclosed I was quickly up and running with a basic WCF service hosted in a Windows service. It was at this point I started thinking about security. The existing .NET Remoting approach had no security in place. This wasn't ideal but also probably wasn't the worry you might think. It was hosted in an intranet environment and hence not so exposed to the rigours of the Wild Wild Web. However, since I was looking at WCF I thought it would be a good opportunity to get some basic security in place. This generally pleases auditors. I opted to use Windows Transport authentication as this seemed pretty appropriate for an intranet environment. The idea being that we'd authenticate with Windows for an account in our domain. After headbutting Windows for some time I managed to get a successful client call going from the website running on my development machine to the (separate) development server that was hosting our WCF Window service using Transport Windows authentication. However, when deploying the website to the development server I discovered we would experience the following error when the website attempted to call the WCF service (on the same server). ``` Event Type: Failure Audit Event Source: Security Event Category: Logon/Logoff Event ID: 537 Date: 15/02/2012 Time: 16:32:04 User: NT AUTHORITY\SYSTEM Computer: MINE999 Description: Logon Failure: Reason: An error occurred during logon Logon Type: 3 Logon Process: ^ Authentication Package: NTLM Status code: 0xC000006D

Not terribly helpful. At the end of the day it seemed we were suffering from a security "feature" introduced by Microsoft to prevent services calling services on the same box with a fully qualified name. An explanation of this can be found here: [http://developers.de/blogs/damir\_dobric/archive/2009/08/28/authentication-problems-by-using-of-ntlm.aspx](<http://developers.de/blogs/damir_dobric/archive/2009/08/28/authentication-problems-by-using-of-ntlm.aspx>) Using method 1 in the enclosed link I initially worked round this by amending the registry and rebooting the server: [http://support.microsoft.com/kb/887993](<http://support.microsoft.com/kb/887993>) This was not a fantastic solution. Fortunately I subsequently found a better one but since the resources on the web are \***ATROCIOUS**\* on this point I thought I should take the time to note down the full explanation since otherwise it'll be lost in the mists of time. Here we go: The equivalent security to the previous .NET Remoting solution in WCF was to use this config setting on client and service: ```xml
<security mode="None" />

As I've said, this is an intranet environment and so having this "none" security setting in place is made less worrying by the fact that the network itself is secured. But obviously this is not ideal and unlikely to be audit compliant. To use Windows security you need this netTcpBinding config setting on client and service: ```xml

```

To call the service with this setting in place you will need to be an authenticated Windows user. (Or at the very least impersonating one - but you knew that.) NOW FOR THE MOST IMPORTANT BIT..... The endpoint addresses *must* be "localhost" for both

client and service when both are deployed to the same server. If this is not the case then you will suffer from the aforementioned security "feature" which will provide you with unhelpful "the server has rejected the client credentials" messages and *nothing* else. OK FINISHED - MOVE ALONG NOW... NOTHING MORE TO SEE HERE With WCF Windows Transport authentication in place you can interrogate the calling user id within the service methods by simply evaluating ServiceSecurityContext.Current.PrimaryIdentity.Name (which will be something like "myDomain\myUserName"). So we you wanted to, we could have a simple step which evaluated if the calling user is on the "approved" / "authorised" list. I'm sure this could be made more sophisticated by using groups etc I guess - though I haven't investigated it further as yet. In fact, I suspect Microsoft may have something even more sophisticated still available for use which I'm unaware of - if anyone knows a simple explanation of this then please do let me know! In closing, I do think Microsoft could work on providing more helpful error messages than "the server has rejected the client credentials". Going by what I read as I researched this error many people seem to have struggled much as I did before eventually bailing out and ended up chancing it by turning security off in their applications. Clearly it is not desirable to have people so confused by errors that they give up and settle for a less secure solution.