Powershell as Administrator

iiMStevo

Member
Joined
Jan 26, 2020
Messages
5
Programming Experience
Beginner
Hi,

I'm running round in circles. I have an application that assembles a powershell script (Get-ChildItems | Remove-Item on UNC directory) on the local computer that has the application installed on.
The application assembles the .ps1 file successfully, this file runs perfectly when I open ps as administrator.

However, I cannot find any way to get the Powershell.Create() to open as Administrator so that the script runs. It simply does nothing now...

C#:
 private void Execute_Script_CMD(int _i, string _cmd)
        {
            _i = _i - 1;
            jobs.Add(false);

            WSManConnectionInfo _conInfo = new WSManConnectionInfo();
            _conInfo.ComputerName = serverHost;
            Runspace _psRun = RunspaceFactory.CreateRunspace(_conInfo);
            using (PowerShell _pscon = PowerShell.Create())
            {
                _psRun.Open();
                _pscon.Runspace = _psRun;
                
                var re = _pscon.AddScript(@"'" + _cmd + @"'");
                var results = re.Invoke();


                _pscon.Runspace.Close();
                _pscon.Dispose();
            }
            


            /*
            RunspaceMode rsM = RunspaceMode.NewRunspace;
            PowerShell _pscon = PowerShell.Create(rsM);
            _pscon.AddScript("Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser -Force");
            _pscon.AddScript(@"'" + _cmd + @"'");
            _pscon.Invoke();
            _pscon.Runspace.Close();
            */
            jobs[_i] = true;
        }

The above code has two versions of it. Initially I simply started with the console being created, the script added, and the invoke executing... Now I've got all this stuff everywhere from trying out what everyone suggests, but nothing works...

I've also added this line into my App Manifest so that the application itself is started as administrator:

HTML:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

Any help on how to do this would be greatly appreciated.

Cheers,
Steve
 
Start-Process powershell -Verb runAs
Also see : Start-Process (Microsoft.PowerShell.Management) for executing on a given working dir

I’m confused... do you want me to use c# to launch Powershell to then launch Powershell again and pass it commands? Is that the only valid fix? How would I get a return from the command to say that it’s finished processing the script in the second module?
 
That's strange... first verify that your script truly is running as an administrator.

With my code that looks like this:
C#:
using System;
using System.Management.Automation;

namespace TestPSHost
{
    class Program
    {
        static void Main(string[] args)
        {
            string script =
@"$user = [Security.Principal.WindowsIdentity]::GetCurrent();
(New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)";

            var ps = PowerShell.Create();
            ps.AddScript(script);
            var results = ps.Invoke();
            foreach (var result in results)
                Console.WriteLine(result);
        }
    }
}

If my app.manifest has "asInvoker" then I get the output of "False" (because I don't always run as admin). If my app.manifest has "requireAdministrator", then I get an output of "True". (As aside, if you are testing from within Visual Studio, you'll need to run VS as an admin to debug when the app.manifest has "requireAdministrator".)

In general, the way Windows works is if the parent application is running as an administrator, then any spawn applications will also run as an administrator. So if your app is truly running as an administrator, then any powershell scripts that you execute should also bu running as an admin.
 
That's strange... first verify that your script truly is running as an administrator.

With my code that looks like this:
C#:
using System;
using System.Management.Automation;

namespace TestPSHost
{
    class Program
    {
        static void Main(string[] args)
        {
            string script =
@"$user = [Security.Principal.WindowsIdentity]::GetCurrent();
(New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)";

            var ps = PowerShell.Create();
            ps.AddScript(script);
            var results = ps.Invoke();
            foreach (var result in results)
                Console.WriteLine(result);
        }
    }
}

If my app.manifest has "asInvoker" then I get the output of "False" (because I don't always run as admin). If my app.manifest has "requireAdministrator", then I get an output of "True". (As aside, if you are testing from within Visual Studio, you'll need to run VS as an admin to debug when the app.manifest has "requireAdministrator".)

In general, the way Windows works is if the parent application is running as an administrator, then any spawn applications will also run as an administrator. So if your app is truly running as an administrator, then any powershell scripts that you execute should also bu running as an admin.

Yup, so I’ve got VS running as Admin for the application, App Manifest runs as administrator. I even built and published the application to test while installed as well, none of the script actually executes.
Open the script file in PS ISE as admin, run exact same script file, and it executes perfectly.

While I originally had a similar script block, I haven’t had to actually use the results of the invoke. If there’s some kind of execution problem with the console not having access to where the scripts are stored (localappdata for user) could that be obtained inside Vs to output to a message box or something?
 
Trim down the script to only do a simple Start-Transcript and Stop-Transcript and nothing else. Make sure that the script actually executes.

Out of curiousity if all you are doing in your script is Get-ChildItem | Remove-Item why even use PowerShell. Just do something like:
C#:
foreach(var file in Directory.EnumerateFiles( ... ))
    File.Delete(file);
 
I think I’ve figured it out. I’m not working on it at the moment, but it could be nothing to do with the administration aspect, and could be because the script path contains spaces.
I added in ‘ around the script before because it was trying to execute up to the first space previously...
Now I’m only guessing, but I assume pasting a script path into Powershell as a string, would result in nothing happening (which is exactly what my issue is)

I’m thinking of doing something like the following to bypass it;


C#:
ps.addScript(
    @"Set-location '" + scriptPathDir + @"';
    .\script.ps1;"
);
 
Trim down the script to only do a simple Start-Transcript and Stop-Transcript and nothing else. Make sure that the script actually executes.

Out of curiousity if all you are doing in your script is Get-ChildItem | Remove-Item why even use PowerShell. Just do something like:
C#:
foreach(var file in Directory.EnumerateFiles( ... ))
    File.Delete(file);

Yeah I grossly oversimplified as it’s basically a tool for cleaning up Citrix profiles on an enterprise platform.
It’s got all sorts of filters, checks, logging etc included before it removes the directories.
 
This:
C#:
_pscon.AddScript(@"'" + _cmd + @"'");
seem unncessarily complex. There is no need for the '@' to protect the single quotes.

That could be simplified to:
C#:
_pscon.AddScript(string.Format("'{0}'", _cmd));
or
C#:
_pscon.AddScript($"'{_cmd}'");
or
C#:
_pscon.AddScript("'" + _cmd + "'");

Anyway, vaguely recall some kind of issue like for executing scripts that live in path with spaces. I think I solved it by using the something like:
C#:
& 'C:\some\path with spaces\script.ps1'
 
Back
Top Bottom