I am looking to convert all .doc documents that end up in a specific folder. This part I have covered (see below code). The issue that I am having is there is a field that is inside of the document itself that breaks every time you try to save the document as a different file type. If you highlight the field and lock it (CRTL + F11) then save works like a champ. If you have any ideas at all please let me know. I am willing to try anything out at this point in time.
$wdFormatPDF = 17
$word = New-Object -ComObject word.application
$word.visible = $false
$folderpath = "c:\test\*"
$fileTypes = "*.doc"
Get-ChildItem -path $folderpath -include $fileTypes |
foreach-object `
{
$path = ($_.fullname).substring(0,($_.FullName).lastindexOf("."))
"Converting $path to pdf ..."
$doc = $word.documents.open($_.fullname)
$doc.saveas([ref] $path, [ref]$wdFormatPDF)
$doc.close()
}
$word.Quit()
After you grab the filename and remove extension you didn't append .pdf to to it.
$path = ($_.fullname).substring(0,($_.FullName).lastindexOf("."))
"Converting $path to pdf ..."
You are missing this line
$path = $path + ".pdf"
## $doc = $word.documents.open($_.fullname)
$doc.saveas([ref] $path, [ref]$wdFormatPDF)
If that doesn't help then $doc has Fields.Locked Property which you set it to True or False.
$doc.Fields.Locked = $true
Related
I would like to modify this script if possible:
((Get-Content -path "C:\Users\User1\OUT\Summary.txt" -Raw) -replace '</ab></cb>','</x>') | Set-Content -Path "C:\Users\User1\OUT\Summary.txt"
I would like a script that will run with Windows OS to search through one file it finds at this path:
C:\Users\User1\File\Summary.txt
And within that file, when it finds data starting with: <a><b>Data
And at the same time ending with: </ab></cb>
It would need to change the ending to: </x>
And it would need to save the file without changing the name of the file.
For instance a line showing this data:
<a><b>Data:</y> 12345678</ab></cb>
Would be changed to:
<a><b>Data:</y> 12345678</x>
The PowerShell script above will find all instances of </ab></cb> and replace it with </x>, which is not what I am hoping to accomplish.
You can use Get-Content to process the file line be line and only do the Replace when you have a Match on <a><b>. Something like this:
$InFile = ".\TestIn.txt"
$OutFile = ".\TestOut.txt"
If (Test-Path -Path $OutFile) {Remove-Item $OutFile}
Get-Content $InFile | ForEach-Object -Process {
$NewLine = $_
If ($_ -Match '<a><b>') {
$NewLine = ($_ -Replace '</ab></cb>','</x>')
}
Add-Content $OutFile $NewLine
}
This is my first time using Powershell so please forgive my ignorance.
I have a SQL query that returns back a bunch of order numbers. I want to check another file to see if there is an existing PDF in that file with the same name as the orders numbers returned by the SQL query.
Everything in my code works up until the ForEach loop which returns nothing. Based on my google searches I think I'm pretty close but I'm not sure what I'm doing wrong. Any help would be appreciated.
I've removed the actual file name for obvious reasons, and I do know that the file is correct and other commands do access it so I know that is not my problem at the moment. I've also removed sensitive info from the SQL query.
$statement = "SELECT A, Date FROM XXXX
WHERE STAT = 1 AND Date >= trunc(sysdate)"
$con = New-Object System.Data.OracleClient.OracleConnection($connection_string)
$con.Open()
$cmd = $con.CreateCommand()
$cmd.CommandText = $statement
$result = $cmd.ExecuteReader()
$list = while ($result.Read()) { $result["A"]}
Write-Output $list​
#########Loop through the list above here to check for matching PDF
ForEach ($Order in $list){
Get-ChildItem "\\xxxxxx\" -Filter $Order -File
#########If FALSE - notify that PDF is missing
}
$con.close()
I have also tried the following code, which gets me closer and actually finds the files I'm looking for, but gives the error
" Get-ChildItem : A positional parameter cannot be found that accepts argument
CategoryInfo : InvalidArgument: (:) [Get-ChildItem], ParameterBindingException
FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand"
ForEach ($Order in $list){
if((Get-ChildItem "\\xxxxx\" + $Order)){
Write-Output
} else { Write-Host "Does not exist."}
I gather from your comment that $list is an array of order numbers.
Next, you want to check if there is a file in a folder having that name, correct?
Then I'd suggest you use Test-Path instead of Get-ChildItem:
$folderToSearch = '\\servername\sharename\folder'
foreach ($Order in $list) {
$fileToCheck = Join-Path -Path $folderToSearch -ChildPath ('{0}.pdf' -f $Order)
if (Test-Path -Path $fileToCheck -PathType Leaf) {
"File found: $fileToCheck"
}
else {
"File $fileToCheck does not exist"
}
}
I've got a PowerShell script that I call from VBA using Excel. The script uses WinSCP to download some datetime-named FTP and SFTP files and saves them with a static filename, overwriting the old file, on a network drive location.
The script works on first run, but after that it loads the same cached version of the file. The workaround is to change the cache settings in IE to check for newer versions of stored webpages 'every time I visit the webpage'.
The macro is used by several people and is accessed using a variety of computers. Is there a way around this that I can incorporate in my code, either in VBA or PS so they don't have to remember to go into IE to change their settings?
Script is called from VBA:
Call Shell("powershell -executionpolicy bypass & ""H:\FTP\FTP.ps1""", vbHide)
Script:
try
{
# Load WinSCP .NET assembly
Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"
$localPath = "H:\Worksheets\FTP"
$remotePath = "/outgoing/data/LatestData/"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.Protocol = [WinSCP.Protocol]::ftp
$sessionOptions.HostName =
$sessionOptions.UserName =
$sessionOptions.Password =
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
# Get list of files in the directory
$directoryInfo = $session.ListDirectory($remotePath)
# Select the most recent file
$latest = $directoryInfo.Files |
Where-Object { -Not $_.IsDirectory} |
Where-Object {
[System.IO.Path]::GetExtension($_.Name) -eq ".nc1" -or
[System.IO.Path]::GetExtension($_.Name) -eq ".ky1" -or
[System.IO.Path]::GetExtension($_.Name) -like ".tn*" }
Group-Object { [System.IO.Path]::GetExtension($_.Name) } |
ForEach-Object{
$_.Group | Sort-Object LastWriteTime -Descending | Select -First 1
}
$extension = [System.IO.Path]::GetExtension($latest.Name)
"GetExtension('{0}') returns '{1}'" -f $fileName, $extension
if ($latest -eq $Null)
{
Write-Host "No file found"
exit 1
}
$latest | ForEach-Object{
$extension = ([System.IO.Path]::GetExtension($_.Name)).Trim(".")
$session.GetFiles($session.EscapeFileMask($remotePath + $_.Name), "$localPath\$extension.txt" ).Check()
}
$stamp = $(Get-Date -f "yyyy-MM-dd-HHmm")
$filename = $stamp.subString(0,$stamp.length-6)
$session.GetFiles(
($remotePath + $fileName),
($localPath + $fileName + "." + $stamp)).Check()
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
exit 0
}
catch [Exception]
{
Write-Host $_.Exception.Message
exit 1
}
The script I'm working on is producing a log file every time it runs. The problem is that when the script runs in parallel, the current log file becomes inaccessible for Out-File. This is normal because the previous script is still writing in it.
So I would like the script being able to detect, when it starts, that there is already a log file available, and if so, create a new log file name with an increased number between the brackets [<nr>].
It's very difficult to check if a file already exists, as it can have another number each time the script starts. It would be great if it could then pick up that number between the brackets and increment it with +1 for the new file name.
The code:
$Server = "UNC"
$Destination ="\\domain.net\share\target\folder 1\folder 22"
$LogFolder = "\\server\c$\my logfolder"
# Format log file name
$TempDate = (Get-Date).ToString("yyyy-MM-dd")
$TempFolderPath = $Destination -replace '\\','_'
$TempFolderPath = $TempFolderPath -replace ':',''
$TempFolderPath = $TempFolderPath -replace ' ',''
$script:LogFile = "$LogFolder\$(if($Server -ne "UNC"){"$Server - $TempFolderPath"}else{$TempFolderPath.TrimStart("__")})[0] - $TempDate.log"
$script:LogFile
# Create new log file name
$parts = $script:LogFile.Split('[]')
$script:NewLogFile = '{0}[{1}]{2}' -f $parts[0],(1 + $parts[1]),$parts[2]
$script:NewLogFile
# Desired result
# \\server\c$\my logfolder\domain.net_share_target_folder1_folder22[0] - 2014-07-30.log
# \\server\c$\my logfolder\domain.net_share_target_folder1_folder22[1] - 2014-07-30.log
#
# Usage
# "stuff" | Out-File -LiteralPath $script:LogFile -Append
As mentioned in my answer to your previous question you can auto-increment the number in the filename with something like this:
while (Test-Path -LiteralPath $script:LogFile) {
$script:LogFile = Increment-Index $script:LogFile
}
where Increment-Index implements the program logic that increments the index in the filename by one, e.g. like this:
function Increment-Index($f) {
$parts = $f.Split('[]')
'{0}[{1}]{2}' -f $parts[0],(1 + $parts[1]),$parts[2]
}
or like this:
function Increment-Index($f) {
$callback = {
$v = [int]$args[0].Groups[1].Value
$args[0] -replace $v,++$v
}
([Regex]'\[(\d+)\]').Replace($f, $callback)
}
The while loop increments the index until it produces a non-existing filename. The parameter -LiteralPath in the condition is required, because the filename contains square bracket, which would otherwise be treated as wildcard characters.
I have this powershell script running. The first time it runs it runs flawlessly, the second time it runs i get the error that the .csv cannont be access "because it is being used by another process. Any idea which part of the script is "holding onto" the file and how i can make it let it go at the end?
clear
set-executionpolicy remotesigned
# change this to the directory that the script is sitting in
cd d:\directory
#############################################
# Saves usernames/accountNumbers into array #
# and creates sql file for writing to #
#############################################
# This is the location of the text file containing accounts
$accountNumbers = (Get-Content input.txt) | Sort-Object
$accountID=0
$numAccounts = $accountNumbers.Count
$outString =$null
# the name of the sql file containing the query
$file = New-Item -ItemType file -name sql.sql -Force
###################################
# Load SqlServerProviderSnapin100 #
###################################
if (!(Get-PSSnapin | ?{$_.name -eq 'SqlServerProviderSnapin110'}))
{
if(Get-PSSnapin -registered | ?{$_.name -eq 'SqlServerProviderSnapin110'})
{
add-pssnapin SqlServerProviderSnapin100
Write-host SQL Server Provider Snapin Loaded
}
else
{
}
}
else
{
Write-host SQL Server Provider Snapin was already loaded
}
#################################
# Load SqlServerCmdletSnapin100 #
#################################
if (!(Get-PSSnapin | ?{$_.name -eq 'SqlServerCmdletSnapin100'}))
{
if(Get-PSSnapin -registered | ?{$_.name -eq 'SqlServerCmdletSnapin100'})
{
add-pssnapin SqlServerCmdletSnapin100
Write-host SQL Server Cmdlet Snapin Loaded
}
else
{
}
}
else
{
Write-host SQL Server CMDlet Snapin was already loaded
}
####################
# Create SQL query #
####################
# This part of the query is COMPLETELY static. What is put in here will not change. It will usually end with either % or '
$outString = "SELECT stuff FROM table LIKE '%"
# Statement ends at '. loop adds in "xxx' or like 'xxx"
IF ($numAccounts -gt 0)
{
For ($i =1; $i -le ($AccountNumbers.Count - 1); $i++)
{
$outString = $outstring + $AccountNumbers[$accountID]
$outString = $outString + "' OR ca.accountnumber LIKE '"
$accountID++
}
$outString = $outString + $AccountNumbers[$AccountNumbers.Count - 1]
}
else
{
$outString = $outString + $AccountNumbers
}
# This is the end of the query. This is also COMPLETELY static. usually starts with either % or '
$outString = $outString + "%'more sql stuff"
add-content $file $outString
Write-host Sql query dynamically written and saved to file
###########################
# Create CSV to email out #
###########################
#Make sure to point it to the correct input file (sql query made above) and correct output csv.
Invoke-Sqlcmd -ServerInstance instance -Database database -Username username -Password password -InputFile sql.sql | Export-Csv -Path output.csv
####################################
# Email the CSV to selected people #
####################################
$emailFrom = "to"
$emailTo = "from"
$subject = "test"
$body = "test"
$smtpServer = "server"
# Point this to the correct csv created above
$filename = "output.csv"
$att = new-object Net.mail.attachment($filename)
$msg = new-object net.mail.mailmessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.from = $emailFrom
$msg.to.add($emailto)
$msg.subject = $subject
$msg.body = $body
$msg.attachments.add($att)
$smtp.Send($msg)
Can you try to add at th end :
$att.Dispose()
$msg.Dispose()
$smtp.Dispose()
You could also try and use a tool like procmon and see what does the script do whenever it acquires a lock on the file and doesn't release it. Also, since (supposedly) the problem is with the .csv file, you could load it as byte array instead of passing it's path as an attachment. This way the file should be read once and not locked.