using credentials to get-childitem on other server - credentials

I'm working on a script that uses get-childitem on the other server, but need to change it so it uses credentials of the local account on the other server to do that. When I was just using Active Directory to do that, I was saving the task in our scheduler with my AD login, and it was good on the other server, using the UNC path. But we decided to change it to the local login there recently and I'm getting an error message, trying to use net use. Does anyone know of a good way to do this with the UNC path instead? Or, any idea why the following is giving an error message?
function GetSecureLogin(){
$global:username = "stuff"
$global:password = get-content C:\filename.txt | convertto-securestring
}
function Cleanup([string]$Drive) {
try {
$deleteTime = -42
$now = Get-Date
**#this is saying cannot find path '\\name.na.xxx.net\20xServerBackup\V' name truncated**
Get-ChildItem -Path $Drive -Recurse -Force |Where-Object {$_.LastWriteTime -lt $limit} | Remove-Item -Force
}
Catch{
Write-Host "Failed"
}
}
#####################start of script####################
$share = '\\name.na.xxx.net\20xServerBackup\'
$TheDrive = '\\name.na.xxx.net\20xServerBackup\VMs\'
$global:password = ""
$global:username = ""
GetSecureLogin
net use $share $global:password /USER:$global:username
[array]$DriveArray = #(TheDrive)
try{
$i=0
for ($i = $DriveArray.GetLowerBound(0); $i -le $DriveArray.GetUpperBound(); $i++) {
$tempDrv = $DriveArray[$i]
Cleanup $tempDrv
}
}
catch [Exception] {
Write-Host $_.Exception.Message
}
As you can see, I started using the example at this link with net use, but it's not doing the trick to use credentials to access the other server. powershell unc path cred

I got it to work this way, with New-PSDrive as #robert.westerlund suggests above:
$DestPath = split-path "$Drive" -Parent #this gives format without slash at and and makes powerShell *very happy*
New-PSDrive -Name target -PSProvider FileSystem -Credential $global:cred -Root "$DestPath" | Out-Null
$temp1 = Get-ChildItem -Path target:\VMs\ -Recurse -Force | Where-Object { $_.LastWriteTime -lt $limit}
Get-ChildItem -Path $Drive -Recurse -Force | Where-Object { $_.LastWriteTime -lt $limit} | Remove-Item -Force
Remove-PSDrive target
I had to add the cred part like this too:
$global:cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $global:username, $global:password

Related

Device Not coming in MEM portal or are with partially Workload shifted. How fix it?

I Tried below PowerShell.
Created a Powershell Script:
DeleteEnrollment.PS1
## Create Log
Function Write-Log
{
Param
(
[string]$Message
)
$Logfilepath = "C:\ProgramData\Microsoft\CoMgmtFixLog"
$Logfile = "C:\ProgramData\Microsoft\CoMgmtFixLog\CoMgmtFixLog.log"
If (!(Test-Path $Logfilepath))
{
New-Item -ItemType Directory -Path $Logfilepath -Force | Out-Null
}
If (!(Test-Path $Logfile))
{
New-Item -ItemType File -Path $Logfile -Force | Out-Null
}
$Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
$mgs = "$Stamp $Message"
Add-Content $Logfile -Value $mgs
}
## Create TimeStamp in Registry
Function Create-Timestamp
{
param
(
[String]$RegKeypath,
[String]$RegKeyName,
[String]$RegKeyValue
)
$ComgmtFixHive = 'HKLM:\SOFTWARE\Policies\Microsoft\CoMgmtFix'
$Step = "$ComgmtFixHive\$RegKeypath"
If (!(Test-Path $ComgmtFixHive))
{
New-Item -Path $ComgmtFixHive -Force | Out-Null
}
If(!(Test-Path $Step))
{
New-Item -Path $Step -Force | Out-Null
}
If($Step -and $RegKeyName -and $RegKeyValue)
{
New-ItemProperty -Path $Step -Name $RegKeyName -Value $RegKeyValue -PropertyType 'String' -force -ea SilentlyContinue | Out-Null
}
New-ItemProperty -Path $Step -Name 'ExecutionTimeStap' -Value (Get-Date).toString("yyyy/MM/dd HH:mm:ss") -PropertyType 'String' -force -ea SilentlyContinue | Out-Null
}
## Script Block ##
$Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
Write-Log "=========== Begining of Log - $Stamp =========="
## Retrieving Enrollment GUID
(Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Provisioning\OMADM\Accounts\*' | select Pschildname).pschildname | Out-File -FilePath 'C:\ProgramData\Microsoft\CoMgmtFixLog\EnrollmentGUID.txt'
$DeviceEnrollmentID = Get-Content 'C:\ProgramData\Microsoft\CoMgmtFixLog\EnrollmentGUID.txt'
Write-Log "Collected Enrollment GUID : $DeviceEnrollmentID"
Create-Timestamp -RegKeypath 'GetEnrollmentID' -RegKeyName 'EnrollmentID' -RegKeyValue $DeviceEnrollmentID
If (Test-Path "HKLM:\SOFTWARE\Microsoft\EnterpriseResourceManager\Tracked\$DeviceEnrollmentID")
{
Remove-Item -Path HKLM:\SOFTWARE\Microsoft\EnterpriseResourceManager\Tracked\$DeviceEnrollmentID -Recurse -Force
Write-Log "Delected : `"HKLM:\SOFTWARE\Microsoft\EnterpriseResourceManager\Tracked\$DeviceEnrollmentID`" registry."
}
If (Test-Path "HKLM:\SOFTWARE\Microsoft\Enrollments\$DeviceEnrollmentID")
{
Remove-Item -Path HKLM:\SOFTWARE\Microsoft\Enrollments\$DeviceEnrollmentID -Recurse -Force
Write-Log "Delected : `"HKLM:\SOFTWARE\Microsoft\Enrollments\$DeviceEnrollmentID`" registry."
}
## Retrieve Scheduled tasks
Write-Log "Checking and deleting Enrollment Scheduled tasks."
Create-Timestamp -RegKeypath 'ScheduledTaskDeletion'
$AllSchdTasks = Get-ScheduledTask | where TaskPath -eq "\Microsoft\Windows\Enterprisemgmt\$DeviceEnrollmentID\"
ForEach ($AllSchdTask in $AllSchdTasks)
{
$taskname = $AllSchdTask.TaskName
Unregister-ScheduledTask -TaskPath $AllSchdTask.TaskPath -TaskName $taskname -Confirm:$false
Write-Log "Deleting : $taskname"
}
Start-Process "$PSScriptRoot\PsExec.exe" -ArgumentList "-is powershell.exe -command Remove-Item 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\Microsoft\Windows\EnterpriseMgmt\$DeviceEnrollmentID' -Recurse -Force" -WindowStyle Hidden
## Removing MDM Certificate
Write-Log "Finding and deleting MDM certificate"
Create-Timestamp -RegKeypath 'MDMCertificateDeletion'
gci cert:\LocalMachine\My -Recurse | Where {$_.Issuer -match 'Microsoft Intune MDM Device CA'} | Remove-Item -Force
$MDMcert = Get-ChildItem cert:\LocalMachine\My -Recurse | Where {$_.Issuer -match 'Microsoft Intune MDM Device CA'}
If($MDMcert)
{
Write-Log "MDM Certificate NOT Deleted"
}
Else
{
Write-Log "MDM Certificate Deleted"
}
## Retrieving existing users
Write-Log "Retrieving Existing user name and deleting Microsoft AAD broker plugin files."
Create-Timestamp -RegKeypath 'DeleteUserFiles'
$UserFolders = Get-ChildItem "C:\Users"
ForEach ($UserFolder in $UserFolders)
{
if ($UserFolder.Name -ne 'adiadmin')
{
if ($UserFolder.Name -ne 'Public')
{
if ($UserFolder.Name -ne 'Default')
{
$username = $UserFolder.Name
Write-Log "Deleting Microsoft.AAD.BrokerPlugin files from $username"
$msaadName = (Get-ChildItem "C:\Users\$username\AppData\Local\Packages" -Recurse -Force -Include Microsoft.AAD.BrokerPlugin* -ea SilentlyContinue).Name
Remove-Item -Path "C:\Users\$username\AppData\Local\Packages\$msaadName\Settings\*" -Force -Recurse -ea SilentlyContinue
Remove-Item -Path "C:\Users\$username\AppData\Local\Packages\$msaadName\AC\TokenBroker\Accounts\*" -Force -Recurse -ea SilentlyContinue
}
}
}
}
## Running dsregcmd /leave
Write-Log "Running dsregcmd /leave command"
Create-Timestamp -RegKeypath 'DsRegcmdLeave'
Start-Process -FilePath "dsregcmd.exe" -ArgumentList "/leave" -Verb RunAs
#.\dsregcmd.exe /leave
## Printing Reboot required regkey
Write-Log "Please restart you computer to proceed with next step."
Create-Timestamp -RegKeypath 'Reboot' -RegKeyName 'IsRebootRequired' -RegKeyValue 'Yes'
#Remove-Item -Path C:\temp\PsExec.exe -Force
Write-Log "=========== End of Log - $Stamp =========="
Created text file(Server.txt) with the device list having the issue.
Executed CoMgmtFix.Ps1 script which does all the work..
Issue in the above steps is I need to delete device from Azure AD manually. If there any way to delete the device entery from Azure AD via Script itself?
Tried the above stesp but need a way to delete device from Azure AD via Script itself.
To delete device from Azure AD:
Include RemoveAzureADDevice PowerShell script command directly.
Before running the command, you must call connect-AzureAD in PowerShell.
Remove-AzureADDevice -objectID <objectID>
To test, I created a virtual machine windows device in my environment and joined with Azure AD.
Get the object ID from AD joined VM properties by visiting Azure Active Directory -> Devices -> All Devices & search for the registered device.
Output:
Note: To remove an Azure AD joined device, you must have "administrative/owner" permissions under Roles & Assignments -> Azure Active Directory
Refer MsDoc

Powershell Script Can't Run Properly With Task Scheduler

I have an odd problem. I have a script that works fine when manually run it. I created a scheduled job in windows and run this script automatically. The script works fine until the last stage of script.
$deploymentfiles_mdm = Get-ChildItem 'D:\DeploymentTriggerApp\*'
Write-Host $deploymentfiles_mdm
$timestamp_app = Get-Date -Format o | ForEach-Object {$_ -replace ":", "."}
Write-Host $timestamp_app
$server = Get-Content 'C:\Users\Administrator\Desktop\Scripts\AutoDeployment\ProdMDMapps.txt'
$User = 'domain\user'
$SecurePassword = Get-Content C:\Users\Administrator\Desktop\Scripts\Password.txt | ConvertTo-SecureString
$UserCred = New-Object System.Management.Automation.PSCredential ($User, $SecurePassword)
if (Test-Path -Path $deploymentfiles_mdm)
{
do{
try
{
$ServerSessions = New-PSSession -ComputerName $server -Credential $UserCred -ErrorAction Stop
Write-Host ("$ServerSessions")
}
catch [Exception]
{
Write-Host("Credential is incorrect or password is expired. Either change credential and run CredentialEncryption.ps1 or communicate with dc admin to open expired password!")
}
}while(!$ServerSessions)
Copy-Item "D:\Deployment_Files\*.zip" -ToSession $ServerSessions -Destination "D:\Deployment_Files\" -ErrorAction SilentlyContinue
try{
Invoke-Command -Session $ServerSessions -ScriptBlock {
param($timestampApp)
$appPath = Get-ChildItem 'D:\MDM\live\bin\'
Expand-Archive -Path 'D:\Deployment_Files\*.zip' -DestinationPath 'D:\Deployment_Files\' -Force
Remove-Item -Path 'D:\Deployment_Files\*.zip'
$nodeProcess = Get-Process | Where-Object { $_.Name -eq "node"}
if($nodeProcess -Or $appPath)
{
Get-Process | Where-Object { $_.Name -eq "node"} | Select-Object -First 1 | Stop-Process -Force
New-Item -Path 'D:\Backups\' -Name $timestampApp -ItemType 'directory'
Get-ChildItem -Path "D:\MDM\live\bin\" -Recurse | Move-Item -Destination "D:\Backups\$timestampApp\"
}
Copy-Item "D:\Deployment_Files\bin" -Destination "D:\MDM\live\" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item "D:\Deployment_Files\*" -Recurse -Force
Start-Job -ScriptBlock{ node D:\MDM\live\bin\main.js}
} -ArgumentList $timestamp_app
}
catch
{
$_.Exception.Message
}
}
Remove-Item D:\DeploymentTriggerApp\*
In section Start-Job -ScriptBlock{ node D:\MDM\live\bin\main.js} the script can't start the node process. When I manually run it, it runs without any problem.
Any suggestions for that? (The node process needed to be in background job. If any alternative commands to that, I can also try that solution)
Below line solved my problem.
Start-Job -ScriptBlock{& 'C:\Program Files\nodejs\node.exe' D:\MDM\live\bin\main.js}

Powershell script to Find folders which have "Everyone" access and how to delete it

Need a Power Shell Script to find on a remote server which folders have "Everyone" access and How do I takeout this particular access (Remove Everyone group from Security)?
Something along these lines?
# 1. Get list of folders
$FolderList = Get-ChildItem -Path c:\test\everyone -Directory -Recurse;
# 2. Iterate over folders and remove 'everyone' rules
foreach ($Folder in $FolderList) {
$Acl = Get-Acl -Path $Folder.FullName;
$Everyone = $Acl.Access.Where({ $PSItem.IdentityReference -eq 'Everyone' });
foreach ($Ace in $Everyone) {
[void] $Acl.RemoveAccessRule($Ace);
}
Set-Acl -Path $Folder.FullName -AclObject $Acl;
}
IMPORTANT: This script requires PowerShell version 4.0, as it uses the Where "method syntax."
Translating Trevor's solution to PowerShell v2/v3:
$rootFolder = '\\server\c$\some\folder'
# get locale-specific name for 'Everyone' security principal
$sid = New-Object Security.Principal.SecurityIdentifier('S-1-1-0')
$everyone = $sid.Translate([Security.Principal.NTAccount]).Value
Get-ChildItem $rootFolder -Recurse | ? { $_.PSIsContainer } | % {
$acl = Get-Acl $_.FullName
$acl.Access | ? { $_.IdentityReference -eq $everyone } | % {
$acl.RemoveAccessRule($_)
}
Set-Acl $_.FullName -Acl $acl | Out-Null
}
In PowerShell v3 you can replace | ? { $_.PSIsContainer } with -Directory.
Note that this won't remove Everyone ACEs on the root folder itself, and it also won't remove inherited Everyone ACEs.

How to rename application pool that already has application assigned to it?

I have an Application pool that has a lot of applications been assigned to it, it won't let me rename.
Beside delete and creating a new application pool, is there anyway to get a new name for my application pool? I don't want to go and reassign every application in it.
Assign applications to another pool, rename the one you wanted renamed. Re-assign applications back to your pool.
IIS doesn't support other options
This was the simplest way that I could work it out, although I can't believe this isn't easier.
Import-Module WebAdministration
$oldName = "OldAppPool";
$newName = "NewAppPool";
if(-not (Test-Path IIS:\AppPools\TempPool)){
New-WebAppPool TempPool
}
$tempAppPool = Get-Item IIS:\AppPools\TempPool
foreach($site in Get-ChildItem IIS:\Sites){
$apps = $site | Get-ChildItem | Where-Object { $_.ApplicationPool -eq $oldName }
foreach($app in $apps){
$path = ("IIS:\Sites\{0}\{1}" -f $site.name, $app.name)
$path
Set-ItemProperty $path applicationPool TempPool
}
}
Set-ItemProperty "IIS:\AppPools\$oldName" -Name name -Value $newName
foreach($site in Get-ChildItem IIS:\Sites){
$apps = $site | Get-ChildItem | Where-Object { $_.ApplicationPool -eq "TempPool" }
foreach($app in $apps){
$path = ("IIS:\Sites\{0}\{1}" -f $site.name, $app.name)
$path
Set-ItemProperty $path applicationPool $newName
}
}
Remove-WebAppPool TempPool
No, there isn't.
Either put up with the name, or create a new App Pool and assign the applications one-by-one.
If you need to repeat it on multiple servers, you can even automate it with ADSI and JavaScript or VBScript:
http://msdn.microsoft.com/en-us/library/ms525389(v=vs.90).aspx
I've created similar script to automate this job.
It is a bit different from the other answer here:
It works for WebSites in addition to WebApplications;
It works for all pools: with and without assigned applications;
Powershell script:
Import-Module WebAdministration
Function Rename-AppPool([String]$oldName="", [String]$newName="") {
if ($oldName -eq "") {
Write-Warning "Parameter 'oldName' was not provided."
return
}
if ($newName -eq "") {
Write-Warning "Parameter 'newName' was not provided."
return
}
if(-not (Test-Path "IIS:\AppPools\$oldName")){
Write-Warning "There is no pool with name '$oldName' to rename. Operation stopped."
return
}
if(Test-Path "IIS:\AppPools\$newName"){
Write-Warning "Pool with name '$newName' already exists. Operation stopped."
return
}
Write-Output "Renaming app pool '$oldName' to '$newName'"
$pathsOfPools = New-Object System.Collections.ArrayList
$listOfSites = Get-ChildItem "IIS:\Sites"
foreach ($site in $listOfSites) {
if ($site.applicationPool -eq $oldName) {
$path = ("IIS:\Sites\{0}" -f $site.name)
$pathsOfPools.Add($path) | Out-Null
}
$apps = $site | Get-ChildItem
foreach ($app in $apps) {
if ($app.applicationPool -eq $oldName) {
$path = ("IIS:\Sites\{0}\{1}" -f $site.name, $app.name)
$pathsOfPools.Add($path) | Out-Null
}
}
}
$tempGuid = [Guid]::NewGuid()
$tempName = $tempGuid.Guid
if ($pathsOfPools.Count -gt 0) {
$pathsOfPools
New-WebAppPool $tempName | Out-Null
Write-Output "Temp app pool '$tempName' has been created"
Write-Output "Changing apps to Temp pool"
foreach ($path in $pathsOfPools) {
Set-ItemProperty $path applicationPool $tempName
}
}
Set-ItemProperty "IIS:\AppPools\$oldName" -Name name -Value $newName
Write-Output "Application pool name has been changed"
if ($pathsOfPools.Count -gt 0) {
Write-Output "Changing apps to New pool"
foreach ($path in $pathsOfPools) {
Set-ItemProperty $path applicationPool $newName
}
Remove-WebAppPool $tempName
Write-Output "Temp pool has been removed"
}
}
Rename-AppPool "OldName" "NewBetterName"
Yes, there is an option. Create a dummy app pool or make use of DefaultApppool. Associate the existing site to the defaultapppool . Now go to the original app pool, Stop the app pool and rename.
Associate back the url to the renamed appool.

downloading a file from SharePoint Online with PowerShell

I have a requirement to download files from a sharepoint online document library using powershell
I've managed to get to the point where the download should happen but no luck.
I know its something to do with how I am using the stream/writer
any hints would be greatly appreciated
*Edit
No error messages are thrown just 0 length files in my local Directory
$SPClient = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
$SPRuntime = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")
$webUrl = Read-Host -Prompt "HTTPS URL for your SP Online 2013 site"
$username = Read-Host -Prompt "Email address for logging into that site"
$password = Read-Host -Prompt "Password for $username" -AsSecureString
$folder = "PoSHTest"
$destination = "C:\\test"
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($webUrl)
$ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)
$web = $ctx.Web
$lists = $web.Lists.GetByTitle($folder)
$query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery(10000)
$result = $lists.GetItems($query)
$ctx.Load($Lists)
$ctx.Load($result)
$ctx.ExecuteQuery()
#Edited the foreach as per #JNK
foreach ($File in $result) {
Write-host "Url: $($File["FileRef"]), title: $($File["FileLeafRef"]) "
$binary = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($ctx,$File["FileRef"])
$Action = [System.IO.FileMode]::Create
$new = $destination + "\\" + $File["FileLeafRef"]
$stream = New-Object System.IO.FileStream $new, $Action
$writer = New-Object System.IO.BinaryWriter($stream)
$writer.write($binary)
$writer.Close()
}
You could also utilize WebClient.DownloadFile Method by providing SharePoint Online credentials to download the resource from SharePoint Online as demonstrated below.
Prerequisites
SharePoint Online Client Components SDK have to be installed on the machine running the script.
How to download a file in SharePoint Online/O365 in PowerShell
Download-File.ps1 function:
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")
Function Download-File([string]$UserName, [string]$Password,[string]$FileUrl,[string]$DownloadPath)
{
if([string]::IsNullOrEmpty($Password)) {
$SecurePassword = Read-Host -Prompt "Enter the password" -AsSecureString
}
else {
$SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
}
$fileName = [System.IO.Path]::GetFileName($FileUrl)
$downloadFilePath = [System.IO.Path]::Combine($DownloadPath,$fileName)
$client = New-Object System.Net.WebClient
$client.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword)
$client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
$client.DownloadFile($FileUrl, $downloadFilePath)
$client.Dispose()
}
Usage
Download-File -UserName "username#contoso.onmicrosoft.com" -Password "passowrd" -FileUrl https://consoto.sharepoint.com/Shared Documents/SharePoint User Guide.docx -DownloadPath "c:\downloads"
I was able to download the file successfully with the following relevant code snippet. You should be able to extend it for your situation.
Add-Type –Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type –Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
$siteUrl = Read-Host -Prompt "Enter web URL"
$username = Read-Host -Prompt "Enter your username"
$password = Read-Host -Prompt "Enter password" -AsSecureString
$source = "/filepath/sourcefilename.dat" #server relative URL here
$target = "C:/detinationfilename.dat" #URI of the file locally stored
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)
$ctx.Credentials = $credentials
[Microsoft.SharePoint.Client.FileInformation] $fileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($ctx,$source);
[System.IO.FileStream] $writeStream = [System.IO.File]::Open($target,[System.IO.FileMode]::Create);
$fileInfo.Stream.CopyTo($writeStream);
$writeStream.Close();
While the CSOM code above likely can be made to work I find it easier to use the web client method.
(from http://soerennielsen.wordpress.com/2013/08/25/use-csom-from-powershell/)
I've used the code below, to retrieve a bunch of files (metadata from CSOM queries) to a folder (using your $result collection, other params should be adjusted a bit):
#$siteUrlString site collection url
#$outPath path to export directory
$siteUri = [Uri]$siteUrlString
$client = new-object System.Net.WebClient
$client.UseDefaultCredentials=$true
if ( -not (Test-Path $outPath) ) {
New-Item $outPath -Type Directory | Out-Null
}
$result |% {
$url = new-object Uri($siteUri, $_["FileRef"])
$fileName = $_["FileLeafRef"]
$outFile = Join-Path $outPath $fileName
Write-Host "Downloading $url to $outFile"
try{
$client.DownloadFile( $url, $outFile )
}
catch{
#one simple retry...
try{
$client.DownloadFile( $url, $outFile )
}
catch{
write-error "Failed to download $url, $_"
}
}
}
The trick here is the
$client.UseDefaultCredentials=$true
which will authenticate the webclient for you (as the current user).
The direct and almost shortest answer to the question is simply:
$url = 'https://the.server/path/to/the/file.txt'
$outfile = "$env:userprofile\file.txt"
Invoke-WebRequest -Uri $url -OutFile $outfile -Credential (Get-Credential)
This works at least in Powershell 5.1...
So I gave up on this. it turned out to be much easier to write an SSIS script component to do the job.
I have awarded Soeren as he posted some code that will work for regular websites but not sodding SharePoint Online.
Thanks Sorean!
Short an easy approach to download a file from sharepoint online, using just powershell and sharepoint online url ( no pnp powershell )
This approach can also be used to perform Sharepoint REST queries, with just powershell and sharepoint REST api
# required MS dependencies
# feel free to download them from here https://www.microsoft.com/en-us/download/details.aspx?id=42038
Add-Type -Path 'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll' -ErrorAction Stop
Add-Type -Path 'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll' -ErrorAction Stop
# prepare passwords
$spCredential = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($user, $(ConvertTo-SecureString -AsPlainText $pass -Force))
# prepare and perform rest api query
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($targetSiteUrl)
$Context.Credentials = $spCredential
try {
#this may return an error, but still will finish context setup
$Context.ExecuteQuery()
}
catch {
write-host "TODO: fix executeQuery() err 400 bug" -ForegroundColor Yellow
}
$AuthenticationCookie = $Context.Credentials.GetAuthenticationCookie($targetSiteUrl, $true)
$WebSession = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$WebSession.Credentials = $Context.Credentials
$WebSession.Cookies.SetCookies($targetSiteUrl, $AuthenticationCookie)
$WebSession.Headers.Add("Accept", "application/json;odata=verbose")
Invoke-WebRequest -Uri $spFileUrl -OutFile $outputFilePath -WebSession $WebSession -errorAction Stop
Where
$outputFilePath is the target output file in which you want to save the remote file.
$targetSiteUrl is the target sp site url.
$spFileUrl is the "[sharepoint file full url]"
$user plain text sp user email
$pass plain text sp user pass

Resources