Powershell - StreamWriter only write first line - powershell

I´m working on a code that is supposed to import-csv - change the content, and then export to csv.
I´ve tried to export with Export-Csv - but it only writes the lenght of the string
I also tried with StreamWriter - but it only writes $Resultat once
I am new to PowerShell :-)
$workfile = import-csv "X:\powershell\converter\test.csv" -Delimiter ';'
ForEach ($item in $workfile)
{
$Id = $item.("ID")
$Maaler = $item.("Maaler")
$Fra = $item.("Fra")
$Til = $item.("Til")
#Dato gymnastik
$Tilto = $item.("Til")
$Tilto = $Tilto.substring(0,10)
$Til = $Til.substring($Til.length - 8, 8)
$Forbrug = $item.("Forbrug")
$Enhed = $item.("Enhed")
$aflaesningstype = $item.("Aflæsningstype?")
$T = ".000+02:00"
$Resultat = $Tilto + "T" + $Til + $T + ',"' + $Maaler + '","' + '","' + '","' + '","' + '","' + $Forbrug + '","' + $Enhed + '","' + '255"'
Write-output "$Resultat"
}
$Resultat | Export-Csv "X:\powershell\behandlet\Output $(get-date -f dd-MM-yyyy-hh-mm-ss).csv" -Delimiter ',' -NoType
#$fhStream = [System.IO.StreamWriter] "X:\powershell\behandlet\Output $(get-date -f dd-MM-yyyy-HH-mm-ss).csv"
#$fhStream.WriteLine($Resultat)
#$fhStream.Close()
The Write-output shows the output in the right way
Can anyone see what I am doing wrong ?

Try this:
$workfile = import-csv "X:\powershell\converter\test.csv" -Delimiter ';'
$result = New-Object System.Collections.ArrayList
ForEach ($item in $workfile)
{
$Id = $item.("ID")
$Maaler = $item.("Maaler")
$Fra = $item.("Fra")
$Til = $item.("Til")
#Dato gymnastik
$Tilto = $item.("Til")
$Tilto = $Tilto.substring(0,10)
$Til = $Til.substring($Til.length - 8, 8)
$Forbrug = $item.("Forbrug")
$Enhed = $item.("Enhed")
$aflaesningstype = $item.("Aflæsningstype?")
$T = ".000+02:00"
$result += $Tilto + "T" + $Til + $T + ',"' + $Maaler + '","' + '","' + '","' + '","' + '","' + $Forbrug + '","' + $Enhed + '","' + '255"'
}
$result | Out-File "X:\powershell\behandlet\Output $(get-date -f dd-MM-yyyy-hh-mm-ss).csv"

Related

Powershell modify CSV

I read a lot of questions here about this and i don't find what i search ...
I start scripting with powershell (just for information :p )
I want to modify a CSV file, exported from a database with information like "FirstName,LastName,OtherMail,IDAurion,Department". I have to add some titles to the HEADER, and i have to take informations in the CSV to concatenate some informations and put them in another CSV file.
I don't know if i explain well, i put you my script :
$OriginalCSV = "$PSScriptRoot\original.csv"
function Remove-StringLatinCharacters
{
PARAM ([string]$String)
[Text.Encoding]::ASCII.GetString([Text.Encoding]::GetEncoding("Cyrillic").GetBytes($String))
}
Import-Csv -path $OriginalCSV -Encoding Default | ForEach-Object {
$OtherMail = $_.OtherMail
$IDAurion = $_.IDAurion
$Department = $_.Department
$FirstnameCSV = $_.FirstName
$FirstName = $FirstnameCSV -replace '(^\s+|\s+$)',''
$FirstnameNoLatin = Remove-StringLatinCharacters $FirstName
$FirstnameNoLatinNoSpace = $FirstnameNoLatin -replace '\s','-'
$FirstnameFirstLetterUpper = $Firstname.Substring(0,1).ToUpper()
$LastNameCSV = $_.LastName
$LastName = $LastnameCSV -replace '(^\s+|\s+$)',''
$LastnameNoLatin = Remove-StringLatinCharacters $LastName
$LastnameNoLatinNoSpace = $LastnameNoLatin -replace '\s',''
$LastnameFirstLetterUpper = $Lastname.Substring(0,1).ToUpper()
$UserPrincipalNameCSV = $FirstnameCSV + "." + $LastNameCSV + "#campus.ocellia.fr"
$UserPrincipalNameConcatene = $FirstnameNoLatinNoSpace + "." + $LastNameNoLatinNoSpace + "#email.fr"
$UserPrincipalName = $UserPrincipalNameConcatene.ToLower()
$MailNickName = $FirstnameNoLatinNoSpace.substring(0,1).toupper() + $($FirstnameNoLatin.substring(1).tolower() -replace '\s','') + $LastnameNoLatinNoSpace.toupper()
$Password = $FirstnameFirstLetterUpper + $LastnameFirstLetterUpper + $IDAurion + "$"
$Number = 0
Get-Content $OriginalCSV |
ForEach-Object{
If($Number -eq 0){
$_ + ",MailNickName" + ",Password" + ",UserPrincipalName"
$Number = 1
}
Else {
$_ + "," + $MailNickName + "," + $Password + "," + $UserPrincipalName
}
} | Out-File $PSScriptRoot\Modified-CSV.csv
}
This work for 1 line, but not for multiples line ...
Edit :
This is the examples for input CSV and how i want the resulting output CSV:
Input csv :
Firstname,Lastname,OtherMail,ID,Department
Pierre,DUPONT,pierre.dupont#mail.com,123456,Paris
Marie,CHANTAL,marie.chantal#mail.com,456789,Marseille
Output csv:
Firstname,Lastname,OtherMail,ID,Department,MailNickName,Password,UserPrincipalName
Pierre,DUPONT,pierre.dupont#mail.com,123456,Paris,PierreDupont,PD123456,p.dupont#entreprise.com
Marie,CHANTAL,marie.chantal#mail.com,456789,Marseille,MarieCHANTAL,MC456789,m.chantal#entreprise.com
I'm guessing this is what you're trying to do but since we don't have a minimal reproducible example it's quite hard to tell. I also attempted to improve your code, there was a lot of redundancy.
$OriginalCSV = "$PSScriptRoot\original.csv"
$ModifiedCSV = "$PSScriptRoot\modified.csv"
$txtInfo = (Get-Culture).TextInfo
function Remove-StringLatinCharacters
{
PARAM ([string]$String)
[Text.Encoding]::ASCII.GetString([Text.Encoding]::GetEncoding("Cyrillic").GetBytes($String))
}
(Import-Csv -Path $OriginalCSV -Encoding Default | ForEach-Object {
$OtherMail = $_.OtherMail.Trim()
$IDAurion = $_.IDAurion.Trim()
$Department = $_.Department.Trim()
$FirstnameCSV = $_.FirstName.Trim()
$LastNameCSV = $_.LastName.Trim()
$firstName = (Remove-StringLatinCharacters $FirstName) -replace '\s','-'
$lastName = (Remove-StringLatinCharacters $LastName) -replace '\s'
$UserPrincipalName = "$FirstnameCSV.$LastNameCSV#campus.ocellia.fr"
$UserPrincipalNameConcat = "$firstName.$lastName#email.fr".ToLower()
$MailNickName = $txtInfo.ToTitleCase($firstName) + $lastName.ToUpper()
$Password = "{0}{1}$IDAurion$" -f $firstName.ToUpper()[0],$lastName.ToUpper()[0]
[pscustomobject]#{
FirstNameCSV = $FirstnameCSV
LastNameCSV = $LastNameCSV
OtherMail = $OtherMail
IDAurion = $IDAurion
Department = $Department
MailNickName = $MailNickName
Password = $Password
UserPrincipalNameCAMPUS = $UserPrincipalName
UserPrincipalNameEMAILFR = $UserPrincipalNameConcat
}
} | ConvertTo-Csv -NoTypeInformation) -replace '"' |
Out-File $ModifiedCSV

How to handle looping to create file using powershell?

I have INI file and I want to get specific section. The items in the section that I choose are 24 items. I want to use all the item to write in a file. I tried this, It works, but it looks like bad way to write 24 times to do the process. Is there any other way to do that more beautiful? The section of my INI file like this
Input ini:
[Code]
A1=12,34,56
A2=23,45,67
A3=34,56,78,9,10
...
A24=a1,b2,c3,d4,e5
Script:
Function F_ML
{
$FilePath = "C:\Users\File.ini"
$section = "Code"
$R_1 = "A1"
$R_2 = "A2"
$R_3 = "A3"
$R_4 = "A4"
$R_5 = "A5"
$R_6 = "A6"
$R_7 = "A7"
$R_8 = "A8"
$R_9 = "A9"
$R_10 = "A10"
$R_11 = "A11"
$R_12 = "A12"
$R_13 = "A13"
$R_14 = "A14"
$R_15 = "A15"
$R_16 = "A16"
$R_17 = "A17"
$R_18 = "A18"
$R_19 = "A19"
$R_20 = "A20"
$R_21 = "A21"
$R_22 = "A22"
$R_23 = "A23"
$R_24 = "A24"
$store = "C:\Users\"
$FilePath
$input_file = $FilePath
$ini_file = #{}
Get-Content $input_file | ForEach-Object {
$_.Trim()
} | Where-Object {
$_ -notmatch '^(;|$)'
} | ForEach-Object {
if ($_ -match '^\[.*\]$') {
$section = $_ -replace '\[|\]'
$ini_file[$section] = #{}
} else {
$key, $value = $_ -split '\s*=\s*', 2
$ini_file[$section][$key] = $value
}
}
#--------
$Path_Store = $store
#---------
$Get_1 = $ini_file.($section).($R_1)
$L_1 = $Get_1.Substring(0,3)
$Get_2 = $ini_file.($section).($R_2)
$L_2 = $Get_2.Substring(0,3)
$Get_3 = $ini_file.($section).($R_3)
$L_3 = $Get_3.Substring(0,3)
#---------
$Outer = ";********************"
$Header = ";*******************"
$ML = "12345"
$FB = ";Initial=1a2b"
#----------
$B_ID_1 = ";Build=" + $ML + "#" + "S" + $L_1 + "#" + "D" + $L_1
$CRM_1 = ";CRM=" + $R_1
$Output_1 = $Header, $B_ID_1, $FB, $CRM_1 , $Outer | Out-File $Path_Store\A1
$B_ID_2 = ";Build=" + $ML + "#" + "S" + $L_2 + "#" + "D" + $L_2
$CRM_2 = ";CRM=" + $R_2
$Output_2 = $Header, $B_ID_2, $FB, $CRM_2 , $Outer | Out-File $Path_Store\A2
$B_ID_3 = ";Build=" + $ML + "#" + "S" + $L_3 + "#" + "D" + $L_3
$CRM_3 = ";CRM=" + $R_3
$Output_3 = $Header, $B_ID_3, $FB, $CRM_3 , $Outer | Out-File $Path_Store\A3
#---------
}
$call = F_ML
My expectation, I can make this way shorter and the output is getting 24 output file.
Output Sample
Output File 1
;********************
;Build=12345#S12#D12
;Initial=1a2b
;CRM=A1
;********************
Output File 2
;********************
;Build=12345#S23#D23
;Initial=1a2b
;CRM=A2
;********************
Try below...
$IniContent = Get-Content -Path $IninPath
$IniContent | ForEach-Object -Process {
$Split = $_ -split '=';
$OutPutfilePath = "c:\temp\$($Split[0]).txt"
$first = ($Split[1] -split ',')[0]
$append = "#S{0}D{1}" -f $first,$first
# create a herestring to build the output
#"
;********************
;Build=$Ml$append
$FB
;CRM=$($Split[0])
;********************
"# | Out-File -Path $OutPutfilePath -Force
}
Use a ForEach to manipulate a string and Invoke the Expression.
1..24 | ForEach-Object { Invoke-Expression -Command (
'$R_{0} = "A{0}"' -f $_
)}
.
.
.
1..24 | ForEach-Object { Invoke-Expression -Command (
'$Get_{0} = $ini_file.($section).($R_{0}) `
$L_{0} = $Get_{0}.Substring(0,3)' -f $_
)}
.
.
.
1..24 | ForEach-Object { Invoke-Expression -Command (
'$B_ID_{0} = ";Build=" + $ML + "#" + "S" + $L_{0} + "#" + "D" + $L_{0}
$CRM_{0} = ";CRM=" + $R_{0}
$Output_{0} = $Header, $B_ID_{0}, $FB, $CRM_{0} , $Outer | Out-File $Path_Store\A{0}' -f $_
)}
{0} will be replaced by the value behind -f so it will be replaced Foreach number from 1 to 24...
Would this work?
All I did here was use your existing code to run everything in a loop from 1 to 24, removing the duplicated code. I reformatted it a little so it was a little easier for me to read.
Essentially, the variable $i will be a number from 1 to 24, while the variable $R will be "A" and whatever number is in $i (essentially A + $i)
Function F_ML
{
$section = "Code"
$store = "C:\Users\"
$input_file = "C:\Users\File.ini"
$ini_file = #{}
for ($i=1; $i -le 24; $i++)
{
$R = "A$($i)"
Get-Content $input_file |
ForEach-Object `
{
$_.Trim()
} |
Where-Object `
{
$_ -notmatch '^(;|$)'
} |
ForEach-Object `
{
if ($_ -match '^\[.*\]$')
{
$section = $_ -replace '\[|\]'
$ini_file[$section] = #{}
}
else
{
$key, $value = $_ -split '\s*=\s*', 2
$ini_file[$section][$key] = $value
}
}
#--------
$Path_Store = $store
#---------
$Get = $ini_file.($section).($R)
$L = $Get.Substring(0,3)
#---------
$Outer = ";********************"
$Header = ";*******************"
$ML = "12345"
$FB = ";Initial=1a2b"
#----------
$B_ID = ";Build=" + $ML + "#" + "S" + $L + "#" + "D" + $L
$CRM = ";CRM=" + $R
$Output = $Header, $B_ID, $FB, $CRM , $Outer | Out-File $Path_Store\$R
}
}

Export/Import Term Set in SharePoint 2013

For navigation purpose, we use Term sets.
I need to create a PowerShell to get term sets with URLs from specific term groups.
Here is my script
Set-ExecutionPolicy -Scope CurrentUser Unrestricted
#Specify admin user and SharePoint site URL
##update login
$User = "corporate\spuser"
##update siteUrl
$Site = "http://sp13"
#Adding references to SharePoint client assemblies
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Taxonomy.dll"
$Pwd = "xvcx23423"
$GroupName = "India"
$TermSetName ="India_Global"
#Recursive function to get terms
function GetTerms([Microsoft.SharePoint.Client.Taxonomy.Term] $Term,[String]$ParentTerm,[int] $Level)
{
$Terms = $Term.Terms;
$Context.Load($Terms)
$Context.ExecuteQuery();
if($ParentTerm)
{
$ParentTerm = $ParentTerm + "," + $Term.Name;
}
else
{
$ParentTerm = $Term.Name;
}
Foreach ($SubTerm in $Terms)
{
$Level = $Level + 1;
#up to 7 terms levels are written
$NumofCommas = 7 - $Level;
$commas ="";
For ($i=0; $i -lt $NumofCommas; $i++)
{
$commas = $commas + ",";
}
$file.Writeline("," + "," + "," + "," + $Term.Description + "," + $ParentTerm + "," + $SubTerm.Name + $commas );
GetTerms -Term $SubTerm -ParentTerm $ParentTerm -Level $Level;
}
}
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($Site)
$Credentials = New-Object System.Net.NetworkCredential($User,$Pwd);
$Context.Credentials = $Credentials
$MMS = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($Context)
$Context.Load($MMS)
$Context.ExecuteQuery()
#Get Term Stores
$TermStores = $MMS.TermStores
$Context.Load($TermStores)
$Context.ExecuteQuery()
$TermStore = $TermStores[0]
$Context.Load($TermStore)
$Context.ExecuteQuery()
#Get Groups
$Group = $TermStore.Groups.GetByName($GroupName)
$Context.Load($Group)
$Context.ExecuteQuery()
#Bind to Term Set
$TermSet = $Group.TermSets.GetByName($TermSetName)
$Context.Load($TermSet)
$Context.ExecuteQuery()
#Create the file and add headings
$OutputFile = "Output File Path1.csv"
$file = New-Object System.IO.StreamWriter($OutputFile)
$file.Writeline("Term Set Name,Term Set Description,LCID,Available for Tagging,Term Description,Level 1 Term,Level 2 Term,Level 3 Term,Level 4 Term,Level 5 Term,Level 6 Term,Level 7 Term");
$Terms = $TermSet.Terms
$Context.Load($Terms);
$Context.ExecuteQuery();
$lineNum = 1;
Foreach ($Term in $Terms)
{
if($lineNum -eq 1)
{
##output term properties on first line only
$file.Writeline($TermSet.Name + "," + $TermSet.Description + "," + $TermStore.DefaultLanguage + "," + $TermSet.IsAvailableForTagging + "," + $Term.Description + "," + $Term.Name + "," + "," + "," + "," + "," + "," );
}
else
{
$file.Writeline("," + "," + "," + "," + $Term.Description + "," + $Term.Name + "," + "," + "," + "," + "," + "," );
}
$lineNum = $lineNum + 1;
$TermTreeLevel = 1;
GetTerms -Term $Term -Level $TermTreeLevel -ParentTerm "";
}
$file.Flush();
$file.Close();
Any idea how to get the URLs of the term set.
Is there any better approach to export/import term set of a specific group.
You can get the term set friendly URL using TaxonomySession:
SPSite site = SPSite.Current.Site;
TaxonomySession servis = new TaxonomySession(site);
siteNavigationStore = servis.DefaultSiteCollectionTermStore;
siteNavigationGroup = sitenavigationstore.GetSiteCollectionGroup(site);
siteNavigationSet = sitenavigationgrup.TermSets["Term Set Name"];
NavigationTerm navigatedTerm = NavigationTerm.GetAsResolvedByWeb(navigationterm, site.RootWeb, StandardNavigationProviderNames.GlobalNavigationTaxonomyProvider);
navigatedTerm.GetWebRelativeFriendlyUrl();
GetWebRelativeFriendlyUrl return your friendly url

Method invocation failed because [Microsoft.Exchange.Data.Directory.ADObjectId] doesn't contain a method named 'op_Addition'

I've never encountered this error in PowerShell before. Using an IDE it works, but it doesn't work in the Exchange shell window.
I can do this all day in C#, but for some reason it doesn't work in Powershell. I've seen a bunch of examples on the net saying I can't use the + in the .Add() method, as well as defining $results as an array and using += with that, but none of those work.
I'd appreciate it someone could fix my code, but also tell me why this isn't working so that I can not make this mistake again.
The error message is
Method invocation failed because [Microsoft.Exchange.Data.Directory.ADObjectId]
doesn't contain a method named 'op_Addition'.
At C:\Users\XXXX\Desktop\bleh1.ps1:168 char:3
+ $results.Add($serverName + "|" + $totalDbs.ToString() + "|" + $activeDbs.ToSt ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~‌​~~~~~~~~~~~~~~~~~~~~‌​~~~
+ CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
To reproduce you only need to populate $servers with 2 or more Exchange server names
$servers = #("server1", "server2");
[int] $mountedDBs = 0;
[int] $dismountedDBs = 0;
$preferenceOne = 0;
$preferenceTwo = 0;
$preferenceThree = 0;
$preferenceFour = 0;
[int] $displayLineCount = 0;
$results = New-Object System.Collections.ArrayList
foreach($server in $servers)
{
if ($server -ne "")
{
[Array]$values = Get-MailboxDatabase -Server $server -Status;
$serverTest = $server;
Clear-Item Variable:mountedDBs
Clear-Item Variable:dismountedDBs
for($i = 0; $i -lt $values.Count; $i++)
{
#servername totaldbs activedbs passivedbs preferencecountlist mounteddbs dismounteddbs dagname
$serverName = $server;
$totaldbs = $values.Count;
$temp1 = $values[$i].Mounted;
if ($values[$i].Mounted -eq "true")
{
$mountedDBs = $mountedDBs + 1 | Out-Null;;
}
else
{
$dismountedDBs = $dismountedDBs + 1 | Out-Null;;
}
$activationPrefTemp = $values[$i].ActivationPreference;
for($j = 0; $j -lt $activationPrefTemp.Count; $j++)
{
$temp1 = $activationPrefTemp[$j].ToString();
if ($activationPrefTemp[$j].ToString().Contains($server.ToString()))
{
$activationPref = $activationPrefTemp[$j];
[string]$activationPrefNumber = $activationPref;
[int] $index = $activationPrefNumber.IndexOf(",");
$activationPrefNumber = $activationPrefNumber.Remove(0, $index + 1);
$activationPrefNumber = $activationPrefNumber.Trim()
$index = $activationPrefNumber.IndexOf("]");
$activationPrefNumber = $activationPrefNumber.Remove($index);
Switch ($activationPrefNumber)
{
1 {$preferenceOne = $preferenceOne + 1; break;}
2 {$preferenceTwo = $preferenceTwo + 1; break;}
3 {$preferenceThree = $preferenceThree + 1; break;}
4 {$preferenceFour = $preferenceFour + 1; break;}
default {$null}
}
}
}
$mountedDBs = $mountedDBs;
}
$activeDbs = $preferenceOne;
$passiveDbs = $preferenceTwo + $preferenceThree + $preferenceFour;
$results.Add($serverName + "|" + $totalDbs.ToString() + "|" + $activeDbs.ToString() + "|" + $passiveDbs.ToString() + "|" + $preferenceOne + "," + $preferenceTwo + "," + $preferenceThree + "," + $preferenceFour + "|" + $mountedDBs + "|" + $dismountedDbs + "|" + $dagName);
$displayLineCount = $displayLineCount + 1 | Out-Null;
$preferenceOne = 0 | Out-Null;
$preferenceTwo = 0 | Out-Null;
$preferenceThree = 0 | Out-Null;
$preferenceFour = 0 | Out-Null;
}
}
This is what ended up working, thank you for the help #MacroPower . You deleted your post so I do not know how to give you credit for answering?
You were right, because the $server variable was not explicitly typed as a string, the .ToString() cast was necessary.
[int] $mountedDBs = 0;
[int] $dismountedDBs = 0;
$preferenceOne = 0;
$preferenceTwo = 0;
$preferenceThree = 0;
$preferenceFour = 0;
[int] $displayLineCount = 0;
$results = New-Object "System.Collections.Generic.List[String]"
foreach($server in $servers)
{
if ($server -ne "")
{
[Array]$values = Get-MailboxDatabase -Server $server -Status;
$serverTest = $server;
Clear-Item Variable:mountedDBs
Clear-Item Variable:dismountedDBs
for($i = 0; $i -lt $values.Count; $i++)
{
#servername totaldbs activedbs passivedbs preferencecountlist mounteddbs dismounteddbs dagname
$serverName = $server;
$totaldbs = $values.Count;
$temp1 = $values[$i].Mounted;
if ($values[$i].Mounted -eq "true")
{
$mountedDBs = $mountedDBs + 1;
}
else
{
$dismountedDBs = $dismountedDBs + 1;
}
$activationPrefTemp = $values[$i].ActivationPreference;
for($j = 0; $j -lt $activationPrefTemp.Count; $j++)
{
$temp1 = $activationPrefTemp[$j].ToString();
if ($activationPrefTemp[$j].ToString().Contains($server.ToString()))
{
$activationPref = $activationPrefTemp[$j];
[string]$activationPrefNumber = $activationPref;
[int] $index = $activationPrefNumber.IndexOf(",");
$activationPrefNumber = $activationPrefNumber.Remove(0, $index + 1);
$activationPrefNumber = $activationPrefNumber.Trim()
$index = $activationPrefNumber.IndexOf("]");
$activationPrefNumber = $activationPrefNumber.Remove($index);
Switch ($activationPrefNumber)
{
1 {$preferenceOne = $preferenceOne + 1; break;}
2 {$preferenceTwo = $preferenceTwo + 1; break;}
3 {$preferenceThree = $preferenceThree + 1; break;}
4 {$preferenceFour = $preferenceFour + 1; break;}
default {$null}
}
}
}
$mountedDBs = $mountedDBs;
}
$activeDbs = $preferenceOne;
$passiveDbs = $preferenceTwo + $preferenceThree + $preferenceFour;
$results.Add($serverName.ToString() + "|" + $totalDbs.ToString() + "|" + $activeDbs.ToString() + "|" + $passiveDbs.ToString() + "|" + $preferenceOne + "," + $preferenceTwo + "," + $preferenceThree + "," + $preferenceFour + "|" + $mountedDBs + "|" + $dismountedDbs + "|" + $dagName);
$displayLineCount = $displayLineCount + 1 | Out-Null;
$preferenceOne = 0;
$preferenceTwo = 0;
$preferenceThree = 0;
$preferenceFour = 0;
}

Download attachments with multiple subjects from Exchange

I am attempting to download attachments from emails with certain subject lines in an inbox, then delete the email.
There are about a dozen different subject lines in total.
I want to schedule this process to run every 10 minutes or so, so I'd like to keep any processing overheads to a minimum..
Current script is in PowerShell (based on this), but I'm unsure how I could make it loop through a bunch of different subjects. I could just repeat the whole script for each subject, but it's quite inefficient this way..
I'm open to non-PowerShell alternatives too..
$MailboxName = "mailbox#address.com"
$Subject = #("Subject1")
$downloadDirectory = "c:\temp"
Function FindTargetFolder($FolderPath){
$tfTargetidRoot = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)
$tfTargetFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$tfTargetidRoot)
for ($lint = 1; $lint -lt $pfArray.Length; $lint++) {
$pfArray[$lint]
$fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1)
$SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+isEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$pfArray[$lint])
$findFolderResults = $service.FindFolders($tfTargetFolder.Id,$SfSearchFilter,$fvFolderView)
if ($findFolderResults.TotalCount -gt 0){
foreach($folder in $findFolderResults.Folders){
$tfTargetFolder = $folder
}
}
else{
"Error Folder Not Found"
$tfTargetFolder = $null
break
}
}
$Global:findFolder = $tfTargetFolder
}
$dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll"
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
$windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$sidbind = "LDAP://<SID=" + $windowsIdentity.user.Value.ToString() + ">"
$aceuser = [ADSI]$sidbind
$uri=[system.URI] "https://webmail.company.com.au/EWS/Exchange.asmx"
$service.Url = $uri
FindTargetFolder($ProcessedFolderPath)
$folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
$InboxFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
$Sfsub = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::Subject, $Subject[0])
$Sfha = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::HasAttachments, $true)
$sfCollection = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And);
$sfCollection.add($Sfsub)
$sfCollection.add($Sfha)
$view = new-object Microsoft.Exchange.WebServices.Data.ItemView(2000)
$frFolderResult = $InboxFolder.FindItems($sfCollection,$view)
foreach ($miMailItems in $frFolderResult.Items){
$miMailItems.Subject
$miMailItems.Load()
foreach($attach in $miMailItems.Attachments){
$attach.Load()
$fiFile = new-object System.IO.FileStream(($downloadDirectory + “\” + (Get-Date -Format "yyMMdd") + "_" + $attach.Name.ToString()), [System.IO.FileMode]::Create)
$fiFile.Write($attach.Content, 0, $attach.Content.Length)
$fiFile.Close()
write-host "Downloaded Attachment : " + (($downloadDirectory + “\” + (Get-Date -Format "yyMMdd") + "_" + $attach.Name.ToString()))
}
$miMailItems.isread = $true
$miMailItems.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)
$miMailItems.delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::MoveToDeletedItems)
}
Okay, here's what I've got:
$Subjects = #(
'newIM_IPSC',
'newCM_IPSC',
'CNSDI',
'SMEC_Incident_SLM',
'Incident_SLM',
'MEC_Incident_WorkInfo',
'SMEC_Incident_Header',
'SMEC_SR_Header'
)
[regex]$SubjectRegex = ‘^(?i)(‘ + (($Subjects |foreach {[regex]::escape($_)}) –join “|”) + ‘)$’
Then:
foreach($attach in $miMailItems.Attachments){
foreach ($miMailItems in $frFolderResult.Items){
if ($miMailItems.Subject -match $SubjectRegex)
{
$miMailItems.Load()
foreach($attach in $miMailItems.Attachments){
$attach.Load()
$fiFile = new-object System.IO.FileStream(($downloadDirectory + “\” + (Get-Date -Format "yyMMdd") + "_" + $attach.Name.ToString()), [System.IO.FileMode]::Create)
$fiFile.Write($attach.Content, 0, $attach.Content.Length)
$fiFile.Close()
write-host "Downloaded Attachment : " + (($downloadDirectory + “\” + (Get-Date -Format "yyMMdd") + "_" + $attach.Name.ToString()))
}
$miMailItems.isread = $true
$miMailItems.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)
$miMailItems.delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::MoveToDeletedItems)
}
}
Add or remove subject lines from the $Subjects array as needed.
An explanation of the bits that are building the regex can be found here:
http://blogs.technet.com/b/heyscriptingguy/archive/2011/02/18/speed-up-array-comparisons-in-powershell-with-a-runtime-regex.aspx