I'm working with automating the opening of a public folder by EntryID from IE with javascript and activex and ran across some errors. To debug I've re-wrote it as a power shell script.
$eid = "HEX EntryID FOR PUBLIC FOLDER";
$o = new-object -com outlook.application;
$ns = $o.GetNamespace("MAPI");
#$ns #if this line is commented, error
$f = $ns.GetFolderFromID($eid)
$f.Display();
If I shut outlook down completely, and then run the script I get the following error
Exception calling "GetFolderFromID" with "2" argument(s): "The messaging interface has returned an unknown error. If the problem persists, restart Outlook."
At G:\scripts\outlook.ps1:5 char:25
+ $f = $ns.GetFolderFromID <<<< ($eid)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
If I uncomment the $ns line, everything works fine, even if its removed again. That is, until I close out of Outlook completely, almost as if the $ns com object isn't being truly initialized until I output it to the console.
I'd like to know:
why calling $ns fixes the problem
why powershell thinks I'm passing 2 arguments
is there a way to implement this workaround
in javascript
The GetFolderFromID() requires two arguments: EntryID and StoreID of folder wanted.
This code gives no error and show outlook with PublicFolder selected:
$o = new-object -com outlook.application;
$ns = $o.GetNamespace("MAPI");
$cp = $ns.Folders # FolderClass ComObject containing all Outlook folders, usually first is the PublicFolder
$f = $ns.GetFolderFromID( $cp.GetFirst().EntryID ,$cp.GetFirst().StoreID )
$f.Display();
Using your code I can't do it, $ns line commented or not.
You can get the public folders store programatically:
$ol = New-Object -ComObject Outlook.Application
$pf = $ol.GetNamespace("MAPI").Folders | Where-Object {$_.FolderPath -like "\\Public Folders*"}
$pf.Display()
Related
I have started learning PowerShell with excel and getting null-valued expression error
#open excel application
$x1 = New-Object -comobject excel.application
#open excel to show the result in realtime
$x1.Visible = $true
#open the already existing excel to edit
$test = $x1.Workbooks.Open("C:\Users\tushar.v\OneDrive - HCL Technologies Ltd\Documents\test.xlsx")
#to open a specific worksheet
$test2 = $test.worksheets.Item(1).Activate
$test2.Cells.Item(1,1) = "alphatext"
Error :
You cannot call a method on a null-valued expression.
At line:9 char:1
+ $test2.Cells.Item(1,1) = "alphatext"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Also , I am not getting the output in the excel
First of all, I would advise to use better variable names, so in a larger script it is clear what every variable contains. $test and $test2 are not really descriptive..
Then for what you have tried:
The worksheet's Activate() method does not return an object referencing the activated worksheet as you might think, so you need to first get the worksheet object in a variable and use that to perform the Activate() method.
Try:
# create excel application
$excel = New-Object -comobject excel.application
# open excel to show the result in realtime
$excel.Visible = $true
# open the already existing excel to edit
$workbook = $excel.Workbooks.Open("D:\Test\blah.xlsx")
# get a reference to the first worksheet in the file
$worksheet = $workbook.WorkSheets.Item(1)
# make this worksheet active
$worksheet.Activate()
# and add content to the cell
$worksheet.Cells.Item(1,1) = "alphatext"
Finally, creating COM objects consumes memory, so after your work is done, you need to tell Windows that it can clean up those objects:
# Don't forget to quit Excel when done (after saving perhaps?) and to remove the created COM objects from memory:
$excel.Quit()
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($worksheet)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
I'm using Word to convert a docx to PDF from PowerShell by opening the document and writing it by using SaveAs().
My code:
# got that hint from http://stackoverflow.com/questions/36487507/troubles-using-powershell-and-word-saveas
[Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Interop.Word") | Out-Null
$Word = New-Object -ComObject "Word.Application"
$Word.Visible = $False
foreach ($transf_file in $doc_path) {
$transf_pdf_file = $transf_file -replace "`.docx?$", ".pdf"
$rel_path = Split-Path -Parent $transf_file
Copy-Item -Path "$src_pp_dir\$transf_file" -Destination "$dest_pp_dir\$rel_path" -Force
$word_doc = $Word.Documents.Open( "$dest_pp_dir\$transf_file" )
# Hess / Herlet workaround die nächste Zeile einkommentieren, die übernächste Zeile auskommentieren
#$word_doc.SaveAs( "$dest_pp_dir\$transf_pdf_file" ,17 )
$word_doc.SaveAs( [ref] [system.object] "$dest_pp_dir\$transf_pdf_file" ,[ref]17)
$word_doc.Close()
Remove-Item -Force -Path "$dest_pp_dir\$transf_file"
}
# this line avoids saving of normal.dot what is normally requested when another
# Word is open in parallel
# the rest is necessary to kill this word process (otherwise they sum up in the
# system and after a while it doesn't work anymore)
$Word.NormalTemplate.Saved = $true
$Word.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Word) > $null
Remove-Variable Word
The code runs on my computer as expected.
On a colleagues computer the line:
$word_doc.SaveAs( [ref] [system.object] "$dest_pp_dir\$transf_pdf_file" ,[ref]17)
throws an error:
Argument: '1' should not be a System.Management.Automation.PSReference. Do not
use [ref].
At D:\DMG\NX_Projekte\handle\PP-Encode.ps1:1015 char:7
+ $word_doc.SaveAs( [ref] [system.object] "$dest_pp_dir\$transf_pdf_file" ,[ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : RefArgumentToNonRefParameterMsg
On his machine the line before (now as comment, without [ref]), works fine.
What I checked:
We are using identical versions of PowerShell, Word, Word COM object, .NET Framework.
I scanned the hints on this site and improved in particular exiting from Word (making sure that all Word processes are finished -- what's the case on my computer).
I couldn't find any hints to this specific problem neither here nor elsewhere.
I have a script that goes into SCSM, gets the relevant files from the IR and downloads them properly onto the user's computer.
Next, I need the script to create an email from the client's outlook application and display it on their screen before sending the email..
Here is the part of the script that does that:
$GetFiles = Get-ChildItem "$ArchiveRootPath\$IRID\"
$ol = New-Object -comObject Outlook.Application #| New-Object Net.Mail.MailMessage
$mail = $ol.CreateItem(0)
$mail.To = "johndoe#contoso.com"
$mail.Subject = "This is a test [$IRID]"
Foreach($GetFile in $GetFiles)
{
Write-Host “Attaching File :- ” $GetFile
$attachment = New-Object System.Net.Mail.Attachment –ArgumentList C:\Temp\SCSM_Archive\$IRID\$GetFile
$mail.Attachments.Add($attachment)
}
$inspector = $mail.GetInspector
$inspector.Display()
However, when I run the script, I get this error:
Attaching File :- email.eml
Exception calling "Add" with "1" argument(s): "Value does not fall within the expected range."
At C:\Temp\SSWireless Script.ps1:99 char:2
+ $mail.Attachments.Add($attachment)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
All the variables are checked from the previous part of the script that downloads the files. PS is able to see the files, but cannot attach them to the email.
I don't want to use the send-message function due to the fact that we will be moving to a cross domain email account and would rather use outlook to create the email itself.
Here is a reference for Microsoft.Office.Interop.Outlook Attachments.Add method . This confirms that the first parameter (and the only parameter in your case) needs to be a full path to file.
There is no point passing [System.Net.Mail.Attachment] .NET objects to COM interface.
Your code should look something like this:
$GetFiles = Get-ChildItem "$ArchiveRootPath\$IRID\"
$ol = New-Object -comObject Outlook.Application
$mail = $ol.CreateItem(0)
$mail.To = "johndoe#contoso.com"
$mail.Subject = "This is a test [$IRID]"
Foreach($GetFile in $GetFiles)
{
Write-Host “Attaching File :- $GetFile.Name"
$mail.Attachments.Add($GetFile.FullName)
}
I am trying to use InsertAdjacentHtml with IE COM by Powershell but my code fails what can be the reason ?
$oIE = new-object -ComObject InternetExplorer.Application
$oIE.visible=$True
$oIE.navigate2("http://www.quirksmode.org/dom/core/getElementsByName.html")
While ($ie.Busy) {
Sleep 2
}
$doc = $oIE.Document
$btns = $doc.getElementsByTagName("input")
$btns.insertAdjacentHTML('afterend', '<div id="secondDiv">Second</div>');
$oIE.visible=$True
The comand line shows Invalid Operation error
I ran your script both line by line and by saving it as a PowerShell script, but got different results - both were errors.
When running line by line, I get this error:
Method invocation failed because [System.__ComObject] does not contain a method named 'insertAdjacentHTML'.
At line:1 char:1
+ $btns.insertAdjacentHTML('afterend', '<div id="secondDiv">Second</div>');
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (insertAdjacentHTML:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Altough the method 'insertAdjacentHTML' is listed with Get-Member, it cannot be used.
So, I wanted to find a reason for that or another way to achieve the same thing. I ended up with this conclusion: PowerShell might not be the best tool to achieve what you are trying for OR you should use objects that have more reliable methods.
When I run an altered script, line by line, it sort of works:
$oIE = new-object -ComObject InternetExplorer.Application
$oIE.visible=$True
$oIE.navigate2("http://www.quirksmode.org/dom/core/getElementsByName.html")
$doc = $oIE.Document
$btn = $doc.all.item("test", 1)
$btn.insertAdjacentHTML('afterend', '<div id="secondDiv">Second</div>')
$oIE.visible=$True
This is the HTML produced:
<div id="test">
<p name="test">This is a paragraph with name="test"</p>
<ppk name="test">This is a ppk tag with name="test"</ppk>
<p><input name="test"><div id="secondDiv">Second</div>This is an input with name="test"</p>
<p><img name="test">This is an image with name="test"</p>
</div>
To make things even stranger, this only works in a normal PowerShell console, it fails when using PowerShell ISE.
EDIT: Try it with a ForEach loop, it just might work. It occurred to me that you cannot run a method on an array of objects unless you call it within a loop AND another thing, that the page the script was navigating to might have issues.
So, this works:
$oIE = new-object -ComObject InternetExplorer.Application
$oIE.visible = $True
$oIE.navigate2("https://stackoverflow.com/questions/28650033/use-insertadjacenthtml-by-powershell-with-ie-com/")
Start-Sleep -Milliseconds 3333
$doc = $oIE.Document
$btns = $doc.getElementsByName("_id_")
$btns | ForEach-Object { $_.insertAdjacentHTML('afterend', '<div id="secondDiv">Second</div>') }
Thank you for the question, this is nice to know.
I'm trying to run some code that looks for all .doc & .docx files in a directory & sub-directories and then converts each one to PDF format.
The code below works only if there are no instances of the pdf in these directories i.e. it only works first time. Every subsequent time it fails with:
Exception calling "SaveAs" with "2" argument(s): "Command failed"
At C:\convert\convertword.ps1:12 char:13
+ $doc.saveas <<<< ($path, $wdFormatPDF)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
When I delete the previously created PDFs and re-run the PS it works fine. Therefore I can only assume there is a switch or parameter that I'm missing from my SaveAs function which somehow forces the overwrite?
$wdFormatPDF = 17
$word = New-Object -ComObject word.application
$word.visible = $false
$folderpath = "c:\convert\*"
$fileTypes = "*.docx","*doc"
Get-ChildItem -path $folderpath -recurse -include $fileTypes |
foreach-object `
{
$path = ($_.fullname).substring(0,($_.FullName).lastindexOf("."))
"Converting $path to pdf ..."
$doc = $word.documents.open($_.fullname)
$doc.saveas($path, $wdFormatPDF)
$doc.close()
}
$word.Quit()
Ok I finally think I've tracked down the problem. It's the Windows Explorer Preview Pane which is locking the file. I had show preview pane turned on the directory where the files were being created and converted, this must have been creating a file lock on the pdf's therefore the script cannot save the new pdf. I turned off preview pane in my Windows Explorer and the script now works repeatedly! Therefore nothing wrong with the Powershell Scripting but thanks for all the input guys. Here's a link to the closest MS KB article that I could find on the subject http://support.microsoft.com/kb/942146
try this:
$word.displayalerts = $false
$doc.saveas($path, $wdFormatPDF) # with Word2010 I've to use $doc.saveas([ref]$path, [ref]$wdFormatPDF)
$word.displayalerts = $true
No error is raised, but I'm using Word2010 I can't test it with other versions
There's no flag to overwrite according to the documentation for SaveAs and SaveAs2. So you could just remove it before saving with something like this:
Remove-Item -Path $path -Force -ErrorAction SilentlyContinue
$doc.saveas ($path, $wdFormatPDF)