2

I have a WCF project in Visual Studio that I need to deploy to a client's test server. I was on the brink of declaring "Mission Accomplished" when I realized that I have no idea how to take my project from Visual Studio 2010 to something that I can deploy on the client's server.

My gist of this problem is that we use a makefile to do building and packaging when deploying to the client. This means that I need a command-line executable to do whatever it is that I need to do to deploy my WCF service. I did discover right-clicking the project and selecting "Build Deployment Package", but since I need to execute via command-line, I don't think this is going to help much.

The bonus second part of this problem is that, once I get the packaged file the client's server, I'm not sure what to do with it. Now, if I knew what to expect from the packaged deployment file, I might have a better idea, but until then, it's all just speculation.

REW
  • 752
  • 2
  • 9
  • 27
  • Oh, sure, Google for a while and find nothing. Post on Stack Overflow. Go back to Google. Find a potentially perfect solution, AT STACK OVERFLOW, on the first try. Yeesh: http://stackoverflow.com/questions/3117083/build-web-deployment-package-from-command-line – REW Feb 17 '12 at 00:24
  • For future record: **Must use .NET 4.0+** msbuild {csproj_file} /t:package /target:build Now I just need to figure out the deploy-to-client-server-from-zip-file part... – REW Feb 17 '12 at 01:16

1 Answers1

9

OK, here is what I came up with.

Packaging

First, the packaging. Use msbuild. Something like this (apparently you need to use a v4 or better version of .NET for it to succeed):
C:/Windows/Microsoft.NET/Framework/v4.0.30319/msbuild.exe {project_file} /t:package /target:Build /p:PlatformTarget=x86;
Fairly easy, right?

Deployment

Now, the bonus part of the question, the deployment. This consists of the easy part and the hard part. The easy part was getting the .zip file created with msbuild.exe added into IIS. I found 2 possibilities.

Commandline

The first is the command-line, which gave me issues (something about being unable to cast 'Microsoft.Web.Deployment.DeploymentProviderOptions' to type 'Microsoft.Web.Deployment.DeploymentProviderOptions' --- I KNOW, RIGHT?). Anyway, this is the command-line I used. It may help someone, or it may not. Again, I had issues with it.
c:\inetpub\wwwroot>"c:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" -verb:sync -presync:runCommand="md c:\inetpub\wwwroot\{MyWCFCodeDest} & c:\windows\system32\inetsrv\appcmd add site /name:{MyWCFCodeDest} /id:22 bindings:http/*:54095: /physicalPath:c:\inetpub\wwwroot\{MyWCFCodeDest}" -source:package={ZipFileFromMSBuild.exe} -dest:auto -setParam:"IIS Web Application Name"="{MyIISName}"

UI

OK, so I decided I would be happy with using the second way. It's by far the easiest if you don't care about automation. Open up IIS Manager, right-click the computer OR the website (depending on whether you want it as its own website or an application in an existing website), Deploy, Import, and follow the wizard to the end.

Errors in Deployment

And now where I spent most of my time. I hit my newly deployed .svc file and get an error. This error involves the certificate I was using. Now, maybe not all deployments will have to worry about this, but mine did. The error was lengthy, something about "keyset does not exist" and "cannot be activated due to an exception during compilation" and "may not have a private key that is capable of key exchange or the process may not have access rights for the private key". I tried a bunch of stuff, including using mmc to re-import certs and makecert to recreate both my CA and my personal cert. None of that was the problem for me (ymmv). Finally, I focused on user rights. I found that if I gave the Everyone user permission to the private key for the cert (the cert needs to have a private key), everything worked. Obviously not a solution I want for a client, so I hunted down the correct user to give rights to. Surprisingly, this took a while. Various websites had me adding Network Service, ASPNET, current user, the user specified in machine.config (which is in the .NET directory somewhere), IIS_{MachineName}... none of these worked. The one I had to add was IIS_IUSRS.

So, a handful of caviats that may help your sanity when you scream at your monitor that this isn't working for you, despite following all the directions. Because apparently IIS changes far too much over time and this stuff does matter:
Windows 7 Ultimate sp1
IIS 7.5.7600.16385

Useful Related Stuff

Also, some commandline tools you may be interested in:
-winhttpcertcfg.exe -l -c LOCAL_MACHINE\My -s "{cert_name}" -- lists the users authorized to access the cert's private key (you can also do it the old fashioned way through file properties); I tried downloading winhttpcertcfg.exe, but it was part of a Windows 2003 package that gives warnings about not being compatible (not sure if it came from my attempt to install that file or if it now comes with something I already had installed)
-winhttpcertcfg.exe -g -c LOCALHOST\My -s "{cert_name}" -a IIS_IUSRS -- adds IIS_IUSRS to the permissions for the cert's private key
-findprivatekey.exe My LocalMachine -n "{cert_name}" -- Finds the private key file for the specified cert; for some reason, this is a tool that you have to build in Dev Studio on your own (found in some WCF examples downloaded from Microsoft)
-cacls.exe {private_key_file_for_cert} /E /G "IIS_IUSRS" -- another way to add a user to the private key's permissions
-mmc -- launchs a manager for installed certificate
-makecert -n "CN={CertificateAuthorityName}" -r -sv {CertificateAuthorityName}.pvk {CertificateAuthorityName}.cer -- create a certificate authority cert
-makecert -sk {SignedCertName} -iv {CertificateAuthorityName}.pvk -n "CN={SignedCertName}" -ic {CertificateAuthorityName}.cer {SignedCertName}.cer -sr localmachine -ss My -- create a certificate signed by a certificate authority

One last thing: if you want to import your certs using mmc, you need to launch mmc, File->Add/Remove Snapin. Add the Certificates snapin. Import the certificate authority to the Trusted Root Certification Authorities and the certificate signed by the certificate authority to Personal.

Hopefully you have enjoyed your ride here. Please wait for the browser to come to a complete stop before exiting, and please remember to take any personal items with you.

Additional Discoveries

When it came time to deploy everything to a test server (rather than my development machine), I didn't expect all the hassles that I encountered. I'm documenting these here, again, in an effort to help some other poor, lost soul (or myself at a later date).
-This one should have bee obvious: FindPrivateKey.exe wasn't on the server. I had to jump through some hoops to get it there. ymmv.
-Only the client 4.0 version of .NET had been installed on the server. By the time I discovered this AND realized it was a problem, a few hours had passed. Discovery of the installed .NET versions came courtesy of netfx_setupverifier, which I got from one of Microsoft's websites. The client version doesn't include all the WCF stuff.
-IIS needed some additional settings (files found in the .NET Framework version directory, run from the commandline):
aspnet_regiis.exe -i -enable
ServiceModelReg.exe -r
-cacls.exe informed me that it was deprecated and that I should use icacls.exe. The commandline for icacls is something like:
icacls.exe {private_key_file_for_cert} /GRANT "IIS_IUSRS":R (note, didn't exactly work for me, but you can always just go to the {private_key_file_for_cert} file, probably in ProgramData\Microsoft\Crypto\RSA\MachineKeys, and give permissions via Explorer - right-click - properties)
-You may need to add a handler mapping for the WCF. I highly recommend having it running under an Application Pool that is .NET v4.0.

Community
  • 1
  • 1
REW
  • 752
  • 2
  • 9
  • 27