The PowerShell module GlobalFunctions got updated to Version 2.0. This module is used by some of my PowerShell scripts which utilize centralized logging.
The new release contains the first functions required for some upcoming scripts for managing on-boarding process for joiners and the off-boarding process for leavers for companies utilizing Office 365.
The New-RandomPassword functions is based on Simon Wahlin's script published here: https://gallery.technet.microsoft.com/scriptcenter/Generate-a-random-and-5c879ed5
PowerShell module providing centralizied logging and other helpful functions.
Import-Module GlobalFunctions $ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path $ScriptName = $MyInvocation.MyCommand.Name # Create a new logger object, keeping the last 14 days of log files $logger = New-Logger -ScriptRoot $ScriptDir -ScriptName $ScriptName -LogFileRetention 14 # Write a new informational message to the log file $logger.Write('My Log Message') # Write an error message to the log file $logger.Write('My custom error message') # Write a warning message to the log file $logger.Write('My custom warning') # Send a log file by email at the end of your script $logger.SendLogFile('sender@mcsmemail.de', 'recipient@mcsmemail.de', 'smtpserver.mcsmemail.de')
You can "install" a PowerShell module by copying the module to a sub folder of the same name as the module in either of the two following locations:
PS C:\> $env:PSModulePath C:\Users\admin\Documents\WindowsPowerShell\Modules;C:\Program Files\WindowsPowerShell\Modules;C:\WINDOWS\sys tem32\WindowsPowerShell\v1.0\Modules
Create a new folder named GlobalFunctions in C:\Program Files\WindowsPowerShell\Modules
Copy the GlobalFunctions.psm1 file to C:\Program Files\WindowsPowerShell\Modules\GlobalFunctions
That's it.
These steps assume that you use a dedicated PowerShell scripts folder, e.g. D:\MyScripts
.\Set-PersistentPSModulePath.ps1 -Add
Close the current PowerShell window and open a new PowerShell window. That's it.
When using PowerShell 5, you can simply use the following PowerShell command from within an administrative PowerShell window.
Install-Module GlobalFunctions
When a new version of the GlobalFunctions module has been released, use the following PowerShell command to update the module.
Update-Module GlobalFunctions
The GlobalFunctions PowerShell module has been updated to support writing of log messages to the PowerShell output pipeline.
When writing to the PowerShell output pipeline, the severity level is not written to the pipeline. In most cases you will use this option for debugging purposes.
# Import module first Import-Module -Name GlobalFunctions # Create an instance of the logger $ScriptDir = Split-Path -Path $script:MyInvocation.MyCommand.Path $ScriptName = $MyInvocation.MyCommand.Name $logger = New-Logger -ScriptRoot $ScriptDir -ScriptName $ScriptName -LogFileRetention 14 # Write an informational message to the log file only $logger.Write('Some informational message') # Write an informational message to the log file only $logger.Write('Some message to log and console',0,$true) # Write a warning level message to log file and the message only to PowerShell output pipeline $logger.Write('Some warning message',2,$true)
Remember to add the severity level when writing to console.
Read more about the GlobalFunctions module here.
You can get the source code here:
The PowerShell script to purge Exchange Server and IIS log files has been updated to version 2.1.
The function Copy-LogFiles has been slightly rewritten and there has been a change in the cmdlet parameters.
When using ArchiveMode CopyAndZip or CopyZipAndDelete all copied log files in the EXCHANGESERVER\LOGS folder are added to a compressed archive. The script creates a separate archive for IIS and Exchange logs.
Code updated
function Copy-LogFiles { [CmdletBinding()] param( [string]$SourceServer, [string]$SourcePath, $FilesToMove, [string]$ArchivePrefix = '' ) if($SourceServer -ne '') { # path per SERVER for zipped archives $ServerRepositoryPath = Join-Path -Path $RepositoryRootPath -ChildPath $SourceServer # subfolder used as target for copying source folders and files $ServerRepositoryLogsPath = Join-Path -Path $ServerRepositoryPath -ChildPath $LogSubfolderName $ServerRepositoryPath = Join-Path -Path $RepositoryRootPath -ChildPath $SourceServer if(!(Test-Path -Path $ServerRepositoryPath)) { # Create new target directory for server, if does not exist $null = New-Item -Path $ServerRepositoryPath -ItemType Directory -Force -Confirm:$false } foreach ($File in $FilesToMove) { # target directory $targetDir = $File.DirectoryName.Replace($TargetServerFolder, $ServerRepositoryLogsPath) # target file path $targetFile = $File.FullName.Replace($TargetServerFolder, $ServerRepositoryLogsPath) # create target directory, if not exists if(!(Test-Path -Path $targetDir)) {$null = mkdir -Path $targetDir} # copy file to target $null = Copy-Item -Path $File.FullName -Destination $targetFile -Recurse -Force -Confirm:$false -ErrorAction SilentlyContinue } if($ZipArchive) { # zip copied log files $Archive = Join-Path -Path $ServerRepositoryPath -ChildPath ('{0}-{1}' -f $ArchivePrefix, $ArchiveFileName) $logger.Write(('Zip copied files to {0}' -f $ArchiveFileName)) # delete archive file, if already exists if(Test-Path -Path $Archive) {Remove-Item -Path $Archive -Force -Confirm:$false} try { # create zipped asrchive Add-Type -AssemblyName 'System.IO.Compression.FileSystem' [IO.Compression.ZipFile]::CreateFromDirectory($ServerRepositoryLogsPath,$Archive) } catch { $logger.Write(('Error compressing files from {0} to {1}' -f $ServerRepositoryLogsPath, $Archive),3) } finally { # cleanup, if compression was successful if($DeleteZippedFiles) { $logger.Write(('Deleting folder {0}' -f $ServerRepositoryLogsPath)) $null = Remove-Item -Path $ServerRepositoryLogsPath -Recurse -Force -Confirm:$false -ErrorAction SilentlyContinue } } } } }
The PowerShell script to purge Exchange Server and IIS log files has been updated to version 2.0.
Release 2.0 allows for copying of files that will be deleted to be copied to a central file repository. The script will create a folder per server and the full log file folder structure will be preserved.
The next release will contain an option to compress the copied log files.
Added code:
function Copy-LogFiles { [CmdletBinding()] param( [string]$SourceServer, [string]$SourcePath, $FilesToMove ) if($SourceServer -ne '') { # path per SERVER for zipped archives $ServerRepositoryPath = Join-Path -Path $RepositoryRootPath -ChildPath $SourceServer # subfolder used as target for copying source folders and files $ServerRepositoryLogsPath = Join-Path -Path $ServerRepositoryPath -ChildPath $LogSubfolderName $ServerRepositoryPath = Join-Path -Path $RepositoryRootPath -ChildPath $SourceServer if(!(Test-Path -Path $ServerRepositoryPath)) { # Create new target directory for server, if does not exist $null = New-Item -Path $ServerRepositoryPath -ItemType Directory -Force -Confirm:$false } foreach ($File in $FilesToMove) { # target directory $targetDir = $File.DirectoryName.Replace($TargetServerFolder, $ServerRepositoryLogsPath) # target file path $targetFile = $File.FullName.Replace($TargetServerFolder, $ServerRepositoryLogsPath) # create target directory, if not exists if(!(Test-Path -Path $targetDir)) {$null = mkdir -Path $targetDir} # copy file to target $null = Copy-Item -Path $File.FullName -Destination $targetFile -Recurse -Force -Confirm:$false -ErrorAction SilentlyContinue }-Force if($ZipArchive) { # zip copied log files # <# NOT FULLY TESTED YET $Archive = Join-Path -Path $ServerRepositoryPath -ChildPath $ArchiveFileName $logger.Write(('Zip copied files to {0}' -f $ArchiveFileName)) if(Test-Path -Path $Archive) {Remove-Item $Archive -Force -Confirm:$false} Add-Type -AssemblyName 'System.IO.Compression.FileSystem' [IO.Compression.ZipFile]::CreateFromDirectory($ServerRepositoryLogsPath,$Archive) #> } } }
This blog post is about creating an Twitter Bot to tweet messages using Azure Automation. The steps and the script itself are based on Trevor Sullivan's TechNet Gallery post. His post assumes that you are familiar with some Azure Automation steps. So I am going to describe the required steps in more detail.
You'll need the following components to setup your personal Twitter Bot.
First you'll need to create a Twitter application to reference your Azure Automation bot. The authentication information of your Twitter application will be needed in step 2.
The information required are
You need to create a new Twitter application by accesssing the following link: https://apps.twitter.com/
Ensure that you've added your mobile phone number to your Twitter account before creating a new Twitter application. This is a requirement for creating Twitter applications.
Log on to Twitter using the Twitter account you want your Twitter Bot to post as.You'll see something similar as this:
Just click Create New App.
Enter the information as needed. The application name must be a globally unique name. So it might be tricky to find a suitable application name. Click Create your Twitter application to finally create the application.
Select Keys and Access Tokens and copy the Consumer Key (API Key) and the Consumer Secret (API Secret) value into a text editor of your choice.
Further down on the same web page you'll find the Your Access Token section.
Click Create my access token.
After you've created the access token, copy the Access Token and the Access Token Secret to your text editor document. You'll need all four values in just a moment.
The Azure automation component will require application credentials for posting Tweets on your behalf. These required credentials are stored in a JSON file. Yo do not need top worry about the JSON data format.
The PoshTwit PowerShell module helps you to create the required JSON file.
The simpliest way to get the PoshTwit module is by installing the module directly from the PowerShell Gallery using an Administrative PowerShell session.
Install-Module PoshTwit
If you cannot use the Install-Module cmdlet, use the link provided in the Links section.
Remember that this step is only needed to create the JSON file containing the required credential information for Azure Automation.
After you've successfully installed the PoshTwit module, call the Set-PoshTwitToken cmdlet using all four Twitter app credential information to create the authentication JSON file.
Set-PoshTwitToken -ConsumerKey [YourConsumerKey] -ConsumerSecret [YourConsumerSecret] -AccessToken [YourAccessToken] -AccessSecret [AccessSecret]
The JSON file wil be created in the PowerShell module installtion folder. Which is by default:
C:\Program Files\WindowsPowerShell\Modules\PoshTwit\0.1.6
The version number might differ depending on the version you've installed.
Open the token.json file and copy the content to your text editor. The content of the token.json file will be the password for the Azure Automation credential object. The content will look like this:
{"ConsumerKey":"9FX***********","ConsumerSecret":"4kIxa***********","AccessToken":"24540854***********","AccessSecret":"OSYP***********"}
You should see your Twitter application authentication information. You will nedd to copy & paste this string including the curly brackets as account credentials at a later step.
Log on to the Azure Portal and create a new Azure Automation account. The Azure Automation will host your automation runbooks, variables and other settings. You can have multiple Azure Automation accounts. This is especially usefull when you want to delegate access and control of Automation accounts to different members of staff.
Click '+', enter Auto as search text and select Automation.
Click Create on the next blade.
Configure your new Azure Automation account by using a unique name, select the appropriate Azure subscription, create a new Resource Group or use an existing, select the Azure location, leave Yes as the default option for creating an Azure Run As account, select the checkbox to pin the Azure Automation account to your Azure dashboard, and click Create.
After you've been redirected to the Azure Dashboard wait for the Azure Automation Account to be created. If you are not redirected to the Azure Automation blade automatically, select the Automation Account tile on the Azure dashboard.
Select Process Automation - Runbooks. You'll notice two tutorials and two tutorial scripts which are automatically provisioned for you.
Click Add a runbook to create the Twitter Bot runbook.
The next step requires that you've download the Tweet-PowerShellTips.ps1 script. If you haven't, download it now.
Select Import an exisiting runbook and browse for the downloaded PowerShell script on the next blade. After selecting the PowerShell file the fiel will be uploaded and validated automatically. The Runbook type and Runbook name properties will be set automatically for you. Just enter a short description for your runbook. Click Create.
The uploaded PowerShell script utilizes the PoshTwit PowerShell module. This PowerShell module needs to be available within the Azure Automation account as well. Additonal PowerShell modules are configured within the Shared Resources section of your Azure Automation account. The PoshTwit module is added from the PowerShell Gallery.
Select Modules Gallery, enter PoshTwit as search text and press Enter, click the PoshTwit search result tile.
Click Import to import the PowerShell module to thre shared ressources of your Azure Automation account. Click OK on the following blade. Close the PoshTwit module blade.
Now you'll add the required Twitter application credentials to the Shared Resources of the Azure Automation account.
Select Shared Resources - Credentials and click Add a credential.
Use TwitterCredential as Name and User name. The variable is accessed by the PowerShell script using the cmdlet
Get-AutomationPSCredential -Name TwitterCredential
Now copy and paste the full JSON file content as Password and Password confirmation. Click Create to save the new credential information.
Select the new runbook from the list of runbooks to edit the runbook properties.
Click Edit to edit the PowerShell code to adjust the tweets to match your needs (at least). YOu are able to edit the PowerShell code directly from the browser window.
Ensure to click Save, after you've edited the PowerShell code.
Each time you've edited an Azure Runbook, you need to publish the new version of the runbook. Click Publish and confirm the publishing with Yes.
You can test your runbook using the Test pane. The script itself will not write any output to the output windows, as the script does not use any Write-Output cmdlets.
You can add the following PowerShell code to the script to output the Tweet Id and Tweet text.
Write-Output "Publish Tweet $($TweetId) | $($TweetList[$TweetId])"
As a last step you need to create a schedule to post random tweets automatically. Automation schedules are created as shared resources again.
Select Shared Resources - Schedules and click Add a schedule.
Configure a schedule name, the start date, the schedule time zone, and the recurring interval. Click Create.
Select your runbook to link the just created schedule.
Select Schedules and click Add a schedule.
Click Link a schedule to your runbook, select the schedule and click OK.
The runbook schedules overview will show an information when the next run will be initiated.
That's it. Your Azure Automation Twitter Bot is up and running.
Now you can simply edit the runbook, add new tweets to the string array, save the changes and publish the changed runbook for production use. As long as the changes are not published, Azure Automation will use the last published version of the runbook.
Enjoy Azure.
This is the source code of the updated PowerShell script.
# Array of tweets # Ensure that the length of each tweet does not exceed 140 characters # Ensure to have at least 2 entries $TweetList = @( 'Find more #PowerShell #scripts at http://scripts.granikos.eu ', 'More #Office365 and #MSFTExchange tips at http://JustCantGetEnough.granikos.eu ' ) # Get a tweet text by random $TweetId = Get-Random -Minimum 0 -Maximum ($TweetList.Count - 1); # Fetch automation credentials $TwitterCredential = Get-AutomationPSCredential -Name TwitterCredential; $TwitterCredential = ConvertFrom-Json -InputObject $TwitterCredential.GetNetworkCredential().Password; # Provision the tweet $Tweet = @{ ConsumerKey = $TwitterCredential.ConsumerKey; ConsumerSecret = $TwitterCredential.ConsumerSecret; AccessToken = $TwitterCredential.AccessToken; AccessSecret = $TwitterCredential.AccessSecret; Tweet = $TweetList[$TweetId]; }; # Publish the tweet Publish-Tweet @Tweet;
The script published by the Exchange Team (Analyzing Exchange Transaction Log Generation Statistics) requires an update when run on a system that does not use the en-US locale as Culture.
When the script analyses the saved log file information, a DateTime error is being thrown:
Cannot convert value "21/05/2010" to type "System.DateTime"
See the original blog post for examples: http://blogs.technet.com/b/exchange/archive/2013/10/07/analyzing-exchange-transaction-log-generation-statistics.aspx
The script utilizes the Get-UICulture cmdlet to fetch the culture settings required to have [DATETIME]::Parse() work as expected.
DateTime values are stored in the CSV file using the UICulture setting, but [DATETIME]::Parse() uses the local culture settings to parse values by default.
To check your settings in PowerShell use the following cmdlets: