Assistance with combining two PowerShell scripts into one script.

Hello Forum,

I’ve managed to cobble together two PowerShell scripts with the following details:

Input file in Script #1 is an excel spreadsheet (.xlsx) that has this type of format:

Server1 192.168.40.10

Server2 192.168.40.11

Server3 192.168.4012

Where column A in the spreadsheet is the Sever Hostname and Column B in the spreadsheet is the IP address. There are no headings in this input file.

The output from Script #1 is to create .csv files of the input file broken down into 12 servers per .csv file. There will be as many .csv files as necessary based on the number of rows in the .xlsx file.

The input of Script #2 are the .csv files. Currently I need to run Script #2 for each .csv file created from Script #1.

I’m looking to bring together both scripts so that I read in the .xlsx file, and then create the output file of Script #2 where as many .mxtsessions files will be created based on 12 servers per .mxtsessions file. I hope I’m explaining this properly. Here are both scripts. Any advice or pointers you can provide on how to bring together both scripts into one would be greatly appreciated.

PowerShell script #1:

$file = "C:\mydirectory\InputFile.xlsx"
$batchDirectory = "C:\mydirectory"
$batchFileName="Results"
$sheetName = "Sheet1"
$batchNum = 1
$objExcel = New-Object -ComObject Excel.Application
$workbook = $objExcel.Workbooks.Open($file)
$sheet = $workbook.Worksheets.Item($sheetName)
$objExcel.Visible=$false
$rowMax = ($sheet.UsedRange.Rows).count
$rowHostname,$ColHostname = 0,1
$rowIP,$ColIP=0,2
for ($i=1; $i -le $rowMax; $i++)
{ 
$percentageComplete = ($i / $rowMax) * 100
$status= [Math]::Round($percentageComplete,2)
Write-Progress -Activity 'Creating Batches' -status "$status % complete" -PercentComplete $percentageComplete
$name = $sheet.Cells.Item($rowHostname+$i,$colHostName).text
$ip = $sheet.Cells.Item($rowIP+$i,$colIP).text
$csvRow= [pscustomobject]@{'hostname' = $name.Trim() ; 'ip' = $ip.Trim()}
$csvRow | Export-Csv -NoTypeInformation -Append -Path $batchDirectory\$batchFileName$batchNum.csv
if ($i % 12 -eq 0)
{ 
++$batchNum
}
}

 

PowerShell Script #2:

Function Get-FileName($initialDirectory)
{
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null

$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.initialDirectory = $initialDirectory
$OpenFileDialog.filter = "CSV (*.csv)| *.csv"
$OpenFileDialog.ShowDialog() | Out-Null
$OpenFileDialog.filename
}

$csvFilename = Get-FileName "C:\temp"
$inputdata = get-content $csvFilename


$csv = Import-Csv -Path $csvFilename -Delimiter ','

$SaveChooser = New-Object -TypeName System.Windows.Forms.SaveFileDialog
$SaveChooser.filter = "MXTSESSIONS (*.mxtsessions)| *.mxtsessions"
$SaveChooser.ShowDialog()

@'
[Bookmarks]
SubRep=
ImgNum=42
'@ | Out-File $SaveChooser.Filename -Encoding ASCII


$output = foreach ($line in $csv) {
"$($line.hostname)= #109#0%$($line.ip)%22%[username]%%-1%-1%%%22%%0%0%0%%%-1%0%0%0%%1080%%0%0%1#MobaFont 
%10%0%0%0%15%236,236,236%0,0,0%180,180,192%0%-1%0%%xterm%- 
1%0%0,0,0%54,54,54%255,96,96%255,128,128%96,255,96%128,255,128%255,255,54%255,255,128%96,96,255%128,128,255%255,54,255%255,128,255%5 
4,255,255%128,255,255%236,236,236%255,255,255%80%24%0%1%-1%<none>%%0#0#"
}


$output | Out-File $SaveChooser.Filename -Append -Encoding ASCII

I know I need to start with PowerShell script #1 and add somewhere in the for loop statement create the 12 serves per list AND add in the details from Script #2 to create the required .mxtsssions output file with the details I have in the output from Script #2…but I’m at a loss as to how to start this.

Any advice or pointers on what bits of Script #2 need to be added to the For loops of Script #1 to make this work for me would be greatly appreciated.

 

Are you saying that when you run these script individually, you get results you’d expect?

As for…

'Where column A in the spreadsheet is the Sever Hostname and Column B in the spreadsheet is the IP address. There are no headings in this input file.'

This does not matter, you can add headers as you read / Import the data in the XLS

Import-Csv -Path 'C:\mydirectory\InputFile.xlsx' # no headers

Or

Import-Csv -Path 'C:\mydirectory\InputFile.xlsx' -Header ServerName,IPAddress # Add headers 
# Use a loop to hit all servers the list
$ServerList = Import-Csv -Path 'C:\mydirectory\InputFile.xlsx' -Header ServerName,IPAddress # Add headers 
ForEach($Server in $ServerList)
{
    "Processing $($Server.ServerName)"
    # Your other code here
}

I am really not sure why you are doing this the way you are doing this. If all you need to do is read the xls to get server information, that is no need for the first script at all, and that Import-Csv, will read the xls natively.

You only need to call the XL DOM, if you are going to do something with the XLS, meaning create, update, delete stuff in it.

If you are doing that script just to produce this…

$batchDirectory\$batchFileName$batchNum.csv

… which is only to be read in / use by script 2, then these are two different process and in most cases should be different. From reading your script there is nothing in script 1 that is being used in script 2 and vice versa.
If you had to combine, you don’t really need to as you can call script 2 from 1 using the function name.

Hello Postanote and thank you for your reply.

It would appear that I haven’t posed my questions properly so thank you for asking for clarification. I’ll do my best to explain what I need.

Running each script works for me. But what I don’t like is the iterative process I need to go through to get to the result I need. I read in one file in script #1 out of script #1 I get as many files as there are 12 in the input file. So if there are 36 serves in my input .xlsx file I will receive 3 .csv files as output. I then have to run script #2 three times reading in each of the .csv files from script #1 in order to get 3 .mxtsessions files which is ultimately what my end goal is with running these 3 scripts.

Basically what I’m looking to do is to combine both scripts together so I read in the excel spreadsheet (I don’t need how it’s read in changed necessarily…it’s how script #1 reads in the file and it works) and from this combined script I will have created as many .mxtsessions files as there are sets of 12 servers from the input files.

But you make a comment that I could call the second script as a function. If in my example I have 36 servers and therefore will create 3 .csv files out of script #1, would I add in the a call at the end of each .csv file created as input to script #2 so that script #2 could be called 3 times to create each of my .mxtsession files? Where could this call be added to script #1 to make this work and what would have to change in script #2 to take in the input of the .csv file output from script #1?

 

Thank you.

With the help of ImportExcel module, i would change the script #1 like bellow.

$File = "C:\mydirectory\InputFile.xlsx"
Import-Excel -Path $File | Select-Object -Property @{E={$_.name.Trim()};L='hostname' ; E={$_.IP.Trim()} L='IP'} | Export-Csv -Path $OutputFilePath -NoTypeInformation

And to combine with and without csv file.

#With CSV file
$File = "C:\mydirectory\InputFile.xlsx"
Import-Excel -Path $File | Select-Object -Property @{E={$_.name.Trim()};L='hostname' ; E={$_.IP.Trim()} L='IP'} | Export=Csv -Path $OutputFilePath -NoTypeInformation

$csvFilename = Get-ChildItem -Path "C:\temp" -filter *.csv

foreach($CSv in $csvFilename.FullName){

$csv = Import-Csv -Path $csvFilename -Delimiter ','

$SaveChooser = New-Object -TypeName System.Windows.Forms.SaveFileDialog
$SaveChooser.filter = "MXTSESSIONS (*.mxtsessions)| *.mxtsessions"
$SaveChooser.ShowDialog()

@'
[Bookmarks]
SubRep=
ImgNum=42
'@ | Out-File $SaveChooser.Filename -Encoding ASCII


$output = foreach ($line in $csv) {
"$($line.hostname)= #109#0%$($line.ip)%22%[username]%%-1%-1%%%22%%0%0%0%%%-1%0%0%0%%1080%%0%0%1#MobaFont 
%10%0%0%0%15%236,236,236%0,0,0%180,180,192%0%-1%0%%xterm%- 
1%0%0,0,0%54,54,54%255,96,96%255,128,128%96,255,96%128,255,128%255,255,54%255,255,128%96,96,255%128,128,255%255,54,255%255,128,255%5 
4,255,255%128,255,255%236,236,236%255,255,255%80%24%0%1%-1%%%0#0#"
}


$output | Out-File $SaveChooser.Filename -Append -Encoding ASCII
}


#Without CSV file
$File = "C:\mydirectory\InputFile.xlsx"
Import-Excel -Path $File | ForEach-Object -Process {
$HostName = $_.name.Trim()
$IP = $_.IP.Trim()
$SaveChooser = New-Object -TypeName System.Windows.Forms.SaveFileDialog
$SaveChooser.filter = "MXTSESSIONS (*.mxtsessions)| *.mxtsessions"
$SaveChooser.ShowDialog()

@'
[Bookmarks]
SubRep=
ImgNum=42
'@ | Out-File $SaveChooser.Filename -Encoding ASCII



"$Hostname= #109#0%$($IP)%22%[username]%%-1%-1%%%22%%0%0%0%%%-1%0%0%0%%1080%%0%0%1#MobaFont 
%10%0%0%0%15%236,236,236%0,0,0%180,180,192%0%-1%0%%xterm%- 
1%0%0,0,0%54,54,54%255,96,96%255,128,128%96,255,96%128,255,128%255,255,54%255,255,128%96,96,255%128,128,255%255,54,255%255,128,255%5 
4,255,255%128,255,255%236,236,236%255,255,255%80%24%0%1%-1%%%0#0#"


$output | Out-File $SaveChooser.Filename -Append -Encoding ASCII
}

Hello kvprasoon and Wow! Thanks very much for your assistance.

Does your suggestion create multiple files of 12 servers in each file? I’m not seeing where this is done in your code?

I’ve tried the following:

I’m using Powershell Version 5.1.14409.1018 so I imported the ImportExcel module using >Install-Module ImportExcel and had no errors.

I’m using your suggestion of “Without csv file” and ran the script. I’m receiving the following error:

ForEach-Object : You cannot call a method on a null-valued expression.
At C:\scripts\script3.ps1:3 char:38

  • $Detail = Import-Excel -Path $File | ForEach-Object -Process {
  • CategoryInfo : InvalidOperation: (:slight_smile: [ForEach-Object], RuntimeException
  • FullyQualifiedErrorId : InvokeMethodOnNull,Microsoft.PowerShell.Commands.ForEach
    ObjectCommand

Here is my script I’m using:

#Without CSV file $File = "C:\mydirectory\InputFile.xlsx" $Detail = Import-Excel -Path $File | ForEach-Object -Process { $HostName = $_.name.Trim() $IP = $_.IP.Trim() $SaveChooser = New-Object -TypeName System.Windows.Forms.SaveFileDialog $SaveChooser.filter = "MXTSESSIONS (*.mxtsessions)| *.mxtsessions" $SaveChooser.ShowDialog()

@’
[Bookmarks]
SubRep=
ImgNum=42
'@ | Out-File $SaveChooser.Filename -Encoding ASCII

“$Hostname= #109#0%$($IP)%22%[username]%%-1%-1%%%22%%0%0%0%%%-1%0%0%0%%1080%%0%0%1#MobaFont
%10%0%0%0%15%236,236,236%0,0,0%180,180,192%0%-1%0%%xterm%-
1%0%0,0,0%54,54,54%255,96,96%255,128,128%96,255,96%128,255,128%255,255,54%255,255,128%96,96,255%128,128,255%255,54,255%255,128,255%5
4,255,255%128,255,255%236,236,236%255,255,255%80%24%0%1%-1%%%0#0#”

$output | Out-File $SaveChooser.Filename -Append -Encoding ASCII
}


 

Any suggestions on what I’m doing wrong to get this working?

 

Thank you.

You could put a breakpoint at Import-Excel command and debug the script in an Editor. Make sure the excel is not empty.