Request a topic or
contact an Arke consultant
404-812-3123
Visual Studio 2008

Arke Systems Blog

Useful technical and business information straight from Arke.

About the author

Author Name is someone.
E-mail me Send mail

Recent comments

Archive

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2024

Deploying IIS dlls, part 2

Following up on my previous post about copying some CRM Plugin DLLs after a build ( http://arkesystems.com/blog/post/2009/02/Recycling-IIS-app-pools.aspx ):

It turns out that the error checking in post-build events isn't reliable (it only checks errorlevel at the end of the script), and apppools don't stop instantly even when told to stop instead of recycle. 

So if my xcopy encounters a "sharing violation" (errorlevel 4) then the post-build event isn't smart enough to notice by default.

Luckily, it's just a bat file, so we can add some checking ourselves.  This is getting more complicated than I would like, but at least I build reliably now.

"sleep" isn't necessary, but it's a useful command to have around.  It comes with Windows 2003 Server Resource Kit: http://www.microsoft.com/downloads/details.aspx?FamilyID=9d467a69-57ff-4ae7-96ee-b18c4790cffd&DisplayLang=en ; restart visual studio after installing the kit.

A note on checking return codes in batch files: Equality checks are actually 'greater than or equal', so you will see people checking if errorlevel eq 1 often.  However, this only catches >= 1 error levels, and the occassional program that returns negative error codes will slip past.  Accordingly, always check "neq 0" instead of "eq 1".  Also, using "SETLOCAL ENABLEDELAYEDEXPANSION" and !ERORRLEVEL! is not strictly necessary in this script, but it's good practice to just always use delayed expansion when checking return values in batch files so that you don't screw up one day when you write an error check inside a loop.

So, hopefully my final iteration of a post-build script that needs to update some IIS dlls:

SETLOCAL ENABLEDELAYEDEXPANSION 
net pause KeepAliveService 
cscript /nologo "$(ProjectDir)\iis_stop_app_pool.vbs" "CRMAppPool" 
if !ERRORLEVEL! NEQ 0 GOTO FAIL 
set CRMDIR=C:\Program Files\Microsoft Dynamics CRM 
set loop=0 
:TRYCOPY 
set /a loop=%loop%+1 
xcopy "$(TargetPath)" "%CRMDIR%\Server\bin\assembly" /i /d /y 
if !ERRORLEVEL! NEQ 0 GOTO COPYFAIL 
xcopy "$(TargetDir)$(TargetName).pdb" "%CRMDIR%\Server\bin\assembly" /i /d /y 
if !ERRORLEVEL! NEQ 0 GOTO COPYFAIL 
cscript /nologo "$(ProjectDir)\iis_start_app_pool.vbs" "CRMAppPool" 
if !ERRORLEVEL! NEQ 0 GOTO FAIL 
net continue KeepAliveService 
GOTO OK 
:COPYFAIL 
if %LOOP% LEQ 10 GOTO TRYCOPYSLEEP 
goto FAIL 
:TRYCOPYSLEEP 
sleep 1 
goto TRYCOPY 
:FAIL 
echo "Failed with errorlevel !ERRORLEVEL!" 
exit 1 
:OK 
echo "OK" 

Edit 3/30/2010: For a 64 bit system, you can get silently redirected to SysWOW64 when a 32 bit process is trying to run something in system32.This causes iisapp.vbs to fail when run as a post build event. In Visual Studio, it shows as an exited with code 1 error. If you manually go to the [windows]\SysWOW64 folder and run iisapp.vbs, you can get an error like:Could not create an instance of the CmdLib object.Please register the Microsoft.CmdLib component.

One solution is to copy the necessary files to the SysWOW64 folder and reregister the dlls:
cd c:\windows\SysWOW64
copy ..\system32\iisapp.vbs .
copy ..\system32\IIsScHlp.wsc .
copy ..\system32\cmdlib.wsc .
regsvr32 cmdlib.wsc
regsvr32 IIsScHlp.wsc

 

Posted by David Eison on Friday, February 27, 2009 5:23 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Recycling IIS app pools

When developing for Sharepoint or working on CRM DLLs, you need to recycle the IIS app pool a fair bit.

 

Maybe I’m late to the party and everyone already knows this, but just in case, this utility for resetting iis app pools rocks: http://www.harbar.net/articles/APM.aspx 

 

You can also recycle an app pool in a script with

cscript c:\windows\system32\iisapp.vbs /a "CRMAppPool" /r 

But, for my CRM DLL, I need a post-build event that stops the app pool before I copy a DLL.  I tried simply using iisapp.vbs to recycle, but this failed sometimes because the DLL can still be in use after the restart (I'm not sure if it restarts too fast, or if it due to overlapped recycling).

Based on posts from http://mscrm4ever.blogspot.com/2008/12/expediting-plug-in-development-using-vs.html and http://www.experts-exchange.com/Programming/Languages/Visual_Basic/Q_21362452.html , I ended up with the below.

My post-build event:

cscript /nologo "$(ProjectDir)\iis_stop_app_pool.vbs" "CRMAppPool"
set CRMDIR=C:\Program Files\Microsoft Dynamics CRM
xcopy "$(TargetPath)" "%CRMDIR%\Server\bin\assembly" /i /d /y
xcopy "$(TargetDir)$(TargetName).pdb" "%CRMDIR%\Server\bin\assembly" /i /d /y
cscript /nologo "$(ProjectDir)\iis_start_app_pool.vbs" "CRMAppPool"

 

The stop and start scripts: 

iis_stop_app_pool.vbs:

Option Explicit
Dim apool, strComputer, objWMIService, colItems, objItem
apool = WScript.Arguments.Item(0)
strComputer = "."
Set objWMIService = GetObject _
    ("winmgmts:{authenticationLevel=pktPrivacy}\\" _
        & strComputer & "\root\microsoftiisv2") 
Set colItems = objWMIService.ExecQuery _
    ("Select * From IIsApplicationPool Where Name = " & _
        "'W3SVC/AppPools/" & apool & "'")
 
For Each objItem in colItems
  Wscript.Echo "Stopping " & objItem.Name    
  objItem.Stop
Next

iis_start_app_pool.vbs:

Option Explicit
Dim apool, strComputer, objWMIService, colItems, objItem
apool = WScript.Arguments.Item(0)
strComputer = "."
Set objWMIService = GetObject _
    ("winmgmts:{authenticationLevel=pktPrivacy}\\" _
        & strComputer & "\root\microsoftiisv2") 
Set colItems = objWMIService.ExecQuery _
    ("Select * From IIsApplicationPool Where Name = " & _
        "'W3SVC/AppPools/" & apool & "'")
 
For Each objItem in colItems
    Wscript.Echo "Starting " & objItem.Name
    objItem.Start
Next

Posted by David Eison on Friday, February 27, 2009 1:09 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Web Application Foundation - Part 1 - Preparing a Continuous Integration Server

This is the first article in a series that I intend to be a step by step walkthrough of preparing for a new web project. 

  1. Part 1 is going to cover creating a continuous integration server using CruiseControl.NET, and assumes that you already have a server setup with Windows Server and a Visual Source Safe Server.
  2. Part 2 is going to cover setting up a client computer for running Visual Studio 2008 and integrating with CCNet and VSS
  3. Part 3 is going to cover creating a sample web application with a deployment project and having this project run in our continuous integration environment
  4. Part 4 will be adding the ASP.NET Membership Provider to our Web Application
  5. Part 5 is going to cover using MVP Architecture to be able to unit test our web application
  6. Part 6 will be using WiX to create a setup file
  7. Finally part 7 will go over various tools and applications that really go hand-in-hand with CI.  Tools will include FxCop, Simian, NCover, NDepend, and others.

We're going to start with a base install of Windows Server 2003 (2008 will work just fine as well), all all the latest updates from Microsoft. 

  • Create a user "CruiseControl" with local administrative rights
  • Make sure that IIS is installed and running.
  • Create a shared directory called "Builds", and another directory called "vssroot"
  • Install the .NET Frameworks v2.0, v3.0, and v3.5
  • Install WiX v3.0.3621 or greater
  • Install CruiseControl.NET v1.3
  • Optionally install CCNetConfig a tool to edit CruiseControl.NET configuration files with a GUI
  • Install the Visual Source Safe 2005 client utilities
  • Install Nant 0.85
  • Run services.msc
  • Open the properties of the "CruiseControl.NET Server" service
  • Set the Startup type to Automatic
  • Under the Log On tab, select Log on as the CruiseControl user you created

Configuring the VSS Database: (more on this later)

  • Create a new VSS Database
  • Add a read/write user by the name cruisecontrol 
  • The project should be layed out in the following manner:
    • $/
    •     trunk
    •         buildScript
    •             cruise.build
    •         source
    •             project.sln

Configuring the project in CruiseControl.NET

  • Open the CruiseControl.NET Config file located by default here:  C:\Program Files\CruiseControl.NET\server\ccnet.config
  • Insert the following project xml into the config file changing the fields in brackets to meet your needs: 

 

<project name="[MyProjectName]">
<sourcecontrol type="vss">
<project>$/trunk</project>
<username>cruisecontrol</username>
<password>[CruiseControlUserPassword]</password>
<executable>[path to visual source safe]\SS.EXE</executable>
<ssdir>[ Path to VSS database .ini file ]\</ssdir>
<autoGetSource>True</autoGetSource>
<applyLabel>False</applyLabel>
<workingDirectory>c:\vssroot\[MyProjectName]\</workingDirectory>
<cleanCopy>True</cleanCopy>
      </sourcecontrol>
<triggers>
            <intervalTrigger seconds="60" />
</triggers>
      <tasks>
            <nant>
                  <executable>C:\Program Files\nant-0.85\bin\NAnt.exe</executable>
                  <baseDirectory>C:\vssroot\[MyProjectName]</baseDirectory>               
                  <buildFile>C:\vssroot\[MyProjectName]\buildScript\cruise.build</buildFile>
                  <nologo>True</nologo>
                  <buildTimeoutSeconds>30</buildTimeoutSeconds>
                  <targetList>
<target>run</target>
                  </targetList>
            </nant>
</tasks>
</project>

 

  • All of the other scripts will be included in VSS and pulled automatically during a build.

 

[Added]

 

I had a couple questions about the proper way to install NAnt in our configuration.  Basically there are three items you need in order to have a successful installation.

  1. Unzip the NAnt-0.85 folder into your program files directory under c:\Program File\NAnt-0.85
  2. Unzip NAnt-Contrib into the NAnt installation directory.  The files will need to be in the following Locations:

    \
        bin\
            lib\
                net\
                    CollectionGen.dll
                    Interop.MsmMergeTypeLib.dll
                    Interop.StarTeam.dll
                    Interop.WindowsInstaller.dll
                    SourceSafe.Interop.dll

            tasks\
                net\
                    MSITaskErrors.mst
                    MSITaskTemplate.msi
                    MSMTaskErrors.mst
                    MSMTaskTemplate.msm
                    NAnt.Contrib.Tasks.dll
                    NAnt.Contrib.Tasks.pdb (not available for releases)
                    NAnt.Contrib.Tasks.xml

            SLiNgshoT.Core.dll
            SLiNgshoT.exe

    Note: you might have to manually create the "tasks\net" and "lib\net" directories. (taken from NAnt Contrib Readme file)

    3. Finally you'll need to modify the NAnt config file in order for it to handle working with VS2008, Palermo offers an excellent article on this:

    Jeffrey Palermo's Explaination of the NAnt Upgrade to 3.5

     


kick it on DotNetKicks.com

Posted by Trenton Adams on Friday, January 4, 2008 4:23 PM
Permalink | Comments (0) | Post RSSRSS comment feed