在计划任务中参数化PowerShell参数

我有一堆PowerShell脚本在不同时间通过计划任务启动。

脚本用不同的参数运行多次。 也不熟悉脚本的pipe理员需要能够更改参数而不必编辑代码。

由于这个要求,我将参数通过parameter passing给计划任务中的powershell.exe。 但是这立即变得笨拙,因为现在要改变一个脚本的参数,你必须进入任务调度程序,并编辑参数到powershell.exe,现在看起来像这样(甚至更长):

-command "& 'C:\some\file\path\' -param1 'C:\some\file\path\' -param2 'C:\soawme\fawdile\pawawasth\' -param3 'C:\some\fisdfle\pasdfth\' -param4 'some arg'" 

所以现在我想要做的就是每个脚本只需要一个可编辑的configuration文件,其中的参数可以由pipe理员更改。 我也可以更容易地组织参数 – 具有所有脚本使用的“全局”参数configuration文件,然后使用特定于脚本的configuration文件。

我以为我会在configuration文件中使用JSON ,并正在考虑做这样的事情:

 { "folder1": [ "string", "C:\\sldks\\dsf\\sdf\\sdf\\sd\\fsdf\\" ], "folder2": [ "string", "C:\\jiji\\sfef\\igig\\igg\\" ], "CSSFile": [ "string", "\\\\some\\netqwork\\path\\" ], "DBServer": [ "string", "myserver" ], "DB": [ "string", "DB" ], "SqlQuery": [ "string", "SELECT * FROM myTable" ], "UID": [ "string", "root" ], "PWD": [ "string", "123456" ] } $jsonObject = ConvertFrom-Json (cat $PathToMyExternalJsonFilePassedInFromTaskShedualer) function Set-ParamType ($jsonNode) { switch ($jsonNode[0]) { 'string' {return [string]$jsonNode[1]} 'int' {return [int]$jsonNode[1]} 'switch' {return [switch]$jsonNode[1]} default {"Debug: Unknown type"} } } $folder1 = Set-ParamType($jsonObject.folder1) $folder2 = Set-ParamType($jsonObject.folder2) $CSSFile = Set-ParamType($jsonObject.CSSFile) $DBServer = Set-ParamType($jsonObject.DBServer) $DB = Set-ParamType($jsonObject.DB) $SqlQuery = Set-ParamType($jsonObject.SqlQuery) $UID = Set-ParamType($jsonObject.UID) $PWD = Set-ParamType($jsonObject.PWD) 

这样,在计划的任务中,我只有一个参数传入(configuration文件的path)。 这似乎工作,但我想问是否有一个更好,更完善的方式来实现我的目标。 有没有什么愚蠢的做法,我没有看到?

你在做什么是有道理的; 没有人需要摆弄脚本(这可能会引入代码问题),或与计划的任务(可能要求他们知道“运行”帐户的凭据,也是特别是那些不熟悉的人)。

将configuration文件path作为参数传入也是有道理的; 这样你就可以轻松地重复使用不同configuration的脚本。 所以在任何时候您都不会被限制在一个“参数集”中,但是可以为每个计划任务提供一组参数(configuration文件)。

可能的问题

你的JSON包含数据types; 例如"folder1": ["string","C:\\sldks\\dsf\\sdf\\sdf\\sd\\fsdf\\"] 。 为什么? 无论如何,你将在PS文件中定义types(如果需要的话); 在你的configuration中,你只想保存数据,而不需要你的pipe理员知道“string”的意思是“文本”/而不必考虑它。 即只有"folder1": "C:\\sldks\\dsf\\sdf\\sdf\\sd\\fsdf\\"

还有一些额外的考虑:

  • JSON vs XML vs INI vs Database vs其他。 什么样的文件/技术是您的pipe理员最熟悉/他们发现最容易操作? 就我个人而言,我会用XML来做这件事。 PS是一样舒适,但优点是你的pipe理员可以打开它在浏览器中,并立即看到是否有效的XML(即如果他们错过了结束标签/拼写错误)。 这就是说,这很大程度上取决于你的团队的能力/喜好/工具。

  • validation。 如果有人input错误的数据,或者破坏了文件格式(例如丢失括号),或者破坏了文件(例如保存在ANSI而不是UTF8中),会发生什么? 确保你的脚本有处理这个东西; 还要考虑你怎么知道 即“如果configuration有问题,请不要运行”,如果您要“报告问题,以便我可以在configuration有问题的情况下进行调查和修复”。

  • 字符转义。 在上面的例子中,你必须转义你的文件path: C:\\sldks\\dsf\\sdf\\sdf\\sd\\fsdf\\而不是C:\sldks\dsf\sdf\sdf\sd\fsdf\ 。 pipe理员知道这样做/知道哪些字符转义configuration文件的格式? 如果你有一个编辑这种文件的(通用)工具,可以省却一些麻烦, 否则请参阅上面的validation点。

  • 安全。 包含脚本和configuration文件的文件夹是否得到了适当的保护; 否则人们可以在任务的“运行方式”帐户下操作自己的代码来执行自己喜欢的任务。 如果人员编辑configuration与编辑脚本不同,最好将他们保存在单独的目录中,以限制每个人可以执行的操作。

如果传递参数,大部分这些事情仍然是考虑因素; 所以无论如何考虑,你的方式肯定会有所提升。 但是如果你想要做一些非常友好和强大的事情,考虑到以上几点就会有所帮助。