Upload fra et fildrev til SharePoint Online med PowerShell
Et planlagt PnP PowerShell-script, der flytter filer fra et netværksdrev til et dokumentbibliotek, logger hvert trin og kun sletter kilden, når uploaden er gået igennem.
Et gammelt system lægger filer på et netværksdrev hver nat — rapporter, eksporter, PDF’er — og de skal ind i et dokumentbibliotek i SharePoint Online. Så længe nogen gør det i hånden hver morgen, bliver filer glemt eller lagt op to gange. Det her script kører som planlagt opgave: det finder filerne på drevet, lægger dem i biblioteket, sletter hver fil fra drevet, når den er oppe, og skriver det hele i en daglig logfil.
Scheduled Task → PowerShell Script → Connect to SharePoint (App Auth) → Scan File Share → Upload Files → Delete Local Copies → Write Logs → Exit
Forbindelsen i dag#
Scriptet herunder logger ind med klient-id og klienthemmelighed (-ClientId og -ClientSecret). I PnP PowerShell er det ACS-login, og Azure ACS holdt op med at virke for SharePoint Online den 2. april 2026. For nye tenants har det været slået fra siden november 2024. Som det står, kan scriptet altså ikke længere forbinde.
Det, der virker, er en app-registrering i Entra ID med et certifikat. Forbindelseslinjen i Get-SharePoint-Connection bliver da:
1$connection = Connect-PnPOnline -Url $global:sharePointSite `
2 -ClientId $global:sharepointClient `
3 -Tenant "<tenant>.onmicrosoft.com" `
4 -Thumbprint "<certifikat-thumbprint>" `
5 -ReturnConnection
-Thumbprint finder certifikatet i Windows’ certifikatlager hos den konto, opgaven kører som. Alternativet er -CertificatePath og -CertificatePassword med en .pfx-fil. $global:sharepointClientSecret bliver så overflødig.
Forudsætninger#
PnP PowerShell. På en maskine med internet:
1# Install for current user
2Install-Module -Name PnP.PowerShell -Scope CurrentUser -Force
3
4# Verify installation
5Get-Module -Name PnP.PowerShell -ListAvailable
På en server uden internet hentes modulet på en anden maskine, kopieres over og importeres fra mappen:
1Save-Module -Name PnP.PowerShell -Path "C:\Temp\PnPModules"
1Import-Module -Name "D:\Scripts\external-modules\PnP.PowerShell" -Verbose
PnP.PowerShell 2.x og nyere kræver PowerShell 7, ikke Windows PowerShell 5.1.
App-registrering i Entra ID.
- App registrations → New registration. Navn fx
SharePoint File Upload Automation, Single tenant, ingen redirect-URI. - API permissions → Add a permission → SharePoint → Application permissions →
Sites.ReadWrite.All, og Grant admin consent. - Certificates & secrets → upload certifikatets offentlige del (
.cer). Den private nøgle bliver på serveren. - Notér Application (client) ID og tenant-id’et fra oversigten.
Sites.ReadWrite.All giver adgang til alle websteder i tenanten. Skal appen kun kunne skrive ét sted, er det Sites.Selected i stedet, og så gives adgangen pr. websted:
1Grant-PnPAzureADAppSitePermission -AppId "<klient-id>" -DisplayName "SharePoint File Upload Automation" -Site "https://<tenant>.sharepoint.com/sites/<websted>" -Permissions Write
Biblioteket. Et eksisterende bibliotek eller et nyt, fx “Uploaded Files”. Scriptet skal bruge den serverrelative sti, fx /sites/YourSite/UploadedFiles. Stien er den del af bibliotekets adresse, der kommer efter domænet — ikke visningsnavnet og ikke listedit.aspx?List={GUID}, som bibliotekets indstillinger viser.
Er indholdsgodkendelse slået til (Versioning settings → Content Approval), sættes $global:sharePointModerationEnabled til $true, og scriptet godkender filerne, når de lægges op.
Scriptet#
Upload-FilesToSharePoint.ps1:
1<#
2.SYNOPSIS
3 Automated file upload from network file share to SharePoint Online
4.DESCRIPTION
5 Monitors a network file share, uploads new files to SharePoint document library,
6 deletes successfully uploaded files, and maintains comprehensive logs.
7.EXAMPLE
8 .\Upload-FilesToSharePoint.ps1
9#>
10
11#---------------------------------------------------------------------------------------------------
12# Script Settings
13#---------------------------------------------------------------------------------------------------
14
15# File Share Configuration
16$global:localFolderPath = "\\fileserver\reports\daily"
17
18# SharePoint Configuration
19$global:sharePointSite = "https://yourtenant.sharepoint.com/sites/yoursite"
20$global:sharepointServerRelativeDocumentLibraryPath = "/sites/yoursite/UploadedFiles"
21$global:sharePointModerationEnabled = $false # Set to $true if content approval enabled
22
23# Azure AD App Authentication
24$global:sharepointClient = "YOUR-CLIENT-ID-HERE"
25$global:sharepointClientSecret = "YOUR-CLIENT-SECRET-HERE"
26
27# Logging Configuration
28$global:runningFolderPath = Convert-Path "."
29$global:logPath = ""
30$global:keepLogFiles = 10 # Retain last 10 days of logs
31
32#---------------------------------------------------------------------------------------------------
33# Auxiliary Methods
34#---------------------------------------------------------------------------------------------------
35
36function Ensure-Structure($date) {
37 <#
38 .SYNOPSIS
39 Creates log directory structure and manages log retention
40 #>
41 try {
42 $global:logPath = "$($global:runningFolderPath)\logs"
43 New-Item -ItemType Directory -Force -Path $global:logPath | Out-Null
44
45 $file = "$($date.ToString("yyyyMMdd")).log"
46 $global:logFilePath = "$($global:logPath)\$($file)"
47
48 # Log rotation - delete old log files
49 $logFiles = Get-ChildItem $global:logPath | Sort-Object FullName -Descending
50 if ($logFiles -ne $null -and $logFiles.Length -gt $global:keepLogFiles) {
51 $exclude = $logFiles | Select-Object -Skip $global:keepLogFiles
52
53 foreach ($current in $exclude) {
54 try {
55 Remove-Item -Path $current.FullName -Force
56 Write-Verbose "Deleted old log file: $($current.Name)"
57 }
58 catch {
59 Write-Warning "Failed to delete old log file: $($current.Name)"
60 }
61 }
62 }
63
64 return $true
65 }
66 catch {
67 Write-Error "Failed to ensure log structure: $_"
68 return $false
69 }
70}
71
72function Log-Entry([string]$message, [string]$type) {
73 <#
74 .SYNOPSIS
75 Writes log entry to file and console with timestamp and severity
76 #>
77 try {
78 if ([string]::IsNullOrEmpty($type)) {
79 $type = "INFO"
80 }
81 else {
82 $type = $type.ToUpper()
83 }
84
85 $logMessage = "$((Get-Date).ToString("yyyy-MM-dd HH:mm:ss")) :: $($type) :: $($message)"
86
87 switch ($type) {
88 "ERROR" {
89 Write-Host $logMessage -ForegroundColor Red
90 Add-Content -Path $global:logFilePath -Value $logMessage
91 }
92 "WARNING" {
93 Write-Host $logMessage -ForegroundColor Yellow
94 Add-Content -Path $global:logFilePath -Value $logMessage
95 }
96 "SUCCESS" {
97 Write-Host $logMessage -ForegroundColor Green
98 Add-Content -Path $global:logFilePath -Value $logMessage
99 }
100 default {
101 Write-Host $logMessage -ForegroundColor White
102 Add-Content -Path $global:logFilePath -Value $logMessage
103 }
104 }
105 }
106 catch {
107 Write-Error "Failed to write log entry: $_"
108 }
109}
110
111#---------------------------------------------------------------------------------------------------
112# SharePoint Methods
113#---------------------------------------------------------------------------------------------------
114
115function Get-SharePoint-Connection {
116 <#
117 .SYNOPSIS
118 Establishes connection to SharePoint Online using app-only authentication
119 #>
120 try {
121 Log-Entry "Connecting to SharePoint Online: $($global:sharePointSite)" "INFO"
122
123 $connection = Connect-PnPOnline -Url $global:sharePointSite `
124 -ClientId $global:sharepointClient `
125 -ClientSecret $global:sharepointClientSecret `
126 -ReturnConnection
127
128 $web = Get-PnPWeb -Connection $connection
129
130 if ($web -ne $null) {
131 Log-Entry "Connected successfully to: $($web.Url)" "SUCCESS"
132 return $connection
133 }
134 else {
135 Log-Entry "Connection failed - web object is null" "WARNING"
136 Disconnect-PnPOnline
137 return $null
138 }
139 }
140 catch {
141 Log-Entry "SharePoint connection error: $($_.Exception.Message)" "ERROR"
142 return $null
143 }
144}
145
146function Upload-File-To-SharePoint($connection, $filePath, $fileName) {
147 <#
148 .SYNOPSIS
149 Uploads a single file to SharePoint document library
150 #>
151 try {
152 if ($global:sharePointModerationEnabled -eq $true) {
153 # Upload and auto-approve if moderation enabled
154 Add-PnPFile -Path $filePath `
155 -Folder $global:sharepointServerRelativeDocumentLibraryPath `
156 -Publish `
157 -PublishComment "Auto-uploaded by scheduled task" `
158 -Connection $connection | Out-Null
159 }
160 else {
161 # Standard upload
162 Add-PnPFile -Path $filePath `
163 -Folder $global:sharepointServerRelativeDocumentLibraryPath `
164 -Connection $connection | Out-Null
165 }
166
167 Log-Entry "Upload successful: $fileName" "SUCCESS"
168 return $true
169 }
170 catch {
171 Log-Entry "Upload failed for $fileName - $($_.Exception.Message)" "ERROR"
172 return $false
173 }
174}
175
176#---------------------------------------------------------------------------------------------------
177# File Operations
178#---------------------------------------------------------------------------------------------------
179
180function Get-Files-To-Upload($folderPath) {
181 <#
182 .SYNOPSIS
183 Scans local folder and returns list of files to upload
184 #>
185 try {
186 $array = @()
187 Log-Entry "Scanning folder: $folderPath" "INFO"
188
189 if (-not (Test-Path $folderPath)) {
190 Log-Entry "Folder path does not exist: $folderPath" "WARNING"
191 return $array
192 }
193
194 $files = Get-ChildItem -Path $folderPath -File
195
196 if ($files.Count -eq 0) {
197 Log-Entry "No files found in folder" "INFO"
198 return $array
199 }
200
201 foreach ($file in $files) {
202 $data = [PSCustomObject]@{
203 FullPath = $file.FullName
204 Name = $file.Name
205 }
206 $array += $data
207 }
208
209 Log-Entry "Found $($array.Count) file(s) to upload" "INFO"
210 return $array
211 }
212 catch {
213 Log-Entry "Error scanning folder: $($_.Exception.Message)" "ERROR"
214 return @()
215 }
216}
217
218function Delete-Local-File($filePath) {
219 <#
220 .SYNOPSIS
221 Deletes file from local file share after successful upload
222 #>
223 try {
224 Remove-Item -Path $filePath -Force
225 Log-Entry "Deleted local file: $(Split-Path $filePath -Leaf)" "SUCCESS"
226 return $true
227 }
228 catch {
229 Log-Entry "Failed to delete: $(Split-Path $filePath -Leaf) - $($_.Exception.Message)" "ERROR"
230 return $false
231 }
232}
233
234function Upload-Files-To-SharePoint-And-Delete-Local($connection, $fileInfos) {
235 <#
236 .SYNOPSIS
237 Uploads multiple files and deletes them after successful upload
238 #>
239 try {
240 $successCount = 0
241 $failCount = 0
242
243 foreach ($fileInfo in $fileInfos) {
244 Log-Entry "Processing: $($fileInfo.Name)" "INFO"
245
246 $uploadSuccess = Upload-File-To-SharePoint $connection $fileInfo.FullPath $fileInfo.Name
247
248 if ($uploadSuccess -eq $true) {
249 $deleteSuccess = Delete-Local-File $fileInfo.FullPath
250 if ($deleteSuccess) {
251 $successCount++
252 }
253 }
254 else {
255 $failCount++
256 }
257 }
258
259 Log-Entry "Upload summary: $successCount successful, $failCount failed" "INFO"
260 }
261 catch {
262 Log-Entry "Batch upload error: $($_.Exception.Message)" "ERROR"
263 }
264}
265
266#---------------------------------------------------------------------------------------------------
267# Main Process
268#---------------------------------------------------------------------------------------------------
269
270function Start-Process {
271 <#
272 .SYNOPSIS
273 Main orchestration function
274 #>
275 try {
276 Log-Entry "-" * 100 "INFO"
277 Log-Entry "Upload process started" "INFO"
278 Log-Entry "Source: $($global:localFolderPath)" "INFO"
279 Log-Entry "Destination: $($global:sharePointSite)$($global:sharepointServerRelativeDocumentLibraryPath)" "INFO"
280
281 $fileInfos = Get-Files-To-Upload $global:localFolderPath
282
283 if ($fileInfos.Count -gt 0) {
284 $connection = Get-SharePoint-Connection
285
286 if ($connection -eq $null) {
287 Log-Entry "Cannot proceed without SharePoint connection" "ERROR"
288 return $false
289 }
290
291 Upload-Files-To-SharePoint-And-Delete-Local $connection $fileInfos
292
293 Disconnect-PnPOnline -Connection $connection
294 }
295 else {
296 Log-Entry "No files to process" "INFO"
297 }
298
299 return $true
300 }
301 catch {
302 Log-Entry "Process error: $($_.Exception.Message)" "ERROR"
303 return $false
304 }
305 finally {
306 Log-Entry "Upload process completed" "INFO"
307 Log-Entry "-" * 100 "INFO"
308 }
309}
310
311#---------------------------------------------------------------------------------------------------
312# Execution
313#---------------------------------------------------------------------------------------------------
314
315$ensured = Ensure-Structure (Get-Date)
316if ($ensured -eq $false) {
317 Write-Error "Failed to ensure log structure, exiting"
318 exit 1
319}
320
321$result = Start-Process
322if ($result -eq $false) {
323 Write-Error "Upload process failed, check logs at: $($global:logFilePath)"
324 exit 1
325}
326
327Write-Host "Process completed successfully" -ForegroundColor Green
328exit 0
Opsætning#
Variablerne øverst i scriptet:
1$global:localFolderPath = "\\fileserver\reports\daily"
1$global:sharePointSite = "https://contoso.sharepoint.com/sites/ProjectSite"
1$global:sharepointServerRelativeDocumentLibraryPath = "/sites/ProjectSite/Documents"
1$global:sharepointClient = "<klient-id>" # Your Client ID
2$global:sharepointClientSecret = "YOUR-SECRET-HERE" # Your Client Secret
1$global:sharePointModerationEnabled = $false # Set to $true if library uses content approval
Kør det i hånden først:
1# Navigate to script directory
2cd "D:\Scripts\SharePointUpload"
3
4# Run script
5.\Upload-FilesToSharePoint.ps1
6
7# Check log output
8Get-Content ".\logs\$(Get-Date -Format 'yyyyMMdd').log"
Loggen ser sådan ud, når det går:
2025-10-03 14:30:15 :: INFO :: Connecting to SharePoint Online: https://tenant.sharepoint.com/sites/site
2025-10-03 14:30:18 :: SUCCESS :: Connected successfully to: https://tenant.sharepoint.com/sites/site
2025-10-03 14:30:18 :: INFO :: Scanning folder: \\fileserver\reports\daily
2025-10-03 14:30:18 :: INFO :: Found 5 file(s) to upload
2025-10-03 14:30:19 :: SUCCESS :: Upload successful: report_20251003.pdf
2025-10-03 14:30:19 :: SUCCESS :: Deleted local file: report_20251003.pdf
...
2025-10-03 14:30:25 :: INFO :: Upload summary: 5 successful, 0 failed
Jeg prøver med én fil, så fem, så en hel nats portion.
Planlagt opgave#
I Task Scheduler → Create Basic Task: navn SharePoint File Upload, dagligt kl. 2, Start a program.
powershell.exe
-ExecutionPolicy Bypass -File "D:\Scripts\SharePointUpload\Upload-FilesToSharePoint.ps1"
D:\Scripts\SharePointUpload
Det er program, argumenter og Start in. Med PnP.PowerShell 2.x og nyere skal programmet være pwsh.exe, ikke powershell.exe. Opgaven skal køre whether user is logged on or not, med highest privileges, som en servicekonto, der både kan læse og slette på drevet og har certifikatet i sit lager.
1# Run task immediately to test
2Start-ScheduledTask -TaskName "SharePoint File Upload"
3
4# Check task status
5Get-ScheduledTask -TaskName "SharePoint File Upload" | Select-Object State, LastRunTime, LastTaskResult
6
7# View task history
8Get-ScheduledTaskInfo -TaskName "SharePoint File Upload"
Varianter#
Undermapper pr. måned. Filerne lægges i 2025-10/, 2025-11/ osv., og mappen oprettes, hvis den mangler:
1function Upload-File-To-SharePoint($connection, $filePath, $fileName) {
2 try {
3 # Create date-based subfolder
4 $dateFolder = (Get-Date).ToString("yyyy-MM")
5 $targetFolder = "$($global:sharepointServerRelativeDocumentLibraryPath)/$dateFolder"
6
7 # Ensure folder exists
8 Resolve-PnPFolder -SiteRelativePath $targetFolder -Connection $connection | Out-Null
9
10 # Upload to subfolder
11 Add-PnPFile -Path $filePath `
12 -Folder $targetFolder `
13 -Connection $connection | Out-Null
14
15 Log-Entry "Uploaded to $dateFolder folder: $fileName" "SUCCESS"
16 return $true
17 }
18 catch {
19 Log-Entry "Upload failed: $($_.Exception.Message)" "ERROR"
20 return $false
21 }
22}
Karantæne for fejlede filer. En fil, der ikke kom op, flyttes til en fejlmappe i stedet for at blive liggende og blive forsøgt igen hver nat:
1$global:errorFolderPath = "\\fileserver\reports\upload-errors"
2
3function Upload-Files-To-SharePoint-And-Delete-Local($connection, $fileInfos) {
4 foreach ($fileInfo in $fileInfos) {
5 $uploadSuccess = Upload-File-To-SharePoint $connection $fileInfo.FullPath $fileInfo.Name
6
7 if ($uploadSuccess -eq $true) {
8 Delete-Local-File $fileInfo.FullPath
9 }
10 else {
11 # Move to error folder for manual review
12 $errorPath = Join-Path $global:errorFolderPath $fileInfo.Name
13 Move-Item -Path $fileInfo.FullPath -Destination $errorPath -Force
14 Log-Entry "Moved failed file to error folder: $($fileInfo.Name)" "WARNING"
15 }
16 }
17}
Kun bestemte filtyper:
1function Get-Files-To-Upload($folderPath) {
2 $allowedExtensions = @(".pdf", ".docx", ".xlsx")
3 $array = @()
4
5 $files = Get-ChildItem -Path $folderPath -File | Where-Object {
6 $allowedExtensions -contains $_.Extension
7 }
8
9 foreach ($file in $files) {
10 $data = [PSCustomObject]@{
11 FullPath = $file.FullName
12 Name = $file.Name
13 }
14 $array += $data
15 }
16
17 Log-Entry "Found $($array.Count) eligible file(s) (filtered by extension)" "INFO"
18 return $array
19}
Metadata på filen. Kræver kolonnerne UploadSource (tekst), ProcessedDate (dato og tid) og SourceLocation (tekst) i biblioteket:
1function Upload-File-To-SharePoint($connection, $filePath, $fileName) {
2 try {
3 # Upload file
4 $uploadedFile = Add-PnPFile -Path $filePath `
5 -Folder $global:sharepointServerRelativeDocumentLibraryPath `
6 -Connection $connection
7
8 # Set metadata
9 Set-PnPListItem -List "Documents" `
10 -Identity $uploadedFile.ListItemAllFields.Id `
11 -Values @{
12 "UploadSource" = "Automated Script"
13 "ProcessedDate" = (Get-Date)
14 "SourceLocation" = $global:localFolderPath
15 } `
16 -Connection $connection
17
18 Log-Entry "Upload and metadata set: $fileName" "SUCCESS"
19 return $true
20 }
21 catch {
22 Log-Entry "Upload/metadata error: $($_.Exception.Message)" "ERROR"
23 return $false
24 }
25}
-List "Documents" skal være det bibliotek, der uploades til — i eksemplet her er det ikke. Add-PnPFile har også selv en -Values-parameter, så metadata kan sættes i samme kald.
Revisionsspor. En CSV-linje pr. fil ved siden af loggen:
1function Log-GDPR-Audit($fileName, $action) {
2 $auditEntry = [PSCustomObject]@{
3 Timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
4 FileName = $fileName
5 Action = $action
6 ProcessedBy = $env:COMPUTERNAME
7 SourcePath = $global:localFolderPath
8 }
9
10 $auditPath = "$($global:runningFolderPath)\audit-trail.csv"
11 $auditEntry | Export-Csv -Path $auditPath -Append -NoTypeInformation
12}
13
14# Call in upload function
15Log-GDPR-Audit $fileName "Uploaded to SharePoint and deleted from file share"
Flyt til arkiv i stedet for at slette, når kontoen ikke må slette på drevet:
1function Archive-Local-File($filePath) {
2 $archivePath = "\\fileserver\reports\archive"
3 $fileName = Split-Path $filePath -Leaf
4 Move-Item -Path $filePath -Destination (Join-Path $archivePath $fileName) -Force
5 Log-Entry "Moved to archive: $fileName" "SUCCESS"
6}
Mange filer. I portioner af 100 med en pause imellem, så SharePoint ikke begynder at svare 429:
1# Process files in batches of 100
2$batchSize = 100
3for ($i = 0; $i -lt $fileInfos.Count; $i += $batchSize) {
4 $batch = $fileInfos[$i..([Math]::Min($i + $batchSize - 1, $fileInfos.Count - 1))]
5 Upload-Files-To-SharePoint-And-Delete-Local $connection $batch
6 Start-Sleep -Seconds 5 # Throttle protection
7}
Besked, når det er kørt:
1function Send-Completion-Email($successCount, $failCount) {
2 Send-MailMessage -From "noreply@company.com" `
3 -To "it@company.com" `
4 -Subject "SharePoint Upload: $successCount succeeded, $failCount failed" `
5 -Body (Get-Content $global:logFilePath | Out-String) `
6 -SmtpServer "smtp.company.com"
7}
1Write-EventLog -LogName Application `
2 -Source "SharePoint Upload" `
3 -EventId 1001 `
4 -EntryType Information `
5 -Message "Uploaded $successCount files successfully"
Send-MailMessage er forældet og kan ikke logge ind mod Exchange Online med moderne godkendelse. Write-EventLog findes kun i Windows PowerShell 5.1, og kilden skal oprettes én gang med New-EventLog, før den kan bruges.
Fejlfinding#
“Cannot bind argument to parameter ‘Path’ because it is null”. Drevet kan ikke nås eller er tomt. Prøv som servicekontoen:
1# Test file share access
2Test-Path "\\fileserver\reports\daily"
3
4# Check permissions
5Get-Acl "\\fileserver\reports\daily" | Format-List
6
7# Test as service account
8runas /user:DOMAIN\ServiceAccount powershell.exe
9Test-Path "\\fileserver\reports\daily"
“AADSTS7000215: Invalid client secret provided”. Hemmeligheden er udløbet eller forkert. Med certifikat er det tilsvarende et udløbet certifikat — datoen står under Certificates & secrets.
“Access denied. You do not have permission”. Tilladelsen mangler, eller admin-samtykket er ikke givet. Virker det med en almindelig bruger, er det appens rettigheder, der er problemet:
1Connect-PnPOnline -Url $siteUrl -Interactive
2Add-PnPFile -Path $file -Folder $folder
-Interactive kræver i dag også en app-registrering (-ClientId), fordi PnP’s egen fælles app er fjernet. Den gamle vej med appinv.aspx og AllowAppOnlyPolicy er ACS og virker ikke længere. Rettigheder til ét websted gives med Sites.Selected som ovenfor.
“Cannot find path ‘\fileserver\reports’”. UNC-stien kan ikke nås fra opgavens kontekst. Et drevbogstav i scriptet eller et eksplicit login:
1New-PSDrive -Name "Z" -PSProvider FileSystem -Root "\\fileserver\reports" -Persist
2$global:localFolderPath = "Z:\daily"
1$netCred = New-Object System.Management.Automation.PSCredential("DOMAIN\User", (ConvertTo-SecureString "Password" -AsPlainText -Force))
2New-PSDrive -Name "Z" -PSProvider FileSystem -Root "\\fileserver\reports" -Credential $netCred
Bedst er det dog at lade opgaven køre som en konto, der har adgang til drevet, så der ikke står en adgangskode i scriptet.
Filerne kommer op, men bliver ikke slettet. Kontoen har ikke Delete eller Modify på drevet:
1# Check delete permissions
2$acl = Get-Acl "\\fileserver\reports\daily"
3$acl.Access | Where-Object { $_.IdentityReference -eq "DOMAIN\ServiceAccount" }
4
5# Verify required permission:
6# FileSystemRights should include "Delete" or "Modify"
Mappen i SharePoint findes ikke. Den serverrelative sti er forkert:
1# Test folder existence
2$folderPath = "/sites/sitename/LibraryName"
3Get-PnPFolder -Url $folderPath
Det der driller#
- Klienthemmeligheden er ACS, og ACS er væk (se øverst). Scriptet skal have et certifikat for at forbinde i dag.
Log-Entry "-" * 100 "INFO"skriver ikke en streg. PowerShell læser argumenterne som"-",*,100og"INFO", så beskeden bliver-og typen*. Det skal væreLog-Entry ("-" * 100) "INFO".- Funktionen
Start-Processskygger for PowerShells egen cmdlet af samme navn. Det virker i scriptet, men et andet navn, fxStart-Upload, undgår overraskelser. - Filerne slettes kun efter en upload, der gik igennem, men en fil, der har samme navn som en fil i biblioteket, overskrives uden videre.
Add-PnPFilespørger ikke. - Eksemplerne i originalen havde to ting, der ikke virker og er udeladt her:
Add-PnPFile -ChunkSizefindes ikke, ogForEach-Object -Parallelkan ikke se scriptets funktioner, fordi hver tråd har sin egen runspace. - Loggen roterer på antal filer, ikke på dage.
$global:keepLogFiles = 10er de ti nyeste logfiler, og der kommer kun en fil på de dage, scriptet har kørt. - Hemmeligheder hører ikke til i scriptet. Certifikatet ligger i servicekontoens lager. Skal der alligevel bruges en hemmelighed, ligger den i Azure Key Vault eller Windows Credential Manager.