I have a script which I'd like to use PowerShell to bcp out data. I need to kick off multiple bcp commands and want to read 1. table name and 2. field name from a text file to populate the bcp command string.
Currently this doesn't work, but I'm not sure how to incorporate the 2 variables.
The text file looks like:
table: table1
table: table2
field: field1
field: field2
# Log file time stamp:
$LogTime = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
# Log file name:
$LogFile = "C:\Administration\Logs\BCPEXPORTLOG_" + $LogTime + ".log"
$database = "database"
$schema = "dbo"
$table = "TableName"
$tablename = Get-Content 'C:\Administration\Scheduled Tasks\CUBTableList.txt' |
? { $_ -match '^\s*table:\s*' } |
select -First 1 |
% { ($_ -split ':\s*', 2)[1] }
$fieldname = Get-Content 'C:\Administration\Scheduled Tasks\CUBTableList.txt' |
? { $_ -match '^\s*field:\s*' } |
select -First 1 |
% { ($_ -split ':\s*', 2)[1] }
foreach ($line in Get-Content 'C:\Administration\Scheduled Tasks\CUBTableList.txt') {
$bcp_command = "bcp 'SELECT * FROM $database.$schema.$tablename WHERE ($fieldname <= DATEADD(ms, -3, GETDATE()))' QUERYOUT 'D:\BCPOut\$database`_$tablename.txt' -c -U 'user' -P 'password'"
Tee-Object -FilePath $LogFile -InputObject $bcp_command -Append
$bcp_results = Invoke-Expression $bcp_command
Tee-Object -FilePath $LogFile -InputObject $bcp_results -Append
}
I've fixed up my dodgy script.
Used import-csv instead.
# Log file time stamp:
$LogTime = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
# Log file name:
$LogFile = "C:\Administration\Logs\BCPEXPORTLOG_"+$LogTime+".log"
$database = "database"
$schema = "dbo"
$table = "TableName"
Import-CSV 'C:\Administration\Scheduled Tasks\CUBList.csv' | ForEach{
$bcp_command = "bcp 'SELECT * FROM $database.$schema." + $_.tablename + " WHERE (" + $_.fieldname + " <= DATEADD(ms, -3, GETDATE()))' QUERYOUT 'D:\BCPOut\$database`_" + $_.tablename + ".txt' -c -U 'user' -P 'password'"
Tee-Object -FilePath $LogFile -InputObject $bcp_command -Append
$bcp_results = Invoke-Expression $bcp_command
Tee-Object -FilePath $LogFile -InputObject $bcp_results -Append
}
Try with this code:
$LogFile = "c:\temp\BCPEXPORTLOG_{0:MM-dd-yyyy_hh-mm-ss}.log" -f (Get-Date)
$database = "database"
$schema = "dbo"
#split with 'table:'
$Split1=(Get-Content c:\temp\CUBTableList.txt) -split 'table:'
#split fields and take only tablename <>'' and table have field
$Elements=$Split1 | %{
$Split2=$_ -split 'field:'
$table=$Split2[0];
[pscustomobject]#{TableName=$Split2[0].Trim(); Fields=$Split2[1..$($Split2.Length)] | %{$_.Trim()}} | where {$_.TableName -ne '' -and $_.Fields -ne $null}
}
$bcp_command=#()
#build bcp commands
$Elements | %{
$TableName=$_.TableName
$_.Fields | %{
$bcp_command+="bcp 'SELECT * FROM {0}.{1}.{2} WHERE {3} <= DATEADD(ms, -3, GETDATE())' QUERYOUT 'D:\BCPOut\{0}_{2}_{3}.txt' -c -U 'user' -P 'password'" -f $database, $schema, $TableName, $_
}
}
#run commands
$bcp_command | %{
$_ | out-file $LogFile -Append
try
{
$result=Invoke-Expression $_
}
catch
{
$result=$_.Exception.Message
}
finally
{
$result | Out-File $LogFile -Append
}
}
Related
I am a programming enthusiast and novice, I am using Powershell to try to solve the following need:
I need to extract the full path of files with extension .img. inside a folder with +/- 900 thousand folders and +/- million files. -/+ 900,000 img files.
Each img file must be processed in an exe. that is read from a file.
Which is better to store the result of the GetChildItem in a variable or a file?
I would greatly appreciate your guidance and support to optimize and / or find the best way to speed up processes vs. resource consumption.
Thank you un advance!!
This is the code I am currently using:
$PSDefaultParameterValues['*:Encoding'] = 'Ascii'
$host.ui.RawUI.WindowTitle = “DICOM IMPORT IN PROGRESS”
#region SET WINDOW FIXED WIDTH
$pshost = get-host
$pswindow = $pshost.ui.rawui
$newsize = $pswindow.buffersize
$newsize.height = 3000
$newsize.width = 150
$pswindow.buffersize = $newsize
$newsize = $pswindow.windowsize
$newsize.height = 50
$newsize.width = 150
$pswindow.windowsize = $newsize
#endregion
#
$out = ("$pwd\log_{0:yyyyMMdd_HH.mm.ss}_import.txt" -f (Get-Date))
cls
"`n" | tee -FilePath $out -Append
"*****************" | tee -FilePath $out -Append
"**IMPORT SCRIPT**" | tee -FilePath $out -Append
"*****************" | tee -FilePath $out -Append
"`n" | tee -FilePath $out -Append
#
# SET SEARCH FOLDERS #
"Working Folder" | tee -FilePath $out -Append
$path1 = Read-Host "Enter folder location" | tee -FilePath $out -Append
"`n" | tee -FilePath $out -Append
#
#
# SET & SHOW HOSTNAME
"SERVER NAME" | tee -FilePath $out -Append
$ht = hostname | tee -FilePath $out -Append
Write-Host $ht
Start-Sleep -Seconds 3
"`n" | tee -FilePath $out -Append
#
#
# GET FILES
"`n" | tee -FilePath $out -Append
#"SEARCHING IMG FILES, PLEASE WAIT..." | tee -FilePath $out -Append
$files = $path1 | Get-ChildItem -recurse -file -filter *.img | ForEach-Object { $_.FullName }
# SHOW Get-ChildItem PROCESS ON CONSOLE
Out-host -InputObject $files
"`n" | tee -FilePath $out -Append
Write-Output ($files | Measure).Count "IMG FILES FOUND TO PUSH" | tee -FilePath $out -Append
# DUMP Get-ChildIte into a file
$files > $pwd\pf
Start-Sleep -Seconds 5
# TIMESTAMP
"`n" | tee -FilePath $out -Append
"IMPORT START" | tee -FilePath $out -Append
("{0:yyyy/MM/dd HH:mm:ss}" -f (Get-Date)) | tee -FilePath $out -Append
"********************************" | tee -FilePath $out -Append
"`n" | tee -FilePath $out -Append
#
#
#SET TOOL
$ir = $Env:folder_tool
$pt = "utils\tool.exe"
#
#PROCESSING FILES
$n = 1
$pe = foreach ($file in Get-Content $pwd\pf ) {
$tb = (Get-Date -f HH:mm:ss) | tee -FilePath $out -Append
$fp = "$n. $file" | tee -FilePath $out -Append
#
$ep = & $ir$pt -c $ht"FIR" -i $file | tee -FilePath $out -Append
$as = "`n" | tee -FilePath $out -Append
# PRINT CONSOLE IMG FILES PROCESS
Write-Host $tb
Write-Host $fp
Out-host -InputObject $ep
Write-Host $as
$n++
}
#
#TIMESTAMP
"********************************" | tee -FilePath $out -Append
"IMPORT END" | tee -FilePath $out -Append
("{0:yyyy/MM/dd HH:mm:ss}" -f (Get-Date)) | tee -FilePath $out -Append
"`n" | tee -FilePath $out -Append
Try using parallel with PoshRSJob.
Replace Start-Process in Process-File with your code and note that there is no access to console. Process-File must return string.
Adjust $JobCount and $inData.
The main idea is to load all file list into ConcurrentQueue, start 20 background jobs and wait them to exit. Each job will take value from queue and pass to Process-File, then repeat until queue is empty.
NOTE: If you stop script, RS Jobs will continue to run until they finished or powershell closed. Use Get-RSJob | Stop-RSJob and Get-RSJob | Remove-RSJob to stop background work
Import-Module PoshRSJob
Function Process-File
{
Param(
[String]$FilePath
)
$process = Start-Process -FilePath 'ping.exe' -ArgumentList '-n 5 127.0.0.1' -PassThru -WindowStyle Hidden
$process.WaitForExit();
return "Processed $FilePath"
}
$JobCount = [Environment]::ProcessorCount - 2
$inData = [System.Collections.Concurrent.ConcurrentQueue[string]]::new(
[System.IO.Directory]::EnumerateFiles('S:\SCRIPTS\FileTest', '*.img')
)
$JobScript = [scriptblock]{
$inQueue = [System.Collections.Concurrent.ConcurrentQueue[string]]$args[0]
$outBag = [System.Collections.Concurrent.ConcurrentBag[string]]$args[1]
$currentItem = $null
while($inQueue.TryDequeue([ref] $currentItem) -eq $true)
{
try
{
# Add result to OutBag
$result = Process-File -FilePath $currentItem -EA Stop
$outBag.Add( $result )
}
catch
{
# Catch error
Write-Output $_.Exception.ToString()
}
}
}
$resultData = [System.Collections.Concurrent.ConcurrentBag[string]]::new()
$i_cur = $inData.Count
$i_max = $i_cur
# Start jobs
$jobs = #(1..$JobCount) | % { Start-RSJob -ScriptBlock $JobScript -ArgumentList #($inData, $resultData) -FunctionsToImport #('Process-File') }
# Wait queue to empty
while($i_cur -gt 0)
{
Write-Progress -Activity 'Doing job' -Status "$($i_cur) left of $($i_max)" -PercentComplete (100 - ($i_cur / $i_max * 100))
Start-Sleep -Seconds 3 # Update frequency
$i_cur = $inData.Count
}
# Wait jobs to complete
$logs = $jobs | % { Wait-RSJob -Job $_ } | % { Receive-RSJob -Job $_ }
$jobs | % { Remove-RSJob -Job $_ }
$Global:resultData = $resultData
$Global:logs = $logs
$Global:resultData is array of Process-File return strings
Which is better to store the result of the GetChildItem in a variable or a file?
If you're hoping to keep memory utilization low, the best solution is to not store them at all - simply consume the output from Get-ChildItem directly:
$pe = Get-ChildItem -Recurse -File -filter *.img |ForEach-Object {
$file = $_.FullName
$tb = (Get-Date -f HH:mm:ss) | tee -FilePath $out -Append
$fp = "$n. $file" | tee -FilePath $out -Append
#
$ep = & $ir$pt -c $ht"FIR" -i $file | tee -FilePath $out -Append
$as = "`n" | tee -FilePath $out -Append
# PRINT CONSOLE IMG FILES PROCESS
Write-Host $tb
Write-Host $fp
Out-host -InputObject $ep
Write-Host $as
$n++
}
What I like to do is pass the $sContractNumbers variable to the loop I have below which essentially pieces two csv files together based on the SQL queries.
I'm using the block below to get a value from an excel spreadsheet. Something that will be updated by a different user. The cell will always be static but the data in the cell will change in size so I have to use the IN clause.
My variable value looks like so.
$sContractNumbers = 'abc123','abc456','abc789','abc112','abc345'
$xl = New-Object -COM "Excel.Application"
$xl.Visible = $true
$wb = $xl.Workbooks.Open("C:\Dev\Blah\ManualContracts.xlsx")
$ws = $wb.Sheets.Item(1)
#Looking up a value in one column and assigning the corresponding value from another column to a variable could be done like this:
for ($i = 0; $i -le 1; $i++) {
if ( $ws.Cells.Item(1, 2).Text -eq $ColumnHeader ) {
$i = $i++;
$sContractNumbers = $ws.Cells.Item(2, 2).Value
#$sContractNumber
break
}
}
$wb.Close()
$xl.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl)
$sContractNumbers
Prior to adding this piece I was just copying and pasting my list of contracts in both queries.
Currently the error I'm getting is the following. I don't believe the loop is picking up on the variable. I've tried using AddWithValue but I don't think I'm placing it correctly, which is why its not listed. Fairly new to powershell but know a little bit of T-SQL. I think its a simple question but I cannot fully understand what I need to correct it since I'm noob. Be gentle...
$DetailContent[1] = "{0}`r`n{1}" -f $HeadeDetail, $DetailContent[1]
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Cannot index into a null array.
Function Run-Query
{
param([string[]]$queries,[string[]]$sheetnames)
Begin
{
$SQLServer = 'server'
$Database = 'warehouse'
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $Database; Integrated Security = True"
$FileNameDate = Get-Date -f 'yyyyMMdd'
}#End Begin
Process
{
# Loop through each query
For($i = 0; $i -lt $queries.count; $i++)
{
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $queries[$i]
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$DataSet.Tables[0] | Export-CSV -NoTypeInformation -Path "C:\Dev\blah\HeaderDetail\$($sheetnames[$i])_$FileNameDate-000.csv" -Delimiter '|'
}
}#End Process
End
{
$SqlConnection.Close()
}
}#End function run-query.
$queries = #()
$queries += #'
SET NOCOUNT ON
SET ANSI_WARNINGS OFF
/*FE Header*/
SELECT [sContractNumber] as ContractNumber,
into #Temp
FROM C
INNER JOIN D ON C.Id=D.iId
WHERE c.sContractNumber in ('$sContractNumbers')
order by sContractNumber
declare #TotalNewContracts int = 0
declare #TotalCanContracts int = 0
declare #TotalExpContracts int = 0
set #TotalNewContracts = (select COUNT(fe.ContractNumber) from #temp fe where Record_Type = 'P')
set #TotalCanContracts = (select COUNT(fe.ContractNumber) from #temp fe where Record_Type = 'C')
select
count(contractnumber) as 'Total Number of All Contracts',
FROM #temp ;
drop table #Temp;
'#
$queries += #'
SET NOCOUNT ON
SET ANSI_WARNINGS OFF
/*FE Header*/
SELECT [sContractNumber] as ContractNumber,
into #Table
FROM [pcmi_warranty_custom_twsi].[dbo].[Contract_Header] C
INNER JOIN [pcmi_warranty_custom_twsi].[dbo].[Dealer_Header] D ON C.iDealerId=D.iId
WHERE c.sContractNumber in ('$sContractNumbers')
order by sContractNumber
SELECT ContractNumber,
FROM #temp FE;
drop table #Temp;
'#
$sheetnames = #()
$sheetnames += 'Header'
$sheetnames += 'Details'
#FileName
$FileNameDate = Get-Date -f 'yyyyMMdd'
Run-Query -queries $queries -sheetnames $sheetnames
#Removes Double Quotes from File
(Get-Content C:\Dev\blah\HeaderDetail\Header_$FileNameDate-000.csv) | % {$_ -replace '"', ''} | out-file -FilePath C:\Dev\blah\Header\Header_$FileNameDate-000.csv -Force -Encoding ascii
(Get-Content C:\Dev\blah\HeaderDetail\Details_$FileNameDate-000.csv) | % {$_ -replace '"', ''} | out-file -FilePath C:\Dev\blah\Detail\Details_$FileNameDate-000.csv -Force -Encoding ascii
#Add Double Pipes as Delimter
(Get-Content C:\Dev\blah\Header\Header_$FileNameDate-000.csv) | % {$_ -replace "\|", "||"} | out-file -FilePath C:\Dev\blah\Header\Header_$FileNameDate-000.csv -Force -Encoding ascii
(Get-Content C:\Dev\blah\Detail\Details_$FileNameDate-000.csv) | % {$_ -replace "\|", "||"} | out-file -FilePath C:\Dev\blah\Detail\Details_$FileNameDate-000.csv -Force -Encoding ascii
#Add Header Detail Row to Detail File
#Header Path
$HeaderPath = "C:\Dev\blah\Header\Header_$FileNameDate-000.csv"
#Detail Path
$DetailsPath = "C:\Dev\blah\Detail\Details_$FileNameDate-000.csv"
#Gets second row of header file and sets it as a varaible
$HeadeDetail = Get-Content $HeaderPath -TotalCount 2 | Select-Object -Last 1;
#print the header detail row
$HeadeDetail
#Get Detail File content
$DetailContent = Get-Content -Path $DetailsPath
#Add Header Detail row to Detail file
$DetailContent[1] = "{0}`r`n{1}" -f $HeadeDetail, $DetailContent[1]
#Save Detail File
$DetailContent | Set-Content "C:\Dev\blah\blah$FileNameDate-000.csv" -Force -Encoding ascii
#Set the file name
$SourceFile = "C:\Dev\blah\blah$FileNameDate-000.csv"
$DestinationFolder = 'C:\Dev\blah'
$HeaderFile = "C:\Dev\blah\Header\Header_$FileNameDate-000.csv"
$DetailFile = "C:\Dev\blah\Detail\Details_$FileNameDate-000.csv"
$HDestinationFolder = 'C:\Dev\blah\Header'
$DDestinationFolder = 'C:\Dev\blah\Detail'
if (Test-Path $SourceFile)
{
$latest = Get-ChildItem -Path $DestinationFolder| Sort-Object Name -Descending | Select-Object -First 1
#split the latest filename, increment the number, then re-assemble new filename:
$newFileName = $latest.BaseName.Split('-')[0] + "-" + ([int]$latest.BaseName.Split('-')[1] + 1).ToString().PadLeft(3,"0") + $latest.Extension
Move-Item -path $SourceFile -destination $DestinationFolder"\"$newFileName
}
if (Test-Path $HeaderFile)
{
$latest = Get-ChildItem -Path $HDestinationFolder| Sort-Object Name -Descending | Select-Object -First 1
#split the latest filename, increment the number, then re-assemble new filename:
$newFileName = $latest.BaseName.Split('-')[0] + "-" + ([int]$latest.BaseName.Split('-')[1] + 1).ToString().PadLeft(3,"0") + $latest.Extension
Move-Item -path $HeaderFile -destination $HDestinationFolder"\"$newFileName
}
if (Test-Path $DetailFile)
{
$latest = Get-ChildItem -Path $DDestinationFolder| Sort-Object Name -Descending | Select-Object -First 1
#split the latest filename, increment the number, then re-assemble new filename:
$newFileName = $latest.BaseName.Split('-')[0] + "-" + ([int]$latest.BaseName.Split('-')[1] + 1).ToString().PadLeft(3,"0") + $latest.Extension
Move-Item -path $DetailFile -destination $DDestinationFolder"\"$newFileName
}
#Creates backup folder with corresponding date and places the file
$FolderName = Get-Date -f 'MMdd'
$FolderToCreate = "C:\Dev\blah\$FolderName"
if (!(Test-Path $FolderToCreate -PathType Container)) {
New-Item -ItemType Directory -Force -Path $FolderToCreate
}
Copy-Item -Path "$DestinationFolder\TWFE*.csv" -Destination $FoldertoCreate -force;
$ODrive = 'O:\blah\blah\blah'
$FolderToCopy = "O:\blah\blah\blah\$FolderName"
$LatestFile = Get-ChildItem -Path "$DestinationFolder\$FolderName" -Name TWFE*.csv | Sort-Object -Descending | Select-Object -First 1
if (!(Test-Path $FolderToCopy -PathType Container)) {
Copy-Item -Path "$DestinationFolder\$FolderName" -Destination $FolderToCopy -Recurse -Force -ErrorAction Continue
}
if ((Test-Path $FolderToCopy -PathType Container)) {
Copy-Item -Path $LatestFile -Destination $FolderToCopy -Recurse -Force -ErrorAction Continue
}
I currently have a CSV file that has 2,440 lines of data. The data looks something like:
server1:NT:Y:N:N:00:N
server2:NT:Y:N:n:33:N
This is what I have so far:
$newCsvPath = Get-Content .\sever.csv |
Where-Object { $_ -notmatch '^#|^$|^"#' }
[int]$windows = 0
[int]$totalsever = 0
$Results = #()
$date = Get-Date -Format g
Clear-Content .\results.csv -Force
foreach ($thing in $newCsvPath) {
$totalsever++
$split = $thing -split ":"
if ($split[1] -contains "NT") {
$windows++
$thing | Out-File results.csv -Append -Force
} else {
continue
}
}
Clear-Content .\real.csv -Force
$servers = Get-Content results.csv
foreach ($server in $servers) {
$server.Split(':')[0] | Out-File real.csv -Append -Force
}
My issue is that when the script gets to the $server.Split(':')[0] | Out-File real.csv -Append -Force part, for some reason it only outputs 1,264 lines instead of all 2,440 to "real.csv". However, when I remove | Out-File real.csv -Append -Force, $server stores ALL 2,400 names of servers.
Does anyone have any idea of why this is happening?
I'm using the following code to load SQL scripts from a folder and execute them.
foreach ($sqlScript in Get-ChildItem -path "$pathToScripts" -Filter *.sql | sort-object) {
Write-Host "Running Script " $sqlScript.Name
#Execute the query
switch ($removeComments) {
$true {
(Get-Content $sqlScript.FullName -Encoding UTF8 | Out-String) -replace '(?s)/\*.*?\*/', " " -split '\r?\ngo\r?\n' -notmatch '^\s*$' |
ForEach-Object { $SqlCmd.CommandText = $_.Trim(); $reader = $SqlCmd.ExecuteNonQuery() }
}
$false {
(Get-Content $sqlScript.FullName -Encoding UTF8 | Out-String) -split '\r?\ngo\r?\n' |
ForEach-Object { $SqlCmd.CommandText = $_.Trim(); $reader = $SqlCmd.ExecuteNonQuery() }
}
}
}
I've been asked if its possible to have some sort of table of contents to execute these files in a particular sequence without having to rename them. Is it possible to have a comma delimited file that I could loop through and load each file in the same sequence?
Edit
This is the code I think I'm going to go with:
Get-Content $executionOrder
ForEach ($file in $executionOrder) {
$sqlScript = $pathToScripts + "\" + $file
Write-Host "Running Script " $sqlScript.Name
#Execute the query
switch ($removeComments) {
$true {
(Get-Content $sqlScript -Encoding UTF8 | Out-String) -replace '(?s)/\*.*?\*/', " " -split '\r?\ngo\r?\n' -notmatch '^\s*$' |
ForEach-Object { $SqlCmd.CommandText = $_.Trim(); $reader = $SqlCmd.ExecuteNonQuery() }
}
$false {
(Get-Content $sqlScript -Encoding UTF8 | Out-String) -split '\r?\ngo\r?\n' |
ForEach-Object { $SqlCmd.CommandText = $_.Trim(); $reader = $SqlCmd.ExecuteNonQuery() }
}
}
}
Is it possible to have a comma delimited file that I could loop through and load each file in the same sequence
Yes. You just need to update your outer look logic to account for that input. With only minor changes you can get what you want.
foreach ($sqlScript in (Import-CSV $pathtoCSV)){
# Process file.
}
That would work if you wanted a CSV file input as you requested. In comments it looks like you are getting a static list of file names in a predefined directory.
$pathToFileList = "C:\Bagel.txt"
$rootScriptDirectory = "\\path\to\scripts"
$removeComments = $true
Get-Content $pathToFileList | ForEach-Object{
# Build the full file paths
$scriptFilePath = [io.path]::Combine($rootScriptDirectory,$_)
# If this file actually exists then it should be processed
If(Test-Path $scriptFilePath -PathType Leaf){
# Get the file contents
$fileContents = Get-Content $scriptFilePath -Encoding UTF8 | Out-String
# Clean the file contents as required
if($removeComments){
$queries = $fileContents -replace '(?s)/\*.*?\*/', " " -split '\r?\ngo\r?\n' -notmatch '^\s*$'
} else {
$queries = $fileContents -split '\r?\ngo\r?\n'
}
# Execute each query of the file
$queries | ForEach-Object{
$SqlCmd.CommandText = $_.Trim()
$reader = $SqlCmd.ExecuteNonQuery()
}
# Hilarity ensues
} else {
Write-Warning "Could not locate the file '$scriptFilePath'"
}
}
The features of switch are a little wasted here since you only have two states. Move the things that actually get changes into an if block. Get the file list and test that the file exists. Open it and parse the queries from it with your already set logic.
I am trying to write ALL the output to a logfile, and I seem to be doing something wrong. I also need the output on the screen.
Here is what I have so far:
# Log file time stamp:
$LogTime = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
# Log file name:
$LogFile = "EXPORTLOG_"+$LogTime+".log"
$database = "DB"
$schema = "dbo"
$table = "TableName"
foreach($line in Get-Content .\Alltables.txt) {
if($line -match $regex){
$bcp = "bcp $($database).$($schema).$($line) out $line.dat -T -c"
Invoke-Expression $bcp | Out-File $LogFile -Append -Force
}
}
When I want to write out the command to the logfile so I know which table is processed, I get an error:
Here is the code:
# Log file time stamp:
$LogTime = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
# Log file name:
$LogFile = "EXPORTLOG_"+$LogTime+".log"
$database = "DB"
$schema = "dbo"
$table = "TableName"
foreach($line in Get-Content .\Alltables.txt) {
if($line -match $regex){
$bcp = "bcp $($database).$($schema).$($line) out $line.dat -T -c" | Out-File $LogFile -Append -Force
Invoke-Expression $bcp | Out-File $LogFile -Append -Force
}
}
And the error:
Invoke-Expression : Cannot bind argument to parameter 'Command' because it is null.
At C:\Temp\AFLAC\export.ps1:16 char:21
+ Invoke-Expression $bcp | Out-File $LogFile -Append -Force
+ ~~~~
+ CategoryInfo : InvalidData: (:) [Invoke-Expression], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.InvokeExpressionCommand
I am obviously not very good with Powershell and I please need your advise on how I should code this the best possible way.
Maybe the above way is completely wrong, I do appreciate your guidance.
Thank you
Try modifying your code to something like this:
foreach($line in Get-Content .\Alltables.txt) {
if($line -match $regex) {
$bcp_command = "bcp $database" + '.' + $schema '.' + $line + ' out ' + $line + '.dat -T -c')
Tee-Object -FilePath $LogFile -InputObject $bcp_command -Append
$bcp_results = Invoke-Expression $bcp_command
Tee-Object -FilePath $LogFile -InputObject $bcp_results -Append
}
}