AutoSPSourceBuilder heads to the PowerShell Gallery!

Standard

File under “why didn’t I do this years ago??”

You can now easily install AutoSPSourceBuilder (my PowerShell-based utility for downloading SharePoint updates and integrating them into the installation media) from the PowerShell Gallery.

TL;DR:

Install-Module -Name AutoSPSourceBuilder

No more need to browse to the GitHub repo, download the zip, extract it, etc. The simple one-liner above will (on any modern Windows machine with installed-by-default PowerShellGet etc.) automatically download and install AutoSPSourceBuilder.ps1 to your default Scripts directory, and make it available to directly run in any PowerShell sessions you launch.

What’s more, the AutoSPInstaller.xml update inventory file, updated on a (roughly) monthly basis and previously bundled with the script, is now by default automatically downloaded at script run-time to ensure you have the latest set of SharePoint updates to choose from. If however for any reason you want to use your own XML inventory, you can opt to skip the xml download and use a local copy of the inventory file by including the new -UseExistingLocalXML switch parameter.

Now that I finally realized just how ridiculously easy it is to publish a script to the Gallery, you can expect to see some more of my stuff make its way there in the near future.

Hopefully this latest batch of changes makes it easier to keep the AutoSPSourceBuilder SharePoint update management tool… updated!

Cheers
Brian

Pre-Populating SharePoint Farm Details for ULSViewer

Standard

The new ULSViewer for SharePoint introduces the capability to monitor all the ULS logs in your SharePoint farm at once, in real time. While this is a fantastic enhancement to an already near-perfect piece of software, I found one tiny little pain point with it. When configuring ULSViewer to monitor an entire farm, you need to manually specify all the servers in your farm as well as the common ULS log path.

image

As a seasoned (crusty) SharePoint IT pro, I thought to myself, “hey ULSViewer, you seem smart… figure it out yourself!” After all, this isn’t top-secret information, it’s all right there within the farm configuration. And being the type of person who hates doing anything manually (especially more than once), I wanted some sort of automated fix.

So I set upon writing a fairly simple PowerShell script that would query the farm to grab all the SharePoint servers in the farm, plus the diagnostic (ULS) logging path. These pieces of information are available via two SharePoint PowerShell cmdlets: Get-SPFarm and Get-SPDiagnosticConfig. The rest was just reading and if necessary adding to ULSViewer’s Settings.XML file.

Head on over to the TechNet Gallery to grab the PowerShell script for yourself… heck it could even save you seconds of your precious time!

Using AutoSPInstaller to Run Specific Configuration Changes

Standard

While AutoSPInstaller (my open-source project for installing SharePoint 2010/2013) is designed so it can be run and re-run as often as required to complete or tweak the installation and initial configuration of a SharePoint farm, there admittedly are times when executing the entire scripted process might seem like overkill.

For example, you might want to provision a service application that you accidentally had left set to “false” the first time around. Or, you might want to rewire which servers in your farm are running the Distributed Cache service (maybe to create a dedicated Cache cluster). Alternately, maybe several months (and changes) have passed since your farm was built, and your level of confidence that something hasn’t diverged from your original XML configuration (to the point of conflicting with it) isn’t rock-solid.

Luckily, since the included file AutoSPInstallerFunctions.ps1 is, as the filename suggests, just a (very) big collection of PowerShell functions, you can actually isolate and run these chunks of script code individually. The advantages are twofold: First, you can continue to leverage the consistent and automated approach that helped get your farm built quickly in the first place. Second, you can completely bypass all the redundant steps in the process (such as checking for and creating web apps, adding managed accounts, etc.) and can be assured that only the net-new changes you need will be executed.

To do this, you’ll obviously need the AutoSPInstaller script files themselves, as well as the AutoSPInstallerInput*.xml file you used to originally build the farm (with your new modifications included of course). For the steps below, you’ll want to be logged in as the SharePoint installer account (you did use a dedicated account to install SharePoint, right?)

First, we want to grab the full path to your XML, so we can easily paste it below. A quick shortcut to do this is to shift-right-click the XML file itself and select Copy as path:

image

Now, launch a SharePoint Management Console (as Administrator), and enter the following in order to assign the content of our input file to an XML object:

[xml]$xmlinput = (Get-Content "<path to your XML file which you can just paste here>") -replace "localhost", $env:COMPUTERNAME

Note that you can simply paste the path to your XML in the designated space above (by the way, the line above was basically pulled straight from AutoSPInstallerMain.ps1).

Now that our entire XML input file is loaded and available as $xmlinput, we can use it to pass parameters to many of the functions found in AutoSPInstallerFunctions.ps1. First however we’ll need to make those functions available to us in this console – this is accomplished by dot-sourcing the script. Here we have another one-liner, and if we use the same technique to copy the path to our AutoSPInstallerFunctions.ps1 as we did above, we can just type a dot “.” followed by a space then paste the path, for example:

. "\\Win2012R2-SP\C$\SP\AutoSPInstaller\AutoSPInstallerFunctions.ps1"

Finally, we’re ready to call nearly any of the functions in AutoSPInstaller (in fact we can use familiar tab-based autocomplete to get their names, too) since they’re loaded in memory for the current PowerShell console.

Let’s say for example we want to provision Business Connectivity Services on this particular server (the one we’re logged on to, that is). We would simply enter:

CreateBusinessDataConnectivityServiceApp $xmlinput

At this point, the BCS service app should get provisioned based on the details in our XML input file:

image

Note, if nothing happens, it’s likely because you forgot to change the XML Provision attribute from “false” to either “true” or the name of your target server.

That’s really about all there is to it. Hopefully this helps folks who are leery of running the entire monolithic AutoSPInstaller process just to make small changes to their existing farms.

(Oh I realize the current layout & structure of AutoSPInstaller may not be optimal – namely, much of this should probably have been implemented as one or more PowerShell modules… it’s in the queue of future enhancements!)

Slipstreaming issues beginning with SharePoint August 2012 CU (Part 2)

Standard

In my last post, I described the installation errors that I experienced when attempting to do a slipstreamed install of SharePoint 2010 with SP1 + August 2012 CU, and a workaround that I’d implemented in AutoSPInstaller to allow the script to proceed beyond the error. It seems however that I was a tad hasty… subsequent testing revealed that the errors were not just benign & safely ignore-able – you’d basically be left with a half-patched SP2010 installation afterwards. This was evidenced on two fronts: the version info on certain files were still showing the SP1 build, and the fact that I was able to re-run the August 2012 CU after the supposed successful slipstreamed install and could see it was actually doing stuff (instead of just quickly exiting with an “…already applied” type of message.

In discussing this problem with the usual suspects, we discovered that the August 2012 CU does indeed behave differently. Although SharePoint 2010 Service Pack 1 was nearly always listed as a prerequisite for CUs released after it, up until recently it seems it didn’t actually matter whether SP1 was installed before or after the CU. However, with the release of the August 2012 CU, this has apparently changed – the CU won’t even install on an existing farm if it fails to detect the presence of SP1.

Though we have a support case open with Microsoft about this issue, at the moment we don’t have a real solution. One viable workaround though would involve simply using a slipstreamed source containing SP1 (optionally with the June 2012 CU – the most recent one that worked for full slipstreaming), then afterwards applying the August (or October) 2012 CU. Yes, a pain in the butt… You could even go one step further and run the CU with unattended switches to ease the manual pain – probably the best approach if you’re looking for the latest & greatest SharePoint 2010 build with minimum steps & effort.

I’ll update this post as soon as I confirm any new details, either from the open support case or from the general Interwebz/Twitterz.

Update (Jan 14/2013): Trevor has posted this update based on the support case he opened with Microsoft. Let’s cross our fingers that we see a fix before (heck, or even with) SP2.

Slipstreaming issues beginning with SharePoint August 2012 CU (and a fix)

Standard

Ever since the release of the August 2012 SharePoint 2010 Cumulative Update (CU), I (and several others) noticed that, during the SharePoint binary file installation portion of AutoSPInstaller, it would fail with a PatchApplicationFailure error in the SharePoint installation log, if we integrated Service Pack 1 + the August 2012 CU in the SP2010 install media. Since this did not happen with any prior CU up to and including June 2012, those of us affected basically thought we’d found a bug in the CU. Famous SharePoint admin dude Todd Klindt even included it on his Bugs & Regressions page.

Feeling smug & confident that I’d been part of discovering a sneaky bug, I waited patiently for the latest October 2012 CU to be released, hoping it would provide a fix. Wellll imagine my surprise when I ran into the very SAME issue with the slipstreamed October 2012 CU media… Hang on, I thought. This couldn’t still be an issue with this latest CU. I turned to a good ol’ search of the Interwebz and found a shockingly low number of hits for the problem. Surely, if it were truly a bug then lots more folks would be experiencing it. But the top search hits actually came back to my AutoSPInstaller discussions on the issue. Hmm.

Time to try a manual (non-scripted) install of SharePoint then. Let’s see if it fails, gives a warning, or otherwise indicates a corruption of the install media. What I found was a familiar dialog box, but with a message I’d never seen before:

SP2010UpdatesNotInstalled

Note the text – “Some updates were not installed”. Well, we know that during our scripted install, some updates were indeed not installed – and this caused AutoSPInstaller to blow up & exit. However, the dialog box above simply notes it as an FYI, and allows us to proceed with the usual Config Wizard. Huh?

I did a comparison of the SharePoint installation log files – the log produced when AutoSPInstaller errored out, and the one associated with the apparently successful manual installation above. To my (repeated) surprise, both logs included the PatchApplicationFailure error. But, although this may be a new thing starting with the August 2012 CU, it apparently isn’t considered something critical enough to cause the installation to fail. Further, I noticed that both logs contained the message: “Successfully installed package: oserver” – which I take to be an indication that the setup process as a whole was a net success.

It soon became clear to me why AutoSPInstaller was bombing out. After the setup of the SharePoint binaries, the script would simply parse the log for the string “Error:” If it found at least one instance of it, it would consider the binary installation a failure and throw an error. This worked fine for every type of slipstreamed installation until the August 2012 CU. For reasons as-yet unknown, this update (and presumably all CUs going forward) does things differently to the effect that a successful installation can still actually contain errors in the log…

Luckily the fix was simple. In addition to parsing the log for the string “Error:”, I now needed to search for the string “Successfully installed package: oserver”, and modify the If statement to look for both the presence of “Error:” and the absence of “Successfully installed package: oserver” – in other words, if there was an error in the log but no message indicating overall success, then AutoSPInstaller should throw an error.

The updated AutoSPInstaller changeset that fixes this problem can be obtained as always from http://autospinstaller.codeplex.com/SourceControl/list/changesets and will eventually make its way into the default recommended AutoSPInstaller download package.

Note: At the time of writing this I realized this is seemingly not all there is to this issue. Part 2 of this post will delve deeper – stay tuned!

Using PowerShell to Automate SQL 2008 R2 SP1 Slipstreaming

Standard

Like most of you SharePoint folks, I find myself installing SQL Server quite frequently (since SharePoint has an ever-so-slight dependency on it). However I also like to have the latest & greatest service pack in my environments, and currently this means SP1 for SQL 2008 R2 (yeah I know SQL 2012 is out, but most of my clients are a bit shy with such ‘new’ releases). Since I do extreme slipstreaming of SP1 + CUs for SharePoint as described (for example) in Todd Klindt’s excellent blog post, I looked for a way to do this with my SQL Server 2008 R2 binaries.

The slipstreaming process for SQL Server is a bit convoluted, and for a guy like me, very forgettable. It is however fairly well documented in articles like this one. Therefore I sat down on evening and sought to automate the process, in order to minimize the amount of thought and manual effort required.

I wanted this script to:

  • Copy the original RTM binary files from a DVD/ISO/directory to my designated path
  • Download the SP1 packages for me (cuz I didn’t want to have to remember or hunt around for the URLs for the service packs for each respective platform (IA64, x64, x86) each time I needed to slipstream)
  • Extract each platform service pack (thus avoiding having to remember the associated command-line switches)
  • Make the required edits to each platform-specific DefaultSetup.ini
  • Place a nice little text file to serve as a label in the target path, to remind me that I’d slipstreamed this particular binary source location

Anyhow I’m happy to announce my successful first attempt at tackling the automated slipstreaming of SQL 2008 R2 + SP1 via PowerShell, and you can grab it from the TechNet Script Center Gallery, here.

Cheers
Brian

P.S. My next goal in case you’re interested is of course to automate SharePoint 2010 service pack and cumulative update slipstreaming, but due to the way MS packages their CUs this has proven challenging (apparently there are no known command-line switches for the downloaded Microsoft Self-Extractor packages!)

What’s In Store For AutoSPInstaller v.Next

Standard

Well it’s been a little while since the last AutoSPInstaller release (and the last blog post, to be honest) but let me assure you it’s been all work and (slightly less) play! The last few months have seen a pretty intense development crunch for the automated SharePoint 2010 install/config script, and I just can’t seem to figure out when to call it quits and stop scope-creeping myself. Anyhow I think it’s time I came up for air to let everyone know what I’ve been up to.

More Of The Same Goodness, Tweaked

While there’s some notable new features (see below), one of the goals of a new release should obviously be to resolve some outstanding issues. So I managed to fit a bunch of fixes in, and here are some of them in no particular order…

First, the CreateEnterpriseSearchServiceApp function seems to have never been able to successfully have more than one query server and successfully create the query topology (for reasons that turned out to be pretty odd.) Expect a fix for that in v3.

Also, the ValidatePassphrase function will now actually check farm passphrases against all criteria (previously, the requirement for an 8-character minimum was missing).

A nice treat for me was stumbling upon http://support.microsoft.com/kb/2581903. Why? Because it explains a nagging issue I’d been having lately with the PrerequisiteInstaller.exe – namely that it would almost always crap out on KB976462 lately. Well it turns out the fix is simple – as per the article, I re-jigged the InstallPrerequisites function to install the .Net Framework prior to running PrerequisiteInstaller.exe. Done and done.

Finally and maybe worth mentioning is the small but interesting addition of a timer for the SharePoint and Office Web Apps binary installation functions. This is nice for when you’re trying to get an idea of how long each install takes (e.g. for comparing the speed of various servers & platforms).

Sure there are other tweaks and fixes here and there, but let’s get to the new stuff…

Run Once, Install Many

A much pondered (if not requested) feature of AutoSPInstaller was the ability to install and configure your entire farm from a single, central server. Well ponder no more; I’ve had a good deal of success in finally remote-enabling the SharePoint scripted process. Lots of hoops to jump through for this one, including leveraging the ever-useful PsExec.exe to, uh, remotely open the door to PowerShell remoting in the first place. I expect this feature will go through a LOT of iterations since it seems there are a ton of things that can cause remoting to go wonky, never mind trying to do a full SharePoint 2010 install over a remote session!

So far I’ve had repeated luck building 2 and 3-server farms – can’t wait to try it on larger target farms with decently-powered hardware though. Oh and one more thing – the machine on which you trigger the install doesn’t even have to be one of the farm servers…

Simultaneous Installs

Hand-in-hand with the new remote functionality is the promise of parallel installations. Some of the faithful have asked, “Hey, why can’t we have multiple binary installs going at once, since these can take a long time, especially when installing n-server SharePoint 2010 farms?” Following a suggestion that was made on the AutoSPInstaller discussion list, I’ve implemented the ability to pause after the binaries have completed installing. That way, you can safely kick off the script on as many servers as you’d like at the same time, then return to each server one at a time to press a key and configure/join the farm.

Further, if remote installs have been specified, the script will kick off simultaneous remote sessions to each server in the farm and perform the binary install portion of the script. For now, each session will wait for input (key press) before proceeding with the farm config/join, but the ultimate goal is to go fully automated and have each session somehow detect when the farm is ‘ready to be joined’.

DB Control Freaks, Rejoice

Another oft-requested piece of functionality is the ability to spread your SharePoint 2010 databases out to more than just one SQL server. This is certainly a nice-to-have for large farms where (for example) you’d like your Search databases to have dedicated hardware. Or, maybe you need to put a particular content database on an extra-secure and isolated SQL cluster instance.

The next version of AutoSPInstaller will include the ability to specify a different SQL server (and SQL alias!) for each web app, and nearly every service app you can think of. The semi-exception is Search, which does allow for a different SQL instance to be specified, but currently won’t automatically create your alias for you (though you can simply create one manually, in advance).

Even if you don’t plan on using distributed SQL servers now, but are thinking you might need to segregate your DB back-end duties in the future, you can take advantage of this new feature by creating different SQL aliases (pointing to the same SQL instance, for now). The aliases can then fairly easily be re-pointed to different SQL instances later. Cheap insurance for growing farms that aren’t quite ready to spring for all that new SQL server hardware on day one.

Choose Your Input

Last and probably least, the under-appreciated AutoSPInstallerLaunch.bat will support an arbitrarily-named input XML file passed to it as an argument. So, if you’re like me and have amassed a decent collection of AutoSPInstallerInput-<string>.XML files, you’ll appreciate the ability to tell the script exactly which XML input file you’d like to use at that particular moment (and not just one auto-detected based on server name, domain etc. – though that’s still supported.)

Aaaaannnndd a nice little feature I discovered (maybe a little late to this party) is that you can actually drag an input file onto the AutoSPInstallerLaunch.bat:

DragOntoAutoSPInstallerLaunch

That way, it gets passed to the batch file as an argument without having to type it all out in a command window – a pretty decent time-saving tip!

Coming… when?

Aha, see the note earlier in this post about scope-creep 😉 Well if I can lock things down in the coming days/weeks, I hope to check in some code that you can download and try out on your own. Something I’d consider beta I guess, although there are really two streams going on:

  • The core traditional functionality (one server at-a-time, script launched on each server manually) which is actually pretty stable and has benefitted from the fixes and features listed above
  • The new bleeding-edge remote/parallel install stuff (which can be completely bypassed by setting the appropriate input file parameters to false).

Both will of course be included in the next source code check-in, so you can decide then how lucky you feel 🙂 You can always subscribe to updates to be notified of that imminent update!

Cheers
Brian

Automating Managed Property Mapping in MOSS 2007 / Search Server 2008

Standard

I was recently asked to customize the Advanced Search experience for a Search Server Express 2008 customer. Remember that MSSE is basically WSS 3.0 + the search components from MOSS 2007 (remember that ancient product?). Anyhow this involved enabling the selection of a number of custom fields in the ‘property restrictions’ drop-down. Part of this overall process is mapping Managed Properties to Crawled Properties within the Search Administration area of the shared services provider. I more or less assumed that this would be a GUI-only, manual process for the 20+ properties I was dealing with. However I was faced with applying the changes to at least 4 different environments – not a lot of fun, and likely prone to error by tired eyes and fingers. I wasn’t (and still am not) aware of a way to do this using STSADM.exe, and even scoured the help for STSADM once again in case I’d missed something – no luck.

As is often the case, I stumbled on a neat solution while looking for something else entirely. The folks over at mosssearch.com released a freeware utility called MOSS Search Manager a while back, and it was designed exactly for this purpose. Fantastic! Now all I needed to do was include it in a batch file, give it the names of the managed properties to map (via a text input file), and run the batch file in each environment.

Here is the full script of the batch file. Copy/paste to <something>.cmd, and don’t forget to list all of your managed properties in a file called PropNames.txt in the same directory as the script and MOSSSearchManager.exe.

@ECHO OFF
ECHO - Adding/Mapping Managed Properties...
SET URL=http://yourURL:
SET ContentSource="Content Source Name, e.g. Local Office SharePoint Server sites"
SET InputFile=%~dp0PropNames.txt
ECHO - Getting crawled properties...
FOR /F %%a in (%InputFile%) do (
MOSSSearchManager crawledprop %URL% SharePoint | find /i "ows_%%a"
IF ERRORLEVEL 1 ECHO Crawled property "ows_%%a" not found!
)
ECHO - Getting managed properties...
FOR /F %%a in (%InputFile%) do (
MOSSSearchManager managedprop %URL% SharePoint | find /i "%%a"
IF ERRORLEVEL 1 ECHO Managed property "%%a" not found! & pause
)
pause
ECHO - Mapping properties...
FOR /F %%a in (%InputFile%) do (
ECHO - Mapping property %%a:
MOSSSearchManager mapmprop %URL% %%a %%a
ECHO - Mapping property ows_%%a:
MOSSSearchManager mapmprop %URL% ows_%%a %%a
)
IF ERRORLEVEL 1 pause
ECHO - Initiating Full Crawl...
MOSSSearchManager crawl %URL% %ContentSource% startfull
timeout 10
ECHO - Checking Full Crawl Status...
MOSSSearchManager crawl %URL% %ContentSource% status
pause
EXIT

Although this script was used for Search Server in my case, the search components are shared with MOSS 2007 so the utility/script will work with both products. And yes I suppose I could/should have used Powershell, it wasn’t yet installed on the target server(s) and would have involved additional change management process – not worthwhile for the length of this particular engagement.

So I suppose the lesson is… just when you think it can’t be automated, there may be a solution out there!

Cheers

Powershell script to enable/disable services in SP2010 Demo VM

Standard

If any of you have had the chance to play around with Microsoft’s recent public release of the Information Worker Demo VM, you’ll notice that a) it has pretty much everything thrown in in terms of the Office suite of server/client products and b) it’s a hog! At idle, the VM will start to consume almost 10GB RAM (combined physical and virtual/paging) within minutes of booting up. For developers and sysadmins used to running (2 or 3) 32-bit MOSS2007 Virtual PCs concurrently on your laptop, the new resource requirements for SP2010 can be quite a shock. How can we trim and optimize the resources the demo VM uses? By turning off services we don’t immediately need…

For example, if you want to develop/demo SharePoint 2010 stuff only, but don’t care about Office Communications Server, you can turn all of these services (and the supporting SQL instance) off, and free up quite a bit of RAM. However, you might want to change this in a different scenario, so that only the OCS services are running but the SharePoint stuff is off. This could get pretty tedious if we were simply using the Services MMC each time!

Using a Powershell script though, we can quickly enable/start or disable/stop different services on our demo VM, just in time for its intended use at any particular time. The script below can easily be further customized to allow for greater granularity over what services are controlled, etc. Consider it a starting point towards getting only the services you want running at any particular time on a machine with limited resources.

[UPDATE] – turns out Emmanuel Bergerat had already released scripts with very similar functionality, way back in November! Definitely check these out for another approach to freeing up resources on a SP2010 install.

Hope you find it useful! Oh and watch the line breaks and double quotes when copying/pasting…


## Stop-Start-Services.ps1 by Brian Lalancette
## Originally intended for SP2010 IW Demo VM

Function StopUnneededServices
{
Write-Host -ForegroundColor Blue "- Stopping services..."
#Permanent service stoppage - you likely wont need these in the demo VM
$ServicesToSetManual = ("Spooler",`
"AudioSrv",`
"TabletInputService",`
"UxSms",`
"ftpsvc",`
"MSSQLFDLauncher",`
"SQLSERVERAGENT")
$ServicesToDisable = ("WPDBusEnum",`
"WerSvc",`
"WSearch")
Write-Host -ForegroundColor Blue "- Setting some unneeded services to Manual start..."
ForEach ($SvcName in $ServicesToSetManual)
{
If (Get-Service -Name $SvcName -ErrorAction SilentlyContinue)
{
Stop-Service -Name $SvcName -Force
Set-Service -Name $SvcName -StartupType Manual
Write-Host -ForegroundColor Blue " - Service $SvcName is now set to Manual start"
}
}
Write-Host -ForegroundColor Blue "- Disabling some unneeded services..."
ForEach ($SvcName in $ServicesToDisable)
{
If (Get-Service -Name $SvcName -ErrorAction SilentlyContinue)
{
Stop-Service -Name $SvcName -Force
Set-Service -Name $SvcName -StartupType Disabled
Write-Host -ForegroundColor Blue " - Service $SvcName is now disabled."
}
}
}

Function StopSPServices
{
#Temporary SP demo service stoppage; use actual service name, not display (long) name
$ServicesToDisable = ("FASTSearchService",`
"FASTSearchMonitoring",`
"ProjectEventService14",`
"ProjectQueueService14",`
"WebAnalyticsService",`
"SPAdminV4",`
"SPTimerV4",`
"SPTraceV4",`
"SPAdminV4",`
"SPUserCodeV4",`
"OSearch14",`
"FIMService",`
"FIMSynchronizationService",`
"MSSQLSERVER",`
"MSSQLServerOLAPService",`
"MSDtsServer100",`
"ReportServer",`
"SQLWriter",`
"W3SVC",`
"IISADMIN")
Write-Host -ForegroundColor Blue "- Disabling SP demo services..."
ForEach ($SvcName in $ServicesToDisable)
{
If (Get-Service -Name $SvcName -ErrorAction SilentlyContinue)
{
Stop-Service -Name $SvcName -Force
Set-Service -Name $SvcName -StartupType Disabled
Write-Host -ForegroundColor Blue " - Service $SvcName is now disabled."
}
}
Write-Host -ForegroundColor White "- Finished disabling SP demo services."
}

Function StopFASTServices
{
#Temporary FAST service stoppage; use actual service name, not display (long) name
$ServicesToDisable = ("FASTSearchService",`
"FASTSearchMonitoring")
Write-Host -ForegroundColor Blue "- Disabling FAST services..."
ForEach ($SvcName in $ServicesToDisable)
{
If (Get-Service -Name $SvcName -ErrorAction SilentlyContinue)
{
Stop-Service -Name $SvcName -Force
Set-Service -Name $SvcName -StartupType Disabled
Write-Host -ForegroundColor Blue " - Service $SvcName is now disabled."
}
}
Write-Host -ForegroundColor White "- Finished disabling FAST services."
}

Function StopOCSServices
{
If (Get-Service -Name 'MSSQL$RTC' -ErrorAction SilentlyContinue)
{
Write-Host -ForegroundColor Blue "- Disabling OCS demo services..."
Set-Service -Name 'MSSQL$RTC' -StartupType Disabled
Stop-Service -Name 'MSSQL$RTC'
Get-Service | ?{$_.DisplayName -like "Office Communications*"} | Set-Service -StartupType Disabled
Get-Service | ?{$_.DisplayName -like "Office Communications*"} | Stop-Service
Write-Host -ForegroundColor White "- Finished disabling OCS services."
}
}

Function StartSPServices
{
$ServicesToSetAutomatic = ("FASTSearchService",`
"FASTSearchMonitoring",`
"MSSQLSERVER",`
"MSSQLServerOLAPService",`
"MSDtsServer100",`
"ReportServer",`
"SQLWriter",`
"W3SVC",`
"ProjectEventService14",`
"ProjectQueueService14",`
"WebAnalyticsService",`
"SPAdminV4",`
"SPTimerV4",`
"SPTraceV4",`
"SPAdminV4",`
"SPUserCodeV4",`
"FIMService",`
"FIMSynchronizationService",`
"OSearch14",`
"IISADMIN")
Write-Host -ForegroundColor Blue "- Re-enabling SP demo services..."
ForEach ($SvcName in $ServicesToSetAutomatic)
{
If (Get-Service -Name $SvcName -ErrorAction SilentlyContinue)
{
Set-Service -Name $SvcName -StartupType Automatic
Start-Service -Name $SvcName
Write-Host -ForegroundColor Blue " - Service $SvcName is now set to Automatic start"
}
}
Write-Host -ForegroundColor White "- Finished re-enabling SP demo services."
}

Function StartOCSServices
{
If (Get-Service -Name 'MSSQL$RTC' -ErrorAction SilentlyContinue)
{
Write-Host -ForegroundColor Blue "- Re-enabling OCS demo services..."
Set-Service -Name 'MSSQL$RTC' -StartupType Automatic
Start-Service -Name 'MSSQL$RTC'
Get-Service | ?{$_.DisplayName -like "Office Communications*"} | Set-Service -StartupType Automatic
Get-Service | ?{$_.DisplayName -like "Office Communications*"} | Start-Service
Write-Host -ForegroundColor White "- Finished re-enabling OCS demo services."
}
}

Function ChooseOption
{
$Choice = Read-Host "Please select:`n`
(1) - Stop ALL demo services`n`
(2) - Stop OCS demo services`n`
(3) - Stop SharePoint demo services`n`
(4) - Stop FAST services`n`
(5) - Start ALL demo services`n`
(6) - Start OCS demo services`n`
(7) - Start Sharepoint demo services`n`
(0) - QUIT`n`
Choice"

Switch ($Choice)
{
"1" {StopUnneededServices;StopSPServices;StopOCSServices;ChooseOption}
"2" {StopUnneededServices;StopOCSServices;ChooseOption}
"3" {StopUnneededServices;StopSPServices;ChooseOption}
"4" {StopFASTServices;ChooseOption}
"5" {StartSPServices;StartOCSServices;ChooseOption}
"6" {StartOCSServices;ChooseOption}
"7" {StartSPServices;ChooseOption}
"0" {break}
default {Write-Host -ForegroundColor Red "- Please select a valid option...";ChooseOption}
}
If ($Choice -eq "0") {break}
}

$Choice
If ($Choice -ne "0") {ChooseOption}

Write-Host "Press any key to exit..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")