Running quser.exe in PowerShell scripts works in IDE but not when running as a service - powershell

If I run the following snippet in a console window or in ISE it works as expected, listing the active user sessions on the local computer:
(Invoke-Expression "$env:windir\system32\quser.exe") -replace '\s{2,}', ',' | ConvertFrom-Csv
Unfortunately this is not a console application, rather a PowerShell script that is installed as a service. The service runs as LocalSystem (not LocalService). When the service attempts to run this code it outputs the following error:
The term 'C:\Windows\system32\quser.exe' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
I contacted Sapien support and was informed that A service runs with no profile and does not have execution access to the system folders. You need to give the service account execution access to the exe and its support DLLs as well as using the full path to the EXE.
I have proven (I think) that the security principal has access to quser. I used PSExen to open a PowerShell console running as LocalSystem and successfully ran the quser application:
The issue MUST be that I'm running as a service. Does anyone know how I can access/use QUser in a service?
I guess the real question would be, how can services running as LocalSystem execute applications in system folders?

My guess is that whatever tool you are using to run your PowerShell script as a service is 32-bit, and there is not a quser.exe in C:\Windows\SysWOW64.
If this is the case, you can probably work around this on a 64-bit OS by running C:\Windows\Sysnative\quser.exe (see File System Redirector in the documentation for details).
If that's the case, I would say that the information you got ("service runs with no profile and does not have execution access to the system folders") is simply incorrect.

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.

Powershell script on network drive still giving security prompt even after running Unblock-File

I am trying to run a Powershell Cmdlet that I wrote.
It is stored on a network drive mapped to Z:\....
I have launched Powershell in administrator mode and set the execution policy to Unrestricted.
I have run Unblock-File on my Cmdlet, and every script that it calls.
I am calling my Cmdlet either with its absolute path, or with a relative path beginning with .\.
But still, tab completion is not working for my Cmdlet's parameters, and I still get this security warning:
Security warning
Run only scripts that you trust. While scripts from the internet can be useful, this script
can potentially harm your computer. If you trust this script, use the Unblock-File cmdlet to
allow the script to run without this warning message. Do you want to run <file-name>?
[D] Do not run [R] Run once [S] Suspend [?] Help (default is ā€œDā€):
What am I doing wrong?
The answer, in my case, is that Windows was configured to regard the network drive as a location on the public internet.
The solution was to launch the Internet Options control panel, navigate to the Security tab, and add the network share where my scripts were located (eg, \\networkshare) to the Local intranet security zone.
Afterwards, the tab completion worked correctly with my Cmdlet's parameters, and the script could execute without any security warning.

Powershell Script Deployed through Intune - Command Not Found

Not sure if this is for stakoverflow or serverfault.
I am deploying a Powershell script using MS Intune. The script works when run locally, but when deployed I get the error below:
Remove-LocalGroupMember : The term 'Remove-LocalGroupMember' is not
recognized as the name of a cmdlet, function, script file, or
operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again. At
C:\Program Files (x86)\Microsoft Intune Management
I am not sure why this commandlet is unavailable as it is definitely there if I open a powershell and run this command.
I am logging the $user variable to check that it is not null or running under a different context.
The code is quite simple as below:
$user = $(whoami)
$user | Out-File 'C:\powershelllog.log'
Remove-LocalGroupMember -Group Administrators -Member $user
I believe I've run into the same issue as you are having. I've been trying to create a local admin account on machines. Running the powershell script with the system context in Intune. What I've found is that you must check: "Run script in 64 bit PowerShell Host" inside of the Intune where you import powershell scripts.
Apparently not all commands are available with the 32 bit ps console running that way.
I also used the get-command to determine what module the command that was reporting not found was is in, and used the import-module at the top of my script in case.

Powershell as scheduled task issue with importing module, it seems

I am attempting to configure some powershell/view powercli scripts for our VMware horizon environment. I have a powershell script that works properly to query the horizon instance and check machine states. However, when I try to run this as a scheduled task using a service account, it seems to fail to import a module, as a command is unrecognized ("The term 'Connect-HVServer' is not recognized as the name of a cmdlet, function, script file, or operable program.")
I tried profiles as well, didn't matter.
What I observed is that if I open powershell as the user in question (run as different user > authenticate as service account), leaving that powershell instance open will allow the scheduled task to run as expected. However, if i close the powershell instance, the scheduled task fails. This is obviously not viable since the goal is for this script to run on a schedule without the service account (or any account) being logged into the windows server at the time the powershell script gets run.
The problem you're running into is environment variables. In the course of running as a user versus running as machine, the PSModulePath environment variable changes to include user-directories for user-scoped module installs. You should install PowerCLI machine-wide.
Alternatives (these assume your service account has admin privileges):
Modify your $Env:PSModulePath in the script to include each user's module path
Specify the path in an Import-Module statement in your script before you use any of the cmdlets
Example of the first alternative:
foreach ($user in (Get-ChildItem -Path C:\Users)) {
$Env:PSModulePath += ";$($user.FullName)\Documents\WindowsPowerShell\Modules"
}
Example of the second:
Import-Module -Name 'C:\Users\KnownUser\Documents\WindowsPowerShell\Modules\PowerCLI'

Azure Powershell agent task pipeline

I'm just wondering whats the chain underlies Azure Powershell VSO agent task. I assume that is not simple powershell host because it is not working with some commandlets (for example Get-Module -ListAvailable) and fails with an error:
The term 'Get-ServiceEndpoint' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the spelling
of the name, or if a path was included, verify that the path is
correct and try again.
A Connected Service with name 'xxxxx-xxxx-xxxxx-xxxx-xxxxxxxxxxx' could not be found. Ensure that
this Connected Service was successfully provisioned using services tab
in Admin UI.
VSTS build task are normal powershell scripts. However the 'Get-ServiceEndpoint' is a known issue: issue.
As far as I can see other cmdlets are working normally. I've been able to write several build tasks without any problems.