PowerShell - SCOM PropertyBag, How to check if already added? - powershell

I want to add values to a PropertyBag.
How is it possible to check if the value is already in the PropertyBag?
I know one can use an array, list, etc. But how can I use the $bag/$api object to do this check?
$api = New-Object -comObject “MOM.ScriptAPI”
$bag = $api.CreatePropertyBag()
$bag.AddValue("TestValue1","1234")
I'm searching for something like this:
if($bag -match "TestValue1")
{"In the Bag!"}
But, unfortunately, it's not working.

I do not have SCOM on a server I can access, but could you do the following to get the bag contents and check against it?
$api = New-Object -comObject “MOM.ScriptAPI”
$bag = $api.CreatePropertyBag()
$bagContents = $api.Return($bag)

Related

Set ContextMenu items from a string list

Basically I'm trying to create a ContextMenu that shows a list of mounted network drive, so the user can click on one and access it.
The problem is : the list is not fix, but depend on a string list extracted from a DataGrid.
In my mind, I could just create the menu items by looping on that string list.
Here is the code sample :
$Main_Tool_Icon = New-Object System.Windows.Forms
[...]
# Add menu entries
$contextmenu = New-Object System.Windows.Forms.ContextMenu
$Main_Tool_Icon.ContextMenu = $contextmenu
foreach ($nameTag in $dataGrid[$DATAGRID_COLUMN_NAME]){
$menuEntry = New-Object System.Windows.Forms.MenuItem
$menuEntry.Text = $nameTag
$Main_Tool_Icon.ContextMenu.MenuItems.AddRange($menuEntry)
}
# Add separator
$Main_Tool_Icon.ContextMenu.MenuItems.Add('-')
# Last one to show main form
$displayMainform = New-Object System.Windows.Forms.MenuItem
$displayMainform.Text = "Edit"
$Main_Tool_Icon.ContextMenu.MenuItems.Add($displayMainform)
It appears that's wrong and only shows the separator and last "Edit" line.
Is there a way to populate a contextual menu with a list ?
Or I should look for a better way to do the job ?
EDIT #Mathias R. Jessen
You're right about AddRange(), it's just a mistake.
I can't show everything since it's quite big. I'll try to synthesize an answer properly.
The data grid is created/populated by my script and is just a table of strings from a csv file.
$DATAGRID_COLUMN_NAME = 'NAME' it's one of constants defined for my datagrid headers.
Here is the setup
# set datagrid
$dataGrid = New-Object System.Windows.Forms.DataGridView
[...]
$dataGrid.Columns.Add($DATAGRID_COLUMN_NAME,'Name')
$dataGrid.Columns[0].DataPropertyName = $dataGrid.Columns[0].Name
Then some databinding
# initiate the data table
$table = New-Object System.Data.DataTable
[...]loop on csv file[...]
# bind data table to data grid
$dataGrid.DataSource = $table
EDIT #SantiagoSquarzon
You were right for pointing out $dataGrid[$DATAGRID_COLUMN_NAME]. The syntax was bad and returned something null. Instead, I looped over the $dataGrid.Rows like so:
foreach ($row in $dataGrid.Rows){
$nameTag = $row.Cells[$DATAGRID_COLUMN_NAME].Value
if ($nameTag -ne $null){
$menuEntry = New-Object System.Windows.Forms.MenuItem
$menuEntry.Text = $nameTag
$Main_Tool_Icon.ContextMenu.MenuItems.AddRange($menuEntry)
}
}
Now I just have to figure out how to invoke there click event.

Using SendAndReceive() with ImapX

I am trying to use the ImapX DLL effectively. I have got $client.Folders.Inbox.Search() and $client.Folders.Inbox.Messages.Download() to work for downloading messages but they're very slow. I was looking into using $client.SendAndReceive() instead. I thought it would work like Outlook's send and receive but it wants a lot of parameters I don't understand.
This is the method definition:
bool SendAndReceive(string command, [ref] System.Collections.Generic.IList[string] data, ImapX.Parsing.CommandProcessor processor, System.Text.Encoding encoding, bool pushResultToDatadespiteProcessor)
I don't know what any of the parameters are for. I searched online for documentation for ImapX, but I couldn't find anything helpful.
Is SendAndReceive() a good method for downloading messages? If so, how do I use it?
This is my PowerShell code so far:
$DLL = [Reflection.Assembly]::LoadFile(“$PSScriptRoot\DLL\ImapX.dll”)
$client = New-Object ImapX.ImapClient
$client.IsDebug = $true
$client.ValidateServerCertificate = $true
$client.ThrowConnectExceptions = $true
$client.UseSsl = $false
$client.Behavior.MessageFetchMode = "Full"
$client.Host = $mailHost
$client.Port = $Port
$client.Connect()
$client.Login($user,$password)
# Downloads all messages but very slow
$client.Folders.Inbox.Search("ALL", $client.Behavior.MessageFetchMode)
$client.Folders.Inbox.Messages.Download()

Removing the Add_Click from a WinForm Button in Powershell (remove_Click)

I have got an understanding problem regarding to Powershell Code in order to remove a Click Event from a WinForm button. After several hours... several days of trying, trying to understand and despairing I thought I give it a break and probably you guys can help me. I really have read several Posts regarding this theme. But that did not help me finally. So please let me ask that question again.
I have seen that there is a possibility to use Eventhandlers and this method seems to work quite fine. As my code seems to be correct, because Powershell do not throw out an error, I would like to know why the code line seems not to be affective. I really do not understand why. Because I have found several codes with remove_Click examples, but in my case it seems not to do what I expect. As I really do not understand why I would like you to help me. Please be so kind and try to explain to me why line 30 of my script has no effect or not the desired effect.
Short: What do I want to do? I just want to remove a Click Event from a button. I could add the Event to the button using Add_Click. So I thought Remove_Click would remove the "Click Code" from this Special button. But it does not seem to work. I just want to remove the Click Property from the button if the savefiledialog is closed by using the cancel button.
This is the code:
Add-Type -AssemblyName System.Windows.Forms
function form_status(){
$form_status = New-Object System.Windows.Forms.Form
$form_status.Size = New-Object System.Drawing.Size(800,530)
$form_status.StartPosition = 'CenterScreen'
$form_status.FormBorderStyle = 'FixedToolWindow'
$form_status_button_csv_logfile = New-Object System.Windows.Forms.Button
$form_status_button_csv_logfile.Location = New-Object System.Drawing.Point(1,1)
$form_status_button_csv_logfile.Size = New-Object System.Drawing.Size(50,50)
$form_status.Controls.Add($form_status_button_csv_logfile)
$form_status_button_csv_logfile.Add_Click({Choose-Folder-For-Checksumlog})
$form_status_button_csv_logfile.add_MouseHover({button_mousehover})
$form_status_button_csv_logfile.add_MouseLeave({button_mouseleave})
[System.Windows.Forms.Application]::EnableVisualStyles();
$form_status_result = $form_status.ShowDialog()
}
Function Choose-Folder-For-Checksumlog(){
$SaveChooser = New-Object -Typename System.Windows.Forms.SaveFileDialog
$SaveChooser.InitialDirectory = [Environment]::GetFolderPath("Desktop")
$SaveChooser.Filter = "CSV Logfile (*.csv)|*.csv"
$savechooser.FileName = "testfile.csv"
if($SaveChooser.ShowDialog() -eq [System.Windows.Forms.DialogResult]::CANCEL){
$savechooser.FileName = ""
$form_status_button_csv_logfile.Remove_Click({Choose-Folder-For-Checksumlog})
}
$checksumlog_folder = $SaveChooser.FileName
}
function button_mouseleave(){
$form_status.Cursor=[System.Windows.Forms.Cursors]::Default
}
function button_mousehover(){
$form_status.Cursor=[System.Windows.Forms.Cursors]::Hand
}
form_status
I appreciate any help from you guys. Please be so kind and explain to me what I do wrong. Probably my expectaions are wrong... But I do not understand it at the moment.
With kindest Regards
FernandeZ
$clickexample = {Choose-Folder-For-Checksumlog};
$form_status_button_csv_logfile.add_Click($clickexample);
$form_status_button_csv_logfile.remove_Click($clickexample);
I know that I'm a bit late to the party, but recently I came into the situtation where it was required to remove multiple event handlers from multiple elements (several different-purpose Click handlers on each of six buttons in my case).
While suggestion from #D'Artagnan works, it is still not helpful in case if your scriptblock handler is not stored in variable (or variable is unknown).
For example, this code removes handler from the button:
$ScriptBlock = {Write-Host 'Clicked'}
$MyButtonObject.Add_Click($ScriptBlock)
$MyButtonObject.Remove_Click($ScriptBlock)
But this one does not (I believe, it is because scriptblock is not referenced by variable, therefore it is a different object, which is not registered in event handler, and, as result, cannot be removed):
$MyButtonObject.Add_Click({Write-Host 'Clicked'})
$MyButtonObject.Remove_Click({Write-Host 'Clicked'})
In addition, I wasn't able to find something like .Remove_AllHandlers(), unfortunately.
Thankfully, I've discovered this question and was able to adapt the code given by #Douglas to PowerShell, so with credits to the original author, I'm happy to share the solution with anyone who wonders:
Function Remove-RoutedEventHandlers {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $True)]
[ValidateNotNullorEmpty()]
[System.Windows.UIElement]$Element,
[Parameter(Mandatory = $True)]
[ValidateNotNullorEmpty()]
[System.Windows.RoutedEvent]$RoutedEvent
)
$eventHandlersStoreProperty = $Element.GetType().GetProperty("EventHandlersStore", [System.Reflection.BindingFlags]'Instance, NonPublic')
$eventHandlersStore = $eventHandlersStoreProperty.GetValue($Element, $Null)
If ($eventHandlersStore) {
$getRoutedEventHandlers = $eventHandlersStore.GetType().GetMethod("GetRoutedEventHandlers", [System.Reflection.BindingFlags]'Instance, Public, NonPublic')
$RoutedEventHandlers = [System.Windows.RoutedEventHandlerInfo[]]$getRoutedEventHandlers.Invoke($eventHandlersStore, $RoutedEvent)
ForEach ($RoutedEventHandler in $RoutedEventHandlers) {
$Element.RemoveHandler($RoutedEvent, $RoutedEventHandler.Handler)
}
}
}
To call the function, you must provide the control and required kind of events to be cleared. For example:
Remove-RoutedEventHandlers -Element $MyButtonObject -RoutedEvent $([System.Windows.Controls.Button]::ClickEvent)
Please note that you have to put event in $() to avoid it from being treated as string. Alternatively, you could alter the function to accept string (for example, with value "Click") and re-construct such event on the provided control inside the function like this $RoutedEvent = $Element.GetType()::"${RoutedEvent}Event"
This function enumerates all handlers of the specified type on provided object and removes them.
If I'm not mistaken, if you call $Element.Remove_SomeEvent($ScriptBlockToRemove) in PowerShell, $Element.RemoveHandler($Element.GetType()::SomeEvent, $ScriptBlockToRemove) is being executed under the hood, so in given example this function is equivalent of enumerating all of the scriptblocks (referenced in Handler property of RoutedEventHandlerInfo object) and calling $MyButtonObject.Remove_Click($ScriptBlockToRemove) on each of them

Outlook Distribution Lists (DistListItem) are not updated after a referenced contact (ContactItem) is changed

I've gathered some code from around the web to create Contacts and then Contact groups. However, if I update the contact after creation, the "relation" between the contact object inside the Contact group and the Contact is gone. The Contact group is not updated with the changes to the Contact.
If I manually create a Contact and Contact group, the relationship is just maintained as expected. Any ideas on what I could have missed?
Code for the Contact:
$olContactItem = 2
$o = new-object -comobject outlook.application
$c = $o.CreateItem($olContactItem)
$c.FullName = "Dummy Account"
$c.Email1Address = "aa#bb.com"
$a = $c.Save()
Code for the Contact group:
$outlook = new-object -com Outlook.Application
$contacts = $outlook.Session.GetDefaultFolder(10)
$session = $outlook.Session
$session.Logon("Outlook")
$namespace = $outlook.GetNamespace("MAPI")
$DL = $contacts.Items.Add("IPM.DistList")
$DL.DLName = "dummy2"
$recipient = $namespace.CreateRecipient("Dummy Account")
$recipient.Resolve()
$DL.AddMember($recipient)
$DL.Save()
Looks pretty straight forward to me. I checked the API, but that didn't get me much further.
https://msdn.microsoft.com/en-us/vba/outlook-vba/articles/recipients-object-outlook
Thanks in advance!
You add $recipient before it is initialized.
UPDATE: DistListItem.AddMember in OOM only adds one-off recipients, there is no way to add contacts. If using Redemption (I am its author) is an option, it exposes RDODistListItem.AddContact method that allows to pass either Outlook's ContactItem object or RDOContactItem object from Redemption. RDODistListItem also exposes AddMembers / AddMember / AddMemberEx methods.

Getting status of olMailItem visibility (Powershell)

I'm doing some scripting in PowerShell involving sending some mail automatically. I'm aware that the olMailItem object (on 2003 at least) has a couple of methods, Display() and Close() but is it possible to get the current visibility status?
If I run the following:
$Outlook = New-Object -ComObject Outlook.Application
$Mail1 = $Outlook.CreateItem(0)
$Mail1.To = $_.UserID
$Mail1.SentOnBehalfOfName = "me#mydomain.com"
$Mail1.Subject = $Subject1
$Mail1.Body = $BodyText1
$Mail1.Display()
$a = $Mail1
$Mail1.Close()
$b = $Mail1
I can't see any difference between $a and $b
What I was hoping for was a $Mail.IsVisible bool property or something.
Can it be done?
You can loop through the Application.Inspectors collection and compare each Inspector.CurrentItem.EntryId with MailItem.EntryId property of the item in question. If it is you who create the item and do not save it first, how can be opened in one of the Inspectors? You are the only one who can show it.