I'm working on a script that gets executed only if X account is found, but is not working as intended the if/else statements get bypassed and the code gets executed anyways. What am i doing wrong?
$Account = "XXXX"
Get-LocalUser -name $Account
if (($Account) -eq $true) {
} else {
Write-host -foreground cyan "I found it"
}
exit
If i ran the script as is it will output the text on the console even tho "XXX" account is not present, could something like that can be done?
This should do it:
$Account = "XXXX"
$AccountObject=Get-LocalUser -name $Account -ErrorAction SilentlyContinue
if (($AccountObject)) {
Write-host -foreground cyan "I found it"
} else {
Write-host -foreground cyan "No luck"
}
The issue with the sniplet provided - the return of Get-LocalUser was not used. Instead you were using a string value which is always set therefore true - as you set it to 'XXXX' in your first line.
As Bill_Stewart explains, the reason that the else block is reached is because ($Account) -eq $true evaluates to $false unless the account name is "true".
In order to test whether Get-LocalUser succeeded or failed to retrieve the user account, you can instead inspect the $? automatic variable - it will have a value of $false only if the previous command threw an error:
$AccountName = "nonExistingUser"
# Try to fetch existing user account, don't show any errors to the user
$UserAccount = Get-LocalUser -Name $AccountName -ErrorAction SilentlyContinue
# Test if the call was successful
if($?) {
Write-Host "Found account named '$AccountName'!" -ForegroundColor Cyan
$UserAccount
} else {
Write-Host "No account named '$AccountName' was found ..." -ForegroundColor Magenta
}
Related
Hey Everyone so I am able to set the sharepoint sites sensitivity labels in my tenant by doing them individually using the following commands:
# Get the label (required ExchangeOnlineManagement module)
Connect-IPPSSession -userprincipalname wise#redacted
$c = Get-Credential wise#redacted
Connect-SPOService -Url https://redacted-admin.sharepoint.com -Credential $c -ModernAuth:$true -AuthenticationUrl https://login.microsoftonline.com/organizations
Set-SPOSite -identity {site_url} -SensitivityLabel:'{GUID of sens label here}'
And now I am trying to set a default label for all sites that have not been manually set by users with the following code, but its throwing the "Site already has a sensitivity label" message, meaning the if statement isnt triggering when ran from a site in a variable???
# Get the label (required ExchangeOnlineManagement module)
Connect-IPPSSession -userprincipalname wise#redacted
$c = Get-Credential wise#redacted
Connect-SPOService -Url https://redacted-admin.sharepoint.com -Credential $c -ModernAuth:$true -AuthenticationUrl https://login.microsoftonline.com/organizations
#Create a progress counter and fail counter
$count = 0
$fail = 0
#get all sites
write-host "Collecting site data" -ForegroundColor Yellow
$SiteCollections = Get-SPOSite -Limit All
write-host "Collecting site data - COMPLETED" -ForegroundColor Green
#get a count of total sites
$total = $SiteCollections.count
write-host "There are $total total sites." -ForegroundColor Green
foreach ($site in $SiteCollections){
$count++
try{
if ( $site.SensitivityLabel -eq '' ){
Set-SPOSite $site -SensitivityLabel:'{GUID}'
} else {
$label = $site.SensitivityLabel
Write-host "Site already has a sensitivity label: $label"
$site.Url | Out-File '.\Sites_already_labeled.txt' -Append
}
} catch {
$sitename = $site.Name
"Bad site: $sitename" | Out-File '.\Failed_change_sites.txt' -Append
$fail++
Write-Host "Failed site count = $fail" -ForegroundColor Blue
Write-Host "Failed site = $sitename" -ForegroundColor Blue
}
Write-Host "Processing Site $count of $total" -ForegroundColor Red
}
I have tested the if sens label = '' on singular sites and it does infact fufill the if statement so im completely lost.
Thanks ChatGPT!
It's likely that the issue is with the following line of code: if ( $site.SensitivityLabel -eq '' ). The SensitivityLabel property of a SharePoint Online site may not be an empty string when it has no label applied to it. Instead, it may be $null, so the if statement should be updated to if ( $site.SensitivityLabel -eq $null ).
I am attempting to make a script that will check a variety of settings and ask permission before changing them. I'm writing this for non-IT users, so each of the user checks is a pop out message box. I thought that this part of the code was working, but now not so much. I'm getting an error indicating the user wasn't found, but that's what I'm trying to use as an if-else trigger. Error Message
As always, thanks to all the saints out there saving my behind from this.
PS: I know its not overly secure to have the password hard coded into the script, and if it were up to me, we wouldn't do it this way. But this is how the boss wants it for now.
#User Group
If (Get-LocalGroup -Name "Koko Svc"){
Write-Host "User Group Koko Svc already exists"
}
Else{
$UserConfirm=[System.Windows.Forms.MessageBox]::Show("Would you like to create the Local Group `"Koko Svc`"?","`"Koko Svc`" Group Not Found",[System.Windows.Forms.MessageBoxButtons]::YesNoCancel)
switch ($UserConfirm){
"Yes" {
write-host "User agreed to create `"Koko Svc`""
New-LocalGroup -Name 'Koko Svc' -Description 'KoKo Svc'
}
"No" {
write-host "User declined to create `"Koko Svc`""
break
}
"Cancel" {
write-host "User stopped Settings Check"
exit
}
}
}
#Users
If (Get-LocalUser -Name "KoKo Svc"){
Write-Host "User Koko Svc already exists"
}
Else{
$UserConfirm=[System.Windows.Forms.MessageBox]::Show("Would you like to create the User `"Koko Svc`"?","`"Koko Svc`" User Not Found",[System.Windows.Forms.MessageBoxButtons]::YesNoCancel)
switch ($UserConfirm){
"Yes" {
write-host "User agreed to create `"Koko Svc`""
$Password1 = ConvertTo-SecureString "FooBar" -AsPlainText -Force
New-LocalUser "KoKo Svc" -Password $Password1 -FullName "KoKo Svc"
Add-LocalGroupMember -Group 'Administrators' -Member ('KoKo Svc','Administrators')
Add-LocalGroupMember -Group 'Koko Svc' -Member ('KoKo Svc','KoKo Svc')
}
"No" {
write-host "User declined to create `"Koko Svc`""
break
}
"Cancel" {
write-host "User stopped Settings Check"
exit
}
}
}
If (Get-LocalUser -Name "Valued Customer"){
Write-Host "User Valued Customer already exists"
}
Else{
$UserConfirm=[System.Windows.Forms.MessageBox]::Show("Would you like to create the User `"Valued Customer`"?","`"Valued Customer`" User Not Found",[System.Windows.Forms.MessageBoxButtons]::YesNoCancel)
switch ($UserConfirm){
"Yes" {
write-host "User agreed to create `"Valued Customer`""
$Password2 = ConvertTo-SecureString "BarFoo" -AsPlainText -Force
New-LocalUser "Valued Customer" -Password $Password2 -FullName "Valued Customer"
Add-LocalGroupMember -Group 'Administrators' -Member ('Valued Customer','Administrators')
Add-LocalGroupMember -Group 'Koko Svc' -Member ('Valued Customer','KoKo Svc')
}
"No" {
write-host "User declined to create `"Valued Customer`""
break
}
"Cancel" {
write-host "User stopped Settings Check"
exit
}
}
}
You could change it to
If (Get-LocalUser -Name "Valued Customer" -ErrorAction SilentlyContinue){
Write-Host User Valued Customer already exists
}
Else{
write-host available
}
That way only if it produces an output it will run the if portion.
A few things.
You can't use the same name for both a group and a user, which is why you get the error
The name KoKo Svc is already in use
On commands that you expect to fail, and want to take action if it does, use try/catch blocks. You can go the -ErrorAction SilentlyContinue route, but in my opinion, that's sloppy and inelegant. You'll just be ignoring the error, instead of taking action on it. I would do something like this
try
{
Get-LocalUser -Name $Name -ErrorAction Stop
$exists = $true
Write-Host "User $Name already exists"
}
catch [Microsoft.PowerShell.Commands.UserNotFoundException]
{
$exists = $false
}
then DRY the code up by tossing it in a simple function or two, so I'm not copy pasting a big chunk every time
function Test-LocalUser([string]$Name)
{
try
{
Get-LocalUser -Name $Name -ErrorAction Stop
$exists = $true
Write-Host "User $Name already exists"
}
catch [Microsoft.PowerShell.Commands.UserNotFoundException]
{
$exists = $false
}
return $exists
}
function Test-LocalGroup([string]$Name)
{
try
{
Get-LocalGroup -Name $Name -ErrorAction Stop
$exists = $true
Write-Host "Group $Name already exists"
}
catch [Microsoft.PowerShell.Commands.GroupNotFoundException]
{
$exists = $false
}
return $exists
}
Then for your code, you can do something like this
$group = "Koko Svc group"
if(!(Test-LocalGroup -Name $group))
{
$UserConfirm=[System.Windows.Forms.MessageBox]::Show("Would you like to create the Local Group `"$group`"?","`"$group`" Group Not Found",[System.Windows.Forms.MessageBoxButtons]::YesNoCancel)
switch ($UserConfirm)
{
"Yes"
{
write-host "User agreed to create `"$group`""
New-LocalGroup -Name $group -Description $group
}
"No"
{
write-host "User declined to create `"$group`""
break
}
"Cancel"
{
write-host "User stopped Settings Check"
exit
}
}
}
#Users
$user = "Koko Svc user"
if(!(Test-LocalUser -Name "Koko Svc"))
{
$UserConfirm=[System.Windows.Forms.MessageBox]::Show("Would you like to create the User `"$user`"?","`"$user`" User Not Found",[System.Windows.Forms.MessageBoxButtons]::YesNoCancel)
switch ($UserConfirm)
{
"Yes"
{
write-host "User agreed to create `"$user`""
$Password1 = ConvertTo-SecureString "FooBarasdasdasdasdadad2334342342!!!" -AsPlainText -Force
New-LocalUser "$user" -Password $Password1 -FullName "$user"
Add-LocalGroupMember -Group 'Administrators' -Member ($user,'Administrators')
Add-LocalGroupMember -Group $group -Member ($user,$group)
}
"No"
{
write-host "User declined to create `"$user`""
break
}
"Cancel"
{
write-host "User stopped Settings Check"
exit
}
}
}
I would also recommend tossing the user creation portion into a function as well, to reduce all the copy-paste code. If this is something designed for other people, making it easy to maintain is a priority. By making functions out of your repeated code, you only have to make a change in one place, rather than every copy/pasted section. If you want to see an example of the user creation portion in a function, lemme know and I'll toss it in an edit.
I have to delete users from my AD through Powershell. Powershell has to ask me who I want to delete, once I type in the username it should delete the account. Also when Powershell succesfully deleted the account or it should give me a message.
I'm kind of noob at this, but here is my code:
function aduser-remove($userremove){
Remove-ADUser -Identity $delete
if ($delete -eq $userremove){
return $true
}
else {
return $false
}
}
$delete = Read-host "Which user do you want to delete? (Type in username)."
aduser-remove $delete
if ($userremove -eq $true){
Write-Host $delete "deleted succesfully!" -ForegroundColor Green
}
elseif ($userremove -eq $false){
Write-Host "An error occured by deleting" $delete -ForegroundColor Red
}
else {
Write-Host $delete "does not exist." -ForegroundColor DarkGray
}
The result here is that Powershell does ask if I want to delete the account and it works. But Powershell keeps giving me the else message instead of the if message. Deleting the account was succesfull.
I have no idea what to now or if I'm missing something (I bet I am otherwise it would work).
I hope you guys can help me!
As commented, your code uses variables in places where they do not exist.
Also, I would recommend trying to find the user first and if you do, try and remove it inside a try/catch block, as Remove-ADUser creates no output.
Below a rewrite of your code. Please note that I have changed the name of the function to comply with the Verb-Noun naming convention in PowerShell.
function Remove-User ([string]$userremove) {
# test if we can find a user with that SamAccountName
$user = Get-ADUser -Filter "SamAccountName -eq '$userremove'" -ErrorAction SilentlyContinue
if ($user) {
try {
$user | Remove-ADUser -ErrorAction Stop -WhatIf
return $true
}
catch {
return $false
}
}
# if we get here, the user does not exist; returns $null
}
$delete = Read-host "Which user do you want to delete? (Type in username)."
# call your function and capture the result
$result = Remove-User $delete
if ($result -eq $true){
Write-Host "User $delete deleted succesfully!" -ForegroundColor Green
}
elseif ($result -eq $false){
Write-Host "An error occured while deleting user $delete" -ForegroundColor Red
}
else {
Write-Host "$delete does not exist." -ForegroundColor DarkGray
}
Note also that I have put in the -WhatIf switch. This switch ensures you will only get a message of what would happen. No user is actually deleted. Once you are satisfied the code does what you want, remove the -WhatIf switch.
Hope that helps
If you have rsat installed https://www.microsoft.com/en-us/download/details.aspx?id=45520
remove-aduser https://learn.microsoft.com/en-us/powershell/module/addsadministration/remove-aduser?view=win10-ps
I am working on a validation script for a Domain Controller. I have an account that has 4 things that I need to verify. The code that I have works but I don't want it to break if one of the conditions aren't met and that is what it is doing now. So, basically I'm needing it to check all 4 criteria, regardless if the condition is met or not.
Here is my code:
if(net user "user.dadm") {
Write-Host "[√] User.dadm was created successfully" -fore GREEN
if((((uACADA "user.dadm") -band 65536) -ne 0) -eq $true) {
Write-Host "[√] Password for user.dadm is set to never expire" -fore GREEN
if((Get-ADGroupMember -Identity "Domain Admins").Name -contains "user.dadm") {
Write-Host "[√] User.dadm was added to Domain Admins" -fore GREEN
if((((uACADA "user.dadm") -band 1048576) -ne 0) -eq $true) {
Write-Host "[√] Account Delegation Authority was removed" -fore GREEN
} else {
Write-Host "[X] Account Delegation was not removed" -fore RED
}
} else {
Write-Host "[X] User.dadm was not added to Domain Admins" -fore RED
}
} else {
Write-Host "[X] Password for user.dadm has been set to expire" -fore RED
}
} else {
Write-Host "[X] User.adam was not created" -fore RED
}
What this does is it will break to the else statement if any of the conditions aren't met but I need it to continue checking each condition.
I know that I could break this up and check each condition individually but I prefer to have it as compressed as possible as it is already going to be over a thousand lines.
I guess the REAL question is if this can be done without making 4 separate IF/ELSE statements.
I'm not sure if its a structuring issue (nested IF) or a command issue (using IF and ELSE when I should use IF and ELSEIF).
Could someone point me in the right direction? Thanks in advance.
not tested, but this may be a starting point, though you may just choose the simplicity of multiple if statements.
$user = 'user.dadm'
$info = [ordered]#{
created = "[X] $user was not created"
neverexp = "[X] Password for $user has been set to expire"
admin = "[X] $user was not added to Domain Admins"
delegation = "[X] Account Delegation for $user was not removed"
}
switch ($true) {
{net user $user} {
$info.created = "[√] $user was created successfully"
}
{((uACADA $user) -band 65536) -ne 0} {
$info.neverexp = "[√] Password for $user is set to never expire"
}
{(Get-ADGroupMember -Identity 'Domain Admins').Name -contains $user} {
$info.admin = "[√] $user was added to Domain Admins"
}
{((uACADA $user) -band 1048576) -ne 0} {
$info.delegation = "[√] Account Delegation Authority for $user was removed"
}
default {Write-Host 'all are false'}
}
$info.Keys | % {
if ($info.$_.startswith('[X]')) {
Write-Host $($info.$_) -ForegroundColor Red
} else {
Write-Host $($info.$_) -ForegroundColor Green
}
}
Yes, you can write it without if tests, e.g.
$colors = #('Red', 'Green')
$messages = #('[X] Failed -', '[√] Succeeded -')
$username = "user.adm"
$result = [bool](net user "$username")
Write-Host "$($messages[$result]) Check user account exists" -ForegroundColor $colors[$result]
$result = [bool]((uACADA "$username") -band 65536)
Write-Host "$($messages[$result]) Check password never expires" -ForegroundColor $colors[$result]
$result = [bool]((Get-ADGroupMember -Identity "Domain Admins").Name -contains "$username")
Write-Host "$($messages[$result]) Check account is a domain admin" -ForegroundColor $colors[$result]
$result = [bool]((uACADA "$username") -band 1048576)
Write-Host "$($messages[$result]) Check Delegation Authority removed" -ForegroundColor $colors[$result]
NB. that if you aren't using if/else, you need some other way to do the true/false testing. I'm casting results to [bool] and using 2-element arrays. $array[$false] casts $false -> 0 and gets element 0, $array[$true] casts $true -> 1 and gets element 1. That's how the result is turned into the appropriate colors and messages.
Another reasonable way to write this would be to move the Write-Hosts into a function.
Function Report-Result {
param($Result, $Text)
if ($Result) {
Write-Host "Success - $Text" -Fore Green
} else {
Write-Host "Failure - $text" -Fore Red
}
}
$result = [bool](...)
report-result $result "Check password never expires"
... etc.
Output looks like:
Which is okayyyy - it gets your 20 lines of code down to ~10, and has no nesting, and runs all the tests.
But it really feels like you're re-inventing PowerShell DSC ("my desired state is that accounts with .adm at the end have their passwords set to never expire") or Pester - PowerShell's test framework, ("test that all .adm accounts have passwords set to never expire").
I'm not sure that you can exactly fit Pester into your use case, but it makes me think I would change everything about the script from the way it's structured to the output messages, to make it look and feel like Pester. Particularly I want clear separation of test definitions and printed output, e.g.:
1. Here are my tests, with self-explanatory names
2. Here is a loop which runs all tests, and reports on them
and that gives me something like:
Function Validate-DCUserAccountShouldExist {
param($Username) [bool](net user "$UserName")
}
Function Validate-DCUserAccountPasswordNeverExpireShouldBeSet {
param($Username) [bool]((uACADA "$username") -band 65536)
}
Function Validate-DCUserAccountShouldBeADomainAdmin {
param($Username) [bool]((Get-ADGroupMember -Identity "Domain Admins").Name -contains "$username")
}
Function Validate-DCUserAccountShouldHaveDelegationAuthorityRemoved {
param($Username) [bool]((uACADA "$Username") -band 1048576)
}
# Search for all Validation functions and run them
$tests = (gci function: |Where Name -Like 'Validate-DCUserAccount*').Name
foreach ($test in $tests) {
$result = try {
& $test "user.adm"
} catch {
$false
}
if ($result) {
Write-Host -ForegroundColor Green "[√] $test - succeeded"
} else {
Write-Host -ForegroundColor Red "[X] $test - Failed"
}
}
Which gives an output like:
My view of my second code is that:
It's longer
more complex, less easy to follow
a lot less duplication of Write-Host
more structured, separation of test definitions and output
function names explain what the state should be, which makes the output messages work for success/failure
Output messages are neater in the code, but uglier to read in the output (but could be adjusted, e.g. add spaces when printing them)
would scale to more tests nicely, just by adding more tests
I'm deploying apps using Import-SPAppPackage and Install-SPApp. I'd like to be able to use Set-AppPrincipalPermission to set permissions but I can't get it working.
I'm uploading a SharePoint-hosted app to SharePoint using the PowerShell cmdlets Import-SPAppPackage and Install-SPApp. This is working fine for SharePoint-hosted apps that do not require additional permissions.
However, one app needs read access to the site, so this is declared in the manifest. And it works fine when run through Visual Studio - on first launch, it correctly asks to trust the app for read access to the site.
When I add this app via PowerShell, it has no opportunity to ask. The install continues without problems, but then the app doesn't work. (It fails with a permissions problem, which is absolutely the correct behavour since the permissions haven't yet been granted.)
I can fix the permissions by going to the Site Contents, clicking on the '...' for the problem app, choosing 'Permissions' and then clicking the link that says 'If there's something wrong with the app's permissions, click here to trust it again'.
But I really want to just be able to do the whole deployment via PowerShell.
The Set-AppPrincipalPermission cmdlet should allow me to set the permissions, but I can't get it to work. Specifically, I can't get a handle on the app principal that was automatically created when the app was deployed, so I can't pass this app principal to Set-AppPrincipalPermission.
The app principal has a name of the form 'i:0i.t|ms.sp.int|#' and it is listed on /_layouts/15/appprincipals.aspx. When I use Get-SPAppPrincipal with it, all I get is:
Get-SPAppPrincipal : The app principal could not be found.
I haven't seen any examples of using Get-SPAppPrincipal for any SharePoint-hosted apps - they all seem to be for provider-hosted apps. They also all seem to just use an app principal ID built from the client ID and the realm ID, but my SharePoint-hosted app doesn't have a client ID.
Is it possible to get the app principal of a SharePoint-hosted app and use it to set the permissions via PowerShell? Am I doing something wrong, or is there another approach?
I struggled the same problem like you and finally found an answer in these two blogs:
Blog with a nice Install, Update and Delete Script
Here is a nice post about "pressing" the "Trust It" Button via PowerShell Link
And because I know how lazy programmers like me are, feel free to use this merged script to Install Apps:
param
(
[string]$Web = $(throw '- Need a SharePoint web site URL (e.g. "http://portal.contoso.com/")'),
[string]$Source = "ObjectModel"
)
Write-Host -ForegroundColor White "-------------------"
Write-Host -ForegroundColor White "| App Installer |"
Write-Host -ForegroundColor White "-------------------"
Write-Host -ForegroundColor White "- "
#Global vars
$AppPackageName = "App.app";
#Loads powershell settings
Write-Host -ForegroundColor White "- Load Powershell context.."
$0 = $myInvocation.MyCommand.Definition
$dp0 = [System.IO.Path]::GetDirectoryName($0)
#Loads the SharePoint snapin
Write-Host -ForegroundColor White "- Load SharePoint context.."
$ver = $host | select version
if ($ver.Version.Major -gt 1) {$host.Runspace.ThreadOptions = "ReuseThread"}
if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {
Add-PSSnapin "Microsoft.SharePoint.PowerShell";
}
[void][System.Reflection.Assembly]::Load("Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c")
#Imports the App package
Write-Host -ForegroundColor White "- Import app package '$AppPackageName'..."
$appPath = "C:\Projects\App\App\bin\Debug\app.publish\1.0.0.0" + "\" + $AppPackageName;
if ($Source.Equals("ObjectModel", [System.StringComparison]::InvariantCultureIgnoreCase)) {
$sourceApp = ([microsoft.sharepoint.administration.spappsource]::ObjectModel);
}
elseif ($Source.Equals("Marketplace", [System.StringComparison]::InvariantCultureIgnoreCase)) {
$sourceApp = ([microsoft.sharepoint.administration.spappsource]::Marketplace);
}
elseif ($Source.Equals("CorporateCatalog", [System.StringComparison]::InvariantCultureIgnoreCase)) {
$sourceApp = ([microsoft.sharepoint.administration.spappsource]::CorporateCatalog);
}
elseif ($Source.Equals("DeveloperSite", [System.StringComparison]::InvariantCultureIgnoreCase)) {
$sourceApp = ([microsoft.sharepoint.administration.spappsource]::DeveloperSite);
}
elseif ($Source.Equals("RemoteObjectModel", [System.StringComparison]::InvariantCultureIgnoreCase)) {
$sourceApp = ([microsoft.sharepoint.administration.spappsource]::RemoteObjectModel);
}
$spapp = Import-SPAppPackage -Path "$appPath" -Site $Web -Source $sourceApp -Confirm:$false -ErrorAction SilentlyContinue -ErrorVariable err;
if ($err -or ($spapp -eq $null))
{
Write-Host -ForegroundColor Yellow "- An error occured during app import !"
throw $err;
}
Write-Host -ForegroundColor White "- Package imported with success."
#Installs the App
Write-Host -ForegroundColor White "- Install the APP in web site..."
$app = Install-SPApp -Web $Web -Identity $spapp -Confirm:$false -ErrorAction SilentlyContinue -ErrorVariable err;
if ($err -or ($app -eq $null)) {
Write-Host -ForegroundColor Yellow "- An error occured during app installation !"
throw $err;
}
$AppName = $app.Title;
Write-Host -ForegroundColor White "- App '$AppName' registered, please wait during installation..."
$appInstance = Get-SPAppInstance -Web $Web | where-object {$_.Title -eq $AppName};
$counter = 1;
$maximum = 150;
$sleeptime = 2;
Write-Host -ForegroundColor White "- Please wait..." -NoNewline;
$url = "$($Web)_layouts/15/appinv.aspx?AppInstanceId={$($appInstance.Id)}"
$ie = New-Object -com internetexplorer.application
try
{
$ie.visible=$true
$ie.navigate2($url)
while ($ie.busy)
{
sleep -milliseconds 60
}
$trustButton = $ie.Document.getElementById("ctl00_PlaceHolderMain_BtnAllow")
$trustButton.click()
sleep -Seconds 1
Write-Host "App was trusted successfully!"
}
catch
{
throw ("Error Trusting App");
}
while (($appInstance.Status -eq ([Microsoft.SharePoint.Administration.SPAppInstanceStatus]::Installing)) -and ($counter -lt $maximum))
{
Write-Host -ForegroundColor White "." -NoNewline;
sleep $sleeptime;
$counter++;
$appInstance = Get-SPAppInstance -Web $Web | where-object {$_.Title -eq $AppName}
}
Write-Host -ForegroundColor White ".";
if ($appInstance.Status -eq [Microsoft.SharePoint.Administration.SPAppInstanceStatus]::Installed) {
Write-Host -ForegroundColor White "- The App was successfully installed.";
$appUrl = $appInstance.AppWebFullUrl;
Write-Host -ForegroundColor White "- The App is now available at '$appUrl'.";
Write-Host -ForegroundColor White "- (Don't forget to add app host name in your host file if necessary...).";
Write-Host -ForegroundColor White "- "
}
else {
Write-Host -ForegroundColor Yellow "- An unknown error has occured during app installation. Read SharePoint log for more information.";
}
Figured out a way other than using IE.
Basically just using powershell to call SPAppPrincipalPermissionsManager.AddAppPrincipalToWeb
$rootUrl = "https://ur-sp.com"
$urlSiteName = "ur-site"
$web = Get-SPWeb "$rootUrl/$urlSiteName"
$appPrincipalManager = [Microsoft.SharePoint.SPAppPrincipalManager]::GetManager($web)
$applicationEndPointAuthorities = new-object System.Collections.Generic.List[string]
$applicationEndPointAuthorities.Add("$rootUrl/$urlSiteName");
$symmetricKey = New-Object System.Security.SecureString;
$datetimeNow = [System.DateTime]::Now
$credential = [Microsoft.SharePoint.SPAppPrincipalCredential]::CreateFromSymmetricKey($symmetricKey,$datetimeNow,$datetimeNow)
$creationParameters =New-Object Microsoft.SharePoint.SPExternalAppPrincipalCreationParameters($appid,$appFriendlyName,$applicationEndPointAuthorities,$credential)
$appPrincipal = $appPrincipalManager.CreateAppPrincipal($creationParameters)
$appPrincipalPermissionsManager = New-Object -TypeName
Microsoft.SharePoint.SPAppPrincipalPermissionsManager -ArgumentList $web
$r = $appPrincipalPermissionsManager.AddAppPrincipalToWeb($appPrincipal, 3)
3 is of SPAppPrincipalPermissionKind enum, and I don't think its value really matters.
This will do the full trust part via powershell:
$targetWeb = Get-SPSite "http://dev.my.com"
$clientID = "82ea34fc-31ba-4e93-b89a-aa41b023fa7e"
$authRealm = Get-SPAuthenticationRealm -ServiceContext $targetWeb
$AppIdentifier = $clientID + "#" + $authRealm
$appPrincipal = Get-SPAppPrincipal -Site $targetWeb.RootWeb -NameIdentifier $AppIdentifier
Set-SPAppPrincipalPermission -Site $targetWeb.RootWeb -AppPrincipal $appPrincipal -Scope SiteCollection -Right FullControl
More info here:
http://lixuan0125.wordpress.com/2013/11/18/register-and-install-app-through-powershell/