不要在命令提示符下使用 icacls,而是使用 Powershell 脚本,因为 Powershell 允许您在 IIS 中枚举网站并获取物理文件夹路径。
不幸的是,您不能将 Powershell 脚本设置为启动任务。所以你必须创建一个常规的 CMD 或 BAT 文件,然后在这个文件中让 Powershell 执行你的脚本。
CMD 文件:
PowerShell -ExecutionPolicy Unrestricted .\Setup.ps1 >> %TEMP%\Setup-DebugLog.txt 2>&1
exit /B 0
第一行执行 Powershell 脚本并将所有输出保存到文件 Setup-DebugLog.txt。第二行确保 CMD 文件向 Windows Azure 返回一个 OK,因此 Azure 知道启动脚本中的一切正常。
这是我用来在 App_Data 文件夹上设置文件夹权限的 Powershell 脚本:
Import-Module WebAdministration
cd IIS:\Sites
$dir = Get-ChildItem
$timeout = 0
while ($dir -eq $NULL -and $timeout -lt 11)
{
"IIS Site not ready. Waiting for 2 seconds..."
[System.Threading.Thread]::Sleep(2000)
$timeout++
$dir = Get-ChildItem
}
if ($dir -eq $NULL)
{
"IIS Site still not ready. Aborting."
}
else
{
"IIS site ready."
Set-Location $dir.physicalPath
"Location is $($dir.physicalPath)"
$acl = (Get-Item App_Data).GetAccessControl("Access")
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Network Service", "Modify, Write", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
Set-Acl App_Data $acl
"Permission added."
}
它首先导入 WebAdministration 模块,该模块允许 Powershell 与 IIS 交互。然后它会尝试枚举网站。但是,这是一个有趣的挑战。因为,启动任务在您的网站部署到 IIS 之前运行。所以你需要将你的启动任务设置为后台任务运行,然后等到站点部署完毕。所以代码尝试枚举网站,如果没有找到网站,它会等待 2 秒,然后再试一次。它总共执行 20 秒,然后超时。如果网站准备就绪,则找到物理路径并将 FileSystemAccessRule 添加到 App_Data 文件夹的 ACL。您可以修改添加的权限以满足您的需要。请注意,此脚本预计 IIS 中只有 1 个站点。如果您部署超过 1 个网站,
为了完整起见,这里是您应该添加到您的 XML ServiceDefinition.csdef
:
<Startup>
<Task commandLine="Setup.cmd" executionContext="elevated" taskType="background" />
</Startup>
两者都Setup.cmd
应该Setup.ps1
放在您网站的根目录中。如果您希望将它们放置在您网站的子文件夹中,您可以这样做,但是您必须将 Task 元素中的 commandLine 属性更新为“Subfolder\Setup.cmd”,并且您需要在 CMD 文件中更新 Powershell 文件的路径:
PowerShell -ExecutionPolicy Unrestricted .\Subfolder\Setup.ps1 >> %TEMP%\Setup-DebugLog.txt 2>&1
另外,请注意,Powershell v1 和 v2 在调用 Powershell 脚本方面存在一些差异。如果我没记错的话,Windows Azure 上的 Windows 2008 运行 Powershell v1,Windows 2008 R2 和更新版本运行 Powershell v2。因此,如果您在 Azure 上使用 Windows 2008,则需要更改调用 Powershell 脚本的行,因为在设置执行策略方面存在一些差异。