Powershell script - Remove-AppxPackage - powershell

I'm trying to build a powershell script to do 4 things:
Create a list with Get-AppxPackage and Output-File - works
Erase with Remove-AppxPackage - doesn't work
Display a list on the terminal - works
Quit the script - works
How do I put the second option running without problems?
Here's the code for the second option:
function Erase {
([string] $app) = Read-Host -Prompt "Insert the AppxPackage name."
cls
Write-Host $app
$appchoice = Read-Host -Prompt "Is this the correct name? Answer Y or N."
cls
If (($appchoice -eq 'Y') -or ($appchoice -eq 'y')) {
Get-AppxPackage "'$app'" | Remove-AppxPackage -AllUsers "'$app'"
Write-Host "The package $app was erased."
Read-Host -Prompt "Press enter to continue."
Menu
} Else {
Write-Host "Somehow we messed things up. Let's start again!"
Read-Host -Prompt "Press enter to continue."
Menu
}
}
The error is the image attached to this question. It doesn't even prompts the user for the name...
Thanks in advance.

Related

Ping and Install applications for multiple PCs

I hope someone can help me with the following script:
The script I built works for 1 computer. It asks the user to enter the computer name, and It will check if the computer is ONLINE, if it is it will copy and install the application.
Now, I want to add another functionality. I want users to create a TXT file with all the computer names (line by line) and save them somewhere in the computer. The user will run the script, and a Windows Explorer would open requesting the location of the TXT file. So, the script will collect that data (I might be wrong, but should I use arrays for that?) From there, I am assuming a ForEach statement should do it right?
The most difficult (for me) part is... if the computer is OFFLINE, it will skip that computer, and go for the next one... when it reaches the end of the lines, it should go back to the first line and check if the computer (that was offline) is online. The tricky part is... if the computer already has the app installed, it should skip it, and continue to keep pinging computers and so on. I want the script to run until someone manually stops it, installed the app to all the pcs, or runs for 3 days.
This might be too much to ask, but... it would also be nice to see a report of all the computers where the app was successfully installed (I am sure this should be on the ForEACH portion).
Thank you all
function HarvesterMenu {
$PCName = read-host -Prompt "Enter the computer name"
$PCName = $PCName -replace '(^\s+|\s+$)','' -replace '\s+',' '
$pingPC = Test-Connection -ComputerName $PCName -Quiet -Count 1 -ErrorAction SilentlyContinue
if ($pingPC -eq $True) {
Write-host "ONLINE"
harvesterInstall($PCName)
}
else {
Write-host "OFFLINE"
}
}
function HarvesterInstall($InstallOnPC) {
$Sourcefile = "\\SERVER1\discovery03$\HarvesterRemote.msi"
Copy-Item -Path $Sourcefile -Destination "\\$InstallOnPC\c$\windows\temp\HarvesterRemote.msi"
Invoke-Command -ComputerName $InstallOnPC -ScriptBlock {
Start-Process c:\windows\temp\HarvesterRemote.msi -ArgumentList "/quiet" -Wait
}
Start-Sleep 3
$InstCompleted = Test-Path -Path '\\$InstallOnPC\C$\Program Files (x86)\Labs\Harvester Remote\Harvester\Harvester.exe'
Write-Host $InstCompleted
if ($InstCompleted -eq $True) {
Write-host "Harvester was successfuly installed on $InstallOnPC"
}
else {
Write-host "Something went wrong. Ping the server and try again"
}
$BacktoMenu = read-host -Prompt "Press Y to go back to the Main Menu or N to exist"
if ($backtoMenu -eq "y") {
harvesterMenu
}
else {
Exit
}
}
HarvesterMenu
You can do that easily with a Foreach-Loop.
U need a File with the pc's u wanna install the application. maybe .txt or .csv
Then u can just address it in a foreach.
something like that:
$InputFile = 'C:\Temp\lIST.csv'
$addresses = get-content $InputFile
foreach($address in $addresses) {
if (test-Connection -ComputerName $address -Count 1 -Quiet ) {
write-Host "$address Online"
#ur harvesterinstall
}
else
{
Write-Warning "$address Offline"
}
}

Automating a boring task

The second half of my script does not function the way I want it to. I believe I am using the incorrect cmdlet. I am trying to add a group from active directory to the local administrator account on a laptop/pc. And after this add a domain user to the power user group.
I want to pull from AD the group name, which I thought this cmdlet would do so. Any ideas?
I only ran the second half but receive errors. I have tried other cmdlets but I think this one is the most accurate.
#change computer name of the device + condition
$answer = Read-Host -Prompt 'Do you want to change the computer name?'
# First condition - 1) name comupter 2) take user creds 3) Rename computer using stored cred 4) write host if yes is the answer
if ($answer -match "yes"){
$computername = Read-Host -Prompt "What will be the name of the computer?"
#This part of the script will contain your credentials to change the computername and priveledges
$cred = Get-Credential -Message "This will be used to changed the computername. Do not worry!"
#$cred = Read-Host -Prompt "Enter your network username" - Uneeded string
Rename-Computer -NewName "$computername" -LocalCredential $cred -DomainCredential $cred
Write-Host "Computername has been changed to $computername successfully!"
}
#Second condition - If answer is no move on to second portion of the script to set privledges
elseif($answer -match "no"){
Write-Host "Moving to the next part of the script"
}
#Third condition - If answer is anything else - loop to the beginning of the script to accept the right answer
else{
write-host "Please answer with yes or no"
}
#Second half of script
#Adding AD group to local adminitrator
$localuser= Read-Host "Enter username of the PowerUser."
Add-LocalGroupMember -Group "Administrator" -Member "memeber"
Add-LocalGroupMember -Group "Power Users" -Member $localuser + "tamu.jaguar.edu"

Trying to script profile deletion for remote workstations

I work in a large company and that is global and I would like to be able to run a script that will allow me to clean up old profile remotely. I found this script but it doesn't seem to do anything. Does anyone have thought to why. I am a novice in powershell so any help would be appreciated. Thanks in advance!
function Remove-ProfileWD {
<#
.SYNOPSIS
Interactive menu that allows a user to connect to a local or remote computer and remove a local profile.
.DESCRIPTION
Presents an interactive menu for user to first make a connection to a remote or local machine. After making connection to the machine,
the user is presented with all of the local profiles and then is asked to make a selection of which profile to delete. This is only valid
on Windows Vista OS and above for clients and Windows 2008 and above for server OS.
.EXAMPLE
Remove-ProfileWF
Description
-----------
Presents a text based menu for the user to interactively remove a local profile on local or remote machine.
#>
#Prompt for a computer to connect to
(
[Parameter(Mandatory=$true)]
$Computer = Read-Host "Please enter a computer name"
)
#Test network connection before making connection
If ($computer -ne $Env:Computername) {
If (!(Test-Connection -comp $computer -count 1 -quiet)) {
Write-Warning "$computer is not accessible, please try a different computer or verify it is powered on."
Break
}
}
Do {
#Gather all of the user profiles on computer
Try {
[array]$users = Get-WmiObject -ComputerName $computer Win32_UserProfile -filter "LocalPath Like 'C:\\Users\\%'" -ea stop
}
Catch {
Write-Warning "$($error[0]) "
Break
}
#Cache the number of users
$num_users = $users.count
Write-Host -ForegroundColor Green "User profiles on $($computer):"
Write-Host -ForegroundColor Green "User profile Last Use ate"
#Begin iterating through all of the accounts to display
For ($i=0;$i -lt $num_users; $i++) {
Write-Host -ForegroundColor Green "$($i): $(($users[$i].localpath).replace('C:\Users\','')) $(get-item \\$computer\C`$\users\$(($users[$i].localpath).replace('C:\Users\',''))| Foreach {$_.LastWriteTime}) "
}
Write-Host -ForegroundColor Green "q: Quit"
#Prompt for user to select a profile to remove from computer
Do {
$account = Read-Host "Select a number to delete local profile or 'q' to quit"
#Find out if user selected to quit, otherwise answer is an integer
If ($account -NotLike "q*") {
$account = $account -as [int]
}
}
#Ensure that the selection is a number and within the valid range
Until (($account -lt $num_users -AND $account -match "\d") -OR $account -Like "q*")
If ($account -Like "q*") {
Break
}
Write-Host -ForegroundColor Yellow "Deleting profile: $(($users[$account].localpath).replace('C:\Users\',''))"
#Remove the local profile
($users[$account]).Delete()
Write-Host -ForegroundColor Green "Profile: $(($users[$account].localpath).replace('C:\Users\','')) has been deleted"
#Configure yes choice
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes","Remove another profile."
#Configure no choice
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No","Quit profile removal"
#Determine Values for Choice
$choice = [System.Management.Automation.Host.ChoiceDescription[]] #($yes,$no)
#Determine Default Selection
[int]$default = 0
#Present choice option to user
$userchoice = $host.ui.PromptforChoice("","Remove Another Profile?",$choice,$default)
}
#If user selects No, then quit the script
Until ($userchoice -eq 1)
}

Using Read-host with Input validation and TRAP

I'm just a typical admin trying to make a simple script for some IT assistants in remote offices, to make domain joins easier while minimizing potential errors. The script's end game is to run the one-liner command Add-Computer -DomainName $DomainToJoin -OUPath $LocDN -NewName $WS_NewName -Restart.
But the whole script is supposed to include input validation for the computer's new name as well as for the target OU for the two-letter code for the remote office.
Googling for code snippets for days, esp. from sites like yours, was very helpful. But the problem I have now is I couldn't find the right codes to combine Read-Host , input length validation, and TRAP to work together without losing the value for my variables.
Pardon my coding as obviously I'm no real PS scripter, and I know the wrong portions of it are very basic. I would want to spend more time if I had the luxury, but I would really so much appreciate it if you could point me in the right direction.
Thank you so much in advance.
Please see my code below:
# START: Display name and purpose of invoked script
$path = $MyInvocation.MyCommand.Definition
Clear-Host
Write-Host $path
Write-Host " "
Write-Host "This script will allow you to do the following in a single-step process:"
Write-Host "(1) RENAME this computer"
Write-Host "(2) JOIN it to MYDOMAIN"
Write-Host "(3) MOVE it to a target OU"
Write-Host "(4) REBOOT"
Write-Host " "
Pause
# Function: PAUSE
Function Pause ($Message = "Press any key to continue . . . ") {
if ((Test-Path variable:psISE) -and $psISE) {
$Shell = New-Object -ComObject "WScript.Shell"
$Button = $Shell.Popup("Click OK to continue.", 0, "Script Paused", 0)
}
else {
Write-Host -NoNewline $Message
[void][System.Console]::ReadKey($true)
Write-Host
}
Write-Host " "
}
# Function: Define the parameters
Function Define-Parameters {
# Specify new computer name, with validation and TRAP
$WS_NewName = $null
while ($null -eq $WS_NewName) {
[ValidateLength(8,15)]$WS_NewName = [string](Read-Host -Prompt "NEW NAME of computer (8-15 chars.)" )
TRAP {"" ;continue}
}
Write-Host " "
# Domain to join.
$DomainToJoin = 'mydomain.net'
# Specify the target OU, with validation and trap
$baseOU='OU=Offices OU,DC=mydomain,DC=net'
$OU2 = $null
while ($null -eq $OU2) {
[ValidateLength(2,2)]$OU2 = [string](Read-Host -Prompt 'Target OU (TWO-LETTER code for your office)' )
TRAP {"" ;continue}
}
Write-Host " "
$LocDN = "OU=$OU2,$baseOU"
}
# Function: Summary and confirmation screen for defined parameters.
Function Confirm-Parameters {
Write-Host "==========================================================================="
Write-Host "Please confirm that you are joining this computer to
$DomainToJoin (MYDOMAIN)"
Write-Host "with the following parameters:"
Write-Host ""
Write-Host ""
Write-Host "Computer's NEW NAME: $WS_NewName"
# Write-Host "Domain to Join: $DomainToJoin"
Write-Host "TARGET mission OU: $OU2"
}
# Call Define-Parameters Function
Define-Parameters
# Call Confirm-Parameters Function
Confirm-Parameters
<#
Some more code here
#>
# FINAL COMMAND if all else works: Join the computer to the domain, rename it, and restart it.
# Add-Computer -DomainName $DomainToJoin -OUPath $LocDN -NewName $WS_NewName -Restart
In your code, you have a lot of things defined very strangely. Your functions create a new scope and the variables you're trying to define therein will disappear after calling them unless you change the variable scope (in this case, to $script: or $global:). Also, to use functions, you need to define them first (your Pause doesn't actually do anything)
Here's something you can do with your Define-Parameters function (I suggest looking at Get-Verb)
# Domain to join.
$DomainToJoin = 'mydomain.net'
# Function: Define the parameters
Function Get-Parameters {
do {
$global:WS_NewName = Read-Host -Prompt 'NEW NAME of computer (8-15 chars)'
} until ($WS_NewName.Length -gt 7 -and $WS_NewName.Length -lt 16)
''
do {
$global:OU2 = Read-Host -Prompt 'Target OU (TWO-LETTER code for your office)'
} until ($OU2 -match '^[a-z]{2}$')
''
$OU2 = "OU=$global:OU2,OU=Offices OU,DC=mydomain,DC=net"
}
I'd strongly recommend moving away from the ISE to do your testing and test in an actual powershell console.
Perhaps Try/Catch block instead of trap?
Try {
[ValidatePattern('^\w{8,15}$')]$compname=read-host 'enter comp name' -ErrorAction Stop
[ValidatePattern('^\w{2}$')]$OU=read-host 'enter OU name' -ErrorAction Stop
}
Catch {
$ErrorMessage = $_.Exception.Message
$ErrorLineNumber = $_.InvocationInfo.ScriptLineNumber
$ErrorCommandName = $_.InvocationInfo.InvocationName
Write-Error -Message "The error message was: <$ErrorMessage>, script line: <$ErrorLineNumber>, command name: <$ErrorCommandName>"
exit 255
}

Exiting from a powershell menu

I've created a powershell menu script but occasionally I don't want to use the menu function I have created I want to come out and run a custom command, or even better add a menu feature which allows me to write a custom command.
Can anyone help me achieve this please?
write-host "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
write-host "Exchange Online Management"
write-host
write-host "Press 1: To assign Full Access To A Mailbox"
write-host "Press 2: Get Mailbox Size"
write-host "Press 3: Custom Exchange Command"
write-host "Press Q: To Leave Exchange Management"
write-host
write-host
write-host "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
$SM2 = Read-Host "Please Make A Selection"
Switch ($SM2) {
'1'{
DO something
}
'2' {
$Mailboxuser = read-host "Who's Mailbox are you trying to query?"
Get-MailboxStatistics $Mailboxuser | ft DisplayName, TotalItemSize, ItemCount
}
'3' {
return
}
'Q' {
Remove-PSSession $Session
return
}
}
}
until ($SM -eq 'Q')
The PowerShell console window is closing after it has finished executing your script.
You can get around this by running another powershell process with your script:
'Q' {
Remove-PSSession $Session
& powershell
}
The other option is to create a shortcut to your script and add the -NoExit switch, which stops the window from closing when the script is finished.
PowerShell -NoExit "C:\folder\script.ps1"