issue with powershell script to convert multiple excel files to csv - windows

Converting all the excel files in a specified directory using the below code. When I try to convert one file to csv it works as intended but when I try to convert all excel files to csv nothing happens no exception thrown, and the files are not converted.
$path = get-childitem -path "\\sharedrive\excelfiles\" -filter *.xlsx
foreach ($file in $path)
{
$Excelfilename = $file.fullname
$CSVfilename = "" + $file.Basename
$xlCSV=6
$Excel = New-Object -comobject Excel.Application
$Excel.Visible = $False
$Excel.displayalerts=$False
$Workbook = $Excel.Workbooks.Open($ExcelFileName)
$Workbook.SaveAs($CSVfilename,$xlCSV)
$Excel.Quit()
}

I have run into this same issue before, and this technet article was very useful: https://technet.microsoft.com/en-us/library/ff730962.aspx
Basically you're doing everything right, but the .Quit() method isn't exactly what you're looking for since it gets rid of the program but not the com object. We need to go one layer further and call the .NET Framework to release the COM object like below, then release the $Excel variable.
$Excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)
Remove-Variable $Excel
This should give you what you're looking for and clean up your environment appropriately, allowing you to loop back through and make the change to all the .csv's

Related

Powershell dir command options not working

I was trying to use dir command to list recursively all files that end with .cpp in a given directory, I tried to follow various solutions but my powershell seems not to accept any options after '/' sign as seen on the picture bellow:
Example
The command I initially tried was 'dir sourcefolder "*.cpp"' but it only lists files in a given folder (because I cant provide any additional options as seen in microsoft doc), also any example command provided there does not work for me giving the same error as shown in example above.
here is how I will bring out all the files in .cpp.
Here is a small program in powershell :
$path = "C:\temp\"
$filter = "*.cpp"
$files = Get-ChildItem -Path $path -Filter $filter
Write-Host "here, all the .cpp files in '$path' :"
Write-Host $files -Separator "`r`n"
I prefer to use the cmdlet "Get-ChildItem" rather than "dir".
Here the content folder for my test
And, why so many / ?

Windows PowerShell - Input file name, output file path

I've just started using PowerShell and I have a task where I need to be able to have the file path displayed on screen when I enter the file name.
Is there a script that allows me to do the below ? :
Ex 1: I enter "test.txt" and I get "C:\Program Files...."
Ex 2: I enter a file name "My Documents" and I also get its path.
I have searched online on how to do this but I didn't quite find what I was looking for and all the queries/answers were too complicated for me to understand.
Can anyone help me out, please?
Thanks in advance!
Here is a starter sample for you.
This example search only within the confine of the paths present is the Path system environment variable. It also only looks for files and do not recurse through these path.
So anything you could access directly from the command line should be available to you through it.
Now, if you want to search the whole drive, you could replace the $DefaultPaths assignment with Get-ChildItem -Path 'C:' -Recurse but doing that each time won't be super efficient.
You could do it and it will work... but it will be slow.
To search on the whole drive or whole filesystem, there are alternative methods that might work better. Some examples of what might entice:
Using a database which you have to buld & maintain to index all the files so that when you search, results are instantaneous and / or very fast
Parsing the MFT table (if using Windows / NTFS filesystem only) instead of using Get-ChildItem (This is not somehting natively doable through a simple cmdlet though) .
Relying on a third party software and interface with (For example, Void Tools Everything search engine already parse MFT and build its own database, allowing users to search instantly through a Windows NTFS filesystem. It also have its own SDK you can plug in through Powershell and retrieve what you seek instantly. The caveats is that you need the software installed first for that solution to work.)
Example: Searching through all paths defined in the Path variable
# What you are looking for. Accept wildcards characters (*)
$Filter = 'notepad.exe'
# Get the System Environment Path variable in an array
$DefaultPaths = $env:Path -split ';'
$Paths =
Foreach ($P in $DefaultPaths) {
# Search for files matching the specified filter. Ignore errors (often if the path do not exist but is sin the Path)
$MatchingFiles = Get-ChildItem -Path $P -Filter $Filter -File -ErrorAction SilentlyContinue
if ($MatchingFiles.count -gt 0) {
$MatchingFiles.Directory.FullName
}
}
$Paths | out-string | Write-Host -ForegroundColor Cyan
Output for Notepad.exe search using this method.
C:\Windows\system32
C:\Windows

script that searches for word documents (.rtf) and change the resolution of the images

I need an script that searches in a folder for word documents (.rtf) and change the resolution of the images. The problem is that I have a lot of .rtf files that are taking a lot of space because they have high resolution images. If I change the resolution of the images the file reduces it space about 97%. Please help me.
Thank you.
Unfortunately, there is no programmatic way to do "Select Image > Picture Format > Compress Pictures". It might be worth setting up an AutoHotKey script to run through your files.
If your rtf files were originally created in word, they likely saved two copies of each image (original file and huge uncompressed version). You can change this behavior by setting ExportPictureWithMetafile=0 in the registry, then re-saving each file. This can be done with a script, for example:
# Set registry key: (use the correct version number, mine is 16.0)
Try { Get-ItemProperty HKCU:\SOFTWARE\Microsoft\Office\16.0\Word\Options\ -Name ExportPictureWithMetafile -ea Stop}
Catch { New-ItemProperty HKCU:\SOFTWARE\Microsoft\Office\16.0\Word\Options\ -Name ExportPictureWithMetafile -Value "0" | Out-Null }
# Get the list of files
$folder = Get-ChildItem "c:\temp\*.rtf" -File
# Set up save-as-filetype
$WdTypes = Add-Type -AssemblyName 'Microsoft.Office.Interop.Word, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' -Passthru
$RtfFormat = [Microsoft.Office.Interop.Word.WdSaveFormat]::wdFormatRTF
# Start Word
$word = New-Object -ComObject word.application
$word.Visible = $False
ForEach ($rtf in $folder) {
# save as new name temporarily (otherwise word skips the shrink process)
$doc = $word.documents.open($rtf.FullName)
$TempName=($rtf.Fullname).replace('.rtf','-temp.rtf')
$doc.saveas($TempName, $RtfFormat)
# check for success, then delete original file
# re-save to original name
# check for success again, then clean up temp file
if (Test-Path $TempName) { Remove-Item $rtf.FullName }
$doc.saveas($rtf.FullName, $RtfFormat)
if (Test-Path $rtf.FullName) { Remove-Item $TempName }
# close the document
$doc.SaveAs()
$doc.close()
}
$word.quit()
I made some default word files with a 2mb image, saved as rtf (without the registry change), and saw the rtf files were a ridiculous 19mb! I ran the script above, and it shrunk them down to 5mb.

How to invoke a verb on multiple files

Using PowerShell I would like to invoke the print verb on multiple files. In Windows Explorer I can go into a folder, select a number of files, right-click and choose the print options. This opens up the Print Pictures dialog with all the selected files. I am able to do this for one file using:
$path = "C:\person.jpg";
Start-Process -FilePath $path -Verb Print | Out-Null;
Start-Sleep -s 150;
But was wondering how I could do it for a number of files.
You can use COM to invoke a verb on multiple files in one operation.
Assuming...
$folderPath = 'X:\Test'
$verbName = 'print'
$verbArguments = ''
...you can print all objects in a folder with...
$application = New-Object -ComObject 'Shell.Application'
$folder = $application.NameSpace($folderPath)
$folderItems = $folder.Items()
Write-Verbose "Folder ""$($folder.Self.Name)"" contains $($folderItems.Count) item(s)."
$folderItems.InvokeVerbEx($verbName, $verbArguments)
I say "objects" because $folderItems will contain both files and folders. The default appears to be enumerate subfolders and ignore hidden objects, while verbs are ignored on objects that don't support them.
If, for example, you wanted to only print files with a certain extension that are immediate children and include hidden files, you can do so using the Filter() method...
New-Variable -Name 'SHCONTF_NONFOLDERS' -Option 'Constant' -Value 0x00040
New-Variable -Name 'SHCONTF_INCLUDEHIDDEN' -Option 'Constant' -Value 0x00080
$application = New-Object -ComObject 'Shell.Application'
$folder = $application.NameSpace($folderPath)
$folderItems = $folder.Items()
$folderItems.Filter($SHCONTF_NONFOLDERS -bor $SHCONTF_INCLUDEHIDDEN, '*.jpg')
Write-Verbose "Filtered folder ""$($folder.Self.Name)"" contains $($folderItems.Count) item(s)."
$folderItems.InvokeVerbEx($verbName, $verbArguments)
If you want to print some custom set of files that don't nicely align by extension, visibility, etc. then I'm not seeing a way to do that. That would seem to require modifying $folderItems or creating a new FolderItems3 instance, and neither appears to be possible. I see there is a ShellFolderView type that supports item selection, but that looks like it's for interacting with an Explorer(-like) window.
Documentation for types and constants used above:
Shell.Application property
Shell.NameSpace method
Folder object
FolderItems3 object
FolderItems2.InvokeVerbEx method
FolderItems3.Filter method
_SHCONTF Enumeration
As far as I know, you can use foreach to iterate over all items in an array of items (files that you want to print), and execute the action print on each one of them as follows:
Get-ChildItem "C:\" -Include "*.jpg" | ForEach-Object {start-process $_.FullName –Verb Print}
Start-Sleep -s 150
This will:
get all the files (jpg files) found in C
apply the verb print on each file.
Note
You can use -wait parameter for Start-Process instead of Start-Sleep -s 150; This waits for the specified process and its descendants to complete before accepting more input.

Install Windows Updates from a folder & return the status installed or not

I wanted a help on verifying status of updates installed from a folder, here is the script below.
# Specify the location of the *.msu files
$updatedir = "C:\install\hvpatches"
foreach ($msu in $msus)
{
write-host "Installing update $msu ..."
$fullname = $msu.fullname
# Need to wrap in quotes as folder path may contain spaces
$fullname = "`"" + $fullname + "`""
###
$files = Get-ChildItem $updatedir -Recurse
$msus = $files | ? {$_.extension -eq ".msu"}
# Specify the command line parameters for wusa.exe
$parameters = $fullname + " /quiet /norestart"
# Start wusa.exe and pass in the parameters
$install = [System.Diagnostics.Process]::Start( "wusa",$parameters )
$install.WaitForExit()
write-host "Finished installing $msu"
}
The windows updates are installed from above script, what i wanted is some way to verify if these updates are installed correctly or give a status if the installation failed.
I hope some of our powershell gurus help me out :)
Thanks,
Vinith!
I'm hardly a PS guru, but some time ago I was playing with checking updates in different context, so maybe my advice will be of use to you.
To the point. Try calling this snippet I have written down back then:
$session = New-Object -ComObject Microsoft.Update.Session
$searcher = $session.CreateUpdateSearcher()
$result = $searcher.Search("IsInstalled=1 and Type='Software'" )
$result.Updates | get-member
After some time (it's kinda slow) you'll get list of things you can check. I don't know what information you have about these updates you're installing, but here's some possibly useful, like Title or KBArticleIDs number (hopefully containing some relevant info). Then you replace last line with what you want, e.g.
$result.Updates | select Title
and compare with data about recently installed updates.
Sorry for somehow incomplete answer -- my current Windows box has some issues and above codes do not work exactly like I remember it. Don't hesitate to point out if it's simply wrong, errare humanum est! ;)

Resources