{"id":8934,"date":"2022-03-01T15:52:12","date_gmt":"2022-03-01T20:52:12","guid":{"rendered":"https:\/\/jdhitsolutions.com\/blog\/?p=8934"},"modified":"2022-03-01T15:52:16","modified_gmt":"2022-03-01T20:52:16","slug":"metric-meta-powershell-scripting","status":"publish","type":"post","link":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/","title":{"rendered":"Metric Meta PowerShell Scripting"},"content":{"rendered":"\n<p>I was fiddling around with PowerShell the other day. I spend my day in front of a PowerShell prompt and am always looking for ways to solve problems or answer questions without taking my hands off the keyboard. For some reason, I started thinking about metric conversions. How many feet are 50 meters? How many meters is 21.5 feet? For this sort of thing, I have a rough idea. But not something like converting grams to ounces. But I can look up a formula and use PowerShell.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">$v = 123.456\n$v\/28.35<\/code><\/pre>\n\n\n\n<p>This snippet will convert the value of grams ($v) to ounces. Seems pretty simple. I can even build a function around it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Function Convert-Gram {\n    [cmdletbinding()]\n    [alias(\"gr2oz\")]\n    [outputType([System.Double])]\n    Param(\n        [Parameter(Position = 0, HelpMessage = \"Specify a gram value.\")]\n        [double]$Value,\n        [Parameter(HelpMessage = \"Round the result to this many decimal places\")]\n        [int]$Round = 2\n    )\n    $from = \"grams\"\n    $to = \"ounces\"\n    Write-Verbose \"Converting $value $from to $to\"\n    [math]::Round($value \/ 28.35, $round)\n{<\/code><\/pre>\n\n\n\n<p>In fact, I took the time to manually create all the functions I would need to convert from one unit to another. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Function Convert-Millimeter {\n    [cmdletbinding()]\n    [alias(\"mm2in\")]\n    [OutputType([System.Double])]\n    Param(\n        [Parameter(Position = 0, HelpMessage = \"Specify a millimeter value.\")]\n        [double]$Value,\n        [Parameter(HelpMessage = \"Round the result to this many decimal places\")]\n        [int]$Round = 2\n    )\n    $from = \"millimeters\"\n    $to = \"inches\"\n    Write-Verbose \"Converting $value $from to $to\"\n    [math]::Round($value\/25.4, $round)\n}<\/code><\/pre>\n\n\n\n<p>When I finished, I realized I had spent a lot of time manually scripting. What I could have done is to let PowerShell write the functions for me!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Meta-Scripting<\/h2>\n\n\n\n<p>I decided to see if I could write PowerShell code to write PowerShell code. To begin, I need some guidelines. First, all I wanted was the function to exist in my PowerShell session. I didn't require a file. I wanted to follow a standard naming convention using the Convert verb. I wanted each command to have a short alias to make it easier to use from the console.<\/p>\n\n\n\n<p>My meta function would need to accept parameters for the <em>from <\/em>unit, e.g. Gram, and the <em>to <\/em>unit, e.g. Ounce. This should generate a function called <strong>Convert-GramToOunce <\/strong>with an alias of <em>gr2oz<\/em>. The new function name is simple enough to construct.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\"> $name = \"global:Convert-$($from)To$($To)\"<\/code><\/pre>\n\n\n\n<p>You'll notice I'm using the global: prefix. This is because, ultimately, I'm going to create the function in the Function: PSDrive.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">New-Item -Path function: -Name $name -Value $value -Force<\/code><\/pre>\n\n\n\n<p>But because of scope, when this runs in the meta function, it doesn't create the function in the global scope that I am expecting. The New-Item cmdlet doesn't have a -Scope parameter like some cmdlets do, i.e., New-PSDrive. Instead, I have to rely on the global: prefix to give PowerShell a hint. <\/p>\n\n\n\n<p>The value of the function will be a scriptblock built from a here-string.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">$value = [scriptblock]::Create($body)<\/code><\/pre>\n\n\n\n<p>The here-string started as a copy of my original function body.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">        $body = @\"\n$help\n[Cmdletbinding()]\n[Alias(\"$alias\")]\n[OutputType([System.Double])]\nParam(\n    [Parameter(Position = 0, Mandatory,ValueFromPipeline,HelpMessage = \"Specify a $($from.tolower()) value.\")]\n    [ValidateNotNullOrEmpty()]\n    $(If ($Validation) {\n        $v = \"[$validation]\"\n        $v\n    })\n    [double]`$Value,\n    [Parameter(HelpMessage = \"Round the result to this many decimal places. Specify a value between 0 and 10.\")]\n    [ValidateRange(0,10)]\n    [int]`$Round = 2,\n    [Parameter(HelpMessage = \"Get a rich object result.\")]\n    [switch]`$Detailed\n    )\n    Process {\n        Write-Verbose \"Converting `$value from $($from.tolower()) to $($to.ToLower()) rounded to `$round decimal places.\"\n        `$r = [math]::Round(($code),`$round)\n        if (`$Detailed) {\n            [PSCustomObject]@{\n                $From = `$Value\n                $To = `$r\n            }\n        }\n        else {\n            `$r\n        }\n    }\n\"@<\/code><\/pre>\n\n\n\n<p>Variables like $code and $from will be expanded from parameter values. But I have to be careful to escape variables like Detailed. I want the final code to use $Detailed from the function. Not replace it with a value from my meta function.<\/p>\n\n\n\n<p>I should point out that even though the function includes an Alias definition, creating the function item doesn't process this directive. I need to manually define the alias in my meta function.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Set-Alias -Name $alias -Value $name -Scope Global<\/code><\/pre>\n\n\n\n<p>Notice the use of the Scope parameter. I build the alias from a hashtable of names.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">$abbreviations = @{\n            gram       = \"gr\"\n            ounce      = \"oz\"\n            meter      = \"m\"\n            feet       = \"ft\"\n            millimeter = \"mm\"\n            inch       = \"in\"\n            mile       = \"mi\"\n            kilometer  = \"km\"\n            kilogram   = \"kg\"\n            pound      = \"lb\"\n            fahrenheit = \"f\"\n            celsius    = \"c\"\n            yard       = \"yd\"\n            liter      = \"l\"\n            quart      = \"qt\"\n            milliliter = \"ml\"\n            kelvin     = \"k\"\n}\n$alias = \"{0}2{1}\" -f $abbreviations[$from], $abbreviations[$to]<\/code><\/pre>\n\n\n\n<p>This is how I create the <em>gr2oz<\/em> alias.<\/p>\n\n\n\n<p>My meta function takes a string for the conversion code. This is the algorithm I was using in my original metric conversion function.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/new-metricfunction-whatif.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1009\" height=\"149\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/new-metricfunction-whatif.png\" alt=\"new-metricfunction whatif\" class=\"wp-image-8935\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/new-metricfunction-whatif.png 1009w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/new-metricfunction-whatif-300x44.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/new-metricfunction-whatif-768x113.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/new-metricfunction-whatif-850x126.png 850w\" sizes=\"auto, (max-width: 1009px) 100vw, 1009px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Adding Help<\/h2>\n\n\n\n<p>I also decided to autogenerate comment-based help. I am dynamically creating functions based on a template. Generating help should be no different. I can create a here-string and drop in parameter values. I wrote a separate function for this task.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Function New-MetricFunctionHelp {\n    [cmdletbinding()]\n    Param (\n        [Parameter(ValueFromPipelineByPropertyName)]\n        [string]$From,\n        [Parameter(ValueFromPipelineByPropertyName)]\n        [string]$To,\n        [string]$Alias,\n        [double]$ExampleValue\n    )\n\n    $cmd = \"Convert-$($From)To$($To)\"\n    #create the example value object\n    $obj = [pscustomobject] @{\n        $From = 1\n        $To = $ExampleValue\n    } | Out-String\n    $h = @\"\n&lt;#\n.Synopsis\nConvert a value from $From to $To.\n.Description\nUse this function to convert values between $from and $to. The default output\nis the converted value. Or you can use -Detailed to get a rich object. See examples.\n.Parameter Value\nSpecify a value for the $($from.tolower()) unit.\n.Parameter Round\nRound the result to this many decimal places. Specify a value between 0 and 10.\n.Parameter Detailed\nGet a rich object result.\n.Example\nPS C:\\> $cmd 1\n$ExampleValue\n\nGet a value result.\n.Example\nPS C:\\> $cmd 1 -detailed\n\n$($obj.trim())\n\nGet an object result.\n.Example\nPS C:\\> $alias 1\n$ExampleValue\n\nUsing the function alias.\n.Link\nConvert-$($To)To$($From)\n.Notes\nThis command has an alias of $alias. This is an auto-generated function.\n.Inputs\nSystem.Double\n.Outputs\nSystem.Double\n#>\n\"@\n    $h\n}<\/code><\/pre>\n\n\n\n<p>This function is called within New-MetricFunction. Because I need an actual value for the sample, I generate one and pass it to the help function.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">$b = [scriptblock]::create(\"param (`$value) [math]::Round($code,2)\")\n$v1 = Invoke-Command $b -ArgumentList 1\n$help = New-MetricFunctionHelp -From $From -to $To -Alias $alias -ExampleValue $v1<\/code><\/pre>\n\n\n\n<p>Re-running my command to create Convert-GramToOunce generates this code.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">&lt;#\n.Synopsis\nConvert a value from Gram to Ounce.\n.Description\nUse this function to convert values between Gram and Ounce. The default output\nis the converted value. Or you can use -Detailed to get a rich object. See examples.\n.Parameter Value\nSpecify a value for the gram unit.\n.Parameter Round\nRound the result to this many decimal places. Specify a value between 0 and 10.\n.Parameter Detailed\nGet a rich object result.\n.Example\nPS C:\\> Convert-GramToOunce 1\n0.04\n\nGet a value result.\n.Example\nPS C:\\> Convert-GramToOunce 1 -detailed\n\n\u001bGram Ounce\u001b\n\u001b---- -----\u001b\n   1  0.04\n\nGet an object result.\n.Example\nPS C:\\> gr2oz 1\n0.04\n\nUsing the function alias.\n.Link\nConvert-OunceToGram\n.Notes\nThis command has an alias of gr2oz. This is an auto-generated function.\n.Inputs\nSystem.Double\n.Outputs\nSystem.Double\n#>\n[Cmdletbinding()]\n[Alias(\"gr2oz\")]\n[OutputType([System.Double])]\nParam(\n    [Parameter(Position = 0, Mandatory,ValueFromPipeline,HelpMessage = \"Specify a gram value.\")]\n    [ValidateNotNullOrEmpty()]\n    \n    [double]$Value,\n    [Parameter(HelpMessage = \"Round the result to this many decimal places. Specify a value between 0 and 10.\")]\n    [ValidateRange(0,10)]\n    [int]$Round = 2,\n    [Parameter(HelpMessage = \"Get a rich object result.\")]\n    [switch]$Detailed\n    )\n    Process {\n        Write-Verbose \"Converting $value from gram to ounce rounded to $round decimal places.\"\n        $r = [math]::Round(($value\/28.35),$round)\n        if ($Detailed) {\n            [PSCustomObject]@{\n                Gram = $Value\n                Ounce = $r\n            }\n        }\n        else {\n            $r\n        }\n    }<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Generating from Data<\/h2>\n\n\n\n<p>Still with me? Here's the complete meta scripting function.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Function New-MetricFunction {\n    [cmdletbinding(SupportsShouldProcess)]\n    Param(\n        [Parameter(Mandatory,ValueFromPipelineByPropertyName)]\n        [string]$From,\n        [Parameter(Mandatory,ValueFromPipelineByPropertyName)]\n        [string]$To,\n        [Parameter(Mandatory,ValueFromPipelineByPropertyName)]\n        [string]$Code,\n        [Parameter(ValueFromPipelineByPropertyName)]\n        [string]$Validation\n    )\n\n    Begin {\n        Write-Verbose \"[$((Get-Date).TimeofDay) BEGIN  ] Starting $($myinvocation.mycommand)\"\n        #hash table of unit abbreviations used to construct aliases\n        $abbreviations = @{\n            gram       = \"gr\"\n            ounce      = \"oz\"\n            meter      = \"m\"\n            feet       = \"ft\"\n            millimeter = \"mm\"\n            inch       = \"in\"\n            mile       = \"mi\"\n            kilometer  = \"km\"\n            kilogram   = \"kg\"\n            pound      = \"lb\"\n            fahrenheit = \"f\"\n            celsius    = \"c\"\n            yard       = \"yd\"\n            liter      = \"l\"\n            quart      = \"qt\"\n            milliliter = \"ml\"\n            kelvin     = \"k\"\n        }\n    } #begin\n    Process {\n        #make sure From and To are in proper case\n        $from = (Get-Culture).TextInfo.ToTitleCase($from.toLower())\n        $to = (Get-Culture).TextInfo.ToTitleCase($to.toLower())\n        #define a function name that will be found in the global scope\n        $name = \"global:Convert-$($from)To$($To)\"\n        Write-Verbose \"[$((Get-Date).TimeofDay) PROCESS] Creating function Convert-$($from)To$($To)\"\n\n        #construct an alias from the data\n        $alias = \"{0}2{1}\" -f $abbreviations[$from], $abbreviations[$to]\n\n        #build comment-based help\n        $b = [scriptblock]::create(\"param (`$value) [math]::Round($code,2)\")\n        $v1 = Invoke-Command $b -ArgumentList 1\n        $help = New-MetricFunctionHelp -From $From -to $To -Alias $alias -ExampleValue $v1\n\n        # this here string will be turned into the function's scriptblock. I need to be careful\n        # to escape $ where I want it to remain a variable in the output.\n        $body = @\"\n$help\n[Cmdletbinding()]\n[Alias(\"$alias\")]\n[OutputType([System.Double])]\nParam(\n    [Parameter(Position = 0, Mandatory,ValueFromPipeline,HelpMessage = \"Specify a $($from.tolower()) value.\")]\n    [ValidateNotNullOrEmpty()]\n    $(If ($Validation) {\n        $v = \"[$validation]\"\n        $v\n    })\n    [double]`$Value,\n    [Parameter(HelpMessage = \"Round the result to this many decimal places. Specify a value between 0 and 10.\")]\n    [ValidateRange(0,10)]\n    [int]`$Round = 2,\n    [Parameter(HelpMessage = \"Get a rich object result.\")]\n    [switch]`$Detailed\n    )\n    Process {\n        Write-Verbose \"Converting `$value from $($from.tolower()) to $($to.ToLower()) rounded to `$round decimal places.\"\n        `$r = [math]::Round(($code),`$round)\n        if (`$Detailed) {\n            [PSCustomObject]@{\n                $From = `$Value\n                $To = `$r\n            }\n        }\n        else {\n            `$r\n        }\n    }\n\"@\n        $value = [scriptblock]::Create($body)\n\n        if ($PSCmdlet.ShouldProcess($name)) {\n            New-Item -Path function: -Name $name -Value $value -Force\n        }\n        if ($PSCmdlet.ShouldProcess($name, \"Create alias $alias\")) {\n            #need to manually create the alias even though it is defined in the function\n            Set-Alias -Name $alias -Value $name -Scope Global\n        }\n    } #process\n    End {\n        Write-Verbose \"[$((Get-Date).TimeofDay) END    ] Ending $($myinvocation.mycommand)\"\n    } #end\n}<\/code><\/pre>\n\n\n\n<p>The function also allows me to specify a parameter validation string for the value. Also, note that I configured parameters to accept pipeline input by property name.<\/p>\n\n\n\n<p>I can use an external data source such as a CSV file to generate all of the functions. In the script file with the previously defined functions, I'm defining the CSV data like this.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">#use single quote for the here-string so that $value doesn't get\n#treated as a variable upon conversion\n$data = @'\nFrom,To,Code,Validation\nGram,Ounce,$value\/28.35,ValidateScript({$_ -gt 0})\nOunce,Gram,$value*28.35,ValidateScript({$_ -gt 0})\nMillimeter,Inch,$value\/25.4,ValidateScript({$_ -gt 0})\nInch,Millimeter,$value*25.4,ValidateScript({$_ -gt 0})\nMeter,Feet,$value*3.281,ValidateScript({$_ -gt 0})\nFeet,Meter,$value\/3.281,ValidateScript({$_ -gt 0})\nKilometer,Mile,$value\/1.609,ValidateScript({$_ -gt 0})\nMile,Kilometer,$value*1.609,ValidateScript({$_ -gt 0})\nKilogram,Pound,$value*2.205,ValidateScript({$_ -gt 0})\nPound,Kilogram,$value\/2.205,ValidateScript({$_ -gt 0})\nYard,Meter,$value\/1.094,ValidateScript({$_ -gt 0})\nMeter,Yard,$value*1.094,ValidateScript({$_ -gt 0})\nLiter,Quart,$value*1.057,ValidateScript({$_ -gt 0})\nQuart,Liter,$value\/1.057,ValidateScript({$_ -gt 0})\nMilliliter,Ounce,$value\/29.574,ValidateScript({$_ -gt 0})\nOunce,Milliliter,$value*29.574,ValidateScript({$_ -gt 0})\nCelsius,Fahrenheit,($value*(9\/5)) + 32\nFahrenheit,Celsius,($value - 32)*(5\/9)\nKelvin,Fahrenheit,($value-273.15)*(9\/5)+32\nFahrenheit,Kelvin,($value-32)*(5\/9)+273.15\nKelvin,Celsius,($value - 273.15)\nCelsius,Kelvin,($value + 273.15)\n'@<\/code><\/pre>\n\n\n\n<p>Importing this data and passing it to the meta scripting functions is a one-line command.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">$new = $data | ConvertFrom-Csv | New-MetricFunction<\/code><\/pre>\n\n\n\n<p>Finally, to make it easier for me to remember all of the new commands, I'll create a \"cheat sheet.\"<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">$metric = $new | Select-Object -Property Name, @{Name = \"Alias\"; Expression = { Get-Alias -Definition \"global:$($_.name)\" } }\n$metric<\/code><\/pre>\n\n\n\n<p>Assuming I dot-source the PowerShell script file, I'll have a reference variable.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/metric-cheatsheet.png\"><img loading=\"lazy\" decoding=\"async\" width=\"428\" height=\"586\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/metric-cheatsheet.png\" alt=\"metric cheat sheet\" class=\"wp-image-8936\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/metric-cheatsheet.png 428w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/metric-cheatsheet-219x300.png 219w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/metric-cheatsheet-300x411.png 300w\" sizes=\"auto, (max-width: 428px) 100vw, 428px\" \/><\/a><\/figure>\n\n\n\n<p>With one command, I created all of these functions and loaded them into my PowerShell session.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/metrichelp.png\"><img loading=\"lazy\" decoding=\"async\" width=\"959\" height=\"532\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/metrichelp.png\" alt=\"generated help\n\" class=\"wp-image-8937\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/metrichelp.png 959w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/metrichelp-300x166.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/metrichelp-768x426.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/metrichelp-850x472.png 850w\" sizes=\"auto, (max-width: 959px) 100vw, 959px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/l2qt.png\"><img loading=\"lazy\" decoding=\"async\" width=\"767\" height=\"233\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/l2qt.png\" alt=\"convert liter to quart\" class=\"wp-image-8938\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/l2qt.png 767w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/l2qt-300x91.png 300w\" sizes=\"auto, (max-width: 767px) 100vw, 767px\" \/><\/a><\/figure>\n\n\n\n<p>If I decide to change something, like the verbose message, I can modify New-MetricFunction and regenerate the functions. I don't have to make changes in 22 different files.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>While I value the results and will use these metric conversion functions, my real purpose is to share the meta scripting content and techniques. I don't have another project in mind to use this, but I'll be better prepared when I do. If you find a way to use these techniques, I hope you'll share.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was fiddling around with PowerShell the other day. I spend my day in front of a PowerShell prompt and am always looking for ways to solve problems or answer questions without taking my hands off the keyboard. For some reason, I started thinking about metric conversions. How many feet are 50 meters? How many&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"New on the blog: #PowerShell Meta-Scripting","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[4,8],"tags":[224,534,540],"class_list":["post-8934","post","type-post","status-publish","format-standard","hentry","category-powershell","category-scripting","tag-function","tag-powershell","tag-scripting"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Metric Meta PowerShell Scripting &#8226; The Lonely Administrator<\/title>\n<meta name=\"description\" content=\"Why write PowerShell code when you can have PowerShell write your code for you. Here is a proof-of-concept of PowerShell meta-scripting.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Metric Meta PowerShell Scripting &#8226; The Lonely Administrator\" \/>\n<meta property=\"og:description\" content=\"Why write PowerShell code when you can have PowerShell write your code for you. Here is a proof-of-concept of PowerShell meta-scripting.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/\" \/>\n<meta property=\"og:site_name\" content=\"The Lonely Administrator\" \/>\n<meta property=\"article:published_time\" content=\"2022-03-01T20:52:12+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-03-01T20:52:16+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/new-metricfunction-whatif.png\" \/>\n<meta name=\"author\" content=\"Jeffery Hicks\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@JeffHicks\" \/>\n<meta name=\"twitter:site\" content=\"@JeffHicks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeffery Hicks\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8934\\\/metric-meta-powershell-scripting\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8934\\\/metric-meta-powershell-scripting\\\/\"},\"author\":{\"name\":\"Jeffery Hicks\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"headline\":\"Metric Meta PowerShell Scripting\",\"datePublished\":\"2022-03-01T20:52:12+00:00\",\"dateModified\":\"2022-03-01T20:52:16+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8934\\\/metric-meta-powershell-scripting\\\/\"},\"wordCount\":804,\"commentCount\":2,\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"image\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8934\\\/metric-meta-powershell-scripting\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/03\\\/new-metricfunction-whatif.png\",\"keywords\":[\"Function\",\"PowerShell\",\"Scripting\"],\"articleSection\":[\"PowerShell\",\"Scripting\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8934\\\/metric-meta-powershell-scripting\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8934\\\/metric-meta-powershell-scripting\\\/\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8934\\\/metric-meta-powershell-scripting\\\/\",\"name\":\"Metric Meta PowerShell Scripting &#8226; The Lonely Administrator\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8934\\\/metric-meta-powershell-scripting\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8934\\\/metric-meta-powershell-scripting\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/03\\\/new-metricfunction-whatif.png\",\"datePublished\":\"2022-03-01T20:52:12+00:00\",\"dateModified\":\"2022-03-01T20:52:16+00:00\",\"description\":\"Why write PowerShell code when you can have PowerShell write your code for you. Here is a proof-of-concept of PowerShell meta-scripting.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8934\\\/metric-meta-powershell-scripting\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8934\\\/metric-meta-powershell-scripting\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8934\\\/metric-meta-powershell-scripting\\\/#primaryimage\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/03\\\/new-metricfunction-whatif.png\",\"contentUrl\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/03\\\/new-metricfunction-whatif.png\",\"width\":1009,\"height\":149},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8934\\\/metric-meta-powershell-scripting\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"PowerShell\",\"item\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/category\\\/powershell\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Metric Meta PowerShell Scripting\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/\",\"name\":\"The Lonely Administrator\",\"description\":\"Practical Advice for the Automating IT Pro\",\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\",\"name\":\"Jeffery Hicks\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"caption\":\"Jeffery Hicks\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Metric Meta PowerShell Scripting &#8226; The Lonely Administrator","description":"Why write PowerShell code when you can have PowerShell write your code for you. Here is a proof-of-concept of PowerShell meta-scripting.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/","og_locale":"en_US","og_type":"article","og_title":"Metric Meta PowerShell Scripting &#8226; The Lonely Administrator","og_description":"Why write PowerShell code when you can have PowerShell write your code for you. Here is a proof-of-concept of PowerShell meta-scripting.","og_url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/","og_site_name":"The Lonely Administrator","article_published_time":"2022-03-01T20:52:12+00:00","article_modified_time":"2022-03-01T20:52:16+00:00","og_image":[{"url":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/new-metricfunction-whatif.png","type":"","width":"","height":""}],"author":"Jeffery Hicks","twitter_card":"summary_large_image","twitter_creator":"@JeffHicks","twitter_site":"@JeffHicks","twitter_misc":{"Written by":"Jeffery Hicks","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/#article","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/"},"author":{"name":"Jeffery Hicks","@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"headline":"Metric Meta PowerShell Scripting","datePublished":"2022-03-01T20:52:12+00:00","dateModified":"2022-03-01T20:52:16+00:00","mainEntityOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/"},"wordCount":804,"commentCount":2,"publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"image":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/#primaryimage"},"thumbnailUrl":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/new-metricfunction-whatif.png","keywords":["Function","PowerShell","Scripting"],"articleSection":["PowerShell","Scripting"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/","url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/","name":"Metric Meta PowerShell Scripting &#8226; The Lonely Administrator","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/#primaryimage"},"image":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/#primaryimage"},"thumbnailUrl":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/new-metricfunction-whatif.png","datePublished":"2022-03-01T20:52:12+00:00","dateModified":"2022-03-01T20:52:16+00:00","description":"Why write PowerShell code when you can have PowerShell write your code for you. Here is a proof-of-concept of PowerShell meta-scripting.","breadcrumb":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/#primaryimage","url":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/new-metricfunction-whatif.png","contentUrl":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2022\/03\/new-metricfunction-whatif.png","width":1009,"height":149},{"@type":"BreadcrumbList","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8934\/metric-meta-powershell-scripting\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"PowerShell","item":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},{"@type":"ListItem","position":2,"name":"Metric Meta PowerShell Scripting"}]},{"@type":"WebSite","@id":"https:\/\/jdhitsolutions.com\/blog\/#website","url":"https:\/\/jdhitsolutions.com\/blog\/","name":"The Lonely Administrator","description":"Practical Advice for the Automating IT Pro","publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/jdhitsolutions.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9","name":"Jeffery Hicks","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","url":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","caption":"Jeffery Hicks"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg"}}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":1330,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell-v2-0\/1330\/powershell-ise-convert-all-aliases\/","url_meta":{"origin":8934,"position":0},"title":"PowerShell ISE Convert All Aliases","author":"Jeffery Hicks","date":"April 8, 2011","format":false,"excerpt":"Yesterday I posted an article on how to convert a selected word to an alias or cmdlet. While I think there is still some value in this piecemeal approach. sometimes you want to make wholesale changes, such as when troubleshooting a script that someone else wrote that is full of\u2026","rel":"","context":"In &quot;PowerShell v2.0&quot;","block_context":{"text":"PowerShell v2.0","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell-v2-0\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":6855,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell-7\/6855\/powershell-scripting-for-linux-is-still-about-the-objects\/","url_meta":{"origin":8934,"position":1},"title":"PowerShell Scripting for Linux is Still About the Objects","author":"Jeffery Hicks","date":"October 8, 2019","format":false,"excerpt":"I've been trying to increase my Linux skills, especially as I begin to write PowerShell scripts and tools that can work cross-platform. One very important concept I want to make sure you don't overlook is that even when scripting for non-Windows platforms, you must still be thinking about objects. The\u2026","rel":"","context":"In &quot;PowerShell 7&quot;","block_context":{"text":"PowerShell 7","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell-7\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1340,"url":"https:\/\/jdhitsolutions.com\/blog\/scripting\/1340\/convert-aliases-with-the-tokenizer\/","url_meta":{"origin":8934,"position":2},"title":"Convert Aliases with the Tokenizer","author":"Jeffery Hicks","date":"April 12, 2011","format":false,"excerpt":"Last week I posted a function you can use in the Windows PowerShell ISE to convert aliases to command definitions. My script relied on regular expressions to seek out and replace aliases. A number of people asked me why I didn't use the PowerShell tokenizer. My answer was that because\u2026","rel":"","context":"In &quot;PowerShell ISE&quot;","block_context":{"text":"PowerShell ISE","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell-ise\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4985,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/4985\/converting-text-to-html-revised\/","url_meta":{"origin":8934,"position":3},"title":"Converting Text to HTML Revised","author":"Jeffery Hicks","date":"May 9, 2016","format":false,"excerpt":"A few years ago I published a PowerShell function to convert text files into HTML listings. I thought it would be handy to convert scripts to HTML documents with line numbering and some formatting. Turns out someone actually used it! He had some questions about the function which led me\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"convertto-htmllisting2","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2016\/05\/convertto-htmllisting2_thumb.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2016\/05\/convertto-htmllisting2_thumb.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2016\/05\/convertto-htmllisting2_thumb.png?resize=525%2C300 1.5x"},"classes":[]},{"id":2318,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/2318\/introducing-the-scriptinghelp-powershell-module\/","url_meta":{"origin":8934,"position":4},"title":"Introducing the ScriptingHelp PowerShell Module","author":"Jeffery Hicks","date":"May 16, 2012","format":false,"excerpt":"Over the last few weeks I've posted articles on the different parameter validation options in Windows PowerShell. More than one person suggested consolidating the articles. That seemed like a good idea. There were a variety of ways to handle this but I wanted something more PowerShell-oriented. Then I realized, why\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2011\/03\/helpbubble.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1055,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1055\/more-wmi-dates-win32product-installdate\/","url_meta":{"origin":8934,"position":5},"title":"More WMI Dates \u2013 Win32Product InstallDate","author":"Jeffery Hicks","date":"January 11, 2011","format":false,"excerpt":"I've written in the past about converting obtuse WMI datetime formats into more user friendly formats. The other day via Twitter I got a question about the InstallDate property that comes from the Win32_Product class. This property has a different format, than what I've written about previously. And while I\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/8934","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/comments?post=8934"}],"version-history":[{"count":0,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/8934\/revisions"}],"wp:attachment":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/media?parent=8934"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/categories?post=8934"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/tags?post=8934"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}