rodneyviana / ODSyncService

OneDrive service/DLL for Sync State
MIT License
93 stars 26 forks source link

Not working when running in a script as scheduled task #12

Closed mxroo closed 4 years ago

mxroo commented 4 years ago

Thank you for all your work on this, this looks like it will meet our needs. It's almost working perfectly, I created a powershell ps1 script to run this and output to a txt file that I then parse elsewhere.

contents of ondriveoutput.ps1

Import-Module C:\Users\Administrator.EMC\Downloads\OneDriveLib.dll
Get-ODStatus | Out-File -FilePath C:\Windows\Temp\onedrivestatus.txt

When in a normal cmd window it works perfectly, gives the output I need into the txt file. C:\Users\Administrator.EMC>powershell.exe "C:\Users\Administrator.EMC\onedriveoutput.ps1" When I run it in powershell ISE or powershell command window, also works right.

When I run that ps1 file as a windows scheduled task, onedrivestatus.txt comes out empty. I have made sure I'm not running the scheduled tasks as elevated, running it as the Administrator user, running with full path to powershell, full path to the ps1 script, run in the directory, and tried every other setting I could, but still when running as a scheduled task, the output file is empty.

Is there a setting I'm missing or another bit of code my ps1 script should have?

thanks!

rodneyviana commented 4 years ago

It requires interactive mode as well (not my rule, OneDrive's). So, you should schedule to run only when customer is logged in. You may use "-IncludeLog $true" to generate a log file on user temp folder and confirm whether it is because it is not running in interactive mode. Notice that user A can only check OneDrive status for User A. So, Administrator can only check OneDrive status of Administrator's. One of my customers has it working as a Task running when user is logged in and uploading the results to a SharePoint list.

mxroo commented 4 years ago

Thank you, I tried that, still the same empty result. Yes, I am trying to check the OneDrive status for the Administrator account.

Screen Shot 2020-05-08 at 2 59 59 PM Screen Shot 2020-05-08 at 2 59 37 PM
mxroo commented 4 years ago

tested changing the script to include log, and when I run it via cmd, it works and writes to log. when I run it in scheduled task, it does not write anything to that same log file

Import-Module C:\Users\Administrator.EMC\Downloads\OneDriveLib.dll
Get-ODStatus -IncludeLog $true | Out-File -FilePath C:\Windows\Temp\onedrivestatus.txt

when running in cmd, here is the file it is writing to: C:\Users\Administrator.EMC\AppData\Local\Temp\1\OneDriveLib-2020-05-08.log

rodneyviana commented 4 years ago

First, change your script to the one below to avoid the problem of being barred because you are writing to the OS folder:

Import-Module C:\Users\Administrator.EMC\Downloads\OneDriveLib.dll
Get-ODStatus | Out-File -FilePath "$($env:TEMP)\onedrivestatus.txt"

Then if it fails:

Paste the log file generated with "-IncludeLog $true" . Change all sensitive information for X (like the name of your company on the path if it is OneDrive Business). The GUID ids are not sensitive (they are OneDrive related) and they need to be left as they are.

mxroo commented 4 years ago

Thank you for your help. Unfortunately, when I make that change and run it as a scheduled task, nothing happens. The onedrivestatus.txt file doesn't get created in the TEMP directory, and no logs get written there either.

rodneyviana commented 4 years ago

Try to create a root folder like c:\temp. Change your script to save on that folder. Also add this line to show the temp folder when you run a task:

"$($env:TEMP)\onedrivestatus.txt" | Out-File c:\temp\tempfolder.txt

mxroo commented 4 years ago

Telling the script to save the onedrivestatus.txt file to c:\temp creates a file, but that file is still empty when run as a scheduled task, and still nothing is written to the log even with -IncludeLog $true.

rodneyviana commented 4 years ago

So let's see what PowerShell is saying:

$transcriptFile = "c:\temp\transcript$((Get-Date).ToString('yyyyMMdd_hhmmssfff')).txt"
Start-Transcript -Path $transcriptFile
Import-Module C:\Users\Administrator.EMC\Downloads\OneDriveLib.dll
Get-ODStatus | Out-File -FilePath "$($env:TEMP)\onedrivestatus.txt"
Stop-Transcript
rodneyviana commented 4 years ago

Actually, use this instead:

$transcriptFile = "c:\temp\transcript$((Get-Date).ToString('yyyyMMdd_hhmmssfff')).txt"
Start-Transcript -Path $transcriptFile
Write-Host "Temp is set to: $($env:TEMP)"
Import-Module C:\Users\Administrator.EMC\Downloads\OneDriveLib.dll
Get-ODStatus | Out-File -FilePath "$($env:TEMP)\onedrivestatus.txt"
Stop-Transcript
mxroo commented 4 years ago

Thank you!!! Looks like even though I said run only when user is logged on, and unchecked run with highest privileges, it's still running as elevated.

**********************
Windows PowerShell transcript start
Start time: 20200508173401
Username: EMC\Administrator
RunAs User: EMC\Administrator
Configuration Name: 
Machine: EMCDC (Microsoft Windows NT 10.0.17763.0)
Host Application: powershell.exe C:\Users\Administrator.EMC\onedriveoutput.ps1
Process ID: 14804
PSVersion: 5.1.17763.1007
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.17763.1007
BuildVersion: 10.0.17763.1007
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
Transcript started, output file is c:\temp\transcript20200508_053401168.txt
Temp is set to: C:\Users\ADMINI~1.EMC\AppData\Local\Temp
PS>TerminatingError(Get-ODStatus): "PowerShell is running in Administrator mode. OneDrive status cannot be checked in elevated privileges"
Get-ODStatus : PowerShell is running in Administrator mode. OneDrive status cannot be checked in elevated privileges
At C:\Users\Administrator.EMC\onedriveoutput.ps1:13 char:1
+ Get-ODStatus | Out-File -FilePath "$($env:TEMP)\onedrivestatus.txt"
+ ~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-ODStatus], InvalidOperationException
    + FullyQualifiedErrorId : System.InvalidOperationException,OneDriveLib.GetStatus
Get-ODStatus : PowerShell is running in Administrator mode. OneDrive status cannot be checked in elevated privileges
At C:\Users\Administrator.EMC\onedriveoutput.ps1:13 char:1
+ Get-ODStatus | Out-File -FilePath "$($env:TEMP)\onedrivestatus.txt"
+ ~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-ODStatus], InvalidOperationException
    + FullyQualifiedErrorId : System.InvalidOperationException,OneDriveLib.GetStatus

**********************
Windows PowerShell transcript end
End time: 20200508173401
**********************
mxroo commented 4 years ago

I remember seeing similar in another issue, so I checked my local security policy, and it looks as it should. https://github.com/rodneyviana/ODSyncService/issues/9#issuecomment-585986842

Screen Shot 2020-05-08 at 5 42 39 PM
rodneyviana commented 4 years ago

Nice catch. I forgot about it.

mxroo commented 4 years ago

Unfortunately my security policy already was what you recommended it be, but somehow still powershell is running as elevated. It is very difficult to find any documentation online on how to tell powershell to run not as elevated.

rodneyviana commented 4 years ago

Replace your script by this:

$IsAdmin = [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")

if($IsAdmin)
{
$parts = [System.Environment]::CommandLine.Split(' ');
[string]$params = '';
for($i=1;$i -le $parts.Length;$i++)
{
  $params = $params+$parts[$i]+' ';
}
$path = (Get-Process -Id $PID | % { $_.Path })
Unregister-ScheduledTask -TaskName ODSyncImproved -Confirm:$false -ErrorAction Ignore
$action = New-ScheduledTaskAction -Execute $path -Argument $params
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 1) -RepetitionDuration (New-TimeSpan -Days 365)
$principal = New-ScheduledTaskPrincipal -UserID "$([System.Environment]::UserDomainName)\$([System.Environment]::UserName)" -LogonType Interactive -RunLevel Limited
$settings = New-ScheduledTaskSettingsSet -MultipleInstances Parallel

Write-Host "Rerunning $($path) $params" 

Register-ScheduledTask -TaskName "ODSyncImproved" -TaskPath "$($env:HOMEPATH)" -Action $action -Trigger $trigger -Settings $settings -Principal $principal
#Start-ScheduledTask -TaskName ODSync
Write-Host "Running as Admin. So running again.."
Start-Sleep -Seconds 100

} else
{
      Write-Host "Running as non-admin";
      Write-Host "Doing what it should";

      Import-Module C:\Users\Administrator.EMC\Downloads\OneDriveLib.dll
      Get-ODStatus | Out-File -FilePath "c:\temp\onedrivestatus.txt"

}
Unregister-ScheduledTask -TaskName ODSyncImproved -Confirm:$false -ErrorAction Ignore

After the script runs you have to wait at least 1 minute before checking if it worked

mxroo commented 4 years ago

That works when running from cmd or powershell command, but still doesn't work when running as a scheduled task. It pops up with a windows that says:

Running as Admin. So running again.. then it pops up another one of those windows, and another, until they all just close after a couple minutes. It doesn't update the c:\temp\onedrivestatus.txt file. I checked the scheduled task timeout, and it's one hour.

rodneyviana commented 4 years ago

I am out of ideas. Sorry for not being able to help you. Does it happen to all users or just Administrator?

mxroo commented 4 years ago

Thank you for all your work on this, even though we didn't figure it out, I appreciate the help! Administrator is the only user on that machine connected to onedrive. I'll update this if I find a solution.