31 December 2014

PowerShell 5.0 and the OneGet commandlets

Great new feature coming up in WMF 5.0: OneGet.
Most people are familiar with the package managers within the different Linux tastes.

Well OneGet is just like that but then for Windows.
Command line based software installation and un-installation.
It works with the Chocolatey as the software repository which currently holds up 2561 applications.

There are 2 more repository's, PSGallery and MSPSGallery but they hold none to little applications.

First let's see what we can do with OneGet:

Get-Command -Module OneGet | Select Name

Name
----
Find-Package
Get-Package
Get-PackageProvider
Get-PackageSource
Install-Package
Register-PackageSource
Save-Package
Set-PackageSource
Uninstall-Package
Unregister-PackageSource

If you want to start using OneGet, you first have to install "nuget":

Find-Package

The provider 'nuget v2.8.3.6' is not installed.
'nuget' may be manually downloaded from
'https://oneget.org/nuget-anycpu-2.8.3.6.exe' and copied to 'C:\Program
Files\OneGet\ProviderAssemblies'.
Would you like OneGet to automatically download and install 'nuget' now?
[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"):

To view the installed repositories:
Get-PackageSource
To view the total number of packages in the repository:
Find-Package | Measure-Object
To show all the packages in the repository:
Find-Package | Sort-Object –Property Name | Out-GridView
Install a package:
install-package -Name imgburn
To uninstall a package:
uninstall-package -Name imgburn
Set the repository as trusted:
set-packagesource -name chocolatey -trusted
To unregister the Chocolatey repository:
Unregister-PackageSource –name Chocolatey

Source

16 December 2014

Schedule a PowerShell script with task scheduler

For all your status emails that you want to run every day the task scheduler is your friend, well sort of.
Sometimes i just can't understand why it throws errors at me.
I found a nice article about this over at Dmitry's blog.

1. Get your script ready
Surprising as it might sound, your script might actually not be ready to run in a scheduled task as is. This happens if it uses cmdlets from a particular PowerShell module or snapin, and it worked for you interactively because you used a specialized shell (e.g. Exchange Management Shell) or a tool like PowerGUI Script Editor which loads the modules for you.
If you indeed are using using any non-default cmdlets, simply add Add-PSSnapin or Import-Module to the beginning of the script. For example:

Add-PSSnapin Quest.ActiveRoles.ADManagement
2. Schedule the task
To schedule a task simply start Windows Task Scheduler and schedulepowershell.exe executable passing the script execution command as a parameter. The -File parameter is the default one so simply specifying the script path as the argument would work in a lot of cases:
You can find powershell.exe in your system32\WindowsPowerShell\v1.0 folder.
4. Report task success or failure
If you want your script to report success or failure (or some sort of other numerical result) simply use the exit keyword in the script to pass the value, e.g.:
exit 4
Then your Windows Task Scheduler will show the value in the Last Run Result (you might need to hit F5 to refresh the column in the task scheduler):
3. Passing parameters
If you need to pass parameters things get a little trickier. Say, you have a script which adds two numbers:
param($a=2, $b=2)
"Advanced calculations ahead"
exit $a + $b
To pass the numbers as parameters, you would want to use powershell.exe -Command instead of powershell.exe -File. This -Command argument will then have the script invocation operator &, path to the script, and the parameters. E.g.:
Program:C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe Add argument (optional)-Command "& c:\scripts\hello.ps1 -a 2 -b 3"
If you want to also get your exit code from the script, you would need to re-transmit that by adding exit $LASTEXITCODE to the command (I learnt this tip from MoW). E.g.
Program:C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe Add argument (optional)-Command "& c:\scripts\hello.ps1 -a 2 -b 3; exit $LASTEXITCODE"
5. Run x86 PowerShell on x64 Windows
On 64-bit versions of Windows you actually have both 64-bit and 32-bit versions of PowerShell. In most cases you don’t care but in some cases (e.g. specific COM objects being used) you might need specifically a 32-bit version. To get that to run, simply pick the proper executable when you schedule the task:
Regular PowerShell (64-bit version on 64-bit Windows):%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
32-bit PowerShell (x86):%SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe
6. Other options
To learn about all parameters PowerShell executable has simply run it with /? option (from either cmd.exe or a PowerShell session).
I normally use -noprofile to make sure that nothing in the PowerShell profile interferes with the task.
Also, if your Execution Policy does not allow running scripts the -ExecutionPolicy parameter comes handy allowing you to make an exception just for this task. E.g.:
c:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -File c:\scripts\hello.ps1 -ExecutionPolicy RemoteSigned
Here are some other parameters provided by PowerShell:
-PSConsoleFile
    Loads the specified Windows PowerShell console file. To create a console
    file, use Export-Console in Windows PowerShell.
I guess you could use that is you want the exact environment you have in the predefined shell from Exchange, AD, or SQL. E.g.: PowerShell -PSConsoleFile SqlSnapIn.Psc1
-Version
    Starts the specified version of Windows PowerShell.
I don’t think this one actually works.
-NoLogo
Hides the copyright banner at startup.
Not really relevant for scheduled tasks, imho…
-NoExit
    Does not exit after running startup commands.
Might be useful for troubleshooting.
-Sta
    Start the shell using a single-threaded apartment.
If your script needs STA mode (if you don’t know what this is – most likely you don’t need this. ;))
-NonInteractive
    Does not present an interactive prompt to the user.
Not really relevant for scheduled tasks, imho…
-InputFormat
    Describes the format of data sent to Windows PowerShell. Valid values are
    "Text" (text strings) or "XML" (serialized CLIXML format).

-OutputFormat
    Determines how output from Windows PowerShell is formatted. Valid values
    are "Text" (text strings) or "XML" (serialized CLIXML format).
-WindowStyle
    Sets the window style to Normal, Minimized, Maximized or Hidden.
Unfortunately, I could not make this work. I tried to use -WindowStyle Hiddento avoid the PowerShell console window popping up during task execution but with no luck.
-EncodedCommand
    Accepts a base-64-encoded string version of a command. Use this parameter
    to submit commands to Windows PowerShell that require complex quotation
    marks or curly braces.

    # To use the -EncodedCommand parameter:
    $command = 'dir "c:\program files" '
    $bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
    $encodedCommand = [Convert]::ToBase64String($bytes)
    powershell.exe -encodedCommand $encodedCommand
Can be useful when having to pass advanced expressions and getting issues with parser.

02 December 2014

Check WAN IP address at icanhazip.com and mail the results

Since my ISP had planned maintenance last week, i couldn't access my boxes at home from the internet. My WAN IP address had changed. This happens once a year maybe but it's annoying enough to make something for it.

I found a great script from Leon van Efferen, but it didn't do exactly what i needed so i modified it a bit.

First off the check against whatismyip.com didn't work anymore, so i modified that to check against icanhazip.com.

Which by the way you can also do from Powershell directly:
(Invoke-WebRequest icanhazip.com).Content.Trim()
Then i wanted to receive an email everyday just to know it's still working and to be able to check my IP address always, not only if it changes.

This is what i came up with:
###########################################################################
#
# NAME:  CheckWANIP 
#
# COMMENT: Check the WAN IP Address based on ifconfig.me Automation page
#   and e-mail a message .
#
###########################################################################

#Set Target Domain
$TargetDomain = "domain.com" #Enter your FQDN that is linked to your WAN ip address

Function SendMail {
$EmailFrom = "IPCheck@domain.com" #Enter the e-mail address it should send the message from.
$EmailTo = "user@domain.com" #Enter the e-mail address it should send the message to.
$Subject = "External IP Address at icanhazip.com is $current_WAN_IP" #Enter your subject the e-mail message should contain.
$Body = "Compare the IP addresses from domain.com $DNS_WAN_IP and DNS records from ifconfig.me $Current_WAN_IP"  #Enter the message that the e-mail should contain.
$SMTPServer = "smtp.gmail.com" #Enter the FQDN of your SMTP server eg. smtp.gmail.com
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 25) #Enter your SMTP Port eg. 587
$SMTPClient.EnableSsl = $false # Change to $false if you don't want to use SSL
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
}

# Do not change anything below this line.
$DNS_WAN_IP = [System.Net.Dns]::GetHostAddresses("$TargetDomain") | select-object IPAddressToString -expandproperty  IPAddressToString
Write-host "Resolved IP Address of $TargetDomain = $DNS_WAN_IP" 
$Current_WAN_IP = (Invoke-WebRequest icanhazip.com).Content.Trim()
Write-host "Current WAN IP Address = $Current_WAN_IP"
SendMail
Write-host "Sending email"
exit

Then you can schedule it as a daily task:
Powershell.exe "& 'C:\path to script\CheckWANIP.ps1'"

26 November 2014

How to Publish New Certificate Revocation List (CRL) from Offline Root CA to Inetpub

Its highly recommended when building your Microsoft PKI (Public Key Infrastructure) to have your Root CA offline after issuing the Enterprise Sub CA certificates. Its recommended to minimize the access to the Offline Root CA as possible. The Root CA is not a domain joined machine and can be turned off without any problem.

One of the Key issue is the CRL generated from the Root CA, you need to set the CRL interval for a large value so that we don’t need to copy the CRL to an online location frequently and do not implement delta CRLs, because the publication of each delta CRL would require access to the offline root CA in order to copy the delta CRL to an online publication location. In order to change the CRL interval you need to:

  1. Turn on the Offline Root CA and login with Admin account
  2. Open the Certification Authority Console
  3. Right Click on the "Revoked Certificates" and click Properties.
  4. Set “CRL Publish interval” to a large value (Default is 26 Weeks) and  uncheck “Publish Delta CRL” check-box.



In order to Publish a new CRL from the offline Root CA to the Enterprise Sub CA you need to do the following:

  1. Publish a new CRL on the Root CA, this can be done by Right Click the "Revoked Certificates" - All Tasks - Publish                                                                                                                                                                                                                                                          
                                                                                                                                                                     
  2. Copy the CRL file from the Root CA located under %systemroot%\system32\certsrv\certenroll to the Sub CA Server
  3. Turn off the Root CA
  4. Copy the above file to the InetPub folder (HTTP Path) in the Sub CA server which is by default located under the C:\inetpub\wwwroot\Certdata

This process of renewing the CRL and publishing a new one is manually done since the Root CA is offline and thats why its better to make the CRL publish interval more than the default value so you won't do it frequently. You may also want to set an automated reminder before the next renewal date.

Source

25 November 2014

All 101 Tips of the day

Tip of the day #1:

Did you know that the Identity parameter is a "positional parameter"? That means you can use:
Get-Mailbox "user" instead of: Get-Mailbox -Identity "user"
It's a neat usability shortcut!

Tip of the day #2:

Did you know that the Identity parameter is a "positional parameter"? That means you can use:
Get-Mailbox "user" instead of: Get-Mailbox -Identity "user"
It's a neat usability shortcut!

Tip of the day #3:

Did you know that the Identity parameter is a "positional parameter"? That means you can use:
Get-Mailbox "user" instead of: Get-Mailbox -Identity "user"
It's a neat usability shortcut!

Tip of the day #4:

Did you know that the Identity parameter is a "positional parameter"? That means you can use:
Get-Mailbox "user" instead of: Get-Mailbox -Identity "user"
It's a neat usability shortcut!

Tip of the day #5:

Tired of typing a long command every time that you want to do something? Alias it! Type:
Set-Alias GetMre Get-ManagementRoleEntry
For all the current aliases, type:
Get-Alias

Tip of the day #6:

Want to see the members of a dynamic distribution group that has a custom filter? Just use the Get-Recipient cmdlet. Type:
$DDG = Get-DynamicDistributionGroup "Contoso Marketing Managers"
  Get-Recipient -RecipientPreviewFilter $DDG.RecipientFilter

Tip of the day #7:

The Exchange Management Shell is a calculator too! Try it directly at a command prompt:
1.2343+3123 or (23/435)*2

Tip of the day #8:

Command line SOS! Do you need help? Type:
Help <cmdlet-name>  or  <cmdlet-name> -?
You can choose what information to return when you view Help by using the Detailed, Full, and Examples switches:
Help Get-Mailbox -Detailed

Tip of the day #9:

Want to look at Help for a cmdlet but don't want to read through pages and pages of text in the Shell window? Just use the Online switch with the Get-Help cmdlet. The Online switch tells the Shell to open the online version of the cmdlet's Help topic in your default browser. Type:
Get-Help <cmdlet> -Online

Tip of the day #10:

The tilde character (~) should be familiar to Unix users. It represents the shortcut to your root directory. To see what it's evaluated to by default, type:
Dir ~
You can use it as a useful shortcut:
Cp SomeFile "~\My Documents"

Tip of the day #11:

CTRL+C is the equivalent of the hard-break command in the Exchange Management Shell. If a command is taking too long to run or you want to cancel an operation quickly, press CTRL+C to stop execution.

Tip of the day #12:
Pushd and Popd work the same way in the Exchange Management Shell as they do in cmd.exe. Type:
Pushd <location>

Tip of the day #13:

XML over everything! The Exchange Management Shell treats XML as a native type, so that you can do interesting things like:
$Sample = [XML](Get-Content SomeXMLFile.xml)
This command assigns $Sample to the actual XML object. To see it, type:
$Sample
To navigate, type:
$Sample.Prop1.Prop2
No need for text parsing when you want to load XML data!

Tip of the day #14:

Cmdlets that end in "Config" manage singleton configuration, either one per server or organization. For these tasks, you don't have to specify an identity because there is only one instance of the configuration. You may have to specify the Server parameter if the configuration is per server.

Tip of the day #15:

To get a list of all users on an Exchange 2010 server who aren't Unified Messaging-enabled, type:
$Mailboxes = Get-Mailbox
  $Mailboxes | ForEach { If($_.UmEnabled -Eq $False){$_.Name}}

Tip of the day #16:

To get a list of all users on an Exchange 2010 server who are Unified Messaging-enabled, type:
$Mailboxes = Get-Mailbox
  $Mailboxes = | ForEach { If($_.UmEnabled -Eq $True){$_.Name}}

Tip of the day #17:

To display the user's alias formatted in a table together with the user's Exchange 2010 server name and telephone extension, type:
Get-Mailbox | Format-Table ServerName,@{e={$_.SamAccountName};Label="User Alias"},@{Expression="Extensions";Label="Telephone numbers"}

Tip of the day #18:

To display the list of UM IP gateway server names disabled for outbound calling and hunt groups associated with a UM IP gateway server, type:
$Gateways = Get-UMIPGateway
  $Gateways | ForEach {If($_.OutCallsAllowed -Eq $False){ "Gateway Name = " +$_.Name;ForEach ($HuntGroup In $_.Huntgroups ){"Huntgroups " + $Huntgroup}}}

Tip of the day #19:

If you want to test all IP Block List providers, you just have to pipe the Get-IpBlockListProvider cmdlet to the Test-Ip BlockListProvider cmdlet:
Get-IpBlockListProvider | Test-IpBlockListProvider -IpAddress 192.168.0.1

Tip of the day #20:

Before you remove an object by using the Remove verb, use the WhatIf parameter to verify the results are what you expect.

Tip of the day #21:

Sometimes it's useful to convert the output of a cmdlet to a string to interoperate with native cmdlets. For example, type:
Get-Mailbox | Out-String | Findstr "Administrator"

Tip of the day #22:

Get all Win32 WMI information, such as Perfmon counters and local computer configurations. For example, type:
Get-WMIObject Win32_PerfRawData_PerfOS_Memory

Tip of the day #23:

Who isn't tired of spam? You can configure real-time block list (RBL) providers with the Exchange Management Shell by running the following two commands:
Set-IPBlockListProvidersConfig -Enabled $True -ExternalMailEnabled $True
and then
Add-IPBlockListProvider -Name <Name of RBL Provider> -LookupDomain <FQDN of RBL Provider> -AnyMatch $True

Tip of the day #24:

Access the event log from the Exchange Management Shell. To retrieve the whole event log, type:
Get-EventLog Application | Format-List
To retrieve all Exchange-related events, type:
Get-EventLog Application | Where { $_.Source -Ilike "*Exchange*" }

Tip of the day #25:

One benefit of the Exchange Management Shell is that cmdlets can output objects to the console. You can then manipulate this output and organize it in interesting ways. For example, to get a quick view in tabular format, use Format-Table:
Get-Mailbox | Format-Table Name,Database,RulesQuota

Tip of the day #26:

Forget a property name? Not a problem because you can use wildcard characters to retrieve all properties that match the part of the name that you specify:
Get-Mailbox | Format-Table Name,*SMTP*

Tip of the day #27:

Want to work with data contained in a CSV file? Use Import-CSV to assign the data to an object. For example, type:
$MyCSV = Import-CSV TestFile.CSV
You can then manipulate the data easily in the Exchange Management Shell. For example, if there is a column called Mailboxes in the CSV data, you can use the following commands to sort or group the data by the Mailboxes column:
To sort: $MyCSV | Sort Mailboxes
To group: $MyCSV | Group Mailboxes

Tip of the day #28:

This command spins through all your mailbox servers and reconnects all the uniquely identified but disconnected mailboxes in any one of the mailbox stores:
$Servers = Get-ExchangeServer
  $Servers | `
  Where { $_.IsMailboxServer -Eq '$True' } `
  | ForEach { Get-MailboxStatistics -Server $_.Name `
  | Where { $_.DisconnectDate -NotLike '' } `
  | ForEach { Connect-Mailbox -Identity `
    $_.DisplayName -Database $_.DatabaseName} }

Tip of the day #29:

Tab completion reduces the number of keystrokes required to complete a cmdlet. Just press the TAB key to complete the cmdlet you are typing. Tab completion kicks in whenever there is a hyphen (-) in the input. For example:
Get-Send<tab>
should complete to Get-SendConnector. You can even use wildcards, such as:
Get-U*P*<tab>
Pressing the TAB key when you enter this command cycles through all cmdlets that match the expression, such as the Unified Messaging Mailbox policy cmdlets.

Tip of the day #30:

Tab completion reduces the number of keystrokes required to complete a cmdlet. Just press the TAB key to complete the cmdlet you are typing. Tab completion kicks in whenever there is a hyphen (-) in the input. For example:
Get-Send<tab>
should complete to Get-SendConnector. You can even use wildcards, such as:
Get-U*P*<tab>
Pressing the TAB key when you enter this command cycles through all cmdlets that match the expression, such as the Unified Messaging Mailbox policy cmdlets.

Tip of the day #31:

Tab completion reduces the number of keystrokes required to complete a cmdlet. Just press the TAB key to complete the cmdlet you are typing. Tab completion kicks in whenever there is a hyphen (-) in the input. For example:
Get-Send<tab>
should complete to Get-SendConnector. You can even use wildcards, such as:
Get-U*P*<tab>
Pressing the TAB key when you enter this command cycles through all cmdlets that match the expression, such as the Unified Messaging Mailbox policy cmdlets.

Tip of the day #32:

Tab completion reduces the number of keystrokes required to complete a cmdlet. Just press the TAB key to complete the cmdlet you are typing. Tab completion kicks in whenever there is a hyphen (-) in the input. For example:
Get-Send<tab>
should complete to Get-SendConnector. You can even use wildcards, such as:
Get-U*P*<tab>
Pressing the TAB key when you enter this command cycles through all cmdlets that match the expression, such as the Unified Messaging Mailbox policy cmdlets.

Tip of the day #33:

Want to create a group of test users in your lab? Use this command:
1..100 | ForEach { Net User "User$_" MyPassword=01 /ADD /Domain; Enable-Mailbox "User$_" }

Tip of the day #34:

Like the Exchange Management Shell Tip of the Day? Try this:
Get-Tip

Tip of the day #35:

Want to change the authentication settings on an Outlook Web Access virtual directory? Try the following command as an example. It changes authentication from forms-based authentication to Windows authentication:
Set-OwaVirtualDirectory -Identity "OWA (Default Web Site)" -FormsAuthentication 0 -WindowsAuthentication 1

Tip of the day #36:

Want to set the properties on all or some Outlook Web Access virtual directories? Pipe the output of Get-OwaVirtualDirectory to the Set-OwaVirtualDirectory cmdlet. For example, the following command sets the Gzip level for all Outlook Web Access virtual directories:
Get-OwaVirtualDirectory | Set-OwaVirtualDirectory -GzipLevel High

Tip of the day #37:

Want to remove an ActiveSync device from a user's device list? Type:
Remove-ActiveSyncDevice
This cmdlet can be helpful for troubleshooting devices that don't synchronize successfully with the server.

Tip of the day #38:

Want to clear all data from a mobile device? Use:
Clear-ActiveSyncDevice
Specify a time of day to clear the device, or let the task complete the next time that the device connects to the server
.

Tip of the day #39:

Want to see a list of all devices that synchronize with a user's mailbox? Type:
Get-ActiveSyncDeviceStatistics
A variety of information is returned including device name, operating system, and last sync time.

Tip of the day #40:

Has one of your users asked you to recover their mobile device synchronization password? To return the user's password, type:
Get-ActiveSyncDeviceStatistics -ShowRecoveryPassword

Tip of the day #41:

Want to move your database path to another location? Type:
Move-DatabasePath -EdbFilePath DestFileName
To change the file path setting without moving data, use this command together with the ConfigurationOnly parameter. This command is especially useful for disaster recovery. Caution: Misuse of this cmdlet will cause data loss.

Tip of the day #42:

Need an easy way to add a new primary SMTP address to a group of mailboxes? The following command creates a new e-mail address policy that assigns the @contoso.com domain to the primary SMTP address of all mailboxes with Contoso in the company field:
New-EmailAddressPolicy -Name Contoso -RecipientFilter {Company -Eq "Contoso"} -EnabledPrimarySMTPAddressTemplate "@contoso.com"

Tip of the day #43:

Want to retrieve a group of objects that have similar identities? You can use wildcard characters with the Identity parameter to match multiple objects. Type:
Get-Mailbox *John*
  Get-ReceiveConnector *toso.com
  Get-JournalRule *discovery*

Tip of the day #44:

Want to configure a group of objects that have similar identities? You can use wildcard characters with the Identity parameter when you use a Get cmdlet and pipe the output to a Set cmdlet. Type:
$Mailboxes = Get-Mailbox *John*
$Mailboxes | Set-Mailbox -ProhibitSendQuota 100MB -UseDatabaseQuotaDefaults $False
This command matches all mailboxes with the name John in the mailbox's identity and sets the ProhibitSendQuota parameter to 100MB. It also sets the UseDatabaseQuotaDefaults parameter to $False so that the server uses the new quota you specified instead of the database default quota limits.

Tip of the day #45:

Forgot what the available parameters are on a cmdlet? Just use tab completion! Type:
Set-Mailbox -<tab>
When you type a hyphen (-) and then press the TAB key, you cycle through all the available parameters on the cmdlet. Want to narrow your search? Type part of the parameter's name and then press the TAB key. Type:
Set-Mailbox -Prohibit<tab>

Tip of the day #46:

Want to add an alias to multiple distribution groups that have a similar name? Type:
$Groups = Get-DistributionGroup *Exchange*
$Groups | Add-DistributionGroupMember -Member kim
This command adds the alias kim to all distribution groups that contain the word Exchange.

Tip of the day #47:

Want to record exactly what happens when you're using the Exchange Management Shell? Use the Start-Transcript cmdlet. Anything that you do after you run this cmdlet will be recorded to a text file that you specify. To stop recording your session, use the Stop-Transcript cmdlet.
Notice that the Start-Transcript cmdlet overwrites the destination text file by default. If you want to append your session to an existing file, use the Append parameter:
Start-Transcript c:\MySession.txt -Append

Tip of the day #48:

Do you have a user who has network access but maintains an external mail account outside your Exchange organization? With Exchange Server 2010, you can now create mail-enabled users that are regular Active Directory accounts, but also behave like mail-enabled contacts. By using the Enable-MailUser cmdlet, you can add e-mail contact attributes to any existing Active Directory user who doesn't already have a mailbox on an Exchange server. Users in your Exchange organization will then be able to send e-mail messages to that user's external mail account. Type:
Enable-MailUser -Identity <Active Directory Alias> -ExternalEmailAddress <Destination SMTP Address>

Tip of the day #49:

Want to change the default prohibit send quota for a mailbox database? Type:
Set-MailboxDatabase <Mailbox Database Name> -ProhibitSendQuota <New Quota Size> -UseDatabaseQuotaDefaults $False
You can specify a bytes qualifier when you use the ProhibitSendQuota parameter. For example, if you want to set the prohibit send quota to 200 megabytes, type:
Set-MailboxDatabase <Mailbox Database Name> ProhibitSendQuota 200MB -UseDatabaseQuotaDefaults $False
You can also configure the IssueWarningQuota parameter and the ProhibitSendReceiveQuota parameter in the same way.

Tip of the day #50:

Want to know what version of Exchange Server each of your servers is running? Type:
Get-ExchangeServer | Format-Table Name, *Version*

Tip of the day #51:

Want to determine whether a server is running Exchange Server 2010 Standard Edition or Exchange Server 2010 Enterprise Edition? Type:
Get-ExchangeServer <Server Name> | Format-Table Name, Edition
If you want to view which edition all your Exchange servers are running, omit the <Server Name> parameter.

Tip of the day #52:

Want to create a new resource mailbox that can be used to book a meeting room? Type:
New-Mailbox -Name <Conference Room Name> -UserPrincipalName <SMTP Address> -OrganizationalUnit <Organizational Unit> -Room
This command creates a disabled Active Directory user who has a mailbox that accepts meeting requests from users.

Tip of the day #53:

Want to control the properties of e-mail messages sent to a specific domain? Use the RemoteDomain cmdlets. Create a new remote domain by using the New-RemoteDomain cmdlet. Type:
New-RemoteDomain -Name "Contoso.com Configuration" -DomainName contoso.com
Then modify the properties that you want for this remote domain by using the Set-RemoteDomain cmdlet:
Set-RemoteDomain "Contoso.com Configuration" -AutoReplyEnabled $True -AutoForwardEnabled $True

Tip of the day #54:

You can control which features are available to Outlook Web Access users by using the Set-OwaVirtualDirectory cmdlet. Type:
Set-OwaVirtualDirectory "OWA (Default Web Site)" -ContactsEnabled $True -ChangePasswordEnabled $True

Tip of the day #55:

Booleans are parameters that can be evaluated as either $True or $False. Booleans are typically used as a flag on an object that modifies the behavior of that object. In the Exchange Management Shell, you must supply a Boolean parameter with either a $True, $False, 1, or 0. No other values are accepted, including True or False. For example, both of the following commands set the enabled state of the ExampleAssignment management role assignment to $True:
Set-ManagementRoleAssignment ExampleAssignment -Enabled $True
  Set-ManagementRoleAssignment ExampleAssignment -Enabled 1

Tip of the day #56:

Want an easy way to apply deleted item retention limits across multiple databases and servers? Try the following command to configure deleted item retention across all databases on a specified server:
Get-MailboxDatabase -Server <Server Name> | Set-MailboxDatabase -DeletedItemRetention 45.00:00:00
You can also apply the same deleted item retention limits or mailbox retention limits across all servers in your organization:
Get-MailboxDatabase | Set-MailboxDatabase -DeletedItemRetention 45.00:00:00 -MailboxRetention 120.00:00:00

Tip of the day #57:

Want to know what permissions an Active Directory user account has on a specific mailbox? Use:
Get-Mailbox <Mailbox to Check> | Get-MailboxPermission -User <Active Directory User>

Tip of the day #58:

Want to know which mailboxes a specific Active Directory user has permissions to? Type:
$Mailboxes = Get-Mailbox -ResultSize Unlimited
  $Mailboxes | Get-MailboxPermission -User <Active Directory User> | Format-Table Identity, AccessRights, Deny
Caution: This command enumerates all the mailboxes in your organization. If you have lots of mailboxes, you may want to target specific mailboxes.

Tip of the day #59:

Want to get a list of the backup status of all mailbox databases in your organization? Type:
Get-MailboxDatabase -Status | Format-Table Name, Server, *Backup*
How about just the mailbox databases on a specific server? Type:
$Databases = Get-MailboxDatabase -Server <Server Name> -Status
  $Databases | Format-Table Name, *Backup*

Tip of the day #60:

To retrieve the current status of an Exchange server or database, use the Status parameter. For example:
Get-ExchangeServer -Status | Format-List
  Get-MailboxDatabase -Server <Server Name> -Status | Format-List

Tip of the day #61:

Want to view the mounted status of all mailbox databases? Type:
Get-MailboxDatabase -Status | Format-Table Name, Server, Mounted

Tip of the day #62:

What's the difference between server-side filtering and client-side filtering? Server-side filtering is used with the recipient and queue cmdlets, which support the Filter parameter, because these cmdlets can return large result sets. The server filters the results by using the criteria you specify and then sends you the filtered results. Client-side filtering can be used with any cmdlet. The entire result set is sent to the client computer, which then filters the data and provides a filtered result set. Client-side filtering uses the Where-Object cmdlet, which can be shortened to Where.

Tip of the day #63:

With Exchange Server 2010 Unified Messaging, you can redirect unauthenticated callers to certain telephone extensions to an operator instead of to the extension that was dialed. To list users for whom Unified Messaging transfers unauthenticated callers to the operator, instead of to the user, type:
$Mailboxes = Get-UMMailbox
  $Mailboxes | Where-Object { $_.AllowUMCallsFromNonUsers -eq `
  [Microsoft.Exchange.Data.Directory.Recipient.AllowUMCallsFromNonUsersFlags] "None" }

Tip of the day #64:

You can use client-side filtering to return only the data that you want to see or work with. The following example retrieves all Active Directory user accounts in the Engineering department and puts the results in a table with two columns, Name and Department. By using the ResultSize parameter, the Get-User cmdlet limits the result set to 2,000 users.
$Users = Get-User -ResultSize 2000
$Users | Where { $_.Department -Eq "Engineering" } | Format-Table Name, Department

Tip of the day #65:

The special variable $_ represents the objects being passed from one cmdlet to another cmdlet in the pipeline. The $_ variable is automatically initiated by the Shell and is bound to the current pipeline object. You can access the properties of the object assigned to the $_ variable as you would any other object. The following example shows how you can view the Name property of each mailbox object that is passed through the pipeline:
Get-Mailbox | ForEach { $_.Name }

Tip of the day #66:

You can import CSV files and treat them as objects by using the Import-Csv cmdlet. Each row in a CSV file becomes an element in an array, and each column becomes a property. You can assign the CSV file to a variable, or you can pipe its contents directly to another cmdlet. In the following example, there are three columns in the CSV file, Name, Alias, and EmailAddress, with several rows that the ForEach cmdlet will cycle through. The data in each row is used to create a new mail contact.
$CSV = Import-Csv
  $CSV | ForEach { New-MailContact -Name $_.Name -Alias $_.Alias -ExternalEmailAddress $_.EmailAddress -OrganizationalUnit Users }

Tip of the day #67:

Want to customize your Exchange Management Shell profile? Run the following command to determine the location of your Microsoft.PowerShell_profile.ps1 file:
$Profile
You may have to create the PSConfiguration folder and Microsoft.PowerShell_profile.ps1 file. After you've done that, you can add your favorite functions and aliases, which will be loaded every time that the Exchange Management Shell is opened.

Tip of the day #68:

Want to see everything that occurs when you run a command? Include the Verbose parameter with the command. This parameter instructs the Exchange Management Shell to display detailed information about each action that the server takes to complete the command. This information can be useful in troubleshooting.

Tip of the day #69:

Any cmdlet that accepts a size value lets you specify whether the integer value is in kilobytes (KB), megabytes (MB), gigabytes (GB), or terabytes (TB). For example:
Set-Mailbox "Kim Akers" -ProhibitSendQuota 200MB -UseDatabaseQuotaDefaults $False

Tip of the day #70:

Want to create a new role group for your administrators? Use the New-RoleGroup cmdlet. The New-RoleGroup cmdlet lets you add management roles and specify the members to add to the new role group. Those members will be granted the permissions provided by the management roles. Type:
New-RoleGroup <role group name> -Roles <role 1>, <role 2>, <role 3...> -Members <member 1>, <member 2>, <member3...>
Remember, role groups are used to grant permissions to groups of administrators or specialist end users who require special permissions. If you want to manage permissions for end users, use management role assignment policies.

Tip of the day #71:

Do you want to create a new management role assignment policy that's based on an existing policy, but you don't want to include all of the management roles? Use the Get-ManagementRoleAssignment cmdlet and pipe the results to the Where cmdlet. The Where cmdlet excludes any role assignments that contain the roles you specify. The remaining role assignments are piped to the New-ManagementRoleAssignment cmdlet. Type:
New-RoleAssignmentPolicy <new role assignment policy name>
Get-ManagementRoleAssignment -RoleAssignee <old role assignment policy name> | Where { ($_.Role -NE "<role name 1>") -And ($_.Role -NE "<role name 1>") } | New-ManagementRoleAssignment -Policy <new role assignment policy name>
Then you can apply the new policy to a mailbox using the Set-Mailbox cmdlet:
Set-Mailbox <mailbox name> -RoleAssignmentPolicy <new role assignment policy name>

Tip of the day #72:

Do you want to remove a management role from a role group, role assignment policy, USG or user but don't know the name o f the management role assignment? Just find the role assignment with the Get-ManagementRoleAssignment cmdlet and pipe the results to the Remove-ManagementRoleAssignment cmdlet. Type:
Get-ManagementRoleAssignment -RoleAssignee <role assignee name> -Role <role name> | Remove-ManagementRoleAssignment

Tip of the day #73:

Exchange 2010 uses management role groups and management role assignment policies to manage permissions.  Role groups enable you to grant permissions to groups of administrators and specialist end users. These are people who manage your organization or perform special tasks, like mailbox searches for compliance reasons.  Role assignment policies enable you to grant permissions to your end users. These permissions include whether users can manage their own distribution groups, edit their own profile information, access voice mail, and more.

Tip of the day #74:

Exchange 2010 uses management role groups and management role assignment policies to manage permissions.
Role groups enable you to grant permissions to groups of administrators and specialist end users. These are people who manage your organization or perform special tasks, like mailbox searches for compliance reasons.
Role assignment policies enable you to grant permissions to your end users. These permissions include whether users can manage their own distribution groups, edit their own profile information, access voice mail, and more.

Tip of the day #75:

Exchange 2010 uses management role groups and management role assignment policies to manage permissions.
Role groups enable you to grant permissions to groups of administrators and specialist end users. These are people who manage your organization or perform special tasks, like mailbox searches for compliance reasons.
Role assignment policies enable you to grant permissions to your end users. These permissions include whether users can manage their own distribution groups, edit their own profile information, access voice mail, and more.

Tip of the day #76:

Exchange 2010 uses management role groups and management role assignment policies to manage permissions.
Role groups enable you to grant permissions to groups of administrators and specialist end users. These are people who manage your organization or perform special tasks, like mailbox searches for compliance reasons.
Role assignment policies enable you to grant permissions to your end users. These permissions include whether users can manage their own distribution groups, edit their own profile information, access voice mail, and more.

Tip of the day #77:

Management role groups enable you to grant permissions to groups of administrators and specialist end users. These are people who manage your organization or perform special tasks, like mailbox searches for compliance reasons.
If you want to manage permissions for end users, use management role assignment policies.

Tip of the day #78:

Management role assignment policies enable you to grant permissions to your end users. These permissions include whether users can manage their own distribution groups, edit their own profile information, access voicemail, and more.
If you want to manage permissions for administrators and specialist users, use management role groups.

Tip of the day #79:

Management role assignments determine what management roles are associated with management role groups and management role assignment policies. Role assignments also control what objects users who are members of role groups or assignment policies can modify using the cmdlets available on the associated management roles.

Tip of the day #80:

The Get-RoleGroupMember cmdlet lists all the members on a management role group. But if you want to get more details about the members of the role group, use the Get-ManagementRoleAssignment cmdlet. The Get-ManagementRoleAssignment cmdlet enables you to view the members of universal security groups that are members of role groups, view the management scope t
hat applies, and more.

Tip of the day #81:

Do you need to store a value in a variable in a script and make sure it never changes? If so, make the variable a constant using the New-Variable cmdlet. Constants can be set once and don't allow their values to be changed. For example, the following creates the $IPAddress constant with the value 10.0.0.2.
New-Variable -Option Constant -Name IPAddress -Value "10.0.0.2"

Tip of the day #82:

To get a list of all parameters available for a cmdlet, type:
(Get-Command <Cmdlet Name>).Parameters | ft key
For example, to get all parameters for the New-TransportRule cmdlet, type:
(Get-Command New-TransportRule).Parameters | ft key

Tip of the day #83:

Did you know that you need to use the AssembleMessage script when exporting messages from a queue? For example, if you want to export the message with message ID 1234 from the contoso.com queue on server Hub1, you need to run the following command:
Export-Message -Identity Hub1\contoso.com\1234 | AssembleMessage –Path C:\ExportedMessages\Message1234.eml"

Tip of the day #84:

When you are creating a new Edge subscription, you need to run the New-EdgeSubscription cmdlet first on your Edge Transport server, and then on an administrator console that is connected to your internal Exchange organization. However, because Exchange 2010 uses remote Windows PowerShell, you can no longer use the Path parameter when importing an Edge subscription file. Instead you need to use the Get-Content cmdlet to first retrieve and encode the data, and then pass it to the New-EdgeSubscription cmdlet, like so:
New-EdgeSubscription -FileData ([byte[]]$(Get-Content -Path "C:\EdgeServerSubscription.xml" -Encoding Byte -ReadCount 0) ) -Site "Default-First-Site"

Tip of the day #85:

Wondering how many log files are generated per server every minute? Quickly find out by typing:
Get-MailboxDatabase -Server $env:ComputerName | ?{ %{$_.DatabaseCopies | ?{$_.ReplayLagTime -ne [TimeSpan]::Zero -And $_ .HostServerName -eq $env:ComputerName} } } | %{ $count = 0; $MinT = [DateTime]::MaxValue; $MaxT = [DateTime]::MinValue; Get-ChildItem -Path $_.LogFolderPath -Filter "*????.log" | %{ $count = $count + 1; if($_.LastWriteTime -gt $MaxT){ $MaxT = $_.LastWriteTime}; if($_.LastWriteTime -lt $MinT){ $MinT= $_.LastWriteTime} }; ($count / ($MaxT.Subtract($MinT)).TotalMinutes) } | Measure-Object -Min -Max -Ave

Tip of the day #86:

Wondering how many log files are generated per database every minute? Quickly find out by typing:
Get-MailboxDatabase -Server $env:ComputerName | %{ Get-ChildItem -Path $_.LogFolderPath -Filter "*????.log" | Group-Object -Property {$_.LastWriteTime.Day,$_.LastWriteTime.Hour,$_.LastWriteTime.minute} | ?{$_.Count -gt 1} | Measure-Object -Property Count -Min -Max -Ave }

Tip of the day #87:

Get quick health and status information for your mailbox database copies by typing:
Get-DatabaseAvailabilityGroup DAG1 | %{ $_.Servers | %{ Get-MailboxDatabaseCopyStatus -Server $_ } }

Tip of the day #88:

Did you know that you can share your calendar and contacts folders with other federated Exchange 2010 organizations by first creating a federation trust with the Microsoft Federation Gateway with a valid digital certificate? Just use the New-FederationTrust cmdlet and the certificate thumbprint to get started. Type:
New-FederationTrust -Name "Microsoft Federation Gateway" -Thumbprint <cetificate thumbprint>
Finish by setting up an organization relationship with another federated Exchange organization to share limited calendar  free/busy information. Type:
Get-FederationInformation -DomainName <other domain name> | New-OrganizationRelationship -Name "<name of relationship>" -FreeBusyAccessEnabled $true -FreeBusyAccessLevel -LimitedDetails

Tip of the day #89:

Need to quickly get a list of your Exchange certificates and their thumbprints? Just use the Get-ExchangeCertificate cmdlet. Type:
Get-ExchangeCertificate | fl
Want to filter the list and include just the self-signed certificates? No problem! Type:
Get-ExchangeCertificate | where {$_.IsSelfSigned -eq $true} | fl

Tip of the day #90:

Not sure your Federation Trust with the Microsoft Federation Gateway is working correctly? To test if a security token c
an be retrieved, just type:
Test-FederationTrust

Tip of the day #91:

Need a report on the status of each Exchange certificate installed on all Hub Transport and Client Access servers? Try this:
Test-FederationTrustCertificate

Tip of the day #92:

Need to verify that an organization relationship is correctly configured and functioning as expected for a user in an external Exchange organization? Just type:
Test-OrganizationRelationship -UserIdentity <user email address> -Identity <external domain> -Confirm

Tip of the day #93:

Use this command to get all active mailbox move requests on a mailbox server:
$(Get-MailboxDatabaseCopyStatus -Server MBX | ?{ $_.status -eq "Mounted" }) | %{ Get-MoveRequest -TargetDatabase $_.DatabaseName } | ?{ $_.Status -ne "Completed" -and $_.Status -ne "CompletedWithWarning" }

Tip of the day #94:

Use this command to find all non-completed move requests and group them by target database:
Get-MoveRequest | ?{ $_.Status -ne "Completed" -and $_.Status -ne "CompletedWithWarning" } | group targetdatabase | sort  Count -Descending

Tip of the day #95:

Use this command to find failure messages for all failed moves:
Get-MoveRequest -MoveStatus Failed | Get-MoveRequestStatistics | ft Alias, percentcomplete, message -auto

Tip of the day #96:

Use these commands to get a snapshot of the move throughput for completed moves.
$stats = Get-MoveRequest -MoveStatus Completed | Get-MoveRequestStatistics
$stats | sort totalmailboxsize | ft Alias,{$_.totalmailboxsize.ToMB()},totalinprogressduration -auto

Tip of the day #97:

Use this command to view the last move report for a mailbox:
(Get-MailboxStatistics aylakol -IncludeMoveReport).MoveHistory[0] | fl

Tip of the day #98:

Use this command to view how many move requests are in the queue to be moved:
(Get-MoveRequest -MoveStatus Queued).count

Tip of the day #99:

Use this command to find all mailbox move requests for mailboxes on the active mailbox database copies that are hosted on the specified mailbox server. This command returns the display name, status of the move request, and the database to which the mailbox is being moved.
$(Get-MailboxDatabaseCopyStatus -Server MBX01 | ?{ $_.status -eq "Mounted" }) | %{ Get-MoveRequest -TargetDatabase $_.DatabaseName }

Tip of the day #100:

Did you know that you can allow users in your Exchange organization to publish their calendars to the Internet so that anyone can view their free/busy availability? Just configure a few settings to get started. To enable an Outlook Web App Virtual Directory and allow calendar publishing, type:
Set-OWAVirtualDirectory -Identity <Client Access server> -ExternalURL <External URL for Client Access server> -CalendarPublishingEnabled $true
To set the web proxy for the Mailbox server, type:
Set-ExchangeServer -Identity "<Mailbox server>" -InternalWebProxy <webproxy URL>
Finish by setting up a sharing policy for the "Anonymous" Internet domain and assign the sharing policy to a user mailbox. First type:
New-SharingPolicy -Name "<policy name>" -Domains 'Anonymous: CalendarSharingFreeBusySimple' -Enabled $True
Then type:
Get-Mailbox -Identity <user alias> | Set-Mailbox -SharingPolicy "<policy name>"

Tip of the day #101:

Need to see a list of the URLs for a user's calendar that has been published for Internet access? Just type:
Get-MailboxCalendarFolder -Identity <user alias>:\calendar | fl