Powershell PowerPoint Header - powershell

I have a simple script that creates a Word Document and a PowerPoint document for staff that are sitting an exam where the files needed are pre loaded to a user area on a file share. The Word Document opens an creates the document header with the line of code
$Header = $Section.Headers.Item(1);
$Header.Range.Text = "$FirstName $SecondName $ID Activity 1";
PowerPoint is a bit more funnier and when you add a header it asks for dates. Is there a way to do this with powershell? We are printing them afterwards so would be a lot more benificial to have the variables that are in the CSV printed in the header of the document.
If this isn't doable is there a way to edit the first slide to have the variables in the first slide of the PowerPoint.
If anyone is able to look at the code or any ways of simplifying it, it would be massively appreiciated
The CSV is listed below and the full script is at the bottom :)
ID Four First Second
219999 9999 Tech Support
Have a good day
$Exams = Import-Csv "C:\\techtest.csv"
$fileserver = "C:\\ExamHomes\"
foreach ($User in $Exams)
{
$FirstName = $User.First
$SecondName = $User.Second
$ID = $User.ID
$FourID = $User.Four
$Time = "am"
$Date = "1511"
$Word = New-Object -ComObject Word.Application;
$Word.Visible = $false;
$Doc = $Word.Documents.Add();
$Section = $Doc.Sections.Item(1);
$Header = $Section.Headers.Item(1);
$Header.Range.Text = "$FirstName $SecondName $ID Activity 1";
$Doc.SaveAs("$fileserver\${date}${time}-${FourID}\Desktop\activity 1_${ID}_${FirstName}_${SecondName}.docx");
$Word.Quit()
Write-Host "File 'activity 1_${ID}_${FirstName}_${SecondName}.docx' for $FirstName $SecondName has been created and sent to the folder ${date}${time}-${FourID}" -BackgroundColor Black -ForegroundColor Cyan
add-type -assembly microsoft.office.interop.powerpoint
$Application = New-Object -ComObject powerpoint.application
$slideType = "microsoft.office.interop.powerpoint.ppSlideLayout" -as [type]
$presentation = $application.Presentations.add()
$presentation.SaveAs("$fileserver\${date}${time}-${FourID}\Desktop\activity 1_${ID}_${FirstName}_${SecondName}.pptx")
$presentation.close()
Stop-Process -name POWERPNT -Force
Write-Host "File 'activity 1_${ID}_${FirstName}_${SecondName}.pptx' for $FirstName $SecondName has been created and sent to the folder ${date}${time}-${FourID}" -BackgroundColor Black -ForegroundColor Cyan
}
Write-Host "All Staff have successfully had their document deployed for the exam" -BackgroundColor Black -ForegroundColor Red

Headers are only available for Notes Master and Handout Master objects
But you can add a Footer on a slide.
Add-Type -AssemblyName microsoft.office.interop.powerpoint
$Application = New-Object -ComObject powerpoint.application
$presentation = $application.Presentations.add()
$slide = $presentation.Slides.Add(1, [Microsoft.Office.Interop.PowerPoint.PpSlideLayout]::ppLayoutTitle)
$slide.Shapes.Title.TextFrame.TextRange.Text = "My Title"
$slide.Shapes(2).TextFrame.TextRange.Text = "My SubTitle"
$slide.HeadersFooters.Footer.Visible = $true
$slide.HeadersFooters.Footer.Text = "My Name"
You can use some Text on the DateAndTime HeaderFooter object like this:
$slide.HeadersFooters.DateAndTime.Visible = $true
$slide.HeadersFooters.DateAndTime.UseFormat = $true
$slide.HeadersFooters.DateAndTime.Format = [Microsoft.Office.Interop.PowerPoint.PpDateTimeFormat]::ppDateTimeFigureOut
$slide.HeadersFooters.DateAndTime.Text = "Coucou"
EDIT: SLIDE MASTER
In fact this can be defined on the SlideMaster so that every Slide inherit the values from the footer, pagenumber or datetime.
This is defined at the presentation level. So depending what you want do it on the SlideMaster or on any Slide you create. Probably a Slide may override the values from the SlideMaster.
$presentation.SlideMaster.HeadersFooters.SlideNumber.Visible = $true
$presentation.SlideMaster.HeadersFooters.Footer.Visible = $true
$presentation.SlideMaster.HeadersFooters.Footer.Text = "My Name"
$presentation.SlideMaster.HeadersFooters.DateAndTime.Visible = $true
$presentation.SlideMaster.HeadersFooters.DateAndTime.UseFormat = $true
$presentation.SlideMaster.HeadersFooters.DateAndTime.Format = [Microsoft.Office.Interop.PowerPoint.PpDateTimeFormat]::ppDateTimeFigureOut
$presentation.SlideMaster.HeadersFooters.DateAndTime.Text = "Something"

Related

Powershell: Output a search from a csv to a small gui

maybe one of you experts can help a complete newbie (I don't know if what I want is even feasible).
Let's assume I have a CSV file with various data. (see csv_screenshot)csv_screenshot
I import this data via Powershell into a small GUI . How can I make it so that when I search for "Paris", I really only get the output for Paris in the GUI as a list view like this (see powershell_screenshot)
powershell_screenshot
Currently the output in the GUI looks like this (see current_result.png). How do I get it nicely formatted as a list in there. I really want to insert it like this (via Out Grid View it is no problem)
current_result.png
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Windows.Forms.Application]::EnableVisualStyles();
function search_csv {
$Input = $textbox_Search.text
$Input = "*$Input*"
$Input_Result = import-csv -path C:\Users\check.csv -Header "Location", "Client", "Mobile Device"
$output_TextBox.text = $Input_Result -like $Input
}
$search_csvtool = New-Object System.Windows.Forms.Form
$search_csvtool.Text = "CSV Search"
$search_csvtool.Size = New-Object System.Drawing.Size(674,500)
$search_csvtool.FormBorderStyle ="FixedDialog"
$search_csvtool.TopMost = $true
$search_csvtool.MaximizeBox = $false
$search_csvtool.MinimizeBox = $true
$search_csvtool.ControlBox = $true
$search_csvtool.StartPosition = "CenterScreen"
$search_csvtool.Font = "Courier New"
$label_Search = New-Object System.Windows.Forms.Label
$label_Search.Location = New-Object System.Drawing.Size(195,18)
$label_Search.Size = New-Object System.Drawing.Size(265,32)
$label_Search.TextAlign ="MiddleCenter"
$label_Search.Text = "Please enter "
$search_csvtool.Controls.Add($label_Search)
$textbox_Search = New-Object System.Windows.Forms.TextBox
$textbox_Search.Location = New-Object System.Drawing.Size(195,50)
$textbox_Search.Size = New-Object System.Drawing.Size(266,37)
$search_csvtool.Controls.Add($textbox_Search)
$button_Search = New-Object System.Windows.Forms.Button
$button_Search.Location = New-Object System.Drawing.Size(195,80)
$button_Search.Size = New-Object System.Drawing.Size(266,24)
$button_Search.TextAlign = "MiddleCenter"
$button_Search.Text = "Search"
$button_Search.Add_Click({search_csv})
$search_csvtool.Controls.Add($button_Search)
$output_TextBox = New-Object System.Windows.Forms.TextBox
$output_TextBox.Multiline = $true;
$output_TextBox.Location = New-Object System.Drawing.Size(16,130)
$output_TextBox.Size = New-Object System.Drawing.Size(627,314)
$output_TextBox.ScrollBars = "Vertical"
$output_TextBox.ReadOnly = $true;
$search_csvtool.Controls.Add($output_TextBox)
$search_csvtool.Add_Shown({$search_csvtool.Activate()})
[void] $search_csvtool.ShowDialog()
Ok, so here's what I meant in my comment:
Start the code with
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$csvData = Import-Csv -path 'C:\Users\check.csv' -Header "Location", "Client", "Mobile Device"
function search_csv {
$searchThis = $textbox_Search.Text.Trim()
# use $script: scoping here to reference the $csvData variable
$data = $script:csvData | Where-Object {$_.Location -like "*$searchThis*"}
if ($data) {
$output_TextBox.Text = ($data | Format-List | Out-String).Trim()
}
else {
$output_TextBox.Text = "Not found.."
}
}
Then create the rest of the form as you did.
Important: Destroy the form when done with a last new code line:
$search_csvtool.Dispose()
You should then have this result:
As per your comment to empty the textbox when nothing (or just whitespace) has been entered, you could change the function to:
function search_csv {
$searchThis = $textbox_Search.Text.Trim()
# use $script: scoping here to reference the $csvData variable
$data = $script:csvData | Where-Object {$_.Location -like "*$searchThis*"}
if ([string]::IsNullOrWhiteSpace($searchThis)) {
$output_TextBox.Clear()
}
elseif ($data) {
$output_TextBox.Text = ($data | Format-List | Out-String).Trim()
}
else {
$output_TextBox.Text = "Not found.."
}
}
However, as postanote already commented, it would be much better to simply disable the search button and only enable it when something other that whitespace has been entered.
To do that, you need to add an eventhandler to the textbox:
$textbox_Search = New-Object System.Windows.Forms.TextBox
$textbox_Search.Location = New-Object System.Drawing.Size(195,50)
$textbox_Search.Size = New-Object System.Drawing.Size(266,37)
$textbox_Search.Add_TextChanged({
# enable the button when there is at least one non-whitespace character present
$button_Search.Enabled = $this.Text -match '\S'
# or use
# $button_Search.Enabled = (-not [string]::IsNullOrWhiteSpace($this.Text))
})
$search_csvtool.Controls.Add($textbox_Search)
And initialize the button to be disabled at startup:
$button_Search = New-Object System.Windows.Forms.Button
$button_Search.Location = New-Object System.Drawing.Size(195,80)
$button_Search.Size = New-Object System.Drawing.Size(266,24)
$button_Search.TextAlign = "MiddleCenter"
$button_Search.Text = "Search"
# initialize to Disabled; will be enabled as soon as there is text entered in the $textbox_Search
$button_Search.Enabled = $false
$button_Search.Add_Click({search_csv})
$search_csvtool.Controls.Add($button_Search)
Inside an event handler, you can refer to the object itself using automatic variable $this
You should be able to go thru your string output line by line and change this.
That stated, you probably won't like how it looks. Normalized colons will probably look better.
This code should do the trick. I'll let you be the judge of if it looks "better"
$dataLines = ($data | Format-List | Out-String).Trim() -split '(?>\r\n|\n)'
$dataText = #(
foreach ($dataLine in $dataLines) {
$dataLine -replace '\s{1,}\:', ':'
}
) -join [Environment]::Newline
$output_TextBox.Text = $dataText

PowerShell: How do I get information selected in a combo box to be used as a variable later on in?

I am trying to create a script to aid my helpdesk team when creating an AD Account.
So far I am able to create a user account with a few attributes, however I am trying to make the script capable of filling all the required details out.
What I would like to do is have a set list of locations and once a location is selected the script will use the variable $UserLocation in a range of functions, for now I just want the text returned ie; a user selects 'Location1' the variable $UserLocation returns the value 'Location1'. However at the moment it doesn't seem to work, I realise this is a really silly question but I can't figure it out for the life of me.
The area that has the issue is ##GetUserLocation The end result is to user $UserLocation to return the text selected in the combo box.
The Code I have so far is:
$primaryTelexNumber = "1"
$telexNumber = "7"
##Get Users First Name
[string] [Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
$title = "AD New User Script: First Name"
$msg = "Please Enter the new User's First Name"
$FirstName = [Microsoft.VisualBasic.Interaction]::InputBox($msg, $title)
##Get Users Last Name
[string] [Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
$title = "AD New User Script: Last Name"
$msg = "Please Enter the new User's Last Name"
$LastName = [Microsoft.VisualBasic.Interaction]::InputBox($msg, $title)
##Define UserName - not wokring yet hense manual capture
#$UserName = "$LastName($FirstName.SubString(0,1))"
##Get UserName
[string] [Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
$title = "AD New User Script: User Name"
$msg = "Please Enter the proposed User Name"
$UserName = [Microsoft.VisualBasic.Interaction]::InputBox($msg, $title)
##Set UserPassowrd
[string] [Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
$title = "AD New User Script: Password"
$msg = "Please Enter initial Password"
$Password = [Microsoft.VisualBasic.Interaction]::InputBox($msg, $title)
##GetUserLocation
function Show-DropDownSelector_psf {
#----------------------------------------------
#region Import the Assemblies
#----------------------------------------------
[void][reflection.assembly]::Load('System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
[void][reflection.assembly]::Load('System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
#endregion Import Assemblies
#----------------------------------------------
#region Generated Form Objects
#----------------------------------------------
[System.Windows.Forms.Application]::EnableVisualStyles()
$formADNewUserScriptSetUs = New-Object 'System.Windows.Forms.Form'
$buttonCancel = New-Object 'System.Windows.Forms.Button'
$buttonOK = New-Object 'System.Windows.Forms.Button'
$labelSelectUserLocation = New-Object 'System.Windows.Forms.Label'
$combobox1 = New-Object 'System.Windows.Forms.ComboBox'
$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
#endregion Generated Form Objects
#----------------------------------------------
# User Generated Script
#----------------------------------------------
$formADNewUserScriptSetUs_Load={
#TODO: Initialize Form Controls here
}
#region Control Helper Functions
function Update-ComboBox
{
<#
.SYNOPSIS
This functions helps you load items into a ComboBox.
.DESCRIPTION
Use this function to dynamically load items into the ComboBox control.
.PARAMETER ComboBox
The ComboBox control you want to add items to.
.PARAMETER Items
The object or objects you wish to load into the ComboBox's Items collection.
.PARAMETER DisplayMember
Indicates the property to display for the items in this control.
.PARAMETER ValueMember
Indicates the property to use for the value of the control.
.PARAMETER Append
Adds the item(s) to the ComboBox without clearing the Items collection.
.EXAMPLE
Update-ComboBox $combobox1 "Red", "White", "Blue"
.EXAMPLE
Update-ComboBox $combobox1 "Red" -Append
Update-ComboBox $combobox1 "White" -Append
Update-ComboBox $combobox1 "Blue" -Append
.EXAMPLE
Update-ComboBox $combobox1 (Get-Process) "ProcessName"
.NOTES
Additional information about the function.
#>
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNull()]
[System.Windows.Forms.ComboBox]
$ComboBox,
[Parameter(Mandatory = $true)]
[ValidateNotNull()]
$Items,
[Parameter(Mandatory = $false)]
[string]$DisplayMember,
[Parameter(Mandatory = $false)]
[string]$ValueMember,
[switch]
$Append
)
if (-not $Append)
{
$ComboBox.Items.Clear()
}
if ($Items -is [Object[]])
{
$ComboBox.Items.AddRange($Items)
}
elseif ($Items -is [System.Collections.IEnumerable])
{
$ComboBox.BeginUpdate()
foreach ($obj in $Items)
{
$ComboBox.Items.Add($obj)
}
$ComboBox.EndUpdate()
}
else
{
$ComboBox.Items.Add($Items)
}
if ($DisplayMember)
{
$ComboBox.DisplayMember = $DisplayMember
}
if ($ValueMember)
{
$ComboBox.ValueMember = $ValueMember
}
}
#endregion
$combobox1_SelectedIndexChanged={
#TODO: Place custom script here
}
$buttonOK_Click={
#TODO: Place custom script here
$combobox1.add_SelectedIndexChanged({ $UserLocation = $combobox1.SelectedItem })
}
# --End User Generated Script--
#----------------------------------------------
#region Generated Events
#----------------------------------------------
$Form_StateCorrection_Load=
{
#Correct the initial state of the form to prevent the .Net maximized form issue
$formADNewUserScriptSetUs.WindowState = $InitialFormWindowState
}
$Form_Cleanup_FormClosed=
{
#Remove all event handlers from the controls
try
{
$buttonOK.remove_Click($buttonOK_Click)
$combobox1.remove_SelectedIndexChanged($combobox1_SelectedIndexChanged)
$formADNewUserScriptSetUs.remove_Load($formADNewUserScriptSetUs_Load)
$formADNewUserScriptSetUs.remove_Load($Form_StateCorrection_Load)
$formADNewUserScriptSetUs.remove_FormClosed($Form_Cleanup_FormClosed)
}
catch { Out-Null <# Prevent PSScriptAnalyzer warning #> }
}
#endregion Generated Events
#----------------------------------------------
#region Generated Form Code
#----------------------------------------------
$formADNewUserScriptSetUs.SuspendLayout()
#
# formADNewUserScriptSetUs
#
$formADNewUserScriptSetUs.Controls.Add($buttonCancel)
$formADNewUserScriptSetUs.Controls.Add($buttonOK)
$formADNewUserScriptSetUs.Controls.Add($labelSelectUserLocation)
$formADNewUserScriptSetUs.Controls.Add($combobox1)
$formADNewUserScriptSetUs.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$formADNewUserScriptSetUs.AutoScaleMode = 'Font'
$formADNewUserScriptSetUs.ClientSize = New-Object System.Drawing.Size(371, 123)
$formADNewUserScriptSetUs.Name = 'formADNewUserScriptSetUs'
$formADNewUserScriptSetUs.Text = 'AD New User Script: Set User Location'
$formADNewUserScriptSetUs.add_Load($formADNewUserScriptSetUs_Load)
#
# buttonCancel
#
$buttonCancel.Location = New-Object System.Drawing.Point(231, 86)
$buttonCancel.Name = 'buttonCancel'
$buttonCancel.Size = New-Object System.Drawing.Size(75, 23)
$buttonCancel.TabIndex = 3
$buttonCancel.Text = 'Cancel'
$buttonCancel.UseVisualStyleBackColor = $True
#
# buttonOK
#
$buttonOK.Location = New-Object System.Drawing.Point(137, 86)
$buttonOK.Name = 'buttonOK'
$buttonOK.Size = New-Object System.Drawing.Size(75, 23)
$buttonOK.TabIndex = 2
$buttonOK.Text = 'OK'
$buttonOK.UseVisualStyleBackColor = $True
$buttonOK.add_Click($buttonOK_Click)
#
# labelSelectUserLocation
#
$labelSelectUserLocation.AutoSize = $True
$labelSelectUserLocation.Location = New-Object System.Drawing.Point(25, 45)
$labelSelectUserLocation.Name = 'labelSelectUserLocation'
$labelSelectUserLocation.Size = New-Object System.Drawing.Size(106, 13)
$labelSelectUserLocation.TabIndex = 1
$labelSelectUserLocation.Text = 'Select User Location'
#
# combobox1
#
$combobox1.FormattingEnabled = $True
[void]$combobox1.Items.Add('Location1')
[void]$combobox1.Items.Add('Location2')
[void]$combobox1.Items.Add('Location3')
[void]$combobox1.Items.Add('Location4')
[void]$combobox1.Items.Add('Location5')
[void]$combobox1.Items.Add('Location6')
[void]$combobox1.Items.Add('Location7')
[void]$combobox1.Items.Add('Location8')
[void]$combobox1.Items.Add('Location9')
[void]$combobox1.Items.Add('Location10')
[void]$combobox1.Items.Add('Location11')
[void]$combobox1.Items.Add('Location12')
$combobox1.Location = New-Object System.Drawing.Point(137, 42)
$combobox1.Name = 'combobox1'
$combobox1.Size = New-Object System.Drawing.Size(199, 21)
$combobox1.TabIndex = 0
$combobox1.add_SelectedIndexChanged($combobox1_SelectedIndexChanged)
$formADNewUserScriptSetUs.ResumeLayout()
#endregion Generated Form Code
#----------------------------------------------
#Save the initial state of the form
$InitialFormWindowState = $formADNewUserScriptSetUs.WindowState
#Init the OnLoad event to correct the initial state of the form
$formADNewUserScriptSetUs.add_Load($Form_StateCorrection_Load)
#Clean up the control events
$formADNewUserScriptSetUs.add_FormClosed($Form_Cleanup_FormClosed)
#Show the Form
return $formADNewUserScriptSetUs.ShowDialog()
} #End Function
#Call the form
Show-DropDownSelector_psf | Out-Null
##Get E-Mail
[string] [Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
$title = "AD New User Script: E-mail"
$msg = "Please Enter the user's E-mail Address"
$Email = [Microsoft.VisualBasic.Interaction]::InputBox($msg, $title)
##Get JobTitle
[string] [Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
$title = "AD New User Script: Job Title"
$msg = "Please Enter the user's job title"
$JobTitle = [Microsoft.VisualBasic.Interaction]::InputBox($msg, $title)
##Get Department
[string] [Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
$title = "AD New User Script: Department"
$msg = "Please Enter the user's Department"
$Department = [Microsoft.VisualBasic.Interaction]::InputBox($msg, $title)
##Get DeskPhoneNumber
[string] [Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
$title = "AD New User Script: Desk Phone Extension"
$msg = "Please Enter the user's Desk Phone Extension"
$DeskPhone = [Microsoft.VisualBasic.Interaction]::InputBox($msg, $title)
##Confirm Account Details
[System.Windows.Forms.MessageBox]::show("Verify the followning is correct:
User Name: $UserName
Password: $Password
Full Name: $FirstName $LastName
Job Title: $JobTitle
Department: $Department
Desk Phone Ext: $DeskPhone
Email Address: $Email
Click OK to continue and Create the account. Press Cancel to stop the process.
" , "AD New User", 1)
##Create AD User Account
$NewUserAttributes = #{
'UserPrincipalName' = $UserName
'DisplayName' = "$LastName $FirstName"
'Name' = $UserName
'GivenName' = $FirstName
'Surname' = $LastName
'Title' = $JobTitle
'Department' = $Department
'Description' = $JobTitle
'EmailAddress' = $Email
'SamAccountName' = $UserName
'AccountPassword' = (ConvertTo-SecureString $Password -AsPlainText -Force)
'Enabled' = $True
'ChangePasswordAtLogon' = $True
'path' = "OU=Users,OU=TEST,OU=Site,DC=Dev,DC=Test,DC=Local"
}
New-ADUser #NewUserAttributes
##Set IP Phone
Set-ADUser $UserName -add #{ipPhone="$DeskPhone"}
Here is what I personally do. You have a few issues with scopes. I don't think it's a good idea to create your forms inside functions, it will be a nightmare to work with and you will also have a big problem with scopes.
Functions are meant to act as event listeners for your UI application (imo).
There is probably a better way for this, but I'm used to retrieving values using Set-Variable since the scope of Add_Click event is different than the current scope. Doing something like $locationResult = $combobox1.selectedItem doesn't work.
$formADNewUserScriptSetUs = New-Object 'System.Windows.Forms.Form'
$formADNewUserScriptSetUs.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$formADNewUserScriptSetUs.AutoScaleMode = 'Font'
$formADNewUserScriptSetUs.ClientSize = New-Object System.Drawing.Size(371, 123)
$combobox1 = New-Object 'System.Windows.Forms.ComboBox'
$combobox1.FormattingEnabled = $true
1..12|%{[void]$combobox1.Items.Add("Location $_")}
$combobox1.Location = New-Object System.Drawing.Point(137, 42)
$combobox1.Name = 'combobox1'
$combobox1.Size = New-Object System.Drawing.Size(199, 21)
$combobox1.TabIndex = 0
$buttonOK = New-Object 'System.Windows.Forms.Button'
$buttonOK.Location = New-Object System.Drawing.Point(137, 86)
$buttonOK.Name = 'buttonOK'
$buttonOK.Size = New-Object System.Drawing.Size(75, 23)
$buttonOK.TabIndex = 2
$buttonOK.Text = 'OK'
$buttonOK.UseVisualStyleBackColor = $True
$buttonOK.add_Click({
Write-Host $combobox1.selectedItem #Your answer here
# Use this
Set-Variable -Name locationResult -Value $combobox1.selectedItem -Force -Scope Script
# or this to retrieve the user selection
$script:locationResult = $combobox1.selectedItem
})
$formADNewUserScriptSetUs.Controls.Add($buttonOK)
$formADNewUserScriptSetUs.Controls.Add($combobox1)
$formADNewUserScriptSetUs.ShowDialog()
Very nice UI, nicely done :)
Edit*
On closer review, you had code to set $combobox1.add_SelectedIndexChanged more than once, effectively removing the eventhandler I suggested in my previous answer. There was also a function that was in your code but not used at all, a ComboList helper. I trimmed your code down here and it now works fine.
Gist Link
Old Answer
Here's your issue. You are correctly setting up an event handler to trigger when a user changes the selected item in a combobox.
$buttonOK_Click={
#TODO: Place custom script here
$combobox1.add_SelectedIndexChanged({ $UserLocation = $combobox1.SelectedItem })
}
BUT, this event handler is only set up after the user clicks the OK button, which isn't what you want to do. Also, when the user hits the OK button, the UI should probably progress to the next UI element. So just change it like this:
#move this event handler OUTSIDE of the $buttonOK_Click handler.
$combobox1.add_SelectedIndexChanged({ $UserLocation = $combobox1.SelectedItem })
#when the user clicks OK, echo out to the screen their new selection (for debugging purposes)
#and then also close the UI, as the user would expect
$buttonOK_Click={
#TODO: Place custom script here
$formADNewUserScriptSetUs.Close();
write-host "user select location $($combobox1.SelectedItem )"
}
After testing this, the UI closes as expected, and also the $userLocation variable now held the value selected.

Use powershell to delete Sharepoint online list item

I currently have a powershell script to loop through a list on an Sharepoint online site.
$creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials("[USERNAME]", (ConvertTo-SecureString "[PASSWORD]" -AsPlainText -Force))
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext("https://[SITENAME].sharepoint.com/sites/Projekter")
$ctx.credentials = $creds
try{
$lists = $ctx.web.Lists
$list = $lists.GetByTitle("Ekstern synkronisering")
$listItems = $list.GetItems([Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery())
$ctx.load($listItems)
$ctx.executeQuery()
foreach($listItem in $listItems)
{
$internal = $listItem["ConnectionString1"]
$external = $listItem["ConnectionString2"]
$folder = $listItem["Mappe"]
$project = $listItem["Project"]
$caseNo = $listItem["Title"]
$doc = New-Object System.Xml.XmlDocument
$doc.Load("C:\Script\PS-Layer2\xmlTemplate.xml")
$ns = New-Object System.Xml.XmlNamespaceManager($doc.NameTable)
$ns.AddNamespace("ns", $doc.DocumentElement.NamespaceURI)
$doc.SelectSingleNode("//ns:dataEntity[#name='Intern site']", $ns).connectionString = $internal+";Authentication=Office365;User Id=$userId;Password=$pwd;"
$doc.SelectSingleNode("//ns:dataEntity[#name='Externt site']", $ns).connectionString = $external+";Authentication=Office365;User Id=$userId;Password=$pwd;"
$doc.Save("C:\Temp\$caseNo - $project - $folder.xml")
}
}
catch{
write-host "$($_.Exception.Message)" -foregroundcolor red
}
This works fine to get the items and modify an XML file..
What I would like to do is, when the XML file has been created, it shall delete the listitem from the sharepoint site, so that it will not be created on the next run again.
Does anyone have a solution on that?
Best regards...

Opening a SSRS project using Powershell

I have a report that is copied to a number of different servers. It is imported manually and the data source properties are altered to match the current server's specs. I would like to be able to automate the process by enabling users to open a the SSRS report and dynamically alter it's shared data source properties through PowerShell. I hope you could help. You may see reference below.
The script would accept an input parameter for servername, username and password. Also, the save my password must be ticked.
I couldn't believe I managed to create a script for this. You may make use of the script below as future reference. Comments are available for each part and anything that needs to be altered has a "here" keyword , ex. Your_database_name_here .
Import-Module SqlPs
#Input parameter to get Server\Instancename of your Datasource
$Servername = Read-Host "Please enter your Servername"
$Instancename = Read-Host "Please enter your Instancename. For default instance please press enter"
Write-host ""
if ($Instancename -eq ""){
$ServerInstance = $Servername
}
Else {
$ServerInstance = $Servername +"\"+ $InstanceName
}
#Setting up SSRS Target URL. This is the location where your reports would be deployed.
if ($Instancename -eq ""){
$ReportServerUri = "http://$Servername/ReportServer//ReportService2010.asmx?wsdl"
$TargetURL = "http://$Servername/Reports"
}
Else {
$ReportServerUri = "http://$Servername/ReportServer_$Instancename//ReportService2010.asmx?wsdl"
$TargetURL = "http://$Servername/Reports_$Instancename"
}
$global:proxy = New-WebServiceProxy -Uri $ReportServerUri -UseDefaultCreden
#We would make use of SQL Server Authentication for the reports shared datasource so you need to supply a username and password.
Write-Host " SQL Server Authentication:"
$Username = Read-Host " Username"
$Password = Read-Host -AsSecureString "Password"
$type = $Proxy.GetType().Namespace
$datatype = ($type + '.Property')
$property =New-Object ($datatype);
$property.Name = “NewFolder”
$property.Value = “NewFolder”
$numproperties = 1
$properties = New-Object ($datatype + '[]')$numproperties
$properties[0] = $property;
$newFolder = $proxy.CreateFolder("Reports”, “/”, $properties);
$newFolder = $proxy.CreateFolder("Data Sources”, “/”, $properties);
$Children =$proxy.ListChildren("/",$false)
$DBname = 'Your_Database_Name_Here'
# Creating Datasource through powershell
Write-Host " Creating Datasource ..."
$Name = "Name_Your_Datasource_here"
$Parent = "/Data Sources"
$ConnectString = "data source=$Servername\$Instancename;initial catalog=$DBname"
$type = $Proxy.GetType().Namespace
$DSDdatatype = ($type + '.DataSourceDefinition')
$DSD = new-object ($DSDdatatype)
if($DSD -eq $null){
Write-Error Failed to create data source definition object
}
$CredentialDataType = ($type + '.CredentialRetrievalEnum')
$Cred = new-object ($CredentialDataType)
$CredEnum = ($CredentialDataType).Integrated
$Cred.value__=1
$DSD.CredentialRetrieval =$Cred
$DSD.ConnectString = $ConnectString
$DSD.Enabled = $true
$DSD.EnabledSpecified = $false
$DSD.Extension = "SQL"
$DSD.ImpersonateUserSpecified = $false
$DSD.Prompt = $null
$DSD.WindowsCredentials = $false
$DSD.UserName = $Username
$DSD.Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))
$newDSD = $proxy.CreateDataSource($Name,$Parent,$true,$DSD,$null)
#Deploying RLD files to Target URL
Write-Host " Deploying RDL files ..."
$stream = Get-Content 'D:\Your_RDL_path_here.rdl' -Encoding byte
$warnings =#();
$proxy.CreateCatalogItem("Report","Report_Name_here","/Reports",$true,$stream,$null,[ref]$warnings)
#Let's make use of the datasource we just created for your RDL files.
$Items = $global:proxy.listchildren("/Data Sources", $true)
foreach ($item in $items)
{
$DatasourceName = $item.Name
$DatasourcePath = $item.Path
}
$RDLS = $global:proxy.listchildren("/Reports", $true)
foreach ($rdl in $rdls)
{
$report = $rdl.path
$rep = $global:proxy.GetItemDataSources($report)
$rep | ForEach-Object {
$proxyNamespace = $_.GetType().Namespace
$constDatasource = New-Object ("$proxyNamespace.DataSource")
$constDatasource.Name = $DataSourceName
$constDatasource.Item = New-Object ("$proxyNamespace.DataSourceReference")
$constDatasource.Item.Reference = $DataSourcePath
$_.item = $constDatasource.Item
$global:proxy.SetItemDataSources($report, $_)
Write-Host "Changing datasource `"$($_.Name)`" to $($_.Item.Reference)"
}
}
#Open a IE browser to view the report.
$IE=new-object -com internetexplorer.application
$IE.navigate2($TargetURL)
$IE.visible=$true
Write-Host ""
Write-Host "You may now view the Reports through the open IE browser."
Write-Host -ForegroundColor Green "**STEP COMPLETED!"

Append from the last row on-wards Excel & Powershell

I am currently working on a script that would keep track of the size of databases across different network servers. I am outputting the results to an excel, this will run every day, hence, I need to know how I can get the last row which contains data and append from there on-wards.
#Creates heading on an excel file if the file did not exist previously
Function CreateExcelWithHeadings($intRow, $Sheet)
{
$intRow++
#Create column headers
$Sheet.Cells.Item($intRow,1)= "Date"
$Sheet.Cells.Item($intRow,1).Font.Size = 12
$Sheet.Cells.Item($intRow,1).Font.Bold = $True
$Sheet.Cells.Item($intRow,2) = "Server"
$Sheet.Cells.Item($intRow,2).Font.Size = 12
$Sheet.Cells.Item($intRow,2).Font.Bold = $True
#$intRow++
$Sheet.Cells.Item($intRow,3) = "Database"
$Sheet.Cells.Item($intRow,3).Font.Bold = $True
$Sheet.Cells.Item($intRow,4) = "Data Name"
$Sheet.Cells.Item($intRow,4).Font.Bold = $True
$Sheet.Cells.Item($intRow,5) = "Data File"
$Sheet.Cells.Item($intRow,5).Font.Bold = $True
$sheet.Cells.Item($intRow,6) = "Data Size (MB)"
$Sheet.Cells.Item($intRow,6).Font.Bold = $True
$Sheet.Cells.Item($intRow,7) = "Data Used Space (MB)"
$Sheet.Cells.Item($intRow,7).Font.Bold = $True
$Sheet.Cells.Item($intRow,8) = "Log Name"
$Sheet.Cells.Item($intRow,8).Font.Bold = $True
$Sheet.Cells.Item($intRow,9) = "Log Size (MB)"
$Sheet.Cells.Item($intRow,9).Font.Bold = $True
$Sheet.Cells.Item($intRow,10) = "Log Used Space (MB)"
$Sheet.Cells.Item($intRow,10).Font.Bold = $True
$Sheet.Cells.Item($intRow,11) = "Log File"
$Sheet.Cells.Item($intRow,11).Font.Bold = $True
}
# initalize variables
$serverList = "C:\Database Monitor\sqlservers.txt"
$filepath ='C:\Database Monitor\Log Files\'
$filename = 'database_logging.xlsx'
#Create a new Excel object using COM
$Excel = New-Object -ComObject Excel.Application
# check if file path exists, if its doesn't create one with the proper headings
If (-not (Test-Path -path $filepath))
{
New-Item -ItemType directory -Path $filepath
$Excel.visible = $True
$Excel = $Excel.Workbooks.Add()
$Sheet = $Excel.Worksheets.Item(1)
CreateExcelWithheadings 0 $Sheet
$Sheet.SaveAs($filepath+$filename)
#WritetoExcel($serverList, 0)
}
Else
{
$Excel.visible = $True
$Excel = $Excel.Workbooks.Open($filepath)
$Sheet = $Excel.Worksheets.Item(1)
$ExcelWorkSheet.activate()
#$lastRow =
}