{"id":54053,"date":"2009-04-02T23:10:00","date_gmt":"2009-04-02T23:10:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/04\/02\/hey-scripting-guy-how-can-i-run-a-script-when-my-computer-is-idle\/"},"modified":"2009-04-02T23:10:00","modified_gmt":"2009-04-02T23:10:00","slug":"hey-scripting-guy-how-can-i-run-a-script-when-my-computer-is-idle","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-run-a-script-when-my-computer-is-idle\/","title":{"rendered":"Hey, Scripting Guy! How Can I Run a Script When My Computer Is Idle?"},"content":{"rendered":"<p><H2><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> <\/H2>\n<P>Hey, Scripting Guy! I need to be able to run a script when my computer is idle. But only when it is idle. I have looked in WMI and everywhere else and cannot find anything that will detect when the computer is idle. Can you tell me how to do it?<BR><BR>&#8211; NM<\/P><IMG height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> \n<P>Hi NM,<\/P>\n<P>You know, our computers are busy plotting against us every minute of the day. Of this we are sure. However, if our computers decide they do not have anything better to do, they might condescend to perform tasks for us. That is right; we can create a scheduled task to run when the computer is idle. This is, like, soooo cool!<\/P>\n<TABLE class=\"dataTable\" id=\"EXC\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\">This week we are talking about scheduled tasks. There are at least three different ways that you can work with scheduled tasks. <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/sept04\/hey0922.mspx\" target=\"_blank\">This \u201cHey, Scripting Guy!\u201d article<\/A> provides an example of working with scheduled tasks via WMI. <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/msh\/os\/tasks\/ostkms04.mspx\" target=\"_blank\">This script<\/A> lists scheduled tasks created via WMI. We also have <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/csc\/scripts\/os\/tasks\/index.mspx\" target=\"_blank\">a variety of scheduled task scripts<\/A> from the Community-Submitted Scripts Center. The <B>Schedule.Service<\/B> API is discussed in two articles. The <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/vista\/tasks1.mspx\" target=\"_blank\">first article<\/A> talks about creating a task and setting the trigger. The <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/vista\/tasks2.mspx\" target=\"_blank\">second article<\/A> discusses organizing tasks. <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/aug07\/hey0830.mspx\" target=\"_blank\">This article<\/A> discusses executing scheduled tasks via the <B>Schedule.Service<\/B> API. And the Task Scheduler is documented <A href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa383614.aspx\" target=\"_blank\">on MSDN<\/A>.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>NM, I could not just create a single script that runs when the computer is idle and leave it at that. That would be lame. Instead, I decided to borrow some functions from <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/apr09\/hey0401.mspx\">yesterday&#8217;s script<\/A> and give you the ability to list scheduled tasks, delete scheduled tasks, and create scheduled tasks that run when the computer is idle. I did give it the name <B>CreateScheduledTasks.ps1<\/B>, but you can rename it to whatever you wish. Maybe something like List_Delete_Create_ScheduledTasks.ps1 would be more accurate, but I did not want to do all that&nbsp;typing. <\/P><PRE class=\"codeSample\">Function Get-ScheduleService\n{\n  New-Object -ComObject schedule.service\n} #end Get-ScheduleService\nFunction Get-Tasks($folder)\n{ #returns a task object\n $folder.GetTasks(1)\n} #end Get-Tasks<\/p>\n<p>Function Get-Task($folder,$name)\n{ #returns a task object\n $folder.GetTask($name)\n} #end Get-Tasks<\/p>\n<p>Function New-TaskObject($path)\n{ #returns a taskfolder object\n $taskObject = Get-ScheduleService\n $taskObject.Connect()\n if(-not $path) { $path = &#8220;\\&#8221; }\n $taskObject.GetFolder($path)\n} #end New-TaskObject<\/p>\n<p>Function New-Task($path,$Name,$description,$author,$command,$user,$password,$sddl)\n{ \n  New-Variable -Name TASK_TRIGGER_IDLE -Value 6 -Option constant\n  New-Variable -Name TASK_ACTION_EXEC -Value 0 -Option constant\n  New-Variable -Name CREATE_OR_UPDATE -Value 6 -Option constant\n  New-Variable -Name TASK_LOGON_NONE -Value 0 -Option constant\n  $user=$password=$sddl=$null\n  $taskObject = Get-ScheduleService\n  $taskObject.Connect()\n  if(-not $path) { $path = &#8220;\\&#8221; }\n  $rootFolder = $taskObject.GetFolder($path)\n  $taskdefinition = $taskObject.NewTask($null)\n  $regInfo = $taskdefinition.RegistrationInfo\n  if(-not $description) { $description = &#8220;Created by script&#8221; }\n  $regInfo.Description = $description\n  if(-not $author) { $author = $env:username }\n  $regInfo.Author = $author\n  $settings = $taskdefinition.Settings\n  $settings.StartWhenAvailable = $true\n  $settings.Hidden = $false\n  $triggers = $taskdefinition.Triggers\n  $trigger = $triggers.Create($TASK_TRIGGER_IDLE)\n  $action = $taskdefinition.Actions.Create($TASK_ACTION_EXEC)\n  $action.Path = $command\n  $rootFolder.RegisterTaskDefinition($Name,$taskdefinition,$CREATE_OR_UPDATE,\n                                     $user,$password,$TASK_LOGON_NONE,$sddl)<\/p>\n<p>} #end New-Task<\/p>\n<p>Function Remove-Task($folder,$name)\n{\n $folder.DeleteTask($name,$null)\n} #end Remove-Task<\/p>\n<p># *** entry point to script ***<\/p>\n<p># Get-Tasks -folder (New-taskObject -path &#8220;\\microsoft\\windows\\defrag&#8221;)\n# Returns a collection of task objects representing each task in the defrag folder<\/p>\n<p># Get-Task -folder (New-taskObject -path &#8220;\\&#8221;) -name &#8220;Test idle trigger&#8221;\n# returns a task object representing the Test idle trigger task in the root folder  <\/p>\n<p># New-Task -command &#8220;C:\\Windows\\System32\\notepad.exe&#8221; -name &#8220;test idle trigger&#8221;\n# Creates task to run notepad. task is stored in root and named test idle trigger<\/p>\n<p># New-Task -command &#8220;C:\\Windows\\System32\\notepad.exe&#8221; -path &#8220;\\hsg&#8221; `\n#  -name &#8220;test idle trigger&#8221;<\/p>\n<p># Creates task to run notepad. task is named test idle trigger and \n# is stored in root\\hsg folder.<\/p>\n<p># Remove-Task -folder (New-taskObject) -name &#8220;test idle trigger&#8221;\n# Deletes a scheduled task named &#8220;test idle trigger&#8221; from the root folder<\/p>\n<p># Remove-Task -folder (New-taskObject -path &#8220;\\hsg&#8221;) -name &#8220;test idle trigger&#8221;\n# Deletes a scheduled task named &#8220;test idle trigger&#8221; from the root\\hsg folder\n<\/PRE>\n<P>The first thing that we need to do is to create the function that will create an instance of the <B>schedule.service<\/B> object. The <B>Get\u2013ScheduleService<\/B> function is the same function that we used in <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/apr09\/hey0401.mspx\">yesterday&#8217;s script<\/A> and therefore will not be discussed here. The code is seen here:<\/P><PRE class=\"codeSample\">Function Get-ScheduleService\n{\n  New-Object -ComObject schedule.service\n} #end Get-ScheduleService\n<\/PRE>\n<P>We also need to create the <B>Get\u2013Tasks<\/B> function, which will return a <B>task<\/B> object. This is the same function that we used yesterday and therefore will not be discussed. This code is seen here:<\/P><PRE class=\"codeSample\">Function Get-Tasks($folder)\n{ #returns task object\n$folder.GetTasks(1)\n} #end Get-Tasks\n<\/PRE>\n<P>The <B>Get-Task<\/B> function is seen here and is the same function that we used&nbsp;yesterday:<\/P><PRE class=\"codeSample\">Function Get-Task($folder,$name)\n{ #returns a task object\n $folder.GetTask($name)\n} #end Get-Tasks\n<\/PRE>\n<P>We also need to use the <B>New-TaskObject<\/B> function to create a <B>folder<\/B> object for us to use. This is the same function we used just yesterday:<\/P><PRE class=\"codeSample\">Function New-TaskObject($path)\n{ #returns a taskfolder object\n$taskObject = Get-ScheduleService\n$taskObject.Connect()\nif(-not $path) { $path = &#8220;\\&#8221; }\n$taskObject.GetFolder($path)\n} #end New-TaskObject\n<\/PRE>\n<P>Now we come to the <B>New-Task<\/B> function. This is a new function and we will need to spend some time examining it. Following the <B>Function<\/B> keyword and the name, we define eight input parameters. Because of the way that the script is written, not all eight of these input parameters are required to be supplied when the script is run. This code is shown&nbsp;here:<\/P><PRE class=\"codeSample\">Function New-Task($path,$Name,$description,$author,$command,$user,$password,$sddl)\n{\n<\/PRE>\n<P>We create a few constants. To create a new constant, we use the <B>New-Variable<\/B> cmdlet while supplying a value and a name for the variable. The thing that makes the difference between a variable and a constant is the fact that a constant can neither be changed nor deleted. We did not need to use a constant here; we could in fact simply use a variable and assign a value to it. If we did not assign a new value to the variable, it would in effect be constant. The constant names are the same names that are defined in the Windows Software Development Kit (SDK). We did not need to use these names, but it will make the script easier to read and easier to maintain, particularly when we need to return to the SDK in order to identify additional options for the script. As a matter of fact, we do not even need to use a variable to hold the value. We could simply use literal values directly in the method call. The price for this efficiency is readability. The constants are shown&nbsp;here:<\/P><PRE class=\"codeSample\">New-Variable -Name TASK_TRIGGER_IDLE -Value 6 -Option constant\n  New-Variable -Name TASK_ACTION_EXEC -Value 0 -Option constant\n  New-Variable -Name CREATE_OR_UPDATE -Value 6 -Option constant\n  New-Variable -Name TASK_LOGON_NONE -Value 0 -Option constant\n<\/PRE>\n<P>Because we do not wish to always be required to supply a user name and a password when running the script to create a new scheduled task, we assign the variables <B>$user<\/B>, <B>$password<\/B>, and <B>$sddl<\/B> to be equal to null. This is shown here:<\/P><PRE class=\"codeSample\">$user=$password=$sddl=$null<\/PRE>\n<P>It is time to obtain the <B>TaskService<\/B> object. To do this we call the <B>Get\u2013ScheduleService<\/B> function and assign the resulting object to the <B>$taskObject<\/B> variable. We then call the <B>Connect<\/B>&nbsp;method:<\/P><PRE class=\"codeSample\">$taskObject = Get-ScheduleService\n  $taskObject.Connect()\n<\/PRE>\n<P>Now we need to connect to the <B>TaskFolder<\/B> object. The first thing that we need to do is to verify that a value was supplied for the <B>$path<\/B> variable. If it was not, we connect to the root. We use the <B>GetFolder<\/B> method from the <B>TaskService<\/B> object and assign the resulting <B>TaskFolder<\/B> object to the <B>$rootFolder<\/B> variable. This is seen&nbsp;here:<\/P><PRE class=\"codeSample\">if(-not $path) { $path = &#8220;\\&#8221; }\n  $rootFolder = $taskObject.GetFolder($path)\n<\/PRE>\n<P>Next we call the <B>NewTask<\/B> method from the <B>TaskService<\/B> object and assign the <B>NewTask<\/B> object to the <B>$taskdefinition<\/B> variable. The reason we supply the <B>$null<\/B> value to the method call is because the flag that would normally be placed here is not defined in the API. We next need to obtain registration information and assign it to the <B>$regInfo<\/B> variable. This is shown here:<\/P><PRE class=\"codeSample\">$taskdefinition = $taskObject.NewTask($null)\n  $regInfo = $taskdefinition.RegistrationInfo\n<\/PRE>\n<P>I hate it when I am required to type in a description for the task if it is not something that I intend to keep around for a very long time. If a description is not supplied when the function is called, a default value of \u201cCreated by script\u201d is assigned to the <B>$description<\/B> variable. The value contained inside the <B>$description<\/B> variable is then assigned to the <B>description<\/B> property as shown&nbsp;here:<\/P><PRE class=\"codeSample\">if(-not $description) { $description = &#8220;Created by script&#8221; }\n  $regInfo.Description = $description\n<\/PRE>\n<P>The same goes for the author, so if a value for <B>$author<\/B> is not assigned when the function is called, we read the <B>username<\/B> value from the system environment and assign the value to the <B>author<\/B>&nbsp;:<\/P><PRE class=\"codeSample\">if(-not $author) { $author = $env:username }\n  $regInfo.Author = $author\n<\/PRE>\n<P>Now we get to the <B>TaskSettings<\/B> object. The <B>TestSettings<\/B> object allows us to configure the items seen here:<\/P><IMG height=\"372\" alt=\"Image of the items configurable by the TestSettings object\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/april\/hey0402\/hsg-04-02-09-1.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>To do this, we need to first retrieve the <B>TestSettings<\/B> object by querying the <B>settings<\/B> property from the <B>TaskDefinition<\/B> object and storing the results in the <B>$settings<\/B> variable. In our script we select two properties from the <B>TaskDefinition<\/B> object to work with. The first property, <B>StartWhenAvailable<\/B>, allows the scheduled task to begin after it becomes available. The second property, <B>Hidden<\/B>, allows the task to be visible. This is seen here:<\/P><PRE class=\"codeSample\">$settings = $taskdefinition.Settings\n  $settings.StartWhenAvailable = $true\n  $settings.Hidden = $false\n<\/PRE>\n<P>We need to create a <B>Trigger<\/B> object. The <B>Trigger<\/B> object is obtained by querying the <B>triggers<\/B> property from the <B>TaskDefinition<\/B> object. We store the returned object in the <B>$triggers<\/B> variable. Now we need to decide what kind of trigger we&#8217;re going to use. This is where we can really begin to see some of the power of the Task Scheduler 2.0 API. In this example, we want the scheduled task to run only when the computer is not doing anything. To do this we will create an idle trigger. The <B>$TASK_TRIGGER_IDLE<\/B> constant is used to define the kind of trigger that we will use. We store the idle trigger in the <B>$trigger<\/B> variable. This is seen here:<\/P><PRE class=\"codeSample\">$triggers = $taskdefinition.Triggers\n  $trigger = $triggers.Create($TASK_TRIGGER_IDLE)\n<\/PRE>\n<P>Now we need an <B>action<\/B> object. The <B>action<\/B> object is used to define the action that the scheduled task will take when the trigger fires. We use the <B>actions<\/B> property from the <B>$taskdefinition<\/B> object and call the <B>create<\/B> method to create the <B>action<\/B> object. The <B>create<\/B> method is given the <B>$TASK_ACTION_EXEC<\/B> constant to tell it what kind of action is to be created. We store the returned action object in the <B>$action<\/B> variable. We then use the <B>path<\/B> property of the <B>action<\/B> object and give it the path to the command that will be executed. This is stored in the <B>$command<\/B> variable. This code is seen here:<\/P><PRE class=\"codeSample\">$action = $taskdefinition.Actions.Create($TASK_ACTION_EXEC)\n  $action.Path = $command\n<\/PRE>\n<P>It is time to actually register the scheduled task. This part is actually a little surprising; we use the <B>folder<\/B> object to give us access to the <B>RegisterTaskDefinition<\/B> method. This method has seven parameters. Each of the parameters for the method is supplied values via the variables and constants that we defined earlier. This makes it easy for us to understand what the task is supposed to do:<\/P><PRE class=\"codeSample\">$rootFolder.RegisterTaskDefinition($Name,$taskdefinition,$CREATE_OR_UPDATE,\n                                     $user,$password,$TASK_LOGON_NONE,$sddl)\n} #end New-Task\n<\/PRE>\n<P>We may want to delete a previously scheduled task. To do this we use the <B>DeleteTask<\/B> method from the <B>folder<\/B> object. We create a <B>Remove-Task<\/B> function to allow us to easily call this method. This is shown&nbsp;here:<\/P><PRE class=\"codeSample\">Function Remove-Task($folder,$name)\n{\n$folder.DeleteTask($name,$null)\n} #end Remove-Task\n<\/PRE>\n<P>The entry point to the script is the section of the script that allows us to call the functions contained within the script. There are a number of things that we could do such as returning a collection of task objects that list each of the tasks within a specific folder. If we were to do this, the syntax might look something like this:<\/P><PRE class=\"codeSample\">Get-Tasks -folder (New-taskObject -path &#8220;\\microsoft\\windows\\defrag&#8221;)<\/PRE>\n<P>We may decide that we would like to look at a specific task. To do this we would call the <B>Get-Task<\/B> function, pass it the <B>folder<\/B> object that we obtain via the <B>New-TaskObject<\/B> function. We would need of course to specify the name of the task as seen here:<\/P><PRE class=\"codeSample\">Get-Task -folder (New-TaskObject -path &#8220;\\&#8221;) -name &#8220;Test idle trigger&#8221;<\/PRE>\n<P>If we want to create a new task, the only things which must be supplied are the command to execute and the name of the task. We could even create a function that would generate a random name for the task and allow us to skip the problem of making up names for one-off scheduled tasks, but we have not done so in this particular script. You could use the technique seen in <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/oct08\/hey1016.mspx\" target=\"_blank\">this \u201cHey, Scripting Guy!\u201d article<\/A> to give you some ideas for creating random task names. The code to create the new task is shown&nbsp;here:<\/P><PRE class=\"codeSample\">New-Task -command &#8220;C:\\Windows\\System32\\notepad.exe&#8221; -path &#8220;\\hsg&#8221; `\n  -name &#8220;test idle trigger&#8221;\n<\/PRE>\n<P>If you read the article yesterday and learned how to create your own folders, you probably want to create your scheduled tasks inside a new folder. To do so you use the <B>New-Task<\/B> function, and specify the command, the name, and the path parameters as seen here:<\/P><PRE class=\"codeSample\">New-Task -command &#8220;C:\\Windows\\System32\\notepad.exe&#8221; -path &#8220;\\hsg&#8221; `  -name &#8220;test idle trigger&#8221;<\/PRE>\n<P>If you need to delete a task, we specify a <B>folder<\/B> object that contains the task as well as the name of the task that is to be removed. We need to use the <B>New-TaskObject<\/B> function because the method will not accept a string as a path to the folder. It requires an actual folder object. Keep in mind that we must supply a folder object even if the task is stored in the root of the <B>scheduled tasks<\/B> folder. This code is seen here:<\/P><PRE class=\"codeSample\">Remove-Task -folder (New-TaskObject) -name &#8220;test idle trigger&#8221;<\/PRE>\n<P>If the task that you wish to remove is stored in a different folder, we use the <B>New-Task<\/B> object function and specify the <B>path<\/B> parameter to that function. We place this inside a set of parentheses and then supply that to the <B>folder<\/B> parameter of the <B>Remove-Task<\/B> function. We then specify the name of the task as we did earlier. This is shown here:<\/P><PRE class=\"codeSample\">Remove-Task -folder (New-taskObject -path &#8220;\\hsg&#8221;) -name &#8220;test idle trigger&#8221;<\/PRE>\n<P>This concludes our article detailing the process for creating scheduled tasks and deleting scheduled tasks. It also brings to a conclusion our Scheduled Tasks Week. We hope that you have enjoyed this series of articles and are somewhat intrigued by the new and exciting possibilities offered by the Scheduled Task 2.0 API. Join us tomorrow for Quick-Hits Friday. Until then, peace. <\/P>\n<P>&nbsp;<\/P>\n<P><B>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/B><\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I need to be able to run a script when my computer is idle. But only when it is idle. I have looked in WMI and everywhere else and cannot find anything that will detect when the computer is idle. Can you tell me how to do it?&#8211; NM Hi NM, You [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[31,32,3,45],"class_list":["post-54053","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-operating-system","tag-scheduled-tasks","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I need to be able to run a script when my computer is idle. But only when it is idle. I have looked in WMI and everywhere else and cannot find anything that will detect when the computer is idle. Can you tell me how to do it?&#8211; NM Hi NM, You [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54053","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=54053"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54053\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=54053"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=54053"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=54053"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}