Delete Method Outlook Item - powershell

I'm new in Posh and trying to understand this error message when I add select object:
Method call failed because [Selected.System.__ComObject] does not
contain a method named "Delete".
Here's my code which works fine without the | select-object:
$Outlook = New-Object -comobject “Outlook.Application”
$MAPI = $Outlook.getnamespace(“mapi”)
$folder = $MAPI.GetDefaultFolder(6)
$SubFolder = $folder.Items | Where-Object {$_.tasksubject -like “*Alert*”} | Select-Object TaskSubject
Foreach ($Folder in $SubFolder)
{
$SubFolder.delete()}
Can someone tell me why and where should I place it please? Thanks for your advices.

my code which works fine without the | select-object :
Indeed, the Select-Object call is your problem: It returns [pscustomobject] instances (which don't have a .Delete() method), whereas you need to act directly on the original Outlook folder items.
Since it doesn't look like the Select-Object call does anything useful in your case, you can simply omit it, and use ForEach-Object in the same pipeline to call the .Delete() method on each folder item (using simplified syntax):
$folder.Items |
Where-Object TaskSubject -like *Alert* |
ForEach-Object Delete

Related

Powershell import-csv $variable properly is null

I have a weird issues with Powershell Version 2.0.
The following works on newer versions but its not working as expected on this version. Any help is appreciated.
$DB = Import-Csv -Path "$($path)\DBExtrat.csv"
which is fine.
Headers in DBExtrat.csv ('hostname','hostip','name','type')
all 4 headers are reorganized and show up if i run
$DB
But if I try
$DB.name or $DB.hostname it returns noting. I need to be able to call it like this because my whole logic is tied to those specific variables names.
I've already tried adding the -header option:
$DB = Import-Csv -Path "$($path)\DBExtrat.csv" -Header 'hostname','hostip','name','type'
but it doesn't work and also creates unnecessary extra row with header data.
With an expression such as $DB.name, you're trying to get the name property values of all elements of collection $DB, by performing the property access on the collection as a whole.
This feature is called member-access enumeration, and it is only available in PowerShell v3+.
The PowerShell v2 equivalent requires use of either Select-Object or ForEach-Object:
# Note the use of -ExpandProperty to ensure that only the property *value*
# is returned (without it, you get a *custom object* with a 'name' property).
$DB | Select-Object -ExpandProperty name
# Slower alternative, but can provide more flexibility
$DB | ForEach-Object { $_.name }
I'd recommend going with #mklement0 answer; short and simple. Alternatively, going off the question you asked in the comments, you may try working with a custom object and seeing if the below works.
$import = Import-Csv -Path "$($path)\DBExtrat.csv"
$Object = New-Object psobject -Property #{
'hostname' = $import | Select-Object -ExpandProperty hostname
'hostip' = $import | Select-Object -ExpandProperty hostip
'name' = $import | Select-Object -ExpandProperty name
'type' = $import | Select-Object -ExpandProperty type
}
"$Object.hostname - $Object.hostip"

How to solve the "'IndexOf'." error in PowerShell script

While running the below script I am getting an error:
"Method invocation failed because [System.Management.Automation.PSCustomObject] doesn't contain a method named 'IndexOf'".
Please help me to find out a solution to avoid the above error while running the below script.
Code:
$serverlist_csv1 = Import-Csv -Path $file1
$serverlist_temp1 = $serverlist_csv1
$exclude_serverlist_csv = Import-Csv -Path $file2
foreach ($server in $exclude_serverlist_csv) {
$servers1 = ($serverlist_csv1.'SourceHostName' | Select-Object -ExcludeProperty 'SourceHostName')
if ($servers1 -contains $server.'Exclude Server') {
$server_object1 = ($serverlist_csv1 | Where-Object {$_.SourceHostName -eq $server.'Exclude Server'})
$serverindex1 = $serverlist_csv1.IndexOf($server_object1)
$dataResizable1 = {$serverlist_csv1}.Invoke()
$dataResizable1.RemoveAt($serverindex1)
$serverlist_csv1 = $dataResizable1
}
}
You are getting that error because you used select-object on the pipeline invocation of $serverlist_csv1, which creates a layer over the object effectively creating a new object a pscustomobject and that makes it lose the indexOf() method.
if you avoid this step and instead try for instance to exclude that on the import of the csv or modify the member to nothing if that property isn't necessary to you. The point is like people before me said that does not seem like the better way to solve whatever problem this is.
Build a list of the server names from the second file:
$exclude = Import-Csv $file2 | Select-Object -Expand 'Exclude Server'
Then filter the first file for rows whose SourceHostName column isn't one of those names and write the result back to a file:
Import-Csv $file1 | Where-Object {
$exclude -notcontains $_.SourceHostName
} | Export-Csv 'C:\output.csv' -NoType

Powershell Get-ChildItem, filtered on date with Owner and export to txt or csv

I am trying to export a list of documents modified files after a set date, including its owners from a recursive scan using Get-ChildItem.
For some reason I cannot get it to port out to a file/csv:
$Location2 = "\\fs01\DATAIT"
$loc2 ="melb"
cd $Location2
Get-ChildItem -Recurse | Where-Object { $_.lastwritetime -gt [datetime]"2017/05/01" } | foreach { Write-Host $_.Name "," $_.lastwritetime "," ((get-ACL).owner) } > c:\output\filelisting-$loc2.txt
Could any of the PowerShell gurus on here shed some light please?
The problem with your code is that you are using Write-Host which explicitly sends output to the console (which you then can't redirect elsewhere). The quick fix is as follows:
Get-ChildItem -Recurse | Where-Object { $_.lastwritetime -gt [datetime]"2017/05/01" } | foreach { "$($_.Name),$($_.lastwritetime),$((get-ACL).owner)" } > filelisting-$loc2.txt
This outputs a string to the standard output (the equivalent of using Write-Output). I've made it a single string which includes the variables that you wanted to access by using the subexpression operator $() within a double quoted string. This operator is necessary to access the properties of objects or execute other cmdlets/complex code (basically anything more than a simple $variable) within such a string.
You could improve the code further by creating an object result, which would then allow you to leverage other cmdlets in the pipeline like Export-CSV. I suggest this:
Get-ChildItem -Recurse | Where-Object { $_.lastwritetime -gt [datetime]"2017/05/01" } | ForEach-Object {
$Properties = [Ordered]#{
Name = $_.Name
LastWriteTime = $_.LastWriteTime
Owner = (Get-ACL).Owner
}
New-Object -TypeName PSObject -Property $Properties
} | Export-CSV $Loc2.csv
This creates a hashtable #{} of the properties you wanted and then uses that hashtable to create a PowerShell Object with New-Object. This Object is then returned to standard output, which goes into the pipeline so when the ForEach-Object loop concludes all the objects are sent in to Export-CSV which then outputs them correctly as a CSV (as it takes object input).
As an aside, here is an interesting read from the creator of PowerShell on why Write-Host is considered harmful.
[Ordered] requires PowerShell 3 or above. If you're using PowerShell 2, remove it. It just keeps the order of the properties within the object in the order they were defined.

Issue with Powershell custom table

I'm trying to create a custom table based on two other tables (csv-imported) - some kind of a VLOOKUP, but I can't seem to find a solution. I've come up with the following (failing) code:
$DrawPlaces | select Module, Workplace, #{ Name = "IPaddress"; Expression = {$Workstations.workstation.where($_.WorkPlace -eq $Workstations.Workplace)}} -First 15
Both Drawplaces and $Workplaces are PSCustomObject. The result of this would then go to another variable.
I'm not even sure the logic or syntax is correct, but the result table has the IPaddress column empty. I've also tried with -match instead of -eq.
This doesn't make sense: $Workstations.workstation.where($_.WorkPlace -eq $Workstations.Workplace)
.where() requires a scriptblock parameter like .where({}).
Keeping in mind that inside the where-statement $_ is refering to the current object in the $workstations.workstation-loop, your where-statement is testing ex. $workstations.workstation[0].workplace -eq $workstations.workplace. Is that really what you want?
Are you trying to achieve this?
$DrawPlaces |
Select-Object -First 15 -Property #(
"Module",
"Workplace",
#{ Name = "IPaddress"; Expression = {
#Save the Workspace-value for the current object from $DrawPlaces
$wp = $_.WorkPlace;
#Find the workstation with the same workplace as $wp
$Workstations | Where-Object { $_.WorkPlace -eq $wp} | ForEach-Object { $_.Workstation }
}
}
)

PowerShell/VBScript - Extract Outlook Mails Based on Condition

Is there a way to obtain list of all sent & received emails having suffix not equal to #gmail.com via PowerShell or VBScript and possibly store it in seperate text files.
Add-type -assembly "Microsoft.Office.Interop.Outlook" | out-null
$olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$outlook = new-object -comobject outlook.application
$namespace = $outlook.GetNameSpace("MAPI")
$folder = $namespace.getDefaultFolder($olFolders::olFolderSentMail)
$folder.items | Select-Object -Property Subject, SentOn, To
I was using the above PS to obtain sent mail, but not sure where to apply the condition.
Secondly, the subject is not appearing completely, it becomes ..... is there any way to obtain the full subject as well ?
I'm assuming you're running on a client computer not a server. If you've access to the exchange server there's powershell commandlets that are easy to use (New-MailboxExport).
$folder is a COM-Object
$folder.items property contains a collection of COM-Objects representing messages.
Since they're objects, you can use the object commands (Get-Help Object) to use their properties. You just need to dig a little more to apply your filter. Specifically one more level, to the properties of the items in $folder.items. Pipe $folder.items to Get-Member to get the full list of properties. $folder.items | gm. To, From, SentOn and Subject are all there.
$NonGmailMessages = $folder.items |
where-object { { $_.to -notcontains "gmail.com" } -and
{ $_.from -notcontains "gmail.com" } }
One way of handling collections like this is to do one massive filter like I just did. Or you can filter by stages.
$NonGmailMessages = $folder.items
$NonGmailMessages = $NonGmailMessages | where-object { { $_.to -notcontains "gmail.com" }
$NonGmailMessages = $NonGmailMessages | where-object { { $_.from -notcontains "gmail.com" }
Add further lines to further narrow your collection.
You can export this collection complete with all properties intact to a CSV:
$NonGmailMessages | Export-CSV -NoTypeInformation c:\temp\nonGmailMessages.csv
Or you can narrow the number of properties exported
$NonGmailMessages | Select-Object -Property From, To, SentOn, Subject | Export-CSV -NoTypeInformation c:\temp\nonGmailMessages.csv
-NoTypeInformation prevents the object type information from being listed at the start of the file. This will make it a more 'pure' CSV for use in PS or Excel or whatever. Plus the CSV IS a text based file format, as you wished.