This question already has an answer here:
Parameter interpretation when running jobs
(1 answer)
Closed 3 years ago.
I have a running PS1-script (start-webserver.ps1) running as a "web server" that is listening for http calls that executes a script (example: script2.ps1) executed in the call to the "web server".
I am executing the script with Start-Job. How can I in the executed script (script2.ps1) access variables in start-webserver.ps1?
Start-WebServer.ps1
$allObjects = #()
foreach ($item in $items) {
$objectUID = $item.Attributes.Value
$propertiesHash = [ordered]#{UID = $objectUID}
$properties = $items.ChildNodes
foreach ($property in $properties.ChildNodes) {
$propertyName = $property.Attributes.Value
$propertyValue = $property.innerText
$propertiesHash.Add($propertyName, $propertyValue)
}
$object = New-Object PSObject -Property $propertiesHash
$allObjects += $object
}
$job = Start-Job -Name "$identifier" -FilePath "Path\To\ScriptToExecute.ps1" -InputObject $allObjects -ArgumentList $propertiesHash
ScriptToExecute.ps1
'Script executed!' | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
$propertiesHash | Get-Member | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
$allObjects | Get-Member | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
I end up with an "output.txt" with the following content:
Script executed!
Empty line
You need to define in ScriptToExecute that you are receiving params
By default it is set in the $args variable.
In your case, simply using $args[0] will be sufficient.
i.e.:
'Script executed!' | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
$args[0] | Get-Member | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
If you want to also receive $allObjects, you need to modify Start-WebServer to this:
$job = Start-Job -Name "$identifier" -FilePath "Path\To\ScriptToExecute.ps1" -InputObject $allObjects -ArgumentList #($propertiesHash,$allObjects)
then do this:
'Script executed!' | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
$args[0] | Get-Member | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
$args[1] | Get-Member | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
Nicer way of doing this is to specify the param in ScriptToExecute
i.e.:
param($propertiesHash, $allObjects)
'Script executed!' | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
$propertiesHash | Get-Member | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
$allObjects | Get-Member | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
Related
I am new to PowerShell and I get a lot done using this forum along with other internet searched answers but this one is getting the better of me. I have a script that compares two folders and the part where I'm having problems I cannot get the BitsTransfer source to work. $Differences identifies files from the source folder that are not in the target folder by modified date. I want the BitsTransfer to move the files identified by $Differences but I'm not having any luck getting that behavior. The operation works when I use "Copy-Item -Path $Differences -Destination $Local –Force" instead but i want the progress bar BitsTransfer Uses. The code i am using is as follows
$Local = 'c:\test\local\'
$Remote = 'c:\test\server\'
$Target = Get-ChildItem -Path $Local -File
$Source = Get-ChildItem -Path $Remote -File
Import-Module BitsTransfer
Set-Location $Remote
filter timestamp {"$(Get-Date -Format g): $_"}
if ($Target -eq $null) {
$bitsjob = Start-BitsTransfer -Source $Remote\*.* -Destination $Local
Write-Output "$Local Folder Empty" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"
Rename-Item -Path "D:\Mitek\DCS Stuff\Display PC Scripts\test\RemoteComplete.bat" -NewName "Remote.bat"
Exit
} Else {
if ($Target -ne $null){
Compare-Object $Source $Target -Property Name -PassThru | Where-Object {$_.SideIndicator -eq "=>"} | % {
if(-not $_.FullName.PSIsContainer) {
Write-Output "Removed From $Local" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"
Remove-Item -Path $_.FullName -Force -ErrorAction SilentlyContinue}}}}
$Differences = Compare-Object -ReferenceObject $Source -DifferenceObject $Target -Property LastWriteTime -PassThru
$Differences | Group-Object Name | Select -ExpandProperty Group | Sort-Object LastWriteTime | Select-Object -Last 1
if ($Differences -ne $null) {
foreach ($file in $Differences) {
#Copy-Item -Path $Differences -Destination $Local –Force
Start-BitsTransfer -Source $Differences -Destination $Local
Write-Output "Copied to $Local" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"
Rename-Item -Path "D:\Mitek\DCS Stuff\Display PC Scripts\test\RemoteComplete.bat" -NewName "Remote.bat"}
} Else {
Write-Output "$Local and $Remote are Equal" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"}`
I got the issue figured out with some looping behavior the code used to resolve the issue is bellow for those who may find this helpful in the future...
$Local = 'C:\test\local\'
$Remote = 'C:\test\server\'
$Target = Get-ChildItem -Path $Local -File
$Source = Get-ChildItem -Path $Remote -File
$One = 1
Set-Location $Remote
filter timestamp {"$(Get-Date -Format g): $_"}
if ($Target -eq $null) {
$TotalA = $Source | Measure | Select-Object -ExpandProperty Count
echo "Total Number of Files to be Copied= $TotalA"
echo "---------------------------------------------------------------"
Write-Output "$Local Folder Empty" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"
Start-BitsTransfer -Source $Remote\*.* -Destination $Local -Description "Copying $TotalA Files"
Rename-Item -Path "C:\test\RemoteComplete.bat" -NewName "Remote.bat"
exit
} Else {
if ($Target -ne $null){
Compare-Object $Source $Target -Property Name -PassThru | Where-Object {$_.SideIndicator -eq "=>"} | % {
if(-not $_.FullName.PSIsContainer) {
Write-Output "Removed From $Local" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"
Remove-Item -Path $_.FullName -Force -ErrorAction SilentlyContinue}}}}
$Differences = Compare-Object -ReferenceObject $Source -DifferenceObject $Target -Property LastWriteTime -PassThru
if ($Differences -ne $null) {
$TotalB=$Differences | Group-Object Name | Select -ExpandProperty Group | Sort-Object Name | Measure | Select-Object -ExpandProperty Count
echo "Total Number of Files to be Copied= $TotalB"
Write-Output "Copied to $Local" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"
do {
$Tar = Get-ChildItem -Path $Local -File
$Src = Get-ChildItem -Path $Remote -File
$Diffs = Compare-Object -ReferenceObject $Src -DifferenceObject $Tar -Property LastWriteTime -PassThru
$ListB=$Diffs | Group-Object Name | Select -ExpandProperty Group | Sort-Object Name | Select-Object -First 1
if ($ListB -ne $null) {
echo "---------------------------------------------------------------"
$Rmn=$Diffs | Group-Object Name | Select -ExpandProperty Group | Sort-Object Name | Measure | Select-Object -ExpandProperty Count
$RemainB = $Rmn - $One
Start-BitsTransfer -Source $ListB -Destination $Local -Description "$RemainB Files Remain Copying - $List" }}
Until ($ListB -eq $null)
Rename-Item -Path "C:\test\RemoteComplete.bat" -NewName "Remote.bat"
} Else {
Write-Output "$Local and $Remote are Equal" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"}
This question already has answers here:
Export-Csv emits Length and not values
(2 answers)
Closed 5 years ago.
When I run the code below the data I get in the csv doesn't have the server names I'm expecting.
Instead this is what I get in the .csv file
Length
204
Why is this?
$varoutfile = "\\unc_path\server $(get-date -f yyyy-MM).csv"
$varDOW = (get-date).DayOfWeek
$varservertoreboot = "server1" , "server2" , "server1" ,
if ($varDOW -eq "Sunday") {
foreach ($server in $varservertoreboot) {
Restart-Computer $varservertoreboot -Force
"$(get-date -f yyyy-MM-dd-HH-mm-ss) Today is $vardow, The system
$varservertoreboot is rebooting" | Export-Csv $varoutfile -Append -NoClobber -NoTypeInformation
}
}
else {}
if ($varDOW -eq "Wednesday") {
foreach ($server in $varservertoreboot) {
Restart-Computer $varservertoreboot -Force
"$(get-date -f yyyy-MM-dd-HH-mm-ss) Today is $vardow, The system $varservertoreboot is rebooting" | Export-Csv $varoutfile -Append -NoClobber
}
}
I'd replace:
"$varservertoreboot is rebooting" | Export-Csv $varoutfile -Append -NoClobber -NoTypeInformation
"$(get-date -f yyyy-MM-dd-HH-mm-ss) Today is $vardow, The system $varservertoreboot is rebooting" | Export-Csv $varoutfile
With:
Add-Content -Value "$varservertoreboot is rebooting" -Path $varoutfile
Add-Content -Value "$(get-date -f yyyy-MM-dd-HH-mm-ss) Today is $vardow, The system $varservertoreboot is rebooting" -Path $varoutfile
I am really new to PowerShell and still learning so I am having a requirement to run some of the commands from dbatools and save the results.
$servers = 'E:\DBA\servers.txt'
$outfile = 'E:\DBA\out.csv'
Get-Content $servers | ForEach-Object {Invoke-Command DbaBackupHistory -SQLServer $_ | ConvertTo-CSV -NoTypeInformation | Select-Object -Skip 1 | Out-File -Append $outFile}
I am unsure if this is the correct way to doit
https://dbatools.io/functions/get-dbabackuphistory/
I modified you script and tested. Worked for me. I added 2 more switches to limit result set. -database and -lastfull. You can check documentation for details.
$outfile = 'c:\out.csv'
Get-Content c:\servers.txt|foreach-object {get-DbaBackupHistory -SqlServer $_
-database dbadatabase -lastfull | ConvertTo-CSV -NoTypeInformation |
Select-Object -Skip 1 | Out-File -Append $outFile}
I have a PS script which Invoke-Expression on other scripts on the same computer.
Here is the code:
$webMemory = "C:\Memory_Script\WebMemory_Script.ps1"
$intMemory = "C:\Memory_Script\IntMemory_Script.ps1"
$hungWeb = "C:\Scripts\HungWeb_Script.ps1"
$hungInt = "C:\Scripts\HungInt_Script.ps1"
$intMemoryResult = #()
$webMemoryResult = #()
$hungWebResult = #()
$hungIntResult = #()
$date = Get-Date
$shortDate = (get-date -format ddMMyyy.hhmm)
$filepath = "C:\Scripts\Memory&HungResults\Results" + $shortdate + ".txt"
$break = "`r`n"
out-file -filepath $filepath -inputobject $date -force -encoding ASCII -width 50
out-file -filepath $filepath -Append -inputobject $break -encoding ASCII -width 50
$intMemoryResult += Invoke-Expression $intMemory
$webMemoryResult += Invoke-Expression $webMemory
$hungWebResult += Invoke-Expression $hungWeb
$hungIntResult += Invoke-Expression $hungInt
Write-host $webMemoryResult
out-file -filepath -Append -inputobject $intMemoryResult -encoding ASCII -width 200
out-file -filepath -Append -inputobject $break -encoding ASCII -width 200
out-file -filepath -Append -inputobject $webMemoryResult -encoding ASCII -width 200
out-file -filepath -Append -inputobject $break -encoding ASCII -width 200
out-file -filepath -Append -inputobject $hungIntResult -encoding ASCII -width 200
out-file -filepath -Append -inputobject $break -encoding ASCII -width 200
out-file -filepath -Append -inputobject $hungWebResult -encoding ASCII -width 200
out-file -filepath -Append -inputobject $break -encoding ASCII -width 200
Code in one of the scripts being called (the other three have similar functions)
$serverList = #("List of servers")
$w3wpMemory = #()
$w3wpMemory += "---------- W3WP Memory Consumption ----------"
$w3wpresult = #()
$toBeRecycled =#()
$toBeRecycled += "******************** THE INT SERVERS BELOW NEED TO BE RECYCLED (Hung) ********************" + "`r`n"
$date = Get-Date
$shortDate = (get-date -format ddMMyyy.hhmm)
$filepath = "C:\Scripts\HungIntResults\HungServerResults" + $shortdate + ".txt"
$break = "`r`n"
out-file -filepath $filepath -inputobject $date -force -encoding ASCII -width 50
out-file -filepath $filepath -Append -inputobject $break -encoding ASCII -width 50
ForEach($server in $serverList)
{
$w3wpresult += (get-wmiobject Win32_Process -filter "commandline like '%serviceoptimization%'" -computername $server).privatepagecount / 1gb
$w3wpMemory += $server + ":" + $w3wpresult + "`n"
}
$i = 0
ForEach($server in $serverList)
{
$w3wpresult2 = (get-wmiobject Win32_Process -filter "commandline like '%serviceoptimization%'" -computername $server).privatepagecount / 1gb
Write-Host $w3wpresult2 " , " ($w3wpresult | select-object -index $i)
if($w3wpresult -contains ($w3wpresult2))
{
$toBeRecycled += $server + "`r`n"
}
$i = $i + 1
}
$toBeRecycled += "*******************************************************************************"
$toBeRecycled += "`r`n"
Write-Host $toBeRecycled
out-file -filepath $filepath -Append -inputobject $toBeRecycled -encoding ASCII -width 100
return $toBeRecycled
When the script runs, I see the output of from the execution of the other scripts.
The results from the "Invoke-Expression" command are returning null, why is this?
Write-Host writes directly to the host display. If you want to capture this output then use Write-Output instead or just put a variable on a line by itself because the default output is the "output" stream:
$toBeRecycled
BTW when you execute a PowerShell script from another PowerShell script, the child script will execute synchronously (unless you are using jobs).
I have a powershell scripts that runs and gets security permissions in a server and output these in a csv. At the moment its outputting the information but with each file it reads it is including the header Account, Ace String and Object Path again: how do i remove so it only shows it at the start of the document only?
Account,Ace String,Object Path
NT AUTHORITY\SYSTEM,Allow FullControl, (Inherited),C:\Users\munjanga\Documents\Operations Orchestration\jetty
BUILTIN\Administrators,Allow FullControl, (Inherited),C:\Users\munjanga\Documents\Operations Orchestration\jetty
EMEA\munjanga,Allow FullControl, (Inherited),C:\Users\munjanga\Documents\Operations Orchestration\jetty
Account,Ace String,Object Path
NT AUTHORITY\SYSTEM,Allow FullControl, (Inherited),C:\Users\munjanga\Documents\Operations Orchestration\jre1.6
$OutFile = "C:\Users\munjanga\Documents\AoN Project\Execute\$([Environment]::MachineName).txt"
$Header = "Folder Path,IdentityReference,AccessControlType,IsInherited,InheritanceFlags,PropagationFlags"
Del $OutFile
Add-Content -Value $Header -Path $OutFile
$RootPath = "C:\Users\munjanga\Documents\Operations Orchestration"
$Folders = dir $RootPath -recurse | where {$_.psiscontainer -eq $true}
$isInherited = #{
$true = 'Inherited'
$false = 'Not Inherited'
}
$inheritance = #{
0 = 'files only'
1 = 'this folder and subfolders'
2 = 'this folder and files'
3 = 'subfolders and files'
}
$fldr = $Folder.FullName
$Folders | % {
$fldr = $_.FullName
Get-Acl $fldr | select -Expand Access |
select #{n='Account';e={$_.IdentityReference}},
#{n='Ace String';e={"{0} {1}, {2} ({3})" -f $_.AccessControlType,
$_.FileSystemRights, $inheritance[$_.InheritanceFlags],
$isInherited[$_.IsInherited]}},
#{n='Object Path';e={$fldr}} | ConvertTo-Csv -NoTypeInformation | % {$_ -replace '"', ""} | Out-File $OutFile -Force -Encoding ascii -Append}
Let's see if this works:
#{n='Object Path';e={$fldr}} | ConvertTo-Csv -NoTypeInformation | Select -Skip 1 | % {$_ -replace '"', ""} | Out-File $OutFile -Force -Encoding ascii -Append
The key bit is the Select -Skip 1 after the ConvertTo-Csv piece.
Edit:
After thinking this through a bit more there's a better answer here. The last line should look something like this:
#{n='Object Path';e={$fldr}}} | ConvertTo-Csv -NoTypeInformation | % {$_ -replace '"', ""} | Out-File $OutFile -Force -Encoding ascii -Append
That loop should be closed before converting to CSV.