Exchange: Content index state failed

If you ever had problems with corrupt databases in an Exchange 2010 DAG setup you might have encountered this error. Trying to activate the database on a server where it has this state will fail.

However there is a quite simple fix given that you have a healthy copy of the database on a different server:

Update-MailboxDatabaseCopy -Identity DB<server with failed content index state> -SourceServer <server with healty copy> -CatalogOnly

Run the command in the Exchange Management Shell and it should fix the Content index state and allow you to activate the database again.

 

 

 

 

 

 

 

 

 

Posted in Exchange, Microsoft, Powershell Tagged , , ,

Exchange: Activate Database Copy fails

After some exchange services failed on one of the nodes in our Exchange 2010 DAG we got some problems with one database. The database was mounted on server2 where it has an activation preference of 2.
Trying to manually activate the database on server1, where is has an activation preference of 1, resulted in the following error:

——————————————————–
Microsoft Exchange Error
——————————————————–
Cannot activate database copy ‘Activate Database Copy…’.

Activate Database Copy…
Failed
Error:
An Active Manager operation failed. Error: The database action failed. Error: Operation failed with message: MapiExceptionJetErrorAttachedDatabaseMismatch: Unable to mount database. (hr=0x80004005, ec=-1216)
. [Database: DB1, Server: server1]

An Active Manager operation failed. Error: Operation failed with message: MapiExceptionJetErrorAttachedDatabaseMismatch: Unable to mount database. (hr=0x80004005, ec=-1216)
. [Server: server1]

MapiExceptionJetErrorAttachedDatabaseMismatch: Unable to mount database. (hr=0x80004005, ec=-1216)

——————————————————–
OK
——————————————————–

 

The solution is actually quite simple:

Suspend the database copy on server1 and update the database copy. Then try to activate the database copy again.

More detailed steps:
Using the Exchange management shell:
Suspend-MailboxDatabaseCopy -Identity DB1Server1
Update-MailboxDatabaseCopy -Identity DB1Server1 -SourceServer Server2
Move-ActiveMailboxDatabase DB2 -ActivateOnServer MBX1

Using the Exchange Management Console:
Navigate to Server Configuration–>Mailbox and select Server1
Right click the database and click Suspend Database Copy
Right click the database and click Update Database Copy
In the wizard select server2 as the source server and click Update
When the job completes right click the database again and click Activate Database Copy

 

 

 

Posted in Exchange, Microsoft Tagged , , , ,

Resetting the Discretionary Access Control List (DACL) in a Windows Service security descriptor

OpenService FAILED 5: Access is denied. — “Oh crap!”

If you ever see this error and need to reset the DACL on a Windows service, let’s say in case you (or someone else) accidentally deletes it, or configure it to something that prevents you from reading it’s security settings, this might do the trick:

First of all, get a cup of coffee.

Download PsExec (a tool in PsTools), which among other things allow you  to run commands as the “local system” account.
Find out what the real name of the service is by looking in the following registry key:

HKLMSYSTEMCurrentControlSetServices

The real name (not the display name) of the service is the name of the key itself.

Start a Command Prompt (cmd) window as administrator.
Start a new cmd session as the system account:

PsExec.exe /s cmd

Now it’s time to set a new DACL, this is done by using the command “sc sdset” followed by the service name and the new security descriptor using SDDL-format (Security Descriptor Definition Language). If you are unsure what parameters to use here, you can either run “sc sdshow” on another service that most likely are configured the same way as the service you are changing were, or try the command in the example below.

The command below will give access to Local System (SY), Built-in administrators (BA), Interactively logged-on user (IU) and Service logon user (SU).

sc sdset service_name DSmilie: :(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)

You should be looking at the relieving message: [SC] SetServiceObjectSecurity SUCCESS

Now, enjoy your coffee Smilie: ;)

 

–ricmik

Posted in Microsoft Tagged , , , , , , ,

Powershell: Checking multiple dns records for multiple domains

I don’t know how useful this will be for others, but in our case we had a need to check a few public dns records on some of our domains. Doing so by using a web portal will be time consuming and straight out boring. Luckily you can use Powershell for such things:

First we need to to save our domains in an array:

$domains = @("domainA.com", "domainB.com", "domainC.com")

Then we send that array into a foreach loop:

foreach ($element in $domains)
{
Resolve-DnsName -server 8.8.8.8 record.$($element)
}

You might notice that I use Google’s public dns servere here, but you can use whatever dns server you want, or just leave the -server part out.

The example above is pretty basic and only checks for an A record. In our case we needed to check several SRV records for each of the domains, so I had to extend the script a little. The cmdlet Resolve-DnsName is equivalent to the good ol’ nslookup so it’s quite powerful, given the right swithces.

Heres the script I ended up with for our case (10 points if you guess what the SRV records are for Smilie: :) ):

$domains = @("domainA.com", "domainB.com", "domainC.com" )

foreach ($element in $domains) 
{
Resolve-DnsName -server 8.8.8.8 -type srv _h323cs._tcp.$($element)
Resolve-DnsName -server 8.8.8.8 -type srv _h323ls._udp.$($element)
Resolve-DnsName -server 8.8.8.8 -type srv _sip._tcp.$($element)
Resolve-DnsName -server 8.8.8.8 -type srv _sips._tcp.$($element)
}

Posted in Microsoft, Powershell Tagged , ,

Powershell function for enabling a user for Lync and configure settings

A little while ago I posted a script for enabling users for Lync and settings some settings for that user. That script has been used here ever since I posted it and it has worked like a charm. However there’s always room for improvement, right?.

So I have made a function out of it and for the first time (I think) I have even implemented some error handling. The function is also improved quit a bit on the help section and the info that is shown to the user after the function completes.

As in the script, this function will enable the user for Lync and set some default settings like Dial Plan, Voice Policy, Conferencing Policy. It also gives you the option to specify a Line URI.
The difference is that this function will use the default settings only if nothing else is specified, so you can change the settings if you like, using parameters. Of course theres also the possibility to pipe input from a csv file.

Here’s the code:

function Enable-LyncUser {
[CmdletBinding()]
 Param (
 [parameter(Mandatory=$True)][string]$Identity,
 [string]$Pool = 'lyncpool1.test.local',
 [string]$DialPlan = 'DialPlanSIPtrunk',
 [string]$Voice = 'SIP Trunk Service',
 [string]$Conference = 'Conference',
 [string]$LineURI
 )

Write-Host "Enabling user..."

#Importing the Lync PowerShell module
Import-Module Lync

#Trying to enable the user for Lync
try {
 Enable-CsUser -identity $Identity -RegistrarPool $Pool -SipAddressType emailaddress
 }

#Catching errors, aborting if the user is not found
catch [Microsoft.Rtc.Management.AD.ManagementException] {
 throw "User not found, check username"
 }

#Sleeping, so that the next command doesn't fail
Write-Host "Sleeping... Please wait..."
Start-Sleep -s 4

Write-Host "Configuring user..."

#Setting the user as EnterpriseVoice enabled
Set-CsUser -identity $Identity -EnterpriseVoiceEnabled $True
#Setting dial plan
Grant-CsDialPlan –Identity $Identity -PolicyName $DialPlan
#Setting voice policy
Grant-CsVoicePolicy –Identity $Identity –PolicyName $Voice
#Setting conferenceing policy
Grant-CsConferencingPolicy -identity $Identity -PolicyName $Conference

#Trying to set the optional Line URI
try {
 Set-CsUser -identity $Identity -LineUri $LineURI
 }

#Cathing errors and continuing
catch [System.FormatException] {
 Write-Error -Message "Wrong format on LineURI, it should be tel:+xxxxxxxx." -Category SyntaxError
 }

Write-Host "Config finished"

#Grabbing the Lync login for the user and writing it to the host
$SipAddress = Get-CsUser -Identity $Identity | Select-Object SipAddress
Write-Host "The user may now log in to Lync as $($SipAddress.SipAddress.substring(4))" -ForegroundColor Green

<#
 .Synopsis
  Enables given user for Lync and sets config
 .Description
  The function will enable the user for Lync and add the given config, if no config is given the default values will be used.
 .Parameter Identity
  The user who you want to enable for Lync
 .Parameter Pool
  The Lync pool you want to assign a user to. Default is lyncpool1.test.local
 .Parameter DialPlan
  The dialplan you want to associate the user with. Default is DialPlanSIPtrunk
 .Parameter Voice
  The voice policy you want to associate the user with. Default is SIP Trunk Service
 .Parameter Conference
  The conference policy you want to associate the user with. Default is Conference
 .Parameter LineURI
  If you want to specify a Line URI, do so in the format of tel:
 .Example
  Enable-LyncUser user1
  This will enable user1 with default settings
 .Example
  Enable-Lyncuser user2 -LineURI tel:+4712345678
  This will enable user2 and set the lineuri to tel:+4712345678
 .Link
  http://cloud.kemta.net
 #>
}

 

You may wonder why the Start-Sleep command is there. The reason is that my testing indicated that the function will work to fast for Active Directory if it isn’t there. During my testing I found that without the sleep the next command, Set-CsUser, will fail because the object cannot be found. Running the function again resultet in no errors.
Therefore I tested adding a few seconds of sleep to prevent the Set-CsUser command (and the following commands) from failing. Depending on you environment you can decrease the seconds or even remove the sleep, but I found that 3 seconds was just a bit to short (sometimes it would fail, sometimes not) so I ended up with 4.

I am kinda proud of the error handling in this function, given that I have never used error handling in Powershell before. But please let me know if there are improvements to be made or errors in my code.

Posted in Lync, Microsoft, Powershell Tagged , , , , , , ,

HP ACU cli quick guide

Guess what? It’s time for something different than powershell Smilie: :P

I finally got myself a server to play around with Hyper-V on. This has been sorely missed for a long time. I worked a lot with Hyper-V in my previous job, and even built a small data center running on Hyper-V. But at my current job we only use vmware, which is a great product but to expensive in my book. Especially when we are finally looking at a datacenter license from Microsoft and we already have the System Center suite. This means that we can save a ton of money on switching from vmware to Hyper-V.

Anyway…In this blogpost I want to show you a little about the HP Array Configuration Utility command-line interface.
I usually use the graphical interface for creating volumes and such, but for some reason I couldn’t get it working on my Hyper-V test server. So instead of looking on how to fix that I decided to give the cli a shot. What I want to achieve with this post is to show you how the steps you need after putting one or more new disks in the server.

The ACU cli can be launched by running CSmilie: :Program Files (x86)CompaqHpacucliBinhpacucli.exe.

The first command you should know about is “controller all show”, this will show you all the controllers installed in the server. The output will look something like this:

=> controller all show
Smart Array P410i in Slot 0 (Embedded) (sn: 50014380124xxxxx)

This show that my controller is installed in slot 0, to get some more info on this controller I could run “controller slot=0 show”, the output should look something like this:

 => controller slot=0 show

Smart Array P410i in Slot 0 (Embedded)
 Bus Interface: PCI
 Slot: 0
 Serial Number: 50014380124D5620
 Cache Serial Number: PBCDF0CRHZU5D4
 RAID 6 (ADG) Status: Disabled
 Controller Status: OK
 Hardware Revision: C
 Firmware Version: 5.70
 Rebuild Priority: Medium
 Expand Priority: Medium
 Surface Scan Delay: 15 secs
 Surface Scan Mode: Idle
 Queue Depth: Automatic
 Monitor and Performance Delay: 60 min
 Elevator Sort: Enabled
 Degraded Performance Optimization: Disabled
 Inconsistency Repair Policy: Disabled
 Wait for Cache Room: Disabled
 Surface Analysis Inconsistency Notification: Disabled
 Post Prompt Timeout: 0 secs
 Cache Board Present: True
 Cache Status: OK
 Cache Ratio: 25% Read / 75% Write
 Drive Write Cache: Disabled
 Total Cache Size: 1024 MB
 Total Cache Memory Available: 912 MB
 No-Battery Write Cache: Disabled
 Cache Backup Power Source: Capacitors
 Battery/Capacitor Count: 1
 Battery/Capacitor Status: OK
 SATA NCQ Supported: True

On my test server I have already created a mirrored volume on which I have installed Hyper-V. I have only one extra disk, so I cannot show you how to create a fancy raid configuration but nevertheless I will show you how to create an array and a logical disk.

The first thing we need to do is to find any unassigned disk connected to the controller. This is done by running the command “controller slot=0 physicaldrive allunassigned show” (replace slot=0 with the slot where your controller is connected). The output will look something like this:

=> controller slot=0 physicaldrive allunassigned show

Smart Array P410i in Slot 0 (Embedded)

 unassigned

 physicaldrive 1I:1:3 (port 1I:box 1:bay 3, SATA, 500 GB, OK)

So here we see that I have one unassigned disk that I can use. Given that I want to use all unassigned disks to create a new logical disk in a new array I can run the command “controller slot=0 create type=ld drives=allunassigned raid=0”
This will create a new array and a new logical drive that uses all unassigned drives, the raid level is 0 (striping)

Thats basically what you need to do from the acu. But before you can use the disk in Windows you need to initialize it, create a partition and so on, the required steps could be something like this:

DISKPART> list disk
DISKPART> select disk 1
DISKPART> attributes disk clear readonly
DISKPART> online disk
DISKPART> create partition primary
DISKPART> list volume
DISKPART> select volume 4
DISKPART> assign letter=e:
DISKPART> EXIT
C:UsersAdministrator> format E: /Q

 

Posted in ACU, HP Tagged , , , , ,

SuperOffice and Citrix

I’m just gonna start by putting this out there: I have never been a fan of SuperOffice, and I probably never will be either.

Now that thats out there, heres the situation: We have one citrix farm, and three different SuperOffice instances. The goal with our citrix farm is to have each citrix server completely the same as the others. Because of that, only one of the SuperOffice instance have been accessible from the citrix farm. Until yesterday…

When we first set up the citrix farm, we installed that one SuperOffice instance and didn’t put much effort into getting the other two instances accessible. What we did try was using the -inipath parameter for socrm.exe and soadmin.exe as stated here: http://cs.superoffice.com/scripts/customer.exe?_sf=0&custSessionKey=&customerLang=no&noCookies=true&action=viewKbEntry&id=2388

That didn’t work at all so we didn’t bother trying anymore as the other two instances isn’t that much used anyway.

But yesterday I did another attempt and it turns out that the documentation from SuperOffice is flawed, it clearly states that the inipath parameter should be used like this:

socrm.exe -inipath=c:superoffice.ini

But when in fact the correct way would be like this:

socrm.exe -inipath=c:

As far as I can see, SuperOffice is coded to look for superoffice.ini in the folder specified by the inipath parameter. It also will not recognize i.e. c:superoffice as a folder, you would need to specify c:superoffice

Another thing that is important, and that I have found no documentation on, is that superoffice.config needs to be in the same folder as superoffice.ini.

 

So to sum up: If you want to run a SuperOffice client and connect to different databases, you need to use the -inipath parameter. You should create a superoffice.ini and a superoffice.config file, store it somewhere (a network share works fine), and then start SuperOffice or SuperOffice Admin with the following switch: -inipath=\serversharefolder

Posted in SuperOffice Tagged , , ,

Powershell function for gathering users in groups

A friend of mine asked me a couple of days ago if I knew a way to gather users who are members of given groups. I thought to myself “Hmm, challenge accepted!” and started writing a small powershell script.

After he confirmed that the script worked as planned I decided to make a function of it (Yes, I know it has been a lot of them on this blog lately).
The function accepts two parameters: GroupNames and Filelocation. In addition there is an optional switch called KeepCSV.
Rest of the function isn’t that interesting, if you want to use it you can always consult the help (get-help get-membersinadgroups) that I actually have created Smilie: :)

Heres the code:

function Get-MembersInADGroups
 {
 Param
 (
 [parameter(Mandatory=$True)][string[]]$GroupNames,
 [parameter(Mandatory=$True)][string[]]$Filelocation,
 [switch]$KeepCSV
 )
 Get-ADGroup -LDAPFilter "(name=$GroupNames)" | export-csv $FileLocationtemp.csv -NoTypeInformation

 $groups = Import-Csv $FileLocationtemp.csv

 $groups | ForEach-Object {
 $groupname = $_.SamAccountname
 Get-ADGroupMember -Identity $_.SamAccountName | select-object name,samaccountname | Out-File $Filelocation$groupname.txt -Encoding utf8
 }
 if ($KeepCSV)
    {
    Write-Host "CSV file is now saved as $filelocationtemp.csv"
    }
 Else 
    {
    Remove-Item $FileLocationtemp.csv
    }
 <#
 .Synopsis
 Gathers members in given group(s) and puts the result in txt files
 .Description
 This function will gather all users in the group(s) you specify and write a txt file for each group containing the users who are member of that group. The function accepts wildcards in group name
 .Parameter Groupnames
 This parameter defines what group(s) to look for
 .Parameter FileLocation
 This parameter defines where the output files should be saved
 .Parameter KeepCSV
 Defining this switch will not delete the temp.csv file containing the groups which are polled
 .Example
 Get-MembersInADGroups -GroupNames some_group -Filelocation c:test
 This command will poll Active Directory for the members of some_group and write a file called some_group.txt in c:test
 .Example
 Get-MembersInADGroups -GroupNames some_group* -Filelocation c:test
 This command will poll Active Directory for members of groups whose name begins with some_group and write a txt file for each of them in c:test
 .Link
 http://cloud.kemta.net
 #>
 }

PS: the function requires that you already have loaded the Active Directory module in powershell

Posted in Active Directory, Microsoft, Powershell Tagged , , ,

Motivational Powershell function

If you are ever in need of some motivation, here is a very simple Powershell function for that:

function Motivate-Me
 {
 $motivator = Get-Random -Minimum 1 -Maximum 5
 if ($motivator -eq 1)
 {Write-Host "You are a Powershell God!"}
 if ($motivator -eq 2)
 {Write-Host "You rule dude!"}
 if ($motivator -eq 3)
 {Write-Host "I wish I could errorhandle like you"}
 if ($motivator -eq 4)
 {Write-Host "I am nothing compared to you"}
 if ($motivator -eq 5)
 {Write-Host "Are you sure you intirely human? 'cause you seem to cool to be real"}
 <# 
 .Synopsis 
 Show som motivational words on the screen
 .Description
 This function will print some motivational words on the screen
 .Example 
 Motivate-Me
 Show som motivational words on the screen
 .Link 
 http://cloud.kemta.net 
 #>
 }

Now all you need to do is write Motivate-Me in the powershell window to receive some inspirational words Smilie: :)

Posted in Microsoft, Powershell Tagged , ,

Powershell function for showing some system information

This is a function I created just because I wanted to toy around with Powershell and get-wmiobject. Also, this is my first function where I made it possible to use a switch parameter.

What the function does is gather some system information using get-wmiobject. The info is written to a temp file and then shown using out-gridview.
If the KeepTempFile parameter is used the temp file is saved in the users profile, if not it is deleted after the function finishes.

Heres the code:

function Show-Debug
 {
 Param(
 [switch]$KeepTempFile
 )
 $tempfile = "$env:userprofilepstempfile.txt"
 New-Item $tempfile -ItemType file -Force
 Get-WmiObject -Class Win32_ComputerSystem |fl Manufacturer,Model,Name,Domain,PrimaryOwnerName | Out-File $tempfile -Append
 Get-WmiObject -class "Win32_BIOS" -namespace "rootCIMV2" -computername localhost | fl BIOSVersion,Serialnumber,Status | Out-File $tempfile -Append
 Get-WmiObject Win32_OperatingSystem | fl @{Expression={$_.Caption};Label="OS Name"},SerialNumber,OSArchitecture,Version | Out-File $tempfile -Append
 Get-WmiObject Win32_PhysicalMemory | ft Tag,Capacity,Speed | Out-File $tempfile -Append
 Get-WmiObject Win32_Processor | fl DeviceID,Manufacturer,Caption,Name,NumberOfCores,NumberOfLogicalProcessors,MaxClockSpeed,CurrentClockSpeed,L2CacheSize,L3CacheSize,Status | Out-File $tempfile -Append
 Get-Content $tempfile | Out-GridView
 if ($KeepTempFile){
 Write-Host "Log file is now saved as $tempfile"
 }
 Else {
 Remove-Item $tempfile
 }
 <#
 .Synopsis
 Show some information about your computer
 .Description
 This function will create a txt file which will be populated with some information from wmi. It will then show the info to the user and delete the file
 .Parameter KeepTempFile
 Setting this parameter will keep the txt file with all info
 .Example
 Show-Debug
 Gathers info and show it on screen
 .Link
 http://cloud.kemta.net
 #>
 }

Posted in Microsoft, Powershell Tagged , , , , , ,