I am using the following to connect to my SPO tenant and pull a report, however I am finding that the WebsCount parameter is not populating any subsites, has anyone encountered similar behavior and how to fix this bulk query?
Import-Module Microsoft.Online.SharePoint.Powershell -DisableNameChecking
#Config Parameters
$AdminSiteURL="https://SPTenant-admin.sharepoint.com"
$ReportOutput="C:\Temp\SPOStorage.csv"
#Get Credentials to connect to SharePoint Admin Center
$Cred = Get-Credential
#Connect to SharePoint Online Admin Center
Connect-SPOService -Url $AdminSiteURL –Credential $Cred
#Get all Site collections details and Export to CSV
Get-SPOSite -Limit ALL -Detailed | Export-Csv -Path $ReportOutput -NoTypeInformation
The following PowerShell for your reference.
Import-Module Microsoft.Online.SharePoint.Powershell -DisableNameChecking
#Config Parameters
$AdminSiteURL="https://tenant-admin.sharepoint.com"
$ReportOutput="C:\Temp\SPOStorage.csv"
#Get Credentials to connect to SharePoint Admin Center
$Cred = Get-Credential
#Connect to SharePoint Online Admin Center
Connect-SPOService -Url $AdminSiteURL –Credential $Cred
#Get All site collections
$SiteCollections = Get-SPOSite -Limit All
Write-Host "Total Number of Site collections Found:"$SiteCollections.count -f Yellow
#Array to store Result
$ResultSet = #()
#Loop through each site collection and retrieve details
Foreach ($Site in $SiteCollections)
{
Write-Host "Processing Site Collection :"$Site.URL -f Yellow
$Site=Get-SPOSite -identity $Site.Url -Limit ALL -Detailed
#Get site collection details
$Result = new-object PSObject
$Result | add-member -membertype NoteProperty -name "Title" -Value $Site.Title
$Result | add-member -membertype NoteProperty -name "Url" -Value $Site.Url
$Result | add-member -membertype NoteProperty -name "WebsCount" -Value $Site.WebsCount
$Result | add-member -membertype NoteProperty -name "LastContentModifiedDate" -Value $Site.LastContentModifiedDate
$Result | add-member -membertype NoteProperty -name "Status" -Value $Site.Status
$Result | add-member -membertype NoteProperty -name "LocaleId" -Value $Site.LocaleId
$Result | add-member -membertype NoteProperty -name "LockState" -Value $Site.LockState
$Result | add-member -membertype NoteProperty -name "StorageQuota" -Value $Site.StorageQuota
$Result | add-member -membertype NoteProperty -name "StorageQuotaWarningLevel" -Value $Site.StorageQuotaWarningLevel
$Result | add-member -membertype NoteProperty -name "Used" -Value $Site.StorageUsageCurrent
$Result | add-member -membertype NoteProperty -name "CompatibilityLevel" -Value $Site.CompatibilityLevel
$Result | add-member -membertype NoteProperty -name "Template" -Value $Site.Template
$Result | add-member -membertype NoteProperty -name "SharingCapability" -Value $Site.SharingCapability
$ResultSet += $Result
}
#Export Result to csv file
$ResultSet | Export-Csv $ReportOutput -notypeinformation
Write-Host "Site Quota Report Generated Successfully!" -f Green
Check the similar thread here: SiteProperties.WebsCount property is returning zero (CSOM)?
Related
I am stuck in the following script. The script below works fine to locate the user's team's group, email, and URL. We have recently discovered that some MS Teams contain MS Team Private Channels. We would also like to know if any of those teams (ms teams users are members of) have private channels, and download the name of the channel and the URL.
The following site shows how to find those private channels' URLs from the whole company.
https://pnp.github.io/script-samples/report-private-teams-excel/README.html?tabs=pnpps
But I only need the private channel URL from specific sites.
Can anyone help me please?
Thank you
Connect-ExchangeOnline
Connect-MicrosoftTeams
$CustodianTeams = Read-Host -Prompt "Enter the user ID and #domain. i.e, UserID#Microsoft.com"
$Custodianteams = $CustodianTeams -replace '(^\s+|\s+$)','' -replace '\s+',' '
$TeamIDs = Get-Team -User $CustodianTeams
foreach ($TeamID in $TeamIDs) {
Get-UnifiedGroup -Identity $TeamID.GroupID | select DisplayName, PrimarySmtpAddress, SharePointSiteUrl | Export-Csv .\$CustodianTeams.csv -Append
}
Please refer below steps:
First install and connect:
Install-Module PowerShellGet -RequiredVersion 2.2.4.1
Install-Module -Name MicrosoftTeams -RequiredVersion 3.0.0
Connect-MicrosoftTeams
Then:
1. Copy the ps1 file to your downloads folder
2. cd C:\Users\username\Downloads
3. .\TeamsChannelMemberReport.ps1
Choose option 2 to export all and it will export to downloads.
Save this as TeamsChannelMemberReport.ps1:
<#
.Requires -version 2 - Connect-MicrosoftTeams and then Run the script in Powershell
.SYNOPSIS
.\TeamsChannelMemberReport.ps1 - It Can Display all the Teams and its Channels and its members on a List
Or It can Export to a CSV file
With Export of Specific teams
Example 1
PS C:\Scripts> .\TeamsChannelMemberReportv1.0.ps1
Teams Channel Member Report
----------------------------
1.Display in Microsoft Teams Shell
2.Export to CSV File
3.Display Specific Microsoft Team in Shell
4.Export Specific Microsoft Team to CSV File
Choose The Task: 1
User SMTP Address Role Channel DisplayName Team DisplayName
----------------- ---- ------------------- ----------------
Email address removed Owner General Teams_Azure365pro
Email address removed Member General Teams_Azure365pro
Email address removed Member General Teams_Azure365pro
Email address removed Owner General Teams_Azure365pro
Email address removed Member General Teams_Azure365pro
Email address removed Member General Teams_Azure365pro
Email address removed Owner General InformationTec...
Email address removed Member General InformationTec...
Email address removed Owner ServiceDesk Team InformationTec...
Email address removed Owner Infrastructure Team InformationTec...
Example 2
PS C:\Scripts> .\TeamsChannelMemberReportv1.0.ps1
Teams Channel Member Report
----------------------------
1.Display in Microsoft Teams Shell
2.Export to CSV File
3.Display Specific Microsoft Team in Shell
4.Export Specific Microsoft Team to CSV File
Choose The Task: 2
Enter the Path of CSV file (Eg. C:\Teams.csv): c:\teams.csv
#>
Write-host "
Teams Channel Member Report
----------------------------
1.Display in Microsoft Teams Shell
2.Export to CSV File
3.Display Specific Microsoft Team in Shell
4.Export Specific Microsoft Team to CSV File"-ForeGround "Cyan"
#----------------
# Script
#----------------
Write-Host " "
$number = Read-Host "Choose The Task"
$output = #()
switch ($number)
{
1 {
$i = 0
$AllTeams = Get-Team
Foreach ($Team in $AllTeams)
{
$AllChannels = Get-TeamChannel -GroupID $Team.GroupID
Foreach ($Channel in $AllChannels)
{
$AllMembers = Get-TeamChannelUser -GroupId $Team.GroupID -DisplayName $channel.DisplayName
Foreach ($member in $AllMembers)
{
$userObj = New-Object PSObject
$userObj | Add-Member NoteProperty -Name "User SMTP Address" -Value $member.User
$userObj | Add-Member NoteProperty -Name "Role" -Value $member.role
$userObj | Add-Member NoteProperty -Name "Channel DisplayName" -Value $Channel.DisplayName
$userObj | Add-Member NoteProperty -Name "Team DisplayName" -Value $Team.DisplayName
$output += $UserObj
}
}
# update counters and write progress
$i++
Write-Progress -activity "Scanning Teams . . .Channels . . . Members" -status "Scanned: $i of $($AllTeams.Count)" -percentComplete (($i / $AllTeams.Count) * 100)
Write-Output $Output
}
;Break}
2 {
$i = 0
$CSVfile = Read-Host "Enter the Path of CSV file (Eg. C:\Teams.csv)"
$AllTeams = Get-Team
Foreach ($Team in $AllTeams)
{
$AllChannels = Get-TeamChannel -GroupID $Team.GroupID
Foreach ($Channel in $AllChannels)
{
$AllMembers = Get-TeamChannelUser -GroupId $Team.GroupID -DisplayName $channel.DisplayName
Foreach ($member in $AllMembers)
{
$userObj = New-Object PSObject
$userObj | Add-Member NoteProperty -Name "DisplayName" -Value $member.Name
$userObj | Add-Member NoteProperty -Name "UserId" -Value $member.UserId
$userObj | Add-Member NoteProperty -Name "User SMTP Address" -Value $member.User
$userObj | Add-Member NoteProperty -Name "Role" -Value $member.role
$userObj | Add-Member NoteProperty -Name "Channel DisplayName" -Value $Channel.DisplayName
$userObj | Add-Member NoteProperty -Name "Channel Description" -Value $Channel.Description
$userObj | Add-Member NoteProperty -Name "Channel MembershipType" -Value $Channel.MembershipType
$userObj | Add-Member NoteProperty -Name "Team GroupID" -Value $Team.GroupId
$userObj | Add-Member NoteProperty -Name "Team DisplayName" -Value $Team.DisplayName
$userObj | Add-Member NoteProperty -Name "Team Description" -Value $Team.Description
$userObj | Add-Member NoteProperty -Name "Team Visibility" -Value $Team.Visibility
$userObj | Add-Member NoteProperty -Name "Team MailNickName" -Value $Team.MailNickName
$userObj | Add-Member NoteProperty -Name "Team Classification" -Value $Team.Classification
$userObj | Add-Member NoteProperty -Name "Team Archived" -Value $Team.Archived
$userObj | Add-Member NoteProperty -Name "Team AllowGiphy" -Value $Team.AllowGiphy
$userObj | Add-Member NoteProperty -Name "Team GiphyContentRating" -Value $Team.GiphyContentRating
$userObj | Add-Member NoteProperty -Name "Team AllowStickersAndMemes" -Value $Team.AllowStickersAndMemes
$userObj | Add-Member NoteProperty -Name "Team AllowGuestCreateUpdateChannels" -Value $Team.AllowGuestCreateUpdateChannels
$userObj | Add-Member NoteProperty -Name "Team AllowGuestDeleteChannels" -Value $Team.AllowGuestDeleteChannels
$userObj | Add-Member NoteProperty -Name "Team AllowCreateUpdateChannels" -Value $Team.AllowCreateUpdateChannels
$userObj | Add-Member NoteProperty -Name "Team AllowCreatePrivateChannels" -Value $Team.AllowCreatePrivateChannels
$userObj | Add-Member NoteProperty -Name "Team AllowDeleteChannels" -Value $Team.AllowDeleteChannels
$userObj | Add-Member NoteProperty -Name "Team AllowAddRemoveApps" -Value $Team.AllowAddRemoveApps
$userObj | Add-Member NoteProperty -Name "Team AllowCreateUpdateRemoveTabs" -Value $Team.AllowCreateUpdateRemoveTabs
$userObj | Add-Member NoteProperty -Name "Team AllowCreateUpdateRemoveConnectors" -Value $Team.AllowCreateUpdateRemoveConnectors
$userObj | Add-Member NoteProperty -Name "Team AllowUserEditMessages" -Value $Team.AllowUserEditMessages
$userObj | Add-Member NoteProperty -Name "Team AllowUserDeleteMessages " -Value $Team.AllowUserDeleteMessages
$userObj | Add-Member NoteProperty -Name "Team AllowOwnerDeleteMessages" -Value $Team.AllowOwnerDeleteMessages
$userObj | Add-Member NoteProperty -Name "Team AllowTeamMentions" -Value $Team.AllowTeamMentions
$userObj | Add-Member NoteProperty -Name "Team AllowChannelMentions" -Value $Team.AllowChannelMentions
$userObj | Add-Member NoteProperty -Name "Team ShowInTeamsSearchAndSuggestions" -Value $Team.ShowInTeamsSearchAndSuggestions
$output += $UserObj
}
}
# update counters and write progress
$i++
Write-Progress -activity "Scanning Teams . . .Channels . . . Members" -status "Scanned: $i of $($AllTeams.Count)" -percentComplete (($i / $AllTeams.Count) * 100)
$output | Export-csv -Path $CSVfile -NoTypeInformation -Encoding UTF8
}
;Break}
3 {
$i = 0
$Teamname = Read-Host "Enter the Team Display name or Range (Eg. Teamname , Team*,*Team)"
$AllTeams = Get-Team | Where-object {$_.DisplayName -like $Teamname}
Foreach ($Team in $AllTeams)
{
$AllChannels = Get-TeamChannel -GroupID $Team.GroupID
Foreach ($Channel in $AllChannels)
{
$AllMembers = Get-TeamChannelUser -GroupId $Team.GroupID -DisplayName $channel.DisplayName
Foreach ($member in $AllMembers)
{
$userObj = New-Object PSObject
$userObj | Add-Member NoteProperty -Name "User SMTP Address" -Value $member.User
$userObj | Add-Member NoteProperty -Name "Role" -Value $member.role
$userObj | Add-Member NoteProperty -Name "Channel DisplayName" -Value $Channel.DisplayName
$userObj | Add-Member NoteProperty -Name "Team DisplayName" -Value $Team.DisplayName
$output += $UserObj
}
}
# update counters and write progress
$i++
Write-Progress -activity "Scanning Teams . . .Channels . . . Members" -status "Scanned: $i of $($AllTeams.Count)" -percentComplete (($i / $AllTeams.Count) * 100)
Write-Output $Output
}
;Break}
4 {
$i = 0
$CSVfile = Read-Host "Enter the Path of CSV file (Eg. C:\Teams.csv)"
$Teamname = Read-Host "Enter the Team Display name or Range (Eg. Teamname , Team*,*Team)"
$AllTeams = Get-Team | Where-object {$_.DisplayName -like $Teamname}
Foreach ($Team in $AllTeams)
{
$AllChannels = Get-TeamChannel -GroupID $Team.GroupID
Foreach ($Channel in $AllChannels)
{
$AllMembers = Get-TeamChannelUser -GroupId $Team.GroupID -DisplayName $channel.DisplayName
Foreach ($member in $AllMembers)
{
$userObj = New-Object PSObject
$userObj | Add-Member NoteProperty -Name "DisplayName" -Value $member.Name
$userObj | Add-Member NoteProperty -Name "UserId" -Value $member.UserId
$userObj | Add-Member NoteProperty -Name "User SMTP Address" -Value $member.User
$userObj | Add-Member NoteProperty -Name "Role" -Value $member.role
$userObj | Add-Member NoteProperty -Name "Channel DisplayName" -Value $Channel.DisplayName
$userObj | Add-Member NoteProperty -Name "Channel Description" -Value $Channel.Description
$userObj | Add-Member NoteProperty -Name "Channel MembershipType" -Value $Channel.MembershipType
$userObj | Add-Member NoteProperty -Name "Team GroupID" -Value $Team.GroupId
$userObj | Add-Member NoteProperty -Name "Team DisplayName" -Value $Team.DisplayName
$userObj | Add-Member NoteProperty -Name "Team Description" -Value $Team.Description
$userObj | Add-Member NoteProperty -Name "Team Visibility" -Value $Team.Visibility
$userObj | Add-Member NoteProperty -Name "Team MailNickName" -Value $Team.MailNickName
$userObj | Add-Member NoteProperty -Name "Team Classification" -Value $Team.Classification
$userObj | Add-Member NoteProperty -Name "Team Archived" -Value $Team.Archived
$userObj | Add-Member NoteProperty -Name "Team AllowGiphy" -Value $Team.AllowGiphy
$userObj | Add-Member NoteProperty -Name "Team GiphyContentRating" -Value $Team.GiphyContentRating
$userObj | Add-Member NoteProperty -Name "Team AllowStickersAndMemes" -Value $Team.AllowStickersAndMemes
$userObj | Add-Member NoteProperty -Name "Team AllowGuestCreateUpdateChannels" -Value $Team.AllowGuestCreateUpdateChannels
$userObj | Add-Member NoteProperty -Name "Team AllowGuestDeleteChannels" -Value $Team.AllowGuestDeleteChannels
$userObj | Add-Member NoteProperty -Name "Team AllowCreateUpdateChannels" -Value $Team.AllowCreateUpdateChannels
$userObj | Add-Member NoteProperty -Name "Team AllowCreatePrivateChannels" -Value $Team.AllowCreatePrivateChannels
$userObj | Add-Member NoteProperty -Name "Team AllowDeleteChannels" -Value $Team.AllowDeleteChannels
$userObj | Add-Member NoteProperty -Name "Team AllowAddRemoveApps" -Value $Team.AllowAddRemoveApps
$userObj | Add-Member NoteProperty -Name "Team AllowCreateUpdateRemoveTabs" -Value $Team.AllowCreateUpdateRemoveTabs
$userObj | Add-Member NoteProperty -Name "Team AllowCreateUpdateRemoveConnectors" -Value $Team.AllowCreateUpdateRemoveConnectors
$userObj | Add-Member NoteProperty -Name "Team AllowUserEditMessages" -Value $Team.AllowUserEditMessages
$userObj | Add-Member NoteProperty -Name "Team AllowUserDeleteMessages " -Value $Team.AllowUserDeleteMessages
$userObj | Add-Member NoteProperty -Name "Team AllowOwnerDeleteMessages" -Value $Team.AllowOwnerDeleteMessages
$userObj | Add-Member NoteProperty -Name "Team AllowTeamMentions" -Value $Team.AllowTeamMentions
$userObj | Add-Member NoteProperty -Name "Team AllowChannelMentions" -Value $Team.AllowChannelMentions
$userObj | Add-Member NoteProperty -Name "Team ShowInTeamsSearchAndSuggestions" -Value $Team.ShowInTeamsSearchAndSuggestions
$output += $UserObj
}
}
# update counters and write progress
$i++
Write-Progress -activity "Scanning Teams . . .Channels . . . Members" -status "Scanned: $i of $($AllTeams.Count)" -percentComplete (($i / $AllTeams.Count) * 100)
$output | Export-csv -Path $CSVfile -NoTypeInformation -Encoding UTF8
};
Break
}
Default {Write-Host "No matches found, Enter Options 1 or 2" -ForeGround "red"}
}
How to get all Web Applications with Content DB names from SharePoint 2013/2016 Farm using PowerShell CSOM?
simple one:
#Get all web applications sharepoint using powershell
$WebAppColl = Get-SPWebApplication
#Iterate through each web application
Foreach ($WebApp in $WebAppColl)
{
$Webapp.Url
}
#Or a one liner to loop through web applications
#Get-SPWebApplication | Select URL
#Read more: https://www.sharepointdiary.com/2016/01/get-all-web-applications-in-sharepoint-using-powershell.html#ixzz7JoRyZrx8
with more data:
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
#Configuration Parameters
$ReportOutput= "C:\WebApplications-Report.csv"
$DataCollection = #()
#Get all web applications sharepoint using powershell
$WebAppColl = Get-SPWebApplication
Foreach ($WebApp in $WebAppColl)
{
#Determine the Authentication Type of the web application
if ($WebApp.UseClaimsAuthentication) { $AuthticationTYpe = "Claims"} else {$AuthticationTYpe = "Classic" }
#Get All Managed Paths of the web application
$ManagedPaths =(Get-SPManagedPath -WebApplication $WebApp | Select -ExpandProperty Name) -join ","
$WebAppData = new-object PSObject
$WebAppData | add-member -membertype NoteProperty -name "Web Application Name" -Value $WebApp.Name
$WebAppData | add-member -membertype NoteProperty -name "URL" -Value $WebApp.URL
$WebAppData | add-member -membertype NoteProperty -name "No.of Content Databases" -Value $WebApp.ContentDatabases.Count
$WebAppData | add-member -membertype NoteProperty -name "Authentication Type" -Value $AuthticationTYpe
$WebAppData | add-member -membertype NoteProperty -name "Application Pool" -Value $WebApp.ApplicationPool.DisplayName
$WebAppData | add-member -membertype NoteProperty -name "Outgoing E-mail" -Value $WebApp.OutboundMailServiceInstance[0].Server.Address
$WebAppData | add-member -membertype NoteProperty -name "Managed Paths" -Value $ManagedPaths
$DataCollection += $WebAppData
}
#Export Results to a CSV File
$DataCollection | Export-csv $ReportOutput -notypeinformation
Write-Host "Web Application Audit Report has been Generated!" -f Green
#Read more: https://www.sharepointdiary.com/2016/01/get-all-web-applications-in-sharepoint-using-powershell.html#ixzz7JoSCM4YG
more info - https://www.sharepointdiary.com/2016/01/get-all-web-applications-in-sharepoint-using-powershell.html
I am writing a small program in Powershell which connects to Office 365 to download audit logs, make some changes and then export a CSV to an Azure Data Lake Storage account. To run this process on a schedule, I have created an Azure Function app (timer template) to run the program. To avoid hard-coded credentials, I created an Azure Key Vault to store the credential secrets. I created a managed identity in the Azure Function, created the secrets in Azure Key Vault with the credentials and then created three application settings in Azure Function under "Configuration" with the URL to point at the secrets stored in Azure Key Vault.
The three application settings are called "SecretUsername", "SecretPassword" (to point to the Office 365) and "SecretSAS" (to store the CSV in ADLS).
How do I refer to these variables in my Powershell script? I have tried different variations in my code, but none appear to work. Examples:
$uSecret = $SecretUsername
$uSecret = $ENV:SecretUsername
$uSecret = ENV:SecretUsername
$uSecret = (Get-ChildItem ENV:SecretUsername).SecretValueText
# Input bindings are passed in via param block.
param($Timer)
# Get the current universal time in the default string format.
$currentUTCtime = (Get-Date).ToUniversalTime()
# The 'IsPastDue' property is 'true' when the current function invocation is later than scheduled.
if ($Timer.IsPastDue) {
Write-Host "PowerShell timer is running late!"
}
# Write an information log with the current time.
Write-Host "PowerShell timer trigger function ran! TIME: $currentUTCtime"
Set-ExecutionPolicy AllSigned
Set-Item ENV:\SuppressAzurePowerShellBreakingChangeWarnings "true"
$uSecret = (Get-ChildItem ENV:SecretUsername).SecretValueText
$pSecret = (Get-ChildItem ENV:SecretPassword).SecretValueText
$sasSecret = (Get-ChildItem ENV:SecretSAS).SecretValueText
$securePassword = ConvertTo-SecureString -String $pSecret -AsPlainText -Force
$UserCredential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $uSecret, $securePassword
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $session
$startDate=(get-date).AddDays(-10)
$endDate=(get-date)
$scriptStart=(get-date)
$sessionName = (get-date -Format 'u')+'pbiauditlog'
$aggregateResults = #()
$i = 0 # Loop counter
Do {
$currentResults = Search-UnifiedAuditLog -StartDate $startDate -EndDate $enddate -SessionId $sessionName -SessionCommand ReturnLargeSet -ResultSize 1000 -RecordType PowerBIAudit
if ($currentResults.Count -gt 0) {
Write-Host ("Finished {3} search #{1}, {2} records: {0} min" -f [math]::Round((New-TimeSpan -Start $scriptStart).TotalMinutes,4), $i, $currentResults.Count, $user.UserPrincipalName )
# Accumulate the data.
$aggregateResults += $currentResults
# No need to do another query if the # records returned <1000 - should save around 5-10 seconds per user.
if ($currentResults.Count -lt 1000) {
$currentResults = #()
} else {
$i++
}
}
} Until ($currentResults.Count -eq 0) # End of Session Search Loop.
$data=#()
foreach ($auditlogitem in $aggregateResults) {
$datum = New-Object -TypeName PSObject
$d = ConvertFrom-json $auditlogitem.AuditData
$datum | Add-Member -MemberType NoteProperty -Name Id -Value $d.Id
$datum | Add-Member -MemberType NoteProperty -Name CreationTDateTime -Value $d.CreationDate
$datum | Add-Member -MemberType NoteProperty -Name CreationTime -Value $d.CreationTime
$datum | Add-Member -MemberType NoteProperty -Name RecordType -Value $d.RecordType
$datum | Add-Member -MemberType NoteProperty -Name Operation -Value $d.Operation
$datum | Add-Member -MemberType NoteProperty -Name OrganizationId -Value $d.OrganizationId
$datum | Add-Member -MemberType NoteProperty -Name UserType -Value $d.UserType
$datum | Add-Member -MemberType NoteProperty -Name UserKey -Value $d.UserKey
$datum | Add-Member -MemberType NoteProperty -Name Workload -Value $d.Workload
$datum | Add-Member -MemberType NoteProperty -Name UserId -Value $d.UserId
$datum | Add-Member -MemberType NoteProperty -Name ClientIPAddress -Value $d.ClientIPAddress
$datum | Add-Member -MemberType NoteProperty -Name UserAgent -Value $d.UserAgent
$datum | Add-Member -MemberType NoteProperty -Name Activity -Value $d.Activity
$datum | Add-Member -MemberType NoteProperty -Name ItemName -Value $d.ItemName
$datum | Add-Member -MemberType NoteProperty -Name WorkSpaceName -Value $d.WorkSpaceName
$datum | Add-Member -MemberType NoteProperty -Name DashboardName -Value $d.DashboardName
$datum | Add-Member -MemberType NoteProperty -Name DatasetName -Value $d.DatasetName
$datum | Add-Member -MemberType NoteProperty -Name ReportName -Value $d.ReportName
$datum | Add-Member -MemberType NoteProperty -Name WorkspaceId -Value $d.WorkspaceId
$datum | Add-Member -MemberType NoteProperty -Name ObjectId -Value $d.ObjectId
$datum | Add-Member -MemberType NoteProperty -Name DashboardId -Value $d.DashboardId
$datum | Add-Member -MemberType NoteProperty -Name DatasetId -Value $d.DatasetId
$datum | Add-Member -MemberType NoteProperty -Name ReportId -Value $d.ReportId
$datum | Add-Member -MemberType NoteProperty -Name OrgAppPermission -Value $d.OrgAppPermission
# Option to include the below JSON column however for large amounts of data it may be difficult for PBI to parse
$datum | Add-Member -MemberType NoteProperty -Name Datasets -Value (ConvertTo-Json $d.Datasets)
# Below is a simple PowerShell statement to grab one of the entries and place in the DatasetName if any exist
foreach ($dataset in $d.datasets) {
$datum.DatasetName = $dataset.DatasetName
$datum.DatasetId = $dataset.DatasetId
}
$data+=$datum
}
$dateTimestring = $startDate.ToString("yyyyMMdd") + "_" + (Get-Date -Format "yyyyMMdd") + "_" + (Get-Date -Format "HHmm")
$fileName = ($dateTimestring + ".csv")
Write-Host ("Writing to file {0}" -f $fileName)
$filePath = "$Env:temp/" + $fileName
$data | Export-csv -Path $filePath
Connect-AzAccount -Credential $UserCredential
Get-AzVM -ResourceGroupName "Audit" -status
$Context = New-AzStorageContext -StorageAccountName "auditingstorage" -StorageAccountKey $sasSecret
Set-AzStorageBlobContent -Force -Context $Context -Container "auditlogs" -File $filePath -Blob $filename
Remove-PSSession -Id $Session.Id
How do I reference the application settings in Azure Function so that I can use the stored secrets in my program?
Please assist! Many thanks!
To access the app settings, keyvault or not, you must retrieve it trhough : $env:APPSETTING_YourSettingName
Thus, for your keyvault referenced secret, you would access it through the following variables.
$env:APPSETTING_SecretUserName
$env:APPSETTING_SecretPassword
$env:APPSETTING_SecretSAS
And if ever you need to produce a list of them.
Get-ChildItem env:APPSETTING_*
Note, the values returned will plain text unencrypted string.
Therefore, in your code, this:
$uSecret = (Get-ChildItem ENV:SecretUsername).SecretValueText
becomes that:
$uSecret = $env:APPSETTING_SecretUserName
Additional note
Since it was pointed out in the comments, I'll mention it.
I am not advocating the use of clear text secret in app settings at all.
App settings should be a keyvault referene for any sensitive data.
I am simply stating that it can be retrieved within the function at runtime as clear-text through the $env:APPSETTING_YourSettingName variable.
Example:
AppSetting name : MySecretUser
AppSetting value: #Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931)
Actual secret value (In the keyvault) : I_AM_Secret
At runtime, getting the value of $env:APPSETTING_MySecretUser will return a String Object with the value I_AM_Secret
I have a PowerShell script which downloads audit logs from Azure. The Export-CSV function outputs the file to my local computer. My plan however is to run this script every night using Azure Data Factory and then output the log file directly to Data Lake Storage, not locally.
ADF > PowerShell Script > Data Lake Storage
I need to amend this script so that it either outputs the CSV file directly to Data Lake Storage OR it outputs it so that ADF can channel it to a sink (Data Lake Storage).
Set-ExecutionPolicy RemoteSigned
#This is better for scheduled jobs
$User = "admin#M365XXXXXX.onmicrosoft.com"
$PWord = ConvertTo-SecureString -String "XXXXXXXX" -AsPlainText -Force
$UserCredential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User, $PWord
#This will prompt the user for credential
#$UserCredential = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $Session
$startDate=(get-date).AddDays(-5)
$endDate=(get-date)
$scriptStart=(get-date)
$sessionName = (get-date -Format 'u')+'pbiauditlog'
# Reset user audit accumulator
$aggregateResults = #()
$i = 0 # Loop counter
Do {
$currentResults = Search-UnifiedAuditLog -StartDate $startDate -EndDate $enddate -SessionId $sessionName -SessionCommand ReturnLargeSet -ResultSize 1000 -RecordType PowerBIAudit
if ($currentResults.Count -gt 0) {
Write-Host (" Finished {3} search #{1}, {2} records: {0} min" -f [math]::Round((New-TimeSpan -Start $scriptStart).TotalMinutes,4), $i, $currentResults.Count, $user.UserPrincipalName )
# Accumulate the data
$aggregateResults += $currentResults
# No need to do another query if the # recs returned <1k - should save around 5-10 sec per user
if ($currentResults.Count -lt 1000) {
$currentResults = #()
} else {
$i++
}
}
} Until ($currentResults.Count -eq 0) # --- End of Session Search Loop --- #
$data=#()
foreach ($auditlogitem in $aggregateResults) {
$d=convertfrom-json $auditlogitem.AuditData
$datum = New-Object –TypeName PSObject
$d=convertfrom-json $auditlogitem.AuditData
$datum | Add-Member –MemberType NoteProperty –Name Id –Value $d.Id
$datum | Add-Member –MemberType NoteProperty –Name CreationDateTime –Value $auditlogitem.CreationDate
$datum | Add-Member –MemberType NoteProperty –Name CreationTimeUTC –Value $d.CreationTime
$datum | Add-Member –MemberType NoteProperty –Name RecordType –Value $d.RecordType
$datum | Add-Member –MemberType NoteProperty –Name Operation –Value $d.Operation
$datum | Add-Member –MemberType NoteProperty –Name OrganizationId –Value $d.OrganizationId
$datum | Add-Member –MemberType NoteProperty –Name UserType –Value $d.UserType
$datum | Add-Member –MemberType NoteProperty –Name UserKey –Value $d.UserKey
$datum | Add-Member –MemberType NoteProperty –Name Workload –Value $d.Workload
$datum | Add-Member –MemberType NoteProperty –Name UserId –Value $d.UserId
$datum | Add-Member –MemberType NoteProperty –Name ClientIP –Value $d.ClientIP
$datum | Add-Member –MemberType NoteProperty –Name UserAgent –Value $d.UserAgent
$datum | Add-Member –MemberType NoteProperty –Name Activity –Value $d.Activity
$datum | Add-Member –MemberType NoteProperty –Name ItemName –Value $d.ItemName
$datum | Add-Member –MemberType NoteProperty –Name WorkSpaceName –Value $d.WorkSpaceName
$datum | Add-Member –MemberType NoteProperty –Name DashboardName –Value $d.DashboardName
$datum | Add-Member –MemberType NoteProperty –Name DatasetName –Value $d.DatasetName
$datum | Add-Member –MemberType NoteProperty –Name ReportName –Value $d.ReportName
$datum | Add-Member –MemberType NoteProperty –Name WorkspaceId –Value $d.WorkspaceId
$datum | Add-Member –MemberType NoteProperty –Name ObjectId –Value $d.ObjectId
$datum | Add-Member –MemberType NoteProperty –Name DashboardId –Value $d.DashboardId
$datum | Add-Member –MemberType NoteProperty –Name DatasetId –Value $d.DatasetId
$datum | Add-Member –MemberType NoteProperty –Name ReportId –Value $d.ReportId
$datum | Add-Member –MemberType NoteProperty –Name OrgAppPermission –Value $d.OrgAppPermission
#option to include the below JSON column however for large amounts of data it may be difficult for PBI to parse
#$datum | Add-Member –MemberType NoteProperty –Name Datasets –Value (ConvertTo-Json $d.Datasets)
#below is a PowerShell statement to grab one of the entries and place in the DatasetName if any exist
foreach ($dataset in $d.datasets) {
$datum.DatasetName = $dataset.DatasetName
$datum.DatasetId = $dataset.DatasetId
}
$data+=$datum
}
$datestring = $startDate.ToString("yyyyMMdd")
$fileName = ("C:\Users\Client\Audit Logging\Logs\" + $datestring + ".csv")
Write-Host ("Writing to file {0}" -f $fileName)
$data | Export-csv -Path $fileName
Remove-PSSession -Id $Session.Id
I did start writing some code to connect to Data Lake Storage as follows, but not sure how to integrate this with the above Export-CSV function. How do I get the CSV file to be published to Data Lake Storage (as it won't be stored locally) or output so that ADF can direct it to a sink store?
# Variable Declaration
$rgName = "Audit"
$subscriptionID = "dabdhnca9-0742-48b2-98d5-af476d62c6bd"
$dataLakeStoreName = "pbiauditingstorage12"
$myDataRootFolder = "/auditlogs"
#$sourceFilesPath = "C:\Users\Downloads\datasets\"
# Log in to your Azure account
Login-AzureRmAccount
# List all the subscriptions associated to your account
Get-AzureRmSubscription
# Select a subscription
Set-AzureRmContext -SubscriptionId $subscriptionID
# See if folder exists.
# If a folder or item does not exiss, then you will see
# Get-AzureRmDataLakeStoreChildItem : Operation returned an invalid status code 'NotFound'
Get-AzureRmDataLakeStoreChildItem -AccountName $dataLakeStoreName -Path $myDataRootFolder
# Create new folder
New-AzureRmDataLakeStoreItem -Folder -AccountName $dataLakeStoreName -Path $myDataRootFolder/population
# Upload folder and its contents recursively and force ovewrite existing
Import-AzureRmDataLakeStoreItem -AccountName $dataLakeStoreName `
-Path $sourceFilesPath\ `
-Destination $myDataRootFolder `
-Recurse `
-Force
Please advise, many thanks!
Managed to make it work after passing the exported file's path ($filepath) as the "-File" source parameter using Set-AzStorageBlobContent function:
$User = "sdcadmin#M36dcdcdc.onmicrosoft.com"
$PWord = ConvertTo-SecureString -String "eVadcdcdcR" -AsPlainText -Force
$UserCredential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User, $PWord
$dateTimestring = $startDate.ToString("yyyyMMdd") + "_" + (Get-Date -Format "yyyyMMdd") + "_" + (Get-Date -Format "HHmm")
$fileName = ($dateTimestring + ".csv")
Write-Host ("Writing to file {0}" -f $fileName)
$filePath = "$Env:temp/" + $fileName
$data | Export-csv -Path $filePath
# File transfer to Azure storage account
Connect-AzAccount -Credential $UserCredential
Get-AzVM -ResourceGroupName "Audit" -status
$Context = New-AzStorageContext -StorageAccountName "storageaccountname" -StorageAccountKey "sdfvsdvdsvsfvIdb6JgnnazfLIPDU8kOozDDn15262591efq5sdfvsdfv3M5ew=="
Set-AzStorageBlobContent -Force -Context $Context -Container "auditlogs" -File $filename -Blob $filename
Note – I am not a coding expert so please be gentle 😊 Any assistance/guidance much appreciated
Issue is that my pieced together Powershell script is not working as correctly. I am guessing it will take a coding guru two seconds to help resolve.
The basics of the script is that it performs a basic audit of a list of servers from a text file and outputs the results to a csv. For each server it will test WMI connection and if successful will collect columns of data i.e Name, IP Address, Uptime etc. If WMI connection fails then it should just log a few columns of data i.e. WMI Result, Ping Result etc All results should be piped to the same single output csv
The script works perfectly if the first server in the list’s WMI connection succeeds. All 16 x columns of csv output file are populated for every server in list.
WorkingExample
If the first server in the list’s WMI connection fails then the output fails. Only 4 x columns of csv output file are populated for every server in list.
FailingExample
Hopefully the screenshots of the output csv's help
Powershell Code below
<#
.DESCRIPTION - Auditing Script - Construction Phase !!!
- Create folder called 'Audit' under C:\Temp
- Create text file called 'Servers.txt' and place in newly created C:\Temp\Audit folder
- Servers.txt should contain a list of server names you wish to audit\target
.Author MCD
#>
########## Output Folder ##########
$outputFolderName = 'Audit ' + $(Get-Date -f dd-MM-yyyy)
$outputpath = "C:\temp\Audit\$outputFolderName"
If(!(test-path $outputpath))
{
New-Item -ItemType Directory -Force -Path $outputpath | out-null
}
########## Prompt 1 ##########
Add-Type -AssemblyName Microsoft.VisualBasic
$ClientName = [Microsoft.VisualBasic.Interaction]::InputBox('Please enter Client\Customer name i.e. Contoso Ltd', 'User')
Start-Sleep -s 2
#Manual Input File Location
$computers = Get-Content -path c:\temp\audit\Servers.txt
########## Create an Empty Array ##########
$report = #()
########## Main Start ##########
Foreach ($Computer in $Computers)
{
########## WMI/Ping Test ##########
$wmi = gwmi win32_bios -ComputerName $computer -ErrorAction SilentlyContinue
$Ping = Test-Connection -ComputerName $computer -Quiet -count 2
########## Main If Else Loop ##########
if ($wmi)
{
$WMIResult = 'Server IS Contactable'
########## HW/Serial No/Bios ##########
$Bios = Get-WmiObject -Class win32_bios -ComputerName $Computer
$systemBios = $Bios.serialnumber
$Hardware = Get-WmiObject -Class Win32_computerSystem -ComputerName $Computer
########## OS Version/Last Reboot ##########
$OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer
$lastBoot = $OS.ConvertToDateTime($OS.LastBootUpTime)
$uptimeDays = ((get-date) - ($os.ConvertToDateTime($os.lastbootuptime))).Days
########## Network Info ##########
$Networks = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -ComputerName $Computer | Where-Object {$_.IPEnabled}
$IPAddress = ($Networks.IpAddress | where {$_ -notmatch ":"}) -join "`n"
$MACAddress = ($Networks.MACAddress) -join "`n"
$IpSubnet = ($Networks.IpSubnet | ? { $_ -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}' }) -join "`n"
$DefaultGateway = ($Networks.DefaultIPGateway) -join "`n"
########## LastLogon/Created ##########
$LastLogonDate = Get-ADComputer $computer -Properties * | select -ExpandProperty LastLogonDate
$Created = Get-ADComputer $computer -Properties * | select -ExpandProperty Created
########## OUTPUT ##########
$tempreport = New-Object -TypeName PSObject
$tempreport | Add-Member -MemberType NoteProperty -Name ServerName -Value $Computer.ToUpper()
$tempreport | Add-Member -MemberType NoteProperty -Name Client_Customer -Value $ClientName.ToUpper()
$tempreport | Add-Member -MemberType NoteProperty -Name WMI_Connection -Value $WMIResult
$tempreport | Add-Member -MemberType NoteProperty -Name Pingable -Value $Ping
$tempreport | Add-Member -MemberType NoteProperty -Name Manufacturer -Value $Hardware.Manufacturer
$tempreport | Add-Member -MemberType NoteProperty -Name Model -Value $Hardware.Model
$tempreport | Add-Member -MemberType NoteProperty -Name Operating_System -Value $OS.Caption
$tempreport | Add-Member -MemberType NoteProperty -Name IP_Address -Value $IPAddress
$tempreport | Add-Member -MemberType NoteProperty -Name Default_Gateway -Value $DefaultGateway
$tempreport | Add-Member -MemberType NoteProperty -Name MAC_Address -Value $MACAddress
$tempreport | Add-Member -MemberType NoteProperty -Name IpSubnet -Value $IpSubnet
$tempreport | Add-Member -MemberType NoteProperty -Name Last_ReBoot -Value $lastboot
$tempreport | Add-Member -MemberType NoteProperty -Name Uptime_Days -Value $uptimeDays
$tempreport | Add-Member -MemberType NoteProperty -Name Last_Logon -Value $LastLogonDate
$tempreport | Add-Member -MemberType NoteProperty -Name Created -Value $Created
$tempreport | Add-Member -MemberType NoteProperty -Name Serial_Number -Value $systemBios
$report += $tempreport
} else {
$WMIResult = 'Server NOT Contactable'
$tempreport = New-Object PSObject
$tempreport | Add-Member -MemberType NoteProperty -Name ServerName -Value $Computer.ToUpper()
$tempreport | Add-Member -MemberType NoteProperty -Name Client_Customer -Value $ClientName.ToUpper()
$tempreport | Add-Member -MemberType NoteProperty -Name WMI_Connection -Value $WMIResult
$tempreport | Add-Member -MemberType NoteProperty -Name Pingable -Value $Ping
$report += $tempreport
}
}
########## EXPORT TO CSV ##########
$CSVFileName = $ClientName + ' Server Inventory ' + $(Get-Date -f dd-MM-yyyy) + '.csv'
$report | Export-Csv "$outputpath\$CSVFileName" -NoTypeInformation
<#
.END
#>
The issue is that the two objects you are creating don't contain the same properties. Arrays will report the information based on the properties in the first object. So if the first object fails, then all the others will report back the same four properties when the array is output.
My suggestion for dealing with this in the most simple way is to add the additional properties to the failing object, setting the values as $null. This should see that your CSV receives all the properties as intended.
<#
.DESCRIPTION - Auditing Script - Construction Phase !!!
- Create folder called 'Audit' under C:\Temp
- Create text file called 'Servers.txt' and place in newly created C:\Temp\Audit folder
- Servers.txt should contain a list of server names you wish to audit\target
.Author MCD
#>
########## Output Folder ##########
$outputFolderName = 'Audit ' + $(Get-Date -f dd-MM-yyyy)
$outputpath = "C:\temp\Audit\$outputFolderName"
If(!(test-path $outputpath)) {
New-Item -ItemType Directory -Force -Path $outputpath | out-null
}
########## Prompt 1 ##########
Add-Type -AssemblyName Microsoft.VisualBasic
$ClientName = [Microsoft.VisualBasic.Interaction]::InputBox('Please enter Client\Customer name i.e. Contoso Ltd', 'User')
Start-Sleep -s 2
#Manual Input File Location
$computers = Get-Content -path c:\temp\audit\Servers.txt
########## Create an Empty Array ##########
$report = #()
########## Main Start ##########
Foreach ($Computer in $Computers) {
########## WMI/Ping Test ##########
$wmi = gwmi win32_bios -ComputerName $computer -ErrorAction SilentlyContinue
$Ping = Test-Connection -ComputerName $computer -Quiet -count 2
########## Main If Else Loop ##########
if ($wmi) {
$WMIResult = 'Server IS Contactable'
########## HW/Serial No/Bios ##########
$Bios = Get-WmiObject -Class win32_bios -ComputerName $Computer
$systemBios = $Bios.serialnumber
$Hardware = Get-WmiObject -Class Win32_computerSystem -ComputerName $Computer
########## OS Version/Last Reboot ##########
$OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer
$lastBoot = $OS.ConvertToDateTime($OS.LastBootUpTime)
$uptimeDays = ((get-date) - ($os.ConvertToDateTime($os.lastbootuptime))).Days
########## Network Info ##########
$Networks = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -ComputerName $Computer | Where-Object {$_.IPEnabled}
$IPAddress = ($Networks.IpAddress | where {$_ -notmatch ":"}) -join "`n"
$MACAddress = ($Networks.MACAddress) -join "`n"
$IpSubnet = ($Networks.IpSubnet | ? { $_ -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}' }) -join "`n"
$DefaultGateway = ($Networks.DefaultIPGateway) -join "`n"
########## LastLogon/Created ##########
$LastLogonDate = Get-ADComputer $computer -Properties * | select -ExpandProperty LastLogonDate
$Created = Get-ADComputer $computer -Properties * | select -ExpandProperty Created
########## OUTPUT ##########
$tempreport = New-Object -TypeName PSObject
$tempreport | Add-Member -MemberType NoteProperty -Name ServerName -Value $Computer.ToUpper()
$tempreport | Add-Member -MemberType NoteProperty -Name Client_Customer -Value $ClientName.ToUpper()
$tempreport | Add-Member -MemberType NoteProperty -Name WMI_Connection -Value $WMIResult
$tempreport | Add-Member -MemberType NoteProperty -Name Pingable -Value $Ping
$tempreport | Add-Member -MemberType NoteProperty -Name Manufacturer -Value $Hardware.Manufacturer
$tempreport | Add-Member -MemberType NoteProperty -Name Model -Value $Hardware.Model
$tempreport | Add-Member -MemberType NoteProperty -Name Operating_System -Value $OS.Caption
$tempreport | Add-Member -MemberType NoteProperty -Name IP_Address -Value $IPAddress
$tempreport | Add-Member -MemberType NoteProperty -Name Default_Gateway -Value $DefaultGateway
$tempreport | Add-Member -MemberType NoteProperty -Name MAC_Address -Value $MACAddress
$tempreport | Add-Member -MemberType NoteProperty -Name IpSubnet -Value $IpSubnet
$tempreport | Add-Member -MemberType NoteProperty -Name Last_ReBoot -Value $lastboot
$tempreport | Add-Member -MemberType NoteProperty -Name Uptime_Days -Value $uptimeDays
$tempreport | Add-Member -MemberType NoteProperty -Name Last_Logon -Value $LastLogonDate
$tempreport | Add-Member -MemberType NoteProperty -Name Created -Value $Created
$tempreport | Add-Member -MemberType NoteProperty -Name Serial_Number -Value $systemBios
$report += $tempreport
}
else {
$WMIResult = 'Server NOT Contactable'
$tempreport = New-Object PSObject
$tempreport | Add-Member -MemberType NoteProperty -Name ServerName -Value $Computer.ToUpper()
$tempreport | Add-Member -MemberType NoteProperty -Name Client_Customer -Value $ClientName.ToUpper()
$tempreport | Add-Member -MemberType NoteProperty -Name WMI_Connection -Value $WMIResult
$tempreport | Add-Member -MemberType NoteProperty -Name Pingable -Value $Ping
$tempreport | Add-Member -MemberType NoteProperty -Name Manufacturer -Value $null
$tempreport | Add-Member -MemberType NoteProperty -Name Model -Value $null
$tempreport | Add-Member -MemberType NoteProperty -Name Operating_System -Value $null
$tempreport | Add-Member -MemberType NoteProperty -Name IP_Address -Value $null
$tempreport | Add-Member -MemberType NoteProperty -Name Default_Gateway -Value $null
$tempreport | Add-Member -MemberType NoteProperty -Name MAC_Address -Value $null
$tempreport | Add-Member -MemberType NoteProperty -Name IpSubnet -Value $null
$tempreport | Add-Member -MemberType NoteProperty -Name Last_ReBoot -Value $null
$tempreport | Add-Member -MemberType NoteProperty -Name Uptime_Days -Value $null
$tempreport | Add-Member -MemberType NoteProperty -Name Last_Logon -Value $null
$tempreport | Add-Member -MemberType NoteProperty -Name Created -Value $null
$tempreport | Add-Member -MemberType NoteProperty -Name Serial_Number -Value $null
$report += $tempreport
}
}
########## EXPORT TO CSV ##########
$CSVFileName = $ClientName + ' Server Inventory ' + $(Get-Date -f dd-MM-yyyy) + '.csv'
$report | Export-Csv "$outputpath\$CSVFileName" -NoTypeInformation