Scope/persistence of data issue - powershell

I'm not sure what to search for to solve this one. I have a scope/persistence of data issue, where a variable used to populate my data structure is over-writing other items in the data structure (ImageFileName). This is my code:
###Functions...first two are just for info
#method to get messages for mdb files
#dependency-Need to download accessDatabaseEngine(64 bit) redestributable: https://www.microsoft.com/en-us/download/details.aspx?id=54920
Function ProcessHelpMDB{
[cmdletbinding()]
Param ([string]$mdbLookupError, [string]$mdbFilePath, [string]$mdbDeviceSeries) #$mdbLookupError = error number, like 701. $mdbDeviceSeries is 1000
Process
{
#Write-Host "mdbLookupString: $mdbLookupString" -ForegroundColor Cyan
$adOpenStatic = 3
$adLockOptimistic = 3
#Write-Host "In ProcessMDB" -ForegroundColor darkRed
#$pathViewBase = 'C:\me\EndToEnd_view\' #View dir. Maybe param later
#$pathToMdb = Join-Path -Path $pathViewBase -ChildPath $mdbFileName
$deviceTable = $mdbDeviceSeries + "PP"
$mdbLookupError -Match '[0-9]*-([0-9]*)'
$errLookup = $Matches[1]
#Write-Host "dps" -ForegroundColor DarkMagenta
$selectQuery = “SELECT [$($deviceTable)].[HelpCode],
[$($deviceTable)].[ScreenNumber],
[$($deviceTable)].[TextID],
[$($deviceTable)].[PictureID]
FROM [$($deviceTable)]
WHERE
[$($deviceTable)].[HelpCode] = $($errLookup)"
$cn = new-object -comobject ADODB.Connection
$rs = new-object -comobject ADODB.Recordset
$cn.Open("Provider = Microsoft.ACE.OLEDB.16.0;Data Source = $mdbFilePath")
$rs.Open($selectQuery,
$cn, $adOpenStatic, $adLockOptimistic)
$i=0
$ret = [System.Collections.Generic.List[psobject]]::new()
if($rs.EOF)
{
Write-Host "$mdbLookupString not in $mdbFileName...record set returned emtpy for query"
}#if
else
{
while($rs.EOF -ne $True)
{
$result = [ordered]#{}
#$hash = #{}
foreach ($field in $rs.Fields)
{
$result[$field.name] = $field.Value
}#result
$newObject = [PSCustomObject]$result
$ret.Add($newObject) #
$rs.MoveNext()
} #while
}#else
Write-Host "retArr[0] $($ret[0])" #prints retArr[0] #{PictureID=HELP_...; TextID=HELP_...; HelpCode=9; ScreenNumber=1}
$i=0
foreach($row in $ret) #goes thru all rows
{
Write-Host "retArr[0] $($ret[$i,"TextID"])" #prints retArr[0] #{HelpCode=9; ScreenNumber=1; TextID=HELP_...; PictureID=HELP_...}
####
Write-Host "retArr[] $($row)" #prints retArr[] #{HelpCode=9; ScreenNumber=1; TextID=HELP_...; PictureID=HELP_7000_POWER_COVER_RIBBON}
Write-Host "retArr[0] $($row[$i])" #prints retArr[0] #{HelpCode=9; ScreenNumber=1; TextID=HELP_...; PictureID=HELP_...}
$i++
}
foreach($row in $ret.GetEnumerator()) #this is working for each row
{
Write-Host $row.TextID #prints HELP_...
Write-Host $row.'TextID' #prints HELP_...
}
$ret | ForEach-Object {
Write-Host TextID= $($_.TextID) #prints TextID= HELP_...
Write-Host TextID= $($_.'TextID') #prints TextID= HELP_...
} #
$cn.Close()
return $ret #Items queried from db ################################################# need to put them in excel file in order next
} #end Process
}# End of Function process mdb's
#This function gets mdb info out and returns English-US message found
Function ProcessK_MDB{
[cmdletbinding()]
Param ([string]$mdbLookupstring) #$mdbLookupString like HELP_...
Process
{
$adOpenStatic = 3
$adLockOptimistic = 3
$pathViewBase = 'C:\me\\EndToEnd_view\' #View dir. Maybe param later
$mdbFileNamePath = 'KAppText.mdb'
$pathToMdb = Join-Path -Path $pathViewBase -ChildPath $mdbFileNamePath
if(Test-Path $pathToMdb)
{
$selectQuery = “SELECT [Messages].[Message Description],
[Messages].[English - Us]
FROM [Messages]
WHERE [Messages].[Message Description] = '$($mdbLookupString)'”
$cn = new-object -comobject ADODB.Connection
$rs = new-object -comobject ADODB.Recordset
$cn.Open("Provider = Microsoft.ACE.OLEDB.16.0;Data Source = $pathToMdb")
$rs.Open($selectQuery,
$cn, $adOpenStatic, $adLockOptimistic)
if($rs.EOF) #empty
{
Write-Host "$mdbLookupString not in $mdbFileName...record set returned emtpy for query"
$ret = ""
}#if
else #got results
{
$returnArr = $rs.GetRows()
#$ret = $returnArr[0,1]
#$ret2 = $returnArr[1,1]
$ret = $returnArr[1,0] #has long text
#$ret4 = $returnArr[0,0] #has short text
#Write-Host $ret
}#else got results
$cn.Close()
} #testPath
else {
Write-Host "$pathToMdb does not exist"
}
return $ret #Message English-US for parameter/Message Description given
} #end Process
}# End of Function process mdb's
Function Get-ImageName{
[cmdletbinding()]
Param ([string]$imageName, [string]$fileNamePath)
Process
{
#find image file name to look for
[System.String] $pictureName = ""
if($imageName -Match "HELP")
{
#remove "HELP" part of file name
$($row.PictureID) -Match "HELP_(.*)" #get the part after HELP_
Write-Host $Matches[0]
Write-Host $Matches[1]
$pictureName = $Matches[1]
}
else {
$pictureName = $imageName
}
$imageFile2 = Get-ChildItem -Recurse -Path $ImageFullBasePath -Include #("*.bmp","*.jpg","*.png") | Where-Object {$_.Name -match "$($pictureName)"} #$imageFile | Select-String -Pattern '$($pictureName)' -AllMatches
Write-Host "ImageFile2: $($imageFile2)"
$imgFile = ""
foreach($imgFile in $imageFile2) #there may be more than one...just get last one...there are multiple telephone images
{
if($imgFile.Exists) #if($imageFile2.Exists)
{
#$image = [System.Drawing.Image]::FromFile($imgFile) #may not need this step
#need to figure out which is correct if there's multiple images
return $imgFile
}
else {
Write-Host "$($imgFile) does not exist"
return $null
}
} #foreach imageFile2
return $null
} #end Process
}# End of Function process mdb's
###main####
$resultHelp = ProcessHelpMDB -mdbLookupError $errCode -mdbFilePath $basePathFull -mdbDeviceSeries $deviceVer #######
$result = foreach($row in $resultHelp.GetEnumerator()) #this is working for each row
{
if($row -ne $True) #not sure why it adds true at the top
{
Write-Host $row.TextID #prints HELP_...
#lookup value from kapptext.mdb
Write-Host $($row.TextID) #prints nothing but looks ok in next function
$longText = ProcessK_MDB -mdbLookupstring $($row.TextID) #gives English-US message from device for parameter given
#insert images######################
#I can see that these are assigned correctly and returned from Function:
[System.Drawing.Image] $image = New-Object System.Drawing.Image #error...see Update2
[System.String] $imageNamePath = New-Object System.String #error...see Update2
[System.String] $imageNamePath = Get-ImageName -imageName $($row.PictureID) -fileNamePath $ImageFullBasePath
if($null -ne $imageNamePath)
{
$image = Get-Image -imageFileName $imageNamePath
}
else
{
Write-Host "Did not find an image file for $($row.PictureID) in $ImageFullBasePath"
}
#get the data ready to put in spreadsheet
New-Object psobject -Property $([ordered]#{
ScreenNumber = $($row.ScreenNumber)
KPMKey = $($row.TextID)
EnglishUS = $($longText)
PictureID = $($row.PictureID)
ImageFound = ""
ImageFileName = $($imageNamePath) ###???this is over-written...all same in $result after done with loop
})
} #if not true
} #foreach row $resultHelp
##note: $image gets inserted in the spreadsheet later, but since the names aren't showing correctly when use $results, I'm not sharing that part.
I can see after this runs for the 9 rows, that each ImageFileName is the same in $result. How do I do this so it maintains what is returned from the method? Right now I am trying New-Object, but it didn't fix the issue.
This is what $resultHelp looks like:
[0] $true (I'm not sure why it puts true at the top) [1]
#(HelpCode=9;ScreenNumber=1;TextID=HELP_...JA;PictureID=HELP_...RIB)
[2]
#(HelpCode=9;ScreenNumber=2;TextID=HELP_...ROLL;PictureID=HELP_...ROLL)
[3]
#(HelpCode=9;ScreenNumber=3;TextID=HELP_...EDGE;PictureID=HELP_...UT)
...
I am using Powershell 5.1 and VSCode.
Update:
I checked again, and in Get-ImageName, it's returning a file name like "Contact_Service"...bmp and it looks like it's getting put in the psObject ImageFileName...($imageNamePath), and the same thing for the other images found. When I look in the end, $result has all the same values for that ImageFileName. and the one that used to say "Contact_Service"..bmp is something else now, matching the other ones in $result.
Update2:
There are a couple errors:
New-Object : A constructor was not found. Cannot find an appropriate
constructor for type System.Drawing.Image
and
New-Object : A constructor was not found. Cannot find an appropriate
constructor for type System.String.
for where I tried dealing with the object over-write issue in the main code
Update3:
After I get the psobject in good shape, I put it in a spreadsheet with Export-Excel. I just wanted to give this info so you know why I'm putting it in the psobject like that:
$xlsx = $result | Export-Excel -Path $outFilePath -WorksheetName $errCode -Autosize -AutoFilter -FreezeTopRow -BoldTopRow -PassThru # -ClearSheet can't ClearSheet every time or it clears previous data

I figured it out.
the problem was that even though I was finding different $imageNamePaths for to assign to the Property as ImageFileName for each PictureID, and assigning those properties in the psobject in the foreach loop, I wound up with the same thing for each ImageFileName property (overwritten). This fixed it.
New-Object psobject -Property $([ordered]#{
ScreenNumber = $($row.ScreenNumber)
KPMKey = $($row.TextID)
EnglishUS = $($longText)
PictureID = $($row.PictureID)
ImageFound = ""
ImageFileName = "$($imageNamePath)" ####added double quotes
})
The double quotes let the different $imageNamePath values remain instead of being over-written. I'm not exactly sure why.
And thank you #Mathias, I will suppress output from my -Match to see if the $true is removed at the top of my data returned from the Function. :)

Related

List SPN's Script - Write results to file issue

Good morning everyone.
I found this script on the InterWeb's which works phenominal. HOWEVER... No matter what I try, and where I put it, I can't seem to get it to do the results to an out-file.
What the hell am I doing wrong, and where does the variable need to go?
# Source / credit:
# https://social.technet.microsoft.com/wiki/contents/articles/18996.active-directory-powershell-script-to-list-all-spns-used.aspx
cls
$search = New-Object DirectoryServices.DirectorySearcher([ADSI]"")
$search.filter = "(servicePrincipalName=*)"
## You can use this to filter for OU's:
## $results = $search.Findall() | ?{ $_.path -like '*OU=whatever,DC=whatever,DC=whatever*' }
$results = $search.Findall()
foreach( $result in $results ) {
$userEntry = $result.GetDirectoryEntry()
Write-host "Object Name = " $userEntry.name -backgroundcolor "yellow" -foregroundcolor "black"
Write-host "DN = " $userEntry.distinguishedName
Write-host "Object Cat. = " $userEntry.objectCategory
Write-host "servicePrincipalNames"
$i=1
foreach( $SPN in $userEntry.servicePrincipalName ) {
Write-host "SPN ${i} =$SPN"
$i+=1
}
Write-host ""
}

How to fix Cannot index into a null array in PowerShell

I'm trying to convert my CSV file to Excel file with some Table format and style but I'm getting "Cannot index into a null array" for some reason. I'll be really appreciated if I can get any help or suggestion. Thanks
function Convert-to-Excel{
$params = #{
AutoSize = $true
TableStyle = 'Medium6'
BoldTopRow = $true
WorksheetName = 'Audit Log'
PassThru = $true
Path = "C:\AuditLogSearch\$((Get-Date).AddDays(-7).ToString('yyyy-MM-dd')) _ $(Get-Date -Format "yyyy-MM-dd") Audit-Log-Records11.xlsx"
}
$modifiedFile = Import-Csv "C:\AuditLogSearch\Modified-Audit-Log-Records.csv"
$actionReference = Import-Csv "C:\AuditLogSearch\Reference\Action.csv"
$xlsx = foreach ($u in $modifiedFile) {
$u.User = (Get-AzureADUser -ObjectId $u.User).DisplayName
New-Object PsObject -Property #{
User = $u.User
"Search Criteria" = $u."Search Criteria"
"Result Status" = $u."Result Status"
"Date & Time" = $u."Date & Time"
"Type of Action" = if (($actionReference | where-object { $_.Name -eq $u."Type of Action" }).Value -ne $null) { ($actionReference | where-object { $_.Name -eq $u."Type of Action" }).Value }
else { $u."Type of Action" }
} | Export-Excel #params
$ws = $xlsx.Workbook.Worksheets[$params.Worksheetname]
$ws.View.ShowGridLines = $false # => This will hide the GridLines on your file
Close-ExcelPackage $xlsx
}
}
You're closing the Excel Package on the first iteration of your loop hence why when it goes to the next it's trying to do something like this:
$null[$null] # => InvalidOperation: Cannot index into a null array
Try modifying your function so it looks like this instead:
First, construct the object[]:
$result = foreach ($u in $modifiedFile) {
$u.User = (Get-AzureADUser -ObjectId $u.User).DisplayName
New-Object PsObject -Property #{
User = $u.User
"Search Criteria" = $u."Search Criteria"
"Result Status" = $u."Result Status"
"Date & Time" = $u."Date & Time"
"Type of Action" = if (($actionReference.........
else { $u."Type of Action" }
}
}
Then export it to Excel:
$xlsx = $result | Export-Excel #params
$ws = $xlsx.Workbook.Worksheets[$params.Worksheetname]
$ws.View.ShowGridLines = $false # => This will hide the GridLines on your file
Close-ExcelPackage $xlsx
One thing to note, PassThru = $true on the $params means that instead of saving the Excel directly we want to save the object on a variable for "further manipulation" and by further manipulation what I mean is, in this case, hiding the GridLines of the worksheet ($ws.View.ShowGridLines = $false) and then closing the package (store it on the disk).
If you don't require to perform any modifications over the worksheet you can just remove the PassThru altogether and do:
$result | Export-Excel #params
Which will close the package and store the Excel on your disk.

want the max and used from string

#http://stackoverflow.com/a/24036900/175063
$user = "uuuu"
$pwd = "pppp"
$source = "http://1.1.1.1/manager/jmxproxy?get=java.lang:type=Memory&att=HeapMemoryUsage"
$destination = "D:\Work\ps\test.xml"
$wc = new-object System.Net.WebClient
$p = New-Object System.Net.WebProxy 'http://proxy:8080'
$p.UseDefaultCredentials = $true
$wc.proxy = $p
$credCache = New-Object System.Net.CredentialCache
$creds = New-Object System.Net.NetworkCredential($user, $pwd)
$credCache.Add($source, "Basic", $creds)
$wc.Credentials = $credCache
$wc.DownloadFile($source, $destination)
# max=1445462016, used=898674904
# free
foreach ($thing in Get-Content $destination) {
$max = $thing.split("max=")
$used = $thing.split("used=")
Write-Host $max
Write-Host $used
}
#$free = $max - $used
#Write-Host $free
The string the file that is downloaded is a one-liner:
OK - Attribute get 'java.lang:type=Memory' - HeapMemoryUsage= javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=java.lang.management.MemoryUsage,items=((itemName=committed,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=init,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=max,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=used,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)))),contents={committed=1444478976, init=1494220800, max=1445462016, used=868228272})
And all I really want from it is:
max=1445462016
used=868228272
to be:
1445462016-868228272=577233744
I would extract the values from the contents={...} portion of the string with a regular expression, replace the commas with newlines and convert the result to a hashtable. Then you just need to cast the values to integers for the calculation.
Get-Content $destination | Where-Object {
$_ -match ',contents=\{(.+?)\}'
} | ForEach-Object {
$values = $matches[1] -replace ', ', "`n" | ConvertFrom-StringData
$free = [int]$values['max'] - [int]$values['used']
'Max: {0}' -f $values['max']
'Used: {0}' -f $values['used']
'Free: {0}' -f $free
}
I think I interpreted this correctly, do you want to display this in the console or store it in a variable, I'm assuming console here:
write-host "$max-$used="($max-$used)
I have figured out my own solution... I know it may not be the best way, but seems to work..
#http://stackoverflow.com/a/24036900/175063
$user="uuuu"
$pwd="pppp"
$source="http://1.1.1.1/manager/jmxproxy?get=java.lang:type=Memory&att=HeapMemoryUsage"
$destination="D:\Work\ps\test.xml"
$wc=new-object System.Net.WebClient
$p = New-Object System.Net.WebProxy 'http://proxy:8080'
$p.UseDefaultCredentials = $true
$wc.proxy=$p
$credCache=new-object System.Net.CredentialCache
$creds=new-object System.Net.NetworkCredential($user,$pwd)
$credCache.Add($source, "Basic", $creds)
$wc.Credentials=$credCache
$wc.DownloadFile($source, $destination)
# max=1445462016, used=898674904
# free
foreach ($thing in Get-Content $destination) {
# , max=1445462016, used=696318832})
# $a = $a.substring(2,3)
# MID: https://technet.microsoft.com/en-us/library/ee176901.aspx
# LEN: https://technet.microsoft.com/en-us/library/ee176895.aspx
# Instr: https://technet.microsoft.com/en-us/library/ee176876.aspx
$len = $thing.length
$maxst = $thing.indexof("max=")
$usedst = $thing.indexof("used=")
$max=$thing.substring($maxst+4,$len-$usedst-6)
$used=$thing.substring($usedst+5,$len-$usedst-7)
$free=$max-$used
# , max=1445462016, used=696318832})
write-host $len
write-host $maxst
write-host $usedst
write-host $max
write-host $used
write-host $free
}

Is the first element of a powershell array always "true"?

arg1I have some code that creates an empty powershell array, then adds items to this array in a do..while loop. For some reason, no matter what I do, the first element in the array is "true". Why is this?
In my code below, you'll notice the loop adds output a line at a time from an external exe. The exe never returns "true", and you can see I'm doing Write-Host for each it that gets added to the array, and there's never a "true" output from this Write-Host call. There is no other code anywhere in my script that adds any elements to the array. This is frustrating because the index of the array is messed up. This essentially makes this array 1-indexed instead of 0-indexed. Does anyone have any ideas about what's happening here?
Also, one more thing to notice, after I initialize the array, i Write-Host the length, and it's 0, then after I'm dont adding all items, the length is what I would expect it to be if "true" were not the first element. So if there's 4 lines returned from the external app, then the second Write-Host $output.Length call will output 4.
Here is my code:
$output = #()
Write-Host "OUTPUT LENGTH START: $($output.Length)" -ForegroundColor Yellow
$continue = $true
do {
$tempoutput = $Process.StandardOutput.ReadLine()
if(($tempoutput -ne $null) -and ([string]::IsNullOrWhiteSpace($tempoutput) -ne $true)) {
Write-Host $tempoutput -ForegroundColor DarkGray
$output += $tempoutput
} else {
$continue = $false
}
}
while($continue -eq $true)
Write-Host "OUTPUT LENGTH END: $($output.Length)" -ForegroundColor Yellow
Also, at the end of my function, i'm returning the output array like this:
$output
And then in my code that calls my function, if I do a foreach over the returned array's elements, "True" will always be the first item in this array.
EDIT TO INCLUDE FULL FUNCTION
Here is my full function with all the Write-Host calls removed:
function Execute-HttpManager($arguments, $filepath){
$ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo
$ProcessInfo.FileName = $filepath
$ProcessInfo.RedirectStandardError = $true
$ProcessInfo.RedirectStandardOutput = $true
$ProcessInfo.RedirectStandardInput = $true
$ProcessInfo.UseShellExecute = $false
$ProcessInfo.CreateNoWindow = $true
$ProcessInfo.Arguments = $arguments
$Process = New-Object System.Diagnostics.Process
$Process.StartInfo = $ProcessInfo
$Process.Start()
$Process.WaitForExit()
$output = #()
$continue = $true
do {
$tempoutput = $Process.StandardOutput.ReadLine()
if(($tempoutput -ne $null) -and ([string]::IsNullOrWhiteSpace($tempoutput) -ne $true)) {
$output += $tempoutput
} else {
$continue = $false
}
}
while($continue -eq $true)
$deployError = $Process.StandardError.ReadToEnd()
$exitcode = $Process.ExitCode
if($exitcode -eq 4) {
$deployagainresponse = Read-Host
if($deployagainresponse -eq 'y') {
Deploy-Database $localapp $localsqlinstance $localdatabasename $localbackup $localsnapshot
} elseif($deployagainresponse -ne 'bypass') {
throw "http interaction failed with error. Check the output."
}
} elseif ($exitcode -ne 0) {
throw "Database deploy failed."
}
return $output
}
And here is the code that calls my function:
$tokenoutput = Execute-HttpManager #("arg1", "arg2", "arg3", "arg4") $pathtoexecutable
It is this $tokenoutput variable that has the "True" added to the beginning of it's array.
Make sure to check for any calls that are returning a value (such as $Process.Start()), and either precede them with [void] or pipe to out-null: $Process.Start() | Out-Null.
Be aware of this for any function! Anything the function outputs is part of the return value.

Powershell to get metadata of files

I am looking to get metadata of a specified file (or directory of files). I am specifically looking for "Program Description" on .WTV files.
I found code, but it doesn't list that attribute. Some of that code looks like this:
foreach($sFolder in $folder)
{
$a = 0
$objShell = New-Object -ComObject Shell.Application
$objFolder = $objShell.namespace($sFolder)
foreach ($strFileName in $objFolder.items())
{ FunLine( "$($strFileName.name)")
for ($a ; $a -le 266; $a++)
{
if($objFolder.getDetailsOf($strFileName, $a))
{
$hash += #{ `
$($objFolder.getDetailsOf($objFolder.items, $a)) =`
$($objFolder.getDetailsOf($strFileName, $a))
} #end hash
$hash
$hash.clear()
I can see that attribute in File explorer.
The code you had #user1921849 has almost got it, but to address the original question more clearly you should use the Windows Shell Property System named properties, listed in the Windows devloper documentation for WTV files, and used in line 4 below.
$shell = new-object -com shell.application
$folder = $shell.namespace("\\MEDIA\Recorded Tv\")
$item = $folder.Items().Item('Person of Interest_WBBMDT_2013_11_26_21_01_00.wtv')
write-output $item.ExtendedProperty('System.RecordedTV.ProgramDescription')
Updated URL to docs
General properties list https://learn.microsoft.com/en-us/windows/desktop/properties/props
WTV properties list https://learn.microsoft.com/en-us/windows/desktop/properties/recordedtv-bumper
Grab TagLib# from Nuget or various other places. Then check out this blog post showing how to use TagLib# to edit MP3 tags. Hopefully, it can retrieve the WTV tag you're looking for.
$shell = new-object -comobject shell.application
$ShFolder=$shell.namespace("\\MEDIA\Recorded Tv\")
$ShFile =$ShFolder.parsename("Person of Interest_WBBMDT_2013_11_26_21_01_00.wtv")
$count = 0
while ($count -le 294)
{
$ShRating = $ShFolder.getdetailsof($ShFile,$count)
$count
$ShRating
$count = $count+1
}
Program Description is item 272.
I have done a sample code which will check all file in a folder and export a csv file with all the metadata details. Please find the following powershell script.
Step 1. Create a file Fileproperty.ps1
Import-Module ".\Module\AddModule.psm1" -Force
$commands = {
$source = read-host "Enter folder path "
if ([string]::IsNullOrWhitespace($source)){
Write-host "Invalid file path, re-enter."
$source = $null
&$commands
}else{
$output = read-host "Enter output folder path "
if ([string]::IsNullOrWhitespace($output)){
Write-host "Invalid output path, re-enter."
$output = $null
&$commands
}else{
$outputfilename = read-host "Enter output file name "
if ([string]::IsNullOrWhitespace($outputfilename)){
Write-host "Invalid file name, re-enter."
$outputfilename = $null
&$commands
}else{
Get-FileMetaData -folder $source | Export-Csv -Path $output\$outputfilename.csv -Encoding ascii -NoTypeInformation
Write-host "Process has been done..."
}
}
}
}
&$commands
Step 2. Create a folder Module
Step 3. create another file Module/AddModule.psm1
$FunctionFiles = #(Get-ChildItem -Path $PSScriptRoot\*.ps1 -ErrorAction SilentlyContinue)
Foreach($fileItem in #($FunctionFiles))
{
Try
{
. $fileItem.fullname
}
Catch
{
Write-Error -Message "Vsts module -> Unable to import a function in file $($fileItem.fullname): $_"
}
}
Export-ModuleMember -Function $FunctionFiles.Basename
Step 4. create another file Module/Get-FileMetaData.ps1
Function Get-FileMetaData
{
Param([string[]]$folder)
$OutputList = New-Object 'System.Collections.generic.List[psobject]'
foreach($sFolder in $folder) {
$a = 0
$objShell = New-Object -ComObject Shell.Application
$objFolder = $objShell.namespace($sFolder)
foreach ($File in $objFolder.items())
{
$FileMetaData = New-Object PSOBJECT
for ($a ; $a -le 266; $a++)
{
if($objFolder.getDetailsOf($File, $a))
{
$hash += #{$($objFolder.getDetailsOf($objFolder.items, $a)) =
$($objFolder.getDetailsOf($File, $a)) }
$FileMetaData | Add-Member $hash
$hash.clear()
} #end if
} #end for
$a=0
$OutputList.Add($FileMetaData)
} #end foreach $file
} #end foreach $sfolder
return $OutputList
} #end Get-FileMetaData
Hope this will work for you.