Copy windows features from a server to another

Sometimes you want to create the (almost) same server where you do not yet Chef or CF or some sort of DSC. The best resort is to use what you have: get-windowsfeature

Imagine you want to configure Server B from Server A and obviously those are microsoft windows servers…

#On server A
#export features
> Get-WindowsFeature | ? { $_.Installed -AND $_.SubFeatures.Count -eq 0 } | Export-Clixml .\serverA.xml
#copy the feature file over
> cp .\serverA.xml ‘\\serverB\c$\Files’

#On server B
PS C:\Files> ls
Directory: C:\Files
Mode LastWriteTime Length Name
—- ————- —— —-
-a—- 6/8/2017 4:15 PM 510824 ServerA.xml
PS C:\Files> Import-Module Servermanager
PS C:\Files> Import-Clixml .\ServerA.xml | Add-WindowsFeature
Success Restart Needed Exit Code Feature Result
——- ————– ——— ————–
True Yes SuccessRest… {Application Server, .NET Framework 4.5, W…
WARNING: You must restart this server to finish the installation process.

Voila, another posh timesaver.

Advertisements

Exchange Message Tracking Statistics for Zabbix

I surely missing something but somehow I could not find a way to easily retrieve statistics of Sent and Received messages from Exchange 2013 (SP1 with DAG). I first looked into the performance counters but I could not make sense of all of the MSExchangeTransport – or too lazy to research them up.

typeperf -qx | findstr /ic:MSExchangeTransport

And usually if I am tracking some email flooding or prior to investigating the queues, I go use the get-messagetrackinglog. And so I create a short script to gather the list of the last X minutes of messages, count them, make them available and them to zabbix using zabbix_sender.

So it goes like this:


#import snapin
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010

#list of transport servers
$hts = "EchangeTransport1","EchangeTransport2"
#start one Hour ago from now
$start = (get-date).AddMinutes(-30)
$end = (get-date)
#get all logs
$logs = $hts |% {get-messagetrackinglog -start $start -end $end -server $_ -resultsize unlimited}
#clear stats
$stats = ""| select sent,received
#count Deliver and Send
$logs |% {
if ($_.eventid -eq "Deliver"){[int]$stats.received += 1}
if ($_.eventid -eq "Send"){[int]$stats.sent+= 1}
}
#Display results for debug and info, comment or remove if not needed
$stats | ft -auto > LastCount.log
get-date >> LastCount.log

#cannot run the above using zabbix/system account on exchange
#use zabbix_sender
C:\zabbix\bin\win64\zabbix_sender.exe -z zabbixIP  -s $hts -k Stats.RxMessageCount -o $stats.received
C:\zabbix\bin\win64\zabbix_sender.exe -z zabbixIP -s $hts -k Stats.TxMessageCount -o $stats.sent

It is short and easy but that there some things to do in Zabbix and it can store the sent values, as per above Stats.RxMessageCount and Stats.TxMessageCount.

I went into Zabbix>Configuration>Templates to edit the template I had created to keep all of the Exchange things I monitor. Select the item screen and clicked that “Create Item” button.

msg1

Then the most important is the Type which must be Zabbix Trapper, the rest is up to you.I also chosen a “Unit” and created a new application “Exchange 2013 Statistics”.

msg2

Once the item is create, do the same for the other value. Altogether you’ll end up with 2 new items under the template.

Provided this template is assigned to your exchange host you are running the above script from, the values will be fed to Zabbix accordingly.

I actually set up a scheduled task that matches the timing and now I have some trending of the Sent and Received messages as per the Message Tracking Logs – Yeah it includes the HealthMonitor traffic, I know.

Additionally and once you have a baseline, you can also create a trigger based on the value received.

Managing Certificates using Powershell

Because of my recent work with ADFS I was looking for a way to automate most of the certificate configuration by scripts. The usual run-books I write would usually include the use of the mmc and a bunch of screenshot to accompany them.

The answer is that powershell management for Certificates is there and here are some examples:

 

#Powershell exposes certs under cert:\
PS C:\> Get-PSDrive
Name Used (GB) Free (GB) Provider Root CurrentLocation
—- ——— ——— ——– —- —————
A FileSystem A:\
Alias Alias
C 14.37 45.29 FileSystem C:\
Cert Certificate \
D FileSystem D:\
Env Environment
Function Function
HKCU Registry HKEY_CURRENT_USER
HKLM Registry HKEY_LOCAL_MACHINE
Variable Variable
WSMan WSMan
PS C:\> cd cert:
PS Cert:\> dir localmachine
Name : TrustedPublisher
Name : ClientAuthIssuer
Name : Remote Desktop
Name : Root
Name : TrustedDevices
Name : CA
Name : REQUEST
Name : AuthRoot
Name : TrustedPeople
Name : My
Name : SmartCardRoot
Name : Trust
Name : Disallowed
Name : AdfsTrustedDevices

#Browsing through the stores is pretty intuitive
PS Cert:\> dir Cert:\LocalMachine\My
Directory: Microsoft.PowerShell.Security\Certificate::LocalMachine\My
Thumbprint Subject
———- ——-
E31234DEF282437D167A64FD812342B650C20B42 CN=XXXXa
8912343319B07131C8FD1234E250DC67CBE08D7A CN=XXXX
69AD2C21912340919D186503631234A6F0BE9F7F CN=*.xxx.ca,XXX..

#Exporting a cert is something a little less intuitive
PS Cert:\> $ExportCert = dir Cert:\LocalMachine\Root | where {$_.Thumbprint -eq “892F212349B07131C12347F8E250DC67CBE08D7
A”}
PS Cert:\> $ExportCryp = [System.Security.Cryptography.X509Certificates.X509ContentType]::pfx
PS Cert:\> $ExportKey = ‘pww$@’
PS Cert:\> $ExportPFX = $ExportCert.Export($ExportCryp, $ExportKey)
PS Cert:\> [system.IO.file]::WriteAllBytes(“D:\Temp\CertToExportPFXFile.PFX”, $ExportPFX)

#same mess for importing
# Define The Cert File To Import
$CertFileToImport = “D:\Temp\CertToImportPFXFile.PFX”
# Define The Password That Protects The Private Key
$PrivateKeyPassword = ‘Pa$$w0rd’
# Target The Cert That Needs To Be Imported
$CertToImport = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $CertFileToImport,$PrivateKeyPassword
# Define The Scope And Certificate Store Within That Scope To Import The Certificate Into
# Available Cert Store Scopes are “LocalMachine” or “CurrentUser”
$CertStoreScope = “LocalMachine”
# For Available Cert Store Names See Figure 5 (Depends On Cert Store Scope)
$CertStoreName = “My”
$CertStore = New-Object System.Security.Cryptography.X509Certificates.X509Store $CertStoreName, $CertStoreScope
# Import The Targeted Certificate Into The Specified Cert Store Name Of The Specified Cert Store Scope
$CertStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
$CertStore.Add($CertToImport)
$CertStore.Close()

For import/export, I’d recommend using code from here: http://poshcode.org/?lang=&q=import%2Bcertificate

 

Get a List of All Useless Group Policy Objects

I have another problem today. The problem is that the previous Group Policy administrator had no strategy. I have been the chosen one to clean up our Group Policy strategy. As a result there are bunch of Group Policy objects (GPOs) that go nowhere or do nothing.

I had noticed this powershell guys article, but it looked like utterly complex.

import-module grouppolicy 
 
function IsNotLinked($xmldata){ 
    If ($xmldata.GPO.LinksTo -eq $null) { 
        Return $true 
    } 
     
    Return $false 
} 

Function IsEmpty($xmldata){
    If ($xmldata.GPO.Computer.VersionDirectory -eq 0 -and $xmldata.GPO.User.VersionDirectory -eq 0) { 
        Return $true 
    } 
     
    Return $false 
}
 
$unlinkedGPOs = @() 
$emptyGPOs = @() 

#Search for NotLinked GPOs
Get-GPO -All | ForEach { $gpo = $_ ; $_ | Get-GPOReport -ReportType xml | ForEach { If(IsNotLinked([xml]$_)){$unlinkedGPOs += $gpo} }} 
 
If ($unlinkedGPOs.Count -eq 0) { 
    "No Unlinked GPO's Found" 
} 
Else{
	$unlinkedGPOs | Select DisplayName,ID | ft 
	$unlinkedGPOs | backup-GPO -path S:\ActiveDirectory\GPOBackups | select DisplayName,GpoID, BackupDirectory | ft
	$unlinkedGPOs | remove-gpo -Confirm
}

#Search for Empty GPOs
Get-GPO -All | ForEach { $gpo = $_ ; $_ | Get-GPOReport -ReportType xml | ForEach { If(IsEmpty([xml]$_)){$emptyGPOs += $gpo} }} 

If ($emptyGPOs.Count -eq 0) { 
    "No Empty GPO's Found" 
} 
Else{
	$emptyGPOs | Select DisplayName,ID | ft 
	$emptyGPOs | backup-GPO -path S:\ActiveDirectory\GPOBackups | select DisplayName,GpoID, BackupDirectory | ft
	$emptyGPOs | remove-gpo -Confirm
}

It is to be used simply and get some output list – or uncomment the warranty info and backup and then delete the nasty stuff.

DisplayName                                                 Id
———–                                                 —
Disable Outlook Cache                                       7aca484c-ebcd-4779-9bc8-b2fb8e7302d1
Turn Outlook Junk Mail Filter Off                           de14544c-39be-444f-ac53-089ca0bc65a8
Microsoft Office Trust Centre                               ed6fb632-fdd2-4718-96b0-b3981b4145bd

DisplayName                                                 Id
———–                                                 —
Portal Home page — mandatory                               bbc9efe7-05c3-4187-92ac-948772f50bf8

Please note that GPO backup ID during the Backup-gpo is not the GPOID!

Import PST to mailboxes – Exchange 2013

For this recipe you will need:

  • a pst archive file stored on a UNC accessible location
    New-ManagementRoleAssignment –Role "Mailbox Import Export" –User Administrator
  • be granted the “mailbox import export” management role

when all this is gather, the import is pretty simple.

To import the pst file into a specific mailbox do:

[PS] C:\>New-MailboxImportRequest -FilePath \\SERVER\share$someone.pst -Mailbox someone

you can also import a pst to someone else mailbox into a specific folder:

[PS] C:\>New-MailboxImportRequest -FilePath \\SERVER\share$someone.pst -Mailbox someoneelse -TargetRootFolder "ImportedMailbox from someones PST" 

Once submitted you can follow the request status with this command:

[PS] C:\>Get-MailboxImportRequest -Mailbox someone| Get-MailboxImportRequestStatistics

Name                                   StatusDetail              TargetAlias                           PercentComplete
----                                   ------------              -----------                           ---------------
MailboxImport                          CopyingMessages           someone            92

Removing any switch to the get-mailboximportrequest will show status for all requests.

Shall it fail and you need further information, you shall use the following to examin the reason and pipe it to a file for something more legible:

[PS] C:\>Get-MailboxImportRequest -Mailbox someone | Get-MailboxImportRequestStatistics -IncludeReport | select message

Message

-------

Error: This mailbox exceeded the maximum number of corrupt or missing items that were specified for this request.

Lastly, you can clean up the requests using this one. Feel free to filter by status as needed:

[PS] C:\>Get-MailboxImportRequest | where {$_.status -eq "Completed"} | Remove-MailboxImportRequest

Comparer l’appartenance des groupes AD entre 2 comptes

Ce document décrit le script qui permet de comparer 2 comptes AD afin de calquer les appartenances.

Pre-requis
exécution des scripts powershell
droit de modification de comptes AD

Le script

Param(
<pre>    $sourceacc, 
    $destacc, 
    [switch]$noconfirm 
) 
 
# Checks if both accounts are provided as an argument, otherwise prompts for input 
if (-not $sourceacc) { $sourceacc = read-host "Please input source user name, the user the rights will be read from" } 
if (-not $destacc) { $destacc = read-host "Please input destination user name, the user which will be added to the groups of the source user" } 
 
# Retrieves the group membership for both accounts 
$sourcemember = get-aduser -filter {samaccountname -eq $sourceacc} -property memberof | select memberof 
$destmember = get-aduser -filter {samaccountname -eq $destacc} -property memberof | select memberof 
 
# Checks if accounts have group membership, if no group membership is found for either account script will exit 
if ($sourcemember -eq $null) {"Source user not found";return} 
if ($destmember -eq $null) {"Destination user not found";return} 
 
# Checks for differences, if no differences are found script will prompt and exit 
if (-not (compare-object $destmember.memberof $sourcemember.memberof | where-object {$_.sideindicator -eq '=>'})) {write-host "No difference between $sourceacc & $destacc groupmembership found. $destacc will not be added to any additional groups.";return} 
 
# Routine that changes group membership and displays output to prompt 
compare-object $destmember.memberof $sourcemember.memberof | where-object {$_.sideindicator -eq '=>'} | 
    select -expand inputobject | foreach {write-host "$destacc will be added to:"([regex]::split($_,'^CN=|,OU=.+$'))[1]} 
 
# If no confirmation parameter is set no confirmation is required, otherwise script will prompt for confirmation 
if ($noconfirm)    { 
    compare-object $destmember.memberof $sourcemember.memberof | where-object {$_.sideindicator -eq '=>'} |  
        select -expand inputobject | foreach {add-adgroupmember "$_" $destacc} 
} 
 
else { 
    do{ 
        $UserInput = Read-Host "Are you sure you wish to add $destacc to these groups?`n[Y]es, [N]o or e[X]it" 
        if (("Y","yes","n","no","X","exit") -notcontains $UserInput) { 
            $UserInput = $null 
            Write-Warning "Please input correct value" 
        } 
        if (("X","exit","N","no") -contains $UserInput) { 
            Write-Host "No changes made, exiting..." 
            exit 
        }      
        if (("Y","yes") -contains $UserInput) { 
            compare-object $destmember.memberof $sourcemember.memberof | where-object {$_.sideindicator -eq '=>'} |  
                select -expand inputobject | foreach {add-adgroupmember "$_" $destacc} 
        } 
    } 
    until ($UserInput -ne $null) 
}

Utilisation du script

activer le module ActiveDirectory

Import-Module activedirectory

lancer le script

.\Compare-ADuserAddGroup.ps1
Please input source user name, the user the rights will be read from: user1
Please input destination user name, the user which will be added to the groups of the source user: user2
pruban will be added to: Group ABC 1
pruban will be added to: Group ABC 2
pruban will be added to: Group ABC 36dfa920
pruban will be added to: Group ABC 43
pruban will be added to: Group ABC 42
pruban will be added to: Group ABC 45
pruban will be added to: Group ABC 543
pruban will be added to: Group ABC 45
pruban will be added to: Group ABC 34

Are you sure you wish to add user2 to these groups?
[Y]es, [N]o or e[X]it: Y

source:http://gallery.technet.microsoft.com/scriptcenter/Compare-group-membership-36dfa920

Downloading files with windows server core

I found out that the invoke-webrequest doesn’t work so well on windows core. The Internet Explorer einginre required by the ParseHtml is apparently not supported on Server Core editions of windows Servers. If you want to do web page parsing on Server Core, be sure to use the -UseBasicParsing as a parameter of the request.

This mode performs only limited parsing on the uri – images, input fields, links and raw html content.

So in order to download onto your internet connected windows Core Server, you can use

$url = "http://myfiles.com/download.msi"

$Destination=".\download.msi"

Invoke-WebRequest -uri $url -OutFile $destination 

more practically if I wanted to download a hotfix, I’d go

> iwr -Uri http://download.microsoft.com/download/F/3
/6/F365E995-0C73-48D6-B520-3FF323CA913A/Windows8.1-KB2979576-x64.msu -UseBasicParsing -OutFile .\Windows8.1-KB2979576-x64.msu

Also for some type of file you might want to use the Unblock-File powershell cmdlet.

Add EMC Storage – PowerPath Driven – on Server 2012 R2 Core or Hyper-V 2012 R2 (well core as well)

For this recipe you will need:

  • 1 LUN (setup in a storage group that holds the server)
  • 1 PowerPath (here after PP) Key
  • 1 Diskpart

First, locate your latest PP bundle and install in CLI mode.

PS C:\windows\system32&gt; etsn ptbtt-go-hv
[ptbtt-go-hv]: PS C:\&gt; ls
Directory: C:\
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        11/21/2014   2:46 PM            logs
-a---         5/15/2014   4:45 PM   92347200 EMCPower.X64.signed.5.7.SP3.b509.exe

[ptbtt-go-hv]: PS C:\&gt; EMCPower.X64.signed.5.7.SP3.b509.exe /s /v&quot;/L*v C:\logs\PPsetup.log LICENSENUM=BUPJ-XB4E-LFC3-QYPY-MM92-QDWB NO_REBOOT=1&quot;

Once finished you can log there to see if  all was successful.

[ptbtt-go-hv]: PS C:\logs&gt; Get-Content .\PPsetup.log | Select-String &quot;Installation completed successfully&quot;

MSI (s) (E4:94) [14:48:24:606]: Product: EMC PowerPath 5.7 Service Pack 3 (64bit) -- Installation completed
successfully.

Hooray? well, go play with PowerMT.exe

[ptbtt-go-hv]: PS C:\&gt; cd 'C:\Program Files\EMC\PowerPath'
[ptbtt-go-hv]: PS C:\Program Files\EMC\PowerPath&gt; ls
Directory: C:\Program Files\EMC\PowerPath
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        11/21/2014   2:47 PM            Drivers
d----        11/21/2014   2:53 PM            Logs
d----        11/21/2014   2:47 PM            x86
-a---          2/7/2013   1:08 PM      17728 db_recover.exe
-a---         11/1/2010   4:13 AM        385 db_recover.exe.intermediate.manifest
-a---        11/24/2010   2:04 AM     531512 difxapi.dll
-a---          2/7/2013   1:10 PM      49472 EmcAdminProxy.dll
-a---         5/15/2014   5:20 PM    1125184 EmcAdminSvr.exe
-a---          2/7/2013   1:12 PM     516416 EmcLicTool.exe
-a---          2/7/2013   1:13 PM      27456 EmcLicTool_CHS.dll
-a---          2/7/2013   1:14 PM      27968 EmcLicTool_DEU.dll
-a---          2/7/2013   1:15 PM      27968 EmcLicTool_ESP.dll
-a---          2/7/2013   1:15 PM      27968 EmcLicTool_FRA.dll
-a---          2/7/2013   1:16 PM      27968 EmcLicTool_ITA.dll
-a---          2/7/2013   1:17 PM      27456 EmcLicTool_JPN.dll
-a---          2/7/2013   1:17 PM      27456 EmcLicTool_KOR.dll
-a---          2/7/2013   1:18 PM      27968 EmcLicTool_PTB.dll
-a---          2/7/2013   1:20 PM      29504 emcphostid.exe
-a---          2/7/2013   1:20 PM      27968 EmcpLogMsgs.dll
-a---         5/15/2014   5:20 PM    1117504 EmcpMgmtComp.exe
-a---         5/15/2014   5:20 PM     494400 EmcPowerPathAdmin.dll
-a---         5/15/2014   5:20 PM      39232 EmcPowMon.exe
-a---          2/7/2013   1:24 PM      31552 EmcPowPN22.dll
-a---          2/7/2013   1:25 PM      21312 EmcPowRes.dll
-a---         5/15/2014   5:20 PM     869696 EmcPowSrv.exe
-a---          2/7/2013   1:26 PM      39232 EmcpPerfmonPmiPrvdr.dll
-a---          2/7/2013   1:27 PM      36160 emcpreg.exe
-a---          2/7/2013   1:28 PM      10048 EmcpSvcErr.dll
-a---          2/7/2013   1:28 PM      26432 emcp_lic_rtl.dll
-a---         5/15/2014   5:20 PM    1137472 Emcp_mpapi_rtl.dll
-a---          2/7/2013   1:31 PM      91968 emcp_mp_rtl.dll
-a---         6/10/2003  10:00 PM      43430 Emc_PowerPath_Console.msc
-a---          2/7/2013   1:33 PM    1404224 libdb51.dll
-a---         11/1/2010   4:14 AM        385 libdb51.dll.intermediate.manifest
-a---         5/15/2014   5:20 PM    1748480 Libeay32.dll
-a---         5/15/2014   5:20 PM     303424 ManagementComp_Config.exe
-ar--        11/21/2014   3:38 PM         22 mpaa.excluded
-ar--        11/21/2014   3:38 PM        244 mpaa.lams
-a---         5/15/2014   5:20 PM     332608 powermig.exe
-a---         5/15/2014   5:20 PM     270144 powermigcl.exe
-a---         5/15/2014   5:20 PM    1181504 powermt.exe
-a---        12/18/2012   6:12 PM      23639 powerpath.man
-a---         5/15/2014   5:20 PM     304448 PowMigSrvc.exe
-a---         5/15/2014   5:20 PM     222016 ppinstall.exe
-a---         5/15/2014   5:20 PM     490304 ppRemoveAll.exe
-a---          2/7/2013   1:49 PM      55104 pthreadVC2.dll
-a---         5/15/2014   5:20 PM       5279 server.pem
-a---         5/15/2014   5:20 PM     360448 Ssleay32.dll

Found powermt, let’s use it.

[ptbtt-go-hv]: PS C:\Program Files\EMC\PowerPath&gt; .\powermt.exe display dev=all
Pseudo name=harddisk1
VNX ID=APM00141276882 [TTBTT-GO-HV_SG]
Logical device ID=6006016009B03800F71D7ED4B571E411 [FSP_LUN31_SPB_6882_PTBTT-GO-HV_X_200G]
state=alive; policy=CLAROpt; queued-IOs=0
Owner: default=SP B, current=SP B       Array failover mode: 4
==============================================================================
--------------- Host ---------------   - Stor -  -- I/O Path --   -- Stats ---
###  HW Path               I/O Paths    Interf.  Mode     State   Q-IOs Errors
==============================================================================
2 port2\path0\tgt1\lun0  c2t1d0      SP A3    active   alive      0      0
2 port2\path0\tgt0\lun0  c2t0d0      SP A2    active   alive      0      0
1 port1\path0\tgt1\lun0  c1t1d0      SP B3    active   alive      0      0
1 port1\path0\tgt0\lun0  c1t0d0      SP B2    active   alive      0      0

Looks like you see your disk? Expose it to windows for storing let’s VMs – this is pretty useful for hyper-v hypervisor!

[ptbtt-go-hv]: PS C:\Program Files\EMC\PowerPath&gt; diskpart
Microsoft DiskPart version 6.3.9600
Copyright (C) 1999-2013 Microsoft Corporation.
On computer: PTBTT-GO-HV
DISKPART&gt;
[ptbtt-go-hv]: PS C:\Program Files\EMC\PowerPath&gt; exit

Sometimes powershell session don’t play nice with output redirection and things like diskpart from let you in the interactive mode. Fear not, use psexec instead and use diskpart to create that disk.

PS H:\&gt; cd .\Tools\sysinternals
PS H:\Tools\sysinternals&gt; .\psexec.exe \\ptbtt-go-hv cmd
PsExec v2.11 - Execute processes remotely
Copyright (C) 2001-2014 Mark Russinovich
Sysinternals - www.sysinternals.com
Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.
C:\Windows\system32&gt;diskpart
Microsoft DiskPart version 6.3.9600
Copyright (C) 1999-2013 Microsoft Corporation.
On computer: PTBTT-GO-HV
DISKPART&gt; list disk
Disk ###  Status         Size     Free     Dyn  Gpt
--------  -------------  -------  -------  ---  ---
Disk 0    Online          135 GB      0 B
Disk 1    Offline         200 GB   200 GB
DISKPART&gt; select disk 1
Disk 1 is now the selected disk.
DISKPART&gt; online disk
DiskPart successfully onlined the selected disk.
DISKPART&gt; list disk
Disk ###  Status         Size     Free     Dyn  Gpt
--------  -------------  -------  -------  ---  ---
Disk 0    Online          135 GB      0 B
* Disk 1    Online          200 GB   200 GB
DISKPART&gt; select disk 1
Disk 1 is now the selected disk.
DISKPART&gt; list volume
Volume ###  Ltr  Label        Fs     Type        Size     Status     Info
----------  ---  -----------  -----  ----------  -------  ---------  --------
Volume 0     E   IRM_SHV_X64  UDF    CD-ROM      1917 MB  Healthy
Volume 1     D   RECOVERY     NTFS   Partition   3072 MB  Healthy
Volume 2         System Rese  NTFS   Partition    350 MB  Healthy    System
Volume 3     C                NTFS   Partition    132 GB  Healthy    Boot
DISKPART&gt; create partition primary

DiskPart has encountered an error: The media is write protected.
See the System Event Log for more information. 

Oops, I am not sure what a a disk is defaulted to read-only. Let’s change it manually.

DISKPART&gt; attributes disk
Current Read-only State : Yes
Read-only  : Yes
Boot Disk  : No
Pagefile Disk  : No
Hibernation File Disk  : No
Crashdump Disk  : No
Clustered Disk  : No

DISKPART&gt; attributes disk clear readonly

Disk attributes cleared successfully.

DISKPART&gt; list disk

Disk ###  Status         Size     Free     Dyn  Gpt
--------  -------------  -------  -------  ---  ---
Disk 0    Online          135 GB      0 B
* Disk 1    Online          200 GB   200 GB

DISKPART&gt; create partition primary

DiskPart succeeded in creating the specified partition.

DISKPART&gt; list volume

Volume ###  Ltr  Label        Fs     Type        Size     Status     Info
----------  ---  -----------  -----  ----------  -------  ---------  --------
Volume 0     E   IRM_SHV_X64  UDF    CD-ROM      1917 MB  Healthy
Volume 1     D   RECOVERY     NTFS   Partition   3072 MB  Healthy
Volume 2         System Rese  NTFS   Partition    350 MB  Healthy    System
Volume 3     C                NTFS   Partition    132 GB  Healthy    Boot
* Volume 4                      RAW    Partition    199 GB  Healthy

DISKPART&gt; select volume 4

Volume 4 is the selected volume.

DISKPART&gt; format fs=ntfs quick

100 percent completed

DiskPart successfully formatted the volume.

DISKPART&gt; list volume

Volume ###  Ltr  Label        Fs     Type        Size     Status     Info
----------  ---  -----------  -----  ----------  -------  ---------  --------
Volume 0     E   IRM_SHV_X64  UDF    CD-ROM      1917 MB  Healthy
Volume 1     D   RECOVERY     NTFS   Partition   3072 MB  Healthy
Volume 2         System Rese  NTFS   Partition    350 MB  Healthy    System
Volume 3     C                NTFS   Partition    132 GB  Healthy    Boot
* Volume 4                      NTFS   Partition    199 GB  Healthy

DISKPART&gt; assign letter=f

DiskPart successfully assigned the drive letter or mount point.

DISKPART&gt; list volume

Volume ###  Ltr  Label        Fs     Type        Size     Status     Info
----------  ---  -----------  -----  ----------  -------  ---------  --------
Volume 0     E   IRM_SHV_X64  UDF    CD-ROM      1917 MB  Healthy
Volume 1     D   RECOVERY     NTFS   Partition   3072 MB  Healthy
Volume 2         System Rese  NTFS   Partition    350 MB  Healthy    System
Volume 3     C                NTFS   Partition    132 GB  Healthy    Boot
* Volume 4     F                NTFS   Partition    199 GB  Healthy

DISKPART&gt; exit

Leaving DiskPart...

C:\Windows\system32&gt;f:
f:


F:\&gt;mkdir &quot;Virtual Machines&quot;
mkdir &quot;Virtual Machines&quot;

F:\&gt;dir
dir
Volume in drive F has no label.
Volume Serial Number is 6C59-E0A3

Directory of F:\

11/21/2014  03:49 PM    &lt;DIR&gt;          Virtual Machines
0 File(s)              0 bytes
1 Dir(s)  214,617,317,376 bytes free


cmd exited on ptbtt-go-hv with error code 0.
PS H:\Tools\sysinternals&gt;

Keeping Track of the Shadow … copies

I have 2008R2 and 2012 servers that has been in production for quite some time, running smoothly – I have never paid attention to VSS.

Various volumes with Shares are setup to capture shadows copies – every hours every day. The storage area is set to unlimited (300GB). VSS captures shadow copies accordingly as per schedule.

The problem I’m having is that the Shadow Copies are not growing to use all of the ‘Maximum Shadow Copy Storage space’. The ‘Used Shadow Copy Storage space’ is at 10.962GB – I’ve seen it go a bit higher, but never over 12GB. As a result, I’m not capturing as many prior versions of the volume as I would like.

There are no errors in the System log. Running ‘vssadmin list shadowstorage’ confirms that max size is 27GB. Running ‘vssadmin list writers’ shows all states as ‘stable’ and no errors. Running ‘vssadmin list providers’ shows there is only one provider (Microsoft Software Shadow Copy Provider, version 1.0.0.7).

Anyhow, I wanted to keep an eye on the shadow copies so I created this dirty script

#variables
$ComputerName = hostname

#preflight
if ($args.Length -eq 0)
{
    write-host &quot;Usage = report-vss.ps1 driveletter:&quot;
    exit
}
else
{
$driveletter = $args[0]
$trimmedletter = $driveletter.TrimEnd(&quot;:&quot;)

write-host &quot;Reporting for $driveletter drive on $ComputerName...&quot;
}

#use vssadmin to list the date time and count them
$logfilename = &quot;.\report-vss-$ComputerName-$trimmedletter.log&quot; #vssreports must exists!
$message = &quot;VSS info for $driveletter volume on $ComputerName&quot;
echo $message &gt; $logfilename
vssadmin list shadows /for=$driveletter | Select-String contained &gt;&gt; $logfilename
$vsscount = (vssadmin list shadows /for=$driveletter | Select-String contained).count
echo &quot;There are $vsscount shadows for this volume&quot; &gt;&gt; $logfilename

#use vssadmin to list the shadow storage
vssadmin list shadowstorage /for=$driveletter &gt;&gt; $logfilename

#use powershell to send an email.
$title = "$message wiht $vsscount shadows"
$stringBuilder = New-Object System.Text.StringBuilder
$body = Get-Content -Path $logfilename -Raw
$null = $stringBuilder.Append($body)
send-mailmessage -from "powershell@x.ca" -to "y@x.ca" -subject $message -body $stringBuilder.ToString() -priority High -dno onSuccess, onFailure -smtpServer EMAIL.ca

#do some clean up
rm $logfilename

I then call this from a batch script and use ps-remotesession to get the information on various server volumes.

#remotehost A
$s = New-PSSession -computerName A
Invoke-Command -Session $s -filepath &quot;\\gaia\it\Scripts\files\report-vss.ps1&quot; -ArgumentList &quot;f:&quot;
Invoke-Command -Session $s -filepath &quot;\\gaia\it\Scripts\files\report-vss.ps1&quot; -ArgumentList &quot;l:&quot;
Remove-PSSession $s

#remotehost B
$s = New-PSSession -computerName B
Invoke-Command -Session $s -filepath &quot;\\gaia\it\Scripts\files\report-vss.ps1&quot; -ArgumentList &quot;f:&quot;
Invoke-Command -Session $s -filepath &quot;\\gaia\it\Scripts\files\report-vss.ps1&quot; -ArgumentList &quot;l:&quot;
Remove-PSSession $s

I am now thinking, is there anything in WMI do get those metrics?

Yes there is! Let me know dig this out and come back with some other ideas.

Win32_ShadowProvider
Win32_ShadowContext
Win32_ShadowStorage
Win32_ShadowBy
Win32_ShadowFor
Win32_ShadowOn
Win32_ShadowVolumeSupport
Win32_ShadowDiffVolumeSupport
http://msdn.microsoft.com/en-us/library/aa394428%28v=vs.85%29.aspx

Enable Powershell Remoting via Group Policy

While one can run the command below to enable PS remoting, it is good to standardize this by using a GPO on your servers.

>Enable-PSRemoting

I am assuming that you will want to work with windows 7 and up along with windows server 2008R2 and up as there is a great deal of requirements around .net and powershell 2 and up.

You will need a GPO that contains 3 things (which are what enable-psremoting does:

  1. The enablement of WinRM
  2. The firewall exception
  3. The winRM service

Enabling WinRM
Policies > Administrative Templates > Windows Components > Windows Remote Management (WinRM) > WinRM Service
Enable “Allow Remote Server management through WinRM” (win2012 up) or “Allow automatic configuration of listeners” (win2008-)
Set the IPv4 and IPv6 filters to * unless you need something specific there

Punching holes in the firewall
Policies > Windows Settings > Security Settings > Windows Firewall with Advanced Security > Windows Firewall… > Inbound Rules
Add a new rule and choose the “Windows Remote Management” pre-defined rule.

Configure the WinRM service
Policies > Windows Settings > Security Settings > System Services
Select the Windows Remote Management (WS-Management) service and set it for automatic startup.