Powershell - List View Validation - wpf

I'm trying to build a script to ease the access mirroring.
I'm comparing access groups of two users and then displaying only those that the second user is missing.
I have two List Views:
First - Filled in with access groups
Second - Empty view where I want to copy a group name.
I managed to copy the name from the first to second list view although I'm struggling with creating a validation.
Here's the code I have:
Function Add-ItemListView($Item){
if($firstItem -eq $true){
$userGroupsListView.Items.Add($Item)
$global:firstItem = $false
}
else{
foreach($i in $userGroupsListView.Items){
$itemText = $i.Name
if ($itemText -ne $Item){
$userGroupsListView.Items.Add($Item)
}
}
}
}
I think it's actually checking if there already exists an item with the same name, but I'm getting an error message:
Collection was modified; enumeration may not execute.
I will appreciate every direction or tip.
Also is there any documentation for ListView in Powershell?
I could find a bunch of helpful guides and documentation but for C#

Related

Powershell - Exporting data from powershell into a csv file using custom objects

So I received a list of users from a co-worker who needed to confirm who in the list was still employed and who wasn't. I chose to filter out all users that either didn't exist in AD or were disabled and assign them to $TerminatedUser. I took all active users that assigned them to $EmployeedUser. (I know I spelled "Employed" wrong) I then tried to use the data from $EmployeedUser and $TerminatedUser and create a report within $EmployementStatus.
What I end up with is two columns which is awesome but I also only get 1 cell for each column. All the data for each column is bunched into one cell which makes it hard to read. At first when outputting $EmployementStatus to a csv file was only getting the headers and [system.object] for each cell. I was able to get around that.
So my question here now is: Is it possible to export $EmployementStatus to a csv where the data is listed out and each "Employed"/"Terminated" user receives their own cell as opposed to them all being bunched in cells A2 and B2?
Teach me something!
This is sample code, since I'm not going to type out all that stuff again. And it isn't tested.
What you want, apparently, is to check there's an enabled AD user account that matches your userlist. For Powershell versions greater than 3.0, you can output [pscustomobject] directly into an array from a Foreach.
You just need ONE query to AD to determine if a user exists and whether the account is enabled ("Enabled" is one of the default properties returned in Get-AdUser).
It's probably more convenient for output if you simply have a "Verified" column and set that to TRUE or FALSE. Or you can have a "Status" column and output text to that like "Disabled" or "NotPresent" or "Verified". Whatever, really, I'm going with the easiest.
The try/catch is so you don't get a load of errors when the user doesn't exist. If you want to set different statuses for each "state", then you can place strings in there rather than $true/$false.
$employmentStatus = Foreach ($GID in $MyList) {
$ID = $GID.SamAccountname
try {
# if the user isn't found, it'll go to the Catch block after the next line
$u = get-aduser $ID -erroraction stop
if ($u.enabled) {
$verified = $true
}
else {
$verified = $false
}
}
catch {
# if the user doesn't exist, they're not verified
$verified = $false
}
# output the per-user status as a pscustomobject in $employmentStatus
[pscustomobject]#{
ADUser = $ID
Verified = $verified
}
}
You should find that if you process your userlist with that, you can check the result with $employmentStatus | out-gridview.
That should show the "AdUser" and "Verified" columns, with TRUE or FALSE for each user.
If that looks OK, so will your CSV export: $employmentStatus | export-csv [path].
If you're using an old PS version, then you may need to predefine your output array as you did originally. Then you'd just fix up the line with the [pscustomobject] to append it to the array. Everything else works the same.
$employmentStatus = #()
Foreach ($GID in $MyList) {
...
# output the per-user status as a pscustomobject - append to $employmentStatus
$employmentStatus += [pscustomobject]#{
ADUser = $ID
Verified = $verified
}
}

How to set nodes in a treeview to start off checked if a checkbox on a previous window is selected

First time Posting on this site. I hope I have the information formatted correctly.
I am designing a simple windows form to help create change control forms to track employee access. It is a 2 part form. The main form asks for some user input and there is a checkbox at the bottom that they can select if they are requesting a standard user setup. When they click next in the main form a child form window pops up that contains a treeview and a comments section for any special notes. What I am trying to do is have some nodes automatically checked if the 'Standard Setup' box is checked in the main form.
When I run the code I get a error stating "Method invocation failed because First[System.Windows.Forms.TreeView] does not contain a method named 'checknode'."
My standard setup box is $checkboxStandardSetup and if it has been checked then I want to have it place a checkbox next to these nodes in the treeview. If it isn't checked no other modification need to be made in the treeview. Here is a snippet of what I have.
if ($checkboxStandardSetup.Checked)
{
$treeview1.checknode("7")
$treeview1.checknode("8")
$treeview1.checknode("9")
$treeview1.checknode("10")
$treeview1.checknode("11")
$treeview1.checknode("12")
$treeview1.checknode("14")
$treeview1.checknode("20")
}
I have also tried to use
if ($checkboxStandardSetup.Checked)
{
$treeview1.node7.checked
$treeview1.node8.checked
$treeview1.node9.checked
$treeview1.node10.checked
$treeview1.node11.checked
$treeview1.node12.checked
$treeview1.node14.checked
$treeview1.node20.checked
}
But to no avail. The function below works to parse through and then output a list of the checked nodes but I can't get the standard setup box to apply those checks.
Function Get-CheckedNodes
{
param (
[ValidateNotNull()]
[System.Windows.Forms.TreeNodeCollection]$NodeCollection,
[ValidateNotNull()]
[System.Collections.ArrayList]$CheckedNodes)
foreach ($Node in $NodeCollection)
{
if ($Node.Checked)
{
[void]$CheckedNodes.Add($Node)
}
Get-CheckedNodes $Node.Nodes $CheckedNodes
}
}
To call the function I use
$checkedNodes = New-Object System.Collections.ArrayList
Get-CheckedNodes $treeview1.Nodes $CheckedNodes
foreach ($node in $CheckedNodes)
{
Write-Output $node.text | Out-File -append C:\Change\UserForm$(Get-Date -Format 'MM-dd-yy').csv
}
I expected the treeview list to have a checkbox next to the nodes that I coded but instead I get the above error. I don't understand what I am doing wrong. Any advice appreciated!

How do I save CSV data to variables based on a ListBox selection?

I have a drop down list in my script that gets populated by the "name" column in a CSV file. I'd like to save the information in the other columns that go with that name into variables to be used later.
For example (bullets are there so they show underneath each other, showed as one line otherwise):
Name,Address,PhoneNumber,Email
Bob,1234 Bob Rd,123-4567,bob#email.com
Bill,5678 Bill Ave,246-8024,bill#email.com
The drop down list would show Bob and Bill. Based on what I pick I'd like the rest of their info to be saved into 3 different variables, $Address, $PhoneNumber, and $Email.
I've got as far as importing the CSV into the array and sorting them alphabetically.
$Customers = #(Import-CSV "$dir\Apps\Customers.csv")
$Array = $Customers.name | Sort-Object
Here's part of the drop down box code:
ForEach ($Choice in $Array) {
[void] $companybox.Items.Add($Choice)
}
After that I can't figure out how to grab the correct information based on what's been chosen when I click a button.
Here's the button code:
$handler_gobutton_Click = { $company = $companybox.SelectedItem
....
}
I have a few If statements in there right now for an earlier solution that doesn't use CSV's, but I'd like to move to a CSV file if possible.
Thanks!
EDIT: I'm thinking what I need to do is somehow find the array count number based on the name column. After that I should be able to save $array[0].address into a variable, for example. Finding how to compare the variable with the name in it to the name in the array and from that getting the count number is coming up empty so far... Ideas?
Got it to work!
$handler_gobutton_Click = {
$company = $companybox.SelectedItem
$index = [array]::IndexOf($customers.name,$company)
If ($customers[$index].uninstall -eq "True") { $uninstallbox.checked = $True }
... and so on
}
Source: https://www.reddit.com/r/PowerShell/comments/t1928/finding_array_index_number/

Selecting certain properties from an object in PowerShell

The ADSI query works fine, it returns multiple users.
I want to select the 'name' and 'email' from each object that is returned.
$objSearcher = [adsisearcher] "()"
$objSearcher.searchRoot = [adsi]"LDAP://dc=admin,dc=domain,dc=co,dc=uk"
$objSearcher.Filter = "(sn=Smith)"
$ADSearchResults = $objSearcher.FindAll()
$SelectedValues = $ADSearchResults | ForEach-Object { $_.properties | Select -property mail, name }
$ADSearchResults.properties.mail gives me the email address
When I omit the 'select -properties' it will return all the properties, but trying to select certain properties comes back with nothing but empty values.
Whenever working with ADSI I find it easier to expand the objects returned using .GetDirectoryEntry()
$ADSearchResults.GetDirectoryEntry() | ForEach-Object{
$_.Name
$_.Mail
}
Note: that doing it this way gives you access to the actual object. So it is possible to change these values and complete the changes with something like $_.SetInfo(). That was meant to be a warning but would not cause issues simply reading values.
Heed the comment from Bacon Bits as well from his removed answer. You should use Get-Aduser if it is available and you are using Active Directory.
Update from comments
Part of the issue is that all of these properties are not string but System.DirectoryServices.PropertyValueCollections. We need to get that data out into a custom object maybe? Lets have a try with this.
$SelectedValues = $ADSearchResults.GetDirectoryEntry() | ForEach-Object{
New-Object -TypeName PSCustomObject -Property #{
Name = $_.Name.ToString()
Mail = $_.Mail.ToString()
}
}
This simple approach uses each objects toString() method to break the data out of the object. Note that while this works for these properties be careful using if for other and it might not display the correct results. Experiment and Debug!
Have you tried adding the properties?
$objSearcher.PropertiesToLoad.Add("mail")
$objSearcher.PropertiesToLoad.Add("name")

Copying an SMO collection into an array in Powershell

I've written a Powershell script which will compare two databases and come up with a list of objects in one of the databases to remove. I put those items (as a customized object with a name and schema) into an array.
In the next step of my script I iterate through the objects in the database and see if they match an object in my array. If I find a match then I go ahead and drop the object from my database. The problem that I ran into though, was that if I try to drop the object then the collection through which I'm iterating gets changed and I get an error message that the collection changed and IEnumerable won't work when that happens.
I tried to make a copy of collection, but I can't seem to stuff it into an array using the CopyTo method. Any suggestions?
My current code is below. When I run this the array $sprocs is empty.
function DropSQLObjects
{
param([object]$database, [object]$objectsToDrop)
$sprocs = #()
$database.StoredProcedures.CopyTo($sprocs, 0)
# If I do a $sprocs | out-host I see that the array is still empty
foreach ($objectToDrop in $objectsToDrop)
{
foreach ($sproc in $sprocs)
{
if ($sproc.Name -eq $objectToDrop.Name -and $sproc.Schema -eq $objectToDrop.Schema)
{
$sproc.Drop()
LogToSQL $database "Dropped Stored Procedure: $($objectToDrop.Schema).$($objectToDrop.Name)"
}
}
}
}
I'm adding this as an answer in case anyone else has need of this in the future. It turns out that I was really making things harder than they needed to be. Since I was using Powershell, the "where" function was better than iterating through the stored procedures.
Here's the code which solved my issue:
function DropSQLObjects
{
param([object]$database, [object]$objectsToDrop)
foreach ($objectToDrop in $objectsToDrop)
{
if ($database.StoredProcedures.Contains($objectToDrop.Name, $objectToDrop.Schema))
{
$sproc = $database.StoredProcedures | where {$_.Schema -eq $objectToDrop.Schema -and $_.Name -eq $objectToDrop.Name}
$sproc.Drop()
LogToSQL $database "Dropped Stored Procedure: $($objectToDrop.Schema).$($objectToDrop.Name)"
}
}
}
In actuality, I also have code to go against UserDefinedFunctions, but the code is mostly a cut-and-paste from the StoredProcedures portion.

Resources