Pages

tirsdag 30. april 2013

Exchange 2010: Set calendar permission on new users

You can use Scripting Agent for a lot of things. In this example we will change the default calendar permission for new users. We try to find the calendar using the english name, and if not found we will try the norwegian name. The script will run when a new mailbox is created in Exchange, it will not affect existing users.

You can read about how you enable the Scripting Agent on technet. In short you would:
  1. Create the ScriptingAgentConfig.xml and save it to the CmdletExtensionAgents folder (e.g. C:\Program Files\Microsoft\Exchange Server\V14\Bin\CmdletExtensionAgents) on each Exchange server.
  2. Run this command in Exchange Management Shell:
 Enable-CmdletExtensionAgent "Scripting Agent"  

Be warned! If your syntax is wrong when you save ScriptingAgentConfig.xml (and with the agent enabled), you will not be able to launch Exchange Management Console before you correct the problem. Also if you don't deploy the configuration file first on all your Exchange serversk, and you enable the Scripting Agent, all non-Get cmdlets fail when they're run. Always test your script before you use it with the Scripting Agent.

ScriptingAgentConfig.xml example:
 <?xml version="1.0" encoding="utf-8" ?>  
 <Configuration version="1.0">  
  <Feature Name="MailboxProvisioning" Cmdlets="new-mailbox">  
   <ApiCall Name="OnComplete">  
 if($succeeded) {  
  $DCs = Get-DomainController -ErrorAction SilentlyContinue  
  If ($DCs){  
   do {  
    foreach ($DC in $DCs){  
     $mbox = Get-Mailbox -Identity $provisioningHandler.UserSpecifiedParameters["Alias"] -DomainController $DC.DnsHostName -ErrorAction SilentlyContinue  
     If ($mbox) {  
      $fld = $mbox.Alias+":\Calendar"  
      $mfp = Get-MailboxFolderPermission -Identity $fld -DomainController $DC.DnsHostName -ErrorAction SilentlyContinue  
      if(!$mfp){  
       $fld = $mbox.Alias+":\Kalender"  
       $mfp = Get-MailboxFolderPermission -Identity $fld -DomainController $DC.DnsHostName -ErrorAction SilentlyContinue  
      }  
      if($mfp){  
       Set-MailboxFolderPermission -Identity $fld -User Default -AccessRights Reviewer -DomainController $DC.DnsHostName -ErrorAction SilentlyContinue | out-null  
       Break  
      }  
     }  
    }  
    If($mfp){Break}  
    Start-Sleep 1  
    $i++  
   }  
   until ($i -gt 50)  
  }  
 }  
  </ApiCall>  
  </Feature>  
 </Configuration>  

lørdag 20. april 2013

OpsMgr: How to seal management packs

You need to seal a management pack (.xml to .mp) if:
  • You want to reference it from another MP.
  • It has one or more console tasks (to prevent the security warning).
  • It contains Data Warehouse extensions.
  • You want consistent guids for you classes and properties (reuse MP on other systems).
Is is also a good practice to always seal your management packs.

Step 1 - Strong Name Key

You will need a Strong Name Key (.snk) to seal your management pack. Use sn.exe for this (part of Visual Studio or Windows SDK). I did this on Windows 8 (64-bit) using Windows Software Development Kit (SDK) for Windows 8. When installing SDK you only need to install the .NET Framework 4.5.1 Software Development Kit. Use the correct SDK version for your Operating System.

First we prepare a folder structure for dealing with management packs, open up Command Prompt and type as follows (PS! make proper changes so it will work in your environment):
MD D:\SCOMDev\MP\Key  
MD D:\SCOMDev\MP\Includes
MD D:\SCOMDev\MP\Unsealed
MD D:\SCOMDev\MP\Sealed
COPY X:\SupportTools\AMD64\MPSeal.exe D:\SCOMDev\MP

# Create SNK:
cd "C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\x64"
sn.exe -k D:\SCOMDev\MP\Key\KeyFile.snk

# Extract public key from SNK:
sn.exe -p D:\SCOMDev\MP\Key\KeyFile.snk D:\SCOMDev\MP\Key\KeyFile_publickey.snk  

#Get the readable public key token:
sn.exe -tp D:\SCOMDev\MP\Key\KeyFile_publickey.snk > D:\SCOMDev\MP\Key\KeyFile_publickeytoken.txt

The KeyFile_publickeytoken.txt contains the public key token for your KeyFile. This can be used to reference management packs that you have sealed. You would do this by editing the .xml file and add you management pack to the <References> section and your public key token in the <PublicKeyToken> tag.

PS! I always use the same KeyFile within a company. So you should only need to do step 1 once.

Step 2 - Prepare for sealing

If you have made changes to a management pack always remember to increase the management pack version. Also remember to keep a copy of each unsealed version (.xml) you create (for history and debugging purposes).

Copy your management pack (.xml) to the Unsealed folder (D:\SCOMDev\MP\Unsealed).

Copy any referenced management pack (.mp) to the Includes folder (D:\SCOMDev\MP\Includes). To find the referenced management packs, open up the unsealed management pack (.xml) and look under the tag <References>.

PS! You could also keep a copy of all the management packs in the Includes folder, if you like.

Step 3 - Seal
Open up command prompt and type as follows (PS! make proper changes so it will work in your environment):
 D:\SCOMDev\MP\mpseal.exe D:\SCOMDev\MP\Unsealed\mpname.xml /I D:\SCOMDev\MP\Includes /Keyfile D:\SCOMDev\MP\Key\KeyFile.snk /Company "MyCompany" /Outdir "D:\SCOMDev\MP\Sealed"  

PS! I you are getting errors stating that MPSeal is unable to load ManagementPack this or that, it is because it is missing from the Includes directory. You need to either find it on your system and copy it to the Includes folder, or download the right version from the vendor (like Microsoft), install it and copy it to the Includes folder. When you install a management pack, and after you have copied it and imported it into Operations Manager, you can usually uninstall it.

onsdag 17. april 2013

OpsMgr: How to monitor disk space

I always use this as a general guide:
  1. Always calculate both MB and Percentage threshold.
    The drive must exceed both thresholds for a state change to occur. For example, you need a warning when there is less than 5 GB free space on a disk. The warning threshold on a non-system disk is by default 10 % and 2 GB so a 40 GB disk have a 4 GB Percentage threshold (10 %). This disk will be in a warning state when it has less than 2 GB of free space. If you override the MB threshold to 5120 MB and keep the 10 % threshold (on a 40 GB disk), you will not get a warning at 5 GB, but at 4 GB, because 10 % will be the last threshold to be reached. In this example, you would also have to override the Percentage threshold to at least 12.5, or 25 % if this warning should apply to a 20 GB disk as well.
  2. Minimize the number of overrides needed in your environment.
Current Base OS management pack, 6.0.7026.0, do not show percent and MB free values in the Logical Disk free space alerts. To remedy consider to use the addendum management packs from Kevin Holman:  "Logical Disk free space alerts don’t show percent and MB free values in the alert description". If a future Base OS management pack fix this issue, the addendum management packs needs to be removed and the disk monitoring overrides needs to be recreated.

Another issue to consider is if you want alert on warning state. In general, alert on warning state for a three state monitor is something you should not do. This is because the monitor will change the alert when the state changes, instead of creating a new alert. So if you configure alert on warning state and notifications, the change to critical state will not trigger a new notification. In the latest base OS management pack there is an aggregate rollup monitor which can be used for critical alerting from the warning alerts child unit monitor. However if you use the addendum management packs mentioned earlier, this is not included, and can therefore not be used. To remedy this you could use two monitors, one for warning, and one for critical.

To calculate thresholds, use the Logical Disk Free Space Monitor Calculator by Jonathan Almquist.

Start by finding threshold values that best meets your environment. Use this to override all logical disks. If this is not sufficient, look at the disks that do not meet the general monitoring rule and group those that have the same threshold needs. This could be large file share disks or disks where data growth is faster than normal, etc. Then override based on those groups. Use the calculator to find the best threshold values for each group.

A good starting point would be to use the largest disk size, the smallest disk size and the average disk size for both System and Non-System drives in your environment.

You can list drives monitored by OpsMgr with this SQL query (import the list to Excel for sorting and filtering):

 /* [MTV_LogicalDisk] is a View in the OperationsManager database */  
 SELECT [PrincipalName] AS 'Computer'  
    ,[DisplayName_55270A70_AC47_C853_C617_236B0CFF9B4C] AS 'Drive'  
    ,[SizeNumeric_486ADDDB_2EB8_819A_FA24_8F6AB3E29543] AS 'MBSize'  
 FROM [MTV_LogicalDisk]  
 ORDER BY 'Computer', 'Drive'

/* Or (depending on your OpsMgr/Base OS MP version): */
 SELECT [PrincipalName] AS 'Computer'  
    ,[DisplayName] AS 'Drive'  
    ,[SizeNumeric_749AE6FF_BCF2_0852_7B6D_CE73CA77FD8F] AS 'MBSize'  
 FROM [MTV_Microsoft$Windows$Server$2008$LogicalDisk]
 ORDER BY 'Computer', 'Drive'

onsdag 10. april 2013

OpsMgr: Script Monitor: Check that no folder with name starting with X exist in subfolders

Monitoring details


Using: Operations Manager 2012.
Agent: running Windows Server 2008 R2.
Objective: Verify that no folder starting with Error_AP01 exist in any subfolder of specified folder.
Method: VBScript using two state Script Monitor.
State: Trigger Critical state if folder exist.
Schedule: Run every 60 minutes.
Action to take: If Critical state, notify application owner, by e-mail.

Monitor characteristics

  • Monitor is disabled by default, use override to run on specified computer or group of Computers.
  • Monitor is in Critical state if script returns a status message of BAD
  • Monitor is in Healthy state if script returns a status message of GOOD
  • Arguments (2):
    • [string]FolderPath: Path to the folder we want to monitor
    • [string]FolderName: Name of folder to search for, matches folders that begins with this name
  • Properties (1):
    • [string]Result: GOOD or BAD

Script

 '======================================================================  
 ' NAME  : fscheckiffoldernameexist.vbs  
 ' AUTHOR : Reidar Johansen  
 ' DATE  : 4/10/2013  
 ' COMMENT: Monitor a folder and its subfolders for a foldername starting  
 ' With a specified name. Trigger an error state if the folder exit.  
 ' Used in a two-state monitor.  
 '======================================================================  
 Option Explicit  
 Dim oArgs, oAPI, sMonitorStatus, oBag  
 Dim oFso, sFolderPath, sFolderName, lExist  
 Set oArgs = Wscript.Arguments  
 Set oAPI = CreateObject("MOM.ScriptAPI")  
 If oArgs.Count < 2 Then  
   ' If called without argument, create event and quit  
   Call oAPI.LogScriptEvent(WScript.ScriptName,101,2,"The script was called without correct arguments and was not executed.")  
   Wscript.Quit -1  
 End If  
 Set oFso = CreateObject("Scripting.FileSystemObject")  
 ' Capture path from arguments  
 sFolderPath = oArgs(0)  
 sFolderName = oArgs(1)  
 ' See if folder exists  
 If (oFso.FolderExists(sFolderPath)) Then  
   lExist = FindFolder (sFolderPath,sFolderName)  
   If lExist Then   
     sMonitorStatus = "BAD"  
   Else   
     sMonitorStatus = "GOOD"   
   End If   
 Else  
   ' If folder do not exist, create event and quit  
   Call oAPI.LogScriptEvent(WScript.ScriptName,101,2,"The path " + sFolderPath + " was not found. Verify that it exists and check permissions.")  
   Wscript.Quit -1  
 End If  
 ' Create and submit the propertybag  
 Set oBag = oAPI.CreatePropertyBag()  
 Call oBag.AddValue("Result",sMonitorStatus)  
 Call oAPI.Return(oBag)  
 Function FindFolder (ByVal sFolder, ByVal sName)  
   Dim oParentFld, oSubFld  
   Set oParentFld = oFso.GetFolder (sFolder)  
   ' Matc name of current directory  
   If Left(oParentFld.Name,Len(sName)) = sName Then  
    FindFolder = True  
    Exit Function  
   End If  
   For Each oSubFld In oParentFld.SubFolders  
     ' Match name of each subfolder  
     If FindFolder(oSubFld.Path,sName) Then  
      FindFolder = True  
      Exit Function  
     End If  
   Next  
   'Folder not found  
   FindFolder = False  
 End Function  

To create a Script Monitor in Operations Manager, take a look at my other blogg: OpsMgr: Script Monitor: Check that no files exist in subfolders.

OpsMgr: Script Monitor: Check that no files exist in subfolders

Monitoring details

Using: Operations Manager 2012.
Agent: running Windows Server 2008 R2.
Objective: Verify that all invoices (pdf files stored in various subfolders) have been processed at given time.
Method: VBScript using two state Script Monitor.
State: Trigger Critical state if subfolders contains files at given time.
Schedule: Run once each day, at specified time.
Action to take: If Critical state, notify application owner, by e-mail.

Monitor characteristics

  • Monitor is disabled by default, use override to run on specified computer
  • Monitor is in Critical state if script returns a status message of BAD
  • Monitor is in Healthy state if script returns a status message of GOOD
  • Arguments (1):
    • [string]FolderPath: Path to the folder we want to monitor
  • Properties (2):
    • [integer]FileCount: Number of files in subfolders
    • [string]Result: GOOD or BAD

Script

 '======================================================================  
 ' NAME  : fscheckthatnofilesexist.vbs  
 ' AUTHOR : Reidar Johansen  
 ' DATE  : 4/10/2013  
 ' COMMENT: Monitor file count in a folder and its subfolders.
 ' Trigger an error state if the folder or its subfolders contain files.  
 ' Used in a two-state monitor.  
 '======================================================================  
 Option Explicit  
 Dim oArgs, oAPI, sMonitorStatus, oBag  
 Dim oFso, sFolderPath, iFileCount  
 Set oArgs = Wscript.Arguments  
 Set oAPI = CreateObject("MOM.ScriptAPI")  
 If oArgs.Count < 1 Then  
   ' If called without argument, create event and quit  
   Call oAPI.LogScriptEvent(WScript.ScriptName,1001,2,"The script was called without any arguments and was not executed.")  
   Wscript.Quit -1  
 End If  
 Set oFso = CreateObject("Scripting.FileSystemObject")  
 ' Capture path from arguments  
 sFolderPath = oArgs(0)  
 ' See if folder exists  
 If (oFso.FolderExists(sFolderPath)) Then  
   iFileCount = CountFiles (sFolderPath)  
   If iFilecount = 0 Then   
     sMonitorStatus = "GOOD"   
   Else   
     sMonitorStatus = "BAD"  
   End If   
 Else  
   ' If folder do not exist, create event and quit  
   Call oAPI.LogScriptEvent(WScript.ScriptName,1001,2,"The path " + sFolderPath + " was not found. Verify that it exists and check permissions.")  
   Wscript.Quit -1  
 End If  
 ' Create and submit the propertybag  
 Set oBag = oAPI.CreatePropertyBag()  
 Call oBag.AddValue("FileCount",iFileCount)  
 Call oBag.AddValue("Result",sMonitorStatus)  
 Call oAPI.Return(oBag)  
 Function CountFiles (ByVal sFolder)  
   Dim oParentFld, oSubFld, iCount  
   Set oParentFld = oFso.GetFolder (sFolder)  
   ' Count the number of files in the current directory  
   iCount = oParentFld.Files.Count  
   For Each oSubFld In oParentFld.SubFolders  
     ' Count all files in each subfolder  
     iCount = iCount + CountFiles(oSubFld.Path)  
   Next  
   'Returns the counted files  
   CountFiles = iCount  
 End Function  

Create Script Monitor

1. In the Operations Console, select the Authoring workspace, and then select Monitors.
2. Select Create a Monitor and then Unit Monitor...


3. Expand Scripting and then expand Generic. Select Timed Script Two State Monitor. Also, for this purpose, we will click New... to create Management Pack MyCompany InvoiceSender Monitoring for the application we will monitor. Click Next.


4. In the Name box we type InvoiceSender Processed State. Then we select Monitor target class Windows Computer. Set Parent monitor to Availability. Also unselect the Monitor is enabled box. Click Next.


5. In the Run every box, type 1 and select Days. Also check the Synchronize at box and type 01:30. Click Next.


6. For the File Name value, type fscheckthatnofilesexist.vbs. Leave the default Timeout value. In the Script box, paste the complete contents of the script. Click the Parameters button. Type the path to the folder you would like to monitor like this: "C:\Invoice Folder". Click OK. Click Next.


7. On the Unhealthy Expression page, Click Insert. In the Parameter Name box type Property[@Name='Result']. In the Operator box select Equals. In the Value box type BAD. Click Next.


8. On the Healthy Expression page, Click Insert. In the Parameter Name box type Property[@Name='Result']. In the Operator box select Equals. In the Value box type BAD. Click Next.



9. On the Configure Health page, Change the Health State for the Unhealthy condition to Critical. Click Next.



10. On the Configure Alerts page Select Generate alerts for this monitor. Select The monitor is in a critical health state. Leave the box selected to automatically resolve the alert. In the Alert name box leave the default title. Clear the existing text in the Alert description box and type The folder C:\Invoice Folder on then click the ellipse button. Click Target and then DNS name. Type contains then click Data and then Property. Replace <<STRING>> with FileCount. Type unprocessed files. Click OK. Click Create.


Enable the monitor for a Windows Computer

1. In the Operations Console, select the Authoring workspace, and then select Monitors.
2. Choose Change Scope..., select Clear All and type Windows Computer. Select Windows Computer. Click OK.


3. Expand Windows Computer and then Entity Health and then Availability. Right click Invoice Sender Processed State and select Overrides > Override the Monitor > For a specific object of class: Windows Computer (or you could create a Group with Windows Computers and select For a group...).


4. Select Computer Object from the list or type a Text string to search. Click OK. In Override Properties select the Override box for row with Paramter Name Enabled and set the Override Value to True.


If you open the Health Explorer for the Computer you selected in step 3 above, and then turn off the filter, you will now find the InvoiceSender Processed State monitor by expanding Entity Health and then Availability. You can also open Properties and change settings for the monitor. Best practice would be to export the management pack, seal it, and then import it back (before creating any Overrides). Then you would create an unseald management pack for the overrides.

5. When you receive an alert from this monitor you can create a notification by right clicking the alert and then select Notification subscription.


6. Criterias can be defined with some additional Conditions to prevent a new notification when someone close the alert, if desired...


After completing the wizard we are done...

søndag 7. april 2013

PowerShell: Delete empty folders

Perhaps after deleting files in TEMP folder, you would like to delete empty folders as well...

First, lets get all the folders:
$FolderList = Get-ChildItem -LiteralPath $env:TEMP -Recurse -ErrorAction SilentlyContinue -Force | Where-Object {$_.PSIsContainer} | Sort-Object @{Expression={$_.FullName.Length}; Ascending=$false}

To list the folders you could execute:
$FolderList | Format-Table -Property LastWriteTime,CreationTime,FullName -AutoSize

Now we would like to loop through each folder and see if it has files, and if not, delete it (but not the folder Low).

$Count = $FolderList.Count

for ($i=0;$i -lt $Count;$i++){
  if(-not (Get-ChildItem -LiteralPath $FolderList[$i].FullName -ErrorAction SilentlyContinue -Force|Select-Object -First 1)) {
    if ($FolderList[$i].Name -ne "Low"){
      Remove-Item -LiteralPath $FolderList[$i].FullName -Force -Recurse -ErrorAction SilentlyContinue -WhatIf
    }
  }
}

To actually delete the folders, remove -WhatIf

PowerShell one-liner: delete files older than X days

In this example we want to delete all files older than two days, recursivley, from the TEMP folder.

First, lets list the files we would like to delete, sorted by LastWriteTime:

Get-ChildItem -LiteralPath $env:TEMP -Recurse -ErrorAction SilentlyContinue -Force | Where-Object {! $_.PSIsContainer -And $_.LastWriteTime -le ([datetime]::Today).AddDays(-1)} | Sort-Object LastWriteTime | Format-Table -Property LastWriteTime,CreationTime,FullName -AutoSize

Now, to simulate a delete, we could use:

Get-ChildItem -LiteralPath $env:TEMP -Recurse -ErrorAction SilentlyContinue -Force | Where-Object {! $_.PSIsContainer -And $_.LastWriteTime -le ([datetime]::Today).AddDays(-1)} | Remove-Item -Force -WhatIf

Remove -WhatIf to actually do it...