Recreate or Create Default Reports TFS

Another product that I’ve been working with lately is TFS.  In the environment that I’ve worked with Reporting and SQL Analysis Services were added later after the environment was setup. This was fine for the actual setup but I noticed that folders and reports were not populated for our different project folders. I found that it would take a lot of time create the folders and update the default reports.  I also had to determine the type for each project.  An easier method for this is to use the commands blow.

1. Create a blank XML file and copy the information below into it. It is easier to keep the path and name short as you’ll need to reference it. You’ll want to use the chart below the screenshot to explain all the field placeholders.

<?xml version="1.0" encoding="utf-8"?> 
<Project xmlns="ProjectCreationSettingsFileSchema.xsd"> 
<TFSName>CollectionURI</TFSName> 
<LogFolder>LogFolderName</LogFolder> 
<ProjectName>TeamProjectName</ProjectName> 
<AddFeaturesToExistingProject>true</AddFeaturesToExistingProject> 
<ProjectReportsEnabled>true</ProjectReportsEnabled> 
<ProjectReportsForceUpload>false</ProjectReportsForceUpload> 
<ProjectSiteEnabled>false</ProjectSiteEnabled> 
<ProcessTemplateName>ProcessTemplate</ProcessTemplateName>
</Project>

XML Tag

Parameter

Description

TFSName

CollectionURI

The uniform resource identifier (URI) of the team project collection. The format for the URI is as follows: http://ServerName:Port/VirtualDirectoryName/CollectionName

If no virtual directory is used, the format for the URI is as follows:

http://ServerName:Port/CollectionName

LogFolder

LogFolderName

The location of the folder where you want the log file to be written. The log file that will be created is named TEAMPROJECT.log, and it will contain the events from running the batch file command. For example, you can specify “C:\” for the log folder name. If you leave the value for the folder location blank, the log file will be written to %temp% and will be named following the naming conventions for logs that the New Project Creation Wizard generates. You can locate the log file by navigating to the following directory: $:\Documents and Settings\user name\Local Settings\Temp\VSTS_TeamProjectCreation_yyyy_mm_dd_hh_mm_ss.log.

ProjectName

TeamProjectName

The name of the upgraded team project to be provisioned. You must specify the name of a team project that is defined in the project collection that you specified in the CollectionURI parameter.

AddFeaturesToExistingProject

true | false

Specify true to indicate that you are adding features to an existing team project and false to indicate that you are creating a team project.

ProjectReportsEnabled

true | false

Specify true to provision a report site and false to exclude provisioning a report site.

ProjectReportsForceUpload

true | false

Specify true to cause reports in the process template to be uploaded to the report site and falseto exclude the upload of reports.

ProjectSiteEnabled

true | false

Specify true to enable the team project portal site and false to maintain the site as disabled for the team project.

ProjectSiteWebApplication

SharePointWebApp

Specifies the friendly name (not the URL) to the SharePoint Web application (for example, Team Project Portal). By default, the URL and the friendly name are the same.

ProjectSitePath

PortalSitePath

The relative site path where you want the project portal site to be created (for example, sites/DefaultCollection/MyProject).

NoteNote
The site path that you specify must correspond to a Web site application that has been added to the team project collection where the team project is defined. For more information, see Add a SharePoint Web Application to Your Deployment.

The relative site path corresponds to the home page of the project portal.

ProjectSiteTitle

ProjectSiteTitle

(Optional) If you want a project portal name that differs from the team project name, you can type a name that is easily identified by your team members.

ProjectSiteDescription

SiteDescription

(Optional) The site description for the team project portal (for example, The “My Project” Portal Site).

ProcessTemplateName

ProcessTemplate

The name of the process template to use to create the project portal. To specify a version 5.0 MSF process template, enter one of the following values:

  • MSF for Agile Software Development v5.0

  • MSF for CMMI Process Improvement v5.0

NoteNote
If you want to use another process template, you must first make sure that it is uploaded to Team Foundation Server. For more information, see Upload a Process Template.

2. Open Visual Studio Go to View then click Team Explorer, then go to View again, select Other Windows, and then click Command Window.

3.  Type File.BatchNewTeamProject c:\”link to your file”.

4.  You should see the folder structure there is successful.  If not a log will be placed where you specified it in the XML file.

I hope this saves you some more time than it did for me!!!!

<?xml version="1.0" encoding="utf-8"?> 
<Project xmlns="ProjectCreationSettingsFileSchema.xsd"> 
<TFSName>CollectionURI</TFSName> 
<LogFolder>LogFolderName</LogFolder> 
<ProjectName>TeamProjectName</ProjectName> 
<AddFeaturesToExistingProject>true</AddFeaturesToExistingProject> 
<ProjectReportsEnabled>true</ProjectReportsEnabled> 
<ProjectReportsForceUpload>false</ProjectReportsForceUpload> 
<ProjectSiteEnabled>false</ProjectSiteEnabled> 
<ProcessTemplateName>ProcessTemplate</ProcessTemplateName>
</Project>

Force Server to find new WSUS updates

I know all my posts have been about WSUS and this is probably getting boring now, but this has been ruling my life as of late. One problem I’ve run into is when approving updates and then immediately getting servers to look for updates can be troublesome. For some reason the server will not seem to get the list and won’t show any needed updates. To fix this I have a few simple steps below.

1. Stop the Windows Update Service

2. Browse to c:\Windows\SoftwareDistribution and delete all the files in this directory

3. Start the Windows Update Service

4. Run Windows Update Successfully:)

Stay tuned for more I promised I’ll post something else in the next few days that doesn’t involve WSUS.  I’ve been working on updating some Citrix PVS clients so I’ll include some documentation on this.

WSUS Automation Client Side

Along the same lines as my first post I’ve worked with clients that want updates approved but have a more manual approach to actually installing those updates.  I tailored a VB script that can be scheduled that will check for updates, install updates, and then reboot the server.  This can be useful for shops that don’t necessarily get the GPO approval to fully automate updates but want a script that can be kicked off from each server.  Don’t get me wrong though I still believe a proper GPO setup is the way to go, but many times in IT baby steps are a welcomed transition until buy-in is found.  This so far has been tested on Windows 7, Server 2008, and 2008 R2.  Make sure it is scheduled with CSCRIPT. I can assist more if any additional information is requested.  Also note it will only reboot if the updates report a status of update may be required.

Set updateSession = CreateObject(“Microsoft.Update.Session”)
updateSession.ClientApplicationID = “MSDN Sample Script”

Set updateSearcher = updateSession.CreateUpdateSearcher()

WScript.Echo “Searching for updates…” & vbCRLF

Set searchResult = _
updateSearcher.Search(“IsInstalled=0 and Type=’Software’ and IsHidden=0″)

WScript.Echo “List of applicable items on the machine:”

For I = 0 To searchResult.Updates.Count-1
Set update = searchResult.Updates.Item(I)
WScript.Echo I + 1 & “> ” & update.Title
Next

If searchResult.Updates.Count = 0 Then
WScript.Echo “There are no applicable updates.”
WScript.Quit
End If

WScript.Echo vbCRLF & “Creating collection of updates to download:”

Set updatesToDownload = CreateObject(“Microsoft.Update.UpdateColl”)

For I = 0 to searchResult.Updates.Count-1
Set update = searchResult.Updates.Item(I)
addThisUpdate = false
If update.InstallationBehavior.CanRequestUserInput = true Then
WScript.Echo I + 1 & “> skipping: ” & update.Title & _
” because it requires user input”
Else
If update.EulaAccepted = false Then
WScript.Echo I + 1 & “> note: ” & update.Title & _
” has a license agreement that must be accepted:”
WScript.Echo update.EulaText
WScript.Echo “Do you accept this license agreement? (Y/N)”
strInput = WScript.StdIn.Readline
WScript.Echo
If (strInput = “Y” or strInput = “y”) Then
update.AcceptEula()
addThisUpdate = true
Else
WScript.Echo I + 1 & “> skipping: ” & update.Title & _
” because the license agreement was declined”
End If
Else
addThisUpdate = true
End If
End If
If addThisUpdate = true Then
WScript.Echo I + 1 & “> adding: ” & update.Title
updatesToDownload.Add(update)
End If
Next

If updatesToDownload.Count = 0 Then
WScript.Echo “All applicable updates were skipped.”
WScript.Quit
End If

WScript.Echo vbCRLF & “Downloading updates…”

Set downloader = updateSession.CreateUpdateDownloader()
downloader.Updates = updatesToDownload
downloader.Download()

Set updatesToInstall = CreateObject(“Microsoft.Update.UpdateColl”)

rebootMayBeRequired = false

WScript.Echo vbCRLF & “Successfully downloaded updates:”

For I = 0 To searchResult.Updates.Count-1
set update = searchResult.Updates.Item(I)
If update.IsDownloaded = true Then
WScript.Echo I + 1 & “> ” & update.Title
updatesToInstall.Add(update)
If update.InstallationBehavior.RebootBehavior > 0 Then
rebootMayBeRequired = true
End If
End If
Next

If updatesToInstall.Count = 0 Then
WScript.Echo “No updates were successfully downloaded.”
WScript.Quit
End If

If rebootMayBeRequired = true Then
WScript.Echo vbCRLF & “These updates may require a reboot.”
End If

WScript.Echo “Installing updates…”
Set installer = updateSession.CreateUpdateInstaller()
installer.Updates = updatesToInstall
Set installationResult = installer.Install()

If rebootMayBeRequired = true Then
strShutdown = “shutdown.exe -r -t 10″
set objShell = CreateObject(“WScript.Shell”)
objShell.Run strShutdown, 0, false
End If

WSUS 3.0 Multiple Update Approval by Groups

So let me setup the problem for this post.  I work with a client that has many different servers that require different approval processes for different server groups.  This means before patches can go to Production they must hit Development and some servers need to stay a month behind on updates. Unfortunately the tool provided for this was WSUS which does a fine job but isn’t granular enough to do this out of the box.  Luckily I was able to find some Powershell scripts that do what I need and I’ll further explain them below.

1.  First you’ll use the Powershell code below to determine the identifying number for each group in WSUS.  Take note of the number for the group you want to approve updates for.  Make sure to put your WSUS Servername within the quotation marks at line 3.

[void][reflection.assembly]::LoadWithPartialName(“Microsoft.UpdateServices.Administration“)

$updateServer = “WSUSServername“
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($updateServer,$false)

$wsus.GetComputerTargetGroups()

2. Now that you have the correct group number you’ll want to run the code below. Again fill in the WSUS server name.  Have the FQDN and target group number that you pulled handy. The script will prompt for FQDN of a server located in the group and then the Group number. One thing worth noting is that it will approve updates for all servers located in that group so I’d recommend entering the server that needs the most updates.  This also means you may have to break servers into sub groups that include a Production and Test group depending on your circumstances. Once this script has been run if you check a report on a item included in the group it should show approve.

[void][reflection.assembly]::LoadWithPartialName(“Microsoft.UpdateServices.Administration“)

$updateServer = “WSUSSERVER“
$machineName = Read-Host “Please enter the full DNS name of the computer you wish to approve updates for“

$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($updateServer,$false)

$updateScope = new-object Microsoft.UpdateServices.Administration.UpdateScope

$updateScope.includedInstallationStates = “NotInstalled“

$com = $wsus.GetComputerTargetByName($machineName)

$groupid= Read-Host “Please enter the Computer Group Target ID“

$group = $wsus.GetComputerTargetGroup($groupid)
$action = [Microsoft.UpdateServices.Administration.UpdateApprovalAction]::Not Approved

$updates = $com.GetUpdateInstallationInfoPerUpdate($updateScope)
$updates | foreach-object {$uid = $_.UpdateId; $u = $wsus.GetUpdate($uid); $u.Title; $u.Approve($action,$group);}

[void][reflection.assembly]::LoadWithPartialName(“Microsoft.UpdateServices.Administration“)

$updateServer = “WSUSServer“
$machineName = Read-Host “Please enter the full DNS name of the computer you wish to approve updates for“

$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($updateServer,$false)

$updateScope = new-object Microsoft.UpdateServices.Administration.UpdateScope

$updateScope.includedInstallationStates = “NotInstalled“

$com = $wsus.GetComputerTargetByName($machineName)

$groupid= Read-Host “Please enter the Computer Group Target ID“

$group = $wsus.GetComputerTargetGroup($groupid)
$action = [Microsoft.UpdateServices.Administration.UpdateApprovalAction]::Not Approved

$updates = $com.GetUpdateInstallationInfoPerUpdate($updateScope)
$updates | foreach-object {$uid = $_.UpdateId; $u = $wsus.GetUpdate($uid); $u.Title; $u.Approve($action,$group);}

3.  There really isn’t another step for this but in my experience I’ve maybe made one or two mistakes and one was approving updates for the wrong group.  With developers using the servers I didn’t want anyone to get click happy and take a server down.  The code below will need the same information but do the reverse and set updates back to unapproved.  This is great in a pinch if there are more than 5 to 10 updates and you want to quickly get things back to normal.

[void][reflection.assembly]::LoadWithPartialName(“Microsoft.UpdateServices.Administration“)

$updateServer = “WSUSSERVER“
$machineName = Read-Host “Please enter the full DNS name of the computer you wish to approve updates for“

$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($updateServer,$false)

$updateScope = new-object Microsoft.UpdateServices.Administration.UpdateScope

$updateScope.includedInstallationStates = “NotInstalled“

$com = $wsus.GetComputerTargetByName($machineName)

$groupid= Read-Host “Please enter the Computer Group Target ID“

$group = $wsus.GetComputerTargetGroup($groupid)
$action = [Microsoft.UpdateServices.Administration.UpdateApprovalAction]::NotApproved

$updates = $com.GetUpdateInstallationInfoPerUpdate($updateScope)
$updates | foreach-object {$uid = $_.UpdateId; $u = $wsus.GetUpdate($uid); $u.Title; $u.Approve($action,$group);}

I unfortunately cannot take credit for this scripting genius as I found it online.  I do hope that my additional explanation can help some of the items that I wasted time figuring out.  I did create #3 myself, but that just involved changing approved to NotApproved without a space which debugging is nice enough to tell you.  Show some love to this link!!!!