How to run Task Scheduler on Window Server with non-admin user account

We had a non-admin user that needed to open the Task Scheduler and manage some tasks. The problem is that when that user opened the Task Scheduler, it was empty, but accessing as administrator we could see the tasks were there. We didn’t want to change the user to be an admin since that was the only thing the user needed access to, so we need a workaround.

What I found on my searches

I’ve googled and found some suggestions that didn’t work for me:

  • Adding permission to the user in the folder C:\Windows\System32\Tasks.

  • Change the Local Policy to allow "Log on as a batch job".

Half way through

Funny thing, accessing the scheduler using the command schtasks, shows the tasks there.

Unfortunately, for me, the user accessing that server was not a technical user, so typing commands was not the best option.

A light shines

But them I thought: "If when accessing as admin I can see the tasks, maybe I can run the scheduler as admin and save that configuration including the credentials". Obviously, Windows has no such feature built-in, but using some PowerShell commands I can:

  • Save my credentials into a file
  • Load it later
  • Execute something using that credential.

Now, let’s say the user is called Bob. Let’s create some files somewhere Bob can access but not so visible (we want to hide the ugliness of our solution). Bob’s AppData folder sounds like a good place to put our files, so we will create a folder called Scheduler inside it. The folder’s path will be: C:\Users\Bob\AppData\Roaming\Scheduler. If you’re logged as Bob, simply opening the Run command window (Win Key+R) and typing %AppData% will open up that path. You then just need to create the new Scheduler folder.

First, we save our credential by opening a PowerShell and typing:

$credential | Export-CliXml "C:\Users\Bob\AppData\Roaming\Scheduler\credential.xml"

After our credential is saved, we create a PowerShell script to load the Task Scheduler using that credential. Here is the file’s content:

$credential = Import-Clixml .\credential.xml
Start-Process "C:\Windows\System32\cmd.exe" -workingdirectory $(pwd) -Credential $credential -ArgumentList "/c %windir%\system32\taskschd.msc /s"

We will save that file as: C:\Users\Bob\AppData\Roaming\Scheduler\impersonate.ps1

Then, create a link onto Bob’s desktop folder with the following configuration:

  • Target: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "C:\Users\Bob\AppData\Roaming\Scheduler\impersonate.ps1"
  • Start in: C:\Users\Bob\AppData\Roaming\Scheduler

You can even change the icon so it looks like the real Task Scheduler. You can find the icon in this file: %windir%\system32\miguiresource.dll

Do you have a different way of working around this bug? If you do, please share in the comments bellow.

jQuery UI Sortable with connected tables and empty rows

Sortables are pretty cool. But one thing many people struggle with when trying to implement them is get them to work with tables. I had some issues specially with empty rows, and since I learned a little by working with it, I want to spare you all the searches and tries.

Sorting table rows

The examples on jQuery UI demos page are using ul and li elements. If you are working with them you are fine. When you are working with tables though, the first thing you need to change is which items will be moved/sorted, in this case, the tr. The code will look like this:

$(".sortable").sortable({
    items: 'tbody > tr'
});

Connecting the tables

To connect the tables, we will use the connectWith option:

$(".sortable").sortable({
    items: 'tbody > tr',
    connectWith: ".sortable"
});

It basically says which elements talk to each other. This will work as long as both tables have the same class, which is the easiest way you can do it. If in your case the tables do not have the same class, just separate the selectors by comma, like "#table1, #table2".

Drop table cells on empty rows

I found some code that had tables with empty rows working http://jsfiddle.net/zlzu3/62/ and I was following that code almost exactly but mine still wasn’t working. Then I noticed, it has Table Headers! So, I realized that you need a little visible space in order to be able to drop something on it. Let’s make our table visible:

.sortable {
    background-color: silver;    
    height: 10px;
}

.sortable td { background-color: white; }

I gave my table a background color and a height, I also added an invisible row to the tbody because I couldn’t set a height for an empty table.

<table class='sortable'>    
    <tbody>
        <tr><td colspan="2" class="drop-row" style="display: none;"></td></tr>
    </tbody>    
</table>

Great! Now I can see it and it works!

Here is the full code: http://jsfiddle.net/stanleystl/cea944zp/

Drop table cells on empty rows (version with tfoot)

I wasn’t happy with the fact that I had to isolate my empty row every time I need to get the items in my table, like the :not in my items selector, so I came up with a version using tfoot. No big changes. Here it is:

http://jsfiddle.net/stanleystl/aL72L974/

The technique consists in having an invisible tr with visibility: hidden inside my table. The visibility will hide that row, but still occupies its space, and here is where I can drop my rows. Then, I customized the sortable receive event to check if there is any row in the table, and if there is, I hide the hidden row (or I kill it until it is dead!), but now with display: none; which will no longer occupy that space. I also check if I need to hide any empty rows when the page loads.

function hideOrShowDropRow(){    
    $(".sortable").each(function() {
        var dropRow = $(this).find(".drop-row"),
            hasRows = $(this).find("tbody tr").length;
                        
        hasRows ? dropRow.hide() : dropRow.show();
    });
}

First line empty in Razor

First of all, I never thought a problem so simple would give me such a hard time!

My Problem

I’m using Razor views to generate some XML. I know I should probably use some sort of Serializer/Deserializer for that kind of job, but I needed something easier to change and preferably something that doesn’t need to be compiled. The problem is an empty line before my content which off course makes it invalid.

The code looks like:

@{
Response.ContentType = "text/xml";
}
<?xml version="1.0" encoding="UTF-8" ?>
...

and here is how the output is generated:

Empty line before content

First Try

The first thing I tried was to move the <xml> tag to the line above getting rid of the new lines that could possibly have.

@{
Response.ContentType = "text/xml";
}<?xml version="1.1" encoding="UTF-8" ?>
...

I even moved the Razor block to the bottom…

<?xml version="1.1" encoding="UTF-8" ?>
...
@{
Response.ContentType = "text/xml";
}

Nothing!

Second Try

Ok. This first line is not in my code. Something is putting it there. No problem! I can create a Response Filter and change the output removing this empty line.

using System.IO;
using System.Text;
using System.Web.Mvc;

namespace MyWebsite.Helpers
{
    public class RemoveEmptyLineWriter : MemoryStream
    {
        private readonly Stream filter;

        public RemoveEmptyLineWriter(Stream filter)
        {
            this.filter = filter;
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            var content = Encoding.UTF8.GetString(buffer);
            content = RemoveFirstEmptyLine(content);
            filter.Write(Encoding.UTF8.GetBytes(content), offset, Encoding.UTF8.GetByteCount(content));
        }

        private static string RemoveFirstEmptyLine(string content)
        {
            var firstLineIsEmpty = content.Substring(0, 2) == "\r\n";
            return firstLineIsEmpty ? content.Substring(2, content.Length - 2) : content;
        }
    }

    public class EmptyLinesRemoverFilter : ActionFilterAttribute
    {
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            base.OnResultExecuted(filterContext);
            var response = filterContext.HttpContext.Response;
            response.Filter = new RemoveEmptyLineWriter(response.Filter);
        }
    }
}

 

[EmptyLinesRemoverFilter]
public ActionResult Index()
{
  return View();
}

This code I found here, and then I changed it a little bit.

It simply adds to the Response a Filter which is invoked after the output is generated. So I can get it, modify and write again to the buffer.

I think this would have worked just fine if it wasn’t for my IIS being configured to Gzip the document. With Gzip enabled, after I read the buffer the content is just a bunch of messy characters. Decompressing the content and then compressing again is not a solution as it would cause an unnecessary overhead in my application. I’d rather turn Gzip off for those type of files but only if I really had to.

I also tried changing the order that my filter is added by changing the OnResultExecuted to OnActionExecuting but it doesn’t affect the order that the filter is executed, only the order in which it’s added to the response, which makes no difference.

My next try would be creating an IHttpModule, but I wanted something easier and something that I didn’t have to intercept all my requests.

Solution 1

Maybe you were lucky and the previous solutions worked for you, but in case they don’t, here is what worked for me. I had to go deeper in MVC and change the hierarchy of which the rendering is executed.

I ended up with this:

using System.Web.Mvc;
using System.Web.WebPages;

namespace MyWebsite.Helpers
{
    public class RazorXmlViewPage<T> : WebViewPage<T>
    {
        public override void ExecutePageHierarchy()
        {
            Response.ContentType = "text/xml";
            Layout = null;
            PushContext(new WebPageContext(), Response.Output); // push a new page context to the stack
            base.ExecutePageHierarchy();
        }

        public override void Execute()
        {

        }
    }

    public class RazorXmlViewPage : RazorXmlViewPage<object>
    {

    }
}

and in my Razor view…

@inherits RazorXmlViewPage<IEnumerable<string>>
<?xml version="1.0" encoding="UTF-8"?>

Thanks to this post that provided a source code that helped me get to this one.

The Razor view file inherits the WebViewPage by default. This page tells Razor that it inherits from a different class, in which I can override the execution of its core methods. We also have to override the Execute method because it is abstract.

It turns out I din’t even have to modify the output. Just by pushing a new WebPageContext to the stack the page rendered without the blank line.

But, if wanted, I could do some cools things with the Output. Take this code for instance:

public override void ExecutePageHierarchy()
{
    StringWriter writer = new StringWriter();
    PushContext(PageContext, writer);
    base.ExecutePageHierarchy();
    PopContext();

    Response.Clear();
    string output = writer.ToString();
    output = output.Replace("<body>", "<body><h1>An Example of Filtering Razor Output</h1>");
    Response.Write(output);
    Response.End();
}

If you want to understand better the methods used in the code above, take a look at the WebViewPage source code.

Solution 2

Another solution is to Render your View as a string, using the method bellow, change it and set the Response to your new content.

public string RenderRazorViewToString(string viewName, object model)
{
  ViewData.Model = model;
  using (var sw = new StringWriter())
  {
    var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
    var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
    viewResult.View.Render(viewContext, sw);
    viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
    return sw.GetStringBuilder().ToString();
  }
}

You know when you use return View(model);. This method it’s actually an alias to return new ViewResult {}. What the code above is doing is using the same implementation of that class, as you can see in the MVC source, in the method ExecuteResult.

I knew that I could use this code when dealing with this problem, but as I was looking at that class, I felt bad copying that much code from the MVC source and pasting it into my code. What if MVC updates as it does often and change that code? I’ll have to copy and paste it again in case this bug remains not fixed. So, for my use case I used the first solution as is less code copied and rewrote, plus, I didn’t even have to remove the first line from my output since the change skipped the bug. For other use cases the second solution might suit better your need/taste.

Please comment here what worked for you.

ZeroClipboard hosted on CDN

When working with ZeroClipboard, in my local environment it worked perfectly. However, when I uploaded the .swf to Amazon S3 I started receiving an error and the plugin stopped working.

After some googling I found out how to fix this. Here’s the beginning of my code:

var clip = new ZeroClipboard($(".copy"), {
    moviePath: "http://mysite-assets/js/lib/ZeroClipboard.swf",
    trustedDomains: location.host
});

I had to set the trustedDomains with my site url (not the CDN) to enable the Cross-Domain access.

For more info check out the setting options in the ZeroClipboard documentation.

Setting TortoiseGitMerge in msysgit as the Git mergetool

I use git in command-line using msysgit but I use the TortoiseGit’s merge tool to resolve conflicts. After updating TortoiseGit to version 1.8 the “git mergetool” command stopped working. That’s because they’ve changed the name of the .exe file from TortoiseMerge.exe to TortoiseGitMerge.exe. One simple solution is to create a copy of that file with the previous name. I did that at first, but it was bothering me, as if something wasn’t right. Then I figured it out and here’s how I solved it:

git config --global merge.tool tortoisemerge
git config --global mergetool.tortoisemerge.cmd '"C:/Program Files/TortoiseGit/bin/TortoiseGitMerge.exe" -base:"$BASE" -theirs:"$REMOTE" -mine:"$LOCAL" -merged:"$MERGED"'

How to discover the client IP connected to SQL Server

This query gives you details of who is connected to an instance of SQL Server:

SELECT * FROM sys.dm_exec_connections

In my case, this helped me when I was trying to setup the security access to an Amazon RDS with SQL Server and the IP I was getting, no matter which method I used, did not match the one it was being connected to the database.

GrooveControl for Grooveshark – Chrome Extension

Image

At work is really hard keep focused without any disturbing or distraction. There are always someone calling your attention, and often you need to stop what your doing to solve other problems.

In an effort to help focusing on my task, I am frequently listening music which not only amuses me as it reduces the noises in the environment. Grooveshark is my cloud music player but the thing is that it needs its window to be opened in order to play, and sometimes, you have so many windows and so many tabs, that it takes some time till you find your opened Grooveshark window, so you can pause and pay attention to who is calling you.

So, I created a Chrome Extension called GrooveControl, that displays a small and useful player that helps me to know what’s being played, pause, rewind or forward. That’s like 98% of what I usually do on Grooveshark’s window.

The good news for you, dear developer, is that it’s open-sourced. I’ve saved it in a public repository on GitHub. If you ever were curios about how to create a Chrome Extension, check it out, it’s very simple! And if you want to contribute to it, feel free to do so.