Wednesday, November 15, 2017

NPM global packages

To list global NPM packages:

npm list -g --depth=0

 To update the globally installed NPM packages:

sudo npm -g update

Wednesday, January 25, 2017

Python Debugging Notes

A few notes for me...

  • To print the properties of an object: 
print “Properties are:”, obj.__dict__

Sunday, July 17, 2016

Accessing a VS2015 Express website on a Parallels VM from a Mac

I’ve got a Mac which is running a Windows 10 Parallels VM that I use for Microsoft Visual Studio 2015 development. I’m using the Express Edition of VS2015. If I code up a web application (maybe a web service or an ASP.NET Web API) and run it in the IDE, I can hit it from the browser on that machine at http://localhost:57292/api/test.

How can I consume this Windows 10 web service from my Mac?

First of all I need to know the IP address of my Win 10 machine. Fire up a “cmd" prompt and run “ipconfig”. In my case the "IPv4 Address” is 10.211.55.4

To avoid having to remember and type this address, let’s add it to the “hosts” file on the Mac. Do this from the Terminal on the Mac using “sudo vi /private/etc/hosts” and add in a new line such as:

10.211.55.4     win10

Sadly, if I fire up Safari on my Mac and try to browse to http://win10:57292/api/test or (http://10.211.55.4:57292/api/test), it won’t find the page. There are two reasons for this:

  1. By default, IIS Express only allows access to your Visual Studio websites via localhost, and
  2. The Windows 10 firewall will block incoming connections to this website.

Fortunately, both of these can be overcome thanks to the handy tips on this webpage. Read it for the details, but for my quick reference I need to do the following on the Windows 10 machine:

  1. Edit the {project}\.vs\config\applicationhost.config file and search for my website (using the port is easiest). Add the following binding (the localhost line will already be there - add the second line with the IP address): 

    <binding protocol="http" bindingInformation="*:57292:localhost" />

    <binding protocol="http" bindingInformation="*:57292:10.211.55.4" />

    NB.This step needs to be done for each new website.  

  2. Create a hole in the Windows 10 firewall using these two commands from a “Run as Administrator” cmd prompt:  

    >netsh http add urlacl url=http://10.211.55.4:57292/ user=everyone 

    >netsh advfirewall firewall add rule name="IISExpressWeb" dir=in protocol=tcp localport=57292 profile=private remoteip=localsubnet action=allow

Now, firing up Safari on the Mac and browsing to http://win10:57292/api/test should work!

If you are getting a 503 error, it could be because IIS Express hasn’t restarted and picked up the new website location. Check in the Windows System Tray for the IIS Express icon and click on it to see when there IP address is listed under the application:

IIS express from system tray

 If it isn’t there, stop VS2015, exit IIS Express if still running (using the ‘Exit' option above), and restart your VS2015 application.

Thursday, July 3, 2014

Accessing a VS2013 Express website on a Parallels VM from a Mac

NB. Updated for Windows 10/VS2015 here.

I’ve got a Mac which is running a Windows 7 Parallels VM that I use for Microsoft Visual Studio 2013 development. I’m using the Express Edition of VS2013. If I code up a web application (maybe a web service or an ASP.NET Web API) and run it in the IDE, I can hit it from the browser on that machine at http://localhost:57017/api/test.

How can I consume this Windows 7 web service from my Mac?

First of all I need to know the IP address of my Win 7 machine. Fire up a “cmd" prompt and run “ipconfig”. In my case the "IPv4 Address” is 10.211.55.3

To avoid having to remember and type this address, let’s add it to the “hosts” file on the Mac. Do this from the Terminal on the Mac using “sudo vi /private/etc/hosts” and add in a new line such as:

10.211.55.3     win7

Sadly, if I fire up Safari on my Mac and try to browse to http://win7:57017/api/test or (http://10.211.55.3:57017/api/test), it won’t find the page. There are two reasons for this:

  1. By default, IIS Express only allows access to your Visual Studio websites via localhost, and
  2. The Windows 7 firewall will block incoming connections to this website.

Fortunately, both of these can be overcome thanks to the handy tips on this webpage. Read it for the details, but for my quick reference I need to do the following on the Windows 7 machine:

  1. Edit the C:\Users\{UserName}\Documents\ IISExpress\config\applicationhost.config file and search for my website, adding the following binding (the localhost line will already be there - add the second line with the IP address):

    <binding protocol="http" bindingInformation="*:57017:localhost" />

    <binding protocol="http" bindingInformation="*:57017:10.211.55.3" />

    NB.This step needs to be done for each new website.  

  2. Create a hole in the Windows 7 firewall using these two commands from a “Run as Administrator” cmd prompt: 

    >netsh http add urlacl url=http://10.211.55.3:57017/ user=everyone

    >netsh advfirewall firewall add rule name="IISExpressWeb" dir=in protocol=tcp localport=57017 profile=private remoteip=localsubnet action=allow

Now, firing up Safari on the Mac and browsing to http://win7:57017/api/test should work!

Wednesday, January 29, 2014

Reduce PDF File Size - More options for Mac

On my Mac, I needed to reduce the size of some scanned PDF documents - without changing the scanner settings and rescanning them. I tried to Export from Preview as a PDF using the “Reduce File Size” filter, but it made the files too blurry.

Googling revealed a nice solution, which allows you to add your own custom “Reduce File Size” filters to Preview’s Export window. Once you’ve done this once, you can use them whenever you need to:

New Reduce File Size Filters

I am going to repost how to do this here, so I don’t lose it. The original can be found at: http://hints.macworld.com/article.php?story=20120629091437274

I was never satisfied with results of "Reduce File Size" Quartz filter when trying to make some PDFs smaller before sending them by e-mail. It made them too small, and the graphics were fuzzy. 

I eventually found where these filters are: 

/System/Library/Filters 

I was delighted to find out they're XML files easily editable with TextEdit (or any other text editor). I also found why this particular filter makes quite unusable PDFs, as these parameters were just too low: 

Compression Quality 0.0
ImageSizeMax 512 

So I copied this file to my Desktop, and then made two more copies of it, and called them Reduce File Size Good, Better and Best. Then I changed the parameters of each file to 0.25, 0.5 and 0.75 for Compression Quality, and used these three values for ImageSizeMax: 

842 (that's A4 at 72dpi)
1684 (A4 at 144dpi)
3508 (A4 at 300dpi) 

Finally, I changed the default string for the Name key at the end of each file to reflect the three settings, so they display the names I have given them in the menu. 

Then I copied them to a /Library/Filters folder I created (for some reason, ~/Library/Filters doesn't work in Lion) and now when I open a picture or PDF in Preview, I have the option of four different qualities for reduced file sizes. 

As an example, I have a JPEG of scanned A4 invoice at 300dpi and it's 1.6MB. When exporting to PDF in reduced size, the file is only 27 KB and it's quite unusable - very fuzzy and hard to read. The Good one is much easier to read, slightly fuzzy and still only 80 KB. Better is 420 KB and clear, and the Best is 600 KB and almost as good as the original even on a laser printer.

A few notes:

  • As well as copying and renaming the *.qfilter files, you also need to change the “Name” parameter in the XML document, from “Reduce File Size” to “Reduce File Size Good” (or whatever).
  • You’ll need to use “sudo…” to create the /Library/Fileters folder and to move the files in there.

 

Friday, February 17, 2012

Implementing a VB6 COM interface in VB.Net - it's not all roses!

Not long after my revelation last week, that VB.Net could implement my VB6 COM interface that had a "optional string" parameter, I ran into a brick wall: VB.Net cannot implement a COM interface where a "Public Property" that passes variables by-reference has been exposed. ie. it can't implement this VB6 code:


Public Property Let MyProperty(sValue As String)
...
End Property


Try it and you get the following error:

Implementing property must have matching 'ReadOnly' or 'WriteOnly' specifiers.

This is a known bug and the only solution is to modify your COM interface (in your original VB6 dll) so that the arguments are passed by-value:


Public Property Let MyProperty(ByVal sValue As String)
...
End Property


Which, under the covers, changes the COM interface from:


[id(0x68030000), propput]
HRESULT MyProperty([in, out] BSTR* );


to


[id(0x68030000), propput]
HRESULT MyProperty([in] BSTR );


But of course, I don't want to change the COM interface - I want to implement the interface that has already been defined and is already being used by multiple legacy applications.

Or I can use C#, which handles these Public Properties just fine.

So I'm caught in a bind - only C# can handle the Public Properties, and only VB.Net can handle the Optional String Parameters. I'm going to have to break my COM interface and force multiple client recompilations... OR use a VB6 COM facade that calls my .Net dll.

A tough choice - yuck, yucky, or yuckier?

Monday, February 13, 2012

HOWTO: Replace a VB6 dll with a C# dll when methods have optional string parameters

My quest to replace my VB6 COM dll with a C# dll continues. In my last post I resolved the problems I was having where early binding to the DLL didn't work, but late binding did.

The problem I need to address this time is handling a VB6 method that has an optional String parameter. Something like:


Public Sub TestMethod(ByVal sArgIn As String, Optional sArgOut As String)


Looking in the TypeLibrary for the DLL (the *.IDL file we get from the OLEVIEW tool), we see this:


HRESULT TestMethod(
[in] BSTR sArgIn,
[in, out, optional] BSTR* sArgOut);


Creating the TLB via the MIDL command works, but it gives the following warning:

.\MyDll13.IDL(30) : warning MIDL2400 : for oleautomation, optional parameters should be VARIANT or VARIANT * : [optional
] [ Parameter 'sArgOut' of Procedure 'TestMethod' ( Interface '_TestClass' ) ]


I'll now go ahead and create my .Net DLL. When I use .Net to implement the interface, it stubs the C# method as:


using System.Runtime.InteropServices;

namespace MyDllNet
{
[ProgId("MyDll.TestClass")]
[ComVisible(true)]
[Guid("D860A2A8-5003-4714-AE59-918FE2B0FC42")]
public class MyProxyClass : MyDll13ModifiedTA.TestClass
{
public string GetVersion()
{...}

public void TestMethod(string sArgIn, [OptionalAttribute]ref string sArgOut)
{...}
}
}


This looks good. After completing the code and compiling it, I run my original VB6 app which uses the TestMethod method from a VB6 app via late binding. It works fine when I pass two parameters, but if I only pass one parameter it falls over with "Run-time error '13' Type mismatch". Interestingly, the VB6 app which uses early binding works with both one or two parameters passed!






C# DLL implements IDL with optional BSTR* argument
VB6 BindingPass One ArgPass Two Args
Early BindingOKOK
Late BindingOKError "Type mismatch"


Plan B. Plan B is to change the optional parameter in the IDL from BSTR* to VARIANT*. According to the MIDL error message, VARIANT* is the right type to use for an optional parameter in COM. Note that I'm not changing the original VB6 COM component, I'm just changing the definition in the Type Library.

Creating the TLB via the MIDL command no longer raises a warning; implementing this new IDL/TLB in Visual Studio yields the following method signature:


public void TestMethod(string sArgIn, [OptionalAttribute]ref object sArgOut) {}


But does it work? No, it's worse! Now it crashes the CLR!!






C# DLL implements IDL with optional VARIANT* argument
VB6 BindingPass One ArgPass Two Args
Early BindingError clr.dll APPCRASHError clr.dll APPCRASH
Late BindingOKOK


OK, this confirms that I don't know what I'm doing! But wait, if I remove all of the code from my "TestMethod" in the .Net DLL then everything works!?! The APPCRASH must be caused by the way I'm handling the object argument in my .Net code. Time to debug into the .Net dll component and see what's going on!

And it turns out that if I try to return anything at all (apart from null) in the optional parameter, I get a System.StackOverflowException in an Unknown Module. Almost time for me to give this one away. Just one last thing to try... VB.Net!

Plan C. VB.Net VB.Net offers more comprehensive COM support, presumably because it is supposed to be a migration path for people who have VB6. So I'll create a new VB.Net class project, and add a reference to the "optional BSTR*" assembly (create in Plan A above), and implement the interface in VB.Net. The VB.Net code looks something like:


Imports System.Runtime.InteropServices

<ProgId("MyDll.TestClass")>
<Guid("D860A2A8-5003-4714-AE59-918FE2B0FC42")>
Public Class MyProxyClass
Implements MyDll13TldAssembly.TestClass

Public Function GetVersion() As String Implements MyDll13TldAssembly._TestClass.GetVersion
...
End Function

Public Sub TestMethod(ByVal sArgIn As String, Optional ByRef sArgOut As String = Nothing) Implements MyDll13TldAssembly._TestClass.TestMethod
...
End Sub
End Class


And guess what? It works! Late-binding, early-binding, the optional supplied, the optional not supplied. All combinations work!. Job done.

To Conclude: If you want to implement a VB6 COM interface, which has an optional String parameter, in .Net, then use VB.Net! (with some provisos)