search
Categories
Sponsors
VirtualMetric Hyper-V Monitoring, Hyper-V Reporting
Archive
Blogroll

Badges
MCSE
Community

Cozumpark Bilisim Portali
Posted in Exchange Server, Windows Powershell | 2 Comments | 2,489 views | 27/11/2014 02:00

You may have many reasons to get your config backup of Exchange Server instead of Windows backup. For example, you may want to create a test environment. So in that case, you can use this script to backup your Exchange Server 2010 environment and restore to new Exchange Server 2013.

This script is in v1.1. Backups and restores Accepted Domains, Mailboxes, User Information, Mailbox Permissions, Mail Contacts, Distribution Groups.

First backup your Exchange Server:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Backup Accepted Domains
$AcceptedDomains = Get-AcceptedDomain | ConvertTo-Json
$AcceptedDomains | Set-Content -Path AcceptedDomains.txt
 
# Backup Mailboxes
$Mailboxes = Get-Mailbox -RecipientTypeDetails UserMailbox | ConvertTo-Json
$Mailboxes | Set-Content -Path Mailboxes.txt
 
# Backup User Information
$Users = Get-User | ConvertTo-Json
$Users | Set-Content -Path Users.txt
 
# Backup Mailbox Permissions
$MailboxPermissions = Get-Mailbox -RecipientTypeDetails UserMailbox | Get-MailboxPermission | where {$_.user.tostring() -ne "NT AUTHORITY\SELF" -and $_.IsInherited -eq $false} | Select @{Name='Name';Expression={[string]$_.Identity.Name}},@{Name='AccessRights';Expression={[string]::join(', ', $_.AccessRights)}},@{Name='User';Expression={[string]$_.User.RawIdentity}} | ConvertTo-Json
$MailboxPermissions | Set-Content -Path MailboxPermissions.txt
 
# Backup Mail Contacts
$MailContacts = Get-MailContact | ConvertTo-Json
$MailContacts | Set-Content -Path MailContacts.txt
 
# Backup Distribution Groups
$DistributionGroups = Get-DistributionGroup | Select *, @{label="Members";expression={($_ | Get-DistributionGroupMember).Name}} | ConvertTo-Json
$DistributionGroups | Set-Content -Path DistributionGroups.txt

You will see config backups under your current PowerShell path. Transfer them to new Exchange server.
You can restore all data with following script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# Load JSon Serialization
$LoadJson = [System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")
$JsonSerial= New-Object -TypeName System.Web.Script.Serialization.JavaScriptSerializer
$JsonSerial.MaxJsonLength = [int]::MaxValue
 
# Restore Accepted Domains
$AcceptedDomainsRaw = Get-Content -Path AcceptedDomains.txt -Raw
$AcceptedDomains = $JsonSerial.DeserializeObject($AcceptedDomainsRaw)
 
# Restore Mailboxes
$MailboxesRaw = Get-Content -Path Mailboxes.txt -Raw
$Mailboxes = $JsonSerial.DeserializeObject($MailboxesRaw)
 
# Restore User Information
$UsersRaw = Get-Content -Path Users.txt -Raw
$Users = $JsonSerial.DeserializeObject($UsersRaw)
 
# Restore Mailbox Permissions
$MailboxPermissionsRaw = Get-Content -Path MailboxPermissions.txt -Raw
$MailboxPermissions = $JsonSerial.DeserializeObject($MailboxPermissionsRaw)
 
# Restore Mail Contacts
$MailContactsRaw = Get-Content -Path MailContacts.txt -Raw
$MailContacts = $JsonSerial.DeserializeObject($MailContactsRaw)
 
# Restore Distribution Groups
$DistributionGroupsRaw = Get-Content -Path DistributionGroups.txt -Raw
$DistributionGroups = $JsonSerial.DeserializeObject($DistributionGroupsRaw)
 
Write-Host "Working on Accepted Domains.."
Write-Host " "
 
# Set Accepted Domains
foreach ($AcceptedDomain in $AcceptedDomains)
{
	$CheckAcceptedDomain = Get-AcceptedDomain | Where DomainName -eq $AcceptedDomain.DomainName.Address
	if (!$CheckAcceptedDomain)
	{
		Write-Host $AcceptedDomain.DomainName.Address is not exist. Creating.. -ForegroundColor Red
		$NewAcceptedDomain = New-AcceptedDomain -Name $AcceptedDomain.Name -DomainName $AcceptedDomain.DomainName.Address
	}
	else
	{
		Write-Host $AcceptedDomain.Name is already available. -ForegroundColor Green
	}
}
 
Write-Host " "
Write-Host " "
Write-Host "Working on Mailboxes.."
Write-Host " "
 
# Set Variables
$Database = "FABRIKAM"
$OrganizationalUnit = "fabrikam.com/Contoso"
$SecurePassword = ConvertTo-SecureString "12qwaszxcv!" -AsPlainText -Force
 
# Set Mailboxes
foreach ($Mailbox in $Mailboxes)
{
	if ($Mailbox.RecipientTypeDetails -eq "UserMailbox")
	{
		$CheckMailbox = Get-Mailbox | Where {$_.SamAccountName -eq $Mailbox.SamAccountName}
		if (!$CheckMailbox)
		{
			Write-Host $Mailbox.SamAccountName is not exist. Creating.. -ForegroundColor Red
 
			#$Database = $Mailbox.Database
			#$OrganizationalUnit = $Mailbox.OrganizationalUnit
			$NewMailbox = New-Mailbox -Password $SecurePassword -UserPrincipalName $Mailbox.UserPrincipalName -Name $Mailbox.Name -Database $Database -DisplayName $Mailbox.DisplayName -FirstName $Mailbox.FirstName -Initials $Mailbox.Initials -LastName $Mailbox.LastName -OrganizationalUnit $OrganizationalUnit -PrimarySmtpAddress ($Mailbox.PrimarySmtpAddress.Local + "@" + $Mailbox.PrimarySmtpAddress.Domain) -SamAccountName $Mailbox.SamAccountName
		}
		else
		{
			Write-Host $Mailbox.SamAccountName is already available. -ForegroundColor Green
		}
	}
	else
	{
		Write-Host Skipping $Mailbox.SamAccountName discovery mailbox.. -ForegroundColor Green
	}
}
 
Write-Host " "
Write-Host " "
Write-Host "Working on Email Addresses.."
Write-Host " "
 
# Set Email Addresses
foreach ($Mailbox in $Mailboxes)
{
	if ($Mailbox.RecipientTypeDetails -eq "UserMailbox")
	{
		$MailboxEmailAddresses = $Mailbox.EmailAddresses
 
		$TargetMailbox = Get-Mailbox | Where {$_.SamAccountName -eq $Mailbox.SamAccountName}
 
		foreach ($MailboxEmailAddress in $MailboxEmailAddresses)
		{
			$EmailAddress = $MailboxEmailAddress.Remove(0,5)
 
			$CheckEmailAddress = $TargetMailbox.EmailAddresses | where SMTPAddress -eq $EmailAddress
 
			if (!$CheckEmailAddress)
			{				
				Write-Host $EmailAddress is not exist. Adding.. -ForegroundColor Red
				$AddEmailAddress = $TargetMailbox | Set-Mailbox -EmailAddresses @{add="$EmailAddress"}
			}
			else
			{
				Write-Host $EmailAddress is already available. -ForegroundColor Green
			}
		}
	}
	else
	{
		Write-Host Skipping $Mailbox.SamAccountName discovery mailbox.. -ForegroundColor Green
	}
}
 
Write-Host " "
Write-Host " "
Write-Host "Working on Mailbox Permissions.."
Write-Host " "
 
# Set Mailbox Permissions
foreach ($MailboxPermission in $MailboxPermissions)
{
	$MailboxPermissionUsername = "FABRIKAM\" + ($MailboxPermission.User).Split("\")[-1]
	$CheckMailboxPermission = Get-Mailbox -Identity $MailboxPermission.Name | Get-MailboxPermission | where {$_.user.tostring() -eq $MailboxPermissionUsername -and $_.AccessRights -eq $MailboxPermission.AccessRights}
 
	if (!$CheckMailboxPermission)
	{
		Write-Host $MailboxPermissionUsername doesnt have permission on $MailboxPermission.Name mailbox. Adding.. -ForegroundColor Red
		$AddMailboxPermission = Add-MailboxPermission -Identity $MailboxPermission.Name -User $MailboxPermissionUsername -AccessRights $MailboxPermission.AccessRights -InheritanceType All
	}
	else
	{
		Write-Host $MailboxPermissionUsername has permission on $MailboxPermission.Name mailbox. Skipping.. -ForegroundColor Green
	}
}
 
Write-Host " "
Write-Host " "
Write-Host "Working on Mail Contacts.."
Write-Host " "
 
# Set Variables
$OrganizationalUnit = "fabrikam.com/Contoso"
 
# Set Mail Contacts
foreach ($MailContact in $MailContacts)
{
	$CheckMailContact = Get-MailContact | Where Name -eq $MailContact.Name
	if (!$CheckMailContact)
	{
		#$OrganizationalUnit = $Mailbox.OrganizationalUnit
 
		Write-Host $MailContact.Name is not exist. Creating.. -ForegroundColor Red
		$AddMailContact = New-MailContact -Name $MailContact.Name -DisplayName $MailContact.DisplayName -ExternalEmailAddress $MailContact.ExternalEmailAddress.SmtpAddress -OrganizationalUnit $OrganizationalUnit
	}
	else
	{
		Write-Host $MailContact.Name is already available. -ForegroundColor Green
	}
}
 
Write-Host " "
Write-Host " "
Write-Host "Working on Distribution Groups.."
Write-Host " "
 
# Set Variables
$OrganizationalUnit = "fabrikam.com/Contoso"
 
# Set Distribution Groups
foreach ($DistributionGroup in $DistributionGroups)
{
	$CheckDistributionGroup = Get-DistributionGroup | Where Name -eq $DistributionGroup.Name
	if (!$CheckDistributionGroup)
	{
		#$OrganizationalUnit = $Mailbox.OrganizationalUnit
 
		Write-Host $DistributionGroup.Name is not exist. Creating.. -ForegroundColor Red
		$AddDistributionGroup = New-DistributionGroup -Name $DistributionGroup.Name -Alias $DistributionGroup.Alias -DisplayName $DistributionGroup.DisplayName -Members $DistributionGroup.Members.value -Notes $DistributionGroup.Notes -OrganizationalUnit $OrganizationalUnit -PrimarySmtpAddress ($DistributionGroup.PrimarySmtpAddress.Local + "@" + $DistributionGroup.PrimarySmtpAddress.Domain) -SamAccountName $DistributionGroup.SamAccountName -Type "Distribution"
	}
	else
	{
		Write-Host $DistributionGroup.Name is already available. -ForegroundColor Green
	}
}

There are some variables that you may can change. So you can restore backups into different Exchange environment as well.


Posted in Exchange Server, Windows Powershell | No Comment | 1,639 views | 26/11/2014 11:10

You can export txt based config backups of your Exchange Server 2010 environment with following script.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Backup Accepted Domains
$AcceptedDomains = Get-AcceptedDomain | ConvertTo-Json
$AcceptedDomains | Set-Content -Path AcceptedDomains.txt
 
# Backup Mailboxes
$Mailboxes = Get-Mailbox | ConvertTo-Json
$Mailboxes | Set-Content -Path Mailboxes.txt
 
# Backup User Information
$Users = Get-User | ConvertTo-Json
$Users | Set-Content -Path Users.txt
 
# Backup Mailbox Permissions
$MailboxPermissions = Get-Mailbox | Get-MailboxPermission | where {$_.user.tostring() -ne "NT AUTHORITY\SELF" -and $_.IsInherited -eq $false} | Select Identity,User,@{Name='Access Rights';Expression={[string]::join(', ', $_.AccessRights)}} | ConvertTo-Json
$MailboxPermissions | Set-Content -Path MailboxPermissions.txt
 
# Backup Mail Contacts
$MailContacts = Get-MailContact | ConvertTo-Json
$MailContacts | Set-Content -Path MailContacts.txt
 
# Backup Distribution Groups
$DistributionGroups = Get-DistributionGroup | Select *, @{label="Members";expression={($_ | Get-DistributionGroupMember).Name}} | ConvertTo-Json
$DistributionGroups | Set-Content -Path DistributionGroups.txt

I’ll also publish an import script to show you how to restore this config into your system again.


Posted in Exchange Server, Windows Powershell | No Comment | 1,831 views | 26/11/2014 11:01

I looked for a powershell command to get distribution groups and members in one command but it seems it’s not possible.

So I used an expression to merge them. You can check my following code:

1
Get-DistributionGroup | Select Name, @{label="Members";expression={($_ | Get-DistributionGroupMember).Name}}

Output will be like:

Name Members
—- ——-
Customer Services {Yusuf Ozturk, Bertan Demirci}

You can see all other fields by using:

1
Get-DistributionGroup | Select *, @{label="Members";expression={($_ | Get-DistributionGroupMember).Name}}

You can also add other field by using additional expressions.


Posted in Windows Powershell | No Comment | 2,555 views | 15/11/2014 10:37

This is a text mining example for PowerShell. You can export your Whatsapp conversations
to find out which words you used most.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$Contents = Get-Content Whatsapp.txt -Encoding UTF8
$TagCloud = @{"Whatsapp" = "1"}
$ChatArray = New-Object System.Collections.ArrayList
foreach ($Content in $Contents)
{
	$Words = $Content.Split(" ")
	foreach ($Word in $Words)
	{
		$Word = $Word.ToLower();
 
		if ($ChatArray.Contains($Word) -eq $True)
		{
			$TagCloud.($Word) = [int]$TagCloud.($Word)+1;
		}
		else
		{
			$AddArray = $ChatArray.Add("$Word")
			$TagCloud.($Word) = 1;
		}
	}
}
$TagCloud.GetEnumerator() | Sort-Object -Property Value -Descending

Then you can convert it to tag cloud by using public tag cloud services.


Posted in Windows Powershell | No Comment | 1,576 views | 31/10/2014 17:39

If you create a secure password on PowerShell and output it into a txt file, you can decrypt it on another Windows machine. So we use a predefined user key to create our secure passwords:

There was a question about this post. So how you can create your own key?

So what you need to do is:

1
2
3
4
$SecureKey = New-Object byte[](16)
$RNGCryptoServiceProvider = [System.Security.Cryptography.RNGCryptoServiceProvider]::Create()
$RNGCryptoServiceProvider.GetBytes($SecureKey)
$SecureKey

That will create a random key for you. So you can replace it with predefined key.


Posted in Windows Powershell, Windows Server | No Comment | 2,958 views | 05/10/2014 15:21

You can use following script to get passthrough disk reports from Hyper-V Clusters:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Get Clusters
$Clusters = Get-Content Clusters.txt
 
foreach ($Cluster in $Clusters)
{
	# Get Cluster Nodes
	$ClusterNodes = Get-Cluster $Cluster | Get-ClusterNode
 
	foreach ($ClusterNode in $ClusterNodes)
	{
		Write-Host Working on $ClusterNode
 
		# Clear PT Values
		$PTDisks = $Null;
		$DiskNumber = $Null;
 
		# Get Passthrough Disks
		$PTDisks = Get-VM -ComputerName $ClusterNode | Get-VMHardDiskDrive | Where Path -like Disk*
 
		foreach ($PTDisk in $PTDisks)
		{
			# Get VM Name
			$VMName = $PTDisk.VMName
 
			Write-Host Working on $VMName
 
			# Get Passthrough Disk Info
			$PTInfo = $PTDisk.Path
			$DiskNumber = $PTDisk.DiskNumber
			$ControllerNumber = $PTDisk.ControllerNumber
			$ControllerLocation = $PTDisk.ControllerLocation
			$ControllerType = $PTDisk.ControllerType
			Write-Host Working on Disk $DiskNumber
 
			if (!$DiskNumber)
			{
				$DiskNumber = $PTInfo.Split(" ")[1]
			}
 
			# Get Disk Info
			$DiskInfo = Get-WmiObject Win32_DiskDrive -ComputerName $ClusterNode | Where Index -eq $DiskNumber
			$Model = $DiskInfo.Model
			$Caption = $DiskInfo.Caption
			$Signature = $DiskInfo.Signature
			$Size = [math]::round($DiskInfo.Size / 1GB,0)
 
			# Set Output
			$Value = $VMName + ";" + $ClusterNode + ";" + $ControllerType + ";" + $ControllerNumber + ";" + $ControllerLocation + ";" + $DiskNumber + ";" + $Model + ";" + $Signature + ";" + $Size
 
			# Informational Output
			Add-Content -Value $Value -Path Output.txt
		}
	}
}

You need to add your clusters into Clusters.txt file.


Posted in Windows Powershell, Windows Server | No Comment | 2,550 views | 23/09/2014 04:25

This is an example script to show how you can monitor Supermicro servers via PowerShell:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# Test Supermicro CLI Path
$TestSupermicroCLIPath = Test-Path -Path "C:\Program Files\Supermicro\SuperDoctor5\sdc.bat"
 
if ($TestSupermicroCLIPath -eq $True)
{				
	# Test Supermicro CLI Output
	$SensorInfo = Invoke-Command -ScriptBlock {
		&'C:\Program Files\Supermicro\SuperDoctor5\sdc.bat' "-d"
	}
}
 
# Create Supermicro Sensors Function
function Get-SupermicroSensor
{
	param ($SensorSource)
 
	if ($SensorSource)
	{
		# Get Supermicro Sensors
		$SupermicroSensors = $SensorSource | Select-String "2.1.1.1.1.2."
 
		# Parse Supermicro Output
		foreach ($SupermicroSensor in $SupermicroSensors)
		{
			# Clear Values
			$SupermicroSensorCurrentReading = $Null;
			$SupermicroSensorHighLimit = $Null;
			$SupermicroSensorLowLimit = $Null;
			$SupermicroSensorMetric = $Null;
 
			# Get Sensor Information
			$SupermicroSensorValues = $SupermicroSensor.ToString().Split(",")
			$SupermicroSensorID = ($SupermicroSensorValues[0]).Split(".")[-1]
			$SupermicroSensorName = $SupermicroSensorValues[-1]
 
			# Get Sensor Results
			$SupermicroSensorCurrentReading = $SensorSource | Select-String "2.1.1.1.1.4.$SupermicroSensorID\b"
			$SupermicroSensorHighLimit = $SensorSource | Select-String "2.1.1.1.1.5.$SupermicroSensorID\b"
			$SupermicroSensorLowLimit = $SensorSource | Select-String "2.1.1.1.1.6.$SupermicroSensorID\b"
			$SupermicroSensorMetric = $SensorSource | Select-String "2.1.1.1.1.11.$SupermicroSensorID\b"
 
			# Parameter Validation
			if (!$SupermicroSensorCurrentReading) { [string]$SupermicroSensorCurrentReading = "Unknown" } else { [string]$SupermicroSensorCurrentReading = $SupermicroSensorCurrentReading.ToString().Split(",")[-1] }
			if (!$SupermicroSensorHighLimit) { [string]$SupermicroSensorHighLimit = "Unknown" } else { [string]$SupermicroSensorHighLimit = $SupermicroSensorHighLimit.ToString().Split(",")[-1] }
			if (!$SupermicroSensorLowLimit) { [string]$SupermicroSensorLowLimit = "Unknown" } else { [string]$SupermicroSensorLowLimit = $SupermicroSensorLowLimit.ToString().Split(",")[-1] }
			if (!$SupermicroSensorMetric) { [string]$SupermicroSensorMetric = "Unknown" } else { [string]$SupermicroSensorMetric = $SupermicroSensorMetric.ToString().Split(",")[-1] }
 
			$Properties = New-Object Psobject
			$Properties | Add-Member Noteproperty ID $SupermicroSensorID
			$Properties | Add-Member Noteproperty Name $SupermicroSensorName
			$Properties | Add-Member Noteproperty CurrentReading $SupermicroSensorCurrentReading
			$Properties | Add-Member Noteproperty Metric $SupermicroSensorMetric
			$Properties | Add-Member Noteproperty HighLimit $SupermicroSensorHighLimit
			$Properties | Add-Member Noteproperty LowLimit $SupermicroSensorLowLimit
			Write-Output $Properties
		}
	}
}
 
# Get Supermicro Sensor Results
$SupermicroSensorResults = Get-SupermicroSensor -SensorSource $SensorInfo

You need to install Super Doctor 5 on your Supermicro server before using this script.