PowerShell and Onenote - powershell

I would like to read and write on OneNote pages using PowerShell scripts. I have been trying different scripts I found, but none of them even run on my machine. I am wondering if I have to enable something, or get some kind of library.
When trying to run some scripts I found, I get this error:
Unable to find type [Microsoft.Office.InterOp.OneNote.HierarchyScope].
At line:3 char:27
+ ... erarchy("", [Microsoft.Office.InterOp.OneNote.HierarchyScope]::hsPage ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (Microsoft.Offic....HierarchyScope:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
Could someone point me in the right direction? Or is it even possible?
PS Version: 5.1.17134.407
OneNote 2013

Agreed with Theo on this one.
How are you trying to run them, consolehost, ISE, VSCode, other editor?
Did you set your ExecutionPolicy so that you could run them at all.
Is OneNote on your machine and activated or are you trying to hit a remote box?
However, there is a provider you can use to assist you here...
OneNotePowerShellProvider
# Example Scripts
Name
----
ConvertTo-Object.ps1
Create-OneNoteDocumentation.ps1
Export-PsOn.ps1
Get-OneNoteApplication.ps1
Get-OneNoteDigest.ps1
Get-OneNoteText.ps1
Get-ProviderTests.ps1
Import-FilesToOneNote.ps1
Robocopy-Items.ps1
Set-OneNoteDebug.ps1
Start-Tests.ps1
… as well as this article...
Read and Write Content from OneNote with PowerShell
# Examples
# get a table of all notebooks
$OneNote = New-Object -ComObject OneNote.Application
[xml]$Hierarchy = ""
$OneNote.GetHierarchy("", [Microsoft.Office.InterOp.OneNote.HierarchyScope]::hsPages, [ref]$Hierarchy)
$Hierarchy.Notebooks.Notebook | Format-Table Name, path, isUnread, isCurrentlyViewed

Related

How to create a MSI extractor with Powershell? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 months ago.
Improve this question
A few months back I made a simple MSI extractor script, I improved it some today by adding a popup dialog using WScript.Shell, however I also wanted to improve on the first part of the script, the extractor. Originaly users would have to go in and manually edit the input file (.msi) and the output directory. I used the old friend google to see what the file popup syntax was. Tried to encorperate it into the script, with no luck.
Current code:
msiexec /n /a $FileBrowser /qb TARGETDIR=$Out # This uses the built in Windows tool to extract the MSI
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property #{
InitialDirectory = [Environment]::GetFolderPath('Desktop')
Filter = 'Windows Packages (*.msi)|*.msi'
}
$Out = $FileBrowser.ShowDialog()
$Shell = New-Object -ComObject "WScript.Shell"
$Button = $Shell.Popup("Once you install the MSI using this PowerShell script, please add any programs that run from a shell (i.e. CMD, PowerShell) be added to Path.
To add a program to path, search for Control Panel in Windows Search, and open it. Once in Control Panel,
select User Accounts, then User Accounts again. On the side bar, select Change my Enviorment Variables.
Select the Path variable, and then Edit. Select a unfilled box, and type the path to the program (for most, it can be just the root folder, some may need to be bin) and then Ok, and Ok again.
You WILL need to restart any open shells.", 0, "Thank you for using MSI-Extractor", 0)
Any help is greatly apprecitaed,
James
I tried adding vars, with no luck.
EDIT: I got some outside help, and I somewhat fixed it.
#Use Windows Forms to open a file select dialog
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property #{
InitialDirectory = [Environment]::GetFolderPath('Desktop')
Filter = 'Windows Packages (*.msi)|*.msi'
}
$Out = $FileBrowser.ShowDialog() #Display the dialog
#Select output directory
$FolderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog -Property #{
Description = 'Output'
}
$Out = $FolderBrowser.ShowDialog() #Display the dialog
$FolderBrowser.SelectedPath #Variable stuff
msiexec /a $FileBrowser.FileName /qb TARGETDIR=$($FolderBrowser.SelectedPath) # This uses the built in Windows tool to extract the MSI
#A helpful message
$Shell = New-Object -ComObject "WScript.Shell"
$Button = $Shell.Popup("Once you install the MSI using this PowerShell script, please add any programs that run from a shell (i.e. CMD, PowerShell) be added to Path.
To add a program to path, search for Control Panel in Windows Search, and open it. Once in Control Panel,
select User Accounts, then User Accounts again. On the side bar, select Change my Enviorment Variables.
Select the Path variable, and then Edit. Select a unfilled box, and type the path to the program (for most, it can be just the root folder, some may need to be bin) and then Ok, and Ok again.
You WILL need to restart any open shells.", 0, "Thank you for using MSI-Extractor", 0)
Running this in Windows Powershell ISE works, but in Powershell directly it errors out
New-Object : Cannot find type [System.Windows.Forms.OpenFileDialog]: verify that the assembly containing this type is
loaded.
At C:\Users\693982\Downloads\MSI-extractor.ps1:4 char:16
+ ... leBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
You cannot call a method on a null-valued expression.
At C:\Users\693982\Downloads\MSI-extractor.ps1:9 char:1
+ $Out = $FileBrowser.ShowDialog() #Display the dialog
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
New-Object : Cannot find type [System.Windows.Forms.FolderBrowserDialog]: verify that the assembly containing this
type is loaded.
At C:\Users\693982\Downloads\MSI-extractor.ps1:13 char:18
+ ... erBrowser = New-Object System.Windows.Forms.FolderBrowserDialog -Prop ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
You cannot call a method on a null-valued expression.
At C:\Users\693982\Downloads\MSI-extractor.ps1:17 char:1
+ $Out = $FolderBrowser.ShowDialog() #Display the dialog
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Running this in Windows Powershell ISE works, but in Powershell directly it errors out
The reason this works in the ISE is that the ISE will autoload needed libraries/modules. The Powershell consoles (powershell.exe/pwsh.exe) will not.
You need to put stuff like this at the top of your code for the shells to load for use in GUI-based scripts.
Add-Type -AssemblyName System.Drawing,
PresentationCore,
PresentationFramework,
System.Windows.Forms,
microsoft.VisualBasic
[System.Windows.Forms.Application]::EnableVisualStyles()
Point of Note:
You don't need all of those for what you are doing, but I put them here for your awareness/research of them. Sure, you can still use this old COM...
New-Object -ComObject "WScript.Shell"
... for popups; however, you should be using the modern .Net namespaces above.
Example details:
[enum]::GetNames([System.Windows.MessageBoxImage])
# Results
<#
None
Hand
Error
Stop
Question
Exclamation
Warning
Asterisk
Information
#>
[System.Windows.MessageBox]::Show('Do you want to proceed?', 'Confirm', 'YesNoCancel','Error')
Example message boxes using .Net.
[System.Windows.MessageBox]::Show(
"
General Info
`n Some other Info
`n Username
`n Password,
", 'Dialog Title'
)
[System.Windows.Forms.MessageBox]::Show(
"
General Info
`n Some other Info
`n Username
`n Password
", 'Dialog Title'
)
Here's a refactor of your popup message for readability.
[System.Windows.MessageBox]::Show(
"1. Once you install the MSI using this PowerShell script,
please add any programs that run from a shell (i.e. CMD, PowerShell)
be added to Path.
`n2. To add a program to path,
`t->search for Control Panel in Windows Search, and open it.
`n3. Once in Control Panel,
`t->select User Accounts,
`t->then User Accounts again.
`n4. On the side bar, select Change my Enviorment Variables.
`tSelect the Path variable, and then Edit.
`t`Select a unfilled box, and type the path to the program
`t->for most, it can be just the root folder,
`t->some may need to be bin
`t->and then Ok, and Ok again.
`n5. You WILL need to restart any open shells.", "Thank you for using MSI-Extractor"
)

The start-process cmdlet of powershell will fail with -PassThru argument when trying to launch Edge browser

In my test script by powershell, I'd start an Edge browser and get it's main process's ID. Simply like this:
$edge = Start-Process microsoft-edge: www.ted.com -PassThru
but instead of able to get the process id from $edge.Id, I've got error message like this:
Start-Process : This command cannot be run completely because the system cannot find all the information required.
At line:1 char:7
+ $edge=Start-Process microsoft-edge: www.ted.com -PassThru
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
Is there any simple and straightforward way to really doing this without enumerate and check the process list?
Thanks!
I try to test your script and I am getting a similar error as yours.
Based on my search result, passthru is not one of the common parameters, and it does not exist everywhere.
Reference:
Use the PowerShell Passthru Parameter and Get Back Objects
I think it is not available for the MS Edge browser and that's why the script gives an error.
I try to search for an alternative command for PassThru but I did not get any helpful information about it.
In this situation, it is better to enumerate and check the process list

How to connect Powershell script to an already opened document?

I have a Powershell script that performs some modifications with a MSWord document. In the beginning of the script PS opens the document:
$word = New-Object -ComObject Word.Application
$desktop_path = [Environment]::GetFolderPath("Desktop")
$doc = $word.Documents.Open("$desktop_path" + "blabla.docx")
But as the requirements changed, I now need to run this PS script within an already opened document. Is there any options to force PowerShell find an opened document (by the name for example) and "connect" to it?
FYI: The sequense I want to obtain is: I open the file, launch some macros, call from VBA my PSScript (and here I need PS to be able to "fetch" an opened doc), launch other macros.
Thank you a lot in advance!
This should the same as for Excel:
$word = [Runtime.Interopservices.Marshal]::GetActiveObject('Word.Application')
Note the same-user limitation. I would recommend doing the whole thing programmatically via PowerShell though, as suggested by Guenther.
If word is not running, is running under a different user, or is running as admin (and PowerShell is not running as admin) you will get an error:
Exception calling "GetActiveObject" with "1" argument(s): "Operation unavailable (Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))"
At line:1 char:1
+ $word = [Runtime.Interopservices.Marshal]::GetActiveObject('Word.Appl ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : COMException
As advised, check that PowerShell and Word are running under the same user. You can so this by going to Task Manager > Details, and checking the user name column for WINWORD.EXE and powershell.exe
To get a specific document based on name:
$doc = $word.Documents | Where-Object {$_.Name -eq "Document2"}
You can check how many documents are open by looking at the count:
$word.Documents.Count

Cannot run same script twice in same PowerShell session

I'm writing a PowerShell script that will open an application, run a process, then close it, and then open another application, run a process, and close it. (Ultimately more than two, but I'm starting small.)
I can run the following script, with no issues:
# Project Config
$projectName = "c:\temp\test3.egp"
$projectName2= "c:\temp\test4.egp"
# Start Enterprise Guide
$app = New-Object -ComObject SASEGObjectModel.Application.7.1
#Open the Enterprise Guide Project
$projectObject = $app.Open($projectName, "")
# Save the Enterprise Guide Project
$projectObject.Save()
# Close the Enterprise Guide Project
$projectObject.Close()
# Open the second project
$projectObject = $app.Open($projectName2, "")
# Save the second project
$projectObject.Save()
#Close the second project
$projectObject.Close()
# Quit Enterprise Guide
$app.Quit()
PS C:\temp> ./test.ps1
PS C:\temp>
However, if I run it a second time at that above prompt, without exiting PowerShell, I get errors.
PS C:\temp> ./test.ps1
Exception calling "Open" with "2" argument(s): "Path is not a directory 'C:': The filename, directory name, or volume label syntax is incorrect."
At C:\temp\test.ps1:9 char:27
+ $projectObject = $app.Open <<<< ($projectName, "")
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
... more errors related to $projectObject not having a value, and then a second copy of each of these for the second attempt ...
PS C:\temp>
It works fine if I exit from Powershell, and reopen Powershell, and run it again.
Restrictions that are documented primarily include only one Project being able to be opened at one time; however, clearly $projectObject.Close() works fine, because it does successfully run two in one script. It's only when I've left the script and run it again that it's a problem.
Now, if I remove $app.Quit(), it then allows me to run it a second time in the same session; but I do want to quit the app (to ensure that any following run of the script isn't impacted by anything I just did; this is a programming environment, so things like setting session macro variables and such could have bad impacts). I also don't entirely understand why the line $app = New-Object ... doesn't create a new instance of the application (and so why the prior run's $app quit is relevant)?
Is there something in PowerShell I am doing wrong here? Or is this solely an issue with the API I'm using that I'll have to talk to SAS (the vendor)?
Inside your original PS session create a new PS session for each project: New-PSSession
More details and examples can be found on the Microsoft docs site here.

Unzip with Powershell doesn't work on XP

I got the Request to unzip a .zip file with Powershell. On the Internet i found the following code multiple times:
param( [String]$newlocation, [String]$filepath)
if(($newlocation -and $filepath) -and ((test-path $newlocation) -and (test-path $filepath)))
{
Copy-Item $filepath $newlocation
$shell_app=new-object -com shell.application
$filename = $filepath.split("\")[-1]
if(Test-Path "$newlocation\$filename")
{
$zip_file = $shell_app.namespace("$newlocation\$filename")
$destination = $shell_app.namespace($newlocation)
$destination.Copyhere($zip_file.items())
}
}
As I implemented it into my script it changed a little bit. This above is the changed version. Now I've got an error:
Exception calling "NameSpace" with "1" argument(s): "The system cannot find the file specified. (Exception from HRESULT
: 0x80070002)"
At Z:\MyScripts\deploy.ps1:34 char:34
+ $zip_file = $shell_app.namespace <<<< ("$newlocation\$filename")
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
And then another one, that is quite clear (caused by the first error
You cannot call a method on a null-valued expression.
At Z:\MyScripts\deploy.ps1:36 char:39
+ $destination.Copyhere($zip_file.items <<<< ())
+ CategoryInfo : InvalidOperation: (items:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
The File and the destination Path both exist and I've got rights to acces them (I created both). I'm running on Windows XP with PowerShell 2.0
Major Minor Build Revision
----- ----- ----- --------
2 0 -1 -1
Here is my entire dump from Powershell when I run it directly on the console.
I hope you guys can help me or at least tell me where I can go to find an answer.
I tried already to unzip the zip file manually and it worked, I have got access to both, the file and the file path (as I created both).
I've found this one on the web:
Also the code looks to me like it's dependent on the Windows Explorer support for zipFolders, which you may have turned off
Unregister (disable) XP Zip folders
REGSVR32 /u C:\Windows\System32\zipfldr.dll
Register (enable) XP Zip folders
REGSVR32 zipfldr.dll
It's from here.
I came to it during testing my script on several machines, e.g. on a Windows Server 2008 and on a Windows 7 client. Both worked, so I came to the conclusion that it's not my script,but it's my PC. After the registration of XP Zip folders, it worked.
Many thanks to the guy who wrote this one, I dumped too much time into this problem.
You might be running into a problem with accessing the COM objects. If you are using 64-bit windows, make sure you execute your script from a 64-bit powershell.exe. This means the powershell.exe in c:\windows\system32...\v1.0.... This was counter-intuitive for me, having the '32' in system32. I was executing powershell from Console2, which was a 32bit process, and was therefore launching 32-bit powershell (from c:\windows\syswow64...). Also make sure your powershell.exe is being run with administrator privileges.
Instead of trying to automate the Windows Shell, now in .NET Framework 4.5 there is a ZipFile class that you can use like this:
[System.Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem')
[System.IO.Compression.ZipFile]::ExtractToDirectory($sourceFile, $targetFolder)
Edit: Oops, .NET Framework 4.5 is not supported on Windows XP.
Anyhow, this answer might still prove useful for anyone else with ZIP problems in Powershell…