Powershell - How to include array data with flat file - arrays

I am creating a csv flat with some data. One of the column is content type which may have one or more content types in the column (string values). How do I include all the values from the array object into the flat file but with the respected row? See the code below... I passed $ct to the add-content but flat file does not have the content type data in it. when I do write-host for $ct I see that it has values. Please suggest.
#For Output file generation
$OutputFN = "Libraries.csv"
#delete the file, If already exist!
if (Test-Path $OutputFN)
{
Remove-Item $OutputFN
}
#Write the CSV Headers
Add-Content $OutputFN "Web URL, Site Name, Library Name, Content Types"
$systemlibs =#("Converted Forms", "Customized Reports", "Documents", "Form Templates",
"Images", "List Template Gallery", "Master Page Gallery", "Pages",
"Reporting Templates", "Site Assets", "Site Collection Documents",
"Site Collection Images", "Site Pages", "Solution Gallery",
"Style Library", "Theme Gallery", "Web Part Gallery", "wfpub")
#Get the Site collection
$Site= Get-SPSite "http://inside.contoso.com"
$spWebApp = $Site.WebApplication
foreach($allSites in $spWebApp.Sites)
{
#Loop through all Sub Sites
foreach($Web in $allSites.AllWebs)
{
#Write-Host "-----------------------------------------------------"
#Write-Host "Site Name: '$($web.Title)' at $($web.URL)"
#Write-Host "-----------------------------------------------------"
foreach($list in $Web.Lists)
{
if($list.BaseTemplate -eq "DocumentLibrary" -and $list.AllowContentTypes -eq $true)
{
if(-not ($systemlibs -Contains $list.Title))
{
if ($list.AllowContentTypes -eq $true)
{
$ct = #()
foreach ($contenttype in $list.ContentTypes)
{
$ctProperties = #{ContentType = $contenttype.Name}
$ctObject = New-Object PSObject -Property $ctProperties
#write-host $ct
$ct += $ctObject
#write-host $ct
#Write-Host "$($web.URL), $($web.Title), $($list.Title), $ct"
}
#$ct
write-host $ct
#Write-Host "$($web.URL), $($web.Title), $($list.Title), $($ct)"
$content = $web.URL + "," + $web.Title +"," + $list.Title +"," + $ct
add-content $OutputFN $content
}
}
}
}
}
}

If you wanted to include data in a csv file that could be later converted to an array you could just store it as a delimited string. The delimiter obviously cannot be the same as the one you are using in your flat file. In its basic form you could be using -split and -join
$array = #("a","b","c")
Add-Content $path ($array -join ";")
In context we could make a couple of changes for the better. In place of this if statement
if ($list.AllowContentTypes -eq $true){
# Stuff happens here
}
You could instead do the following.
if ($list.AllowContentTypes -eq $true){
$ct = $list.ContentTypes | Select-Object -ExpandProperty Name
$content = "$($web.URL), $($web.Title), $($list.Title), $($ct -join ";")"
add-content $OutputFN $content
}
You could take this farther using Objects and ConvertTo-CSV but lets be sure we are on the right track first.

Related

File sorting based on file content (string)

I want to build a modular script that sorts files based on content (strings/Get-Content in PowerShell).
Requirement:
Defining a directory. ($directory)
start a foreach loop: foreach
list items in the directory & full path in memory
$FilePath in Get-ChildItem $directory | Select-Object -ExpandPropert FullName
Load content of one file at a time in the memory
$content = Get-Content $FilePath
Search for the keyword and copy the file once a particular keyword is found.
if ($content -match 'keyword1') { Copy-Item $FilePath $OutputPath }
While I am able to do this in a static manner using the below mentioned code, I wanted to modularise it for reuse.
[string] $Directory = "parth to source directory";
[string] $outpath1 = "outpath for keyword1";
[string] $OutputPath2 = "outpath for keyword2";
[string] $OutputPath3 = "outpath for keyword3";
foreach ($FilePath = Get-ChildItem $Directory | Select-Object -ExpandProperty FullName) {
[string] $content = Get-Content $FilePath
if ($content -match 'keyword1') {
Copy-Item $FilePath $OutputPath
} elseif ($content -match 'keyword2') {
Copy-Item $FilePath $OutputPath2
} else {
Copy-Item $FilePath $keyword3
}
}
My questions:
Is it possible to define keywords in a single array? If so how do that in PowerShell? (keyword1, keyword2, keyword3)
Run keywords sequentially in the files and whenever one keyword is detected, the file is copied to it's designated folder. Can I have this done in modular fashion or will I have to define directory for each keyword?
The reason I am doing this is because while the script is being used for 2 or 3 keywords as of now, it will be used for over 50 keywords and allowing reuse should help.
What you describe could be achieved with a hashtable and a nested loop:
$outpath = #{
'keyword1' = 'outpath for keyword1'
'keyword2' = 'outpath for keyword2'
'keyword3' = 'outpath for keyword3'
}
foreach ($FilePath in Get-ChildItem $Directory | Select-Object -Expand FullName) {
$content = Get-Content $FilePath
foreach ($keyword in $outpath.Keys) {
if ($content -match $keyword) {
Copy-Item $FilePath $outpath[$keyword]
break
}
}
}
Alternatively you could use a switch statement:
$outpath = #{
'keyword1' = 'outpath for keyword1'
'keyword2' = 'outpath for keyword2'
'keyword3' = 'outpath for keyword3'
}
$pattern = ($outpath.Keys | ForEach-Object { [regex]::Escape($_) }) -join '|'
foreach ($FilePath in Get-ChildItem $Directory | Select-Object -Expand FullName) {
$content = Get-Content $FilePath
switch -regex ($content) {
$pattern {
Copy-Item $FilePath $outpath[$keyword]
break
}
}
}
The latter would also give you a simple way of specifying a fallback destination path if you also want to handle files with no matching keyword.
$fallbackpath = '...'
foreach ($FilePath in Get-ChildItem $Directory | Select-Object -Expand FullName) {
$content = Get-Content $FilePath
switch -regex ($content) {
$pattern {
Copy-Item $FilePath $outpath[$keyword]
break
}
default {
Copy-Item $FilePath $fallbackpath
break
}
}
}

Automatically import ICS file to outlook.com

I have an *.ics file and want to import it to my calendar on outlook.com. How can I do this with a powershell script?
I need to either delete and recreate the calendar I import to, or clear the calendar before import.
Thanks in advance.
Try
Step 1: Read the contents of the ics file
Step 2: Parse it
Step 3: Use Outlook Application Object in Powershell
Step 4: Get the Calendar folder
Step 5: use the properties of the calendar folder to add the parsed content in step 2
#Folder containing ICS files
$ICSpath="C:\Users\test\testasdasd"
$ICSlist = get-childitem $ICSPath
Foreach ($i in $ICSlist )
{
$file= $i. fullname
$data = #{}
$content = Get-Content $file -Encoding UTF8
$content |
foreach-Object {
if($_.Contains(':')){
$z=#{ $_.split( ':')[0] =( $_.split( ':')[1]).Trim()}
$data. Add( $z. Keys, $z. Values)
}
}
$outlook = new-object -com Outlook.Application
$calendar = $outlook.Session.GetDefaultFolder(9)
$appt = $calendar.Items.Add(1)
$Body=[regex]::match($content,'(?<=\DESCRIPTION:).+(?=\DTEND:)', "singleline").value .trim ()
$Body= $Body -replace "\r\n\s"
$Body = $Body.replace("\,",",").replace("\n"," ")
$Body= $Body -replace "\s\s"
$Start = ($data.getEnumerator() | ?{ $_.Name -eq "DTSTART"}).Value -replace "T"
$Start = [datetime]::ParseExact ($Start ,"yyyyMMddHHmmss" ,$null )
$End = ($data.getEnumerator() | ?{ $_.Name -eq "DTEND"}).Value -replace "T"
$End = [datetime]::ParseExact ($End ,"yyyyMMddHHmmss" ,$null )
$Subject = ($data.getEnumerator() | ?{ $_.Name -eq "SUMMARY"}).Value
$Location = ($data.getEnumerator() | ?{ $_.Name -eq "LOCATION"}).Value
$appt.Start = $Start
$appt.End = $End
$appt.Subject = $Subject
$appt.Categories = "Presentations" #Pick your own category!
$appt.BusyStatus = 0 # 0=Free
$appt.Location = $Location
$appt.Body = $Body
$appt.ReminderMinutesBeforeStart = 15 #Customize if you want
$appt.Save()
if ($appt.Saved)
{ write-host "Appointment saved."}
Else {write-host "Appointment NOT saved."}
}
Acknowledging "thescriptkeeper.wordpress.com" for the script

Upload file from my local system on Sharepoint

Please help me with the complete batch file code:
I want to upload file(.xls,csv) onto Sharepoint server using batch file. It should perform:
a> Do a check to see in the sharepoint location if the file exist. If exist then do nothing.
b> If the file do not exist, then
1.check the local if the file is present in this location or not. If yes then simply upload it n sharepoint.
2.Step a. again
This batch file will be triggered by windows schedular every 20 mins.
My goal is to upload the files the moment they get generated.
Request you to please help me with the correct code logic which I can implement.
Thankyou for the help n support!
Take a look of the SharePoint Multiple File Upload Script;
function Copy-FilestoSP
{
Param (
[parameter(Mandatory=$true)][string]$LocalPath,
[parameter(Mandatory=$true)][string]$SiteUrl,
[parameter(Mandatory=$true)][string]$Library,
[parameter(Mandatory=$false)][string]$LibraryStartFolder,
[parameter(Mandatory=$false)][string]$ManifestFilePath,
[parameter(Mandatory=$false)][switch]$IncludeSubFolders,
[parameter(Mandatory=$false)][switch]$Approve,
[parameter(Mandatory=$false)][switch]$CheckIn,
[parameter(Mandatory=$false)][switch]$Overwrite,
[parameter(Mandatory=$false)][switch]$FlattenStructure
)
try
{
#Get web and document library objects
$web = Get-SPWeb $SiteUrl
$docLibrary = $web.Lists[$Library]
#Load metadata manifest file, if specified
if ($PSBoundParameters.ContainsKey('ManifestFilePath')) {
$metadataManifest = [xml] (Get-Content ($ManifestFilePath))
}
else
{
write-host "Manifest file not specified for categorising uploaded documents"
}
#Check for the LibraryStartFolder parameter to specify a root folder
if ($PSBoundParameters.ContainsKey('LibraryStartFolder')) {
$folder = $web.GetFolder($docLibrary.Title + $LibraryStartFolder)
}
else
{
$folder = $docLibrary.RootFolder
}
#Attach to local folder and enumerate through all files
if($IncludeSubFolders) {
$files = Get-ChildItem $LocalPath -Recurse
}
else
{
$files = Get-ChildItem $LocalPath
}
$files | ForEach-Object {
#Check if the object is a folder - if so, create it in doc library
if ($_.PSIsContainer) {
if (($IncludeSubFolders) -and (!$FlattenStructure)) {
#Generate folder path for creation in SharePoint
#by looking at the parent folder on the local path
$spFolderPath = ($_.Parent.FullName.Replace($LocalPath,"")).Replace("\","/")
#Get the folder into which the new folder will be created
#by adding the folder path generated above, if one existed
if ($spFolderPath -eq "") {
$currentFolder = $web.GetFolder($folder.Url)
}
else
{
$currentFolder = $web.GetFolder($folder.Url + $spFolderPath)
}
#Check to see if subfolder already exists
#and create it if not
$testFolder = $currentFolder.SubFolders[$_.Name]
if ($testFolder -eq $null) {
write-host "`nAdding folder" $_.Name "to" $docLibrary.Title "in" $web.Title "..." -foregroundcolor Green
$newFolder = $currentFolder.SubFolders.Add($_.Name)
}
else
{
write-host "`nFolder" $_.Name "already exists in" $docLibrary.Title "and shall not be created" -foregroundcolor Red
}
}
}
else
{
#Generate file path for upload into SharePoint
if ($FlattenStructure) {
$spFilePath = ("/" + $_.Name)
}
else
{
$spFilePath = ($_.FullName.Replace($LocalPath,"")).Replace("\","/")
}
$spFullPath = $folder.Url + $spFilePath
#Check if the file exists and the overwrite option is selected before adding the file
if ((!$web.GetFile($spFullPath).Exists) -or ($Overwrite)) {
#Add file
write-host "`nCopying" $_.Name "to" $spFullPath.Replace("/" + $_.Name,"") "in" $web.Title "..." -foregroundcolor Green
$spFile = $folder.Files.Add($spFullPath, $_.OpenRead(), $true)
$spItem = $spFile.Item
#Walk through manifest XML file and configure column values on the file
$metadataManifest.Columns.Column | ForEach-Object {
#Single value text columns
try
{
if (($_.Type -eq "Text") -or
($_.Type -eq "Choice") -or
($_.Type -eq "Boolean") -or
($_.Type -eq "Number") -or
($_.Type -eq "Currency")) {
$columnName = $_.Name
write-host "Setting value on column"$columnName "..." -foregroundcolor Blue
$_.Values.Value | ForEach-Object {
$spItem[$columnName] = $_
write-host "Value set to"$_
}
}
}
catch {}
#Multiple line text column
try
{
if ($_.Type -eq "Note") {
$columnName = $_.Name
write-host "Setting value on column"$columnName "..." -foregroundcolor Blue
[string]$multiLineValue = $null
$_.Values.Value | ForEach-Object {
$multiLineValue = $multiLineValue + $_ + "`n"
}
$spItem[$columnName] = $multiLineValue
write-host "Value on multiiple line text column set"
}
}
catch {}
#Multiple choice columns
try
{
if ($_.Type -eq "MultiChoice") {
$columnName = $_.Name
write-host "Setting value on column"$columnName "..." -foregroundcolor Blue
[string]$multiChoiceValue = ";#"
$_.Values.Value | ForEach-Object {
$multiChoiceValue = $multiChoiceValue + $_ + ";#"
write-host "Value"$_ "added to column"
}
$spItem[$columnName] = $multiChoiceValue
}
}
catch {}
#Hyperlink columns
try
{
if ($_.Type -eq "URL") {
$columnName = $_.Name
write-host "Setting value on column"$columnName "..." -foregroundcolor Blue
$urlFieldValue = New-Object Microsoft.SharePoint.SPFieldUrlValue
$_.Values.Description | ForEach-Object {
$urlFieldValue.Description = $_
}
$_.Values.Value | ForEach-Object {
$urlFieldValue.Url = $_
}
$spItem[$columnName] = $urlFieldValue
write-host "Value set to"$urlFieldValue.Url
}
}
catch {}
#Single User column
try
{
if ($_.Type -eq "User") {
$columnName = $_.Name
$user = $null
write-host "Setting value on column"$columnName "..." -foregroundcolor Blue
$_.Values.Value | ForEach-Object {
#Check to see if SharePoint group exists in the site collection
if ($web.SiteGroups[$_])
{
#Set account variable to SPGroup
$account = $web.SiteGroups[$_]
}
else
{
#Set account variable to SPUser
$account = $web.EnsureUser($_)
}
$spItem[$columnName] = $account
write-host "Value set to"$_
}
}
}
catch {}
#Multiple User column
try
{
if ($_.Type -eq "UserMulti") {
$columnName = $_.Name
$user = $null
$userField = New-Object Microsoft.SharePoint.SPFieldUserValueCollection
write-host "Setting value on column"$columnName "..." -foregroundcolor Blue
$_.Values.Value | ForEach-Object {
#Check to see if SharePoint group exists in the site collection
if ($web.SiteGroups[$_])
{
#Set account variable to SPGroup
$account = $web.SiteGroups[$_]
}
else
{
#Set account variable to SPUser
$account = $web.EnsureUser($_)
}
$userValue = New-Object Microsoft.SharePoint.SPFieldUserValue($web, $account.ID, $account.Name)
$userField.Add($userValue)
write-host "Value"$_ "added to column"
}
$spItem[$columnName] = $userField
}
}
catch {}
#Single value Managed Metadata column
try
{
if ($_.Type -eq "TaxonomyFieldType") {
$columnName = $_.Name
$taxonomySession = Get-SPTaxonomySession -Site $web.Site
$termStore = $taxonomySession.DefaultSiteCollectionTermStore
$taxonomyField = $docLibrary.Fields[$columnName]
$termSet = $termStore.GetTermSet($taxonomyField.TermSetId)
write-host "Setting value on column"$columnName "..." -foregroundcolor Blue
$_.Values.Value | ForEach-Object {
$termCollection = $termSet.GetTerms($_, $true)
if ($termCollection.Count -eq 0)
{
$term = $termSet.CreateTerm($_, 1033)
$termStore.CommitAll()
}
else
{
$term = $termCollection[0]
}
$taxonomyField.SetFieldValue($spItem, $term)
write-host "Value set to"$_
}
}
}
catch {}
#Multi value Managed Metadata column
try
{
if ($_.Type -eq "TaxonomyFieldTypeMulti") {
$columnName = $_.Name
$taxonomySession = Get-SPTaxonomySession -Site $web.Site
$termStore = $taxonomySession.DefaultSiteCollectionTermStore
$taxonomyField = $docLibrary.Fields[$columnName]
$tfvc = New-Object Microsoft.SharePoint.Taxonomy.TaxonomyFieldValueCollection($taxonomyField)
$termSet = $termStore.GetTermSet($taxonomyField.TermSetId)
write-host "Setting value on column"$columnName "..." -foregroundcolor Blue
$_.Values.Value | ForEach-Object {
$termCollection = $termSet.GetTerms($_, $true)
if ($termCollection.Count -eq 0)
{
$term = $termSet.CreateTerm($_, 1033)
$termStore.CommitAll()
}
else
{
$term = $termCollection[0]
}
$valueString = "-1;#" + $term.Name + "|" + $term.Id.ToString()
$taxonomyValue = New-Object Microsoft.SharePoint.Taxonomy.TaxonomyFieldValue($valueString)
$tfvc.Add($taxonomyValue)
write-host "Value"$_ "added to column"
}
$taxonomyField.SetFieldValue($spItem, $tfvc)
}
}
catch {}
#Update document with new column values
$spItem.SystemUpdate($false)
}
#Check in file to document library (if required)
#MinorCheckIn=0, MajorCheckIn=1, OverwriteCheckIn=2
if ($CheckIn) {
if ($spFile.CheckOutStatus -ne "None") {
$spFile.CheckIn("File copied from " + $filePath, 1)
write-host $spfile.Name"checked in"
}
}
#Approve file (if required)
if ($Approve) {
if ($spItem.ListItems.List.EnableModeration -eq $true) {
$spFile.Approve("File automatically approved after copying from " + $filePath)
if ($spItem["Approval Status"] -eq 0) { write-host $spfile.Name"approved" }
}
}
}
else
{
write-host "`nFile"$_.Name "already exists in" $spFullPath.Replace("/" + $_.Name,"") "and shall not be uploaded" -foregroundcolor Red
}
}
}
}
catch [System.SystemException]
{
write-host "The script has stopped because there has been an error. "$_.Message
}
finally
{
$web.Dispose()
}
}
write-host "SharePoint 2010 Multiple File Upload Script - Get-SPScripts.com"
More information is available in CodePlex; http://spfileupload.codeplex.com/SourceControl/latest#Get-SPScripts.Copy-FilesToSP.ps1

Easy way to List info from arrays

I have the code below which checks the registry for entries (more than 20 of them) and if it doesn't exists it creates a registry key and adds it to an array.
After that I need to check for all the names in the array to my other array and if it matches, I need it to pull the info from my second array and show it on the screen(the log location, registry location etc). But Can't really figure out how to match the array and write in on the screen without writing very long if statements.
Does anyone know a good way of doing this?
Thanks in advance!
$Reg = "HKLM:\Software\"
$NeedtoCheck = #()
$testing = #("Test1Name","Test2Name", "Test3Name")
$allTests = #(
$Test1 = #{
Name = "Test1"
Logfile = "C:\Checking\test1.log"
Version = "16"
RegName = "test1Nameinfo*"
Installname = "InstallTest1"
UninstallName = "UninstallTest1"
},
$Test2 = #{
Name = "Test"
Logfile = "C:\test2.log"
Version = "7"
RegName = "test2Nameinfo*"
Installname = "InstallTest2"
UninstallName = "UninstallTest2"
},
$Test3 = #{
Name = "Test3"
Logfile = "C:\Temp\Checkhere\test3.log"
Version = "99"
RegName = "test3Nameinfo*"
Installname = "InstallTest3"
UninstallName = "UninstallTest3"
}
$Test1Name = $Test1.name
$Test1Logfile = $Test1.Logfile
$Test1Version = $Test1.Version
$Test1RegName = $Test1.RegName
$Test1Install = $Test1.InstallName
$Test1Uninstall = $Test1.UninstallName
$Test2Name = $Test2.name
$Test2Logfile = $Test2.Logfile
$Test2Version = $Test2.Version
$Test2RegName = $Test2.RegName
$Test2Install = $Test2.InstallName
$Test2Uninstall = $Test2.UninstallName
$Test3Name = $Test3.name
$Test3Logfile = $Test3.Logfile
$Test3Version = $Test3.Version
$Test3RegName = $Test3.RegName
$Test3Install = $Test3.InstallName
$Test3Uninstall = $Test3.UninstallName
Foreach($Test in $testing){
$Key = (Get-Item "Reg").getvalue("$Test")
IF($Key -eq $null)
{
New-Itemproperty -path "HKLM:\Software\" -value "Check" -PropertyType string -name $Test -Force -ErrorAction SilentlyContinue
Write-Host "$Test created"
$Needtocheck += $Test
}
ELSEIF($key -eq "Check")
{
$Needtocheck += $Test
}
ELSE
{
Write-Host "$Test already Checked"
}
}
Foreach($item in $NeedtoCheck)
{
If($item -match $Test1Name)
{
Write-Host "$Test1Name info"
Write-host "$Test1Name`
$Test1Logfile`
$Test1Version`
$Test1RegName`
$Test1Install`
$Test1Uninstall`
}
Else
{
Write-Host "Not in the list"
}
}
....
This code doesn't make a lot of sense to be honest. If you want 20 checks to be setup, and then only run certain checks, then that's fine, but you really don't need additional cross checking to reference one array against another array, and redefining things like you do when you assign variables for each values in each hashtable. Personally I'd make objects not hashtables, but that's me. Actually, probably even better, make a hashtable with all available tests, then for the value make an object with the properties that you need. Oh, yeah, that'd be the way to go, but would need a little re-writing. Check this out...
$Reg = 'HKLM:\Software\'
$NeedtoCheck = #()
$testing = #('Test2','Test1','NotATest')
#Define Tests
$AllTests = #{'Test1' = [PSCustomObject]#{
Name = "Test1"
Logfile = "C:\Checking\test1.log"
Version = "16"
RegName = "test1Nameinfo*"
Installname = "InstallTest1"
UninstallName = "UninstallTest1"
}
'Test2' = [PSCustomObject]#{
Name = "Test"
Logfile = "C:\test2.log"
Version = "7"
RegName = "test2Nameinfo*"
Installname = "InstallTest2"
UninstallName = "UninstallTest2"
}
'Test3' = [PSCustomObject]#{
Name = "Test3"
Logfile = "C:\Temp\Checkhere\test3.log"
Version = "99"
RegName = "test3Nameinfo*"
Installname = "InstallTest3"
UnnstallName = "UninstallTest3"
}
}
#$allTests = #($Test1,$Test2,$Test3)
Foreach($Test in $Testing){
If($Test -in $allTests.Keys){
$Key = (Get-Item $Reg).getvalue($AllTests[$Test].RegName)
Switch($Key){
#Case - Key not there
{[string]::IsNullOrEmpty($_)}{
New-Itemproperty -path "HKLM:\Software\" -value "Check" -PropertyType string -name $AllTests[$Test].RegName -Force -ErrorAction SilentlyContinue
Write-Host "`n$Test created"
Write-Host "`n$Test info:"
Write-host $allTests[$test].Name
Write-host $allTests[$test].LogFile
Write-host $allTests[$test].Version
Write-host $allTests[$test].RegName
Write-host $allTests[$test].Installname
Write-host $allTests[$test].Uninstallname
}
#Case - Key = 'Check'
{$_ -eq "Check"}{
Write-Host "`n$Test info:`n"
Write-host $allTests[$test].Name
Write-host $allTests[$test].LogFile
Write-host $allTests[$test].Version
Write-host $allTests[$test].RegName
Write-host $allTests[$test].Installname
Write-host $allTests[$test].Uninstallname
}
#Default - Key exists and does not need to be checked
default {
Write-Host "`n$Test already Checked"
}
}
}Else{
Write-Host "`n$Test not in list"
}
}
That should do what you were doing before, with built in responses and checks. Plus this doesn't duplicate efforts and what not. Plus it allows you to name tests whatever you want, and have all the properties you had before associated with that name. Alternatively you could add a member to each test run, like 'Status', and set that to Created, Check, or Valid, then you could filter $AllTests later and look for entries with a Status property, and filter against that if you needed additional reporting.
You can filter down the tests you want to check like so, if I understand what you are asking for:
$Needtocheck | Where {$_ -in $testing} |
Foreach {... do something for NeedToCheck tests that existing in $testing ... }
I had to change several pieces of the code as there were syntax errors. Guessing most were from trying to create some sample code for us to play with. I have many comments in the code but I will explain some as well outside of that.
$Reg = "HKLM:\Software\"
$testing = "Test1","Test2", "Test3"
$allTests = #(
New-Object -TypeName PSCustomObject -Property #{
Name = "Test1"
Logfile = "C:\Checking\test1.log"
Version = "16"
RegName = "test1Nameinfo*"
Installname = "InstallTest1"
UninstallName = "UninstallTest1"
}
New-Object -TypeName PSCustomObject -Property #{
Name = "Test2"
Logfile = "C:\test2.log"
Version = "7"
RegName = "test2Nameinfo*"
Installname = "InstallTest2"
UninstallName = "UninstallTest2"
}
New-Object -TypeName PSCustomObject -Property #{
Name = "Test3"
Logfile = "C:\Temp\Checkhere\test3.log"
Version = "99"
RegName = "test3Nameinfo*"
Installname = "InstallTest3"
UninstallName = "UninstallTest3"
}
)
$passed = $testing | ForEach-Object{
# Changed the for construct to better allow output. Added the next line to make the rest of the code the same.
$test = $_
$Key = (Get-Item $Reg).getvalue($Test)
If($Key -eq $null){
# New-Itemproperty creates output. Cast that to void to keep it out of $passed
[void](New-ItemProperty -path "HKLM:\Software\" -value "Check" -PropertyType string -name $Test -Force -ErrorAction SilentlyContinue)
Write-Host "$Test created"
# Send this test to output
Write-Output $Test
} Elseif ($key -eq "Check")
{
# Send this test to output
Write-Output $Test
} Else {
Write-Host "$Test already Checked"
}
}
$allTests | Where-Object{$passed -contains $_.Name}
We run all the values in $testing and if one is created or already "Checked" then we send it down the pipe where it populates the variable $passed. The we take $allTests and filter out every test that has a match.

Powershell: Add user to groups from array

I am trying to write a PowerShell script that will create a user based off of Department and Position and add them to the AD groups specific to that position. I have a function that creates the new user and attempts to join the user to a list of groups in an array.
function CreateUser{
$sam = "$first.$last";...;$pwd = ConvertTo-SecureString "password" -AsPlainText -Force
New-ADUser -Company "MyCompany" -Department $dept -Description $desc -DisplayName $dname -EmailAddress $email -GivenName $first -Office $office -Path $path -SamAccountName $sam -Surname $last -UserPrincipalName $email
foreach ($group in $groups) { if (Get-ADGroup $group) { Add-ADGroupMember $group $sam } }
}
I have another bit of code that creates the $groups array
$positions = #()
if ($dept -eq "CSR") { $positions += "CSR Rep","CSR Lead","CSR Manager" }
if ($dept -eq "IT") { $positions += "Sysadmin","Netadmin","Sqladmin" }
...
$groups = #()
if ($position -eq "CSR Rep") { $groups += "group1","group2","group3",...,"groupN" }
if ($position -eq "CSR Lead") { $groups += "group1","group2","group3","group4",...,"groupN" }
if ($position -eq "CSR Manager") { $groups += "group1","group2","group3","group4","group5",...,"groupN" }
if ($position -eq "Sysadmin") { $groups += "group6","group7",...,"groupN" }
if ($position -eq "Netadmin") { $groups += "group7","group8","group9",...,"groupN" }
if ($position -eq "Sqladmin") { $groups += "group10","group11","group12",...,"groupN" }
After I've specified which department and position the groups array is created and I call the CreateUsers function but I get errors back like it is an empty array.
Is there something I am missing with trying to pass the parameters to the function or is there a better way to accomplish this task?
Any assistance would be greatly appreciated.
Since your code does not show the function call and your function does not have any parameters defined i assume you are not passing anything to it.
Here is how to use parameters with three example parameters, one of them a String[]:
function CreateUser{
param(
[parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string[]] $groups,
[parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[hashtable] $userInfo,
[parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[securestring] $pwd
)
New-ADUser -Company "MyCompany" -Department $userInfo.dept -Description $userInfo.desc -DisplayName $userInfo.dname -EmailAddress $userInfo.email -GivenName $userInfo.first -Office $userInfo.office -Path $userInfo.path -SamAccountName $userInfo.sam -Surname $userInfo.last -UserPrincipalName $userInfo.email
foreach ($group in $groups) { if (Get-ADGroup $group) { Add-ADGroupMember $group $userInfo.sam } }
}
To keep the number of parameters low i have consolidated the user info into a hashtable. Hashtables are key-value sets and can be created like this:
$userInfo = #{sam="sam"; dept="department"; desc="description"; ...}
To call your function correctly do something like this:
CreateUser -groups $groups -userInfo $userInfo -pwd $pwd
You can of course add more parameters. For documentation on possible definitions and validationmethods see Technet
If you're going to create functions that are going to be more than simple things that take parameters I would strongly suggest including parameters with them. Such as:
function CreateUser{
Param([Parameter(Position=0)][string]$First = $(throw "You must specify a first name"),
[Parameter(Position=1)][string]$Last = $(throw "You must specify a last name"),
[Parameter(Position=2)][string]$Desc = $(throw "You must specify a description"),
[Parameter(Position=3)][string]$Dept = $(throw "You must specify a department"),
[Parameter(Position=4)][string]$Office = $(throw "You must specify an office"),
[Parameter(Position=5)][string]$Password = $(throw "You must specify a password"),
[string[]]$Groups
)
$sam = "$first.$last"
$pwd = ConvertTo-SecureString $Password -AsPlainText -Force
$email = "$first.$last#company.com"
$dname = "$First $Last"
$Path = "ou=$office,ou=Users,DN=company,DN=local"
New-ADUser -Company "MyCompany" -Department $dept -Description $desc -DisplayName $dname -EmailAddress $email -GivenName $first -Office $office -Path $path -SamAccountName $sam -Surname $last -UserPrincipalName $email
foreach ($group in $groups) { if (Get-ADGroup $group) { Add-ADGroupMember $group $sam } }
}
Then when you call the function you do it as such:
CreateUser "Jim" "Kirk" "Captain Extraordinaire" "Space" "$uper$ecret123" #("ExploreNewWorlds","WhereNoManHasGone")
Or you can specify arguments by name:
CreateUser -First "Jim" -Last "Kirk" -Desc "Captain Extraordinaire" -Dept "Space" -Password "$uper$ecret123" -Groups #("ExploreNewWorlds","WhereNoManHasGone")
...and while I got caught up in work trying to post this Paul beat me to it. Nice work Paul!
Edit: On a side note, I would like to introduce you to the Switch cmdlet. I think you would benefit greatly from it. While your several If statements probably do work, consider this:
Switch($position){
"CSR Rep" { $groups += "group1","group2","group3",...,"groupN";continue }
"CSR Lead" { $groups += "group1","group2","group3","group4",...,"groupN";continue }
"CSR Manager" { $groups += "group1","group2","group3","group4","group5",...,"groupN";continue }
"Sysadmin" { $groups += "group6","group7",...,"groupN";continue }
"Netadmin" { $groups += "group7","group8","group9",...,"groupN";continue }
"Sqladmin" { $groups += "group10","group11","group12",...,"groupN" }
}
That's simplistic, and in your case may not offer too much in performance improvement, but Switch offers a cleaner solution, and improved performance over several If statements. It also allows for more logic such as:
Switch($position){
{$_ -match "CSR" } { $groups += "group1", "group2" }
{$_ -match "CSR" -and -not $_ -match "Rep"} { $groups += "group3","Group4" }
}
That would add groups 1 and 2 for all CSR, and only Leads and Managers get groups 3 and 4. Anyway, just something to consider.

Resources