• How to use Visual Studio to package a SharePoint solution if you don’t have SharePoint installed

    I re-image my machine often, and when I fire up a Visual Studio 2010 for the first time, I always get an error “To work with this project, either SharePoint Foundation 2010 or SharePoint Server 2010 must be installed on the system” or “A SharePoint server is not installed on this computer. A SharePoint server must be installed to work with SharePoint projects.”

    Instead of installing SharePoint on my local machine, I usually just trick Visual Studio into thinking that SharePoint is installed. This link says to export the RegHive from a real SharePoint server and import it. I can never remember this.

    To compile your code, you need to copy the “Microsoft.SharePoint.dll” and Microsoft.SharePoint.Security.dll from “C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI” to your local drive and “Add Reference” to your project (Right Click References)

    Haven’t worked with remote debugging to much, but this article describes it.


  • How to tell if your PowerShell function was called by name or by alias

    I been wanting to write functions that act differently depending on how they were called. I am not sure if this is good practice or not, but I like the idea. Turns out all you need is “$MyInvocation.InvocationName” Look at they following code:

    Function Test-Calling {
    if ($MyInvocation.InvocationName -eq "cows"){Write-host "This function was called by an alias ($($MyInvocation.InvocationName))"}
    if ($MyInvocation.InvocationName -eq $MyInvocation.MyCommand){Write-host "This function was called by name ($($MyInvocation.MyCommand))"}
    }
    set-alias cows Test-Calling
    

    If you call the function by alias you get : This function was called by an alias (cows)
    If you call the function by it’s name you get: This function was called by name (Test-Calling)

    I hope that helps someone.

    
    

  • 3000 Visitors on one month!

    I remember thinking, when I hit 2000 visitors in a month, I will never make 3000!


  • PowerShell script to force download and install WindowsUpdates

    I have been using the UpdateHF.vbs vbscript for years to patch all my servers. I wrote a simple HTA to wrap it, and it gets executed by psexec. I wanted to take that script, strip it down, and convert it to PowerShell. My intension was to  run it through a PSSession but I get access denied. Maybe I will try launching it with SCCM?

    I found these three scripts, that I chopped to together for a script that I wanted:

    Function JBMURPHY-Install-WindowsUpdates {
    PARAM([switch]$Install,[switch]$reboot)
    	if($(Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired")){
    		if (!($reboot)){
        		write-host "There are pending reboots, please pass the reboot command"
        		return
    		}
    		else{
    		restart-computer
    		return
    		}
    	}
    
    	Write-Host -nonewline " + Searching for Updates: "
    	$UpdateSession = New-Object -ComObject Microsoft.Update.Session
    	$Updates=$updateSession.CreateupdateSearcher().Search("IsAssigned=1 and IsHidden=0 and IsInstalled=0").Updates
    	Write-Host " Found [$($Updates.count)] Updates to Download and install`n`n"
    
    	$UpdatesCollection = New-Object -ComObject Microsoft.Update.UpdateColl
    	$UpdatesDownloader = $UpdateSession.CreateUpdateDownloader()
    	foreach ($Update in $Updates){
    
    		# Add Update to Collection
    		if ( $Update.EulaAccepted -eq 0 ) { $Update.AcceptEula() }
    		$UpdatesCollection.Add($Update) | out-null
    
    		# Download
    		Write-Host -NoNewline " + Downloading Update $($Update.Title)"
    		$UpdatesDownloader.Updates = $UpdatesCollection
    		$DownloadResult = $UpdatesDownloader.Download()
    		$DownloadResultResultCode = switch -exact ($DownloadResult.ResultCode)
    		{
    		  0   {"NotStarted"}
    		  1   {"InProgress"}
    		  2   {"Succeeded"}
    		  3   {"SucceededWithErrors"}
    		  4   {"Failed"}
    		  5   {"Aborted"}
    		}
    		$Message = " [{0}] " -f ($DownloadResultResultCode)
    		Write-Host -ForegroundColor Green $message
    	}
    	if (($Install) -and ($($Updates.count) -gt 0)) {
    	write-host "`n`nInstalling updates"
    	$Installer = $UpdateSession.CreateUpdateInstaller()
    	$Installer.Updates = $UpdatesCollection
    	$InstallerResult = $Installer.Install()
    	$InstallerResultCode = switch -exact ($InstallerResult.ResultCode)
    		{
    		  0   {"NotStarted"}
    		  1   {"InProgress"}
    		  2   {"Succeeded"}
    		  3   {"SucceededWithErrors"}
    		  4   {"Failed"}
    		  5   {"Aborted"}
    		}
    		$Message = " Installation [{0}] " -f ($InstallerResultCode)
    		Write-Host $message
    		Write-Host
    	}
    	if (($reboot) -and ($($Updates.count) -gt 0)) {
    	if($(Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired"))
    		{
        		write-host "Rebooting"
        		restart-computer
    		}
    	}
    }
    

    Thanks to those that put the original scripts together


  • PowerShell script to “process” scripts/functions

    I was not happy with the code I wrote in this post. The goal was to write my functions with a “generic” naming convention, and then “process them” – change the naming convention to match my employer’s company name. For example JBMURPHY-AD-GetCurrentSite would be “processed” to Company-AD-GetCurrentSite. In the previous post, I just looped thought and created an alias for each function that matched a RegEx.

    I think figured out a better way. Instead of creating aliases, I read the contents of the script line by line, replacing strings as I go, and then create a new file with the new naming conventions.

    First I created a hash table with my search and replace strings:

    	$SearchAndReplace = @{
    	"JBMURPHY-" = "COMPANY-";
    	"server.domain.com" = "realservername.company.com";
    	}
    

    Next I loop through the files, get their content line by line, loop through the hash table replacing the matching text and output to a temp file.

          foreach ($file in $(gci $SourcePath)) {
        	$tempFile = [System.IO.Path]::GetTempFileName()
        	get-content $file | %{
        	$OutPut=$_
        	ForEach ($key in $SearchAndReplace.Keys) {
        	  $OutPut=$OutPut -Replace $key,$SearchAndReplace[$key]
        	}
        	$OutPut >> $tempFile
        	}
        	move-item $tempFile $destination -force
        	}
    

    Much cleaner, and I can keep adding search and replace terms to my hash table.


  • PowerShell script to make a WinPE USB drive

    I wanted to take my previous set of scripts to create a WinPE environment  a step further. I wanted a script to create a bootable WinPE USB drive (UFD).

    Here is that script (again it is numbered to indicate the order in which to run things). I borrowed the diskpart stuff from here:

    Function JBMURPHY-WinPE-7MakeUFD{
            Param($OSArchitecture="x86",$RootDirectory="c:\PE\winpe_$OSArchitecture\ISO")
    $UFD=Get-WmiObject -Class Win32_LogicalDisk | Where-Object {($_.DriveType -eq 2) -and ($_.DeviceID -ne "A:")}
    If ($UFD.Count -eq 0){
    Write-host "Can't find any UFDs"
    return
    }
    "list disk" | diskpart
    $DriveToUse=read-host "`nWhat disk do you want to use (just the number)"
    If (!($DriveToUse)){exit}
    
    $command= @"
    select disk $DriveToUse
    clean
    create partition primary
    select partition 1
    format fs=fat32 quick
    active
    assign LETTER=K
    "@
    
    $command|
    DiskPart |
    Where-Object { $_.Length -gt 0 } |
    Foreach-Object { Write-Progress -Activity "Creating New UFD" -Status $_ -Id 1}
    
    copy-item -verbose "$RootDirectory\*" "K:\" -recurse
    }
    

  • PowerShell to create Aliases for all your functions

    I have a naming convention for all the function that I write, for example: JBMURPHY-AD-GetGroup. I wanted to create aliases for all my functions with my employers’s name, for example CompanyName-AD-GetGroup. I created the following function to “grep” all the function names and create an “Alias” file. This file would have all the set-alias commands that would be sourced on PowerShell start up. This function contains Regular Expressions (my weakness), which I borrowed from here.

    FUNCTION JBMURPHY-CreateAliases{
    PARAM($OLDNAME="JBMURPHY-",$NEWNAME="CompanyName-")
    $tempFile = [System.IO.Path]::GetTempFileName()
    
    Select-String -Pattern "function\s+(\w+-\w+-\w+)\b" *.ps1 | %{
    $FUNCTIONS=$_.Matches | %{$_.groups[0].Value -Replace "Function ",""}
    Write-host "set-alias $($FUNCTIONS -Replace $OLDNAME,$NEWNAME) $FUNCTIONS -Option AllScope"
    Out-File $tempFile -encoding ascii -append -inputobject "set-alias $($FUNCTIONS -Replace $OLDNAME,$NEWNAME) $FUNCTIONS -Option AllScope"
    }
    move-item $tempFile "$($NEWNAME)ALIASES.ps1" -force
    }
    

  • PowerShell, Active Setup and running a SCCM package “before log on”

    I have been struggling with the following idea for a while: How to run a package before before a person logs on using SCCM. There is a setting in SCCM that runs when no one is logged on, but if a person reboots and logs on before SCCM fires, the package will never run. Basically I wanted the ability to make SCCM work like Software Deployment in AD (AD prevents you from logging on until software is completely installed).

    The missing piece, for me, was “Active Setup”. Active Setup is pretty well documented here. Combining Active Setup with PowerShell and SCCM, I believe I can run packages before people log on (or at least before they launch any programs).

    Here are my steps

    • Step 1 : I need to create an Active Setup registry entry on everyone’s machine that will run a PowerShell script
      • I created this PowerShell script to create the Active Setup registry entries. This will put a StubPath that launches the PowerShell script.
    • Step 2 : Pop up an info message telling the user we are doing some work before the finish logging in.
    • Step 3 : Launch the SCCM Advertised program that you want. Since Active Setup is running as the user, you have to use SCCM to run anything that needs “administrative privileges”. The following code is used inside a PowerShell script to launch an advertisement on the local machine (you need to know the ProgramID and the PackageID):
    Function JBMURPHY-SCCM-UIExecuteProgram {
     Param([parameter(Mandatory = $true)]$ProgramID,
           [parameter(Mandatory = $true)]$PackageID)
     $UIResource = New-Object -ComObject UIResource.UIResourceMgr
     $UIResource.ExecuteProgram($ProgramID, $PackageID,$true)
    }
    

    Kinda complicated, but I think it will work. Have you used these methods?