Powershell - Find the user who invoked the script - powershell

I have a script(Let's call it myPSScript.ps1) which takes two parameters and performs predefined steps. Script is located in a Windows Server box which people login and execute the script. Supports two users to be logged in at the given time.
I want to find out who invoked the script.
(Get-WmiObject -Class Win32_Process | Where-Object {$_.ProcessName -eq 'explorer.exe'}).GetOwner() | Format-Table Domain, User
This works when the user is logged in currently and trying to run the script. But what if I have a batch file in scheduled tasks and run the same script?
In that case the same command returns a null exception, as there is no one logged into the machine.
Is there a way to find out who/which process invoked the powershell script. I vaguely remember Start-Transcript records which user the command is run from etc, so this should be possible?
Thanks!
Sanjeev

Interesting question. I wrote a script with three different ways to get the user like so:
([Environment]::UserDomainName + "\" + [Environment]::UserName) | out-file test.txt
"$env:userdomain\$env:username" | out-file -append test.txt
[Security.Principal.WindowsIdentity]::GetCurrent().Name | out-file -append test.txt
notepad test.txt
Saved it as test.ps1 and called it using runas as:
runas /user:domain\user "powershell e:\test.ps1"
And I got the domain\user all three times in the output. Used runas to just distinguish between the user I am logged in as (me!!) and the domain\user with which I was running it as. So it does give the user that is running the script.

Related

PowerShell Logon Script by GPO writes empty file

I'm trying to set up a simple script.
Every time a user does log in, it should execute a simple PowerShell script by the GPO I set up, the script should then gather all data from Get-ComputerInfo and write it to a file on a shared folder.
I've tried many things, like Start-Job
$Task = Start-Job -ScriptBlock {
Get-ComputerInfo | Out-File "\\SERVER\ComputerInfo\$env:COMPUTERNAME -
$env:USERNAME.txt"
}
Wait-Job $Task.Name | Out-Null
It works great executing it on the desktop by the user, but as logon script it does not work. It creates the file, but it's empty.
My suspicion is that it does not wait until PowerShell gather all information from Get-ComputerInfo (it usually takes some seconds) and just writes an empty file.
Execution Policy, Permission for Folders, etc shouldn't be a problem, especially considering it creates the file and the script works on the desktop with a non-admin user.

PowerShell script runs in ISE but not as a script

OBJECTIVES :-
I'm having trouble with something that should be relatively simple? Searched similar questions here but no cigar. I dont want to have to pass a command to the file as a Ps1 script (common suggestion). I'm hoping I can just right click, run with PowerShell and it works.
SITUATION :-
I have to automate uninstalling of software often. Rather than scour the registry for msiexec strings, I edited some PS code so I can search for what I want, then do whatever I need to do with the info I receive. The below runs fine in PowerShell ISE, but as a PS1 script (right click, run with PS) it outputs nothing on the screen.
CODE :-
$Prog = Read-Host -Prompt 'Input your Prog name'
Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall | Get-ItemProperty | Where-Object {$_.DisplayName -match "$Prog"} | Select-Object -Property DisplayName, UninstallString
pause
Lets say at the prompt I search for 7-Zip in ISE I get this...
Input your Prog name: 7-zip
DisplayName UninstallString
----------- ---------------
7-Zip 19.00 (x64) C:\Program Files\7-Zip\Uninstall.exe
Running as a script, I get nothing output into the console?
Input your Prog name: 7-zip
Press Enter to continue...:
QUESTION :- What do I need to do to make the script behave like it does in the ISE console?
Many thanks for any assistance
P.S (<see what I did there, I'm new to the PowerShell game, thanks>)
It works in Powershell too, if you run it from Powershell Interactive Prompt or run using powershell -file "FILEPATH" in CMD/PowerShell, the output remains on the screen. But when you run directly with a double-click output doesn't stay persistent on the screen, instead when it reaches EOF then it quits. So, Add Read-Host or cmd /c pause at the end to stop the program at the end, to view output.

Run exe with arguments on remote machine

This one is ruining me. Something that I'm pretty sure should be simple just isn't working and it's probably just a single quotation/character out of place.
There's a lync/Skype tool called sefautil.exe that does all kinds of marvelous things the webGUI doesn't. A typical command would be:
C:\Program Files\Skype for Business Server 2015\ResKit>sefautil.exe /server:sfbpool01.domain.local sip:user1#domain.local /setfwddestination:user2#domain.local /enablefwdimmediate
This works fine when remoted onto any of the machines, but I'm really struggling to run it via remote PowerShell.
Whatever commands I try via invoke-command either give me a standard /? response or nothing at all. I've passed the args via -ArgumentList, as a variable, as anything I can think of and it's just not working.
What makes the thing even more tasking as if you run without admin rights, you won't ever get any results. The command has to be ran as an admin. Now I can quite easily put an admin mode checker into my script, but if it's just as easy to send the command as admin I'll take it.
Any help would be massively appreciated.
#qbanet359
I've gone about it a different way which feels a little cheap, but it does work so can't complain.
I've created a scheduled task on the server hosting sefautil.exe to run a batch file under elevated permissions - I've called it sefautil.
I also copied sefaUTIL.exe to C:\TEMP on the server.
Then in my PowerShell script I'm using:
$SERVER = "\\computer1\c$\temp"
"cd \" | Out-File "$SERVER\sefautiltest.bat" -Encoding unicode
"cmd /c C:\Temp\sefautil.exe /server:sfbpool01.ad.leics.gov.uk sip:dols.team#leics.gov.uk" | Out-File "$SERVER\sefautiltest.bat" -Append
gc $SERVER\sefautiltest.bat | out-file $server\sefautil.bat -encoding ascii
Invoke-Command -Credential $CREDS -ComputerName computer 01-ScriptBlock { schtasks /Run /TN sefautil }
It's almost certainly a long winded way of doing this, but it does work.
Thanks for giving me a fresh perspective on things.
A Little late to the party, but I'm sure a lot of other SfB-Admins will struggle here as well.
This is how I made it work:
Invoke-Command -ComputerName $Global:SefaUtilServer -ScriptBlock {&'C:\Program Files\Skype for Business Server 2015\ResKit\SEFAUtil.exe' '/server:epsachhst-lfe11.epsa.swisscom-mcc.local' $args[0] "/enablefwdnoanswer" "/setfwddestination:$($args[1])" "/callanswerwaittime:$($args[2])"} -Credential $Global:LyncSchedTask_Cred -Authentication Credssp -ArgumentList #($UserSip.replace("sip:",""),$Destination,$Delay)
Hint: make sure, that you don't run in the "Powershell Double Hop issue". SefaUtil will make a Connection to a Frontend Server (I assume it's the one with the CMS located) to make the actual changes in the DB. (See my answer on TechNet: https://social.technet.microsoft.com/Forums/office/en-US/5d4c4f90-1b40-4742-ae4b-c2e1a62a0adb/running-sefautil-remotely?forum=lyncdeploy#da6b82b9-cada-420b-a7a7-2110c0ed2280 (by cwa.cloud)
This is the solution I came up with below.
Basically create a batch file with powershell on the SfB server and then run it with psexec to use the System account (psexec had been copied to the server).
Make sure you insert your own server's name where it has "servername" and run the script with an account that has sufficient permissions. Then call the script with the correct parameters.
BTW, I've noticed it can return an error code of 1 if the forwarding is already in place.
param ([string]$FwdUser,[string]$DestUser)
#skype for business phone forwarding
#create a batch file to run the command, run it as system with psexec and remove the batch file afterwards. sefautil does not cooperate with remote execution
$sefautilcmd = "`"C:\Program Files\Skype for Business Server 2015\ResKit\SEFAUtil.exe`" /Server:servername.headoffice.novationleasing.com.au " + $FwdUser + " /setfwddestination:" + $DestUser + " /enablefwdimmediate"
New-Item \\servername\c$\temp\tempfwd.bat
Set-Content \\servername\c$\temp\tempfwd.bat $sefautilcmd
Invoke-Command -ComputerName servername -ScriptBlock {C:\temp\psexec.exe -s -accepteula c:\temp\tempfwd.bat}
Remove-Item \\servername\c$\temp\tempfwd.bat

Another Task Scheduler not executing PowerShell

I have a simple PowerShell script that just creates a file. Testing this for a bigger PowerShell script.
Running on Windows Server 2012 R2 - 64-bit
its running under the Administrator account.
Run whether user is logged on or not
Run with highest privileges
Action:
Program/Script
:
Powershell.exe (I've tried it this way and the full path)
Add argumetns: -NoProfile -executionpolicy remotesigned -file C:\Scripts\test.ps1
Get-executionPolicy: RemoteSigned
added "Administrator" to:
Set-PSSSessionConfiguration -Name Microsoft.PowerShell -ShowSecurityDescriptorUI
"Administrator" has "Log on as batch job" permissions
"Administrator" is in the Admins group
PowerShell Script for testing:
$text = "Hello World"
$text | Set-Content TestMyFile.txt
$text | Out-File TestMyFile.txt
$text > TestMyFile.txt
# This is to write into a file or append to the text file created:
$text | Add-Content TestMyFile.txt
$text | Out-File TestMyFile.txt -Append
$text >> TestMyFile.txt
Nothing fancy, just trying to make sure Task Scheduler will execute a PowerShell script.
So What am I missing?
Use full paths in your output code, and for any future problems with running scripts from Task Scheduler, you should first put in logging and try/catch blocks to see what errors/outputs the script is generating before seeking further assistance. Doing this will help you find the answer faster & learn faster at the same time.
Tip: Always only name the program in the 'Program to run' aspect of Task Scheduler, as the Task Scheduler uses its own wrapper to execute the action, and in rare occasions, it can produce undesired results if you place the entire execution line in this field. Always put parameters in the parameters field.

Why will PsExec not execute a .ps1 script remotely?

I am trying to write a script in PowerShell that gathers free space on the C: drive and then appends it to a .csv file on a network drive.
Our company does not have PowerShell enabled by default. Remote PowerShell commands are restricted. Because of this, I have to script things out, then kick them off using PsExec.
I have two scripts for this process. The first one, is the one I run from my machine, this script asks for my credentials and then uses a foreach loop to cycle through a .txt file with IP addresses telling each IP to launch the second script from a network drive. The second script gathers the free space, performs a math function on it, then appends the hostname and free space to a .csv file on the network.
However, the second script never runs. After the connection is established using PsExec, my console just sits there. It should kick off the script and then loop again to the next IP. I have tested the second script manually on some of the target machines with no issues.
Locally executed script:
$username = Read-Host "Username"
$outputPath = "\\network\directory\sub-directory\FileName.csv"
$IPpath = Read-Host "Enter the path for the list of IP addresses"
$IPs = Get-Content -Path $IPpath
Add-Content -Path $outputPath -Value """IP"",""Free Space"""
foreach ($IP in $IPs)
{
if (Test-Connection -Count 1 -ComputerName $IP -Quiet)
{
\\network\directory\subdirectory\psexec.exe -accepteula \\$IP -u domain\$username -h PowerShell -ExecutionPolicy Bypass -Command \\network\directory\sub-directory\diskSpaceCheck.ps1
}
else
{
Add-Content -Path $outputPath -Value """$IP"",""Offline"""
}
}
Remotely executed script (diskSpaceCheck.ps1):
$outputPath = "\\network\directory\sub-directory\FreeSpace.csv"
$hostname = hostname
$disk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'"
$freeSpace = [System.Math]::Round((($disk.FreeSpace) / 1GB))
Add-Content -Path $outputPath -Value "$($hostname), $($freeSpace)"
I don't think you can have an if statement inside a foreach also but I've tried it without the if test and got the same results. I can't figure out why the remote machine won't execute this script. I have another script that is copied to these machines and then executed in the same manner that works correctly.
Also, the target machines are locked down to limit their use for only specific purposes. These machines use a generic auto logon and generally have access to a few applications. Everything else is inaccessible, including Windows Explorer, Control Panel, etc. I tested this script on some of the machines local to my office, and it worked fine.
I was thinking maybe a networking latency issue? Can that impact PsExec or .ps1 scripts? I can remote onto the machine, log out, log in with my credentials and run the script while PsExec just sits at running the command I gave it.
Any advice would be appreciated.
This can occur if you are using PSExec to directly execute the Ps1 file. Instead use PSexec to execute PowerShell.exe and pass your ps1 file as a parameter.
Also check this question: Run PowerShell on remote PC
I figured it out. The script was running but it was just sitting there waiting for another command. I added a stop-process command to the script that runs remotely.
Stop-Process -Name powershell
Now it runs, and then exits with error code -1.