1

My script is supposed to get content of an exported XML file, connect to SharePoint (2010) and create folder/files according to the XML file content.

The XML file is build like this:

<?xml version="1.0" encoding="UTF-8"?>
<Domain name = "DomainName">
    <Environments>
        <Environment1 name = "Env1">
            <Applications>
                <Application1 name = "App1">
                    <Jobs>
                        <Job1 name = "Job1">
                        </Job1>
                        <Job2 name = "Job2">
                        </Job2>
                        <Job3 name = "Job3">
                        </Job3>
                    </Jobs>
                </Application1>
                <Application2 name = "App2">
                </Application2>
                <Application2>
                </Application2>
            </Applications>
        </Environment1>
        <Environment2 name = "Env2">
            ... content ...
        </Environment2>
        <Environment3>
            ... content ...
        </Environment3>
        <Environment4>
            ... content ...
        </Environment4>
    </Environments
    <ObjectInstructions>
        <ObjectInstruction objectName="ObjName1" instructionName="App">
        <ObjectInstruction objectName="ObjName2" instructionName="App">
        <ObjectInstruction objectName="ObjName3" instructionName="Job">
        <ObjectInstruction objectName="ObjName4" instructionName="Job">
        <ObjectInstruction objectName="ObjName5" instructionName="ForeWriter">
        <ObjectInstruction objectName="ObjName6" instructionName="MySite">
    </ObjectInstructions>
</Domain>

So folders and files have to be the Environment/Application or Job names. I managed to do this part. In fact almost everything works except one thing.

When my script encounters an Application or a Job with only one field, their name is not taken, the script skips it. It's because the variable is supposed to be an array, but in this particular case it is a String.

Part of the code that don't work well:

$CountEnv = $script:XmlContent.domain.Environments.Environment.Count # nb total of Environment
for ($e = 0; $e -lt $CountEnv; $e++) {
    $Envname = $script:XmlContent.domain.Environments.Environment[$e].name # Get the name of the Environment n°$e
    foreach ($Envelement in $Envname) {
        try {  # Creation folder Environment
            $ParentEnvFolder = $script:web.GetFolderByServerRelativeUrl($script:Library)
            $EnvFolder = $ParentEnvFolder.Folders.Add($Envelement)
            Write-Host " * Environment Folder : $Envelement created * " -ForegroundColor Magenta -BackgroundColor Black
            $compteurEnv++
            $script:ctx.Load($ParentEnvFolder)
            $script:ctx.ExecuteQuery()
        } catch {
            Write-Host " Error on Folder $Envelement creation "
        }

        ### LIGNES THAT CAUSE ME TROUBLES ###

        $CountApp = $script:XmlContent.domain.Environments.Environment[$e].Applications.Application.Count # nb total of Application in the actual Environment
        for ($a = 0; $a -lt $CountApp; $a++) {
            $Appname = $script:XmlContent.domain.Environments.Environment[$e].Applications.Application[$a].name # Get the name of the Application n°$a in the actual Environment
            if ($Appname -and $Appname.Length -eq 1) {
                $Appname = $script:XmlContent.domain.Environments.Environment[$e].Applications.Application.name
            }

            Write-Host " appname :"$Appname

            ### END LIGNES THAT CAUSE ME TROUBLES ###

            foreach ($Appelement in $Appname) {
                $cnA = Check-Names $Appelement # Verification that the Env / App or Job name don't contains specific words, here the cnA is for Application
                if ($cnA -eq 1) {
                    $ciA = Check-InstructionsApp $Envelement $Appelement # Verification that the Application name is present in the list of the objectName and that instructionName is App in ObjectIntruction
                    if ($ciA -eq 1) {
                        $GetAppfile = $script:web.GetFileByServerRelativeUrl("/$LastPart_ctxUrl/$script:Library/$Envelement/$Appelement.aspx")
                        $AfileExist = $false
                        try {  # Verification file Appplication.aspx exist
                            $script:ctx.Load($GetAppfile)
                            $script:ctx.ExecuteQuery()
                            $AfileExist = $GetAppfile.Exists
                        } catch { }
                        if ($AfileExist) {
                            Write-Host " File $Appelement.aspx Already exist"
                        } else {
                            try {  # Creation file Application.aspx
                                $AppFile = $ParentEnvFolder.Files.AddTemplateFile("/$LastPart_ctxUrl/$script:Library/$Envelement/"+"$Appelement.aspx",1)
                                $script:ctx.Load($AppFile)
                                $script:ctx.ExecuteQuery()
                                Write-Host " ** Application file : $Appelement created ** " -ForegroundColor Green -BackgroundColor Black
                                $compteurAppfile++
                            } catch {
                                Write-Host " Error, file creation $Appelement failed" -ForegroundColor Red -BackgroundColor Black
                                $ErrorMessage = $_.Exception.Message
                                $FailedItem = $_.Exception.ItemName
                            }
                        }
                    }
                }

                ### LIGNES THAT CAUSE ME TROUBLES ###

                $CountJob = $script:XmlContent.domain.Environments.Environment[$e].Applications.Application[$a].Jobs.Job.Count # nb total of Job in the actual Application
                for ($j = 0; $j -lt $CountJob; $j++) {
                    $Jobname = $script:XmlContent.domain.Environments.Environment[$e].Applications.Application[$a].Jobs.Job[$j].name # Get the name of the job n°$j in the actual Application
                    if ($Jobname -and $Jobname.Length -eq 1) {
                        $Jobname = $script:XmlContent.domain.Environments.Environment[$e].Applications.Application[$a].Jobs.Job.name
                    }
                    Write-Host " jobname : "$Jobname
                    ###END LIGNES THAT CAUSE ME TROUBLES ###

                    foreach ($Jobelement in $Jobname) {
                        $cnJ = Check-Names $Appelement $Jobelement # Verification that the Env / App or Job name don't contains specific words, here the cnJ is for Job
                        if ($cnJ -eq 2) {    
                            $ciJ = Check-InstructionsJob $Envelement $Appelement $Jobelement # Verification that the Job name is present in the list of the objectName and that instructionName is Job in ObjectIntruction
                            if ($ciJ -eq 1) {
                                try {  # Creation Folder Application
                                    $ParentAppFolder = $script:web.GetFolderByServerRelativeUrl("$script:Library/$Envelement/")
                                    $AppFolder = $ParentAppFolder.Folders.Add("$Appelement")
                                    $compteurAppFolder++ 
                                    Write-Host " ** Application Folder $Appelement created ** " -ForegroundColor Cyan -BackgroundColor Black
                                    $script:ctx.Load($ParentAppFolder)
                                    $script:ctx.ExecuteQuery()
                                } catch {
                                    Write-Host " Error on Application :$Appelement folder creation "
                                }

                                $GetJobfile = $web.GetFileByServerRelativeUrl("/$LastPart_ctxUrl/$script:Library/$Envelement/$Appelement/$Jobelement.aspx")
                                $JfileExist = $false
                                try {  # Verification file Job.aspx already exist
                                    $script:ctx.Load($GetJobfile)
                                    $script:ctx.ExecuteQuery()
                                    $JfileExist = $GetJobfile.Exists      
                                } catch { }
                                if ($JfileExist) {
                                    Write-Host " File $Jobelement.aspx Already exist"
                                }    

                                try {  # Creation file Job.aspx
                                    $JobFile = $ParentAppFolder.Files.AddTemplateFile("/$LastPart_ctxUrl/$script:Library/$Envelement/$Appelement/"+"$Jobelement.aspx",1)                                  
                                    $script:ctx.Load($JobFile)
                                    $script:ctx.ExecuteQuery()
                                    Write-Host " *** Job file : $Jobelement created *** " -ForegroundColor Yellow -BackgroundColor Black
                                    $compteurJob++
                                } catch {
                                    Write-Host " Error, file creation $Jobelement failed" -ForegroundColor Red -BackgroundColor Black
                                    $ErrorMessage = $_.Exception.Message
                                    $FailedItem = $_.Exception.ItemName
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
$compteurApp = $compteurAppfile + $compteurAppFolder
Write-Host "`nNumber of environment created: $compteurEnv," "Number of applications created: $compteurApp" " with $compteurAppFolder App folder and $compteurAppfile App file," "Number of job created: $compteurJob"

Let me know if I can provide any information that might be useful to you.

Edit : Thank you Ansgar for the link you provided, unfortunately I'm not in the same case.

By doing research I now have an idea where to head toward. As I said in the comment under yours, it's a problem of method. The ... .Aplications.Application.count and ....Applications.Application[0].Name don't exist in the case where there's only one or no values returned. I managed to make it work, but it's a disgusting way of doing it.

This is what changed:

$CountApp = $script:XmlContent.domain.Environments.Environment[$e].Applications.Application.Count
            if(!$CountApp)
            {
                $CountApp = 1
            }
            for($a = 0; $a -lt $CountApp; $a++)
            {
                try
                {
                    $Appname = $script:XmlContent.domain.Environments.Environment[$e].Applications.Application[$a].name
                    if(!$Appname)
                    {
                            $Appname = $script:XmlContent.domain.Environments.Environment[$e].Applications.Application.name
                    }
                }
                catch{ }

And before

$CountApp = $script:XmlContent.domain.Environments.Environment[$e].Applications.Application.Count # nb total of Application in the actual Environment
for ($a = 0; $a -lt $CountApp; $a++) {
    $Appname = $script:XmlContent.domain.Environments.Environment[$e].Applications.Application[$a].name # Get the name of the Application n°$a in the actual Environment
    if ($Appname -and $Appname.Length -eq 1) {
        $Appname = $script:XmlContent.domain.Environments.Environment[$e].Applications.Application.name
    }

So with this modification, now I do create everything but I got an error because I force $CountApp to 1 even if there's nothing.

I fixed that with the Try{]Catch{} around $Appname.

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
Yami
  • 44
  • 4
  • Use the [array subexpression operator](https://msdn.microsoft.com/en-us/powershell/reference/5.0/microsoft.powershell.core/about/about_operators) to ensure that the result of the expression is an array. – Ansgar Wiechers May 22 '17 at 21:14
  • Possible duplicate of [How do I merge two "lists" in PowerShell when one list might be just one item from Get-Item?](https://stackoverflow.com/questions/30801868/how-do-i-merge-two-lists-in-powershell-when-one-list-might-be-just-one-item-fr) – Ansgar Wiechers May 22 '17 at 21:15
  • Thank you for the answers. while working on this, i found something new. In fact, for exemple : `$script:XmlContent.domain.Environments.Environment[$e].Applications.Application.Count` doesn't work if in the actual environement there's only one Aplication. so the value would be $null So does `$script:XmlContent.domain.Environments.Environment[$e].Applications.Application[0].Name` because here it's not an Array but a String – Yami May 23 '17 at 16:47

0 Answers0