PowerShell - read SharePoint file properties (datemodified, etc) - powershell

I need to compare a file in SharePoint against a local file and to make sure they are the same version (it's an accdb that's developed offline and shared in multiple client SharePoint locations). I need to get the modified date from the file in SharePoint, and I've been unable to do so.
NB: I don't have Get-SPWeb available, as this needs to be run by various users who won't have SharePoint 2013 Management Shell available to them (reference).
I've tried using Get-PnPFile with -AsListItem, and it doesn't return an error but I can't access any properties.
I've tried .FieldValuesAsText and .ListItemAllFields and not getting anywhere.
This bit, connecting to the SharePoint resource via SharePointPnPPowerShellOnline, is working:
$SiteURL = "https://myorg.sharepoint.com/sites/mysite"
$FileRelativeURL = "Shared Documents/mydb.accdb"
$UserName = "user#myorg.org"
$PlainPassword = "myP#ssw0rd#"
$SecurePassword = $PlainPassword | ConvertTo-SecureString -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecurePassword
Connect-PnPOnline -Url $SiteURL -Credentials $Cred
I tried this, and it downloads the file; I don't need to do that:
$file1 = Get-PnPFile -Url $FileRelativeURL -AsFile
According to this, "-AsListItem" returns the file as a listitem showing all its properties. So I tried it. It didn't download the file, and it didn't return an error, so maybe I have an object I can query now?
$file1 = Get-PnPFile -Url $FileRelativeURL -AsListItem
write-host $file1
The second line returns Microsoft.SharePoint.Client.ListItem.
The following return empty strings:
write-host $file1.Name
write-host $file1.TimeLastModified
write-host $file1.LastModified
write-host $file1[-1]
write-host $file1[0,1,2,3,4,5,6,7,8,9]
Found FieldValuesAsText mentioned somewhere, so I tried it:
$props = $file1.FieldValuesAsText
write-host $props
write-host $props[0]
The first one returns Microsoft.SharePoint.Client.FieldStringValues; the second one returns an empty string.
Tried ListItemAllFields:
$props = $file1.ListItemAllFields
write-host $props
write-host $props[0]
The first line didn't generate an error; the second line returned an empty string; the third line returned:
Cannot index into a null array.
At line:1 char:1
+ write-host $props[0]
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
Very new to PowerShell, and I'm probably missing something obvious. (SharePointPnPPowerShellOnline is installed and working.)
The code above doesn't include getting information from my local file; I haven't gotten that far yet. I imagine the instructions here will work. My issue is getting the metadata from the file in SharePoint.
Grateful for any assistance or pointing me to the right resource; I've done a couple hours of research and am coming up empty.

Your best bet would be to map the SharePoint drive as a PSDrive on your system. Then you can treat it like a regular file system and the property LastWriteTime will be available.
More info on New-PSDrive can be found in the documentation online or by typing Get-Help New-PSDrive in a PowerShell console/ISE.

Related

Powershell Get-FTPItem -Path * ... is not working

I am working on a fairly small script that aims to download all files from a FTP folder. The script is a powershell script and uses the PSFTP module.
So for test purposes I created 3 randoms files in the ftp folder called "a", "b" and "c".
The script works like this
Creating PSCredentials
Creating a FTP connection
Connecting to session
Downloading all files from the root ftp folder
So, all is working except the last line. To take all files i try using the wildcard * but this creates an error : Exception calling ".ctor" with 2 argument(s)
The whole script looks like this :
Import-Module PSFTP
$pass = ConvertTo-SecureString "1234" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ('...2', $pass)
Set-FTPConnection -Credentials $cred -Server ... -Session CertFTP -IgnoreCert -UseBinary -KeepAlive
$Session1 = Get-FTPConnection -Session CertFTP
Get-FTPItem -Path * -LocalPath 'C:\Certificats' -Session $Session1
I tried the same thing but with -Path "a", and this is working.
Thus, what I don't know is : Am I doing something wrong in the syntax itself, or does Get-FTPItem doesn't support using * in -Path?
I ended up using Get-FTPChildItem in a foreach and then using Get-FTPItem on each object.

Start-Process : This command cannot be run due to the error: The filename or extension is too long

I want to configure the Outlook profile with the email account and I'm taking the values from the stored credentials. But when I run the script, it shows
Start-Process : This command cannot be run due to the error: The filename or extension is too long.
The code is as follows:
clear
if($process=(get-process 'outlook' -ErrorAction SilentlyContinue))
{
Write-Host "Outlook is running so close it.." -ForegroundColor Green
kill($process)
Write-Host "Outlook is stopped " -ForegroundColor Green
}
$reg="HKCU:\Software\Microsoft\Office\16.0\Outlook\Profiles"
Write-Host "create new profile for outlook" -ForegroundColor Green
"`n"
New-Item -Name "outlook" -Path $reg -Force -Verbose
Write-Host "New profile created" -ForegroundColor Green
"`n"
Write-Host "Launch outlook with newly created profile" -ForegroundColor Green
$Login = Get-StoredCredential -Target 'test'
$Decrypt = $Login.Password | ConvertFrom-SecureString
$Encrypt = $Decrypt | ConvertTo-SecureString -AsPlainText -Force
$passwd=[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Encrypt))
$Password = ConvertTo-SecureString $passwd -AsPlainText -Force
$cred = new-object -Typename System.Management.Automation.pscredential -ArgumentList($Login.UserName, $password)
Start-Sleep -s 5
Start-Process 'OUTLOOK.EXE' -Credential $cred -ArgumentList '/profile "outlook" '
Error:
Start-Process : This command cannot be run due to the error: The filename or extension is too long.
At line:1 char:2
+ Start-Process 'OUTLOOK.EXE' -Credential $cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessComm
and
In this script, I'm able to create a new profile but unable to launch the outlook with newly created profile including the email account part.
The Start-process raises an error when providing Credentials - possible bug page has the following explanation to the problem:
When you use Start-Process without specifying a target directory with -WorkingDirectory, PowerShell's current location (directory) is used for the target process as well.
Since you're using -Credential to run as a different user - without elevation at that point - the target user may lack permission to access the current directory, which happens if the current directory is inside the current user's home directory subtree, for instance.
Unfortunately, PowerShell's error message obscures this cause by misleadingly reporting: The directory name is invalid.
The solution is to make sure that the current location is accessible to the target user, or, preferably, use the -WorkingDirectory parameter to explicitly set the target process's current directory.
For example, to start the target process from the directory in which a target script is located, you could use something like:
$script = 'c:\path\to\your\script.ps1'
Start-Process -WorkingDirectory (Split-Path $script) -Credential ...

Entering password automatically in enter-pssession

Im currently making a Powershell Script in Powershell ISE that is going to be used for entering all of the servers we're hosting and grabbing all the users from the servers ActiveDirectory. To do that I have to connect to all servers automatically (There are many servers but only 42 that we need to access). Let me explain what I've done so far and what te actual problem is.
So as you know there are many different servers, so we had to read all the server IP:S/Usernames/Passwords from a excel file that a colleague made, and then place them into arrays.
From there, we made a for loop looking like this:
for ($S = 0; $ -le $ServerAdressArray.Length; $S++)
{
if ($ServerAdressArray[$S] -like '192.168.*.10')
{
GetData($S)
}
}
What it does is going through the array filtering out all the local IP-Adresses from the array, if it finds a local ip adress, it runs the GetData function which looks like this at the moment:
function GetData([int]$arg1)
{
Enter-PSsession -ComputerName $ServerAdressArray[$arg1] -Credential $UsernamesArray[$arg1] $PasswordArray[$arg1]
}
What I want it to do is to use the row number it found the local IP-Adress on and then use that number to locate the correct Username and Password to log in with on that specific server.
The problem is, i have to enter the password in powershell for every single server. And i just want to enter it on the same line as Enter-PSSession.
If you want more specific details, let me know. Also, I'm new to this type of scripting so if you cold be as basic as possible in your explanations that would be great :)
Thank you.
The problem here is how you're passing the "Credential" parameter. It should be of type PSCredential.
Assuming you've stored the username and password in clear text in your file you can create a credential object directly:
New-Object PSCredential -ArgumentList #("a", ("p"|ConvertTo-SecureString -AsPlainText -Force))
For your example :
Enter-PSsession -ComputerName $ServerAdressArray[$arg1] -Credential (New-object PSCredential -ArgumentList #($UsernamesArray[$arg1], ($PasswordArray[$arg1]|ConvertTo-secureString -AsPlainText -Force)))
However; if you're interested in returning some data for each server back to the executing host (e.g. for further processing) you wouldn't want to enter the session, you would want to use Invoke-command instead.
E.g.
Invoke-command -ComputerName $ServerAdressArray[$arg1] -Credential (New-object PSCredential -ArgumentList #($UsernamesArray[$arg1], ($PasswordArray[$arg1]|ConvertTo-secureString -AsPlainText -Force))) -Scriptblock $scriptblockToExecute
Hi CmdrTchort/Richard (:P). Thank you for the answer!
All the passwords in the excelfile are encrypted for security reasons. I am currently working on a function that will decrypt the password before using it.
I've looked around a bit more on the internet and i stumbled across this post:
Using PowerShell credentials without being prompted for a password
I tried what Jeroen Landheer said and the function now looks like this:
function GetData(int[$arg1])
{
$secstr = New-Object -TypeName System.Security.Securestring
$PasswordArray[$arg1].ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr
$session = new-pssession -computername $ServerAdressArray[$arg1] -credential $UserNameArray[$arg1] $PasswordArray[$arg1]
}
The Prompt is appearing so the password hasn't automatically been filled in and when i close the prompt(s). I get this error:
New-PSSession : A positional parameter cannot be found that accepts argument '(encryptedpassword)'.
At C:\xxxxxxx\xxxxx\xxxxxx\superfile.ps1:109 char:16
+ ... $session = new-pssession -computername $ServerAdressArray[$arg1] -cr ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [New-PSSession], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.NewPSSessionCommand
Do I have to enter some kind of positional parameter or does it now work because its encrypted?

Error uploading file to FTP Server

I'm trying to use FTP to upload a file to an FTP server. I found the following script online, but I can't get it to work.
$UserName = 'username'
$Password = 'password'
$LocalFilePath = 'c:\FolderName\x.txt'
$RemoteFileName = 'x.txt'
$ServerName = 'my.ftpserver.co.uk'
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($UserName, $Password)
#Connect to FTP
$uri = New-Object System.Uri(“ftp://$ServerName/$RemoteFileName”)
write-host $uri
#upload as file
$webclient.UploadFile($uri, $LocalFilePath)
But when I run this I get the following error:
Exception calling "UploadFile" with "2" argument(s): "An exception occurred during a WebClient request."
At line:21 char:22
+ $webclient.UploadFile <<<< ($uri, $LocalFilePath)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Can anyone point me in the right direction?
I can connect using Filezilla etc from my PC, so it's not blocked by the firewall or anything,
Tested your script and it runs fine, only way I'm able to reproduce your error is if I point $LocalFilePath to a file that doesn't exist. Could you try:
Test-Path($LocalFilePath)
And see if it returns True?
From your comment and the code I see in the question the issue could just be the fact that you have smart quotes in there. It would be a product of your coding editor or the source of copying and paste that code into your environment. You need to watch out for these things. Assuming the paths are correctly formed perhaps that is just your issue.
Smart Quotes
$uri = New-Object System.Uri(“ftp://$ServerName/$RemoteFileName”)
Proper double quotes
$uri = New-Object System.Uri("ftp://$ServerName/$RemoteFileName")
The quotes in the second example are the ones you should use.

powershell credential rejected from server

I need to store credential in powershell to be used several times. Here on StackOverflow there are a lot of example, so I took one
$tmpCred = Get-Credential
$tmpCred.Password | ConvertFrom-SecureString | Set-Content "pwd.dat"
$password = Get-Content "pwd.dat" | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PsCredential "myDomain\myUser", $password
Get-ADUser -Credential $credential
Unfortunately I get this error and I can't find a solution
Get-ADUser : The server has rejected the client credentials.
At line:5 char:11
+ Get-ADUser <<<< "xxx" -Credential $credential
+ CategoryInfo : NotSpecified: (xxx:ADUser) [Get-ADUser], AuthenticationException
+ FullyQualifiedErrorId : The server has rejected the client credentials.,Microsoft.ActiveDirectory.Management.Commands.GetADUser
I can't see anything obviously wrong with your code, I'm guessing that this is just an example of how you are using it as you mention you need to use it in several places. Just to check that it really is the storing of the secure string failing you could check using the following, which should prove that the credentials worked before being persisted to disk:
Get-ADUser -Credential $tmpCred
One option would be to pass around the credentials rather than a file or securestring, using the type [System.Management.Automation.PSCredential] which is returned from your call to Get-Credentials and stored in the variable $tmpCred.
You could also temporarily add a call to the method GetNetworkCredentials() to ensure that your password has been decrypted correctly, the following will show the username and password (unencrypted):
$tmpCred.GetNetworkCredential().Username
$tmpCred.GetNetworkCredential().Password
Hope that helps...

Categories