Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

Friday, February 8, 2019

Connect to SharePoint online, with an account has multi factor authentication (MFA) enable

When I deliver PowerShell script to a customer, that contains log in / credential, I normal use this line of code:

$user = "user@tenant.com"
$password = "ZXY" | ConvertTo-SecureString -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $password
$url = "https://tenant.sharepoint.com"
 
Connect-PnPOnline -Url $url -Credentials $credential

Or reading the password from disk like this:

$user = "user@tenant.com"
$password = Get-Content .\password.txt -Raw | ConvertTo-SecureString -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $password
$url = "https://tenant.sharepoint.com"
 
Connect-PnPOnline -Url $url -Credentials $credential

Or from Windows Credential Manager, https://github.com/SharePoint/PnP-PowerShell/wiki/How-to-use-the-Windows-Credential-Manager-to-ease-authentication-with-PnP-PowerShell.

But this will not work if the customer account is configured for use multi factor authentication (MFA). The PnP/PowerShell script will return with an error message:

“The remote server returned an error: (403) Forbidden”

Luckily, we can work around this errror, by using the UseWebLogin. When using the UseWebLogin parameter a Windows Form will open and show an IE control that navigate to the Office 365 log in page. And this process support MFA login.

$url = "https://ameq.sharepoint.com"
 
Connect-PnPOnline -Url $url -UseWebLogin

Thursday, January 11, 2018

Deploying my website to a Windows Virtual Machine aka deploy to an on-premise IIS webserver.

The setup where working with Visual Studio Online and have a customer, how is running everything on-premise has been quite frustrating. But not anymore! After the release of the feature “Deployment groups” it is now the easiest thing to do.

To over simplify the tasks for configuring Deployment groups. You need only to create a new deployment group in Visual Studio Online, “register machine” and run some PowerShell. And you are done Smile

The how-to guide to setup and create Deployment Groups can be found here https://docs.microsoft.com/en-us/vsts/build-release/apps/cd/deploy-webdeploy-iis-deploygroups

N.B. The how-to show you need two tasks to deploy the website. This is not correct. This remove these tasks and add the task “Deploy IIS Website/App”.

Before you can release anything, setup you build. By following this how-to guide for ASP.NET 4, https://docs.microsoft.com/en-us/vsts/build-release/apps/aspnet/build-aspnet-4?tabs=vsts

And this how-to guide for ASP.NET Core, https://docs.microsoft.com/en-us/vsts/build-release/apps/aspnet/build-aspnet-core?tabs=gitvsts%2Cweb%2Cdeploy-windows

Friday, December 15, 2017

Print all file in a folder

Twice a year I have to print a lot of files in different formats. It's easy to do with a little PowerShell:

Get-ChildItem c:\receipt\ | ForEach-Object {start-process $_.FullName –Verb Print}

Monday, October 23, 2017

Add Usage Guidelines Url for Office 365 Group

While I was configuring Classification for Groups, when I sported the UsageGuidelinesUrl and GuestUsageGuidelinesUrl option. When set, a link appears in the Site Information box.

Guideline

PowerShell to add, update, read and remove the guidelines urls

Add

# get the settings id default template for Groups
$settingTemplateID = Get-AzureADDirectorySettingTemplate | ? -Property "DisplayName" -Value "Group.Unified" -EQ | select -ExpandProperty ID
#get the tempalte object
$Template = Get-AzureADDirectorySettingTemplate -Id $settingTemplateID
#create a setting object
$newSetting = $template.CreateDirectorySetting()
#set the property
$newSetting["GuestUsageGuidelinesUrl"] = "http://guestguideline.com"
$newSetting["UsageGuidelinesUrl"] = "https://guideline.com"
#save the settings object back to Office 365
New-AzureADDirectorySetting -DirectorySetting $newSetting

Update

#Get the setting id for Groups
$settingID = Get-AzureADDirectorySetting | Where-object -Property Displayname -Value "Group.Unified" -EQ | select -ExpandProperty ID
#Get current settings object with the Groups ID
$setting = Get-AzureADDirectorySetting –Id $settingID
#Update the property
$Setting["UsageGuidelinesUrl"] = "https://my-tenant.sharepoint.com/"
$Setting["GuestUsageGuidelinesUrl"] = "http://public-url"
#Save the settings object back to Office 365
Set-AzureADDirectorySetting -Id $settingID -DirectorySetting $Setting

Read

#read all settings
(Get-AzureADDirectorySetting -All $True).Values

Remove – All settings for Groups!

#remove all settings
$settingID = Get-AzureADDirectorySetting | Where-object -Property Displayname -Value "Group.Unified" -EQ | select -ExpandProperty ID
Remove-AzureADDirectorySetting –Id $settingID

Monday, March 27, 2017

The lazy man’s Select-Object Expression

I have known the Select-Object Expression pattern since I started with PowerShell. Where the syntax is this:

select-object @{Name="Property1"; Expression={$_.PropertyObject.Property1}}

But a new PowerShell tip I lean this week is a syntax:

select-object {$_.PropertyObject.Property1}

The big difference is the headline on the column. In the first example, I control the column headline and the second example the headline will be:

$_.PropertyObject.Property1
-----------------------------------------

Monday, February 27, 2017

Get SharePoint logs

It is getting old PowerShell script but did need it recently. The script collection log files from all the servers in the farm for a given period.

Tip: $time is the copy/paste value from the SharePoint error message box.

$time = "23-02-2017 11:26:52"
$time = $time.Trim()
$timeToAdd = 10
$startTime = [Datetime]::Parse($time)
$endTime = $startTime.AddSeconds($timeToAdd)
$path = "c:\temp\log $($time.Replace(":", [String]::Empty)).txt"
Merge-SPLogFile -StartTime $startTime -EndTime $endTime -Path $path -Overwrite

Tuesday, March 15, 2016

Remove all custom user action

On my current project I use the PnP framework provisioning to add custom user action to my web. The web gets quickly fell up the custom user action weird places and it is hard to see which of the custom user action is the latest and therefore the ones I should test. Therefore, I use this PowerShell snippet to delete all, before I re-run my provisioning.

$web = get-spweb https://apps.dev2.net/sites/dev1/
$customActionIds = $web.UserCustomActions | select id
$customActionIds | % {
  $web.UserCustomActions.Item($_.Id).Delete()
}

Wednesday, July 22, 2015

Wait for timerjob to finish

I had an old PowerShell latying around. The PowerShell script wait for a given timerjob to be finished.
1 $sleeptime = 5
2 $timerjobname = "MetadataHubTimerJob"
3
4 $timerjob = Get-SPTimerJob | Where {$_.Name -eq $timerjobname}
5 if($timerjob)
6 {
7 $countBefore = $timerjob.HistoryEntries | select "EndTime"
8
9 $timerjob.RunNow()
10 "Waiting for timerjob: $($timerjob.Name) to finish"
11 while($true)
12 {
13 Start-Sleep -Seconds $sleeptime
14 $countAfter = $timerjob.HistoryEntries | select "EndTime"
15
16 if($countAfter.Count -gt $countBefore.Count)
17 {
18 "The timejob $($timerjob.Name) is done"
19 break
20 }
21 else
22 {
23 "Still waiting on timerjob: $($timerjob.Name) to finish..."
24 }
25 }
26 }
27 else
28 {
29 "The timerjob: $($timerjob.Name) was not found."
30 }

Wednesday, July 8, 2015

PowerShell script to restart application pools, with remote Powershell

Has a follow up on my blog post about a PowerShell script to restart application pools. This script do it with remote PowerShell

$computername = "myserver"
$script = {   
    Import-Module WebAdministration
    (Get-Item "IIS:\Sites\*"| Select-Object applicationPool).applicationPool | % { Restart-WebAppPool $_ }
}
$cred = Get-Credential
$remotesession = New-PSSession -ComputerName $computername -Credential $cred
Invoke-Command -Session $remotesession -ScriptBlock $script

PowerShell script to restart application pools

Two line PowerShell script to restart all application pools on a server

1 #Import WebAdministration
2 Import-Module WebAdministration
3 #Find, pipe and restart
4 (Get-Item "IIS:\Sites\*" | Select-Object applicationPool).applicationPool | % { Restart-WebAppPool $_ }
5

Thursday, March 5, 2015

A C# thing in PowerShell. String.Format

A PowerShell tips. A feature that I often use in C # is string.Format https://msdn.microsoft.com/en-us/library/system.string.format(v=vs.110).aspx. This function can also use the PowerShell. This can be done via [string]::Format("template {0}", $varb1) or you can call -f parameter after a string in PowerShell, for example. "template {0}" -f $ varb1

Wednesday, February 25, 2015

Call Exchange Web servies API through PowerShell

I had to test whether a given user has a given meeting requests in a calendar in Exchange. Therefore, I wrote this little piece of PowerShell script, that’s using Microsoft Exchange Web Services Managed API, to find the Exchange server based on user's email address. Then make a call to the user's calendar, where I could check if there was create meeting request.

Step 1. Download and execute the the Microsoft Exchange Web Services Managed API 2.0 http://www.microsoft.com/en-us/download/details.aspx?id=35371

Step 2. Change the PowerShell script
Change this variable:
$exchangeversion
$pathToExchangeDll
$folderName
$usersmtpadress
$userlogin
$userdomain
$userpassword

Step 3. Run the PowerShell script

1 $exchangeversion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010
2 $pathToExchangeDll = "c:\ExchangeWebserviceApi\Microsoft.Exchange.WebServices.dll"
3 $folderName = [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar
4 $usersmtpadress = "user@domain.dk"
5 $userlogin = "userlogind"
6 $userdomain = "domain"
7 $userpassword = "P@ssword!"
8
9 #callback function
10 function AutodiscoverCallback
11 {
12 param (
13 [System.String]
14 $Url
15 )
16 return $true
17 }
18 $callback = ${function:AutodiscoverCallback}
19 $service = new-object "Microsoft.Exchange.WebServices.Data.ExchangeService" $exchangeversion
20 $principle = new-object "Microsoft.Exchange.WebServices.Data.Mailbox" $usersmtpadress
21 $folder = new-object "Microsoft.Exchange.WebServices.Data.FolderId" $folderName, $principle
22 $connectingIdType = [Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress
23 [system.reflection.assembly]::loadfile($pathToExchangeDll) | Out-Null #e.g. c:\ExchangeWebserviceApi\Microsoft.Exchange.WebServices.dll
24
25 #setup call for Exchange web services
26 $service.Credentials = new-object "System.Net.NetworkCredential" $userlogin, $userpassword, $userdomain
27 $impersonatedUserId = new-object "Microsoft.Exchange.WebServices.Data.ImpersonatedUserId" $connectingIdType, $usersmtpadress
28 $service.ImpersonatedUserId = $impersonatedUserId
29 $service.AutodiscoverUrl($usersmtpadress, $callback)
30
31 #calling Exchange web services
32 $principleCalendar = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service, $folder)
33 "User {0}'s calendar" -f $userlogin
34 $principleCalendar

Thursday, December 18, 2014

Export property bag to a cvs file

Just a simple script, that read the property bag from a web, converts the key/value to a PowerShell object and pipe it to the Export-csv cmdlet.

$path = "c:\temp\propertybag.cvs"
$url = "http://win-l2sfc3oetnn"
$web = get-spweb $url
$web.AllProperties.getenumerator() | % {new-object psobject -Property @{Key = $_.name;Value=$_.value} } | export-csv $path -notype -Delimiter ";"

Thursday, December 11, 2014

PowerShell and delegates

At my current project, we have written a lot of PowerShell. We came to discuss whether, we can use delegates in PowerShell or it is a pure C# (.net) thing. The short answer is yes, you can do it. The syntax is like this:

1 $url = "http://win-l2sfc3oetnn"
2 function GetSiteElevatedPrivileges
3 {
4 $site = new-object "Microsoft.SharePoint.SPSite" $url
5 write-host $site.RootWeb.Title
6 }
7 [Microsoft.SharePoint.SPSecurity]::RunWithElevatedPrivileges(${function:GetSiteElevatedPrivileges})

Friday, July 25, 2014

Find the directory path where a running script, PowerShell 3.0 style

Back in the good old days of PowerShell 2.0, we often started our scripts with a line that referred the directory path where the script ran.

This is used e.g. to get location of a WSP package that was to be deployed to the farm. The PowerShell script looked like this.

1 $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
2 $scriptPath + "\mypackage.wsp"
3 #add and deploy package to farm

But in PowerShell 3.0, there is a new build-in variable for this. The “$PSScriptRoot” and now the PowerShell look like this


1 $PSScriptRoot + "\mypackage.wsp"
2 #add and deploy package to farm

This a not a big change to the script, but a line less is a win.

Thursday, June 26, 2014

Simplify your PowerShell and remember | is your friend

I had a colleague last week who wanted to clean up in his web application for site collection that he did not use. He google and found this piece PoweShell.

1 $tmpRoot = Get-SpWebApplication -Identity http://w520-sp2013-1:81
2 $tmpRootColl=$tmpRoot.Sites
3 for ($index=$tmpRootColl.Count-1 ; $index-ge 0 ; $index--) {Remove-SPSite -Identity $tmpRootColl.Item($index) -GradualDelete -Confirm:$false}
It now works fine too, but he had a hard time reading it and it could easily be made more simple. Eg. this way.


1 Get-SpWebApplication -Identity http://w520-sp2013-1:81 | Get-SPSite -Limit:All | Remove-SPSite -GradualDelete -Confirm:$false
Now there's no loop or variable you must remember to instantiate.

Wednesday, June 11, 2014

“Run as Administrator” the easy way

We live in a world that is run via PowerShell and how often have you not forgot to run his PowerShell script as "run as administrator"? But there are a few tricks in Windows so that it become easy.

As you probably already, how to start a problem with administrative privileges by right-clicking on a program/shortcut and select "Run as Administrator".
clip_image001

But did you know that by holding ctrl+shift down, you can obtain the same?

You can either double-click on a program/​​shortcut while holding ctrl+shift down or hit enter, it is the same.

Another trick is to make a shortcut to your program. Because on a shortcut, you can choose whether it always should "run as administrator"

How do you know about a problem running under the administrator context?

Look up at the program title bar. It says "Administrator" if it is running under sub-administrator context. This works not only for PowerShell command prompt but also for e.g. visual studio.

Untitled3

Tuesday, April 22, 2014

Find a process in a SharePoint farm

Last week I had to help a SharePoint 2010 customer to fix a bug in production environment, containing of three servers. When I looked through the log files, with my favorite ULS logging view tool http://archive.msdn.microsoft.com/ULSViewer, I could see that they was an error about a dll file, which was missing. “System.IO.FileNotFoundException: Could not load file or assembly 'XX.Sharepoint2010, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XX' or one of its dependencies”. However, the error was only showing in some request. So step one, was to figure out which server the dll was missing found, but the ULS log view do not show any thing in the server column.

GetComputerNameByProcessId

Nevertheless, looking in the Process column, we can find the hex value for the process that encounter the error. Then by looping throw all the servers in the farm, with the role type of application, we can call a get-process

Like this:

1 function Get-ComputerNameByProcessId ($processId)
2 {
3 [int]$processIdAsInt = [Convert]::ToInt32($processId)
4 $servers = Get-SPServer | ? { $_.Role -eq "Application" } | % {
5 Get-Process -computername $_.Address -Id $processIdAsInt -ErrorAction:SilentlyContinue | select MachineName
6 }
7 }
8 Get-ComputerNameByProcessId 0x1358
9

Thursday, November 28, 2013

How to load config file in PowerShell?

I had a problem with a customer where we would like to reuse one WCF endpoint from our web.config file. What Microsoft describes and a lot of blogs on the net, all you have to do is call [AppDomain]::CurrentDomain.SetData ("APP_CONFIG_FILE", $pathToConfig) http://msdn.microsoft.com/en-us/library/37z40s1c(v=vs.110).aspx. But it does not work because PowerShell already has loaded a config file loaded. Therefore, you should reset the config file “context” through reflection. To do so:

1 $pathToConfig = "C:\inetpub\wwwroot\wss\VirtualDirectories\80\web.config"
2 #Set the path to the new config file
3 [AppDomain]::CurrentDomain.SetData("APP_CONFIG_FILE", $pathToConfig)
4 [System.Configuration.ConfigurationManager].GetField("s_initState", [Reflection.BindingFlags] "NonPublic,Static").SetValue($null, 0)

Monday, April 8, 2013

New CodePlex project Create host named site collection

I just releast a new codeplex project to help create host named site collection.
Project contains a central administration page that creates the host named site collections. Fill in the form and at the top of the page, the code to be used be to create site collection via PowerShell appear.

You can find the project here