STSDEV – few gotchas, tips and tricks

For those of you who have given up using any versions of Visual Studio extension for Windows SharePoint Services 3.0
(a.k.a. VSeWSS 1.0, 1.1, 1.2)

                                 GOOD ON YA!!!

– You’ve just saved yourself loads of pain.

(I think this itself deserves a good post, my colleagues are currently building the next version of VSeWSS at the time of this post, may God be with them!)

For those of you who have taken up WSPBuilder or STSDEV,

                              GOOD ON YA!!! (X2)

– SharePoint development have just become less painful πŸ™‚

Here are a few tips and tricks I learnt along the way and from my experienced and knowledgeable colleagues from Intergen.

#1. Why STSDEV is ignoring changes made in targets file?

Close your solution in Visual Studio and reopen it, and yes we’ll have to repeat this each time we make a change to the targets file. I know it’s a pain in the bum.

What is up with this close/reopen business and how to fix it? When you find out, please do let me know πŸ™‚

#2. Why is my solution deployed globally?


After a project is created with STSDEV, the default solution deployment command under DebugDeploy Target in targets file is;

<Exec Command="$(STSADM) -o deploysolution -name $(PackageName) -immediate" />

To change your deployment to a site collection;

<Exec Command="$(STSADM) -o deploysolution -name $(PackageName) -immediate -allowgacdeployment -url $(TargetUrl)  -force" />

where $(TargetUrl) is defined as a property between <PropertyGroup> tags at the beginning of the targets file;

  <!-- Other properties omitted -->

#3. “This solution contains no resources scoped for a Web application and cannot be deployed to a particular Web application.”

This is a tricky one. The error message is very generic and can mean many things… To resolve it, you need to flick between the targets file and the SolutionConfig.xml file, make changes and trying deploying it.


Remember, each time you make a change to the targets file, close your solution and reopen it for it to take effect in the build.

If you’ve written any custom code in the project, like event receivers, and you need deploy this assembly to GAC. You’ll have to make each and very single following points are addressed.

(Depend on the option combinations you chose when you created the solution with STSDEV, none / some / all of these should have been done for you.)

a. The assembly is signed with a key file. (Project -> properties)


b. In SolutionConfig.xml, allow GAC deployment and safe control.


c. In SolutionConfig.xml, specify the safe control.

    <Assembly Location="Play.dll" DeploymentTarget="GlobalAssemblyCache">
            <SafeControl Assembly="Play, Version=, Culture=neutral, PublicKeyToken=abbe9e18e07720bf" Namespace="Play" TypeName="*" Safe="True" />

You can get the assembly name by opening up the dll in reflector after signing it with a key and compiled the project.


d. In targets file, under BuildDeploy target, solution deploy command allows GAC deployment.

<Exec Command="$(STSADM) -o deploysolution -name $(PackageName) -immediate -allowgacdeployment -url $(TargetUrl) -force" />

e. If solution is to deploy to a site collection, specify the URL in the deploy command as well, so it knows which web config to place the safe control in. (See the above code snippet.)

f. If you are intending to deploy to all Site Collections in this Web Application, make sure you specify so by having a -allcontenturl switch in the command.

<Exec Command="$(STSADM) -o deploysolution -name $(PackageName) -immediate -allowgacdeployment -allcontenturls -force" />

Failing all above, keep ‘in πŸ˜‰

#4. “This solution contains resources scoped for a Web application and must be retracted from one or more Web applications.”

If you have successfully deployed your wsp solution to a specific site collection following the steps in #2 and 3, then you might come across this message when you try to build the project in “DebugRetract” or “DebugDelete” build targets.

If you take a look at the output windows it fails at line:

"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\bin\stsadm.exe" -o retractsolution -name Play.wsp -immediate

This happens because we haven’t specified the site collection URL that we had deployed the wsp solution to. So, if we change the line to.

"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\bin\stsadm.exe" -o retractsolution -name Play.wsp -immediate -url $(TargetUrl)

Remember to close and reopen your solution for this change to take effect, then build it. You should see the problem go away.

#5. Can’t Debug I hear you say?

There are a couple of things you need to do here,

One is, allows a pdb file to be generated each time you compile the project. in Visual Studio 2008, right click on the project -> Properties -> Build -> Advanced… -> Debug Info -> full


So repeat this for all the concerned Configuration target. I recommend do it for “DebugRefreshAssemblyInGac, DebugBuild, DebugDeploy, and DebugRedeploy”. Not sure about “DebugUpgrade” never used it before.


Two is adding the pdb files to the correct GAC location. First you’ll need to find out where in GAC you’ll want to copy the pdb files into.

Start -> Run and type in “C:\windows\assembly\GAC_MSIL” as it can’t be opened through a file explorer.


Follow your nose and you should find the directory where the bit was deployed to, copy out the path from Address bar, this is the folder you want to deploy your pdb file to.


So in your target file, you need add two lines to your “DebugDeploy” target and “DebugRefreshAssemblyInGac” target like to following;

<Target Name="DebugDeploy" DependsOnTargets="DebugInstall">
  <Message Text="Deploying Solution..." Importance="high" />
  <Exec Command="$(STSADM) -o deploysolution -name $(PackageName) -immediate -allowgacdeployment -url $(TargetUrl) -force" />
  <Exec Command="$(STSADM) -o execadmsvcjobs" />
  <Copy SourceFiles="$(TargetDir)$(TargetName).pdb" DestinationFolder="C:\windows\assembly\GAC_MSIL\Play.0.0.0__abbe9e18e07720bf" SkipUnchangedFiles="" />
  <Message Text="$(TargetDir)$(TargetName).pdb copied to GAC for debugging." Importance="high" />
  <Exec Command="$(POSTBUILD)" />
  <Message Text="" Importance="high" />
<Target Name="DebugRefreshAssemblyInGac" >
  <Message Text="(Re)installing assembly in GAC and recycling app pool" Importance="high" />
  <Exec Command="$(GACUTIL) -if $(TargetPath)" />
  <Copy SourceFiles="$(TargetDir)$(TargetName).pdb" DestinationFolder="C:\windows\assembly\GAC_MSIL\Play.0.0.0__abbe9e18e07720bf" SkipUnchangedFiles="" />
  <Message Text="$(TargetDir)$(TargetName).pdb copied to GAC for debugging." Importance="high" />
  <Exec Command='$(ISSAPP_SCRIPT) /a "SharePoint - 80" /r' />
  <Message Text="" Importance="high" />

Remember to close and reopen your solution each time you change the target file.


Make sure the timestamp for these two files are identical, or your code is likely to be out of sync with the pdb.

#6. Have a post build script depending on your build targets?

In your target file, add a new property inside <PropertyGroup> tag.


And use this as a command in any targets in your target file, like so;

<Exec Command="$(POSTBUILD)" />

– I hear you ask, why wouldn’t you just use Build Event from project properties?
Because STSDEV introduces a handful of build targets (10 of them) and sometimes it’s useful to have control over which targets you want to have a post build script while not others. Also, we can run different post build scripts for different build targets leveraging this approach, just define different scripts as properties inside <PropertyGroup> tag then just invoke the appropriate ones from different build targets.

– Note, in theory we should be able to put anything we have in a post build script in the target file. After all, the targets file is just a script file in an XML format. But to me, I want to be able to share my build script around with other developers or from project to project. By extracting some of the common tasks out to a build script I’m protecting myself against having to relying on STSDEV. After all, STSDEV is just one of the great tools out there. That’s just my opinion, your mileage may vary.

#7. Have multiple projects under one solution?

When you first create a project with STSDEV and call it Play, It will lay out its folder structure like so;


When you create more than one projects and shift them to a sub directory to where the solution file resides, like so;


Then you compile your project, you’ll see this error;


and this in your Output Window;

STSDEV - Simple Tools for SharePoint Developers
Refreshing Solution Package Files
Current Solution Name:
Current Solution Directory:
Refreshing deployment files...
Unhandled Exception: System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Dev\Play\Play\DeploymentFiles\SolutionConfig.xml'.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
   at System.IO.StreamWriter.CreateFile(String path, Boolean append)
   at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding, Int32 bufferSize)
   at System.IO.StreamWriter..ctor(String path)
   at stsdev.SolutionConfigBuilder.Create(String FilePath, Boolean AssemblyDeployment, Boolean SafeControlSettings, AssemblyDeploymentTarget DeploymentTarget, PermissionSet CasPermissions)
   at stsdev.SolutionConfigBuilder.Create(String FilePath, Boolean AssemblyDeployment, Boolean SafeControlSettings, AssemblyDeploymentTarget DeploymentTarget)
   at stsdev.SolutionConfigBuilder.Create(String FilePath, Boolean AssemblyDeployment, Boolean SafeControlSettings)
   at stsdev.SolutionConfigBuilder.Create(String FilePath, Boolean AssemblyDeployment)
   at stsdev.SolutionBuilder.LoadSolutionConfigFile()
   at stsdev.SolutionBuilder.RefreshDeploymentFiles()
   at stsdev.SolutionBuilder.RefreshDeploymentFiles(String TargetSolutionName, String TargetSolutionDirectory)
   at stsdev.Program.Main(String[] args)
MSBUILD : warning MSB3073: The command ""C:\Program Files\STSDev v1.3\stsdev.exe" /refresh "Play" "C:\Dev\Play\Play\"" exited with code -532459699.

This happens because, STSDEV uses solution directory to reference its deployment files and these files are per-project based. When we moved the project related files and folders else where, we’ll need to reference them by project directory.

All you need to do is to change the follow line in your <PropertyGroup> in your targets file.

<REFRESH>$(STSDEV) /refresh "$(TargetName)" "$(SolutionDir)"</REFRESH>


<REFRESH>$(STSDEV) /refresh "$(TargetName)" "$(ProjectDir)"</REFRESH>

Close and reopen the solution then try building the project again!

#8: “error : Cannot create INF file: setup.inf”

This happens because STSDEV will try to create/write to files called setup.inf and setup.rpt. The chances are you have these two files under source control so they are locked.

setup.inf, setup.rpt in project directory, along with manifest.xml and SolutionPackage.ddf in DeploymentFiles folder will get regenerated and written to each time you build your project. So don’t have them under source control.


#9: “Where are my web stuff?”

Enlightened by a colleague of mine – Matt Smith – a SharePoint Evangelist. When you create a project with STSDEV, the project is a C# library type.


When we add New Items, there isn’t a great of items are available to us. Especially when we develop SharePoint solutions, ASP.NET artifacts like ascx User Controls, aspx pages etc…


For us to be able to add web stuff to the project, Visual Studio needs to see the project we are adding stuff to – is a Web Application Project. To achieve this, add the following line of xml to the first <PropertyGroup> node of your .csproj file.



  <Configuration Condition=" '$(Configuration)' == '' ">DebugBuild</Configuration>
  <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>


<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="">
    <Configuration Condition=" '$(Configuration)' == '' ">DebugBuild</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>

Reload the project and we see the project icon has become it of a Web Application Project;


and we can add all the web stuff to our project now;


There you go, the joys and pains for working with STSDEV.

Technorati Tags: ,,,

10 responses to this post.

  1. Posted by Dave on May 13, 2009 at 8:00 am

    Nice write-up. One problem I’ve been having with STSDEV is that it reformats the XML files removing the indents. Any way to correct that behavior??


    • Hiya, oh really? I don’t remember anything like that… Which XML files are affected? I’ve switched to WspBuilder these days.


  2. Posted by mike on October 16, 2009 at 4:37 am

    thank you for this – very helpful indeed!


  3. Posted by Usman Mughal on November 4, 2009 at 1:16 am

    #4. β€œThis solution contains resources scoped for a Web application and must be retracted from one or more Web applications.”
    I am facing this error and i following all these steps then too i am facing this.
    I am using the same feature scope then too,
    I can deploy it globaly


  4. Posted by peace4men on February 25, 2010 at 8:22 am

    #7, Can anyone please show me how to create mutiple project under one solution ? should i use the same SNK file to sign it, I’m new (Very) to MOSS


  5. Helpful instructions–made scoping the solution to a specific webapp a snap with STSDEV. I was surprised at how easy it was to drop an STSDEV-generated solution into my existing “top level” solution directory (like it was just a project), add it to the top level solution as an existing project, make the minor change to the STSDEV command in the PropertyGroup of the target file as you indicated, and it just works. It’s surprisingly flexible in how you can mix and match project types within a solution. BTW, you can simply do a right click on the project in the solution explorer and do Unload/Reload on project when making changes to the targets–a bit less churn than closing the solution (you have to right-click directly on the project name to see that menu choice).


  6. Posted by Samson Louis on March 19, 2013 at 1:20 am

    Helpful !!!


  7. Everything is very open with a very clear explanation of the challenges.
    It was truly informative. Your website is useful. Thank you for


  8. Nice it helped me very much


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: