Powershell cannot create Outlook COM object from Command Prompt - powershell

I have a script used to send mails via Microsoft Outlook from command prompt. This works fine if I run it from inside PowerShell or ISE console. But when I tried to execute same from classic Windows Command prompt (cmd.exe) even with Admin privileges, it was unable to create Outlook COM object. Here is the line to create COM object:
$objOutLook = New-Object -com Outlook.Application
This is how I call my script from cmd.exe (Administrative privileges) :
D:>powershell D:\MiscBuildTasks.ps1 -sendmail -MailTo 'farrukh#MyMail.com'
and here is the error log:
New-Object : Retrieving the COM class factory for component with CLSID
{0006F03A-0000-0000-C000-000000000046} failed due to the following
error: 80080005 Server execution failed (Exception from HRESULT:
0x80080005 (CO_E_SERVER_EXEC_FAILURE)).
At D:\MiscBuildTasks.ps1:81 char:12
+ $Outlook = New-Object -ComObject Outlook.Application
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (:) [New-Object], COMException
+ FullyQualifiedErrorId : NoCOMClassIdentified,Microsoft.PowerShell.Commands.NewObjectCommand
How can I make it work from cmd.exe (Windows Command Prompt)??
Thanks

CO_E_SERVER_EXEC_FAILURE in case of Outlook means the calling app and the COM server are running in different security contexts. If the command prompt is running with elevated privileges, either make sure Outlook is started with elevated privileges as well or that it does not run at all when your code is executed - this way Outlook will be started by your code and it will run with the same elevated privileges.

I had the same issue, I figured out it was a combination of 3 things.
Running with the correct privilege level (admin)
Using the same arch (32-bit vs 64-bit) for outlook and powershell
Closing Outlook, since the script will open it.

The Considerations for server-side Automation of Office article states the following:
Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
If you are building a solution that runs in a server-side context, you should try to use components that have been made safe for unattended execution. Or, you should try to find alternatives that allow at least part of the code to run client-side. If you use an Office application from a server-side solution, the application will lack many of the necessary capabilities to run successfully. Additionally, you will be taking risks with the stability of your overall solution.
Office applications assume a user identity when the applications are run, even when Automation starts the applications. The applications try to initialize toolbars, menus, options, printers, and some add-ins based on settings in the user registry hive for the user who launches the application. Many services run under accounts that have no user profiles (such as the SYSTEM account or the IWAM_[servername] accounts). Therefore, Office may not initialize correctly on startup. In this situation, Office returns an error on the CreateObject function or the CoCreateInstance function. Even if the Office application can be started, other functions may not work correctly if no user profile exists.

If your installation of Outlook is 32-bit, make sure you are using the 32-bit version of PowerShell (x86) and not the 64-bit one.

Related

Why am I getting errors when running PowerShell command "Get-WindowsCapability" in .NetCore console application?

New to PowerShell in .NetCore and the script works fine in PowerShell ISE, but when I run through my console application.
Here is the script:
Get-WindowsCapability -Online -Name Microsoft.Windows.Notepad*
Here is the output through PowerShell ISE:
Name : Microsoft.Windows.Notepad~~~~0.0.1.0 State :
Installed DisplayName : Notepad Description : View, edit, and search
through plain text documents and source code files instantly.
DownloadSize : 301710 InstallSize : 647868
Here is my code snippet from my .NetCore console application:
var psInstance = PowerShell.Create();
psInstance.AddScript("Get-WindowsCapability -Online -Name Microsoft.Windows.Notepad*");
var output = psInstance.Invoke();
psInstance?.Runspace?.Close();
if (psInstance.HadErrors)
{
var error = psInstance.Streams.Error.Select(e => e.ToString());
}
Here is the error I'm seeing in my pInstance object:
Count = 5
[0]: "The 'Get-WindowsCapability' command was found in the module 'Dism', but the module could not be loaded due to the following error:
[File
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\Dism\Dism.psm1
cannot be loaded because running scripts is disabled on this system.
For more information, see about_Execution_Policies at
https://go.microsoft.com/fwlink/?LinkID=135170.]\r\nFor more
information, run 'Import-Module Dism'."
[1]: "The 'Get-WindowsCapability' command was found in the module 'Dism', but the module could not be loaded due to the following error:
[File
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\Dism\Dism.psm1
cannot be loaded because running scripts is disabled on this system.
For more information, see about_Execution_Policies at
https://go.microsoft.com/fwlink/?LinkID=135170.]\r\nFor more
information, run 'Import-Module Dism'."
[2]: "[localhost] Connecting to remote server localhost failed with the following error message : WinRM cannot process the request.
The following error with errorcode 0x8009030e occurred while using
Negotiate authentication: A specified logon session does not exist. It
may already have been terminated. \r\n Possible causes are:\r\n -The
user name or password specified are invalid.\r\n -Kerberos is used
when no authentication method and no user name are specified.\r\n
-Kerberos accepts domain user names, but not local user names.\r\n -The Service Principal Name (SPN) for the remote computer name and port does not exist.\r\n -The client and remote computers are in
different domains and there is no trust between the two domains.\r\n
After checking for the above issues, try the following:\r\n -Check
the Event Viewer for events related to authentication.\r\n -Change
the authentication method; add the destination computer to the WinRM
TrustedHosts configuration setting or use HTTPS transport.\r\n Note th
at computers in the TrustedHosts list might not be authenticated.\r\n
-For more information about WinRM configuration, run the following command: winrm help config. For more information, see the
about_Remote_Troubleshooting Help topic.\r\n Other Possible Cause:\r\n
-The domain or computer name was not included with the specified credential, for example: DOMAIN\UserName or COMPUTER\UserName."
[3]: "Cannot validate argument on parameter 'Session'. The argument is null or empty. Provide an argument that is not null or
empty, and then try the command again."
[4]: "Cannot validate argument on parameter 'Id'. The argument is null. Provide a valid value for the argument, and then try running the
command again."
I a running the console app as Administrator.
Why does the script run successfully through PowerShell IDE, but throw errors through the sample app?
Is there something I additionally have to do to my PowerShell instance object?
tl;dr
Configure your PowerShell SDK-based session with an execution policy that permits script execution, such as RemoteSigned
See this answer for an example.
Background information.
The obsolescent[1] Windows PowerShell ISE invariably runs Windows PowerShell, whereas your .NET (Core) C# application of necessity uses PowerShell (Core)'s SDK.
The two PowerShell editions have separate execution policies, and it sounds like while Windows PowerShell on your system is configured to permit script execution, PowerShell (Core) is not.
It may be surprising that the Dism module, which Get-WindowsCapability is a part of, is subject to the script execution policy, given that modules aren't .ps1 script files.
However, many modules are, namely if they (also) contain PowerShell code, which is not only true for script modules that are entirely implemented in PowerShell code (*.psm1), but also for primarily binary modules (those that provide their cmdlets via assemblies, i.e. compiled code), if such modules also contain PowerShell code and/or formatting files (*.format.ps1xml) or type-definition files (*.types.ps1xml).
The most robust solution is to set the desired execution policy on a per-session basis, as shown in the linked answer.
[1] The Windows PowerShell ISE is no longer actively developed and there are reasons not to use it (bottom section), notably not being able to run PowerShell (Core) 6+. The actively developed, cross-platform editor that offers the best PowerShell development experience is Visual Studio Code with its PowerShell extension.

SCCM 2012 R2 Cannot Run PowerShell Microsoft.SMS.TSEnvironment COMObject

Through a PowerShell script, I'm trying to interact with SCCM 2012 R2 Task Sequences. A lot of sites refer to using something similar to the following:
$tsenv = new-object -ComObject microsoft.sms.tsenvironment
First, if there is a better/different way, I'm totally open to it. But for this way, whenever I run that line, regardless of how I loaded the ConfigurationManager module (e.g. launch PowerShell from SCCM console, load the ConfigurationManager.psd1 from an x86 or x64 PowerShell console), it always returns the error below. I've also tried this on lab SCCM 2012 R2 environments and 2 separate production environments:
"New-Object : Retrieving the COM class factory for component with CLSID ... failed due to the following error: 80040154 Class not registered"
I'm coming up short searching for answers online, so hoping someone here is able to use that ComObject in PowerShell with SCCM 2012 R2 or if I'm just out of luck.
FYI,
In addition to having an active task sequence, you should also make sure that you are running from x64 process when creating the object when running on 64-bit OS, o/w the creation will fail with the 'Class not registered' error as if there is no TS running.

Get-AzurePublishSettingsFile gives Class not registered error

I installed the Azure Powershell Command lets (from here https://www.windowsazure.com/en-us/manage/downloads)
I also ran the
Set-ExecutionPolicy RemoteSigned
I then run the Windows Azure PowerShell under administrator credentials
However I get the following error
Get-AzurePublishSettingsFile : Class not registered
At line:1 char:1
+ Get-AzurePublishSettingsFile
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzurePublishSettingsFile], Win32Exception
+ FullyQualifiedErrorId : Microsoft.WindowsAzure.Management.Cmdlets.GetAzurePublishSettingsCommand
I had exactly the same problem on Windows 8 while using Chrome as my default browser.
The solution is to have Internet Explorer be the default program for opening browser related files like *.html.
Internet Explorer > Internet Settings > Programs > Set associations = Select all
This does the trick. Maybe a single entry would suffice but I didn't check that.
Check to see what the value is in $pshome
If you see %windir%\System32\WindowsPowerShell\v1.0 you are running powershell in 32bit mode. This is the version of PowerShell you will want to use for the Windows Azure PowerShell Cmdlets.
If you see %windir%\SysWOW64\WindowsPowerShell\v1.0 you are running in x64 mode, which may cause issues.
Also, ensure you are NOT running powershell 'As Administrator'
You need the private key of (or on) the certificate in order for this to work correctly. I found this out after a lot of trail and error.
But in short if your certificate manager does not have a little key icon over the certificate (the second certificate in the screen shot), it means you don't have a private key, and that means that Powershell will not be able to connect to Azure.
I noted down the things that I learned over here:
Management certificates and powershell deployment to windows azure
I use a non-administrator account to open powershell then it worked.
Notice launching the command would open up a web page at this url to download the publish settings file for your Azure account.
So effectively, you may open the link above without using the command.
Hope this helps.

Why is my locally-created script not allowed to run under the RemoteSigned execution policy?

Since this question continues to attract responses that are either
refuted by the question body or don't address the actual problem,
please read this simple summary of what you need to know:
This is not a "Why won't my default installation of PowerShell run scripts?" question.
This is not a "Why won't my installation of PowerShell run scripts downloaded from the internet?" question.
The question is why the RemoteSigned execution policy is preventing script execution when it shouldn't.
RemoteSigned is the only execution policy I want to use. I am aware that other, less-restrictive policies are available. If
those policies were acceptable substitutes I would have just used them
instead and this question wouldn't exist.
The execution policy is already set to RemoteSigned. Changing it from RemoteSigned to RemoteSigned is not a solution.
The script file is created and stored locally.
The script file is not blocked. The script file was never blocked (see previous point).
The script file cannot be unblocked because there is nothing to unblock (see previous point).
The script file is (attempted to be) executed by an administrator.
Windows PowerShell is the only application involved. Not Windows PowerShell ISE nor Command Prompt nor any other tools or
editors are relevant.
The cause of the problem has already been identified (see accepted answer). After nearly 8 years, I think all other obvious
explanations, whether applicable or not, have been posted, too. If
you think otherwise then please read the question and existing
answers in their entirety before adding yours.
I am using Windows PowerShell 2.0 on 64-bit Windows 7 Professional. I have a script on my Desktop that causes the following error when I try to run it:
File C:\Users\UserName\Desktop\Script.ps1 cannot be loaded. The file C:\Users\UserName\Desktop\Script.ps1 is not digitally signed. The script will not execute on the system. Please see "get-help about_signing" for more details..
At line:1 char:54
+ C:\Users\UserName\Desktop\TestGetWindowsUpdateLog.ps1 <<<<
+ CategoryInfo : NotSpecified: (:) [], PSSecurityException
+ FullyQualifiedErrorId : RuntimeException
I am both a domain administrator and a local administrator, and if I run Get-ExecutionPolicy -List, I can see that the Group Policy Object I created to configure PowerShell is correctly applying the RemoteSigned execution policy at the machine level:
Scope ExecutionPolicy
----- ---------------
MachinePolicy RemoteSigned
UserPolicy Undefined
Process Undefined
CurrentUser Undefined
LocalMachine Undefined
I created the script myself in Notepad, and used the Sysinternals' streams utility and the file Properties dialog to confirm that the script is not being treated as having come from the internet. If I copy the script to a network share on a domain server, then it's allowed to execute. If I run Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine then the local script is still not allowed to execute, which makes sense since the execution policy at the MachinePolicy scope will take precedence.
As documented by about_Execution_Policies(current; at time of question), the RemoteSigned policy means:
Scripts can run.
Requires a digital signature from a trusted publisher on scripts and configuration files that are downloaded from the Internet
(including e-mail and instant messaging programs).
Does not require digital signatures on scripts that you have run and that you have written on the local computer (not downloaded from
the Internet).
Risks running unsigned scripts from sources other than the Internet and signed, but malicious, scripts.
My script is not signed, but since it is both created and executed locally, it should satisfy the third bullet point above. Therefore...
Why is my script not being allowed to run?
Why does PowerShell complain that my script "is not digitally signed" when that requirement should only apply to files from the Internet?
Why does PowerShell no longer care about the script not being signed when it's run from a network share?
Some things to check:
Can you change to unrestricted?
Set-ExecutionPolicy Unrestricted
Is the group policy set?
Computer Configuration\Administrative Templates\Windows Components\Windows PowerShell
User Configuration\Administrative Templates\Windows Components\Windows PowerShell
Also, how are you calling Script.ps1?
Does this allow it to run?
powershell.exe -executionpolicy bypass -file .\Script.ps1
Is the file being blocked? I had the same issue and was able to resolve it by right clicking the .PS1 file, Properties and choosing Unblock.
When you run a .ps1 PowerShell script you might get the message saying “.ps1 is not digitally signed. The script will not execute on the system.”
To fix it you have to run the command below to run Set-ExecutionPolicy and change the Execution Policy setting.
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
I have found out when running a PS1 file for a Mapped drive to Dropbox that I'm always getting this error. When opening up properties for the PS1 there is no "Unblock".
The only thing that work for me is
powershell.exe -executionpolicy bypass -file .\Script.ps1
I finally tracked this down to .NET Code Access Security. I have some internally-developed binary modules that are stored on and executed from a network share. To get .NET 2.0/PowerShell 2.0 to load them, I had added a URL rule to the Intranet code group to trust that directory:
PS> & "$Env:SystemRoot\Microsoft.NET\Framework64\v2.0.50727\caspol.exe" -machine -listgroups
Microsoft (R) .NET Framework CasPol 2.0.50727.5420
Copyright (c) Microsoft Corporation. All rights reserved.
Security is ON
Execution checking is ON
Policy change prompt is ON
Level = Machine
Code Groups:
1. All code: Nothing
1.1. Zone - MyComputer: FullTrust
1.1.1. StrongName - ...: FullTrust
1.1.2. StrongName - ...: FullTrust
1.2. Zone - Intranet: LocalIntranet
1.2.1. All code: Same site Web
1.2.2. All code: Same directory FileIO - 'Read, PathDiscovery'
1.2.3. Url - file://Server/Share/Directory/WindowsPowerShell/Modules/*: FullTrust
1.3. Zone - Internet: Internet
1.3.1. All code: Same site Web
1.4. Zone - Untrusted: Nothing
1.5. Zone - Trusted: Internet
1.5.1. All code: Same site Web
Note that, depending on which versions of .NET are installed and whether it's 32- or 64-bit Windows, caspol.exe can exist in the following locations, each with their own security configuration (security.config):
$Env:SystemRoot\Microsoft.NET\Framework\v2.0.50727\
$Env:SystemRoot\Microsoft.NET\Framework64\v2.0.50727\
$Env:SystemRoot\Microsoft.NET\Framework\v4.0.30319\
$Env:SystemRoot\Microsoft.NET\Framework64\v4.0.30319\
After deleting group 1.2.3....
PS> & "$Env:SystemRoot\Microsoft.NET\Framework64\v2.0.50727\caspol.exe" -machine -remgroup 1.2.3.
Microsoft (R) .NET Framework CasPol 2.0.50727.9136
Copyright (c) Microsoft Corporation. All rights reserved.
The operation you are performing will alter security policy.
Are you sure you want to perform this operation? (yes/no)
yes
Removed code group from the Machine level.
Success
...I am left with the default CAS configuration and local scripts now work again. It's been a while since I've tinkered with CAS, and I'm not sure why my rule would seem to interfere with those granting FullTrust to MyComputer, but since CAS is deprecated as of .NET 4.0 (on which PowerShell 3.0 is based), I guess it's a moot point now.
If the file is copied from a network location, that is, another computer, Windows might have blocked that file. Right click on the file and click on the unblock button and see if it works.
What works for me was right-click on the .ps1 file and then properties. Click the "UNBLOCK" button. Works great fir me after spending hours trying to change the policies.
Select your terminal Command prompt instead of Power shell. That should work.
This is an IDE issue. Change the setting in the PowerShell GUI. Go to the Tools tab and select Options, and then Debugging options. Then check the box Turn off requirement for scripts to be signed. Done.
Please make a backup for the script.bs1 file
What works for me was deleting the script.bs1 file and running the execution command.
I was having the same issue and fixed it by changing the default program to open .ps1 files to PowerShell. It was set to Notepad.
Try running the Powershell GUI as Administrator
This occurs due to Powershell execution policy is set to restricted by default which prevents execution PowerShell scripts and protects from running malicious scripts.
You can change execution scope for specific scope by running the following command
Set-ExecutionPolicy -Scope Process
Run below 2 commands in PowerShell window
Set-ExecutionPolicy unrestricted
Unblock-File -Path D:\PowerShell\Script.ps1

Running a Powershell script on multiple PCs

I have modified a script to standardise our organisations signatures in Outlook. The script uses a Word document as a template for the signature and extracts user details from the Active Directory info on our SBS 2003 server.
I am logged in as a Domain Admin and the script works ok for my Outlook signature (there are a couple of errors but it creates the 3x outlook signature files that I need). I can't get it to run on any other computer (but this is the only one with Powershell installed) nor will it run for any other user on this computer.
I would really like to be able to run the script from each workstation. This would be easy if it was a batch file, but it won't work as a powershell script. Do I need to install Powershell on every workstation or is there a simpler way to get it to work?
Also,
I wonder if there is a problem with the script that is not allowing other users to run it from this computer (even with Powershell installed).
Cheers,
Greg
Yes, you need Powershell installed on every machine where you want the script to run. It's included with OS on everything from Server 2008 and Windows 7, but otherwise you'll need to install Powershell manually.
You will also have to enable remote scripting on each machine, since this is disabled by default (for security reasons). Take a look at the following help pages for information and instructions on how to set up:
Get-Help about_remote
Get-Help about_remote_FAQ
Get-Help about_remote_requirements
Get-Help about_remote_troubleshooting
If you want to use PowerShell remotely you will need to install it. If you don't want to do that you could look at psexec - that's one of Sys Internals great tools. It will enable you to run commands\scripts remotely.
I have a different suggestion. Could you generate these signature files for your employees on your machine and then push the signatures out to all the other machines?