Author Archives: Chris F Carroll

Max de Vries Interview – What every project manager should know

I was recently fortunate enough to catch Max de Vries on a trip to the UK. Max has overseen complex IT projects in Europe, Asia and the US, in finance, public sector and now games for over 20 years, most recently being in charge of Popcap’s Plants vs Zombies franchise, overseeing the launch of PvZ 2 and PvZ-Garden Warfare. I managed to fire off two quick questions before he had to go:

Q: What are the top 3 things every project manager should know?
Who to trust; how to communicate; and what would success look like.
Q: What are the common mistake that inexperienced project managers make?
  • Not realizing they are inexperienced
  • Making estimation a political process
  • Miscalculating the cost of saying no vs the cost of failure
  • Not thinking about the critical path hard enough
  • Thinking that people know what they want
  • Underestimating the value of a high functioning team
  • With agile processes: Modifying a process without understanding the reasons why the process works and doesn’t work

So now you know.

Command line concatenate PDFs on OS X

A great post at which does what it says on the tin.

He explains how to link to a python script included in OS X since some years ago so as to make concatenating PDFs as easy as typing

pdfconcat -o output.pdf *.pdf

The heavy lifting is all done with calls to OS X Quartz.CoreGraphics module so this isn’t going to work on other platforms, but for the curious it demonstrates how easily you can do such stuff on OS X.

#! /usr/bin/python
# join
#   Joing pages from a a collection of PDF files into a single PDF file.
#   join [--output <file>] [--shuffle] [--verbose]"
#   Parameter:
#   --shuffle
#	Take a page from each PDF input file in turn before taking another from each file.
#	If this option is not specified then all of the pages from a PDF file are appended
#	to the output PDF file before the next input PDF file is processed.
#   --verbose
#   Write information about the doings of this tool to stderr.
import sys
import os
import getopt
import tempfile
import shutil
from CoreFoundation import *
from Quartz.CoreGraphics import *

verbose = False

def createPDFDocumentWithPath(path):
	global verbose
	if verbose:
		print "Creating PDF document from file %s" % (path)
	return CGPDFDocumentCreateWithURL(CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, path, len(path), False))

def writePageFromDoc(writeContext, doc, pageNum):

	global verbose
	page = CGPDFDocumentGetPage(doc, pageNum)
	if page:
		mediaBox = CGPDFPageGetBoxRect(page, kCGPDFMediaBox)
		if CGRectIsEmpty(mediaBox):
			mediaBox = None
		CGContextBeginPage(writeContext, mediaBox)
		CGContextDrawPDFPage(writeContext, page)
		if verbose:
			print "Copied page %d from %s" % (pageNum, doc)

def shufflePages(writeContext, docs, maxPages):
	for pageNum in xrange(1, maxPages + 1):
		for doc in docs:
			writePageFromDoc(writeContext, doc, pageNum)
def append(writeContext, docs, maxPages):

	for doc in docs:
		for pageNum in xrange(1, maxPages + 1) :
			writePageFromDoc(writeContext, doc, pageNum)

def main(argv):

	global verbose

	# The PDF context we will draw into to create a new PDF
	writeContext = None

	# If True then generate more verbose information
	source = None
	shuffle = False
	# Parse the command line options
		options, args = getopt.getopt(argv, "o:sv", ["output=", "shuffle", "verbose"])

	except getopt.GetoptError:

	for option, arg in options:

		if option in ("-o", "--output") :
			if verbose:
				print "Setting %s as the destination." % (arg)
			writeContext = CGPDFContextCreateWithURL(CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, arg, len(arg), False), None, None)

		elif option in ("-s", "--shuffle") :
			if verbose :
				print "Shuffle pages to the output file."
			shuffle = True

		elif option in ("-v", "--verbose") :
			print "Verbose mode enabled."
			verbose = True

		else :
			print "Unknown argument: %s" % (option)
	if writeContext:
		# create PDFDocuments for all of the files.
		docs = map(createPDFDocumentWithPath, args)
		# find the maximum number of pages.
		maxPages = 0
		for doc in docs:
			if CGPDFDocumentGetNumberOfPages(doc) > maxPages:
				maxPages = CGPDFDocumentGetNumberOfPages(doc)
		if shuffle:
			shufflePages(writeContext, docs, maxPages)
			append(writeContext, docs, maxPages)
		del writeContext
def usage():
	print "Usage: join [--output <file>] [--shuffle] [--verbose]"

if __name__ == "__main__":

Visual Studio 2013 Command Prompt Here for Windows Explorer Context Menu

To get a Visual Studio 2013 Command Prompt Here as a Context Menu (i.e., Right Click Menu) item in Windows Explorer, save this snippet to a .reg file and double click to import it into your registry:

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\Command Line VS2013]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\Command Line VS2013\command]
@="cmd.exe /k echo on & pushd \"%1\" & \"C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\Common7\\Tools\\VsDevCmd.bat\"" 

If you prefer to manually create the key path in RegEdit and add the command as the default value, drop the outermost quotes and the backslash escaping:

cmd.exe /k echo on & pushd "%1" & "C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\VsDevCmd.bat"

Mono MVC System.UnauthorizedAccessException Access to the path “/Library/Frameworks/Mono.framework/Versions/…/etc/mono/registry” is denied

Is an error you are likely to see if you run a Visual Studio MVC template in Mono. There are two options for fixing it.

  • Do this from the command line:
    sudo mkdir /Library/Frameworks/Mono.framework/Versions/3.2.5/etc/mono/registry
    sudo chmod g+rwx /Library/Frameworks/Mono.framework/Versions/3.2.5/etc/mono/registry

    (replacing 3.2.5 with your mono version, which you get at the command line with mono --version)

  • Or delete the reference to Microsoft.Web.Infrastructure.dll from the project and delete it from the bin directory too.

The important difference is that deleting Microsoft.Web.Infrastructure.dll will stop your project working on .Net, so the registry access is simpler for cross-platformers. Another option for cross-platform project files would be something like this in the .csproj file:

<Target Name="AfterBuild">
    <Delete Files="$(WebProjectOutputDir)\bin\Microsoft.Web.Infrastructure.dll" Condition=" '$(OS)' != 'Windows_NT'" />

I prefer the ‘grant access to the registry approach’ myself but it does mean having to re-run the 2 line script for every new version of mono.