Posts Tagged ‘powershell’

worksite

Currently you need to purchase imanage mobility server to be able to view NRL files remotely.

We had a request, for users to be able to email Worksite NRL links from any devices especially Mobile devices to an email address and it emails them back the document for review.

It looked like this site software could do it at one stage : http://www.grantselect.co.uk/products/products.htm , however it’s not going anymore , so we developed a Powershell Script to do this.

1) Create a mailbox in Exchange 2010 where you want to get emails sent to . e.g. NRLDocrequest@yourdomain.com.au. Change the value below in the script MAILBOXWHEREREQUESTSGETSENT to the alias of the Email account

2)Under the Inbox create a Folder called Complete and Folder Called External

3)Give the user who will be running this script Send as as well as Full Permissions to mailbox

4)Replace below in script IMANAGESQLSERVERNAME to the SQL server of your iManage Database

5)Where you run this script make sure the user running the script has access to C:\Temp\

6)Add this script as scheduled task to check Mailbox

# Connect to Exchange server and load Exchange powershell modules
. 'C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1'
Connect-ExchangeServer -auto
 
$mailbox = Get-Mailbox MAILBOXWHEREREQUESTSGETSENT
$mailAddress = $mailbox.PrimarySmtpAddress.ToString();
 
[Reflection.Assembly]::LoadFile("C:\Program Files (x86)\Microsoft\Exchange\Web Services\2.1\Microsoft.Exchange.WebServices.dll") | Out-Null
$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
$s.AutodiscoverUrl($mailAddress);
 
$MailboxRootid = new-object  Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$mailAddress)
$MailboxRoot = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,$MailboxRootid)
 
# Get Folder ID from Path to be able to move
Function GetFolder()
{
	# Return a reference to a folder specified by path
 
	$RootFolder, $FolderPath = $args[0];
 
	$Folder = $RootFolder;
	if ($FolderPath -ne '\')
	{
		$PathElements = $FolderPath -split '\\';
		For ($i=0; $i -lt $PathElements.Count; $i++)
		{
			if ($PathElements[$i])
			{
				$View = New-Object  Microsoft.Exchange.WebServices.Data.FolderView(2,0);
				$View.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep;
				$View.PropertySet = [Microsoft.Exchange.WebServices.Data.BasePropertySet]::IdOnly;
 
				$SearchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName, $PathElements[$i]);
 
				$FolderResults = $Folder.FindFolders($SearchFilter, $View);
				if ($FolderResults.TotalCount -ne 1)
				{
					# We have either none or more than one folder returned... Either way, we can't continue
					$Folder = $null;
					Write-Host "Failed to find " $PathElements[$i];
					Write-Host "Requested folder path: " $FolderPath;
					break;
				}
 
				$Folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s, $FolderResults.Folders[0].Id)
			}
		}
	}
 
	$Folder;
}
 
$folderid = new-object  Microsoft.Exchange.WebServices.Data.Folderid([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$mailAddress)
$InboxFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,$folderid)
 
$mails = $inboxFolder.FindItems(5) 
$mails | % {$_.Load()}
#foreachemails
foreach($Item in $mails.Items)
	{ 
	#block emails from outside of domain for security
	if($item.Sender.Address -like "*@yourinternaldomain.com") {
 
 
	#only load items with attachments
	if($item.Attachments.Count -gt 0)
		{ 
 
		#Create the email message and set the Subject and Body
		$message = New-Object Microsoft.Exchange.WebServices.Data.EmailMessage -ArgumentList $s
 
		#Go through each attachment
		foreach($attach in $item.Attachments)
			{
			#Is it an NRL File?
			if ($attach.name -like '*.nrl') {
 
			#If it it load it to temp location
			$attach.load("C:\Temp\"+$attach.name)
 
			#Start Array for content for NRL
			$var = @{}
			$count=0
 
			#Get NRL file and store to array
			Get-Content -LiteralPath ("C:\Temp\" + $attach.name) | ForEach-Object {
				$count++
				$list = $_.Split(':!')
				$var.Add($count, $list)
				}
 
			#Get Variables from Array
			$database = $var[2][8]
			$docvalue = $var[2][11].Split(',')
			$docnumber = $docvalue[0]
			$docversion = $docvalue[1]
 
			#Remove NRL File
			Remove-Item ("C:\Temp\" + $attach.name)
 
##SQL Query Function no SQL installs needed all powershell baby
function Invoke-SQL ($SQLServer, $SqlQuery)  {
	#Uncomment below to double check the statement
	#Write-Host $SqlQuery
	$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
	$SqlConnection.ConnectionString = "Server = $SQLServer; Integrated Security = True"
 
	$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
	$SqlCmd.CommandText = $SqlQuery
	$SqlCmd.Connection = $SqlConnection
 
	$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
	$SqlAdapter.SelectCommand = $SqlCmd
 
	$DataSet = New-Object System.Data.DataSet
	[void]$SqlAdapter.Fill($DataSet)
 
	$SqlConnection.Close()
	return $dataset.tables
}
 
#Get the Doc Details from Number
$sqlresult = Invoke-SQL IMANAGESQLSERVERNAME "SELECT DOCLOC,DOCNAME,APPEXTENSION FROM [$database].[MHGROUP].DOCMASTER INNER JOIN [$database].[MHGROUP].DOCTYPES ON [$database].[MHGROUP].DOCMASTER.T_ALIAS=[$database].[MHGROUP].DOCTYPES.T_ALIAS where [DOCNUM]='$docnumber' and [VERSION]='$docversion'"
 
#Get the Location of file including imanage file server name
$docloc = $sqlresult| select -expand DOCLOC
$docloc = $docloc.Split(':')
$doclocsrv = $docloc[0]
 
#get the doc name to rename or it will be doc number
$docname = $sqlresult| select -expand DOCNAME
 
#get the doc type
$docfileextension = $sqlresult| select -expand APPEXTENSION
 
#Get the unc path of file to copy
$sqlresult = Invoke-SQL IMANAGESQLSERVERNAME "SELECT LOCATION  FROM [$database].[MHGROUP].DOCSERVERS where [DOCSERVER]='$doclocsrv'"
$location = $sqlresult| select -expand LOCATION
$source = $location + $docloc[1]
$destination = $docname + "." + $docfileextension
$pattern = "[{0}]" -f ([Regex]::Escape( [System.IO.Path]::GetInvalidFileNameChars() -join '' ))
$destination = "C:\Temp\NRL\" + [Regex]::Replace($destination, $pattern, '')
 
copy-item $source -Destination $destination
 
$message.Attachments.AddFileAttachment($destination) | Out-Null
 
#End of NRL Loop
}
#End of For Each Attachment
}
#End of the if attachment exists
}
 
#Is the email being sent have any documents to send?
if ($message.Attachments.Count -gt 0){
 
	$message.From = “email@fromdomain.com.au”
	$message.Subject = $item.Subject
	$message.Body = $msgBody
 
	$message.ToRecipients.Add($item.Sender.Address)
 
	#Send the message and save a copy in the users Sent Items folder (Alt is message.Send which will not save a copy.)
	if($item.Sender.Address -ne "emails@toignore.com")
		{
		$message.SendAndSaveCopy()
		}
 
}
 
 
#Move to Folder After Replying
$FolderObject = GetFolder($MailboxRoot, "\Inbox\Complete\");
		try
		{
		$Item.Move($FolderObject.Id) | out-null;
		}
		catch
		{
		Write-Host "Failed to move item", $Item.Id.UniqueId
		}
 
Remove-Item c:\TEMP\NRL\*
 
#Loop per email
 
}
 
#Move to Folder After Replying
$FolderObject = GetFolder($MailboxRoot, "\Inbox\External\");
		try
		{
		$Item.Move($FolderObject.Id) | out-null;
		}
		catch
		{
		Write-Host "Failed to move item", $Item.Id.UniqueId
		}
 
}

 

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

powershell2xa4

Param(
[string]$foo,
)

./Powershellscript.ps1 -foo "Bar1 bar2/ Bar3/Bar4"

When I ran the above as a scheduled task the output I would get for $foo is Bar1 bar2/ Bar3

When I ran the below as a scheduled task ( Single Quotes ) the output I would get for $foo is Bar1 bar2/ Bar3/Bar4 (Correct )

./Powershellscript.ps1 -foo 'Bar1 bar2/ Bar3/Bar4'

So why?

When you run powershell.exe from inside Powershell you are forcing the arguments to go through the old Windows style command line processing.

This way all of the arguments will pass right through without being converted to strings, having double quotes stripped and then being re-parsed.

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Powershell script to query multiple servers for their Local Machine Run Registry Keys

$servers = Get-Content c:\scripts\servers.txt 
 foreach ($server in $servers) {
 
$Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $server.ServerName)
$RegKey= $Reg.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Run")
 
$server
$RegKeyRO.GetValueNames()
}

 

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Below is the command to extract ( Archive ) emails from a particular folder into a PST

#Archive Items from a certain folder
New-MailboxExportRequest -mailbox %mailboxname% -IncludeFolders "path/to/folder/ -ContentFilter {(Received -lt '08/01/2014')} -FilePath \\path\to\pstfile.pst

However due to Exchange updates , the MailboxExport command does not work anymore ( which had the -deletecontent command) and Search-Mailbox does not have any functionality to Include just specific folders. So we have to use powershell EWS below

Note – By default ItemView has a limit of 1000 in exchange, the command below you will probably want to increase this say to 10,000 or even 50,000 so you don’t have to rerun this lots of times. After each run it will tell you how many items it has deleleted. You need to run the powershell script with a useraccount that has a throttling policy set above 1000.

e.g. Set-ThrottlingPolicy PolicyName -EWSFindCountLimit 50000

Set-Mailbox useraccount -ThrottlingPolicy PolicyName

$mailbox = Get-Mailbox %mailboxname%
$mailAddress = $mailbox.PrimarySmtpAddress.ToString();
 
[Reflection.Assembly]::LoadFile("C:\Program Files (x86)\Microsoft\Exchange\Web Services\2.1\Microsoft.Exchange.WebServices.dll") | Out-Null
$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010)
$s.AutodiscoverUrl($mailAddress);
 
$ItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(10000)
$MailboxRootid = new-object  Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$mailAddress)
$MailboxRoot = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,$MailboxRootid)
 
# Get Folder ID from Path
Function GetFolder()
{
	# Return a reference to a folder specified by path
 
	$RootFolder, $FolderPath = $args[0];
 
	$Folder = $RootFolder;
	if ($FolderPath -ne '\')
	{
		$PathElements = $FolderPath -split '\\';
		For ($i=0; $i -lt $PathElements.Count; $i++)
		{
			if ($PathElements[$i])
			{
				$View = New-Object  Microsoft.Exchange.WebServices.Data.FolderView(2,0);
				$View.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep;
				$View.PropertySet = [Microsoft.Exchange.WebServices.Data.BasePropertySet]::IdOnly;
 
				$SearchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName, $PathElements[$i]);
 
				$FolderResults = $Folder.FindFolders($SearchFilter, $View);
				if ($FolderResults.TotalCount -ne 1)
				{
					# We have either none or more than one folder returned... Either way, we can't continue
					$Folder = $null;
					Write-Host "Failed to find " $PathElements[$i];
					Write-Host "Requested folder path: " $FolderPath;
					break;
				}
 
				$Folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s, $FolderResults.Folders[0].Id)
			}
		}
	}
 
	$Folder;
}
 
 
try {
 
	$FolderObject = GetFolder($MailboxRoot, "path\folder\");
#Date from and To
    $findItemResults = $FolderObject.FindItems("System.Message.DateReceived:01/01/2014..01/08/2014",$ItemView)
 
        foreach ($item in $findItemResults.Items) {
 
                try {
#Comment Below out to not delete
                    [void]$item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete)
                    $Deleted ++
#Uncomment below to list before deleting
					#Write-host $item.DateTimeReceived 
                } catch {
                    Write-warning "Unable to delete item, $($item.subject).  $($Error[0].Exception.Message)"
                }
            }        
 
 
    if ($Deleted -gt 0) { Write-host "$Deleted mail items deleted from the Inbox." }
} catch {
    Write-warning "Could not connect to Inbox.  $( $_.exception.message )"
}
VN:F [1.9.22_1171]
Rating: 10.0/10 (2 votes cast)
VN:F [1.9.22_1171]
Rating: +3 (from 3 votes)

I based this script off of one referenced here : http://blogs.msdn.com/b/emeamsgdev/archive/2012/10/29/outlook-code-importing-bank-holidays-from-an-outlook-hol-based-csv-file.aspx?CommentPosted=true#commentmessage

CSV Format

6011-image_thumb_6a014d4e1

However I modified Adding a Category to the item, as well as adding this to All Users of a AD Group recursively instead of a single user. This will add a list of Holidays to Users Calendars across an organisation. If run again it will not import duplicates and have fields there to delete the duplicate Calendar enteries if needed

The user running this will need the impersonation role setup see this :

New users can then have an email sent to them automatically ( http://blogs.technet.com/b/sukum/archive/2013/04/03/send-welcome-email-to-new-mailbox-users.aspx ) with a .HOL file to run ( P.S. The XML did not work in this , I have to add Lines 6-8 from this http://itnuts.wordpress.com/2013/09/03/exchange-2010-automatic-welcome-message-for-a-new-user/)


https://github.com/pariswells/pariswells.com/blob/master/saveappointmentintoalluserscalendar.ps1
VN:F [1.9.22_1171]
Rating: 10.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: +1 (from 1 vote)

I was trying to get a list of Active Computers on our Network. A DSQuery can give me a list of all computer , and I tried to get an inactive list for 4 weeks and subtract the value , however the Inactive List was not that acurate.

Instead I wanted to Query the PwdLastSet to

I found a few scripts online but they moved the computer accounts to OU’s , and I just needed this for auditing purposes. So I edited the tracked back script

Save the script as script.ps1 then run with .\script -OlderThan 30

param(
    [int] $OlderThan = 20
)
 
try {
    Import-Module ActiveDirectory -ErrorAction Stop -Verbose:$false
} catch {
    Write-Error "Active Directory module failed to Import. Terminating the script. More details : $_"
    exit(1)
}
 
try {
    #Get domain name
    $DomainDN = (Get-ADDomain -ErrorAction Stop).DistinguishedName
    #Get Computers in Domaing
    $Computers = Get-ADComputer -Filter * -Properties PasswordLastSet -SearchBase $DomainDN -ErrorAction Stop
} catch {
    Write-Error "Failed to query active Directory for computers. Exiting the script. More details : $_"
    exit(1)
}
$now = Get-Date
$agedate = (Get-Date).AddDays(-$OlderThan)
 
foreach($Computer in $Computers) {
$ComputerName = $computer.Name
$Computerpwdsetdate = $Computer.PasswordLastSet
 
    #$Computerpwdsetdate
    if($Computerpwdsetdate -lt $agedate) {
 
 
	#Write-Host "Expired $ComputerName"
 
	$computernumber = $computernumber + 1         
    }
 
 
}
 
Write-Host "Total = $computernumber"

 

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Recently I rolled out an updated to Update the styles inside Word for Normal.dot. The update only updated the styles and did not change the autotext etc. After the update we wanted to check on a terminal server who had not been updated.

Open powershell and run the follinwg command

Get-ChildItem E:\RoamingProfilePath -Recurse | Where-Object {$_.LastWriteTime -lt “2012-06-23 00:00:00” -and $_.Name -eq “filename.dot“} | Export-Csc “C:\file.csv”

The excel sheet can be pruned for users via their profile path using the excel function

=SUBSTITUTE(SUBSTITUTE(B3,”E:\RoamingProfilePath“,””,1),”\AppData\Roaming\Microsoft\Templates”,””,1)

 

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

ADUsers&Comps**SolarWinds make a free tool GUI for this : http://downloads.solarwinds.com/solarwinds/Release/FreeTool/SolarWinds-Freetools-MS-Mini-Utilities.zip

*****More AD Cleaup Tools

http://www.adaxes.com/blog/cleanup-active-directory-with-powershell.html

You can run these commands in a command prompt on any DC or PC With Active Directory Tools installed

Time Perioud = Weeks so for example let’s work with 6

How to find the CN or OU Path

Open Active Directory Users and Compuer , Click on View and Advanced Features

Find the OU you need to reference and Click on Properties, Attribute Editor Tab and Copy the distinguishedName 

Inactive

Computer Accounts

Find Old Disabled or Enabled Computer accounts across the whole domain older than 6 weeks

dsquery computer -inactive 6 -limit 0

Powershell Find Only Enabled Computer inactive for 3 Months 

Search-ADAccount -ComputersOnly -AccountInactive -TimeSpan "90" | ?{$_.enabled -eq $True}

Find computer accounts old than 6 weeks and disable

dsquery computer -inactive 6 -limit 0 | dsmod computer -disabled yes

Find Old Computers in a Group CN e.g. if the Icon Looks like this : CN_Group

dsquery computer -inactive 6 -limit 0 CN=Computers,DC=domain,DC=local (Add to stop it going further then the current folder) -scope onelevel

Find Old Computers in a Operation Unit OU e.g. if the Icon Looks like this : OU

dsquery computer -inactive 6 -limit 0 OU=Clients,DC=domain,DC=local (Add to stop it going further then the current folder) -scope onelevel

Query THEN DELETE computer objects which have been inactive for 8 weeks in a specific OU and name starts with PCNAME

dsquery computer "OU=Computers,OU=OUNAME,DC=domain,DC=local" -inactive 8 -name PCNAME* | dsrm -noprompt

User Accounts

Find Old Disable or Enabled User accounts across the whole domain older than 6 weeks

dsquery user domainroot -name * -inactive 6

Powershell Find Only Enabled User inactive for 3 Months 

Search-ADAccount -UsersOnly -AccountInactive -TimeSpan "90" | ?{$_.enabled -eq $True}

Exchange Active User accounts

(Get-MailboxStatistics -Server <exchangeservername> | where {$_.LastLogonTime -gt ((get-date).AddDays(-60))}).count

Find Old User accounts across the whole domain older than 6 weeks and disable 

dsquery user domainroot -name * -inactive 6 | dsmod user -disabled yes

Active

Get-ADUser –filter * -Properties passwordLastSet,whencreated,lastlogondate,Enabled,PasswordNeverExpires | Where { ($_.passwordLastSet –eq $null –or $_.lastlogondate –gt (Get-Date).AddDays(-30)) -and ($_.Name -notlike “*svc*” -and $_.Name -notlike “*Admin*” -and $_.Name -notlike “*test*” -and $_.Name -notlike “*huonit*” -and $_.Name -notlike “*Room*” -notlike “*Mailbox*” -notlike “*Exchange*” -notlike “*Service*” -notlike “*Helpdesk*”) }| Select Name

 

VN:F [1.9.22_1171]
Rating: 10.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: -1 (from 1 vote)