Powershell Office365 Employee Photo Upload Script

Hello,

I wrote a script for a resource group to use, but I think I'm doing something wrong... The script crashes Powershell when I try to exit the script from within the script... I've tried changing my "exit code" around a bit, and I have gotten "[environment]::Exit(0)" to work without crashing, except it will close the Powershell window I'm working on, and plus, I think there should be a more "elegant" way of doing this... But I haven't Powershell'ed in a while, so I'm not as "fresh" as I should be.

#########################################################################
# # This script was created by ************************** # #
# # for uploading user profile pictures to Office 365                 # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # Created on: 4/17/2015                                             # #
#########################################################################
$ErrorActionPreference = "Continue"
Function Connect-MSOL-Now() {
	Import-Module MSOnline
	$Credentials = Get-Credential
	$ExSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/?proxymethod=rps -Credential $Credentials -Authentication Basic -AllowRedirection
	Import-PSSession $ExSession -AllowClobber
	# Set-ExecutionPolicy RemoteSigned # Only needed on first run!
	Connect-MsolService -Credential $Credentials
}


# The Open-File Dialog
Function Get-FileName($initialDirectory) {   
	 [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
	 $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
	 $OpenFileDialog.initialDirectory = $initialDirectory
	 $OpenFileDialog.filter = "Uploadable Picture Files (*.jpg, *.gif, *.png)| *.jpg; *.gif; *.png"
	 $OpenFileDialog.Multiselect = $false
	 $OpenFileDialog.Title= "Select an employee headshot photo..."
	 $OpenFileDialog.ShowHelp = $true # Without this line, the dialog won't load - found info on StackOverflow
	 $OpenFileDialogExitStatus = $OpenFileDialog.ShowDialog()
	If ($OpenFileDialogExitStatus -eq "OK")
		{$OpenFileDialog.filename}
	Else
		{$OpenFileDialog.Close} #Write-Host -foregroundcolor RED -backgroundcolor WHITE "You pressed ""Cancel"" - an error will be produced, but this is OK"; 

} #end function Get-FileName


Function UploadPic() {
	[array]$DropDownArray = get-msoluser | where-object { $_.isLicensed -eq "TRUE" } | Sort-Object -Property UserPrincipalName | ForEach{ $_.UserPrincipalName }
	#This function returns whatever object is selected in the dropdown
	##to the command prompt.
	function Return-DropDown {
		If ($DropDown.SelectedItem -eq $null) {
			[System.Windows.Forms.MessageBox]::Show("You must select an employee or cancel!" , "ERROR!") 
		}
		Else {
			$script:User = $DropDown.SelectedItem.ToString()
			$Form.Close()
		}
	}

	[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
	[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 

	$Form = New-Object System.Windows.Forms.Form 
	$Form.Text = "Office365 Current Accounts"
	$Form.Size = New-Object System.Drawing.Size(500,150) 
	$Form.StartPosition = "CenterScreen"

	$Form.KeyPreview = $True
	$Form.Add_KeyDown({if ($_.KeyCode -eq "Enter") 
		{(Return-Dropdown);$Form.Close()}}) #$x=$DropDown.Text
	$Form.Add_KeyDown({if ($_.KeyCode -eq "Escape") 
		{$Form.Close()}})

	$SelectEmployee = New-Object System.Windows.Forms.Button
	$SelectEmployee.Location = New-Object System.Drawing.Size(300,70)
	$SelectEmployee.Size = New-Object System.Drawing.Size(130,23)
	$SelectEmployee.Text = "Select the Employee"
	$Form.AcceptButton = $SelectEmployee
	$SelectEmployee.Add_Click({Return-DropDown})
	$Form.Controls.Add($SelectEmployee)

	$CancelButton = New-Object System.Windows.Forms.Button
	$CancelButton.Location = New-Object System.Drawing.Size(50,70)
	$CancelButton.Size = New-Object System.Drawing.Size(130,23)
	$CancelButton.Text = "Exit Script"
	$CancelButton.Add_Click({DoYouWantToQuit})
	$Form.Controls.Add($CancelButton)
	$Form.CancelButton = $CancelButton
	
	$DropDown = new-object System.Windows.Forms.ComboBox
	$DropDown.Location = new-object System.Drawing.Size(200,10) # Sets the location of the dropdown
	$DropDown.Size = new-object System.Drawing.Size(230,30) # Sets the size of the dropdown
	ForEach ($Item in $DropDownArray) {
	 [void] $DropDown.Items.Add($Item)
	}
	$Form.Controls.Add($DropDown)

	$DropDownLabel = new-object System.Windows.Forms.Label
	$DropDownLabel.Location = new-object System.Drawing.Size(10,10) # Sets the location of the label
	$DropDownLabel.size = new-object System.Drawing.Size(150,50)  # Sets the size of the label
	$DropDownLabel.Text = "Please select the employee you would like to upload a photo for from the dropdown"
	$Form.Controls.Add($DropDownLabel)

	$Form.Topmost = $True

	$Form.Add_Shown({$Form.Activate()})
	[void] $Form.ShowDialog()

	$userphoto = Get-FileName -initialDirectory Previous
	
	If ($userphoto -eq $null)
		{
		TestConnection
		}
	Else
		{
		$CheckPhoto = Preview-Photo $userphoto
		If ($CheckPhoto -eq "Yes") {
			Set-UserPhoto -Identity $user -PictureData ([System.IO.File]::ReadAllBytes($userphoto)) -Confirm:$false
			TestConnection
			}
		Else {
		DoYouWantToQuit; }
		}
}

Function Preview-Photo($PhotoPath) {
	Add-Type -AssemblyName System.Windows.Forms
	$PhotoCheckForm = New-Object System.Windows.Forms.Form
	$PhotoCheckForm.Text = "Is this the right picture?"

	$Image = [System.Drawing.Image]::FromFile($PhotoPath)
	$PhotoCheckForm.BackgroundImage = $Image
	$PhotoCheckForm.BackgroundImageLayout = "Stretch"
	$PhotoCheckForm.Width = 800
	$PhotoCheckForm.Height = 800
	$PhotoCheckForm.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen

	$PhotoCheckFormFont = New-Object System.Drawing.Font("Times New Roman", 30)
	$PhotoCheckFormButtonFont = New-Object System.Drawing.Font("Segoe UI", 9)
	$PhotoCheckForm.Font = $PhotoCheckFormFont

	$PhotoCheckFormLabel = New-Object System.Windows.Forms.Label
	$PhotoCheckFormLabel.Text = "Is this the photo you meant to select (It will not show correctly in this window because it's stretched to fit, just check to see it's the right person)?"
	$PhotoCheckFormLabel.BackColor = "Transparent"
	$PhotoCheckFormLabel.ForeColor = "DarkGray"
	$PhotoCheckFormLabel.Width = 800
	$PhotoCheckFormLabel.Height = 400
	
	$PhotoCheckFormYesButton = New-Object System.Windows.Forms.Button
	$PhotoCheckFormYesButton.Location = New-Object System.Drawing.Size(10,700)
	$PhotoCheckFormYesButton.Size = New-Object System.Drawing.Size(100,60)
	$PhotoCheckFormYesButton.Font = $PhotoCheckFormButtonFont
	$PhotoCheckFormYesButton.Text = "Yes, this Photo is Correct"
	$PhotoCheckFormYesButton.DialogResult = [System.Windows.Forms.DialogResult]::YES
	$PhotoCheckForm.AcceptButton = $PhotoCheckFormYesButton

	$PhotoCheckFormNoButton = New-Object System.Windows.Forms.Button
	$PhotoCheckFormNoButton.Location = New-Object System.Drawing.Size(670,700)
	$PhotoCheckFormNoButton.Size = New-Object System.Drawing.Size(100,60)
	$PhotoCheckFormNoButton.Font = $PhotoCheckFormButtonFont
	$PhotoCheckFormNoButton.Text = "No, Not Correct!"
	$PhotoCheckFormNoButton.DialogResult = [System.Windows.Forms.DialogResult]::NO
	$PhotoCheckForm.CancelButton = $PhotoCheckFormNoButton
	
	$PhotoCheckForm.Controls.Add($PhotoCheckFormNoButton)	
	$PhotoCheckForm.Controls.Add($PhotoCheckFormYesButton)
	$PhotoCheckForm.Controls.Add($PhotoCheckFormLabel)
	$PhotoCheckForm.ShowDialog()
}

Function DoYouWantToQuit() {
	$ExitStatus = [System.Windows.Forms.MessageBox]::Show("Are you sure you want to exit?" , "Exit?" , 4)
	If ($ExitStatus -eq "YES")
		{Remove-PSSession -ID 1 ; [System.Windows.Forms.Application]::Exit($null); } #[environment]::Exit(0)
	Else
		{TestConnection}
}

Function TestConnection() {
	$TestExchOnline = get-command get-user
	If ($TestExchOnline -eq $null) {Connect-MSOL-Now; UploadPic}
	Else {UploadPic}
}

TestConnection

#Connect-MSOL-Now
#UploadPic

Open in new window


Any help or pointers would be greatly appreciated!
-Duane
LVL 1
jay_tullisAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

footechCommented:
I didn't see any crash in testing with both a PS console or PS ISE.  Unless I've missed something, if a user selects "yes, they want to quit", then you're at the end of the script so it can just close normally.  If there's more to the script that you haven't shown, you can just put an "exit" command to skip anything further.
0
jay_tullisAuthor Commented:
Hello footech,

Thank you so much for taking a look at this for me - I've been racking my head trying to figure out what's going on, and it's a relief to hear that it's actually working for someone else. :)

When it crashes for me, it seems to get stuck in some kind of loop - I think it has something to do with the way my functions are setup, and in particular how the UploadPic function is setup... I really don't like how the form and everything is created within that function, but I don't know another way to do it (or can't wrap my head around another way to do it without starting over from scratch)... This would be a LOT easier if I stayed "fresh" with PowerShell!

I can confirm the script DOES crash for at least 2 different users (myself and the resource group user) on two different computers.
What happens is someone clicks "Exit script" and it prompts them to make sure they want to exit. The user then clicks "Yes" and PowerShell almost immediately locks up (turn "hazy" like when applications lock up in Windows) and Windows says "This application has stopped responding..." - then the script continues to do some type of "loop" because I can see a faint image of the UploadPic function dialog box popping up then going away then popping up then going away. After about 5 or 6 times of it "looping", it eventually completely crashes and prompts me to "end task".

On top of this, somehow my PSSession to Office365 doesn't seem to get disconnected (though it could now as I added a line right before the "Exit" line that should disconnect the PSSession) because after three of these PowerShell crashes I have to wait a day before I can log back in to Office365 PSSessions (it says I already have 3 active sessions and it won't let me create another one, though all that happened was the other sessions crashed).

Lastly, I tried to work on this again today and had the resource group run the script and now, for some reason, I'm getting this error when the resource group person runs the script (but it still works just fine for me, so I don't know WHAT is going on here):
[outlook.office365.com] Connecting to remote server failed with the following e
rror message : [ClientAccessServer=BY2PR02CA0024,BackEndServer=blupr05mb1889.na
mprd05.prod.outlook.com,RequestId=230ac3c5-6d61-4d3a-bbb2-cdddafd623f0,TimeStam
p=4/28/2015 3:58:38 PM] Access Denied For more information, see the about_Remot
e_Troubleshooting Help topic.
    + CategoryInfo          : OpenError: (System.Manageme....RemoteRunspace:Re
   moteRunspace) [], PSRemotingTransportException
    + FullyQualifiedErrorId : PSSessionOpenFailed
Import-PSSession : Cannot validate argument on parameter 'Session'. The argumen
t is null. Supply a non-null argument and try the command again.
At L:\_IT\User Photo Upload Script Files\Office365 User Photo Upload Script.ps1
:12 char:18
+     Import-PSSession <<<<  $ExSession -AllowClobber
    + CategoryInfo          : InvalidData: (:) [Import-PSSession], ParameterBi
   ndingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Power
   Shell.Commands.ImportPSSessionCommand

Connect-MsolService : The user name or password is incorrect. Verify your user
name, and then type your password again.
At L:\_IT\User Photo Upload Script Files\Office365 User Photo Upload Script.ps1
:14 char:21
+     Connect-MsolService <<<<  -Credential $Credentials
    + CategoryInfo          : OperationStopped: (:) [Connect-MsolService], Mic
   rosoftOnlineException
    + FullyQualifiedErrorId : 0x80048821,Microsoft.Online.Administration.Autom
   ation.ConnectMsolService

Open in new window


Pretty strange, eh?

I'm going to have my Office365 Cloud Support team take a look at this one, but if anyone else has any ideas I would SO GREATLY APPRECIATE IT!!! I would even be willing to send a framed astrophoto that I took this past Sunday of the Hercules Cluster to you for helping! :)

http://cdn.astrobin.com/images/thumbs/946faa797fb8c9b8f3ae4299ef83c59b.1824x0_q100_watermark.jpg

Thanks,
-Duane
0
footechCommented:
Is everyone using the same PS version?  Are you sure they're entering the right credentials?
I'll try taking another look at it tomorrow.  To be fair, the testing I've done so far has been with a neutered version (so that it wouldn't actually connect to my Office 365).  I pretty much removed the TestConnection and Connect-MSOL-Now functions.  After loading the others, I ran the UploadPic function.
0
Simplify Active Directory Administration

Administration of Active Directory does not have to be hard.  Too often what should be a simple task is made more difficult than it needs to be.The solution?  Hyena from SystemTools Software.  With ease-of-use as well as powerful importing and bulk updating capabilities.

jay_tullisAuthor Commented:
Hi footech,

I think I might be on an older version on my testing machine, but I did a fresh install of the Azure (Office365/MicrosoftOnline) PS module on the resource group computer...

I figured out what the error was (my previous response)... Apparently, getting PowerShell + MicrosoftOnline to run via a double-click is a big pain in the........ Trying many new things now to make sure this person is able to double-click the script file and have it work... Hope to have a solution back here shortly.

Lastly, I think changing the exit code around a little bit helped my script start exiting cleanly. I'll post the final version here when I'm done.
-Duane
0
footechCommented:
I can confirm that I've now observed the behavior you describe.  I was looking at the Preview-Photo function before where I didn't see any problem.  Now I realize that the problem occurs in conjunction with the UploadPic function.  I don't work with forms and PowerShell (besides a few tests I've done), so I can't say exactly why you're seeing the problem.  What I would probably do is set a global variable within the DoYouWantToQuit function when Exit is clicked, and then back in the calling function (like around line 98), check the value of that variable to determine whether to continue processing any of the script.

Hope that's of some use to you.  I don't think I could do any better without diving into forms, which I just don't have the time for now.  Best of luck.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jay_tullisAuthor Commented:
Thank you, footech - glad to hear I'm not the only one having this issue now! I will look into re-writing my exit-code and that will probably fix the issue. For now, the resource group has used the script to upload all of our employee photos, so hopefully they won't need it for a while!
-Duane
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.