ads

Style6

Style3[OneLeft]

Style3[OneRight]

Style4

Style5[ImagesOnly]

Style2

Convert VMDK to VHD




Problem:  

Import VMWare virtual machine (VM) into Hyper-V hypervisor.  Convert VMDK virtual disk into VHDX disk.

Solution:  

Use Microsoft Virtual Machine Converter (MVMC) 3.1 to import and convert the VMWare ESXi VM into Hyper-V.

Background:   

The MVMC GUI provides a simple import wizard.  Please note, the GUI only imports VMWare hypervisors (including ESXi) connected to VMSphere.  MVMC PowerShell commands can convert stand-alone ESX and ESXi VMs.

Convert:

  1. Download MVMC.  The Microsoft download sites lists MVMC as 3.0.  N.B., the file installs version 3.1.
  2. Install MVMC on Hyper-V host.
  3. Uninstall VMTools from VMDK VM.
  4. Copy VMDK to Hyper-V host.
  5. Open PowerShell.  Import MVMC PowerShell library.

    Import-Module "C:\Program Files\Microsoft Virtual Machine Converter\MvmcCmdlet.psd1"
  6. Use PowerShell to convert VMDK to VHD.  N.B., Do not use VMDK_Flat file!

    PS D:\TMP> ConvertTo-MvmcVirtualHardDisk -SourceLiteralPath "D:\VMS\DEV.vmdk" -DestinationLiteralPath "S:\VMS" -VhdType DynamicHardDisk
  7. Create new VM in Hyper-V.  Add newly created (i.e., system) disk to IDE adapter.  Additional disks can use the SCSI adapter.  This is the time to configure dynamic memory or add additional CPUs.
    N.B., Do not resize the disk until after the VM starts at least once in Hyper-V!
  8. Start-up VM.  Install Hyper-V tools.  Restart.
  9. Optional:  New NIC "hardware" causes problems with retaining preexisting static IPs.  Resolve problem by deleting the network adapter and restating.  Windows creates a new network adapter upon start-up.  Manually add IP addresses into new adapter.
That's It!

How to Fix Primary Domain Trust Failures

Error:  

The trust relationship between this workstation and the primary domain failed.

Problem:  

Domain computers use internal passwords to authenticate with Active Directory (AD).  Servers and workstations automatically reset their passwords every 30 days.  Suspended virtual machines or server backups may not logon domain users if the computer has a new password in AD.

Solution:   

Fix domain trust issues: (1) in AD, and (2) on the computer.

  1.    Reset the computer account in Active Directory Users and Computers (ADUC). 

    Open ADUC → Computers OU → Right-Click on the computer → Reset Accout

  2.  Reset the computer with PowerShell.  N.B., This step requires local Administrative rights.  We can't reset the computer, or even re-join the domain, with out the ability to log on locally.

    From PowerShell:  Reset-ComputerMachinePassword 
That's It!

References:  http://technet.microsoft.com/en-us/library/hh849751.aspx

Install Exchange 2010 rollups on DAG servers


By Steven Jordan on 4/17/2014

Takeaway:  Steps on how to apply Windows updates to the Exchange Data Availability Group (DAG) servers.  Take care when applying Exchange service pack rollups on Patch Tuesday.

  1. Prevent the server from activating databases.  N.B., Exchange continues to keep databases current; however it will not activate if other DAG members become unavailable.

  2. Get-MailboxDatabaseCopyStatus –Server (hostname) | Suspend-MailboxDatabaseCopy –ActivationOnly –Confirm:$false
  3. Migrate all active databases to another DAG member

  4. Move-ActiveMailboxDatabse -Server (hostname) -ActivateOnServer (Other DAG Member) 

  5. Check activation status with PowerShell:

  6. Get-MailboxDatabaseCopyStatus –Server (hostname) | Select Name, ActivationSuspended, MailboxServer
    Get-MailboxDatabase | Select Name, ActivationPreference, Server
  7. It's safe to install the Exchange roll-ups when activation is suspended. Proceed with patching.

  8. Re-enable the database after patching is complete. N.B., This server only becomes active if the other DAG member becomes unavailable.
  9. Get-MailboxDatabaseCopyStatus –Server (hostname) | Resume-MailboxDatabaseCopy
  10. Repeat the process for the remaining DAG servers: (a) prevent activation, (b) migrate active database to another DAG member, (c) install the roll-ups, (d) resume activation.
That's It!
References:  http://www.ehloworld.com/167


How to Sign Your PowerShell Scripts

By Steven Jordan on 4/17/2014.

Takeaway:  Sign PowerShell scripts with a code signing certificate.

Assumptions:  We'll assume a code-signing certificate is already installed the Windows certificate root store.  If you don't already have a code-signing certificate, obtain one:
  1. Enroll with the Windows Certificate Authority (CA) server.
  2. Enroll with a public CA.  Best option if you plan to publicly distribute your scripts.
  3. Generate a self-signed certificate.

Use the code-signing certificate located in the the Windows Certificate Store to sign PowerShell scripts.  First, export the certificate from the Certificate Store.  Export the certificate as follows:

Start → MMC → Add/Remove Snap-In → Certificates → Personal → Right click on the certificate → Export.

Save the certificate as a PFX file in a directory of your choice (e.g., c:\scripts).

Lastly, use the following PowerShell script to sign the code:

PS C:\scripts> $cert = Get-PfxCertificate C:\scripts\codesigncert.pfx  C:\scripts> Set-AuthenticodeSignature -Filepath pruneVSS.ps1 -Cert $cert

Directory: C:\scripts SignerCertificate Status Path ----------------- ------ ---- 2603FCAA10343AE1DD78AB41D984728D657499D3 Valid pruneVSS.ps1

That's it -the PowerShell script is signed.  Time to change the set-execution policy throughout the domain!

Remove Inactive Data Sources in DPM with PowerShell.


By Steven Jordan on 4/15/2014.

There are times when the DPM console GUI cannot remove its inactive data sources.  This PowerShell script removes all inactive data from DPM.  Choose between inactive disk or tape based data sources.

Removeinactivedatasource.ps1:

 

param([string] $DPMServerName, [string] $RemoveOption)

function Usage()
{
 write-host
     write-host "Usage::"
 write-host "Remove-InactiveDatasource.ps1 -DPMServerName [DPMServername] -RemoveOption [Remove Options]"
 write-host
 write-host "Run 'Remove-InactiveDatasource.ps1 -detailed' for detailed help"
 write-host
 write-host
}

if(("-?","-help") -contains $args[0])
{
 Usage
 exit 0
}

if(("-detailed") -contains $args[0])
{
 write-host
 write-host "Detailed Help :  Use this script to remove inactive datasources on disk or tape or both"
 write-host "Valid inputs of RemoveOption"
 write-host "OnDisk : Removes all inactive datasources on Disk only"
 write-host "OnTape : Removes all inactive datasources on Tape only"
 write-host "OnBoth : Removes all inactive datasources on both Disk and Tape"
 write-host
 write-host
 exit 0
}

if(!$DPMServerName)
{
     $DPMServerName = read-host "DPMServerName:"
}
$dpmServer = Connect-DPMServer $DPMServerName
if (!$dpmServer)
{
    write-Error "Failed To Connect To DPM Server::$DPMServerName"
    exit 1
}

$dsList = get-datasource $dpmservername
if (!$dsList -or ($dsList.Count -eq 0) )
{
    write-verbose   "No Datasources found"
    disconnect-dpmserver $dpmservername
    exit 2
}


if(!$RemoveOption)
{
 $RemoveOption = read-host "RemoveOption:"
}
if($RemoveOption)
{
 if ("ONDISK" -eq $RemoveOption)
 {
  $RemoveOption = "OnDisk"
 }
 elseIf ("ONTAPE" -eq $RemoveOption)
 {
  $RemoveOption = "OnTape"
 }
 elseIf("ONBOTH" -eq $RemoveOption)
 {
  $RemoveOption = "OnBoth"
 }
 else
 {
  write-Error "Invalid Value::$RemoveOption For Parameter -RemoveOption[OnDisk/OnTape/OnBoth]"
  Disconnect-dpmserver
  exit 1
 }
}
else
{
 Usage
 Disconnect-dpmserver
 exit 1
}

foreach($ds in $dsList)
{
 if($RemoveOption -eq "OnDisk" -and 
            ($ds.InactiveProtectionStatus -eq [Microsoft.Internal.EnterpriseStorage.Dls.UI.ObjectModel.OMCommon.InactiveProtection]::Disk -or
             $ds.InactiveProtectionStatus -eq [Microsoft.Internal.EnterpriseStorage.Dls.UI.ObjectModel.OMCommon.InactiveProtection]::DiskAndTape)
      )
 {
  write-host "Removing inactive Disk protection of " $ds.Name
  $confirm = read-host "Confirm(y/n):"
  if($confirm -eq "y")
  {
   Remove-DatasourceReplica -Datasource $ds -Disk
   write-host "Inactive disk protection for " $ds.Name " removed" 
  }
 }

 if($RemoveOption -eq "OnTape" -and 
            ($ds.InactiveProtectionStatus -eq [Microsoft.Internal.EnterpriseStorage.Dls.UI.ObjectModel.OMCommon.InactiveProtection]::Tape -or
             $ds.InactiveProtectionStatus -eq [Microsoft.Internal.EnterpriseStorage.Dls.UI.ObjectModel.OMCommon.InactiveProtection]::DiskAndTape)
      )
 {
  write-host "Removing inactive Tape protection of " $ds.Name
  $confirm = read-host "Confirm(y/n):"
  if($confirm -eq "y")
  {
   Remove-DatasourceReplica -Datasource $ds -Tape
   write-host "Inactive tape protection for " $ds.Name " removed" 
  }  
 }

 if($RemoveOption -eq "OnBoth" -and 
          $ds.InactiveProtectionStatus -ne [Microsoft.Internal.EnterpriseStorage.Dls.UI.ObjectModel.OMCommon.InactiveProtection]::None)
 {
  write-host "Removing inactive Disk and Tape protection of " $ds.Name
  $confirm = read-host "Confirm(y/n):"
  if($confirm -eq "y")
  {
   if($ds.InactiveProtectionStatus -eq [Microsoft.Internal.EnterpriseStorage.Dls.UI.ObjectModel.OMCommon.InactiveProtection]::Disk) 
   {
    Remove-DatasourceReplica -Datasource $ds -Disk
   }
   elseif($ds.InactiveProtectionStatus -eq [Microsoft.Internal.EnterpriseStorage.Dls.UI.ObjectModel.OMCommon.InactiveProtection]::Tape)
   {
    Remove-DatasourceReplica -Datasource $ds -Tape
   }
   else
   {
    Remove-DatasourceReplica -Datasource $ds -Disk
    Remove-DatasourceReplica -Datasource $ds -Tape
   }
   write-host "Inactive protection for " $ds.Name " removed" 
  }  
 }
}

Disconnect-dpmserver

PruneVSS.ps1 Remove Expired DPM Recovery Points.

By Steven Jordan on April 15th, 2014.

There are times when DPM fails to remove expired recovery points.  PruneVSS.ps1 can remove excessive disk (i.e., not tape) based recovery points.


#Author : Ruud Baars
#Date : 11/09/2008 #Edited : 11/15/2012 By: Wilson S.
#edited : 11:27:2012 By: Mike J.
#Edited : 3/25/2014 By: Steven J.
# $VerbosePreference = "Continue"
# NOTE: Update script to only remove recovery points on Disk. Recovery points removed will be from the oldest one up to the date
# entered by the user while the script is running
#deletes all recovery points before 'now' on selected data source. $version="V4.7"
$ErrorActionPreference = "silentlycontinue"
add-pssnapin sqlservercmdletsnapin100
Add-PSSnapin -Name Microsoft.DataProtectionManager.PowerShell
#display RP's to delete and ask to continue.
#Check & wait data source to be idle else removal may fail (in Mojito filter on 'intent' to see the error)
#Fixed prune default and logfile name and some logging lines (concatenate question + answer)
#Check dependent recovery points do not pass BEFORE date and adjust selection to not select those ($reselect)
#--- Fixed reselect logic to keep adjusting reselect for as long as older than BEFORE date
#--- Fixed post removal rechecking logic to match what is done so far (was still geared to old logic)
#--- Modified to remove making RP and ask for pruning, fixed logic for removal rechecking logic
$MB=1024*1024
$logfile="DPMdeleteRP.LOG"
$wait=10
#seconds $confirmpreference = "None"
function Show_help { cls $l="=" * 79 write-host $l -foregroundcolor magenta write-host -nonewline "`t<<<" -foregroundcolor white write-host -nonewline " DANGEROUS :: MAY DELETE MANY RECOVERY POINTS " -foregroundcolor red write-host ">>>" -foregroundcolor white write-host $l -foregroundcolor magenta write-host "Version: $version" -foregroundcolor cyan write-host "A: User Selects data source to remove recovery points for" -foregroundcolor green write-host "B: User enters date / time (using 24hr clock) to Delete recovery points" -foregroundcolor green write-host "C: User Confirms deletion after list of recovery points to be deleted is displayed." -foregroundcolor green write-host "Appending to log file $logfile`n" -foregroundcolor white write-host "User Accepts all responsibilities by entering a data source or just pressing [Enter] " -foregroundcolor white -backgroundcolor blue } "**********************************" >> $logfile "Version $version" >> $logfile get-date >> $logfile show_help $DPMservername=&"hostname" "Selected DPM server = $DPMservername" >> $logfile write-host "`nConnnecting to DPM server retrieving data source list...`n" -foregroundcolor green $pglist = @(Get-ProtectionGroup $DPMservername) # WILSON - Created PGlist as array in case we have a single protection group. $ds=@() $tapes=$null $count = 0 $dscount = 0 foreach ($count in 0..($pglist.count - 1)) { # write-host $pglist[$count].friendlyname $ds += @(get-datasource $pglist[$count]) # WILSON - Created DS as array in case we have a single protection group. # write-host $ds # write-host $count -foreground yellow } if ( Get-Datasource $DPMservername -inactive) {$ds += Get-Datasource $DPMservername -inactive} $i=0 write-host "Index Protection Group Computer Path" write-host "---------------------------------------------------------------------------------" foreach ($l in $ds) { "[{0,3}] {1,-20} {2,-20} {3}" -f $i, $l.ProtectionGroupName, $l.psinfo.netbiosname, $l.logicalpath $i++ } $DSname=read-host "`nEnter a data source index from list above - Note co-located datasources on same replica will be effected" if (!$DSname) { write-host "No datasource selected `n" -foregroundcolor yellow "Aborted on Datasource name" >> $logfile exit 0 } $DSselected=$ds[$DSname] if (!$DSselected) { write-host "No datasource selected `n" -foregroundcolor yellow "Aborted on Datasource name" >> $logfile exit 0 } $rp=get-recoverypoint $DS[$dsname] $rp # $DoTape=read-host "`nDo you want to remove when recovery points are on tape ? [y/N]" # "Remove tape recovery point = $DoTape" >> $logfile write-host "`nCollecting recoverypoint information for datasource $DSselected.name" -foregroundcolor green if ($DSselected.ShadowCopyUsedspace -gt 0) { while ($DSSelected.TotalRecoveryPoints -eq 0) { # "still 0" } #this is on disk $oldShadowUsage=[math]::round($DSselected.ShadowCopyUsedspace/$MB,1) $line=("Total recoverypoint usage {0} MB on DISK in {1} recovery points" -f $oldShadowUsage ,$DSselected.TotalRecoveryPoints ) $line >> $logfile write-host $line`n -foregroundcolor white } #this is on tape #$trptot=0 #$tp= Get-RecoveryPoint($dsselected) | where {($_.Datalocation -eq "Media")} #foreach ($trp in $tp) {$trptot += $trp.size } #if ($trptot -gt 0 ) #{ # $line=("Total recoverypoint usage {0} MB on TAPE in {1} recovery points" -f ($trptot/$MB) ,$DSselected.TotalRecoveryPoints ) # $line >> $logfile # write-host $line`n -foregroundcolor white #} [datetime]$afterdate="1/1/1980" #$answer=read-host "`nDo you want to delete recovery points from the beginning [Y/n]" #if ($answer -eq "n" ) #{ # [datetime]$afterdate=read-host "Delete recovery points AFTER date [MM/DD/YYYY hh:mm]" #} [datetime]$enddate=read-host "Delete ALL Disk based recovery points BEFORE and Including date/time entered [MM/DD/YYYY hh:mm]" "Deleting recovery points until $enddate" >>$logfile write-host "Deleting recovery points until and $enddate" -foregroundcolor yellow $rp=get-recoverypoint $DSselected if ($DoTape -ne "y" ) { $RPselected=$rp | where {($_.representedpointintime -le $enddate) -and ($_.Isincremental -eq $FALSE)-and ($_.DataLocation -eq "Disk")} } else { $RPselected=$rp | where {($_.representedpointintime -le $enddate) -and ($_.Isincremental -eq $FALSE)} } if (!$RPselected) { write-host "No recovery points found!" -foregroundcolor yellow "No recovery points found, aborting...!" >> $logfile exit 0 } $reselect = $enddate $adjustflag = $false foreach ($onerp in $RPselected) { $rtime=[string]$onerp.representedpointintime $rsize=[math]::round(($onerp.size/$MB),1) $line= "Found {0}, RP size= {1} MB (If 0 MB, co-located datasource cannot be computed), Incremental={2} "-f $rtime, $rsize,$onerp.Isincremental $line >> $logfile write-host "$line" -foregroundcolor yellow # #Get dependent rp's for data source # $allRPtbd=$DSselected.GetAllRecoveryPointsToBeDeleted($onerp) foreach ($oneDrp in $allRPtbd) { if ($oneDrp.IsIncremental -eq $FALSE) {continue} $rtime=[string]$oneDrp.representedpointintime $rsize=[math]::round(($oneDrp.size/$MB),1) $line= ("`t...is dependancy for {0} size {1} `tIncremental={2}" -f $rtime, $rsize, $oneDrp.Isincremental) $line >> $logfile if ($oneDrp.representedpointintime -ge $enddate) { #stick to latest full ($oneDrp = dependents, $onerp = full) $adjustflag = $true $reselect = $onerp.representedpointintime "<< Dependents newer than BEFORE date >>>" >> $logfile Write-Host -nonewline "`t <<< later than BEFORE date >>>" -foregroundcolor white -backgroundcolor red write-host "$line" -foregroundcolor yellow } else { #Ok, include current latest incremental $reselect = $oneDrp.representedpointintime write-host "$line" -foregroundcolor yellow } } } if ($reselect -lt $oneDrp.representedpointintime) { #we adjusted further backward than latest incremental within selection $reselect = $rtime $line = "Adjusted BEFORE date to be $reselect to include dependents to $enddate" $line >> $logfile Write-Host $line -foregroundcolor white -backgroundcolor blue } $line="`n<<< SECOND TO LAST CHANCE TO ABORT - ONE MORE PROMPT TO CONFIRM. >>>" write-host $line -foregroundcolor white -backgroundcolor blue $line >> $logfile $line="Above recovery points within adjusted range will be permanently deleted !!!" write-host $line -foregroundcolor red $line >> $logfile $line="These RP's include dependent recovery points and may contain co-located datasource(s)" write-host $line -foregroundcolor red $line >> $logfile $line="Data source activity = " + $DSselected.Activity $line >> $logfile write-host $line -foregroundcolor white $DoDelete="" while (($DoDelete -ne "N" ) -and ($DoDelete -ne "Y")) { $line="Continue with deletion (must answer) Y/N? " write-host $line -foregroundcolor white $DoDelete=read-host $line = $line + $DoDelete $line >> $logfile } if (!$DSselected.Activity -eq "Idle") { $line="Data source not idle, do you want to wait Y/N ? " write-host $line -foregroundcolor yellow $Y=read-host $line = $line + $Y $line >> $logfile if ($Y -ieq "Y") { Write-Host "Waiting for data source to become idle..." -foregroundcolor green while ($DSselected.Activity -ne "Idle") { ("Waiting {0} seconds" -f $wait) >>$logfile Write-Host -NoNewline "..." -ForegroundColor blue start-sleep -s $wait } } } if ($DoDelete -eq "Y") { foreach ($onerp in $RPselected) { #reselect is adjusted to safe range relative to what was requested #--- if adjustflag not set then all up to including else only older because we must keep the full if ((($onerp.representedpointintime -le $reselect) -and ($adjustflag -eq $false)) -or ($onerp.representedpointintime -lt $reselect)) { $rtime=[string]$onerp.representedpointintime write-host `n$line -foregroundcolor red $line >>$logfile if (($onerp ) -and ($onerp.IsIncremental -eq $FALSE)) { remove-recoverypoint -RecoveryPoint $onerp -recurse -force -confirm:$False} # >> $logfile} $line =("---`nDeleting recoverypoint -> " + $rtime) $line >>$logfile } } } "All Done!" >> $logfile write-host "`nAll Done!`n`n" -foregroundcolor white $line="Do you want to View DPMdeleteRP.LOG file Y/N ? " write-host $line -foregroundcolor white $Y=read-host $line = $line + $Y $line >> $logfile if ($Y -ieq "Y") { Notepad DPMdeleteRP.LOG}

Sign PowerShell scripts with free code signing certificate!


Last updated  September 13th, 2013 by Steven Jordan


Problem:  Incorporate code signing scripts in PowerShell.

PowerShell script execution policy set to unrestricted is poor practice; don't do it!  A compromised computer is especially dangerous with unrestricted PowerShell scripts.  Exceptions may include one time use but don't forget to change the execution policy back to to restricted.

Solution:
  1. Generate a free code signing certificate using Windows SDK (free download from Microsoft).

    Global PKI code signing certificates are expensive. Unless you plan to distribute your PowerShell script outside your organization use of a code signing certificate from a public CA is not necessary.
  2. Incorporate the self generated code signing certificate for all PowerShell scripts.
  3. Change PowerShell execution policy to AllSigned.
  4. Import the self generated code signing certificate to the Trusted Root Certification Authorities using the Certificate manager or distribute to domain resources with group policy.    

All PowerShell scripts must include a code signing certificate to maintain server integrity.  All self generated code signing certificates must be considered a Trusted Root to maintain functionality.

Please visit the Kreelbits Blog  for detailed instructions on how to implement the above steps.  Great work +Scott Kreel!


Exchange 2010 SMTP Logs PowerShell Script


Script to export the Exchange 2010 SMTP logs into an easy to "read and work with" Excel file:

1.  Load Exchange Management Shell:

add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010

2.  Export message tracking results to CSV:

get-messagetrackinglog -resultsize unlimited -Sender "user@sender.com" -MessageSubject "This is where the subject goes" | Select Sender,{$_.Recipients},{$_.RecipientStatus},MessageSubject,TimeStamp, EventId, Source, SourceContext,MessageId,InternalMessageId,ClientIP,ClientHostName,ServerIP,ServerHostName,ConnectorId,TotalBytes,RecipientCount,RelatedRecipientAddress,Reference,ReturnPath,MessageInfo | Export-Csv .\MessageTrackingLog.csv 

Last updated  June 13th, 2013 by Steven Jordan.




DPM 2010 Free Tape with Power Shell Update


This is an update to a previous post on how to mark a tape as "free".  Because of limitations with the DPM GUI a Power Shell script must be run to free the tapes associated with protection groups.

I ran into a problem specifying the location of the tape when using the previous script.  The PS script below sidesteps the location problem.

N. B. Here is the correct format to run the script:
PS C:\scripts> .\free2.ps1 -dpmservername dpserver01 -LibraryName "Hewlett Packard DAT72 drive"
Here is the script:

    param ([string] $DPMServerName, [string] $LibraryName)
    if(("-?","-help") -contains $args[0])
    {
        Write-Host "Usage: ForceFree-Tape.ps1 [[-DPMServerName] ] [-LibraryName]  
        Write-Host "Example: Force-FreeTape.ps1 -Dpmservername SDPM01 -LibraryName   My library
        exit 0
    }
    if (!$DPMServerName)
    {
        $DPMServerName = Read-Host "DPM server name: "
        if (!$DPMServerName)
        {
            Write-Error "Dpm server name not specified."
            exit 1
        }
    }
    if (!$LibraryName)
    {
        $LibraryName = Read-Host "Library name: "
        if (!$LibraryName)
        {
            Write-Error "Library name not specified."
            exit 1
        }
    }
    
    
    if (!(Connect-DPMServer $DPMServerName))
    {
        Write-Error "Failed to connect To DPM server $DPMServerName"
        exit 1
    }
    $library = Get-DPMLibrary $DPMServerName | where {$_.UserFriendlyName -eq $LibraryName}
    write-host "Getting library..."
    if (!$library)
    {
        Write-Error "Failed to find library with user friendly name $LibraryName"
        exit 1
    }
    foreach ($media in @(Get-Tape -DPMLibrary $library))
    {
    write-host "Getting media..."
    
            if ($media -is [Microsoft.Internal.EnterpriseStorage.Dls.UI.ObjectModel.LibraryManagement.ArchiveMedia])
            {
                foreach ($rp in @(Get-RecoveryPoint -Tape $media))
                {
      write-host "Getting recovery point..."
                    Get-RecoveryPoint -Datasource $rp.Datasource | Out-Null
                    Write-Verbose "Removing recovery point created at $($rp.RepresentedPointInTime) for tape in $($media.Location)."
                    write-host "Force removing recovery point..."
      Remove-RecoveryPoint -RecoveryPoint $rp -ForceDeletion -Confirm:$false
                }
                Write-Verbose "Setting tape in $($media.Location) as free."
         write-host "Setting tape as free..."
                Set-Tape -Tape $media -Free
            }
            else
            {
                Write-Error "The tape in $($media.Location) is a cleaner tape."
            }
       
    
    }

FIX: Selected tapes cannot be erased.

*I posted an update to this script here.

Problem:  I wanted to use a DAT 72 tape that previously had data written to it.  When trying to free the tape I received the following error:
The selected tapes cannot be erased because they belong to protection groups
Solution:  The tape cannot be released via DPM 2010 GUI.  I found the following PowerShell script that allowed me to use the tape:

----------------------------- Start of Script --------------------------------

param ([string$DPMServerName, [string$LibraryName, [string[]] $TapeLocationList)

if(("-?","-help"-contains $Args[0])
{
Write-Host "Usage: ForceFree-Tape.ps1 [[-DPMServerName] ] [-LibraryName] [-TapeLocationList] "Write-Host "Example: Force-FreeTape.ps1 -LibraryName "My library" -TapeLocationList Slot-1, Slot-7"exit 0
}
if (!$DPMServerName)
{
$DPMServerName = Read-Host "DPM server name: "if (!$DPMServerName)
{
Write-Error "Dpm server name not specified."exit 1
}
}if (!(Connect-DPMServer $DPMServerName))
{
Write-Error "Failed to connect To DPM server $DPMServerName"exit 1
}
$library = @(Get-DPMLibrary $DPMServerName )if ($library.count -eq 0)
{
Write-Error "Failed to find library with user friendly name $LibraryName"exit 1
}
if (!$LibraryName)
{
$library | foreach {$_.userfriendlyname}$LibraryName = Read-Host "Library name (cut & paste from above): "if (!$LibraryName)
{
Write-Error "Library name not specified."exit 1
}
}
if (!$TapeLocationList)
{
$tmp = Read-Host "Tape location: "$TapeLocationList=$tmp.split(",")write-host "Processing this slot list..."$TapeLocationListif (!$TapeLocationList)
{
Write-Error "Tape location not specified."exit 1
}
}
foreach ($media in @(Get-Tape -DPMLibrary $library))
{
if ($TapeLocationList -contains $media.Location)
{
if ($media -is [Microsoft.Internal.EnterpriseStorage.Dls.UI.ObjectModel.LibraryManagement.ArchiveMedia])
{
foreach ($rp in @(Get-RecoveryPoint -Tape $media))
{
Get-RecoveryPoint -Datasource $rp.Datasource | Out-NullWrite-Verbose "Removing recovery point created at $($rp.RepresentedPointInTime) for tape in $($media.Location)."Remove-RecoveryPoint -RecoveryPoint $rp -ForceDeletion -Confirm:$false}
Write-Verbose "Setting tape in $($media.Location) as free."Set-Tape -Tape $media -Free}else{Write-Error "The tape in $($media.Location) is a cleaner tape."}
}
}

----------------------------- End of Script ---------------------------------

Managed Service Accounts

A common issue that pops up is deciding which service account to use for a specific application or service .  What is the best practice for creating and using service accounts to operate Windows services and applications?

Microsoft has resolved this issue with the MSA (Managed Service Account) in Windows 2008 R2.  


     1.  Create the MSA in AD using the AD nodule for PowerShell:

          New-ADServiceAccount -Name [MSA account name] -Enabled $true

   2. Associate the MSA to a computer:

          Add-ADComputerServiceAccount -Identity [AD Computer Account] -ServiceAccount

     3.  Install the MSA on the associated computer:


          Install-ADServiceAccount -Identity [MSA Account]

     4.   Associate the new MSA with the service.

          Services.MSC → Edit Service Properties
           → Edit "Log On" Tab.


     * Use domain\MSA format
     * Do no enter a password.
   

http://technet.microsoft.com/en-us/library/dd548356(WS.10).aspx


http://blogs.technet.com/b/askds/archive/2009/09/10/managed-service-accounts-understanding-implementing-best-practices-and-troubleshooting.aspx


DPM PowerShell Consitency Check Script

Last updated  March 26th, 2014 by Steven Jordan

Takeaway:  PowerShell script  to run the #consistency check on any every inconsistent replica in DPM.  

I plan to schedule and automate this to cut back on the crazy amount of alerts DPM creates.  This should also cut down on the manual maintenance.


  1. Associate the DPM server:
  2.   $pg = Get-ProtectionGroup

  3. Start the consistency check:
foreach ($pgi in $pg) { $ds = get-datasource $pgi; foreach ($dsi in $ds) { if ($dsi.State -eq 'Invalid') { Start-DatasourceConsistencyCheck $dsi | out-null; $dsi.ProductionServerName + " :: " + $dsi.DisplayPath } } }
Reference:  http://www.avianwaves.com/Blog/default.aspx?id=195

O #Scripts #PowerShell O