Powershell CheckedListBox check if in string / array - powershell

I've started learning Powershell and am now stuck after spending several hours on a problem I can find solutions for in multiple languages except Powershell.
I need to place a check against each item in a CheckedListBox that matches any of the values in a semi-colon delimited string named $MLBSVar_SelectedPackages. (eg. $MLBSVar_SelectedPackages = 'packageA;packageB;packageC;') and so on.
I've come up with this line but it doesn't yet work. Please can you help me?
if ($MLBSVar_SelectedPackages -ne $null) {
ForEach ($PackageName in $MLBSVar_SelectedPackages) {
ForEach ($item in $clb_SC_AvailablePackages.Items) {
if ($item -eq $PackageName) {
$clb_SC_AvailablePackages.Item($PackageName).Checked = $true
}
}
}
}
I've also tried .SetItemCheckState([System.Windows.Forms.CheckState]::Checked) in place of .Checked. The (one) issue seems to be getting a handle on the list item in the final section as it seems to be passed as a string rather than object? I have a VBS background and would really appreciate the assistance.

I think what you're looking for is something like the following code. You can use the SetItemChecked() method of the CheckedListBox class to check an item at a particular index. I see that you have attempted to use SetItemCheckState(), but did not make mention of SetItemChecked().
# Import Windows Forms Assembly
Add-Type -AssemblyName System.Windows.Forms;
# Create a Form
$Form = New-Object -TypeName System.Windows.Forms.Form;
# Create a CheckedListBox
$CheckedListBox = New-Object -TypeName System.Windows.Forms.CheckedListBox;
# Add the CheckedListBox to the Form
$Form.Controls.Add($CheckedListBox);
# Widen the CheckedListBox
$CheckedListBox.Width = 350;
$CheckedListBox.Height = 200;
# Add 10 items to the CheckedListBox
$CheckedListBox.Items.AddRange(1..10);
# Clear all existing selections
$CheckedListBox.ClearSelected();
# Define a list of items we want to be checked
$MyArray = 1,2,5,8,9;
# For each item that we want to be checked ...
foreach ($Item in $MyArray) {
# Check it ...
$CheckedListBox.SetItemChecked($CheckedListBox.Items.IndexOf($Item), $true);
}
# Show the form
$Form.ShowDialog();
After running this code, you should be presented with a dialog that looks similar to the following screenshot.

Related

how to create dynamic link list from .lnk files in a folder with powershell

I would like to be able to create a dynamic link list from .lnk files in a folder with powershell. I want the link list to be presented to the user in a form that can be minimzed, but will stay active for the entire session, even if the user launch one of them the main form will remain active.
I'm having a hard time moving from VBS to powershell, so any help would be appreciated.
Finally I have managed to have a begining of solution here is my code.
$linklist = #(
("MyFisrtApp" , "\\Path\To\MyFisrtApp.exe"),
("MySecondApp" , "\\Path\To\MySecondApp.exe"),
("MyThirdApp" , "\\Path\To\MyThirdApp.exe"),
("MyFourthApp" , "\\Path\To\MyFourthApp.exe")
)
#Create Form Object
$mainform = New-Object System.Windows.Forms.Form
$mainform.Size = New-Object System.Drawing.Size(400,300)
$mainform.Text = " My Virtual Applications"
$mainform.StartPosition = "CenterScreen" #loads the window in the center of the screen
# convert the array of arrays into an ordered Hashtable
$linkHash = [ordered]#{}
$linklist | ForEach-Object { $linkHash[$_[0]] = $_[1] }
$calculatedPosition =40
$linkHash.GetEnumerator() | ForEach-Object {
$lnk = New-Object System.Windows.Forms.LinkLabel
$lnk.Text = $_.Name # set the name for the label
$lnk.Tag = $_.Value # store the link url inside the control's Tag property
$lnk.Location = New-Object System.Drawing.Point(60, $calculatedPosition)
# inside the scriptblock, $this refers to the LinkLabel control itself
$lnk.Add_Click({ Start-Process $this.Tag })
$mainform.Controls.Add($lnk)
$calculatedPosition += 40 # just a guess, you may want different vertical spacing
}
#Show Form
$mainform.ShowDialog()
My next move now is to display the icon of the .lnk file on the left of each link and also dynamically construct the linklist hashtable from the properties of a list of .lnk files in a specific folder. Also having the form to auto-size as needed if more links need to be shown, would be interesting. I'm trying different setting with mitigated results.

creating a System.Windows.Forms.Textbox that would accept array input

i'm looking for help in creating a System.Windows.Forms.Textbox that would accept array input and treat it as an array input, rn textbox properties looks something like this:
$boxname.AcceptsReturn = $true
$boxname.MultiLine = $true
$boxname.Autosize = $true
$boxname.AcceptsTab = $false
$boxname.Scrollbars = 'Vertical'
If i enter multiline paths like this:
C:\Windows
C:\Program Files
C:\Temp
$boxname.text is treated like one huge string and won't let my "test-path on each item in array" function work properly, i bound it to this box with .Add_TextChanged, what i'm trying to do is to create a box, that will perform a check that entered paths exist once the box is filled.
Is this even possible without additional parsing ? Maybe i'm missing something.
You need to split the multiline text into separate lines and then loop over these lines to do your checks.
$boxname.Add_TextChanged({
# inside the eventhandler, you can refer to the control object itself using automatic variable $this
$this.Text -split '\r?\n' -ne '' | ForEach-Object {
if (-not(Test-Path -Path $_)) {
# path does not exist, do something..
Write-Host "Path '$_' not found!"
}
}
})

Creating powershell array

I am a newby to powershell and am trying to automate a complex process. I need to copy and paste a 3 columns of data from one spreadsheet to a second one which will then be exported to an SAP transaction line by line. In my search I found the link below that discusses using $arr1 = #(0) * 20 to create the array. I have two questions.
The first question is what is the (0) referencing?
Also, using this formula how do I reference the workbook, sheet, and column that I need to use to create the array? Any help would be greatly appreciated.
PowerShell array initialization
#() is an array literal (typically used to define empty or single element array)
You can also use list object (System.Collection.ArrayList), might be more convenient since it has dynamic size.
Below is a quick and dirty example with COM object (reads data from range into array list)
$excel= new-object -com excel.application
$excel.Visible = $false
$wb = $excel.workbooks.open("$home\Documents\book1.xlsx")
$ws = $wb.Sheets.Item("Sheet1")
$data = New-Object System.Collections.ArrayList
foreach ($i in 1..20){
$data.Add( (New-Object PSObject -Property #{A=$ws.Range("A$i").Value2; B=$ws.Range("B$i").Value2}) ) | Out-Null
}
Write-Output $data
$wb.Close()

Powershell excel replace always returns true

I've doing a find and replace in a whole bunch of excel files (to update some links that have moved)
I want to track which files had changes made to them however the result of a replace is always true regardless of if the required text was is there. A find like this:
$worksheet.UsedRange.Find($Text)
will either return null if the text being looked for does not exist or an object if it does, but thats significant extra processing I'd prefer to remove given that I have about 1.2million files to check.
Here is my replace code:
$found=$false
$xlCalculationManual = -4135
$excel = New-Object -comobject Excel.Application
$excel.visible = $false
$excel.AskToUpdateLinks = $false
$excel.DisplayAlerts = $false
$excel.EnableEvents = $false
$workbook=$excel.Workbooks.Open($openfile,0,$false,5,"nopassword","nopassowrd")
$excel.Calculation = $xlCalculationManual
foreach ($worksheet in $workbook.Sheets)
{
foreach ($Text in $FindText)
{
If ($worksheet.UsedRange.replace($Text,$ReplaceText))
{
$found=$true
}
}
}
Looks like Theo is correct on this. I've not found anyway to increase the efficiency by removing the find.
Also it seems that on some files a replace only replaces the first instance and therefore a loop is also required.
Maybe try
$worksheet.UsedRange.replace($Text,$ReplaceText)
If ($?)
Instead of
If ($worksheet.UsedRange.replace($Text,$ReplaceText))
OR you could try searching for the text, and confirm that it found something?
Before your if replace option, try (I apologize, but this code is speculation, and may not full fix it. There is an article on this at https://msdn.microsoft.com/en-us/vba/excel-vba/articles/range-find-method-excel
$confirm = $worksheet.Used.Range.find($text)
if ($confirm -ne $null) {
Echo $true
$worksheet.UsedRange.replace($Text,$ReplaceText)
$confirm = $null
}
else{
echo $false
}

how to access string indexer on a collection in Powershell

Slowly learning Powershell ... I'm working on a script to query a third party AD/AM database (ldap). The specific LDAP property name that I want has a hyphen in the name.
I can do this in c# without thinking about it, but I don't want to fire up Visual Studio just to do some simple scripting stuff that changes frequently.
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
.....
$results = $objSearcher.FindAll()
foreach($result in $results) {
$item = $result.Properties
$item.some-property # this fails because of '-'
$result['some-property'] # 'Unable to index into an object of type System.DirectoryServices.SearchResult.'
}
You can also specify the property name via a variable:
$prop = 'some-property'
$result.$prop
You need to place curly braces around the hyphenated property name. This should work:
$item.{some-property}